Fix for bug 744772 (Trace the DOM interface object array). r=bz, a=akeybl.
authorPeter Van der Beken <peterv@propagandism.org>
Wed, 02 May 2012 14:49:43 +0200
changeset 95698 7d702f45c71a1875dd3e87e583a7d848057211b5
parent 95697 62bc457629b60c9352cff17d4582f866f534a2d5
child 95699 b486a6c98abe24707bb80715cf5807c4908d2f74
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbz, akeybl
bugs744772
milestone14.0a2
Fix for bug 744772 (Trace the DOM interface object array). r=bz, a=akeybl.
dom/bindings/Utils.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/Utils.h
+++ b/dom/bindings/Utils.h
@@ -192,16 +192,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
@@ -840,16 +840,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::bindings::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::bindings::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
@@ -1186,16 +1186,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::bindings::TraceProtoOrIfaceCache(trc, obj);
 }
 
 #ifdef DEBUG
 #include "mozilla/Preferences.h"
 #include "nsIXULRuntime.h"
 static void
 CheckTypeInference(JSContext *cx, JSClass *clasp, nsIPrincipal *principal)
 {