Bug 641378 - Don't try to treat an nsXPCWrappedJS as the interface we asked for. r=peterv
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 08 Apr 2011 14:28:24 -0700
changeset 67694 a089731c47d5cee62c33c6423befeaf7f14a921c
parent 67693 a91752ea97cf305921e5d791e2bc8d66cbcb1c06
child 67695 652bd0eed005369e444005e6a75944a174056f91
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs641378
milestone2.2a1pre
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 641378 - Don't try to treat an nsXPCWrappedJS as the interface we asked for. r=peterv
js/src/xpconnect/src/xpcconvert.cpp
js/src/xpconnect/tests/unit/test_bug641378.js
--- a/js/src/xpconnect/src/xpcconvert.cpp
+++ b/js/src/xpconnect/src/xpcconvert.cpp
@@ -1635,31 +1635,34 @@ XPCConvert::JSValToXPCException(XPCCallC
                                              methodName, report, exceptn);
             }
 
 
             uintN ignored;
             JSBool found;
 
             // heuristic to see if it might be usable as an xpcexception
-            if(JS_GetPropertyAttributes(cx, obj, "message", &ignored, &found) &&
-               found &&
-               JS_GetPropertyAttributes(cx, obj, "result", &ignored, &found) &&
-               found)
+            if(!JS_GetPropertyAttributes(cx, obj, "message", &ignored, &found))
+               return NS_ERROR_FAILURE;
+
+            if(found && !JS_GetPropertyAttributes(cx, obj, "result", &ignored, &found))
+                return NS_ERROR_FAILURE;
+
+            if(found)
             {
                 // lets try to build a wrapper around the JSObject
                 nsXPCWrappedJS* jswrapper;
                 nsresult rv =
                     nsXPCWrappedJS::GetNewOrUsed(ccx, obj,
                                                  NS_GET_IID(nsIException),
                                                  nsnull, &jswrapper);
                 if(NS_FAILED(rv))
                     return rv;
-                *exceptn = reinterpret_cast<nsIException*>
-                           (jswrapper);
+
+                *exceptn = static_cast<nsIException *>(jswrapper->GetXPTCStub());
                 return NS_OK;
             }
 
 
             // XXX we should do a check against 'js_ErrorClass' here and
             // do the right thing - even though it has no JSErrorReport,
             // The fact that it is a JSError exceptions means we can extract
             // particular info and our 'result' should reflect that.
new file mode 100644
--- /dev/null
+++ b/js/src/xpconnect/tests/unit/test_bug641378.js
@@ -0,0 +1,46 @@
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+var timer;
+
+// This test XPConnect's ability to deal with a certain type of exception. In
+// particular, bug 641378 meant that if an exception had both 'message' and
+// 'result' properties, then it wouldn't successfully read the 'result' field
+// out of the exception (and sometimes crash).
+//
+// In order to make the test not fail completely on a negative result, we use
+// a timer. The first time through the timer, we throw our special exception.
+// Then, the second time through, we can test to see if XPConnect properly
+// dealt with our exception.
+var exception = {
+  message: "oops, something failed!",
+
+  tries: 0,
+  get result() {
+    ++this.tries;
+    return 3;
+  }
+};
+
+var callback = {
+  tries: 0,
+  notify: function (timer) {
+    if (++this.tries === 1)
+      throw exception;
+
+    try {
+        do_check_true(exception.tries >= 1);
+    } finally {
+        timer.cancel();
+        timer = null;
+        do_test_finished();
+    }
+  }
+};
+
+function run_test() {
+  do_test_pending();
+
+  timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+  timer.initWithCallback(callback, 0, timer.TYPE_REPEATING_SLACK);
+}