Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/builtins/builtins-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
| 6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
| 7 | 7 |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/regexp/jsregexp.h" | 9 #include "src/regexp/jsregexp.h" |
| 10 #include "src/string-builder.h" | |
| 10 | 11 |
| 11 namespace v8 { | 12 namespace v8 { |
| 12 namespace internal { | 13 namespace internal { |
| 13 | 14 |
| 15 // ----------------------------------------------------------------------------- | |
| 16 // ES6 section 21.2 RegExp Objects | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 // ES#sec-isregexp IsRegExp ( argument ) | |
| 21 Maybe<bool> IsRegExp(Isolate* isolate, Handle<Object> object) { | |
| 22 if (!object->IsJSReceiver()) return Just(false); | |
| 23 | |
| 24 Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object); | |
| 25 | |
| 26 Handle<Object> match; | |
| 27 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 28 isolate, match, | |
| 29 JSObject::GetProperty(receiver, isolate->factory()->match_symbol()), | |
| 30 Nothing<bool>()); | |
| 31 | |
| 32 if (!match->IsUndefined(isolate)) return Just(match->BooleanValue()); | |
| 33 return Just(object->IsJSRegExp()); | |
| 34 } | |
| 35 | |
| 36 Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) { | |
| 37 IncrementalStringBuilder builder(isolate); | |
| 38 const JSRegExp::Flags flags = regexp->GetFlags(); | |
| 39 | |
| 40 if ((flags & JSRegExp::kGlobal) != 0) builder.AppendCharacter('g'); | |
| 41 if ((flags & JSRegExp::kIgnoreCase) != 0) builder.AppendCharacter('i'); | |
| 42 if ((flags & JSRegExp::kMultiline) != 0) builder.AppendCharacter('m'); | |
| 43 if ((flags & JSRegExp::kUnicode) != 0) builder.AppendCharacter('u'); | |
| 44 if ((flags & JSRegExp::kSticky) != 0) builder.AppendCharacter('y'); | |
| 45 | |
| 46 return builder.Finish().ToHandleChecked(); | |
| 47 } | |
| 48 | |
| 49 // ES#sec-regexpinitialize | |
| 50 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) | |
| 51 MaybeHandle<JSRegExp> RegExpInitialize(Isolate* isolate, | |
| 52 Handle<JSRegExp> regexp, | |
| 53 Handle<Object> pattern, | |
| 54 Handle<Object> flags) { | |
| 55 Handle<String> pattern_string; | |
| 56 if (pattern->IsUndefined(isolate)) { | |
| 57 pattern_string = isolate->factory()->empty_string(); | |
| 58 } else { | |
| 59 ASSIGN_RETURN_ON_EXCEPTION(isolate, pattern_string, | |
| 60 Object::ToString(isolate, pattern), JSRegExp); | |
| 61 } | |
| 62 | |
| 63 Handle<String> flags_string; | |
| 64 if (flags->IsUndefined(isolate)) { | |
| 65 flags_string = isolate->factory()->empty_string(); | |
| 66 } else { | |
| 67 ASSIGN_RETURN_ON_EXCEPTION(isolate, flags_string, | |
| 68 Object::ToString(isolate, flags), JSRegExp); | |
| 69 } | |
| 70 | |
| 71 // TODO(jgruber): We could avoid the flags back and forth conversions. | |
| 72 RETURN_RESULT(isolate, | |
| 73 JSRegExp::Initialize(regexp, pattern_string, flags_string), | |
| 74 JSRegExp); | |
| 75 } | |
| 76 | |
| 77 } // namespace | |
| 78 | |
| 79 // ES#sec-regexp-pattern-flags | |
| 80 // RegExp ( pattern, flags ) | |
| 81 BUILTIN(RegExpConstructor) { | |
| 82 HandleScope scope(isolate); | |
| 83 | |
| 84 Handle<HeapObject> new_target = args.new_target(); | |
| 85 Handle<Object> pattern = args.atOrUndefined(isolate, 1); | |
| 86 Handle<Object> flags = args.atOrUndefined(isolate, 2); | |
| 87 | |
| 88 Handle<JSFunction> target = isolate->regexp_function(); | |
| 89 | |
| 90 bool pattern_is_regexp; | |
| 91 { | |
| 92 Maybe<bool> maybe_pattern_is_regexp = IsRegExp(isolate, pattern); | |
| 93 if (maybe_pattern_is_regexp.IsNothing()) { | |
| 94 DCHECK(isolate->has_pending_exception()); | |
| 95 return isolate->heap()->exception(); | |
| 96 } | |
| 97 pattern_is_regexp = maybe_pattern_is_regexp.FromJust(); | |
| 98 } | |
| 99 | |
| 100 if (new_target->IsUndefined(isolate)) { | |
| 101 new_target = target; | |
| 102 | |
| 103 // ES6 section 21.2.3.1 step 3.b | |
| 104 if (pattern_is_regexp && flags->IsUndefined(isolate)) { | |
| 105 Handle<Object> pattern_constructor; | |
| 106 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 107 isolate, pattern_constructor, | |
| 108 Object::GetProperty(pattern, | |
| 109 isolate->factory()->constructor_string())); | |
| 110 | |
| 111 if (*pattern_constructor == *new_target) { | |
|
Benedikt Meurer
2016/09/30 11:25:24
Nit: use is_identical_to here
jgruber
2016/10/04 12:25:22
Done.
| |
| 112 return *pattern; | |
| 113 } | |
| 114 } | |
| 115 } else if (!new_target->IsJSReceiver()) { | |
|
Benedikt Meurer
2016/09/30 11:25:24
Shouldn't this be IsCallable? Because new_target c
jgruber
2016/10/04 12:25:22
I had a response to this all written out saying ne
| |
| 116 THROW_NEW_ERROR_RETURN_FAILURE( | |
| 117 isolate, NewTypeError(MessageTemplate::kCalledNonCallable, new_target)); | |
| 118 } | |
| 119 Handle<JSReceiver> new_target_receiver = Handle<JSReceiver>::cast(new_target); | |
| 120 | |
| 121 if (pattern->IsJSRegExp()) { | |
| 122 Handle<JSRegExp> regexp_pattern = Handle<JSRegExp>::cast(pattern); | |
| 123 | |
| 124 if (flags->IsUndefined(isolate)) { | |
| 125 flags = PatternFlags(isolate, regexp_pattern); | |
| 126 } | |
| 127 pattern = handle(regexp_pattern->source(), isolate); | |
| 128 } else if (pattern_is_regexp) { | |
| 129 Handle<Object> pattern_source; | |
| 130 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 131 isolate, pattern_source, | |
| 132 Object::GetProperty(pattern, isolate->factory()->source_string())); | |
| 133 | |
| 134 if (flags->IsUndefined(isolate)) { | |
| 135 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 136 isolate, flags, | |
| 137 Object::GetProperty(pattern, isolate->factory()->flags_string())); | |
| 138 } | |
| 139 pattern = pattern_source; | |
| 140 } | |
| 141 | |
| 142 Handle<JSObject> object; | |
| 143 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 144 isolate, object, JSObject::New(target, new_target_receiver)); | |
| 145 Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(object); | |
| 146 | |
| 147 RETURN_RESULT_OR_FAILURE(isolate, | |
| 148 RegExpInitialize(isolate, regexp, pattern, flags)); | |
| 149 } | |
| 150 | |
| 14 namespace { | 151 namespace { |
| 15 | 152 |
| 16 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context, | 153 compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context, |
| 17 compiler::Node* has_initialmap, | 154 compiler::Node* has_initialmap, |
| 18 compiler::Node* regexp) { | 155 compiler::Node* regexp) { |
| 19 typedef CodeStubAssembler::Variable Variable; | 156 typedef CodeStubAssembler::Variable Variable; |
| 20 typedef CodeStubAssembler::Label Label; | 157 typedef CodeStubAssembler::Label Label; |
| 21 typedef compiler::Node Node; | 158 typedef compiler::Node Node; |
| 22 | 159 |
| 23 Variable var_value(a, MachineRepresentation::kTagged); | 160 Variable var_value(a, MachineRepresentation::kTagged); |
| (...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 288 { | 425 { |
| 289 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, | 426 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, |
| 290 match_elements, string); | 427 match_elements, string); |
| 291 a->Return(result); | 428 a->Return(result); |
| 292 } | 429 } |
| 293 } | 430 } |
| 294 } | 431 } |
| 295 | 432 |
| 296 } // namespace internal | 433 } // namespace internal |
| 297 } // namespace v8 | 434 } // namespace v8 |
| OLD | NEW |