| 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 |