Bug 1246318 - Make the proxy enumerate trap non-standard. r=efaust
authorTom Schuster <evilpies@gmail.com>
Wed, 10 Feb 2016 00:12:24 +0100
changeset 283647 fd209a5854c0
parent 283646 db76a38f2eb8
child 283648 da0d807517ca
push id71626
push userevilpies@gmail.com
push dateTue, 09 Feb 2016 23:12:42 +0000
treeherdermozilla-inbound@874423b7e907 [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 - Make the proxy enumerate trap non-standard. r=efaust
dom/bindings/DOMJSProxyHandler.cpp
dom/bindings/DOMJSProxyHandler.h
js/public/Proxy.h
js/src/builtin/ModuleObject.cpp
js/src/builtin/ModuleObject.h
js/src/proxy/DeadObjectProxy.cpp
js/src/proxy/DeadObjectProxy.h
js/src/vm/ScopeObject.cpp
--- a/dom/bindings/DOMJSProxyHandler.cpp
+++ b/dom/bindings/DOMJSProxyHandler.cpp
@@ -255,23 +255,16 @@ bool
 BaseDOMProxyHandler::getOwnEnumerablePropertyKeys(JSContext* cx,
                                                   JS::Handle<JSObject*> proxy,
                                                   JS::AutoIdVector& props) const
 {
   return ownPropNames(cx, proxy, JSITER_OWNONLY, props);
 }
 
 bool
-BaseDOMProxyHandler::enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
-                               JS::MutableHandle<JSObject*> objp) const
-{
-  return BaseProxyHandler::enumerate(cx, proxy, objp);
-}
-
-bool
 DOMProxyHandler::has(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id, bool* bp) const
 {
   if (!hasOwn(cx, proxy, id, bp)) {
     return false;
   }
 
   if (*bp) {
     // We have the property ourselves; no need to worry about our prototype
--- a/dom/bindings/DOMJSProxyHandler.h
+++ b/dom/bindings/DOMJSProxyHandler.h
@@ -54,19 +54,16 @@ public:
   // Implementations of methods that can be implemented in terms of
   // other lower-level methods.
   bool getOwnPropertyDescriptor(JSContext* cx, JS::Handle<JSObject*> proxy,
                                 JS::Handle<jsid> id,
                                 JS::MutableHandle<JS::PropertyDescriptor> desc) const override;
   virtual bool ownPropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                JS::AutoIdVector &props) const override;
 
-  virtual bool enumerate(JSContext *cx, JS::Handle<JSObject*> proxy,
-                         JS::MutableHandle<JSObject*> objp) const override;
-
   // We override getOwnEnumerablePropertyKeys() and implement it directly
   // instead of using the default implementation, which would call
   // ownPropertyKeys and then filter out the non-enumerable ones. This avoids
   // unnecessary work during enumeration.
   virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, JS::Handle<JSObject*> proxy,
                                             JS::AutoIdVector &props) const override;
 
   bool watch(JSContext* cx, JS::Handle<JSObject*> proxy, JS::Handle<jsid> id,
--- a/js/public/Proxy.h
+++ b/js/public/Proxy.h
@@ -54,26 +54,25 @@ class JS_FRIEND_API(Wrapper);
  * -   DOM objects with special property behavior, like named getters
  *     (dom/bindings/Codegen.py generates these proxies from WebIDL)
  *
  * -   semi-transparent use of objects that live in other processes
  *     (CPOWs, implemented in js/ipc)
  *
  * ### Proxies and internal methods
  *
- * ES6 draft rev 27 (24 August 2014) specifies 14 internal methods. The runtime
- * semantics of just about everything a script can do to an object is specified
- * in terms of these internal methods. For example:
+ * ES2016 specifies 13 internal methods. The runtime  semantics of just
+ * about everything a script can do to an object is specified in terms
+ * of these internal methods. For example:
  *
  *     JS code                      ES6 internal method that gets called
  *     ---------------------------  --------------------------------
  *     obj.prop                     obj.[[Get]](obj, "prop")
  *     "prop" in obj                obj.[[HasProperty]]("prop")
  *     new obj()                    obj.[[Construct]](<empty argument List>)
- *     for (k in obj) {}            obj.[[Enumerate]]()
  *
  * With regard to the implementation of these internal methods, there are three
  * very different kinds of object in SpiderMonkey.
  *
  * 1.  Native objects' internal methods are implemented in vm/NativeObject.cpp,
  *     with duplicate (but functionally identical) implementations scattered
  *     through the ICs and JITs.
  *
@@ -257,24 +256,16 @@ class JS_FRIEND_API(BaseProxyHandler)
                                 Handle<PropertyDescriptor> desc,
                                 ObjectOpResult& result) const = 0;
     virtual bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
                                  AutoIdVector& props) const = 0;
     virtual bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
                          ObjectOpResult& result) const = 0;
 
     /*
-     * Because [[Enumerate]] is one of the standard traps it should be overridden.
-     * However for convenience BaseProxyHandler includes a pure virtual implementation,
-     * that turns the properties returned by getOwnEnumerablePropertyKeys (and proto walking)
-     * into an Iterator object.
-     */
-    virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const = 0;
-
-    /*
      * These methods are standard, but the engine does not normally call them.
      * They're opt-in. See "Proxy prototype chains" above.
      *
      * getPrototype() crashes if called. setPrototype() throws a TypeError.
      */
     virtual bool getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const;
     virtual bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
                               ObjectOpResult& result) const;
