Title: [197899] trunk/Source/_javascript_Core
Revision
197899
Author
[email protected]
Date
2016-03-09 16:36:06 -0800 (Wed, 09 Mar 2016)

Log Message

Array.isArray support for Proxy
https://bugs.webkit.org/show_bug.cgi?id=155179

Reviewed by Mark Lam.

This patch implements Array.isArray to be compliant
with the ES6 spec. Specifically, it needs to interface
properly with Proxy arguments.
https://tc39.github.io/ecma262/#sec-isarray

* runtime/ArrayConstructor.cpp:
(JSC::ArrayConstructor::getCallData):
(JSC::arrayConstructorIsArray):
(JSC::arrayConstructorPrivateFuncIsArrayConstructor):
* runtime/ArrayPrototype.cpp:
(JSC::speciesConstructArray):
* runtime/ProxyObject.cpp:
(JSC::ProxyObject::revoke):
(JSC::ProxyObject::isRevoked):
(JSC::ProxyObject::visitChildren):
* runtime/ProxyObject.h:
(JSC::ProxyObject::target):
(JSC::ProxyObject::handler):
* tests/es6.yaml:
* tests/stress/proxy-is-array.js: Added.
(assert):
(test):

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197898 => 197899)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-10 00:36:06 UTC (rev 197899)
@@ -1,3 +1,33 @@
+2016-03-09  Saam barati  <[email protected]>
+
+        Array.isArray support for Proxy
+        https://bugs.webkit.org/show_bug.cgi?id=155179
+
+        Reviewed by Mark Lam.
+
+        This patch implements Array.isArray to be compliant
+        with the ES6 spec. Specifically, it needs to interface
+        properly with Proxy arguments.
+        https://tc39.github.io/ecma262/#sec-isarray
+
+        * runtime/ArrayConstructor.cpp:
+        (JSC::ArrayConstructor::getCallData):
+        (JSC::arrayConstructorIsArray):
+        (JSC::arrayConstructorPrivateFuncIsArrayConstructor):
+        * runtime/ArrayPrototype.cpp:
+        (JSC::speciesConstructArray):
+        * runtime/ProxyObject.cpp:
+        (JSC::ProxyObject::revoke):
+        (JSC::ProxyObject::isRevoked):
+        (JSC::ProxyObject::visitChildren):
+        * runtime/ProxyObject.h:
+        (JSC::ProxyObject::target):
+        (JSC::ProxyObject::handler):
+        * tests/es6.yaml:
+        * tests/stress/proxy-is-array.js: Added.
+        (assert):
+        (test):
+
 2016-03-09  Benjamin Poulain  <[email protected]>
 
         [JSC] Fix the ARM64 MacroAssembler after r197816

Modified: trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp (197898 => 197899)


--- trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/runtime/ArrayConstructor.cpp	2016-03-10 00:36:06 UTC (rev 197899)
@@ -33,6 +33,7 @@
 #include "JSArray.h"
 #include "JSFunction.h"
 #include "Lookup.h"
+#include "ProxyObject.h"
 #include "JSCInlines.h"
 
 namespace JSC {
@@ -125,9 +126,30 @@
     return CallType::Host;
 }
 
+// ES6 7.2.2
+// https://tc39.github.io/ecma262/#sec-isarray
 EncodedJSValue JSC_HOST_CALL arrayConstructorIsArray(ExecState* exec)
 {
-    return JSValue::encode(jsBoolean(exec->argument(0).inherits(JSArray::info())));
+    JSValue argumentValue = exec->argument(0);
+
+    if (!argumentValue.isObject())
+        return JSValue::encode(jsBoolean(false));
+
+    JSObject* argument = jsCast<JSObject*>(argumentValue);
+    while (true) {
+        if (argument->inherits(JSArray::info()))
+            return JSValue::encode(jsBoolean(true));
+
+        if (argument->type() != ProxyObjectType)
+            return JSValue::encode(jsBoolean(false));
+
+        ProxyObject* proxy = jsCast<ProxyObject*>(argument);
+        if (proxy->isRevoked())
+            return throwVMTypeError(exec, ASCIILiteral("Array.isArray can not be called on a Proxy that has been revoked."));
+        argument = proxy->target();
+    }
+
+    ASSERT_NOT_REACHED();
 }
 
 EncodedJSValue JSC_HOST_CALL arrayConstructorPrivateFuncIsArrayConstructor(ExecState* exec)

Modified: trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp (197898 => 197899)


--- trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/runtime/ArrayPrototype.cpp	2016-03-10 00:36:06 UTC (rev 197899)
@@ -205,7 +205,7 @@
         }
     }
     if (constructor.isUndefined())
-        return std::make_pair(SpeciesConstructResult::FastPath, nullptr);;
+        return std::make_pair(SpeciesConstructResult::FastPath, nullptr);
 
     MarkedArgumentBuffer args;
     args.append(jsNumber(length));

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.cpp (197898 => 197899)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.cpp	2016-03-10 00:36:06 UTC (rev 197899)
@@ -1085,6 +1085,11 @@
     m_handler.set(vm, this, jsNull());
 }
 
+bool ProxyObject::isRevoked() const
+{
+    return handler().isNull();
+}
+
 void ProxyObject::visitChildren(JSCell* cell, SlotVisitor& visitor)
 {
     ProxyObject* thisObject = jsCast<ProxyObject*>(cell);

Modified: trunk/Source/_javascript_Core/runtime/ProxyObject.h (197898 => 197899)


--- trunk/Source/_javascript_Core/runtime/ProxyObject.h	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/runtime/ProxyObject.h	2016-03-10 00:36:06 UTC (rev 197899)
@@ -59,14 +59,15 @@
 
     DECLARE_EXPORT_INFO;
 
-    JSObject* target() { return m_target.get(); }
-    JSValue handler() { return m_handler.get(); }
+    JSObject* target() const { return m_target.get(); }
+    JSValue handler() const { return m_handler.get(); }
 
     static void put(JSCell*, ExecState*, PropertyName, JSValue, PutPropertySlot&);
     static void putByIndex(JSCell*, ExecState*, unsigned propertyName, JSValue, bool shouldThrow);
     void putByIndexCommon(ExecState*, JSValue thisValue, unsigned propertyName, JSValue putValue, bool shouldThrow);
     JSValue performGetPrototype(ExecState*);
     void revoke(VM&);
+    bool isRevoked() const;
 
 private:
     ProxyObject(VM&, Structure*);

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (197898 => 197899)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-10 00:22:12 UTC (rev 197898)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-10 00:36:06 UTC (rev 197899)
@@ -909,7 +909,7 @@
 - path: es6/Proxy_apply_handler.js
   cmd: runES6 :normal
 - path: es6/Proxy_Array.isArray_support.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/Proxy_construct_handler.js
   cmd: runES6 :normal
 - path: es6/Proxy_constructor_requires_new.js

Added: trunk/Source/_javascript_Core/tests/stress/proxy-is-array.js (0 => 197899)


--- trunk/Source/_javascript_Core/tests/stress/proxy-is-array.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/proxy-is-array.js	2016-03-10 00:36:06 UTC (rev 197899)
@@ -0,0 +1,61 @@
+function assert(b) {
+    if (!b)
+        throw new Error("Bad assertion.")
+}
+
+function test(f) {
+    for (let i = 0; i < 500; i++)
+        f();
+}
+
+test(function() {
+    let proxy = new Proxy([], {});
+    assert(Array.isArray(proxy));
+});
+
+test(function() {
+    let {proxy, revoke} = Proxy.revocable([], {});
+    assert(Array.isArray(proxy));
+
+    revoke();
+    let threw = false;
+    try {
+        Array.isArray(proxy);
+    } catch(e) {
+        threw = true;
+        assert(e.toString() === "TypeError: Array.isArray can not be called on a Proxy that has been revoked.");
+    }
+    assert(threw);
+});
+
+test(function() {
+    let proxyChain = new Proxy([], {});
+    for (let i = 0; i < 400; i++)
+        proxyChain = new Proxy(proxyChain, {});
+    assert(Array.isArray(proxyChain));
+});
+
+test(function() {
+    let proxyChain = new Proxy([], {});
+    let revoke = null;
+    for (let i = 0; i < 400; i++) {
+        if (i !== 250) {
+            proxyChain = new Proxy(proxyChain, {});
+        } else {
+            let result = Proxy.revocable(proxyChain, {});
+            proxyChain = result.proxy;
+            revoke = result.revoke;
+        }
+    }
+    assert(Array.isArray(proxyChain));
+
+    revoke();
+    let threw = false;
+    try {
+        Array.isArray(proxyChain);
+    } catch(e) {
+        threw = true;
+        assert(e.toString() === "TypeError: Array.isArray can not be called on a Proxy that has been revoked.");
+    }
+    assert(threw);
+});
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to