Title: [197999] trunk
Revision
197999
Author
[email protected]
Date
2016-03-10 23:10:18 -0800 (Thu, 10 Mar 2016)

Log Message

[ES6] Make RegExp.prototype.toString spec compliant
https://bugs.webkit.org/show_bug.cgi?id=155341

Reviewed by Filip Pizlo.

Before we were directly calling into the flagsString
function. Instead, we must get the "flags" property
of the thisObject. This will usually call into the flags
getter, but not always. Specifically, you can you a Proxy
to observe this behavior.

* runtime/RegExpPrototype.cpp:
(JSC::regExpProtoFuncToString):
(JSC::regExpProtoGetterGlobal):
* tests/es6.yaml:
* tests/es6/Proxy_internal_get_calls_RegExp.prototype.toString.js: Added.
(test.get var):
(test.):
* tests/stress/regexp-prototype-tostring.js: Added.
(assert):
(test):
(test.get var):
(test.):
(let.handler.get switch):
(let.handler):
(get test):
(test.get RegExp):

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/js/regexp-toString-expected.txt (197998 => 197999)


--- trunk/LayoutTests/js/regexp-toString-expected.txt	2016-03-11 07:05:01 UTC (rev 197998)
+++ trunk/LayoutTests/js/regexp-toString-expected.txt	2016-03-11 07:10:18 UTC (rev 197999)
@@ -11,11 +11,11 @@
 PASS RegExp.prototype.toString.call(new RegExp) is '/(?:)/'
 PASS RegExp.prototype.toString.call(new RegExp('a')) is '/a/'
 PASS RegExp.prototype.toString.call(new RegExp('\\\\')) is '/\\\\/'
-PASS RegExp.prototype.toString.call({}) is '/undefined/'
-PASS RegExp.prototype.toString.call({source: 'hi'}) is '/hi/'
-PASS RegExp.prototype.toString.call({ __proto__: { source: 'yo' } }) is '/yo/'
-PASS RegExp.prototype.toString.call({source: ''}) is '//'
-PASS RegExp.prototype.toString.call({source: '/'}) is '///'
+PASS RegExp.prototype.toString.call({}) is '/undefined/undefined'
+PASS RegExp.prototype.toString.call({source: 'hi'}) is '/hi/undefined'
+PASS RegExp.prototype.toString.call({ __proto__: { source: 'yo' } }) is '/yo/undefined'
+PASS RegExp.prototype.toString.call({source: ''}) is '//undefined'
+PASS RegExp.prototype.toString.call({source: '/'}) is '///undefined'
 PASS RegExp.prototype.toString.call(undefined) threw exception TypeError: Type error.
 PASS RegExp.prototype.toString.call(null) threw exception TypeError: Type error.
 PASS RegExp.prototype.toString.call(false) threw exception TypeError: Type error.

Modified: trunk/LayoutTests/js/script-tests/regexp-toString.js (197998 => 197999)


--- trunk/LayoutTests/js/script-tests/regexp-toString.js	2016-03-11 07:05:01 UTC (rev 197998)
+++ trunk/LayoutTests/js/script-tests/regexp-toString.js	2016-03-11 07:10:18 UTC (rev 197999)
@@ -10,11 +10,11 @@
 shouldBe("RegExp.prototype.toString.call(new RegExp('a'))", "'/a/'");
 shouldBe("RegExp.prototype.toString.call(new RegExp('\\\\\\\\'))", "'/\\\\\\\\/'");
 
-shouldBe("RegExp.prototype.toString.call({})", "'/undefined/'");
-shouldBe("RegExp.prototype.toString.call({source: 'hi'})", "'/hi/'");
-shouldBe("RegExp.prototype.toString.call({ __proto__: { source: 'yo' } })", "'/yo/'");
-shouldBe("RegExp.prototype.toString.call({source: ''})", "'//'");
-shouldBe("RegExp.prototype.toString.call({source: '/'})", "'///'");
+shouldBe("RegExp.prototype.toString.call({})", "'/undefined/undefined'");
+shouldBe("RegExp.prototype.toString.call({source: 'hi'})", "'/hi/undefined'");
+shouldBe("RegExp.prototype.toString.call({ __proto__: { source: 'yo' } })", "'/yo/undefined'");
+shouldBe("RegExp.prototype.toString.call({source: ''})", "'//undefined'");
+shouldBe("RegExp.prototype.toString.call({source: '/'})", "'///undefined'");
 
 shouldThrow("RegExp.prototype.toString.call(undefined)");
 shouldThrow("RegExp.prototype.toString.call(null)");

Modified: trunk/Source/_javascript_Core/ChangeLog (197998 => 197999)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-11 07:05:01 UTC (rev 197998)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-11 07:10:18 UTC (rev 197999)
@@ -1,3 +1,33 @@
+2016-03-10  Saam barati  <[email protected]>
+
+        [ES6] Make RegExp.prototype.toString spec compliant
+        https://bugs.webkit.org/show_bug.cgi?id=155341
+
+        Reviewed by Filip Pizlo.
+
+        Before we were directly calling into the flagsString
+        function. Instead, we must get the "flags" property
+        of the thisObject. This will usually call into the flags
+        getter, but not always. Specifically, you can you a Proxy
+        to observe this behavior.
+
+        * runtime/RegExpPrototype.cpp:
+        (JSC::regExpProtoFuncToString):
+        (JSC::regExpProtoGetterGlobal):
+        * tests/es6.yaml:
+        * tests/es6/Proxy_internal_get_calls_RegExp.prototype.toString.js: Added.
+        (test.get var):
+        (test.):
+        * tests/stress/regexp-prototype-tostring.js: Added.
+        (assert):
+        (test):
+        (test.get var):
+        (test.):
+        (let.handler.get switch):
+        (let.handler):
+        (get test):
+        (test.get RegExp):
+
 2016-03-10  Benjamin Poulain  <[email protected]>
 
         [JSC] Add register reuse for ArithAdd of an Int32 and constant in DFG

