Bug 787070 - Expandos on the xray of DOM prototypes should have effect on xrays of DOM nodes, make GetNativePropertyHooks detect global objects. r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 22 Aug 2014 11:25:35 +0200
changeset 207605 adfe4ac95437
parent 207604 8c47153a1dd1
child 207606 6e8655117616
push id49735
push userpvanderbeken@mozilla.com
push dateMon, 29 Sep 2014 07:58:28 +0000
treeherdermozilla-inbound@090b62fdfd21 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs787070
milestone35.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 787070 - Expandos on the xray of DOM prototypes should have effect on xrays of DOM nodes, make GetNativePropertyHooks detect global objects. r=bz.
dom/bindings/BindingUtils.cpp
dom/bindings/BindingUtils.h
--- a/dom/bindings/BindingUtils.cpp
+++ b/dom/bindings/BindingUtils.cpp
@@ -906,19 +906,22 @@ ThrowingConstructor(JSContext* cx, unsig
 bool
 ThrowConstructorWithoutNew(JSContext* cx, const char* name)
 {
   return ThrowErrorMessage(cx, MSG_CONSTRUCTOR_WITHOUT_NEW, name);
 }
 
 inline const NativePropertyHooks*
 GetNativePropertyHooks(JSContext *cx, JS::Handle<JSObject*> obj,
-                       DOMObjectType& type)
+                       DOMObjectType& type, bool& isGlobal)
 {
-  const DOMJSClass* domClass = GetDOMClass(obj);
+  const js::Class* clasp = js::GetObjectClass(obj);
+  isGlobal = (clasp->flags & JSCLASS_DOM_GLOBAL) != 0;
+
+  const DOMJSClass* domClass = GetDOMClass(clasp);
   if (domClass) {
     type = eInstance;
     return domClass->mNativeHooks;
   }
 
   if (JS_ObjectIsFunction(cx, obj)) {
     MOZ_ASSERT(JS_IsNativeFunction(obj, Constructor));
     type = eInterface;
@@ -959,18 +962,19 @@ bool
 XrayResolveOwnProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
                        JS::Handle<JSObject*> obj, JS::Handle<jsid> id,
                        JS::MutableHandle<JSPropertyDescriptor> desc,
                        bool& cacheOnHolder)
 {
   cacheOnHolder = false;
 
   DOMObjectType type;
+  bool isGlobal;
   const NativePropertyHooks *nativePropertyHooks =
-    GetNativePropertyHooks(cx, obj, type);
+    GetNativePropertyHooks(cx, obj, type, isGlobal);
 
   if (type != eInstance) {
     // For prototype objects and interface objects, just return their
     // normal set of properties.
     return XrayResolveNativeProperty(cx, wrapper, nativePropertyHooks, type,
                                      obj, id, desc, cacheOnHolder);
   }
 
@@ -1314,18 +1318,19 @@ bool
 XrayResolveNativeProperty(JSContext* cx, JS::Handle<JSObject*> wrapper,
                           JS::Handle<JSObject*> obj,
                           JS::Handle<jsid> id, JS::MutableHandle<JSPropertyDescriptor> desc,
                           bool& cacheOnHolder)
 {
   cacheOnHolder = false;
 
   DOMObjectType type;
+  bool isGlobal;
   const NativePropertyHooks* nativePropertyHooks =
-    GetNativePropertyHooks(cx, obj, type);
+    GetNativePropertyHooks(cx, obj, type, isGlobal);
 
   if (type == eInstance) {
     // Force the type to be eInterfacePrototype, since we need to walk the
     // prototype chain.
     type = eInterfacePrototype;
   }
 
   if (type == eInterfacePrototype) {
@@ -1395,17 +1400,17 @@ XrayEnumerateAttributesOrMethods(JSConte
   }                                                                           \
 }
 
 
 bool
 XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
                         JS::Handle<JSObject*> obj,
                         unsigned flags, JS::AutoIdVector& props,
-                        DOMObjectType type,
+                        DOMObjectType type, bool isGlobal,
                         const NativeProperties* nativeProperties)
 {
   if (type == eInstance) {
     ENUMERATE_IF_DEFINED(unforgeableMethod);
     ENUMERATE_IF_DEFINED(unforgeableAttribute);
   } else if (type == eInterface) {
     ENUMERATE_IF_DEFINED(staticMethod);
     ENUMERATE_IF_DEFINED(staticAttribute);
@@ -1434,18 +1439,19 @@ XrayEnumerateProperties(JSContext* cx, J
   return true;
 }
 
 #undef ENUMERATE_IF_DEFINED
 
 bool
 XrayEnumerateNativeProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
                               const NativePropertyHooks* nativePropertyHooks,
-                              DOMObjectType type, JS::Handle<JSObject*> obj,
-                              unsigned flags, JS::AutoIdVector& props)
+                              DOMObjectType type, bool isGlobal,
+                              JS::Handle<JSObject*> obj, unsigned flags,
+                              JS::AutoIdVector& props)
 {
   if (type == eInterface &&
       nativePropertyHooks->mPrototypeID != prototypes::id::_ID_Count &&
       !AddStringToIDVector(cx, props, "prototype")) {
     return false;
   }
 
   if (type == eInterfacePrototype &&
@@ -1454,79 +1460,80 @@ XrayEnumerateNativeProperties(JSContext*
       !AddStringToIDVector(cx, props, "constructor")) {
     return false;
   }
 
   const NativePropertiesHolder& nativeProperties =
     nativePropertyHooks->mNativeProperties;
 
   if (nativeProperties.regular &&
-      !XrayEnumerateProperties(cx, wrapper, obj, flags, props, type,
+      !XrayEnumerateProperties(cx, wrapper, obj, flags, props, type, isGlobal,
                                nativeProperties.regular)) {
     return false;
   }
 
   if (nativeProperties.chromeOnly &&
       xpc::AccessCheck::isChrome(js::GetObjectCompartment(wrapper)) &&
-      !XrayEnumerateProperties(cx, wrapper, obj, flags, props, type,
+      !XrayEnumerateProperties(cx, wrapper, obj, flags, props, type, isGlobal,
                                nativeProperties.chromeOnly)) {
     return false;
   }
 
   return true;
 }
 
 bool
 XrayEnumerateProperties(JSContext* cx, JS::Handle<JSObject*> wrapper,
                         JS::Handle<JSObject*> obj,
                         unsigned flags, JS::AutoIdVector& props)
 {
   DOMObjectType type;
+  bool isGlobal;
   const NativePropertyHooks* nativePropertyHooks =
-    GetNativePropertyHooks(cx, obj, type);
+    GetNativePropertyHooks(cx, obj, type, isGlobal);
 
   if (type == eInstance) {
     if (nativePropertyHooks->mEnumerateOwnProperties &&
         !nativePropertyHooks->mEnumerateOwnProperties(cx, wrapper, obj,
                                                       props)) {
       return false;
     }
 
     // Handle Unforgeable properties.
     if (!XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
-                                       obj, flags, props)) {
+                                       isGlobal, obj, flags, props)) {
       return false;
     }
 
     if (flags & JSITER_OWNONLY) {
       return true;
     }
 
     // Force the type to be eInterfacePrototype, since we need to walk the
     // prototype chain.
     type = eInterfacePrototype;
   }
 
   if (type == eInterfacePrototype) {
     do {
       if (!XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
-                                         obj, flags, props)) {
+                                         isGlobal, obj, flags, props)) {
         return false;
       }
 
       if (flags & JSITER_OWNONLY) {
         return true;
       }
     } while ((nativePropertyHooks = nativePropertyHooks->mProtoHooks));
 
     return true;
   }
 
   return XrayEnumerateNativeProperties(cx, wrapper, nativePropertyHooks, type,
-                                       obj, flags, props);
+                                       isGlobal, obj, flags, props);
 }
 
 NativePropertyHooks sWorkerNativePropertyHooks = {
   nullptr,
   nullptr,
   {
     nullptr,
     nullptr
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -176,23 +176,25 @@ UnwrapDOMObject(JSObject* obj)
   MOZ_ASSERT(IsDOMClass(js::GetObjectClass(obj)),
              "Don't pass non-DOM objects to this function");
 
   JS::Value val = js::GetReservedSlot(obj, DOM_OBJECT_SLOT);
   return static_cast<T*>(val.toPrivate());
 }
 
 inline const DOMJSClass*
+GetDOMClass(const js::Class* clasp)
+{
+  return IsDOMClass(clasp) ? DOMJSClass::FromJSClass(clasp) : nullptr;
+}
+
+inline const DOMJSClass*
 GetDOMClass(JSObject* obj)
 {
-  const js::Class* clasp = js::GetObjectClass(obj);
-  if (IsDOMClass(clasp)) {
-    return DOMJSClass::FromJSClass(clasp);
-  }
-  return nullptr;
+  return GetDOMClass(js::GetObjectClass(obj));
 }
 
 inline nsISupports*
 UnwrapDOMObjectToISupports(JSObject* aObject)
 {
   const DOMJSClass* clasp = GetDOMClass(aObject);
   if (!clasp || !clasp->mDOMObjectIsISupports) {
     return nullptr;