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 11616 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
11627 start_index); | 11627 start_index); |
11628 } | 11628 } |
11629 Vector<const uc16> pat_vector = seq_pat.ToUC16Vector(); | 11629 Vector<const uc16> pat_vector = seq_pat.ToUC16Vector(); |
11630 if (seq_sub.IsOneByte()) { | 11630 if (seq_sub.IsOneByte()) { |
11631 return SearchString(isolate, seq_sub.ToOneByteVector(), pat_vector, | 11631 return SearchString(isolate, seq_sub.ToOneByteVector(), pat_vector, |
11632 start_index); | 11632 start_index); |
11633 } | 11633 } |
11634 return SearchString(isolate, seq_sub.ToUC16Vector(), pat_vector, start_index); | 11634 return SearchString(isolate, seq_sub.ToUC16Vector(), pat_vector, start_index); |
11635 } | 11635 } |
11636 | 11636 |
| 11637 MaybeHandle<String> String::GetSubstitution(Isolate* isolate, Match* match, |
| 11638 Handle<String> replacement) { |
| 11639 Factory* factory = isolate->factory(); |
| 11640 |
| 11641 const int replacement_length = replacement->length(); |
| 11642 const int captures_length = match->CaptureCount(); |
| 11643 |
| 11644 replacement = String::Flatten(replacement); |
| 11645 |
| 11646 Handle<String> dollar_string = |
| 11647 factory->LookupSingleCharacterStringFromCode('$'); |
| 11648 int next = String::IndexOf(isolate, replacement, dollar_string, 0); |
| 11649 if (next < 0) { |
| 11650 return replacement; |
| 11651 } |
| 11652 |
| 11653 IncrementalStringBuilder builder(isolate); |
| 11654 |
| 11655 if (next > 0) { |
| 11656 builder.AppendString(factory->NewSubString(replacement, 0, next)); |
| 11657 } |
| 11658 |
| 11659 while (true) { |
| 11660 int pos = next + 1; |
| 11661 if (pos < replacement_length) { |
| 11662 const uint16_t peek = replacement->Get(pos); |
| 11663 if (peek == '$') { // $$ |
| 11664 pos++; |
| 11665 builder.AppendCharacter('$'); |
| 11666 } else if (peek == '&') { // $& - match |
| 11667 pos++; |
| 11668 builder.AppendString(match->GetMatch()); |
| 11669 } else if (peek == '`') { // $` - prefix |
| 11670 pos++; |
| 11671 builder.AppendString(match->GetPrefix()); |
| 11672 } else if (peek == '\'') { // $' - suffix |
| 11673 pos++; |
| 11674 builder.AppendString(match->GetSuffix()); |
| 11675 } else if (peek >= '0' && peek <= '9') { |
| 11676 // Valid indices are $1 .. $9, $01 .. $09 and $10 .. $99 |
| 11677 int scaled_index = (peek - '0'); |
| 11678 int advance = 1; |
| 11679 |
| 11680 if (pos + 1 < replacement_length) { |
| 11681 const uint16_t next_peek = replacement->Get(pos + 1); |
| 11682 if (next_peek >= '0' && next_peek <= '9') { |
| 11683 const int new_scaled_index = scaled_index * 10 + (next_peek - '0'); |
| 11684 if (new_scaled_index < captures_length) { |
| 11685 scaled_index = new_scaled_index; |
| 11686 advance = 2; |
| 11687 } |
| 11688 } |
| 11689 } |
| 11690 |
| 11691 if (scaled_index != 0 && scaled_index < captures_length) { |
| 11692 bool capture_exists; |
| 11693 Handle<String> capture; |
| 11694 ASSIGN_RETURN_ON_EXCEPTION( |
| 11695 isolate, capture, |
| 11696 match->GetCapture(scaled_index, &capture_exists), String); |
| 11697 if (capture_exists) builder.AppendString(capture); |
| 11698 pos += advance; |
| 11699 } else { |
| 11700 builder.AppendCharacter('$'); |
| 11701 } |
| 11702 } else { |
| 11703 builder.AppendCharacter('$'); |
| 11704 } |
| 11705 } else { |
| 11706 builder.AppendCharacter('$'); |
| 11707 } |
| 11708 |
| 11709 // Go the the next $ in the replacement. |
| 11710 next = String::IndexOf(isolate, replacement, dollar_string, pos); |
| 11711 |
| 11712 // Return if there are no more $ characters in the replacement. If we |
| 11713 // haven't reached the end, we need to append the suffix. |
| 11714 if (next < 0) { |
| 11715 if (pos < replacement_length) { |
| 11716 builder.AppendString( |
| 11717 factory->NewSubString(replacement, pos, replacement_length)); |
| 11718 } |
| 11719 return builder.Finish(); |
| 11720 } |
| 11721 |
| 11722 // Append substring between the previous and the next $ character. |
| 11723 if (next > pos) { |
| 11724 builder.AppendString(factory->NewSubString(replacement, pos, next)); |
| 11725 } |
| 11726 } |
| 11727 |
| 11728 UNREACHABLE(); |
| 11729 return MaybeHandle<String>(); |
| 11730 } |
| 11731 |
11637 namespace { // for String.Prototype.lastIndexOf | 11732 namespace { // for String.Prototype.lastIndexOf |
11638 | 11733 |
11639 template <typename schar, typename pchar> | 11734 template <typename schar, typename pchar> |
11640 int StringMatchBackwards(Vector<const schar> subject, | 11735 int StringMatchBackwards(Vector<const schar> subject, |
11641 Vector<const pchar> pattern, int idx) { | 11736 Vector<const pchar> pattern, int idx) { |
11642 int pattern_length = pattern.length(); | 11737 int pattern_length = pattern.length(); |
11643 DCHECK(pattern_length >= 1); | 11738 DCHECK(pattern_length >= 1); |
11644 DCHECK(idx + pattern_length <= subject.length()); | 11739 DCHECK(idx + pattern_length <= subject.length()); |
11645 | 11740 |
11646 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { | 11741 if (sizeof(schar) == 1 && sizeof(pchar) > 1) { |
(...skipping 8286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19933 } | 20028 } |
19934 | 20029 |
19935 // Evaluation of module body. | 20030 // Evaluation of module body. |
19936 Handle<JSFunction> resume( | 20031 Handle<JSFunction> resume( |
19937 isolate->native_context()->generator_next_internal(), isolate); | 20032 isolate->native_context()->generator_next_internal(), isolate); |
19938 return Execution::Call(isolate, resume, generator, 0, nullptr); | 20033 return Execution::Call(isolate, resume, generator, 0, nullptr); |
19939 } | 20034 } |
19940 | 20035 |
19941 } // namespace internal | 20036 } // namespace internal |
19942 } // namespace v8 | 20037 } // namespace v8 |
OLD | NEW |