Modified: trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp (197998 => 197999)


--- trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-03-11 07:05:01 UTC (rev 197998)
+++ trunk/Source/_javascript_Core/runtime/RegExpPrototype.cpp	2016-03-11 07:10:18 UTC (rev 197999)
@@ -208,18 +208,22 @@
     if (JSValue earlyReturnValue = checker.earlyReturnValue())
         return JSValue::encode(earlyReturnValue);
 
-    JSValue sourceValue = thisObject->get(exec, exec->propertyNames().source);
-    if (exec->hadException())
+    VM& vm = exec->vm();
+    JSValue sourceValue = thisObject->get(exec, vm.propertyNames->source);
+    if (vm.exception())
         return JSValue::encode(jsUndefined());
     String source = sourceValue.toString(exec)->value(exec);
-    if (exec->hadException())
+    if (vm.exception())
         return JSValue::encode(jsUndefined());
 
-    auto flags = flagsString(exec, thisObject);
-    if (exec->hadException())
+    JSValue flagsValue = thisObject->get(exec, vm.propertyNames->flags);
+    if (vm.exception())
         return JSValue::encode(jsUndefined());
+    String flags = flagsValue.toString(exec)->value(exec);
+    if (vm.exception())
+        return JSValue::encode(jsUndefined());
 
-    return JSValue::encode(jsMakeNontrivialString(exec, '/', source, '/', flags.data()));
+    return JSValue::encode(jsMakeNontrivialString(exec, '/', source, '/', flags));
 }
 
 EncodedJSValue JSC_HOST_CALL regExpProtoGetterGlobal(ExecState* exec)

Added: trunk/Source/_javascript_Core/tests/es6/Proxy_internal_get_calls_RegExp.prototype.toString.js (0 => 197999)


--- trunk/Source/_javascript_Core/tests/es6/Proxy_internal_get_calls_RegExp.prototype.toString.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/es6/Proxy_internal_get_calls_RegExp.prototype.toString.js	2016-03-11 07:10:18 UTC (rev 197999)
@@ -0,0 +1,10 @@
+// RegExp.prototype.toString -> Get -> [[Get]]
+function test() {
+    var get = [];
+    var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }});
+    RegExp.prototype.toString.call(p);
+    return get + '' === "source,flags";
+}
+
+if (!test())
+    throw new Error("Test failed.")

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (197998 => 197999)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-11 07:05:01 UTC (rev 197998)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-11 07:10:18 UTC (rev 197999)
@@ -994,6 +994,8 @@
   cmd: runES6 :normal
 - path: es6/Proxy_internal_get_calls_RegExp.prototype.test.js
   cmd: runES6 :fail
+- path: es6/Proxy_internal_get_calls_RegExp.prototype.toString.js
+  cmd: runES6 :normal
 - path: es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.match].js
   cmd: runES6 :fail
 - path: es6/Proxy_internal_get_calls_RegExp.prototype[Symbol.replace].js

Added: trunk/Source/_javascript_Core/tests/stress/regexp-prototype-tostring.js (0 => 197999)


--- trunk/Source/_javascript_Core/tests/stress/regexp-prototype-tostring.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/regexp-prototype-tostring.js	2016-03-11 07:10:18 UTC (rev 197999)
@@ -0,0 +1,90 @@
+function assert(b) {
+    if (!b)
+        throw new Error("bad assertion")
+}
+function test(f) {
+    for (let i = 0; i < 100; i++)
+        f();
+}
+
+test(function() {
+    var get = [];
+    var p = new Proxy({}, { get: function(o, k) { get.push(k); return o[k]; }});
+    RegExp.prototype.toString.call(p);
+    assert(get + '' === "source,flags");
+});
+
+test(function() {
+    let handler = {
+        get: function(o, propName) {
+            switch(propName) {
+            case 'source': 
+                return "foobar";
+            case 'flags': 
+                return "whatever";
+            default:
+                assert(false, "should not be reached");
+            }
+        }
+    }
+    let proxy = new Proxy({}, handler);
+    let result = RegExp.prototype.toString.call(proxy);
+    assert(result === "/foobar/whatever");
+});
+
+test(function() {
+    let handler = {
+        get: function(o, propName) {
+            switch(propName) {
+            case 'source': 
+                return "hello";
+            case 'flags': 
+                return "y";
+            default:
+                assert(false, "should not be reached");
+            }
+        }
+    }
+
+    let proxy = new Proxy({}, handler);
+    let result = RegExp.prototype.toString.call(proxy);
+    assert(result === "/hello/y");
+});
+
+test(function() {
+    let error = null;
+    let obj = {
+        get flags() {
+            error = new Error;
+            throw error;
+        }
+    }
+
+    let threw = false;
+    try {
+        RegExp.prototype.toString.call(obj);
+    } catch(e) {
+        assert(e === error);
+        threw = true;
+    }
+    assert(threw);
+});
+
+test(function() {
+    let error = null;
+    let obj = {
+        get source() {
+            error = new Error;
+            throw error;
+        }
+    }
+
+    let threw = false;
+    try {
+        RegExp.prototype.toString.call(obj);
+    } catch(e) {
+        assert(e === error);
+        threw = true;
+    }
+    assert(threw);
+});
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to