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

Unified Diff: src/builtins/builtins-regexp.cc

Issue 2384613004: [regexp] Port RegExpConstructor to C++ (Closed)
Patch Set: Rebase Created 4 years, 2 months 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/builtins/builtins.h ('k') | src/heap-symbols.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/builtins/builtins-regexp.cc
diff --git a/src/builtins/builtins-regexp.cc b/src/builtins/builtins-regexp.cc
index d720bbed011dd2e67f8be57550b6b9f518f832f9..371221fa70a8d0d49c83e2c38bd2e37ddbc77668 100644
--- a/src/builtins/builtins-regexp.cc
+++ b/src/builtins/builtins-regexp.cc
@@ -11,6 +11,153 @@
namespace v8 {
namespace internal {
+// -----------------------------------------------------------------------------
+// ES6 section 21.2 RegExp Objects
+
+namespace {
+
+// ES#sec-isregexp IsRegExp ( argument )
+Maybe<bool> IsRegExp(Isolate* isolate, Handle<Object> object) {
+ if (!object->IsJSReceiver()) return Just(false);
+
+ Handle<JSReceiver> receiver = Handle<JSReceiver>::cast(object);
+
+ if (isolate->regexp_function()->initial_map() == receiver->map()) {
+ // Fast-path for unmodified JSRegExp instances.
+ return Just(true);
+ }
+
+ Handle<Object> match;
+ ASSIGN_RETURN_ON_EXCEPTION_VALUE(
+ isolate, match,
+ JSObject::GetProperty(receiver, isolate->factory()->match_symbol()),
+ Nothing<bool>());
+
+ if (!match->IsUndefined(isolate)) return Just(match->BooleanValue());
+ return Just(object->IsJSRegExp());
+}
+
+Handle<String> PatternFlags(Isolate* isolate, Handle<JSRegExp> regexp) {
+ static const int kMaxFlagsLength = 5 + 1; // 5 flags and '\0';
+ char flags_string[kMaxFlagsLength];
+ int i = 0;
+
+ const JSRegExp::Flags flags = regexp->GetFlags();
+
+ if ((flags & JSRegExp::kGlobal) != 0) flags_string[i++] = 'g';
+ if ((flags & JSRegExp::kIgnoreCase) != 0) flags_string[i++] = 'i';
+ if ((flags & JSRegExp::kMultiline) != 0) flags_string[i++] = 'm';
+ if ((flags & JSRegExp::kUnicode) != 0) flags_string[i++] = 'u';
+ if ((flags & JSRegExp::kSticky) != 0) flags_string[i++] = 'y';
+
+ DCHECK_LT(i, kMaxFlagsLength);
+ memset(&flags_string[i], '\0', kMaxFlagsLength - i);
+
+ return isolate->factory()->NewStringFromAsciiChecked(flags_string);
+}
+
+// ES#sec-regexpinitialize
+// Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
+MaybeHandle<JSRegExp> RegExpInitialize(Isolate* isolate,
+ Handle<JSRegExp> regexp,
+ Handle<Object> pattern,
+ Handle<Object> flags) {
+ Handle<String> pattern_string;
+ if (pattern->IsUndefined(isolate)) {
+ pattern_string = isolate->factory()->empty_string();
+ } else {
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, pattern_string,
+ Object::ToString(isolate, pattern), JSRegExp);
+ }
+
+ Handle<String> flags_string;
+ if (flags->IsUndefined(isolate)) {
+ flags_string = isolate->factory()->empty_string();
+ } else {
+ ASSIGN_RETURN_ON_EXCEPTION(isolate, flags_string,
+ Object::ToString(isolate, flags), JSRegExp);
+ }
+
+ // TODO(jgruber): We could avoid the flags back and forth conversions.
+ RETURN_RESULT(isolate,
+ JSRegExp::Initialize(regexp, pattern_string, flags_string),
+ JSRegExp);
+}
+
+} // namespace
+
+// ES#sec-regexp-pattern-flags
+// RegExp ( pattern, flags )
+BUILTIN(RegExpConstructor) {
+ HandleScope scope(isolate);
+
+ Handle<HeapObject> new_target = args.new_target();
+ Handle<Object> pattern = args.atOrUndefined(isolate, 1);
+ Handle<Object> flags = args.atOrUndefined(isolate, 2);
+
+ Handle<JSFunction> target = isolate->regexp_function();
+
+ bool pattern_is_regexp;
+ {
+ Maybe<bool> maybe_pattern_is_regexp = IsRegExp(isolate, pattern);
+ if (maybe_pattern_is_regexp.IsNothing()) {
+ DCHECK(isolate->has_pending_exception());
+ return isolate->heap()->exception();
+ }
+ pattern_is_regexp = maybe_pattern_is_regexp.FromJust();
+ }
+
+ if (new_target->IsUndefined(isolate)) {
+ new_target = target;
+
+ // ES6 section 21.2.3.1 step 3.b
+ if (pattern_is_regexp && flags->IsUndefined(isolate)) {
+ Handle<Object> pattern_constructor;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, pattern_constructor,
+ Object::GetProperty(pattern,
+ isolate->factory()->constructor_string()));
+
+ if (pattern_constructor.is_identical_to(new_target)) {
+ return *pattern;
+ }
+ }
+ }
+
+ if (pattern->IsJSRegExp()) {
+ Handle<JSRegExp> regexp_pattern = Handle<JSRegExp>::cast(pattern);
+
+ if (flags->IsUndefined(isolate)) {
+ flags = PatternFlags(isolate, regexp_pattern);
+ }
+ pattern = handle(regexp_pattern->source(), isolate);
+ } else if (pattern_is_regexp) {
+ Handle<Object> pattern_source;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, pattern_source,
+ Object::GetProperty(pattern, isolate->factory()->source_string()));
+
+ if (flags->IsUndefined(isolate)) {
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, flags,
+ Object::GetProperty(pattern, isolate->factory()->flags_string()));
+ }
+ pattern = pattern_source;
+ }
+
+ Handle<JSReceiver> new_target_receiver = Handle<JSReceiver>::cast(new_target);
+
+ // TODO(jgruber): Fast-path for target == new_target == unmodified JSRegExp.
+
+ Handle<JSObject> object;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, object, JSObject::New(target, new_target_receiver));
+ Handle<JSRegExp> regexp = Handle<JSRegExp>::cast(object);
+
+ RETURN_RESULT_OR_FAILURE(isolate,
+ RegExpInitialize(isolate, regexp, pattern, flags));
+}
+
namespace {
compiler::Node* LoadLastIndex(CodeStubAssembler* a, compiler::Node* context,
« no previous file with comments | « src/builtins/builtins.h ('k') | src/heap-symbols.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698