Bug 975277 - Add some machinery to allow Traits to specify whether they want to use hasPrototype or not. r=bholley,efaust
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 21 Feb 2014 15:55:30 -0800
changeset 170334 89a7246d2bdd243926c1ddfa99a232dda8feef5f
parent 170333 8ef55688cc4a1fc2ff26cb18fe18b4d8c0f7d54e
child 170335 65192746bdee99ded19f577058d4b66d00545d3c
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersbholley, efaust
bugs975277
milestone30.0a1
Bug 975277 - Add some machinery to allow Traits to specify whether they want to use hasPrototype or not. r=bholley,efaust
js/xpconnect/wrappers/XrayWrapper.cpp
js/xpconnect/wrappers/XrayWrapper.h
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -188,16 +188,20 @@ private:
     JSObject* attachExpandoObject(JSContext *cx, HandleObject target,
                                   nsIPrincipal *origin,
                                   HandleObject exclusiveGlobal);
 };
 
 class XPCWrappedNativeXrayTraits : public XrayTraits
 {
 public:
+    enum {
+        HasPrototype = 0
+    };
+
     static const XrayType Type = XrayForWrappedNative;
 
     virtual bool resolveNativeProperty(JSContext *cx, HandleObject wrapper,
                                        HandleObject holder, HandleId id,
                                        MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObject wrapper,
                                     HandleObject holder, HandleId id,
                                     MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
@@ -228,16 +232,20 @@ public:
     virtual JSObject* createHolder(JSContext *cx, JSObject *wrapper);
 
     static XPCWrappedNativeXrayTraits singleton;
 };
 
 class DOMXrayTraits : public XrayTraits
 {
 public:
+    enum {
+        HasPrototype = 0
+    };
+
     static const XrayType Type = XrayForDOMObject;
 
     virtual bool resolveNativeProperty(JSContext *cx, HandleObject wrapper,
                                        HandleObject holder, HandleId id,
                                        MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
     virtual bool resolveOwnProperty(JSContext *cx, Wrapper &jsWrapper, HandleObject wrapper,
                                     HandleObject holder, HandleId id,
                                     MutableHandle<JSPropertyDescriptor> desc, unsigned flags);
@@ -1234,16 +1242,17 @@ DOMXrayTraits::createHolder(JSContext *c
     RootedObject global(cx, JS_GetGlobalForObject(cx, wrapper));
     return JS_NewObjectWithGivenProto(cx, nullptr, JS::NullPtr(), global);
 }
 
 template <typename Base, typename Traits>
 XrayWrapper<Base, Traits>::XrayWrapper(unsigned flags)
   : Base(flags | WrapperFactory::IS_XRAY_WRAPPER_FLAG)
 {
+    Base::setHasPrototype(Traits::HasPrototype);
 }
 
 template <typename Base, typename Traits>
 XrayWrapper<Base, Traits>::~XrayWrapper()
 {
 }
 
 namespace XrayUtils {
@@ -1858,34 +1867,27 @@ XrayWrapper<Base, Traits>::getPrototypeO
     // specializations (and therefore a helper class), which is all more trouble
     // than it's worth. Do a dynamic check.
     if (Base::hasSecurityPolicy())
         return Base::getPrototypeOf(cx, wrapper, protop);
 
     RootedObject target(cx, Traits::getTargetObject(wrapper));
     RootedObject expando(cx, Traits::singleton.getExpandoObject(cx, target, wrapper));
 
-    // We want to keep the Xray's prototype distinct from that of content, but only
-    // if there's been a set. If there's not an expando, or the expando slot is |undefined|,
-    // hand back content's proto, appropriately wrapped.
-    //
-    // NB: Our baseclass's getPrototypeOf() will appropriately wrap its return value, so there is
-    // no need for us to.
-
-    if (!expando)
-        return Base::getPrototypeOf(cx, wrapper, protop);
+    // We want to keep the Xray's prototype distinct from that of content, but
+    // only if there's been a set. If there's not an expando, or the expando
+    // slot is |undefined|, hand back the default proto, appropriately wrapped.
 
     RootedValue v(cx);
-    {
+    if (expando) {
         JSAutoCompartment ac(cx, expando);
         v = JS_GetReservedSlot(expando, JSSLOT_EXPANDO_PROTOTYPE);
     }
-
     if (v.isUndefined())
-        return Base::getPrototypeOf(cx, wrapper, protop);
+        return getPrototypeOfHelper(cx, wrapper, target, protop);
 
     protop.set(v.toObjectOrNull());
     return JS_WrapObject(cx, protop);
 }
 
 template <typename Base, typename Traits>
 bool
 XrayWrapper<Base, Traits>::setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
--- a/js/xpconnect/wrappers/XrayWrapper.h
+++ b/js/xpconnect/wrappers/XrayWrapper.h
@@ -109,16 +109,37 @@ class XrayWrapper : public Base {
     virtual bool getPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
                                 JS::MutableHandleObject protop) MOZ_OVERRIDE;
     virtual bool setPrototypeOf(JSContext *cx, JS::HandleObject wrapper,
                                 JS::HandleObject proto, bool *bp) MOZ_OVERRIDE;
 
     static XrayWrapper singleton;
 
   private:
+    template <bool HasPrototype>
+    typename mozilla::EnableIf<HasPrototype, bool>::Type
+        getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
+                             JS::HandleObject target, JS::MutableHandleObject protop)
+    {
+        return Traits::singleton.getPrototypeOf(cx, wrapper, target, protop);
+    }
+    template <bool HasPrototype>
+    typename mozilla::EnableIf<!HasPrototype, bool>::Type
+        getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
+                             JS::HandleObject target, JS::MutableHandleObject protop)
+    {
+        return Base::getPrototypeOf(cx, wrapper, protop);
+    }
+    bool getPrototypeOfHelper(JSContext *cx, JS::HandleObject wrapper,
+                              JS::HandleObject target, JS::MutableHandleObject protop)
+    {
+        return getPrototypeOfHelper<Traits::HasPrototype>(cx, wrapper, target,
+                                                          protop);
+    }
+
     bool enumerate(JSContext *cx, JS::Handle<JSObject*> wrapper, unsigned flags,
                    JS::AutoIdVector &props);
 };
 
 #define PermissiveXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::XPCWrappedNativeXrayTraits>
 #define SecurityXrayXPCWN xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::XPCWrappedNativeXrayTraits>
 #define PermissiveXrayDOM xpc::XrayWrapper<js::CrossCompartmentWrapper, xpc::DOMXrayTraits>
 #define SecurityXrayDOM xpc::XrayWrapper<js::CrossCompartmentSecurityWrapper, xpc::DOMXrayTraits>