Bug 1215502: Perform nsIException instance test for XPCOM exceptions draft
authorAndreas Tolfsen <ato@mozilla.com>
Thu, 07 Jan 2016 14:37:06 +0000
changeset 319660 51b5babdda942653a00c51468fa81d3ccf6b646b
parent 319654 e0bcd16e1d4b99ba3e542149d0d41e0f60c54b5c
child 319661 59fc6efc6ba20369a06489a49801dfa851c8acb2
push id9071
push useratolfsen@mozilla.com
push dateThu, 07 Jan 2016 14:45:05 +0000
bugs1215502, 1202576
milestone46.0a1
Bug 1215502: Perform nsIException instance test for XPCOM exceptions The current test of the `result' property does not always pass for all types of XPCOM exceptions. A safer test is to do an instance check against Components.interfaces.nsIException. This fixes hangs such as the one described in bug 1202576. r=dburns
testing/marionette/error.js
--- a/testing/marionette/error.js
+++ b/testing/marionette/error.js
@@ -1,15 +1,15 @@
 /* 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/. */
 
 "use strict";
 
-var {results: Cr, utils: Cu} = Components;
+var {interfaces: Ci, utils: Cu} = Components;
 
 const errors = [
   "ElementNotAccessibleError",
   "ElementNotVisibleError",
   "InvalidArgumentError",
   "InvalidElementStateError",
   "InvalidSelectorError",
   "InvalidSessionIdError",
@@ -26,53 +26,33 @@ const errors = [
   "UnknownCommandError",
   "UnknownError",
   "UnsupportedOperationError",
   "WebDriverError",
 ];
 
 this.EXPORTED_SYMBOLS = ["error"].concat(errors);
 
-// Because XPCOM is a cesspool of undocumented odd behaviour,
-// Object.getPrototypeOf(err) causes another exception if err is an XPCOM
-// exception, and cannot be used to determine if err is a prototypal Error.
-//
-// Consequently we need to check for properties in its prototypal chain
-// (using in, instead of err.hasOwnProperty because that causes other
-// issues).
-//
-// Since the input is arbitrary it might _not_ be an Error, and can as
-// such be an object with a "result" property without it being considered to
-// be an exception.  The solution is to build a lookup table of XPCOM
-// exceptions from Components.results and check if the value of err#results
-// is in that table.
-const XPCOM_EXCEPTIONS = [];
-{
-  for (let prop in Cr) {
-    XPCOM_EXCEPTIONS.push(Cr[prop]);
-  }
-}
-
 this.error = {};
 
 /**
  * Checks if obj is an instance of the Error prototype in a safe manner.
  * Prefer using this over using instanceof since the Error prototype
- * isn't unique across browsers, and XPCOM exceptions are special
+ * isn't unique across browsers, and XPCOM nsIException's are special
  * snowflakes.
  *
  * @param {*} val
  *     Any value that should be undergo the test for errorness.
  * @return {boolean}
  *     True if error, false otherwise.
  */
 error.isError = function(val) {
   if (val === null || typeof val != "object") {
     return false;
-  } else if ("result" in val && val.result in XPCOM_EXCEPTIONS) {
+  } else if (val instanceof Ci.nsIException) {
     return true;
   } else {
     return Object.getPrototypeOf(val) == "Error";
   }
 };
 
 /**
  * Checks if obj is an object in the WebDriverError prototypal chain.