Bug 610381 part B - Report thread-usage errors to the error console directly from xpconnect, so that the error console shows them even when extension authors are using asynchronous dispatch. r=jst a=blocking2.0
authorBenjamin Smedberg <benjamin@smedbergs.us>
Wed, 17 Nov 2010 15:58:53 -0500
changeset 57667 a86f1ab3f3dba57e18c5f09b39b60f4321100103
parent 57666 3862e43372ba848dc57e0d1702100ae06d0d672b
child 57838 78a42f77bb90c49b066023e740fc05f7c863ab37
push id17031
push userbsmedberg@mozilla.com
push dateWed, 17 Nov 2010 21:02:34 +0000
treeherdermozilla-central@a86f1ab3f3db [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjst, blocking2.0
bugs610381
milestone2.0b8pre
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 610381 part B - Report thread-usage errors to the error console directly from xpconnect, so that the error console shows them even when extension authors are using asynchronous dispatch. r=jst a=blocking2.0
js/src/xpconnect/src/xpcwrappedjs.cpp
js/src/xpconnect/tests/unit/test_bug608142.js
--- a/js/src/xpconnect/src/xpcwrappedjs.cpp
+++ b/js/src/xpconnect/src/xpcwrappedjs.cpp
@@ -39,16 +39,17 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /* Class that wraps JS objects to appear as XPCOM objects. */
 
 #include "xpcprivate.h"
 #include "nsAtomicRefcnt.h"
 #include "nsThreadUtils.h"
+#include "nsTextFormatter.h"
 
 // NOTE: much of the fancy footwork is done in xpcstubs.cpp
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsXPCWrappedJS)
 
 NS_IMETHODIMP
 NS_CYCLE_COLLECTION_CLASSNAME(nsXPCWrappedJS)::Traverse
    (void *p, nsCycleCollectionTraversalCallback &cb)
@@ -567,16 +568,27 @@ nsXPCWrappedJS::GetInterfaceInfo(nsIInte
 NS_IMETHODIMP
 nsXPCWrappedJS::CallMethod(PRUint16 methodIndex,
                            const XPTMethodDescriptor* info,
                            nsXPTCMiniVariant* params)
 {
     if(!IsValid())
         return NS_ERROR_UNEXPECTED;
     if (NS_IsMainThread() != mMainThread) {
+        NS_NAMED_LITERAL_STRING(kFmt, "Attempt to use JS function on a different thread calling %s.%s. JS objects may not be shared across threads.");
+        PRUnichar* msg =
+            nsTextFormatter::smprintf(kFmt.get(),
+                                      GetClass()->GetInterfaceName(),
+                                      info->name);
+        nsCOMPtr<nsIConsoleService> cs =
+            do_GetService(NS_CONSOLESERVICE_CONTRACTID);
+        if (cs)
+            cs->LogStringMessage(msg);
+        NS_Free(msg);
+        
         return NS_ERROR_NOT_SAME_THREAD;
     }
     return GetClass()->CallMethod(this, methodIndex, info, params);
 }
 
 NS_IMETHODIMP
 nsXPCWrappedJS::GetInterfaceIID(nsIID** iid)
 {
--- a/js/src/xpconnect/tests/unit/test_bug608142.js
+++ b/js/src/xpconnect/tests/unit/test_bug608142.js
@@ -35,17 +35,33 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 function run_test() { 
     var tm = Components.classes["@mozilla.org/thread-manager;1"].getService();
     var thr = tm.newThread(0);
 
+    var foundThreadError = false;
+ 
+    var listener = {
+        observe: function(message) {
+            if (/JS function on a different thread/.test(message.message))
+                foundThreadError = true;
+        }
+    };
+
+    var cs = Components.classes["@mozilla.org/consoleservice;1"].
+        getService(Components.interfaces.nsIConsoleService);
+    cs.registerListener(listener);
+
     thr.dispatch({
         run: function() {
             do_check_true(false);
         }
     }, Components.interfaces.nsIThread.DISPATCH_NORMAL);
 
     thr.shutdown();
+
+    cs.unregisterListener(listener);
+    do_check_true(foundThreadError);
 }