@@ -310,16 +301,17 @@ class JS_FRIEND_API(BaseProxyHandler)
      * BaseProxyHandler::call()/construct() crash if called. So if you're
      * creating a kind of that is never callable, you don't have to override
      * anything, but otherwise you probably want to override all four.
      */
     virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const;
     virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const;
 
     /* SpiderMonkey extensions. */
+    virtual bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const;
     virtual bool getPropertyDescriptor(JSContext* cx, HandleObject proxy, HandleId id,
                                        MutableHandle<PropertyDescriptor> desc) const;
     virtual bool hasOwn(JSContext* cx, HandleObject proxy, HandleId id, bool* bp) const;
     virtual bool getOwnEnumerablePropertyKeys(JSContext* cx, HandleObject proxy,
                                               AutoIdVector& props) const;
     virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
                             const CallArgs& args) const;
     virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v, bool* bp) const;
--- a/js/src/builtin/ModuleObject.cpp
+++ b/js/src/builtin/ModuleObject.cpp
@@ -489,23 +489,16 @@ ModuleNamespaceObject::ProxyHandler::del
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     if (ns->bindings().has(id))
         return result.failReadOnly();
 
     return result.succeed();
 }
 
 bool
-ModuleNamespaceObject::ProxyHandler::enumerate(JSContext* cx, HandleObject proxy,
-                                               MutableHandleObject objp) const
-{
-    return BaseProxyHandler::enumerate(cx, proxy, objp);
-}
-
-bool
 ModuleNamespaceObject::ProxyHandler::ownPropertyKeys(JSContext* cx, HandleObject proxy,
                                                      AutoIdVector& props) const
 {
     Rooted<ModuleNamespaceObject*> ns(cx, &proxy->as<ModuleNamespaceObject>());
     RootedArrayObject exports(cx, &ns->exports());
     uint32_t count = exports->length();
     if (!props.reserve(props.length() + count))
         return false;
--- a/js/src/builtin/ModuleObject.h
+++ b/js/src/builtin/ModuleObject.h
@@ -157,17 +157,16 @@ class ModuleNamespaceObject : public Pro
                                       MutableHandle<PropertyDescriptor> desc) const override;
         bool defineProperty(JSContext* cx, HandleObject proxy, HandleId id,
                             Handle<PropertyDescriptor> desc,
                             ObjectOpResult& result) const override;
         bool ownPropertyKeys(JSContext* cx, HandleObject proxy,
                              AutoIdVector& props) const override;
         bool delete_(JSContext* cx, HandleObject proxy, HandleId id,
                      ObjectOpResult& result) const override;
