Title: [199106] trunk
Revision
199106
Author
[email protected]
Date
2016-04-06 11:26:11 -0700 (Wed, 06 Apr 2016)

Log Message

RegExp constructor should use Symbol.match and other properties
https://bugs.webkit.org/show_bug.cgi?id=155873

Reviewed by Michael Saboff.

Source/_javascript_Core:

This patch updates the behavior of the RegExp constructor. Now the constructor
should get the Symbol.match property and check if it exists to decide if something
should be constructed like a regexp object.

* runtime/RegExpConstructor.cpp:
(JSC::toFlags):
(JSC::constructRegExp):
(JSC::constructWithRegExpConstructor):
(JSC::callRegExpConstructor):
* runtime/RegExpConstructor.h:
* tests/stress/regexp-constructor.js: Added.
(assert):
(throw.new.Error.get let):
(throw.new.Error.):
(throw.new.Error.get re):

LayoutTests:

Fix test for new behavior.

* fast/regex/constructor-expected.txt:
* fast/regex/script-tests/constructor.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (199105 => 199106)


--- trunk/LayoutTests/ChangeLog	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/LayoutTests/ChangeLog	2016-04-06 18:26:11 UTC (rev 199106)
@@ -1,3 +1,15 @@
+2016-04-06  Keith Miller  <[email protected]>
+
+        RegExp constructor should use Symbol.match and other properties
+        https://bugs.webkit.org/show_bug.cgi?id=155873
+
+        Reviewed by Michael Saboff.
+
+        Fix test for new behavior.
+
+        * fast/regex/constructor-expected.txt:
+        * fast/regex/script-tests/constructor.js:
+
 2016-04-06  Zalan Bujtas  <[email protected]>
 
         ASSERTION FAILED: !floatingObject->originatingLine() in WebCore::RenderBlockFlow::linkToEndLineIfNeeded

Modified: trunk/LayoutTests/fast/regex/constructor-expected.txt (199105 => 199106)


--- trunk/LayoutTests/fast/regex/constructor-expected.txt	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/LayoutTests/fast/regex/constructor-expected.txt	2016-04-06 18:26:11 UTC (rev 199106)
@@ -5,7 +5,7 @@
 
 PASS re === RegExp(re) is true
 PASS re !== new RegExp(re) is true
-PASS re === RegExp(re,'i') is true
+PASS re !== RegExp(re,'i') is true
 PASS re !== new RegExp(re,'i') is true
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/regex/script-tests/constructor.js (199105 => 199106)


--- trunk/LayoutTests/fast/regex/script-tests/constructor.js	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/LayoutTests/fast/regex/script-tests/constructor.js	2016-04-06 18:26:11 UTC (rev 199106)
@@ -4,6 +4,6 @@
 
 shouldBeTrue("re === RegExp(re)");
 shouldBeTrue("re !== new RegExp(re)");
-shouldBeTrue("re === RegExp(re,'i')");
+shouldBeTrue("re !== RegExp(re,'i')");
 shouldBeTrue("re !== new RegExp(re,'i')");
 

Modified: trunk/Source/_javascript_Core/ChangeLog (199105 => 199106)


--- trunk/Source/_javascript_Core/ChangeLog	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-04-06 18:26:11 UTC (rev 199106)
@@ -1,5 +1,28 @@
 2016-04-06  Keith Miller  <[email protected]>
 
+        RegExp constructor should use Symbol.match and other properties
+        https://bugs.webkit.org/show_bug.cgi?id=155873
+
+        Reviewed by Michael Saboff.
+
+        This patch updates the behavior of the RegExp constructor. Now the constructor
+        should get the Symbol.match property and check if it exists to decide if something
+        should be constructed like a regexp object.
+
+        * runtime/RegExpConstructor.cpp:
+        (JSC::toFlags):
+        (JSC::constructRegExp):
+        (JSC::constructWithRegExpConstructor):
+        (JSC::callRegExpConstructor):
+        * runtime/RegExpConstructor.h:
+        * tests/stress/regexp-constructor.js: Added.
+        (assert):
+        (throw.new.Error.get let):
+        (throw.new.Error.):
+        (throw.new.Error.get re):
+
+2016-04-06  Keith Miller  <[email protected]>
+
         We should support the ability to do a non-effectful getById
         https://bugs.webkit.org/show_bug.cgi?id=156116
 

Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp (199105 => 199106)


--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.cpp	2016-04-06 18:26:11 UTC (rev 199106)
@@ -96,7 +96,6 @@
     Base::finishCreation(vm, ASCIILiteral("RegExp"));
     ASSERT(inherits(info()));
 
-    // ECMA 15.10.5.1 RegExp.prototype
     putDirectWithoutTransition(vm, vm.propertyNames->prototype, regExpPrototype, DontEnum | DontDelete | ReadOnly);
 
     // no. of arguments for constructor
@@ -260,47 +259,74 @@
     return structure;
 }
 
