Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/objects.cc

Issue 1472323002: [es6] Correct parsing of regular expression literal flags. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix oversight in interpreter Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | src/preparser.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 <sstream> 9 #include <sstream>
10 10
(...skipping 15636 matching lines...) Expand 10 before | Expand all | Expand 10 after
15647 } 15647 }
15648 15648
15649 private: 15649 private:
15650 Handle<String> source_; 15650 Handle<String> source_;
15651 Handle<SharedFunctionInfo> shared_; 15651 Handle<SharedFunctionInfo> shared_;
15652 LanguageMode language_mode_; 15652 LanguageMode language_mode_;
15653 int scope_position_; 15653 int scope_position_;
15654 }; 15654 };
15655 15655
15656 15656
15657 // static 15657 namespace {
15658 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern,
15659 Handle<String> flags) {
15660 Isolate* isolate = pattern->GetIsolate();
15661 Handle<JSFunction> constructor = isolate->regexp_function();
15662 Handle<JSRegExp> regexp =
15663 Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
15664 15658
15665 return JSRegExp::Initialize(regexp, pattern, flags); 15659 JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, bool* success) {
15666 } 15660 JSRegExp::Flags value = JSRegExp::kNone;
15667
15668
15669 // static
15670 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
15671 Isolate* const isolate = regexp->GetIsolate();
15672 return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
15673 }
15674
15675
15676 static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags,
15677 bool* success) {
15678 uint32_t value = JSRegExp::NONE;
15679 int length = flags->length(); 15661 int length = flags->length();
15680 // A longer flags string cannot be valid. 15662 // A longer flags string cannot be valid.
15681 if (length > 5) return JSRegExp::Flags(0); 15663 if (length > 5) return JSRegExp::Flags(0);
15682 for (int i = 0; i < length; i++) { 15664 for (int i = 0; i < length; i++) {
15683 uint32_t flag = JSRegExp::NONE; 15665 JSRegExp::Flag flag = JSRegExp::kNone;
15684 switch (flags->Get(i)) { 15666 switch (flags->Get(i)) {
15685 case 'g': 15667 case 'g':
15686 flag = JSRegExp::GLOBAL; 15668 flag = JSRegExp::kGlobal;
15687 break; 15669 break;
15688 case 'i': 15670 case 'i':
15689 flag = JSRegExp::IGNORE_CASE; 15671 flag = JSRegExp::kIgnoreCase;
15690 break; 15672 break;
15691 case 'm': 15673 case 'm':
15692 flag = JSRegExp::MULTILINE; 15674 flag = JSRegExp::kMultiline;
15693 break; 15675 break;
15694 case 'u': 15676 case 'u':
15695 if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0); 15677 if (!FLAG_harmony_unicode_regexps) return JSRegExp::Flags(0);
15696 flag = JSRegExp::UNICODE_ESCAPES; 15678 flag = JSRegExp::kUnicode;
15697 break; 15679 break;
15698 case 'y': 15680 case 'y':
15699 if (!FLAG_harmony_regexps) return JSRegExp::Flags(0); 15681 if (!FLAG_harmony_regexps) return JSRegExp::Flags(0);
15700 flag = JSRegExp::STICKY; 15682 flag = JSRegExp::kSticky;
15701 break; 15683 break;
15702 default: 15684 default:
15703 return JSRegExp::Flags(0); 15685 return JSRegExp::Flags(0);
15704 } 15686 }
15705 // Duplicate flag. 15687 // Duplicate flag.
15706 if (value & flag) return JSRegExp::Flags(0); 15688 if (value & flag) return JSRegExp::Flags(0);
15707 value |= flag; 15689 value |= flag;
15708 } 15690 }
15709 *success = true; 15691 *success = true;
15710 return JSRegExp::Flags(value); 15692 return value;
15693 }
15694
15695 } // namespace
15696
15697
15698 // static
15699 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern, Flags flags) {
15700 Isolate* isolate = pattern->GetIsolate();
15701 Handle<JSFunction> constructor = isolate->regexp_function();
15702 Handle<JSRegExp> regexp =
15703 Handle<JSRegExp>::cast(isolate->factory()->NewJSObject(constructor));
15704
15705 return JSRegExp::Initialize(regexp, pattern, flags);
15711 } 15706 }
15712 15707
15713 15708
15709 // static
15710 MaybeHandle<JSRegExp> JSRegExp::New(Handle<String> pattern,
15711 Handle<String> flags_string) {
15712 Isolate* isolate = pattern->GetIsolate();
15713 bool success = false;
15714 Flags flags = RegExpFlagsFromString(flags_string, &success);
15715 if (!success) {
15716 THROW_NEW_ERROR(
15717 isolate,
15718 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
15719 JSRegExp);
15720 }
15721 return New(pattern, flags);
15722 }
15723
15724
15725 // static
15726 Handle<JSRegExp> JSRegExp::Copy(Handle<JSRegExp> regexp) {
15727 Isolate* const isolate = regexp->GetIsolate();
15728 return Handle<JSRegExp>::cast(isolate->factory()->CopyJSObject(regexp));
15729 }
15730
15731
15714 template <typename Char> 15732 template <typename Char>
15715 inline int CountRequiredEscapes(Handle<String> source) { 15733 inline int CountRequiredEscapes(Handle<String> source) {
15716 DisallowHeapAllocation no_gc; 15734 DisallowHeapAllocation no_gc;
15717 int escapes = 0; 15735 int escapes = 0;
15718 Vector<const Char> src = source->GetCharVector<Char>(); 15736 Vector<const Char> src = source->GetCharVector<Char>();
15719 for (int i = 0; i < src.length(); i++) { 15737 for (int i = 0; i < src.length(); i++) {
15720 if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++; 15738 if (src[i] == '/' && (i == 0 || src[i - 1] != '\\')) escapes++;
15721 } 15739 }
15722 return escapes; 15740 return escapes;
15723 } 15741 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
15762 String); 15780 String);
15763 return WriteEscapedRegExpSource<uc16>(source, result); 15781 return WriteEscapedRegExpSource<uc16>(source, result);
15764 } 15782 }
15765 } 15783 }
15766 15784
15767 15785
15768 // static 15786 // static
15769 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp, 15787 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
15770 Handle<String> source, 15788 Handle<String> source,
15771 Handle<String> flags_string) { 15789 Handle<String> flags_string) {
15790 Isolate* isolate = source->GetIsolate();
15791 bool success = false;
15792 Flags flags = RegExpFlagsFromString(flags_string, &success);
15793 if (!success) {
15794 THROW_NEW_ERROR(
15795 isolate,
15796 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
15797 JSRegExp);
15798 }
15799 return Initialize(regexp, source, flags);
15800 }
15801
15802
15803 // static
15804 MaybeHandle<JSRegExp> JSRegExp::Initialize(Handle<JSRegExp> regexp,
15805 Handle<String> source, Flags flags) {
15772 Isolate* isolate = regexp->GetIsolate(); 15806 Isolate* isolate = regexp->GetIsolate();
15773 Factory* factory = isolate->factory(); 15807 Factory* factory = isolate->factory();
15774 // If source is the empty string we set it to "(?:)" instead as 15808 // If source is the empty string we set it to "(?:)" instead as
15775 // suggested by ECMA-262, 5th, section 15.10.4.1. 15809 // suggested by ECMA-262, 5th, section 15.10.4.1.
15776 if (source->length() == 0) source = factory->query_colon_string(); 15810 if (source->length() == 0) source = factory->query_colon_string();
15777 15811
15778 bool success = false;
15779 JSRegExp::Flags flags = RegExpFlagsFromString(flags_string, &success);
15780 if (!success) {
15781 THROW_NEW_ERROR(
15782 isolate,
15783 NewSyntaxError(MessageTemplate::kInvalidRegExpFlags, flags_string),
15784 JSRegExp);
15785 }
15786
15787 Handle<String> escaped_source; 15812 Handle<String> escaped_source;
15788 ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source, 15813 ASSIGN_RETURN_ON_EXCEPTION(isolate, escaped_source,
15789 EscapeRegExpSource(isolate, source), JSRegExp); 15814 EscapeRegExpSource(isolate, source), JSRegExp);
15790 15815
15791 regexp->set_source(*escaped_source); 15816 regexp->set_source(*escaped_source);
15792 regexp->set_flags(Smi::FromInt(flags.value())); 15817 regexp->set_flags(Smi::FromInt(flags));
15793 15818
15794 Map* map = regexp->map(); 15819 Map* map = regexp->map();
15795 Object* constructor = map->GetConstructor(); 15820 Object* constructor = map->GetConstructor();
15796 if (constructor->IsJSFunction() && 15821 if (constructor->IsJSFunction() &&
15797 JSFunction::cast(constructor)->initial_map() == map) { 15822 JSFunction::cast(constructor)->initial_map() == map) {
15798 // If we still have the original map, set in-object properties directly. 15823 // If we still have the original map, set in-object properties directly.
15799 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, 15824 regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex,
15800 Smi::FromInt(0), SKIP_WRITE_BARRIER); 15825 Smi::FromInt(0), SKIP_WRITE_BARRIER);
15801 } else { 15826 } else {
15802 // Map has changed, so use generic, but slower, method. 15827 // Map has changed, so use generic, but slower, method.
15803 PropertyAttributes writable = 15828 PropertyAttributes writable =
15804 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); 15829 static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE);
15805 JSObject::SetOwnPropertyIgnoreAttributes( 15830 JSObject::SetOwnPropertyIgnoreAttributes(
15806 regexp, factory->last_index_string(), 15831 regexp, factory->last_index_string(),
15807 Handle<Smi>(Smi::FromInt(0), isolate), writable) 15832 Handle<Smi>(Smi::FromInt(0), isolate), writable)
15808 .Check(); 15833 .Check();
15809 } 15834 }
15810 15835
15811 RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags), 15836 RETURN_ON_EXCEPTION(isolate, RegExpImpl::Compile(regexp, source, flags),
15812 JSRegExp); 15837 JSRegExp);
15813 15838
15814 return regexp; 15839 return regexp;
15815 } 15840 }
15816 15841
15817 15842
15818 // RegExpKey carries the source and flags of a regular expression as key. 15843 // RegExpKey carries the source and flags of a regular expression as key.
15819 class RegExpKey : public HashTableKey { 15844 class RegExpKey : public HashTableKey {
15820 public: 15845 public:
15821 RegExpKey(Handle<String> string, JSRegExp::Flags flags) 15846 RegExpKey(Handle<String> string, JSRegExp::Flags flags)
15822 : string_(string), 15847 : string_(string), flags_(Smi::FromInt(flags)) {}
15823 flags_(Smi::FromInt(flags.value())) { }
15824 15848
15825 // Rather than storing the key in the hash table, a pointer to the 15849 // Rather than storing the key in the hash table, a pointer to the
15826 // stored value is stored where the key should be. IsMatch then 15850 // stored value is stored where the key should be. IsMatch then
15827 // compares the search key to the found object, rather than comparing 15851 // compares the search key to the found object, rather than comparing
15828 // a key to a key. 15852 // a key to a key.
15829 bool IsMatch(Object* obj) override { 15853 bool IsMatch(Object* obj) override {
15830 FixedArray* val = FixedArray::cast(obj); 15854 FixedArray* val = FixedArray::cast(obj);
15831 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex))) 15855 return string_->Equals(String::cast(val->get(JSRegExp::kSourceIndex)))
15832 && (flags_ == val->get(JSRegExp::kFlagsIndex)); 15856 && (flags_ == val->get(JSRegExp::kFlagsIndex));
15833 } 15857 }
(...skipping 2714 matching lines...) Expand 10 before | Expand all | Expand 10 after
18548 if (cell->value() != *new_value) { 18572 if (cell->value() != *new_value) {
18549 cell->set_value(*new_value); 18573 cell->set_value(*new_value);
18550 Isolate* isolate = cell->GetIsolate(); 18574 Isolate* isolate = cell->GetIsolate();
18551 cell->dependent_code()->DeoptimizeDependentCodeGroup( 18575 cell->dependent_code()->DeoptimizeDependentCodeGroup(
18552 isolate, DependentCode::kPropertyCellChangedGroup); 18576 isolate, DependentCode::kPropertyCellChangedGroup);
18553 } 18577 }
18554 } 18578 }
18555 18579
18556 } // namespace internal 18580 } // namespace internal
18557 } // namespace v8 18581 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | src/preparser.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698