Fix up places that use PRIVATE_IS_NSISUPPORTS to handle the new bindings correctly, with the exception of XBL field installation
authorBoris Zbarsky <bzbarsky@mit.edu>
Tue, 24 Jan 2012 18:50:18 +0100
changeset 85105 0d2f76e245068b35f75fdf28e3cfbc6fc0087905
parent 85104 3d401cbe2520cbf9f9d908a9dce26809f3239eec
child 85106 00402e911111ee567264625cf0b95876e0d69754
push id15
push userbzbarsky@mozilla.com
push dateTue, 24 Jan 2012 17:50:58 +0000
milestone12.0a1
Fix up places that use PRIVATE_IS_NSISUPPORTS to handle the new bindings correctly, with the exception of XBL field installation
caps/src/nsScriptSecurityManager.cpp
dom/base/nsJSEnvironment.cpp
dom/base/nsJSUtils.cpp
dom/bindings/BindingGen.py
dom/bindings/DOMJSClass.h
dom/bindings/GlobalGen.py
dom/bindings/Makefile.in
dom/bindings/Utils.h
js/src/jsapi.cpp
js/src/jsclass.h
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCWrappedNativeScope.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/wrappers/AccessCheck.cpp
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -89,18 +89,20 @@
 #include "nsAboutProtocolUtils.h"
 #include "nsIClassInfo.h"
 #include "nsIURIFixup.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsIChromeRegistry.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "mozilla/Preferences.h"
+#include "mozilla/dom/bindings/Utils.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 static NS_DEFINE_CID(kZipReaderCID, NS_ZIPREADER_CID);
 
 nsIIOService    *nsScriptSecurityManager::sIOService = nsnull;
 nsIXPConnect    *nsScriptSecurityManager::sXPConnect = nsnull;
 nsIThreadJSContextStack *nsScriptSecurityManager::sJSContextStack = nsnull;
 nsIStringBundle *nsScriptSecurityManager::sStrBundle = nsnull;
 JSRuntime       *nsScriptSecurityManager::sRuntime   = 0;
@@ -2438,19 +2440,27 @@ nsScriptSecurityManager::doGetObjectPrin
                                               aAllowShortCircuit
 #else
                                               true
 #endif
                                               );
             if (result) {
                 break;
             }