-        bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const override;
         bool getPrototype(JSContext* cx, HandleObject proxy,
                           MutableHandleObject protop) const override;
         bool setPrototype(JSContext* cx, HandleObject proxy, HandleObject proto,
                           ObjectOpResult& result) const override;
         bool setImmutablePrototype(JSContext* cx, HandleObject proxy,
                                    bool* succeeded) const override;
 
         bool preventExtensions(JSContext* cx, HandleObject proxy,
--- a/js/src/proxy/DeadObjectProxy.cpp
+++ b/js/src/proxy/DeadObjectProxy.cpp
@@ -49,23 +49,16 @@ bool
 DeadObjectProxy::delete_(JSContext* cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult& result) const
 {
     ReportDead(cx);
     return false;
 }
 
 bool
-DeadObjectProxy::enumerate(JSContext* cx, HandleObject wrapper, MutableHandleObject objp) const
-{
-    ReportDead(cx);
-    return false;
-}
-
-bool
 DeadObjectProxy::getPrototype(JSContext* cx, HandleObject proxy, MutableHandleObject protop) const
 {
     protop.set(nullptr);
     return true;
 }
 
 bool
 DeadObjectProxy::preventExtensions(JSContext* cx, HandleObject proxy, ObjectOpResult& result) const
--- a/js/src/proxy/DeadObjectProxy.h
+++ b/js/src/proxy/DeadObjectProxy.h
@@ -23,27 +23,27 @@ class DeadObjectProxy : public BaseProxy
                                           MutableHandle<PropertyDescriptor> desc) const override;
     virtual bool defineProperty(JSContext* cx, HandleObject wrapper, HandleId id,
                                 Handle<PropertyDescriptor> desc,
                                 ObjectOpResult& result) const override;
     virtual bool ownPropertyKeys(JSContext* cx, HandleObject wrapper,
                                  AutoIdVector& props) const override;
     virtual bool delete_(JSContext* cx, HandleObject wrapper, HandleId id,
                          ObjectOpResult& result) const override;
-    virtual bool enumerate(JSContext* cx, HandleObject wrapper, MutableHandleObject objp) const override;
     virtual bool getPrototype(JSContext* cx, HandleObject proxy,
                               MutableHandleObject protop) const override;
     virtual bool preventExtensions(JSContext* cx, HandleObject proxy,
                                    ObjectOpResult& result) const override;
     virtual bool isExtensible(JSContext* cx, HandleObject proxy, bool* extensible) const override;
     virtual bool call(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
     virtual bool construct(JSContext* cx, HandleObject proxy, const CallArgs& args) const override;
 
     /* SpiderMonkey extensions. */
     // BaseProxyHandler::getPropertyDescriptor will throw by calling getOwnPropertyDescriptor.
+    // BaseProxyHandler::enumerate will throw by calling ownKeys.
     virtual bool nativeCall(JSContext* cx, IsAcceptableThis test, NativeImpl impl,
                             const CallArgs& args) const override;
     virtual bool hasInstance(JSContext* cx, HandleObject proxy, MutableHandleValue v,
                              bool* bp) const override;
     virtual bool getBuiltinClass(JSContext* cx, HandleObject proxy,
                                  ESClassValue* classValue) const override;
     virtual bool isArray(JSContext* cx, HandleObject proxy, JS::IsArrayAnswer* answer) const override;
     virtual const char* className(JSContext* cx, HandleObject proxy) const override;
--- a/js/src/vm/ScopeObject.cpp
+++ b/js/src/vm/ScopeObject.cpp
@@ -2328,21 +2328,16 @@ class DebugScopeProxy : public BaseProxy
                 if (!bi->aliased() && !props.append(NameToId(bi->name())))
                     return false;
             }
         }
 
         return true;
     }
 
-    bool enumerate(JSContext* cx, HandleObject proxy, MutableHandleObject objp) const override
-    {
-        return BaseProxyHandler::enumerate(cx, proxy, objp);
-    }
-
     bool has(JSContext* cx, HandleObject proxy, HandleId id_, bool* bp) const override
     {
         RootedId id(cx, id_);
         ScopeObject& scopeObj = proxy->as<DebugScopeObject>().scope();
 
         if (isArguments(cx, id) && isFunctionScope(scopeObj)) {
             *bp = true;
             return true;