Index: src/runtime/runtime-regexp.cc |
diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc |
index 982ef6669932d29d532a7217d7d648cbbd94397a..e46d9b91765d30b7a4beaf4785f43d515dae0146 100644 |
--- a/src/runtime/runtime-regexp.cc |
+++ b/src/runtime/runtime-regexp.cc |
@@ -759,19 +759,6 @@ RUNTIME_FUNCTION(Runtime_StringSplit) { |
} |
-RUNTIME_FUNCTION(Runtime_RegExpCompile) { |
- HandleScope scope(isolate); |
- DCHECK(args.length() == 3); |
- CONVERT_ARG_HANDLE_CHECKED(JSRegExp, re, 0); |
- CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1); |
- CONVERT_ARG_HANDLE_CHECKED(String, flags, 2); |
- Handle<Object> result; |
- ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
- RegExpImpl::Compile(re, pattern, flags)); |
- return *result; |
-} |
- |
- |
RUNTIME_FUNCTION(Runtime_RegExpExecRT) { |
HandleScope scope(isolate); |
DCHECK(args.length() == 4); |
@@ -813,26 +800,65 @@ RUNTIME_FUNCTION(Runtime_RegExpConstructResult) { |
} |
-RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) { |
+static JSRegExp::Flags RegExpFlagsFromString(Handle<String> flags, |
+ bool* success) { |
+ uint32_t value = JSRegExp::NONE; |
+ int length = flags->length(); |
+ // A longer flags string cannot be valid. |
+ if (length > 4) return JSRegExp::Flags(0); |
+ for (int i = 0; i < length; i++) { |
+ uint32_t flag = JSRegExp::NONE; |
+ switch (flags->Get(i)) { |
+ case 'g': |
+ flag = JSRegExp::GLOBAL; |
+ break; |
+ case 'i': |
+ flag = JSRegExp::IGNORE_CASE; |
+ break; |
+ case 'm': |
+ flag = JSRegExp::MULTILINE; |
+ break; |
+ case 'y': |
+ if (!FLAG_harmony_regexps) return JSRegExp::Flags(0); |
+ flag = JSRegExp::STICKY; |
+ break; |
+ default: |
+ return JSRegExp::Flags(0); |
+ } |
+ // Duplicate flag. |
+ if (value & flag) return JSRegExp::Flags(0); |
+ value |= flag; |
+ } |
+ *success = true; |
+ return JSRegExp::Flags(value); |
+} |
+ |
+ |
+RUNTIME_FUNCTION(Runtime_RegExpInitializeAndCompile) { |
HandleScope scope(isolate); |
- DCHECK(args.length() == 6); |
+ DCHECK(args.length() == 3); |
CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); |
CONVERT_ARG_HANDLE_CHECKED(String, source, 1); |
+ CONVERT_ARG_HANDLE_CHECKED(String, flags_string, 2); |
+ Factory* factory = isolate->factory(); |
// If source is the empty string we set it to "(?:)" instead as |
// suggested by ECMA-262, 5th, section 15.10.4.1. |
- if (source->length() == 0) source = isolate->factory()->query_colon_string(); |
- |
- CONVERT_ARG_HANDLE_CHECKED(Object, global, 2); |
- if (!global->IsTrue()) global = isolate->factory()->false_value(); |
- |
- CONVERT_ARG_HANDLE_CHECKED(Object, ignoreCase, 3); |
- if (!ignoreCase->IsTrue()) ignoreCase = isolate->factory()->false_value(); |
- |
- CONVERT_ARG_HANDLE_CHECKED(Object, multiline, 4); |
- if (!multiline->IsTrue()) multiline = isolate->factory()->false_value(); |
+ if (source->length() == 0) source = factory->query_colon_string(); |
+ |
+ bool success = false; |
+ JSRegExp::Flags flags = RegExpFlagsFromString(flags_string, &success); |
+ if (!success) { |
+ Handle<FixedArray> element = factory->NewFixedArray(1); |
+ element->set(0, *flags_string); |
+ Handle<JSArray> args = factory->NewJSArrayWithElements(element); |
+ THROW_NEW_ERROR_RETURN_FAILURE( |
+ isolate, NewSyntaxError("invalid_regexp_flags", args)); |
+ } |
- CONVERT_ARG_HANDLE_CHECKED(Object, sticky, 5); |
- if (!sticky->IsTrue()) sticky = isolate->factory()->false_value(); |
+ Handle<Object> global = factory->ToBoolean(flags.is_global()); |
+ Handle<Object> ignore_case = factory->ToBoolean(flags.is_ignore_case()); |
+ Handle<Object> multiline = factory->ToBoolean(flags.is_multiline()); |
+ Handle<Object> sticky = factory->ToBoolean(flags.is_sticky()); |
Map* map = regexp->map(); |
Object* constructor = map->constructor(); |
@@ -844,41 +870,43 @@ RUNTIME_FUNCTION(Runtime_RegExpInitializeObject) { |
// barrier. |
regexp->InObjectPropertyAtPut(JSRegExp::kGlobalFieldIndex, *global, |
SKIP_WRITE_BARRIER); |
- regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, *ignoreCase, |
+ regexp->InObjectPropertyAtPut(JSRegExp::kIgnoreCaseFieldIndex, *ignore_case, |
SKIP_WRITE_BARRIER); |
regexp->InObjectPropertyAtPut(JSRegExp::kMultilineFieldIndex, *multiline, |
SKIP_WRITE_BARRIER); |
regexp->InObjectPropertyAtPut(JSRegExp::kLastIndexFieldIndex, |
Smi::FromInt(0), SKIP_WRITE_BARRIER); |
- return *regexp; |
+ } else { |
+ // Map has changed, so use generic, but slower, method. We also end here if |
+ // the --harmony-regexp flag is set, because the initial map does not have |
+ // space for the 'sticky' flag, since it is from the snapshot, but must work |
+ // both with and without --harmony-regexp. When sticky comes out from under |
+ // the flag, we will be able to use the fast initial map. |
+ PropertyAttributes final = |
+ static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); |
+ PropertyAttributes writable = |
+ static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
+ Handle<Object> zero(Smi::FromInt(0), isolate); |
+ JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->source_string(), |
+ source, final).Check(); |
+ JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->global_string(), |
+ global, final).Check(); |
+ JSObject::SetOwnPropertyIgnoreAttributes( |
+ regexp, factory->ignore_case_string(), ignore_case, final).Check(); |
+ JSObject::SetOwnPropertyIgnoreAttributes( |
+ regexp, factory->multiline_string(), multiline, final).Check(); |
+ if (FLAG_harmony_regexps) { |
+ JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->sticky_string(), |
+ sticky, final).Check(); |
+ } |
+ JSObject::SetOwnPropertyIgnoreAttributes( |
+ regexp, factory->last_index_string(), zero, writable).Check(); |
} |
- // Map has changed, so use generic, but slower, method. We also end here if |
- // the --harmony-regexp flag is set, because the initial map does not have |
- // space for the 'sticky' flag, since it is from the snapshot, but must work |
- // both with and without --harmony-regexp. When sticky comes out from under |
- // the flag, we will be able to use the fast initial map. |
- PropertyAttributes final = |
- static_cast<PropertyAttributes>(READ_ONLY | DONT_ENUM | DONT_DELETE); |
- PropertyAttributes writable = |
- static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE); |
- Handle<Object> zero(Smi::FromInt(0), isolate); |
- Factory* factory = isolate->factory(); |
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->source_string(), |
- source, final).Check(); |
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->global_string(), |
- global, final).Check(); |
- JSObject::SetOwnPropertyIgnoreAttributes( |
- regexp, factory->ignore_case_string(), ignoreCase, final).Check(); |
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->multiline_string(), |
- multiline, final).Check(); |
- if (FLAG_harmony_regexps) { |
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->sticky_string(), |
- sticky, final).Check(); |
- } |
- JSObject::SetOwnPropertyIgnoreAttributes(regexp, factory->last_index_string(), |
- zero, writable).Check(); |
- return *regexp; |
+ Handle<Object> result; |
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
+ isolate, result, RegExpImpl::Compile(regexp, source, flags)); |
+ return *result; |
} |