-// ECMA 15.10.4
-JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args, JSValue newTarget)
+inline RegExpFlags toFlags(ExecState* exec, JSValue flags)
 {
-    JSValue arg0 = args.at(0);
-    JSValue arg1 = args.at(1);
+    if (flags.isUndefined())
+        return NoFlags;
+    JSString* flagsString = flags.toString(exec);
+    if (!flagsString) {
+        ASSERT(exec->hadException());
+        return InvalidFlags;
+    }
 
+    RegExpFlags result = regExpFlags(flagsString->value(exec));
+    if (exec->hadException())
+        return InvalidFlags;
+    if (result == InvalidFlags)
+        throwSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor."));
+    return result;
+}
+
+JSObject* constructRegExp(ExecState* exec, JSGlobalObject* globalObject, const ArgList& args,  JSObject* callee, JSValue newTarget)
+{
     VM& vm = exec->vm();
-    RegExpFlags flags = NoFlags;
-    bool haveFlags = false;
-    if (!arg1.isUndefined()) {
-        flags = regExpFlags(arg1.toString(exec)->value(exec));
+    JSValue patternArg = args.at(0);
+    JSValue flagsArg = args.at(1);
+
+    bool isPatternRegExp = patternArg.inherits(RegExpObject::info());
+    bool constructAsRegexp = isRegExp(vm, exec, patternArg);
+
+    if (newTarget.isUndefined() && constructAsRegexp && flagsArg.isUndefined()) {
+        JSValue constructor = patternArg.get(exec, vm.propertyNames->constructor);
         if (vm.exception())
-            return 0;
-        if (flags == InvalidFlags)
-            return vm.throwException(exec, createSyntaxError(exec, ASCIILiteral("Invalid flags supplied to RegExp constructor.")));
-        haveFlags = true;
+            return nullptr;
+        if (callee == constructor) {
+            // We know that patternArg is a object otherwise constructAsRegexp would be false.
+            return patternArg.getObject();
+        }
     }
 
-    if (arg0.inherits(RegExpObject::info())) {
-        // If called as a function, this just returns the first argument (see 15.10.3.1).
-        if (newTarget != jsUndefined()) {
-            RegExp* regExp = static_cast<RegExpObject*>(asObject(arg0))->regExp();
-            Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
-            if (vm.exception())
+    if (isPatternRegExp) {
+        RegExp* regExp = jsCast<RegExpObject*>(patternArg)->regExp();
+        Structure* structure = getRegExpStructure(exec, globalObject, newTarget);
+        if (exec->hadException())
+            return nullptr;
+
+        if (!flagsArg.isUndefined()) {
+            RegExpFlags flags = toFlags(exec, flagsArg);
+            if (flags == InvalidFlags)
                 return nullptr;
+            regExp = RegExp::create(vm, regExp->pattern(), flags);
+        }
 
-            if (haveFlags) {
-                regExp = RegExp::create(vm, regExp->pattern(), flags);
-                if (vm.exception())
-                    return nullptr;
-            }
+        return RegExpObject::create(exec->vm(), structure, regExp);
+    }
 
-            return RegExpObject::create(vm, structure, regExp);
-        }
-        return asObject(arg0);
+    if (constructAsRegexp) {
+        JSValue pattern = patternArg.get(exec, vm.propertyNames->source);
+        if (flagsArg.isUndefined())
+            flagsArg = patternArg.get(exec, vm.propertyNames->flags);
+        patternArg = pattern;
     }
 
-    String pattern = arg0.isUndefined() ? emptyString() : arg0.toString(exec)->value(exec);
-    if (vm.exception())
-        return 0;
+    String pattern = patternArg.isUndefined() ? emptyString() : patternArg.toString(exec)->value(exec);
+    if (exec->hadException())
+        return nullptr;
 
+    RegExpFlags flags = toFlags(exec, flagsArg);
+    if (flags == InvalidFlags)
+        return nullptr;
+
     RegExp* regExp = RegExp::create(vm, pattern, flags);
     if (!regExp->isValid())
         return vm.throwException(exec, createSyntaxError(exec, regExp->errorMessage()));
@@ -314,7 +340,7 @@
 static EncodedJSValue JSC_HOST_CALL constructWithRegExpConstructor(ExecState* exec)
 {
     ArgList args(exec);
-    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, exec->newTarget()));
+    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, exec->callee(), exec->newTarget()));
 }
 
 ConstructType RegExpConstructor::getConstructData(JSCell*, ConstructData& constructData)
@@ -323,11 +349,10 @@
     return ConstructType::Host;
 }
 
-// ECMA 15.10.3
 static EncodedJSValue JSC_HOST_CALL callRegExpConstructor(ExecState* exec)
 {
     ArgList args(exec);
-    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args));
+    return JSValue::encode(constructRegExp(exec, asInternalFunction(exec->callee())->globalObject(), args, exec->callee()));
 }
 
 CallType RegExpConstructor::getCallData(JSCell*, CallData& callData)

Modified: trunk/Source/_javascript_Core/runtime/RegExpConstructor.h (199105 => 199106)


--- trunk/Source/_javascript_Core/runtime/RegExpConstructor.h	2016-04-06 17:44:42 UTC (rev 199105)
+++ trunk/Source/_javascript_Core/runtime/RegExpConstructor.h	2016-04-06 18:26:11 UTC (rev 199106)
@@ -87,7 +87,7 @@
 
 RegExpConstructor* asRegExpConstructor(JSValue);
 
-JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, JSValue newTarget = jsUndefined());
+JSObject* constructRegExp(ExecState*, JSGlobalObject*, const ArgList&, JSObject* callee = nullptr, JSValue newTarget = jsUndefined());
 
 inline RegExpConstructor* asRegExpConstructor(JSValue value)
 {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to