Bug 1246318 - Remove the enumerate trap from ES6 proxies. r=efaust
authorTom Schuster <evilpies@gmail.com>
Wed, 10 Feb 2016 00:12:24 +0100
changeset 283687 da0d807517ca
parent 283686 fd209a5854c0
child 283688 874423b7e907
push id29988
push usercbook@mozilla.com
push dateWed, 10 Feb 2016 10:47:59 +0000
treeherdermozilla-central@7042e8a19f94 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersefaust
bugs1246318
milestone47.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1246318 - Remove the enumerate trap from ES6 proxies. r=efaust
addon-sdk/source/lib/sdk/preferences/service.js
js/src/jit-test/tests/proxy/testDirectProxyEnumerate2.js
js/src/jit-test/tests/proxy/testDirectProxyEnumerate3.js
js/src/jit-test/tests/proxy/testDirectProxyEnumerate4.js
js/src/proxy/ScriptedDirectProxyHandler.cpp
js/src/proxy/ScriptedDirectProxyHandler.h
js/src/tests/ecma_6/Proxy/proxy-for-in.js
js/src/tests/ecma_6/Proxy/revoke-as-side-effect.js
testing/specialpowers/content/specialpowersAPI.js
--- a/addon-sdk/source/lib/sdk/preferences/service.js
+++ b/addon-sdk/source/lib/sdk/preferences/service.js
@@ -32,19 +32,16 @@ const Branch = function(branchName) {
     getOwnPropertyDescriptor(target, name, receiver) {
       return {
         configurable: true,
         enumerable: true,
         writable: false,
         value: this.get(target, name, receiver)
       };
     },
-    enumerate(target) {
-      return branchKeys(branchName)[Symbol.iterator]();
-    },
     ownKeys(target) {
       return branchKeys(branchName);
     },
     get(target, name, receiver) {
       return get(`${branchName}${name}`);
     },
     set(target, name, value, receiver) {
       set(`${branchName}${name}`, value);
deleted file mode 100644
--- a/js/src/jit-test/tests/proxy/testDirectProxyEnumerate2.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Throwing [[Enumerate]] handler
-load(libdir + "asserts.js");
-
-let handler = new Proxy({}, {
-    get: function(target, name) {
-        assertEq(name, "enumerate");
-        throw new SyntaxError();
-    }
-});
-
-let proxy = new Proxy({}, handler);
-
-assertThrowsInstanceOf(function() {
-    for (let x in proxy)
-        assertEq(true, false);
-}, SyntaxError)
deleted file mode 100644
--- a/js/src/jit-test/tests/proxy/testDirectProxyEnumerate3.js
+++ /dev/null
@@ -1,16 +0,0 @@
-// Basic [[Enumerate]] functionality test
-let inner = [];
-let handler = {
-    enumerate: function(target) {
-        assertEq(target, inner);
-        assertEq(arguments.length, 1);
-        assertEq(this, handler);
-        return (function*() { yield 'a'; })();
-    }
-};
-
-let x;
-for (let y in new Proxy(inner, handler)) {
-    x = y;
-}
-assertEq(x, 'a');
deleted file mode 100644
--- a/js/src/jit-test/tests/proxy/testDirectProxyEnumerate4.js
+++ /dev/null
@@ -1,15 +0,0 @@
-// Returning primitive from [[Enumerate]] handler
-load(libdir + "asserts.js");
-
-let handler = {
-    enumerate: function() {
-        return undefined;
-    }
-};
-
-let proxy = new Proxy({}, handler);
-
-assertThrowsInstanceOf(function() {
-    for (let x in proxy)
-        assertEq(true, false);
-}, TypeError)
--- a/js/src/proxy/ScriptedDirectProxyHandler.cpp
+++ b/js/src/proxy/ScriptedDirectProxyHandler.cpp
@@ -719,62 +719,16 @@ ScriptedDirectProxyHandler::delete_(JSCo
         ReportValueError(cx, JSMSG_CANT_DELETE, JSDVG_IGNORE_STACK, v, nullptr);
         return false;
     }
 
     // step 16
     return result.succeed();
 }
 
-// ES6 (14 October, 2014) 9.5.11 Proxy.[[Enumerate]]
-bool
-ScriptedDirectProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
-                                      MutableHandleObject objp) const
-{
-    // step 1
-    RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
-
-    // step 2
-    if (!handler) {
-        JS_ReportErrorNumber(cx, GetErrorMessage, nullptr, JSMSG_PROXY_REVOKED);
-        return false;
-    }
-
-    // step 3: unnecessary assert
-    // step 4
-    RootedObject target(cx, proxy->as<ProxyObject>().target());
-
-    // step 5-6
-    RootedValue trap(cx);
-    if (!GetProperty(cx, handler, handler, cx->names().enumerate, &trap))
-        return false;
-
-    // step 7
-    if (trap.isUndefined())
-        return GetIterator(cx, target, 0, objp);
-
-    // step 8-9
-    Value argv[] = {
-        ObjectOrNullValue(target)
-    };
-    RootedValue trapResult(cx);
-    if (!Invoke(cx, ObjectValue(*handler), trap, ArrayLength(argv), argv, &trapResult))
-        return false;
-
-    // step 10
-    if (trapResult.isPrimitive()) {
-        ReportInvalidTrapResult(cx, proxy, cx->names().enumerate);
-        return false;
-    }
-
-    // step 11
-    objp.set(&trapResult.toObject());
-    return true;
-}
-
 // ES6 (22 May, 2014) 9.5.7 Proxy.[[HasProperty]](P)
 bool
 ScriptedDirectProxyHandler::has(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const
 {
     // step 2
     RootedObject handler(cx, GetDirectProxyHandlerObject(proxy));
 
     // step 3
--- a/js/src/proxy/ScriptedDirectProxyHandler.h
+++ b/js/src/proxy/ScriptedDirectProxyHandler.h
@@ -23,17 +23,16 @@ class ScriptedDirectProxyHandler : publi
                                           MutableHandle<PropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
                                 Handle<PropertyDescriptor> desc,
                                 ObjectOpResult& result) const override;
     virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
                                  AutoIdVector& props) const override;
     virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
                          ObjectOpResult& result) const override;