-        } else if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
-                                        JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
-            nsISupports *priv = (nsISupports *) js::GetObjectPrivate(aObj);
+        } else {
+            nsISupports *priv;
+            if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
+                                     JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
+                priv = (nsISupports *) js::GetObjectPrivate(aObj);
+            } else if ((jsClass->flags & JSCLASS_IS_DOMJSCLASS) &&
+                       bindings::DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
+                priv = bindings::UnwrapDOMObject<nsISupports>(aObj);
+            } else {
+                priv = nsnull;
+            }
 
 #ifdef DEBUG
             if (aAllowShortCircuit) {
                 nsCOMPtr<nsIXPConnectWrappedNative> xpcWrapper =
                     do_QueryInterface(priv);
 
                 NS_ASSERTION(!xpcWrapper ||
                              !strcmp(jsClass->name, "XPCNativeWrapper"),
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -105,19 +105,22 @@
 #endif
 #include "prlog.h"
 #include "prthread.h"
 
 #include "mozilla/FunctionTimer.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Telemetry.h"
 
+#include "mozilla/dom/bindings/Utils.h"
+
 #include "sampler.h"
 
 using namespace mozilla;
+using namespace mozilla::dom;
 
 const size_t gStackSize = 8192;
 
 #ifdef PR_LOGGING
 static PRLogModuleInfo* gJSDiagnostics;
 #endif
 
 // Thank you Microsoft!
@@ -2179,23 +2182,31 @@ nsJSContext::GetGlobalObject()
     // If this assertion hits then it means that we have a window object as
     // our global, but we never called CreateOuterObject.
     NS_ASSERTION(inner == global, "Shouldn't be able to innerize here");
   }
 #endif
 
   JSClass *c = JS_GET_CLASS(mContext, global);
 
-  if (!c || ((~c->flags) & (JSCLASS_HAS_PRIVATE |
-                            JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
+  nsISupports *priv;
+  if (c) {
+    if (((~c->flags) & (JSCLASS_HAS_PRIVATE |
+                        JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
+      priv = (nsISupports *)js::GetObjectPrivate(global);
+    } else if ((c->flags & JSCLASS_IS_DOMJSCLASS) &&
+               bindings::DOMJSClass::FromJSClass(c)->mDOMObjectIsISupports) {
+      priv = bindings::UnwrapDOMObject<nsISupports>(global);
+    } else {
+      return nsnull;
+    }
+  } else {
     return nsnull;
   }
 
-  nsISupports *priv = (nsISupports *)js::GetObjectPrivate(global);
-
   nsCOMPtr<nsIXPConnectWrappedNative> wrapped_native =
     do_QueryInterface(priv);
 
   nsCOMPtr<nsIScriptGlobalObject> sgo;
   if (wrapped_native) {
     // The global object is a XPConnect wrapped native, the native in
     // the wrapper might be the nsIScriptGlobalObject
 
--- a/dom/base/nsJSUtils.cpp
+++ b/dom/base/nsJSUtils.cpp
@@ -56,16 +56,20 @@
 #include "nsIXPConnect.h"
 #include "nsCOMPtr.h"
 #include "nsContentUtils.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsPIDOMWindow.h"
 
 #include "nsDOMJSUtils.h" // for GetScriptContextFromJSContext
 
+#include "mozilla/dom/bindings/Utils.h"
+
+using namespace mozilla::dom;
+
 JSBool
 nsJSUtils::GetCallingLocation(JSContext* aContext, const char* *aFilename,
                               PRUint32* aLineno)
 {
   // Get the current filename and line number
   JSStackFrame* frame = nsnull;
   JSScript* script = nsnull;
   do {
@@ -94,32 +98,39 @@ nsJSUtils::GetCallingLocation(JSContext*
   }
 
   return JS_FALSE;
 }
 
 nsIScriptGlobalObject *
 nsJSUtils::GetStaticScriptGlobal(JSContext* aContext, JSObject* aObj)
 {
-  nsISupports* supports;
   JSClass* clazz;
   JSObject* glob = aObj; // starting point for search
 
   if (!glob)
     return nsnull;
 
   glob = JS_GetGlobalForObject(aContext, glob);
   NS_ABORT_IF_FALSE(glob, "Infallible returns null");
 
   clazz = JS_GET_CLASS(aContext, glob);
 
-  if (!clazz ||
-      !(clazz->flags & JSCLASS_HAS_PRIVATE) ||
-      !(clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) ||
-      !(supports = (nsISupports*)::JS_GetPrivate(aContext, glob))) {
+  nsISupports* supports = nsnull;
+  if (clazz) {
+    if ((clazz->flags & JSCLASS_HAS_PRIVATE) &&
+        (clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
+      supports = (nsISupports*)::JS_GetPrivate(aContext, glob);
+    } else if ((clazz->flags & JSCLASS_IS_DOMJSCLASS) &&
+               bindings::DOMJSClass::FromJSClass(clazz)->mDOMObjectIsISupports) {
+      supports = bindings::UnwrapDOMObject<nsISupports>(glob);
+    }
+  }
+
+  if (!supports) {
     return nsnull;
   }
 
   // We might either have a window directly (e.g. if the global is a
   // sandbox whose script object principal pointer is a window), or an
   // XPCWrappedNative for a window.  We could also have other
   // sandbox-related script object principals, but we can't do much
   // about those short of trying to walk the proto chain of |glob|
--- a/dom/bindings/BindingGen.py
+++ b/dom/bindings/BindingGen.py
@@ -67,17 +67,17 @@ namespace %s {
 
 DOMJSClass Class = {
   { "%s",
     JSCLASS_IS_DOMJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(1),
     JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JS_StrictPropertyStub,
     JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, JS_FinalizeStub,
     NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
   },
-    {%s}, -1
+    {%s}, -1, %s
 };
 
 bool
 Install(JSContext* aCx, JSObject* aGlobal)
 {
   return false;
 }
 
@@ -93,17 +93,22 @@ Install(JSContext* aCx, JSObject* aGloba
 """
 
     # Write from templates.
     f.write(prologue)
     for protoInfo in protoStructure:
         protoName = protoInfo[0]
         canonicalName = protoInfo[1]
         interfaceChain = ['id::' + iface for iface in protoInfo[2]]
-        f.write(chunk % (protoName, canonicalName, ', '.join(interfaceChain), protoName))
+        if (protoInfo[3]):
+            hasISupportsNative = "true"
+        else:
+            hasISupportsNative = "false"
+        f.write(chunk % (protoName, canonicalName, ', '.join(interfaceChain),
+                         hasISupportsNative, protoName))
     f.write(epilogue)
     f.close()
 
 def main():
 
     # Parse arguments.
     from optparse import OptionParser
     usagestring = "usage: %prog outputprefix webidlfile"
@@ -116,14 +121,14 @@ def main():
     outputprefix = args[0]
     webidlfile = args[1]
 
     # Parse the WebIDL.
     # XXXbholley - Actually call the parser here.
 
     # Generate the prototype classes.
     protoClassList = ['XMLHttpRequest']
-    protoClassStructure = [('XMLHttpRequest', 'XMLHttpRequest', ['EventTarget', 'XMLHttpRequestEventTarget', 'XMLHttpRequest'])]
+    protoClassStructure = [('XMLHttpRequest', 'XMLHttpRequest', ['EventTarget', 'XMLHttpRequestEventTarget', 'XMLHttpRequest'], True)]
     generate_binding_header(protoClassList, outputprefix);
     generate_binding_cpp(protoClassStructure, outputprefix);
 
 if __name__ == '__main__':
     main()
--- a/dom/bindings/DOMJSClass.h
+++ b/dom/bindings/DOMJSClass.h
@@ -1,42 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef BindingClass_h
-#define BindingClass_h
+#ifndef mozilla_dom_bindings_DOMJSClass_h
+#define mozilla_dom_bindings_DOMJSClass_h
 
 #include "jsapi.h"
+#include "jsfriendapi.h"
 
 #include "PrototypeList.h" // auto-generated
 
+#define DOM_OBJECT_SLOT 0
+
 namespace mozilla {
 namespace dom {
 namespace bindings {
 
 /*
  * Special JSClass for reflected DOM objects.
  */
 struct DOMJSClass
 {
   // It would be nice to just inherit from JSClass, but that precludes pure
   // compile-time initialization of the form |DOMJSClass = {...};|, since C++
   // only allows brace initialization for aggregate/POD types.
   JSClass mBase;
 
   // A list of interfaces that this object implements, in order of decreasing
   // derivedness.
-  prototypes::ID  mInterfaceChain[prototypes::id::Count];
+  const prototypes::ID  mInterfaceChain[prototypes::id::Count];
 
   // We cache the VTable index of GetWrapperCache for objects that support it.
   //
   // -1 indicates that GetWrapperCache is not implemented on the underlying object.
-  int16_t         mGetWrapperCacheVTableOffset;
+  const int16_t         mGetWrapperCacheVTableOffset;
+
+  // We store the DOM object in reserved slot DOM_OBJECT_SLOT.
+  // Sometimes it's an nsISupports and sometimes it's not; this class tells
+  // us which it is.
+  const bool            mDOMObjectIsISupports;
+
+  static DOMJSClass* FromJSClass(JSClass *base) {
+    MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
+    return reinterpret_cast<DOMJSClass*>(base);
+  }
+  static const DOMJSClass* FromJSClass(const JSClass *base) {
+    MOZ_ASSERT(base->flags & JSCLASS_IS_DOMJSCLASS);
+    return reinterpret_cast<const DOMJSClass*>(base);
+  }
+
+  static DOMJSClass* FromJSClass(js::Class *base) {
+    return FromJSClass(Jsvalify(base));
+  }
+  static const DOMJSClass* FromJSClass(const js::Class *base) {
+    return FromJSClass(Jsvalify(base));
+  }
 
   operator JSClass&() { return mBase;};
 };
 
 } // namespace bindings
 } // namespace dom
 } // namespace mozilla
 
-#endif /* BindingClass_h */
+#endif /* mozilla_dom_bindings_DOMJSClass_h */
--- a/dom/bindings/GlobalGen.py
+++ b/dom/bindings/GlobalGen.py
@@ -9,18 +9,18 @@ import os
 
 def generate_prototype_list(protoList, filename):
     print "Generating prototype list: %s" % (filename)
     f = open(filename, 'w')
 
     prologue = """
 /* THIS FILE IS AUTOGENERATED - DO NOT EDIT */
 
-#ifndef PrototypeList_h
-#define PrototypeList_h
+#ifndef mozilla_dom_bindings_PrototypeList_h
+#define mozilla_dom_bindings_PrototypeList_h
 
 namespace mozilla {
 namespace dom {
 namespace bindings {
 namespace prototypes {
 namespace id {
 
 enum ID
@@ -33,17 +33,17 @@ enum ID
 
 typedef id::ID ID;
 
 } // namespace prototypes
 } // namespace bindings
 } // namespace dom
 } // namespace mozilla
 
-#endif // PrototypeList_h
+#endif // mozilla_dom_bindings_PrototypeList_h
 """
 
     f.write(prologue)
 
     # Append the enum count.
     protoList.append('Count')
 
     # Add appropriate indentation before the prototype strings.
--- a/dom/bindings/Makefile.in
+++ b/dom/bindings/Makefile.in
@@ -26,16 +26,24 @@ BINDING_CPP_FILES = $(subst .webidl,Bind
 CPPSRCS = \
   $(BINDING_CPP_FILES) \
   $(NULL)
 
 GLOBAL_PHASE_TARGETS = \
   PrototypeList.h \
   $(NULL)
 
+EXPORTS_NAMESPACES = mozilla/dom/bindings
+
+EXPORTS_mozilla/dom/bindings = \
+  DOMJSClass.h \
+  PrototypeList.h \
+  Utils.h \
+  $(NULL)
+
 include $(topsrcdir)/config/rules.mk
 
 # XXXbholley - the per-webidl deps here are broken - we need to fix them.
 $(BINDING_CPP_FILES): %Binding.cpp: BindingGen.py \
                       $(GLOBAL_PHASE_TARGETS)$ \
                       $(WEBIDL_BASE)/$(filter $*.webidl,$(WEBIDL_PATHS))
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py \
 	$(srcdir)/BindingGen.py $*Binding $(filter %$*.webidl,$(WEBIDL_PATHS))
new file mode 100644
--- /dev/null
+++ b/dom/bindings/Utils.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_bindings_Utils_h__
+#define mozilla_dom_bindings_Utils_h__
+
+#include "jsapi.h"
+#include "DOMJSClass.h"
+
+namespace mozilla {
+namespace dom {
+namespace bindings {
+
+inline bool
+IsDOMClass(JSClass *clasp)
+{
+  return clasp->flags & JSCLASS_IS_DOMJSCLASS;
+}
+
+template<class T>
+inline T*
+UnwrapDOMObject(JSObject *obj)
+{
+  MOZ_ASSERT(IsDOMClass(js::GetObjectJSClass(obj)));
+  return reinterpret_cast<T*>(js::GetReservedSlot(obj,
+						  DOM_OBJECT_SLOT).toPrivate());
+}
+
+
+} // namespace bindings
+} // namespace dom
+} // namespace mozilla
+
+#endif /* mozilla_dom_bindings_Utils_h__ */
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2461,16 +2461,18 @@ JS_PrintTraceThingInfo(char *buf, size_t
             void *privateThing = obj->getPrivate();
             if (privateThing) {
                 const char *xpcClassName = GetXPCObjectClassName(privateThing);
                 if (xpcClassName)
                     name = xpcClassName;
             }
         }
 #endif
+        // XXXbz what, if anything, should we do with
+        // JSCLASS_IS_DOMJSCLASS objects here?
         break;
       }
 
       case JSTRACE_STRING:
         name = ((JSString *)thing)->isDependent()
                ? "substring"
                : "string";
         break;
--- a/js/src/jsclass.h
+++ b/js/src/jsclass.h
@@ -381,22 +381,32 @@ JS_STATIC_ASSERT(offsetof(JSClass, hasIn
 JS_STATIC_ASSERT(offsetof(JSClass, trace) == offsetof(Class, trace));
 JS_STATIC_ASSERT(sizeof(JSClass) == sizeof(Class));
 
 static JS_ALWAYS_INLINE JSClass *
 Jsvalify(Class *c)
 {
     return (JSClass *)c;
 }
+static JS_ALWAYS_INLINE const JSClass *
+Jsvalify(const Class *c)
+{
+    return (const JSClass *)c;
+}
 
 static JS_ALWAYS_INLINE Class *
 Valueify(JSClass *c)
 {
     return (Class *)c;
 }
+static JS_ALWAYS_INLINE const Class *
+Valueify(const JSClass *c)
+{
+    return (const Class *)c;
+}
 
 /*
  * Enumeration describing possible values of the [[Class]] internal property
  * value of objects.
  */
 enum ESClassValue { ESClass_Array, ESClass_Number, ESClass_String, ESClass_Boolean };
 
 /*
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -57,17 +57,20 @@
 
 #include "dombindings.h"
 #include "nsWrapperCacheInlines.h"
 
 #include "jsapi.h"
 #include "jsfriendapi.h"
 #include "jstypedarray.h"
 
+#include "mozilla/dom/bindings/Utils.h"
+
 using namespace mozilla;
+using namespace mozilla::dom;
 
 //#define STRICT_CHECK_OF_UNICODE
 #ifdef STRICT_CHECK_OF_UNICODE
 #define ILLEGAL_RANGE(c) (0!=((c) & 0xFF80))
 #else // STRICT_CHECK_OF_UNICODE
 #define ILLEGAL_RANGE(c) (0!=((c) & 0xFF00))
 #endif // STRICT_CHECK_OF_UNICODE
 
@@ -105,16 +108,21 @@ XPCConvert::GetISupportsFromJSObject(JSO
     JSClass* jsclass = js::GetObjectJSClass(obj);
     NS_ASSERTION(jsclass, "obj has no class");
     if (jsclass &&
         (jsclass->flags & JSCLASS_HAS_PRIVATE) &&
         (jsclass->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS)) {
         *iface = (nsISupports*) xpc_GetJSPrivate(obj);
         return true;
     }
+    if (jsclass && (jsclass->flags & JSCLASS_IS_DOMJSCLASS) &&
+        bindings::DOMJSClass::FromJSClass(jsclass)->mDOMObjectIsISupports) {
+        *iface = bindings::UnwrapDOMObject<nsISupports>(obj);
+        return true;
+    }
     return false;
 }
 
 /***************************************************************************/
 
 static void
 FinalizeXPCOMUCString(JSContext *cx, JSString *str)
 {
--- a/js/xpconnect/src/XPCWrappedNativeScope.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeScope.cpp
@@ -39,16 +39,20 @@
  * ***** END LICENSE BLOCK ***** */
 
 /* Class used to manage the wrapped native objects within a JS scope. */
 
 #include "xpcprivate.h"
 #include "XPCWrapper.h"
 #include "jsproxy.h"
 
+#include "mozilla/dom/bindings/Utils.h"
+
+using namespace mozilla::dom;
+
 /***************************************************************************/
 
 #ifdef XPC_TRACK_SCOPE_STATS
 static int DEBUG_TotalScopeCount;
 static int DEBUG_TotalLiveScopeCount;
 static int DEBUG_TotalMaxScopeCount;
 static int DEBUG_TotalScopeTraversalCount;
 static bool    DEBUG_DumpedStats;
@@ -233,21 +237,29 @@ XPCWrappedNativeScope::SetGlobal(XPCCall
     // We allow for calling this more than once. This feature is used by
     // nsXPConnect::InitClassesWithNewWrappedGlobal.
 
     mGlobalJSObject = aGlobal;
     mScriptObjectPrincipal = nsnull;
     // Now init our script object principal, if the new global has one
 
     const JSClass* jsClass = js::GetObjectJSClass(aGlobal);
-    if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
-                             JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
-        // Our global has an nsISupports native pointer.  Let's
-        // see whether it's what we want.
-        nsISupports* priv = (nsISupports*)xpc_GetJSPrivate(aGlobal);
+    {
+        nsISupports* priv;
+        if (!(~jsClass->flags & (JSCLASS_HAS_PRIVATE |
+                                 JSCLASS_PRIVATE_IS_NSISUPPORTS))) {
+            // Our global has an nsISupports native pointer.  Let's
+            // see whether it's what we want.
+            priv = (nsISupports*)xpc_GetJSPrivate(aGlobal);
+        } else if ((jsClass->flags & JSCLASS_IS_DOMJSCLASS) &&
+                   bindings::DOMJSClass::FromJSClass(jsClass)->mDOMObjectIsISupports) {
+            priv = bindings::UnwrapDOMObject<nsISupports>(aGlobal);
+        } else {
+            priv = nsnull;
+        }
         nsCOMPtr<nsIXPConnectWrappedNative> native =
             do_QueryInterface(priv);
         nsCOMPtr<nsIScriptObjectPrincipal> sop;
         if (native) {
             sop = do_QueryWrappedNative(native);
         }
         if (!sop) {
             sop = do_QueryInterface(priv);
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -63,18 +63,22 @@
 
 #include "XPCQuickStubs.h"
 #include "dombindings.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/Base64.h"
 #include "mozilla/Util.h"
 
+#include "mozilla/dom/bindings/Utils.h"
+
 #include "nsWrapperCacheInlines.h"
 
+using namespace mozilla::dom;
+
 NS_IMPL_THREADSAFE_ISUPPORTS7(nsXPConnect,
                               nsIXPConnect,
                               nsISupportsWeakReference,
                               nsIThreadObserver,
                               nsIJSRuntimeService,
                               nsIJSContextStack,
                               nsIThreadJSContextStack,
                               nsIJSEngineTelemetryStats)
@@ -965,21 +969,26 @@ nsXPConnect::Traverse(void *p, nsCycleCo
         cb.NoteXPCOMChild(to->GetNative());
     }
     // XXX This test does seem fragile, we should probably whitelist classes
     //     that do hold a strong reference, but that might not be possible.
     else if (clazz->flags & JSCLASS_HAS_PRIVATE &&
              clazz->flags & JSCLASS_PRIVATE_IS_NSISUPPORTS) {
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "xpc_GetJSPrivate(obj)");
         cb.NoteXPCOMChild(static_cast<nsISupports*>(xpc_GetJSPrivate(obj)));
-    } else if (mozilla::dom::binding::instanceIsProxy(obj)) {
+    } else if (binding::instanceIsProxy(obj)) {
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "js::GetProxyPrivate(obj)");
         nsISupports *identity =
             static_cast<nsISupports*>(js::GetProxyPrivate(obj).toPrivate());
         cb.NoteXPCOMChild(identity);
+    } else if ((clazz->flags & JSCLASS_IS_DOMJSCLASS) &&
+               bindings::DOMJSClass::FromJSClass(clazz)->mDOMObjectIsISupports) {
+        NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "UnwrapDOMObject(obj)");
+        nsISupports *identity = bindings::UnwrapDOMObject<nsISupports>(obj);
+        cb.NoteXPCOMChild(identity);
     }
 
     return NS_OK;
 }
 
 unsigned
 nsXPConnect::GetOutstandingRequests(JSContext* cx)
 {
--- a/js/xpconnect/wrappers/AccessCheck.cpp
+++ b/js/xpconnect/wrappers/AccessCheck.cpp
@@ -217,16 +217,20 @@ IsLocation(const char *name)
 {
     return name[0] == 'L' && !strcmp(name, "Location");
 }
 
 static nsIPrincipal *
 GetPrincipal(JSObject *obj)
 {
     NS_ASSERTION(!IS_SLIM_WRAPPER(obj), "global object is a slim wrapper?");
+    NS_ASSERTION(js::GetObjectClass(obj)->flags & JSCLASS_IS_GLOBAL,
+                 "Not a global object?");
+    NS_ASSERTION(!js::GetObjectClass(obj)->flags & JSCLASS_IS_DOMJSCLASS,
+                 "Not sure what we should do with these yet!");
     if (!IS_WN_WRAPPER(obj)) {
         NS_ASSERTION(!(~js::GetObjectClass(obj)->flags &
                        (JSCLASS_PRIVATE_IS_NSISUPPORTS | JSCLASS_HAS_PRIVATE)),
                      "bad object");
         nsCOMPtr<nsIScriptObjectPrincipal> objPrin =
             do_QueryInterface((nsISupports*)xpc_GetJSPrivate(obj));
         NS_ASSERTION(objPrin, "global isn't nsIScriptObjectPrincipal?");
         return objPrin->GetPrincipal();