Fix for bug 744772 (Trace the DOM interface object array). r=bz.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 02 May 2012 14:49:43 +0200
changeset 92998 17b552b979d5b07867a9f8a961bf7efcf3186032
parent 92997 94b06a04f17b0da37597cf3e19fa81683e0f08f0
child 92999 efa51cd286eeb15e6de5f03d07bfa726993e8cfe
push id22606
push useremorley@mozilla.com
push dateFri, 04 May 2012 08:42:45 +0000
treeherdermozilla-central@e1a40027dc7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz
bugs744772
milestone15.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
Fix for bug 744772 (Trace the DOM interface object array). r=bz.
dom/bindings/BindingUtils.h
dom/bindings/test/Makefile.in
dom/bindings/test/test_traceProtos.html
dom/workers/WorkerScope.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -198,16 +198,30 @@ AllocateProtoOrIfaceCache(JSObject* obj)
   // Important: The () at the end ensure zero-initialization
   JSObject** protoOrIfaceArray = new JSObject*[kProtoOrIfaceCacheCount]();
 
   js::SetReservedSlot(obj, DOM_PROTOTYPE_SLOT,
                       JS::PrivateValue(protoOrIfaceArray));
 }
 
 inline void
+TraceProtoOrIfaceCache(JSTracer* trc, JSObject* obj)
+{
+  MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
+
+  JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(obj);
+  for (size_t i = 0; i < kProtoOrIfaceCacheCount; ++i) {
+    JSObject* proto = protoOrIfaceArray[i];
+    if (proto) {
+      JS_CALL_OBJECT_TRACER(trc, proto, "protoOrIfaceArray[i]");
+    }
+  }
+}
+
+inline void
 DestroyProtoOrIfaceCache(JSObject* obj)
 {
   MOZ_ASSERT(js::GetObjectClass(obj)->flags & JSCLASS_DOM_GLOBAL);
 
   JSObject** protoOrIfaceArray = GetProtoOrIfaceArray(obj);
 
   delete [] protoOrIfaceArray;
 }
--- a/dom/bindings/test/Makefile.in
+++ b/dom/bindings/test/Makefile.in
@@ -9,12 +9,13 @@ VPATH = @srcdir@
 relativesrcdir = dom/bindings/test
 
 include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _TEST_FILES = \
   test_lookupGetter.html \
   test_InstanceOf.html \
+  test_traceProtos.html \
   $(NULL)
 
 libs:: $(_TEST_FILES)
 	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/bindings/test/test_traceProtos.html
@@ -0,0 +1,37 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=744772
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 744772</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=744772">Mozilla Bug 744772</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  
+</div>
+<pre id="test">
+<script type="application/javascript">
+
+/** Test for Bug 744772 **/
+
+SimpleTest.waitForExplicitFinish();
+
+function callback() {
+  new XMLHttpRequest().upload;
+  ok(true, "Accessing unreferenced DOM interface objects shouldn't crash");
+  SimpleTest.finish();
+}
+
+delete window.XMLHttpRequestUpload;
+SpecialPowers.exactGC(window, callback);
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/workers/WorkerScope.cpp
+++ b/dom/workers/WorkerScope.cpp
@@ -839,16 +839,17 @@ private:
 
   static void
   Trace(JSTracer* aTrc, JSObject* aObj)
   {
     JS_ASSERT(JS_GetClass(aObj) == Class());
     DedicatedWorkerGlobalScope* scope =
       UnwrapDOMObject<DedicatedWorkerGlobalScope>(aObj, Class());
     if (scope) {
+      mozilla::dom::TraceProtoOrIfaceCache(aTrc, aObj);
       scope->_Trace(aTrc);
     }
   }
 
   static JSBool
   PostMessage(JSContext* aCx, unsigned aArgc, jsval* aVp)
   {
     JSObject* obj = JS_THIS_OBJECT(aCx, aVp);
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -690,16 +690,21 @@ TraceForValidWrapper(JSTracer *trc, XPCW
     wrapper->TraceJS(trc);
 
     TraceScopeJSObjects(trc, wrapper->GetScope());
 }
 
 static void
 MarkWrappedNative(JSTracer *trc, JSObject *obj)
 {
+    js::Class* clazz = js::GetObjectClass(obj);
+    if (clazz->flags & JSCLASS_DOM_GLOBAL) {
+        mozilla::dom::TraceProtoOrIfaceCache(trc, obj);
+    }
+
     JSObject *obj2;
 
     // Pass null for the first JSContext* parameter  to skip any security
     // checks and to avoid potential state change there.
     XPCWrappedNative* wrapper =
         XPCWrappedNative::GetWrappedNativeOfJSObject(nsnull, obj, nsnull, &obj2);
 
     if (wrapper) {
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1077,16 +1077,18 @@ TraceXPCGlobal(JSTracer *trc, JSObject *
         // was called.
         reinterpret_cast<VerifyTraceXPCGlobalCalledTracer*>(trc)->ok = true;
         return;
     }
 #endif
 
     if (XPCWrappedNativeScope *scope = XPCWrappedNativeScope::GetNativeScope(obj))
         scope->TraceDOMPrototypes(trc);
+
+    mozilla::dom::TraceProtoOrIfaceCache(trc, obj);
 }
 
 #ifdef DEBUG
 #include "mozilla/Preferences.h"
 #include "nsIXULRuntime.h"
 static void
 CheckTypeInference(JSContext *cx, JSClass *clasp, nsIPrincipal *principal)
 {