Bug 1215502: Perform nsIException instance test for XPCOM exceptions r=automatedtester

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
This commit is contained in:
Andreas Tolfsen 2016-01-07 14:37:06 +00:00
parent 1af2e4cd98
commit 0f68d9cf37

View File

@ -4,7 +4,7 @@
"use strict";
var {results: Cr, utils: Cu} = Components;
var {interfaces: Ci, utils: Cu} = Components;
const errors = [
"ElementNotAccessibleError",
@ -31,32 +31,12 @@ const errors = [
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
@ -67,7 +47,7 @@ this.error = {};
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";