OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/objects.h" | 5 #include "src/objects.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <iomanip> | 8 #include <iomanip> |
9 #include <memory> | 9 #include <memory> |
10 #include <sstream> | 10 #include <sstream> |
(...skipping 11393 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11404 Handle<String> replacement) { | 11404 Handle<String> replacement) { |
11405 Factory* factory = isolate->factory(); | 11405 Factory* factory = isolate->factory(); |
11406 | 11406 |
11407 const int replacement_length = replacement->length(); | 11407 const int replacement_length = replacement->length(); |
11408 const int captures_length = match->CaptureCount(); | 11408 const int captures_length = match->CaptureCount(); |
11409 | 11409 |
11410 replacement = String::Flatten(replacement); | 11410 replacement = String::Flatten(replacement); |
11411 | 11411 |
11412 Handle<String> dollar_string = | 11412 Handle<String> dollar_string = |
11413 factory->LookupSingleCharacterStringFromCode('$'); | 11413 factory->LookupSingleCharacterStringFromCode('$'); |
11414 int next = String::IndexOf(isolate, replacement, dollar_string, 0); | 11414 int next_dollar_ix = String::IndexOf(isolate, replacement, dollar_string, 0); |
11415 if (next < 0) { | 11415 if (next_dollar_ix < 0) { |
11416 return replacement; | 11416 return replacement; |
11417 } | 11417 } |
11418 | 11418 |
11419 IncrementalStringBuilder builder(isolate); | 11419 IncrementalStringBuilder builder(isolate); |
11420 | 11420 |
11421 if (next > 0) { | 11421 if (next_dollar_ix > 0) { |
11422 builder.AppendString(factory->NewSubString(replacement, 0, next)); | 11422 builder.AppendString(factory->NewSubString(replacement, 0, next_dollar_ix)); |
11423 } | 11423 } |
11424 | 11424 |
11425 while (true) { | 11425 while (true) { |
11426 int pos = next + 1; | 11426 const int peek_ix = next_dollar_ix + 1; |
11427 if (pos < replacement_length) { | 11427 if (peek_ix >= replacement_length) { |
11428 const uint16_t peek = replacement->Get(pos); | 11428 builder.AppendCharacter('$'); |
11429 if (peek == '$') { // $$ | 11429 return builder.Finish(); |
11430 pos++; | 11430 } |
| 11431 |
| 11432 int continue_from_ix = -1; |
| 11433 const uint16_t peek = replacement->Get(peek_ix); |
| 11434 switch (peek) { |
| 11435 case '$': // $$ |
11431 builder.AppendCharacter('$'); | 11436 builder.AppendCharacter('$'); |
11432 } else if (peek == '&') { // $& - match | 11437 continue_from_ix = peek_ix + 1; |
11433 pos++; | 11438 break; |
| 11439 case '&': // $& - match |
11434 builder.AppendString(match->GetMatch()); | 11440 builder.AppendString(match->GetMatch()); |
11435 } else if (peek == '`') { // $` - prefix | 11441 continue_from_ix = peek_ix + 1; |
11436 pos++; | 11442 break; |
| 11443 case '`': // $` - prefix |
11437 builder.AppendString(match->GetPrefix()); | 11444 builder.AppendString(match->GetPrefix()); |
11438 } else if (peek == '\'') { // $' - suffix | 11445 continue_from_ix = peek_ix + 1; |
11439 pos++; | 11446 break; |
| 11447 case '\'': // $' - suffix |
11440 builder.AppendString(match->GetSuffix()); | 11448 builder.AppendString(match->GetSuffix()); |
11441 } else if (peek >= '0' && peek <= '9') { | 11449 continue_from_ix = peek_ix + 1; |
| 11450 break; |
| 11451 case '0': |
| 11452 case '1': |
| 11453 case '2': |
| 11454 case '3': |
| 11455 case '4': |
| 11456 case '5': |
| 11457 case '6': |
| 11458 case '7': |
| 11459 case '8': |
| 11460 case '9': { |
11442 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 | 11461 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 |
11443 int scaled_index = (peek - '0'); | 11462 int scaled_index = (peek - '0'); |
11444 int advance = 1; | 11463 int advance = 1; |
11445 | 11464 |
11446 if (pos + 1 < replacement_length) { | 11465 if (peek_ix + 1 < replacement_length) { |
11447 const uint16_t next_peek = replacement->Get(pos + 1); | 11466 const uint16_t next_peek = replacement->Get(peek_ix + 1); |
11448 if (next_peek >= '0' && next_peek <= '9') { | 11467 if (next_peek >= '0' && next_peek <= '9') { |
11449 const int new_scaled_index = scaled_index * 10 + (next_peek - '0'); | 11468 const int new_scaled_index = scaled_index * 10 + (next_peek - '0'); |
11450 if (new_scaled_index < captures_length) { | 11469 if (new_scaled_index < captures_length) { |
11451 scaled_index = new_scaled_index; | 11470 scaled_index = new_scaled_index; |
11452 advance = 2; | 11471 advance = 2; |
11453 } | 11472 } |
11454 } | 11473 } |
11455 } | 11474 } |
11456 | 11475 |
11457 if (scaled_index != 0 && scaled_index < captures_length) { | 11476 if (scaled_index == 0 || scaled_index >= captures_length) { |
11458 bool capture_exists; | |
11459 Handle<String> capture; | |
11460 ASSIGN_RETURN_ON_EXCEPTION( | |
11461 isolate, capture, | |
11462 match->GetCapture(scaled_index, &capture_exists), String); | |
11463 if (capture_exists) builder.AppendString(capture); | |
11464 pos += advance; | |
11465 } else { | |
11466 builder.AppendCharacter('$'); | 11477 builder.AppendCharacter('$'); |
| 11478 continue_from_ix = peek_ix; |
| 11479 break; |
11467 } | 11480 } |
11468 } else { | 11481 |
| 11482 bool capture_exists; |
| 11483 Handle<String> capture; |
| 11484 ASSIGN_RETURN_ON_EXCEPTION( |
| 11485 isolate, capture, match->GetCapture(scaled_index, &capture_exists), |
| 11486 String); |
| 11487 if (capture_exists) builder.AppendString(capture); |
| 11488 continue_from_ix = peek_ix + advance; |
| 11489 break; |
| 11490 } |
| 11491 default: |
11469 builder.AppendCharacter('$'); | 11492 builder.AppendCharacter('$'); |
11470 } | 11493 continue_from_ix = peek_ix; |
11471 } else { | 11494 break; |
11472 builder.AppendCharacter('$'); | |
11473 } | 11495 } |
11474 | 11496 |
11475 // Go the the next $ in the replacement. | 11497 // Go the the next $ in the replacement. |
11476 next = String::IndexOf(isolate, replacement, dollar_string, pos); | 11498 // TODO(jgruber): Single-char lookups could be much more efficient. |
| 11499 DCHECK_NE(continue_from_ix, -1); |
| 11500 next_dollar_ix = |
| 11501 String::IndexOf(isolate, replacement, dollar_string, continue_from_ix); |
11477 | 11502 |
11478 // Return if there are no more $ characters in the replacement. If we | 11503 // Return if there are no more $ characters in the replacement. If we |
11479 // haven't reached the end, we need to append the suffix. | 11504 // haven't reached the end, we need to append the suffix. |
11480 if (next < 0) { | 11505 if (next_dollar_ix < 0) { |
11481 if (pos < replacement_length) { | 11506 if (continue_from_ix < replacement_length) { |
11482 builder.AppendString( | 11507 builder.AppendString(factory->NewSubString( |
11483 factory->NewSubString(replacement, pos, replacement_length)); | 11508 replacement, continue_from_ix, replacement_length)); |
11484 } | 11509 } |
11485 return builder.Finish(); | 11510 return builder.Finish(); |
11486 } | 11511 } |
11487 | 11512 |
11488 // Append substring between the previous and the next $ character. | 11513 // Append substring between the previous and the next $ character. |
11489 if (next > pos) { | 11514 if (next_dollar_ix > continue_from_ix) { |
11490 builder.AppendString(factory->NewSubString(replacement, pos, next)); | 11515 builder.AppendString( |
| 11516 factory->NewSubString(replacement, continue_from_ix, next_dollar_ix)); |
11491 } | 11517 } |
11492 } | 11518 } |
11493 | 11519 |
11494 UNREACHABLE(); | 11520 UNREACHABLE(); |
11495 return MaybeHandle<String>(); | 11521 return MaybeHandle<String>(); |
11496 } | 11522 } |
11497 | 11523 |
11498 namespace { // for String.Prototype.lastIndexOf | 11524 namespace { // for String.Prototype.lastIndexOf |
11499 | 11525 |
11500 template <typename schar, typename pchar> | 11526 template <typename schar, typename pchar> |
(...skipping 8798 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
20299 // depend on this. | 20325 // depend on this. |
20300 return DICTIONARY_ELEMENTS; | 20326 return DICTIONARY_ELEMENTS; |
20301 } | 20327 } |
20302 DCHECK_LE(kind, LAST_ELEMENTS_KIND); | 20328 DCHECK_LE(kind, LAST_ELEMENTS_KIND); |
20303 return kind; | 20329 return kind; |
20304 } | 20330 } |
20305 } | 20331 } |
20306 | 20332 |
20307 } // namespace internal | 20333 } // namespace internal |
20308 } // namespace v8 | 20334 } // namespace v8 |
OLD | NEW |