Bug 761695 - Get the WN directly from the wrapper. r=peterv
authorBobby Holley <bobbyholley@gmail.com>
Fri, 05 Oct 2012 18:59:23 +0200
changeset 109394 03667c5bc77b2eea5e3faf521282ee0d30486716
parent 109393 f5225ec3579517e083d62a5ea6161368ee1d6bae
child 109395 b1c000f475d45cb532e567d7a099b80cc2597fa4
push id16008
push userbobbyholley@gmail.com
push dateFri, 05 Oct 2012 16:59:43 +0000
treeherdermozilla-inbound@3b4562fd4f20 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs761695
milestone18.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 761695 - Get the WN directly from the wrapper. r=peterv All this indirection was getting seriously mucky. This, incidentally, means that the XPCWN holder no longer needs a reserved slot pointing to the WN.
js/xpconnect/wrappers/XrayWrapper.cpp
--- a/js/xpconnect/wrappers/XrayWrapper.cpp
+++ b/js/xpconnect/wrappers/XrayWrapper.cpp
@@ -23,18 +23,17 @@
 #include "mozilla/dom/BindingUtils.h"
 
 using namespace mozilla::dom;
 
 namespace xpc {
 
 using namespace js;
 
-static const uint32_t JSSLOT_WRAPPER = 0;
-static const uint32_t JSSLOT_RESOLVING = 1;
+static const uint32_t JSSLOT_RESOLVING = 0;
 
 static XPCWrappedNative *GetWrappedNative(JSObject *obj);
 
 namespace XrayUtils {
 
 JSClass HolderClass = {
     "NativePropertyHolder",
     JSCLASS_HAS_RESERVED_SLOTS(2),
@@ -255,17 +254,16 @@ JSObject *
 createHolder(JSContext *cx, JSObject *wrapper)
 {
     JSObject *global = JS_GetGlobalForObject(cx, wrapper);
     JSObject *holder = JS_NewObjectWithGivenProto(cx, &HolderClass, nullptr,
                                                   global);
     if (!holder)
         return nullptr;
 
-    js::SetReservedSlot(holder, JSSLOT_WRAPPER, ObjectValue(*wrapper));
     js::SetReservedSlot(holder, JSSLOT_RESOLVING, PrivateValue(NULL));
     return holder;
 }
 
 }
 
 using namespace XrayUtils;
 
@@ -372,16 +370,20 @@ public:
         return getHolderObject(wrapper);
     }
 
     static bool isResolving(JSContext *cx, JSObject *holder, jsid id);
 
     static bool resolveDOMCollectionProperty(JSContext *cx, JSObject *wrapper, JSObject *holder,
                                              jsid id, bool set, PropertyDescriptor *desc);
 
+    static XPCWrappedNative* getWN(JSObject *wrapper) {
+        return GetWrappedNative(getTargetObject(wrapper));
+    }
+
     typedef ResolvingId ResolvingIdImpl;
 
     static XPCWrappedNativeXrayTraits singleton;
 
 private:
     static JSObject* getHolderObject(JSObject *wrapper)
     {
         return &js::GetProxyExtra(wrapper, 0).toObject();
@@ -484,30 +486,16 @@ GetHolder(JSObject *obj)
 
 static XPCWrappedNative *
 GetWrappedNative(JSObject *obj)
 {
     MOZ_ASSERT(IS_WN_WRAPPER_OBJECT(obj));
     return static_cast<XPCWrappedNative *>(js::GetObjectPrivate(obj));
 }
 
-static XPCWrappedNative *
-GetWrappedNativeFromHolder(JSObject *holder)
-{
-    MOZ_ASSERT(js::GetObjectJSClass(holder) == &HolderClass);
-    JSObject *wrapper = &js::GetReservedSlot(holder, JSSLOT_WRAPPER).toObject();
-    return GetWrappedNative(XrayTraits::getTargetObject(wrapper));
-}
-
-static JSObject *
-GetWrappedNativeObjectFromHolder(JSObject *holder)
-{
-    return GetWrappedNativeFromHolder(holder)->GetFlatJSObject();
-}
-
 static inline JSObject *
 FindWrapper(JSContext *cx, JSObject *wrapper)
 {
     while (!js::IsWrapper(wrapper) ||
            !(Wrapper::wrapperHandler(wrapper)->flags() &
              WrapperFactory::IS_XRAY_WRAPPER_FLAG)) {
         if (js::IsWrapper(wrapper) &&
             js::GetProxyHandler(wrapper) == &sandboxProxyHandler) {
@@ -536,17 +524,17 @@ JSBool
 holder_get(JSContext *cx, JSHandleObject wrapper_, JSHandleId id, JSMutableHandleValue vp)
 {
     JSObject *wrapper = FindWrapper(cx, wrapper_);
     if (!wrapper)
         return false;
 
     JSObject *holder = GetHolder(wrapper);
 
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantGetProperty)) {
         JSAutoCompartment ac(cx, holder);
         bool retval = true;
         nsresult rv = wn->GetScriptableCallback()->GetProperty(wn, cx, wrapper,
                                                                id, vp.address(), &retval);
         if (NS_FAILED(rv) || !retval) {
             if (retval)
                 XPCThrower::Throw(rv, cx);
@@ -563,17 +551,17 @@ holder_set(JSContext *cx, JSHandleObject
     if (!wrapper)
         return false;
 
     JSObject *holder = GetHolder(wrapper);
     if (XPCWrappedNativeXrayTraits::isResolving(cx, holder, id)) {
         return true;
     }
 
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantSetProperty)) {
         JSAutoCompartment ac(cx, holder);
         bool retval = true;
         nsresult rv = wn->GetScriptableCallback()->SetProperty(wn, cx, wrapper,
                                                                id, vp.address(), &retval);
         if (NS_FAILED(rv) || !retval) {
             if (retval)
                 XPCThrower::Throw(rv, cx);
@@ -615,17 +603,17 @@ XPCWrappedNativeXrayTraits::resolveDOMCo
                                                          PropertyDescriptor *desc)
 {
     // If we are not currently resolving this id and resolveNative is called
     // we don't do anything. (see defineProperty in case of shadowing is forbidden).
     ResolvingId *rid = ResolvingId::getResolvingId(holder);
     if (!rid || rid->mId != id)
         return true;
 
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = getWN(wrapper);
     if (!NATIVE_HAS_FLAG(wn, WantNewResolve))
         return true;
 
     // Setting the current ResolvingId in non-shadowing mode. So for this id
     // Xray won't ignore DOM specific collection properties temporarily.
     AutoSetWrapperNotShadowing asw(wrapper);
 
     bool retval = true;
@@ -647,18 +635,17 @@ XPCWrappedNativeXrayTraits::resolveDOMCo
 
     return true;
 }
 
 template <typename T>
 static bool
 Is(JSObject *wrapper)
 {
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     nsCOMPtr<T> native = do_QueryWrappedNative(wn);
     return !!native;
 }
 
 // Helper function to work around some limitations of the current XPC 
 // calling mechanism. See: bug 763897.
 // The idea is that we unwrap the 'this' object, and find the wrapped
 // native that belongs to it. Then we simply make the call directly
@@ -674,18 +661,17 @@ mozMatchesSelectorStub(JSContext *cx, un
     JSObject *wrapper = JS_THIS_OBJECT(cx, vp);
     JSString *selector = JS_ValueToString(cx, JS_ARGV(cx, vp)[0]);
     nsDependentJSString selectorStr;
     NS_ENSURE_TRUE(selectorStr.init(cx, selector), false);
 
     nsCOMPtr<nsIDOMElement> element;
     if (IsWrapper(wrapper) && WrapperFactory::IsXrayWrapper(wrapper)) {       
         // If it's xray wrapped we can get the wn directly.
-        JSObject *holder = GetHolder(wrapper);
-        XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+        XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
         element = do_QueryWrappedNative(wn);
     } else {
         // Else we can use the XPC utility function for unwrapping it.
         nsCOMPtr<nsIXPConnectWrappedNative> iwn;  
         nsIXPConnect *xpc = nsXPConnect::GetXPConnect();
         nsresult rv = xpc->GetWrappedNativeOfJSObject(cx, wrapper, 
                                                       getter_AddRefs(iwn));
         if (NS_FAILED(rv) || !iwn) {
@@ -738,33 +724,31 @@ XPCWrappedNativeXrayTraits::resolveNativ
         desc->getter = NULL;
         desc->setter = NULL;
         desc->shortid = 0;
         return true;
     }
 
     desc->obj = NULL;
 
-    JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder);
-    XPCWrappedNative *wn = GetWrappedNative(wnObject);
-
     // This will do verification and the method lookup for us.
-    XPCCallContext ccx(JS_CALLER, cx, wnObject, nullptr, id);
+    XPCCallContext ccx(JS_CALLER, cx, getTargetObject(wrapper), nullptr, id);
 
     // There are no native numeric properties, so we can shortcut here. We will
     // not find the property. However we want to support non shadowing dom
     // specific collection properties like window.frames, so we still have to
     // check for those.
     if (!JSID_IS_STRING(id)) {
         /* Not found */
         return resolveDOMCollectionProperty(cx, wrapper, holder, id, set, desc);
     }
 
     XPCNativeInterface *iface;
     XPCNativeMember *member;
+    XPCWrappedNative *wn = getWN(wrapper);
     if (ccx.GetWrapper() != wn ||
         !wn->IsValid()  ||
         !(iface = ccx.GetInterface()) ||
         !(member = ccx.GetMember())) {
         /* Not found */
         return resolveDOMCollectionProperty(cx, wrapper, holder, id, set, desc);
     }
 
@@ -854,18 +838,17 @@ WrapURI(JSContext *cx, nsIURI *uri, jsva
 static JSBool
 documentURIObject_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSMutableHandleValue vp)
 {
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     nsCOMPtr<nsIDocument> native = do_QueryWrappedNative(wn);
     if (!native) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
     nsCOMPtr<nsIURI> uri = native->GetDocumentURI();
     if (!uri) {
@@ -879,18 +862,17 @@ documentURIObject_getter(JSContext *cx, 
 static JSBool
 baseURIObject_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSMutableHandleValue vp)
 {
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     nsCOMPtr<nsINode> native = do_QueryWrappedNative(wn);
     if (!native) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
     nsCOMPtr<nsIURI> uri = native->GetBaseURI();
     if (!uri) {
         JS_ReportOutOfMemory(cx);
@@ -903,18 +885,17 @@ baseURIObject_getter(JSContext *cx, JSHa
 static JSBool
 nodePrincipal_getter(JSContext *cx, JSHandleObject wrapper, JSHandleId id, JSMutableHandleValue vp)
 {
     if (!IsWrapper(wrapper) || !WrapperFactory::IsXrayWrapper(wrapper)) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+    XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
     nsCOMPtr<nsINode> node = do_QueryWrappedNative(wn);
     if (!node) {
         JS_ReportError(cx, "Unexpected object");
         return false;
     }
 
     JSObject *scope = JS_GetGlobalForScopeChain(cx);
     nsresult rv =
@@ -961,17 +942,17 @@ XPCWrappedNativeXrayTraits::resolveOwnPr
         desc->shortid = 0;
         desc->value = JSVAL_VOID;
         return true;
     }
 
     desc->obj = NULL;
 
     unsigned flags = (set ? JSRESOLVE_ASSIGNING : 0) | JSRESOLVE_QUALIFIED;
-    JSObject *target = GetWrappedNativeObjectFromHolder(holder);
+    JSObject *target = getTargetObject(wrapper);
     JSObject *expando = LookupExpandoObject(cx, target, wrapper);
 
     // Check for expando properties first. Note that the expando object lives
     // in the target compartment.
     if (expando) {
         JSAutoCompartment ac(cx, expando);
         if (!JS_GetPropertyDescriptorById(cx, expando, id, flags, desc))
             return false;
@@ -984,17 +965,17 @@ XPCWrappedNativeXrayTraits::resolveOwnPr
         return true;
     }
 
     JSBool hasProp;
     if (!JS_HasPropertyById(cx, holder, id, &hasProp)) {
         return false;
     }
     if (!hasProp) {
-        XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
+        XPCWrappedNative *wn = getWN(wrapper);
 
         // Run the resolve hook of the wrapped native.
         if (!NATIVE_HAS_FLAG(wn, WantNewResolve)) {
             return true;
         }
 
         bool retval = true;
         JSObject *pobj = NULL;
@@ -1029,17 +1010,17 @@ XPCWrappedNativeXrayTraits::defineProper
         }
 
         return JS_DefinePropertyById(cx, holder, id, desc->value, desc->getter, desc->setter,
                                      desc->attrs);
     }
 
     // We're placing an expando. The expando objects live in the target
     // compartment, so we need to enter it.
-    JSObject *target = GetWrappedNativeObjectFromHolder(holder);
+    JSObject *target = getTargetObject(wrapper);
     JSAutoCompartment ac(cx, target);
 
     // Grab the relevant expando object.
     JSObject *expandoObject = EnsureExpandoObject(cx, wrapper, target);
     if (!expandoObject)
         return false;
 
     // Wrap the property descriptor for the target compartment.
@@ -1050,18 +1031,17 @@ XPCWrappedNativeXrayTraits::defineProper
     return JS_DefinePropertyById(cx, expandoObject, id, wrappedDesc.value,
                                  wrappedDesc.getter, wrappedDesc.setter,
                                  wrappedDesc.attrs);
 }
 
 bool
 XPCWrappedNativeXrayTraits::delete_(JSContext *cx, JSObject *wrapper, jsid id, bool *bp)
 {
-    JSObject *holder = getHolderObject(wrapper);
-    JSObject *target = GetWrappedNativeObjectFromHolder(holder);
+    JSObject *target = getTargetObject(wrapper);
     JSObject *expando = LookupExpandoObject(cx, target, wrapper);
     JSBool b = true;
     if (expando) {
         JSAutoCompartment ac(cx, expando);
         jsval v;
         if (!JS_DeletePropertyById2(cx, expando, id, &v) ||
             !JS_ValueToBoolean(cx, v, &b))
         {
@@ -1072,37 +1052,33 @@ XPCWrappedNativeXrayTraits::delete_(JSCo
     *bp = !!b;
     return true;
 }
 
 bool
 XPCWrappedNativeXrayTraits::enumerateNames(JSContext *cx, JSObject *wrapper, unsigned flags,
                                            JS::AutoIdVector &props)
 {
-    JSObject *holder = getHolderObject(wrapper);
-
     // Enumerate expando properties first. Note that the expando object lives
     // in the target compartment.
-    JSObject *target = GetWrappedNativeObjectFromHolder(holder);
+    JSObject *target = getTargetObject(wrapper);
     JSObject *expando = LookupExpandoObject(cx, target, wrapper);
     if (expando) {
         JSAutoCompartment ac(cx, expando);
         if (!js::GetPropertyNames(cx, expando, flags, &props))
             return false;
     }
     if (!JS_WrapAutoIdVector(cx, props))
         return false;
 
     // Force all native properties to be materialized onto the wrapped native.
     JS::AutoIdVector wnProps(cx);
     {
-        JSObject *wnObject = GetWrappedNativeObjectFromHolder(holder);
-
-        JSAutoCompartment ac(cx, wnObject);
-        if (!js::GetPropertyNames(cx, wnObject, flags, &wnProps))
+        JSAutoCompartment ac(cx, target);
+        if (!js::GetPropertyNames(cx, target, flags, &wnProps))
             return false;
     }
 
     // Go through the properties we got and enumerate all native ones.
     for (size_t n = 0; n < wnProps.length(); ++n) {
         jsid id = wnProps[n];
         JSBool hasProp;
         if (!JS_HasPropertyById(cx, wrapper, id, &hasProp))
@@ -1112,20 +1088,18 @@ XPCWrappedNativeXrayTraits::enumerateNam
     }
     return true;
 }
 
 bool
 XPCWrappedNativeXrayTraits::call(JSContext *cx, JSObject *wrapper,
                                  unsigned argc, Value *vp)
 {
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
-
     // Run the resolve hook of the wrapped native.
+    XPCWrappedNative *wn = getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantCall)) {
         XPCCallContext ccx(JS_CALLER, cx, wrapper, nullptr, JSID_VOID, argc,
                            vp + 2, vp);
         if (!ccx.IsValid())
             return false;
         bool ok = true;
         nsresult rv = wn->GetScriptableInfo()->GetCallback()->Call(wn, cx, wrapper,
                                                                    argc, vp + 2, vp, &ok);
@@ -1139,20 +1113,18 @@ XPCWrappedNativeXrayTraits::call(JSConte
     return true;
 
 }
 
 bool
 XPCWrappedNativeXrayTraits::construct(JSContext *cx, JSObject *wrapper,
                                       unsigned argc, Value *argv, Value *rval)
 {
-    JSObject *holder = GetHolder(wrapper);
-    XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
-
     // Run the resolve hook of the wrapped native.
+    XPCWrappedNative *wn = getWN(wrapper);
     if (NATIVE_HAS_FLAG(wn, WantConstruct)) {
         XPCCallContext ccx(JS_CALLER, cx, wrapper, nullptr, JSID_VOID, argc, argv, rval);
         if (!ccx.IsValid())
             return false;
         bool ok = true;
         nsresult rv = wn->GetScriptableInfo()->GetCallback()->Construct(wn, cx, wrapper,
                                                                         argc, argv, rval, &ok);
         if (NS_FAILED(rv)) {
@@ -1389,21 +1361,18 @@ XrayToString(JSContext *cx, unsigned arg
             return false;
         }
         result.Append(chars, length);
     } else if (IsDOMClass(JS_GetClass(obj))) {
         result.AppendLiteral("[Object ");
         result.AppendASCII(JS_GetClass(obj)->name);
         result.Append(']');
     } else {
-        JSObject *holder = GetHolder(wrapper);
-        XPCWrappedNative *wn = GetWrappedNativeFromHolder(holder);
-        JSObject *wrappednative = wn->GetFlatJSObject();
-
-        XPCCallContext ccx(JS_CALLER, cx, wrappednative);
+        XPCCallContext ccx(JS_CALLER, cx, XrayTraits::getTargetObject(wrapper));
+        XPCWrappedNative *wn = XPCWrappedNativeXrayTraits::getWN(wrapper);
         char *wrapperStr = wn->ToString(ccx);
         if (!wrapperStr) {
             JS_ReportOutOfMemory(cx);
             return false;
         }
         result.AppendASCII(wrapperStr);
         JS_smprintf_free(wrapperStr);
     }