-    virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const override;
 
     /* These two are standard internal methods but aren't implemented to spec yet. */
     virtual bool getPrototype(JSContext* cx, HandleObject proxy,
                               MutableHandleObject protop) const override;
     virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
                               ObjectOpResult& result) const override;
     /* Non-standard, but needed to handle revoked proxies. */
     virtual bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/Proxy/proxy-for-in.js
@@ -0,0 +1,37 @@
+// Any copyright is dedicated to the Public Domain.
+// http://creativecommons.org/licenses/publicdomain/
+"use strict";
+
+let steps = [];
+
+const object = {
+    __proto__: {
+        "xyz": 42
+    }
+};
+const proxy = new Proxy(object, {
+    ownKeys(target) {
+        steps.push("ownKeys")
+        return ["a", "b"];
+    },
+
+    getOwnPropertyDescriptor(target, property) {
+        steps.push("getOwn-" + property);
+        return {
+            value: undefined,
+            configurable: true,
+            writable: true,
+            enumerable: (property === "a")
+        };
+    }
+});
+
+let iterated = [];
+for (let x in proxy)
+    iterated.push(x);
+
+assertEq(iterated.toString(), "a,xyz");
+assertEq(steps.toString(), "ownKeys,getOwn-a,getOwn-b");
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
--- a/js/src/tests/ecma_6/Proxy/revoke-as-side-effect.js
+++ b/js/src/tests/ecma_6/Proxy/revoke-as-side-effect.js
@@ -48,26 +48,16 @@ assertEq(createProxy({a: 5}).a, 5);
 // [[Set]]
 assertThrowsInstanceOf(() => createProxy({}).a = 0, TypeError);
 assertThrowsInstanceOf(() => createProxy({a: 5}).a = 0, TypeError);
 
 // [[Delete]]
 assertEq(delete createProxy({}).a, true);
 assertEq(delete createProxy(Object.defineProperty({}, "a", {configurable: false})).a, false);
 
-// [[Enumerate]]
-for (var k in createProxy({})) {
-    // No properties in object.
-    assertEq(true, false);
-}
-for (var k in createProxy({a: 5})) {
-    // Properties in object.
-    assertEq(k, "a");
-}
-
 // [[OwnPropertyKeys]]
 assertEq(Object.getOwnPropertyNames(createProxy({})).length, 0);
 assertEq(Object.getOwnPropertyNames(createProxy({a: 5})).length, 1);
 
 // [[Call]]
 assertEq(createProxy(function() { return "ok" })(), "ok");
 
 // [[Construct]]
--- a/testing/specialpowers/content/specialpowersAPI.js
+++ b/testing/specialpowers/content/specialpowersAPI.js
@@ -289,23 +289,16 @@ SpecialPowersHandler.prototype = {
     if ('wrappedJSObject' in this.wrappedObject) {
       props = props.concat(Reflect.ownKeys(this.wrappedObject.wrappedJSObject)
                            .filter(flt));
     }
 
     return props;
   },
 
-  enumerate(target) {
-    return (function*() {
-      for (let property in this.wrappedObject)
-        yield property;
-    }).call(this);
-  },
-
   preventExtensions(target) {
     throw "Can't call preventExtensions on SpecialPowers wrapped object";
   }
 };
 
 // SPConsoleListener reflects nsIConsoleMessage objects into JS in a
 // tidy, XPCOM-hiding way.  Messages that are nsIScriptError objects
 // have their properties exposed in detail.  It also auto-unregisters