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);
+});