Backed out 2 changesets (bug 1259822, bug 1488417) for web compat issues. a=backout
authorJulien Cristau <jcristau@mozilla.com>
Thu, 06 Dec 2018 14:57:31 -0500
changeset 501462 290d09651022
parent 501461 021689730ee5
child 501463 e5f98886a12a
push id1873
push userjcristau@mozilla.com
push dateThu, 06 Dec 2018 20:13:42 +0000
treeherdermozilla-release@e5f98886a12a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbackout
bugs1259822, 1488417
milestone64.0
backs out0413c9c3d902
35c61888a49d
Backed out 2 changesets (bug 1259822, bug 1488417) for web compat issues. a=backout Backed out changeset 0413c9c3d902 (bug 1488417) Backed out changeset 35c61888a49d (bug 1259822)
dom/browser-element/mochitest/browserElement_ExecuteScript.js
dom/u2f/tests/frame_appid_facet_insecure.html
js/src/jit-test/tests/basic/bug827104.js
js/src/jit-test/tests/basic/expression-autopsy.js
js/src/jit-test/tests/basic/iterable-error-messages.js
js/src/jit-test/tests/basic/testBug604210.js
js/src/jit-test/tests/debug/bug1275001.js
js/src/jit-test/tests/ion/bug913749.js
js/src/jit/BaselineIC.cpp
js/src/js.msg
js/src/jsapi-tests/testErrorInterceptor.cpp
js/src/tests/non262/extensions/regress-353116.js
js/src/tests/non262/regress/regress-469625-03.js
js/src/tests/non262/regress/regress-469758.js
js/src/vm/Interpreter-inl.h
js/src/vm/Interpreter.cpp
js/src/vm/JSContext.cpp
js/src/vm/JSContext.h
js/src/vm/JSObject.cpp
js/src/vm/JSObject.h
toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
--- a/dom/browser-element/mochitest/browserElement_ExecuteScript.js
+++ b/dom/browser-element/mochitest/browserElement_ExecuteScript.js
@@ -86,17 +86,17 @@ function runTest() {
       `, {url});
     }).then(bail, (error) => {
       is(error.message, 'Value returned (resolve) by promise is not a valid JSON object', `scriptId: ${scriptId++}`);
       return iframe.executeScript('window.btoa("a")', {url})
     }, bail).then(rv => {
       ok(c(rv, 'YQ=='), `scriptId: ${scriptId++}`);
       return iframe.executeScript('window.wrappedJSObject.btoa("a")', {url})
     }, bail).then(bail, (error) => {
-      is(error.message, `TypeError: window.wrappedJSObject is undefined; can't access its "btoa" property`, `scriptId: ${scriptId++}`);
+      is(error.message, 'TypeError: window.wrappedJSObject is undefined', `scriptId: ${scriptId++}`);
       return iframe.executeScript('42', {})
     }).then(bail, error => {
       is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
       return iframe.executeScript('42');
     }).then(bail, error => {
       is(error.name, 'InvalidAccessError', `scriptId: ${scriptId++}`);
       return iframe.executeScript('43', { url: 'http://foo.com' });
     }).then(bail, (error) => {
--- a/dom/u2f/tests/frame_appid_facet_insecure.html
+++ b/dom/u2f/tests/frame_appid_facet_insecure.html
@@ -28,17 +28,17 @@ async function doTests() {
     local_ok(err == "ReferenceError: u2f is not defined", "calling u2f should have thrown from an insecure origin");
   }
 
   try {
     window.u2f.register(null, [], [], function(res) {
       local_ok(false, "Callbacks should not be called.");
     });
   } catch (err) {
-    local_ok(err.toString().includes("TypeError: window.u2f is undefined"), "accessing window.u2f should have thrown from an insecure origin");
+    local_ok(err == "TypeError: window.u2f is undefined", "accessing window.u2f should have thrown from an insecure origin");
   }
 
   try {
     await promiseU2FRegister(null, [{
       version: version,
       challenge: bytesToBase64UrlSafe(challenge),
     }], [], function(res){
       local_ok(false, "Shouldn't have gotten here on an insecure origin");
--- a/js/src/jit-test/tests/basic/bug827104.js
+++ b/js/src/jit-test/tests/basic/bug827104.js
@@ -5,9 +5,9 @@ function f() {
     }
     a[i][0] = 0;
 }
 
 var e;
 try {
     f();
 } catch (error) {e = error;}
-assertEq(e.toString(), `TypeError: a[i] is undefined; can't access element at index 0`);
+assertEq(e.toString(), 'TypeError: a[i] is undefined');
\ No newline at end of file
--- a/js/src/jit-test/tests/basic/expression-autopsy.js
+++ b/js/src/jit-test/tests/basic/expression-autopsy.js
@@ -13,17 +13,17 @@ function check_one(expected, f, err) {
         assertEq(s.slice(11, -err.length), expected);
     }
     if (!failed)
         throw new Error("didn't fail");
 }
 ieval = eval;
 function check(expr, expected=expr, testStrict=true) {
     var end, err;
-    for ([end, err] of [[".random_prop", ` is undefined; can't access its "random_prop" property`], ["()", " is not a function"]]) {
+    for ([end, err] of [[".random_prop", " is undefined"], ["()", " is not a function"]]) {
         var statement = "o = {};" + expr + end, f;
         var cases = [
             // Global scope
             function () {
                 ieval("var o, undef;\n" + statement);
             },
             // Function scope
             Function("o", "undef", statement),
@@ -97,17 +97,17 @@ check("o[(~(o + 1))]");
 check("o[(+ (o + 1))]");
 check("o[(- (o + 1))]");
 
 // A few one off tests
 check_one("6", (function () { 6() }), " is not a function");
 check_one("4", (function() { (4||eval)(); }), " is not a function");
 check_one("0", (function () { Array.prototype.reverse.call('123'); }), " is read-only");
 check_one("[...][Symbol.iterator](...).next(...).value",
-          function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined; can't access its Symbol.iterator property");
+          function () { ieval("{ let x; var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined");
 check_one("(void 1)", function() { (void 1)(); }, " is not a function");
 check_one("(void o[1])", function() { var o = []; (void o[1])() }, " is not a function");
 
 check_one("(typeof 1)", function() { (typeof 1)(); }, " is not a function");
 check_one("(typeof o[1])", function() { var o = []; (typeof o[1])() }, " is not a function");
 
 check_one("(delete foo)",
           function() { (delete foo)(); },
--- a/js/src/jit-test/tests/basic/iterable-error-messages.js
+++ b/js/src/jit-test/tests/basic/iterable-error-messages.js
@@ -10,30 +10,30 @@ function assertThrowsMsg(f, msg) {
 
 // For-of
 function testForOf(val) {
     for (var x of val) {}
 }
 for (v of [{}, Math, new Proxy({}, {})]) {
     assertThrowsMsg(() => testForOf(v), "val is not iterable");
 }
-assertThrowsMsg(() => testForOf(null), "val is null; can't access its Symbol.iterator property");
+assertThrowsMsg(() => testForOf(null), "val is null");
 assertThrowsMsg(() => { for (var x of () => 1) {}}, "() => 1 is not iterable");
 
 // Destructuring
 function testDestr(val) {
     var [a, b] = val;
 }
 for (v of [{}, Math, new Proxy({}, {})]) {
     assertThrowsMsg(() => testDestr(v), "val is not iterable");
 }
-assertThrowsMsg(() => testDestr(null), "val is null; can't access its Symbol.iterator property");
+assertThrowsMsg(() => testDestr(null), "val is null");
 assertThrowsMsg(() => { [a, b] = () => 1; }, "() => 1 is not iterable");
 
 // Spread
 function testSpread(val) {
     [...val];
 }
 for (v of [{}, Math, new Proxy({}, {})]) {
     assertThrowsMsg(() => testSpread(v), "val is not iterable");
 }
-assertThrowsMsg(() => testSpread(null), "val is null; can't access its Symbol.iterator property");
+assertThrowsMsg(() => testSpread(null), "val is null");
 assertThrowsMsg(() => { [...() => 1]; }, "() => 1 is not iterable");
--- a/js/src/jit-test/tests/basic/testBug604210.js
+++ b/js/src/jit-test/tests/basic/testBug604210.js
@@ -1,11 +1,11 @@
 function f() {
     var msg = '';
     try {
         var x = undefined;
         print(x.foo);
     } catch (e) {
         msg = '' + e;
     }
-    assertEq(msg, `TypeError: x is undefined; can't access its "foo" property`);
+    assertEq(msg, "TypeError: x is undefined");
 }
 f();
--- a/js/src/jit-test/tests/debug/bug1275001.js
+++ b/js/src/jit-test/tests/debug/bug1275001.js
@@ -12,19 +12,19 @@ function check_one(expected, f, err) {
     } catch (ex) {
         s = ex.toString()
         assertEq(s.slice(11, -err.length), expected)
     }
 }
 ieval = eval
 function check(expr, expected = expr) {
     var end, err
-    for ([end, err] of [[".random_prop", ` is undefined, can't access its "random_prop" property`]])
+    for ([end, err] of[[".random_prop", " is undefined" ]]) 
          statement = "o = {};" + expr + end;
          cases = [
             function() { return ieval("var undef;" + statement); },
             Function(statement)
         ]
-        for (f of cases)
+        for (f of cases) 
             check_one(expected, f, err)
 }
 check("undef");
 check("o.b");
--- a/js/src/jit-test/tests/ion/bug913749.js
+++ b/js/src/jit-test/tests/ion/bug913749.js
@@ -10,12 +10,12 @@ this.toSource();
 
 y = undefined;
 
 for (var i = 0; i < 3; i++) {
     try {
 	x.toString();
 	assertEq(0, 1);
     } catch (e) {
-	assertEq(e.message === `y is undefined; can't access its "length" property` ||
+	assertEq(e.message === "y is undefined" ||
 		 e.message === `can't access property "length" of undefined`, true);
     }
 }
--- a/js/src/jit/BaselineIC.cpp
+++ b/js/src/jit/BaselineIC.cpp
@@ -1948,17 +1948,17 @@ DoSetElemFallback(JSContext* cx, Baselin
 
     MOZ_ASSERT(op == JSOP_SETELEM ||
                op == JSOP_STRICTSETELEM ||
                op == JSOP_INITELEM ||
                op == JSOP_INITHIDDENELEM ||
                op == JSOP_INITELEM_ARRAY ||
                op == JSOP_INITELEM_INC);
 
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, objv, index));
+    RootedObject obj(cx, ToObjectFromStack(cx, objv));
     if (!obj) {
         return false;
     }
 
     RootedShape oldShape(cx, obj->maybeShape());
     RootedObjectGroup oldGroup(cx, JSObject::getGroup(cx, obj));
     if (!oldGroup) {
         return false;
@@ -2783,17 +2783,17 @@ DoSetPropFallback(JSContext* cx, Baselin
     RootedPropertyName name(cx);
     if (op == JSOP_SETALIASEDVAR || op == JSOP_INITALIASEDLEXICAL) {
         name = EnvironmentCoordinateName(cx->caches().envCoordinateNameCache, script, pc);
     } else {
         name = script->getName(pc);
     }
     RootedId id(cx, NameToId(name));
 
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, lhs, id));
+    RootedObject obj(cx, ToObjectFromStack(cx, lhs));
     if (!obj) {
         return false;
     }
     RootedShape oldShape(cx, obj->maybeShape());
     RootedObjectGroup oldGroup(cx, JSObject::getGroup(cx, obj));
     if (!oldGroup) {
         return false;
     }
--- a/js/src/js.msg
+++ b/js/src/js.msg
@@ -4,32 +4,31 @@
  * 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/. */
 
 /*
  * This is the JavaScript error message file.
  *
  * The format for each JS error message is:
  *
- *     MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
- *             <FORMAT_STRING>)
+ * MSG_DEF(<SYMBOLIC_NAME>, <ARGUMENT_COUNT>, <EXCEPTION_NAME>,
+ *         <FORMAT_STRING>)
  *
- * where:
- *
- *     <SYMBOLIC_NAME> is a legal C identifer that will be used in the
- *     JS engine source.
+ * where ;
+ * <SYMBOLIC_NAME> is a legal C identifer that will be used in the
+ * JS engine source.
  *
- *     <ARGUMENT_COUNT> is an integer literal specifying the total number of
- *     replaceable arguments in the following format string.
+ * <ARGUMENT_COUNT> is an integer literal specifying the total number of
+ * replaceable arguments in the following format string.
  *
- *     <EXCEPTION_NAME> is an enum JSExnType value, defined in jsapi.h.
+ * <EXCEPTION_NAME> is an enum JSExnType value, defined in jsapi.h.
  *
- *     <FORMAT_STRING> is a string literal, optionally containing sequences
- *     {X} where X  is an integer representing the argument number that will
- *     be replaced with a string value when the error is reported.
+ * <FORMAT_STRING> is a string literal, optionally containing sequences
+ * {X} where X  is an integer representing the argument number that will
+ * be replaced with a string value when the error is reported.
  *
  * e.g.
  *
  * MSG_DEF(JSMSG_NOT_A_SUBSPECIES, 2, JSEXN_TYPEERROR,
  *         "{0} is not a member of the {1} family")
  *
  * can be used:
  *
@@ -50,19 +49,16 @@ MSG_DEF(JSMSG_READ_ONLY,               1
 MSG_DEF(JSMSG_CANT_DELETE,             1, JSEXN_TYPEERR, "property {0} is non-configurable and can't be deleted")
 MSG_DEF(JSMSG_CANT_TRUNCATE_ARRAY,     0, JSEXN_TYPEERR, "can't delete non-configurable array element")
 MSG_DEF(JSMSG_NOT_FUNCTION,            1, JSEXN_TYPEERR, "{0} is not a function")
 MSG_DEF(JSMSG_NOT_CONSTRUCTOR,         1, JSEXN_TYPEERR, "{0} is not a constructor")
 MSG_DEF(JSMSG_CANT_CONVERT_TO,         2, JSEXN_TYPEERR, "can't convert {0} to {1}")
 MSG_DEF(JSMSG_TOPRIMITIVE_NOT_CALLABLE, 2, JSEXN_TYPEERR, "can't convert {0} to {1}: its [Symbol.toPrimitive] property is not a function")
 MSG_DEF(JSMSG_TOPRIMITIVE_RETURNED_OBJECT, 2, JSEXN_TYPEERR, "can't convert {0} to {1}: its [Symbol.toPrimitive] method returned an object")
 MSG_DEF(JSMSG_NO_PROPERTIES,           1, JSEXN_TYPEERR, "{0} has no properties")
-MSG_DEF(JSMSG_PROPERTY_FAIL,           2, JSEXN_TYPEERR, "can't access property {0} of {1}")
-MSG_DEF(JSMSG_PROPERTY_FAIL_EXPR,      3, JSEXN_TYPEERR, "{0} is {1}; can't access its {2} property")
-MSG_DEF(JSMSG_ELEMENT_FAIL_EXPR,       3, JSEXN_TYPEERR, "{0} is {1}; can't access element at index {2}")
 MSG_DEF(JSMSG_BAD_REGEXP_FLAG,         1, JSEXN_SYNTAXERR, "invalid regular expression flag {0}")
 MSG_DEF(JSMSG_INVALID_DATA_VIEW_LENGTH, 0, JSEXN_RANGEERR, "invalid data view length")
 MSG_DEF(JSMSG_OFFSET_LARGER_THAN_FILESIZE, 0, JSEXN_RANGEERR, "offset is larger than filesize")
 MSG_DEF(JSMSG_OFFSET_OUT_OF_BUFFER,    0, JSEXN_RANGEERR, "start offset is outside the bounds of the buffer")
 MSG_DEF(JSMSG_OFFSET_OUT_OF_DATAVIEW,  0, JSEXN_RANGEERR, "offset is outside the bounds of the DataView")
 MSG_DEF(JSMSG_SPREAD_TOO_LARGE,        0, JSEXN_RANGEERR, "array too large due to spread operand(s)")
 MSG_DEF(JSMSG_BAD_WEAKMAP_KEY,         0, JSEXN_TYPEERR, "cannot use the given object as a weak map key")
 MSG_DEF(JSMSG_BAD_GETTER_OR_SETTER,    1, JSEXN_TYPEERR, "invalid {0} usage")
--- a/js/src/jsapi-tests/testErrorInterceptor.cpp
+++ b/js/src/jsapi-tests/testErrorInterceptor.cpp
@@ -32,35 +32,35 @@ bool equalStrings(JSContext* cx, JSStrin
     return result == 0;
 }
 }
 
 BEGIN_TEST(testErrorInterceptor)
 {
     // Run the following snippets.
     const char* SAMPLES[] = {
-        "throw new Error('I am an Error')",
-        "throw new TypeError('I am a TypeError')",
-        "throw new ReferenceError('I am a ReferenceError')",
-        "throw new SyntaxError('I am a SyntaxError')",
-        "throw 5",
-        "undefined[0]",
-        "foo[0]",
-        "b[",
+        "throw new Error('I am an Error')\0",
+        "throw new TypeError('I am a TypeError')\0",
+        "throw new ReferenceError('I am a ReferenceError')\0",
+        "throw new SyntaxError('I am a SyntaxError')\0",
+        "throw 5\0",
+        "undefined[0]\0",
+        "foo[0]\0",
+        "b[\0",
     };
     // With the simpleInterceptor, we should end up with the following error:
     const char* TO_STRING[] = {
-        "Error: I am an Error",
-        "TypeError: I am a TypeError",
-        "ReferenceError: I am a ReferenceError",
-        "SyntaxError: I am a SyntaxError",
-        "5",
-        "TypeError: can't access property 0 of undefined",
-        "ReferenceError: foo is not defined",
-        "SyntaxError: expected expression, got end of script",
+        "Error: I am an Error\0",
+        "TypeError: I am a TypeError\0",
+        "ReferenceError: I am a ReferenceError\0",
+        "SyntaxError: I am a SyntaxError\0",
+        "5\0",
+        "TypeError: undefined has no properties\0",
+        "ReferenceError: foo is not defined\0",
+        "SyntaxError: expected expression, got end of script\0",
     };
     MOZ_ASSERT(mozilla::ArrayLength(SAMPLES) == mozilla::ArrayLength(TO_STRING));
 
 
     // Save original callback.
     JSErrorInterceptor* original = JS_GetErrorInterceptorCallback(cx->runtime());
     gLatestMessage.init(cx);
 
--- a/js/src/tests/non262/extensions/regress-353116.js
+++ b/js/src/tests/non262/extensions/regress-353116.js
@@ -14,57 +14,57 @@ var expect = '';
 test();
 //-----------------------------------------------------------------------------
 
 function test()
 {
   printBugNumber(BUGNUMBER);
   printStatus (summary);
 
-  expect = `TypeError: can't access property "y" of undefined`;
+  expect = 'TypeError: undefined has no properties';
   actual = 'No Error';
 
   try
   {
     undefined.y;
   }
   catch(ex)
   {
     actual = ex + '';
   }
   reportCompare(expect, actual, summary);
 
-  expect = `TypeError: can't access property "y" of null`;
+  expect = 'TypeError: null has no properties';
   actual = 'No Error';
 
   try
   {
     null.y;
   }
   catch(ex)
   {
     actual = ex + '';
   }
   reportCompare(expect, actual, summary);
 
-  expect = `TypeError: x is undefined; can't access its "y" property`;
+  expect = 'TypeError: x is undefined';
   actual = 'No Error';
 
   try
   {
     x = undefined; 
     x.y;
   }
   catch(ex)
   {
     actual = ex + '';
   }
   reportCompare(expect, actual, summary);
 
-  expect = `TypeError: x is null; can't access its "y" property`;
+  expect = 'TypeError: x is null';
   actual = 'No Error';
 
   try
   {
     x = null; 
     x.y;
   }
   catch(ex)
--- a/js/src/tests/non262/regress/regress-469625-03.js
+++ b/js/src/tests/non262/regress/regress-469625-03.js
@@ -20,17 +20,17 @@ function test()
 {
   printBugNumber(BUGNUMBER);
   printStatus (summary);
  
   function f(x) {
     var [a, b, [c0, c1]] = [x, x, x];
   }
 
-  expect = `TypeError: [...][Symbol.iterator](...).next(...).value is null; can't access its Symbol.iterator property`;
+  expect = `TypeError: [...][Symbol.iterator](...).next(...).value is null`;
   actual = 'No Error';
   try
   {
     f(null);
   }
   catch(ex)
   {
     actual = ex + '';
--- a/js/src/tests/non262/regress/regress-469758.js
+++ b/js/src/tests/non262/regress/regress-469758.js
@@ -4,11 +4,11 @@
 var err;
 try {
     {let i=1}
     {let j=1; [][j][2]}
 } catch (e) {
     err = e;
 }
 assertEq(err instanceof TypeError, true);
-assertEq(err.message, "[][j] is undefined; can't access element at index 2");
+assertEq(err.message, "[][j] is undefined");
 
 reportCompare(0, 0, 'ok');
--- a/js/src/vm/Interpreter-inl.h
+++ b/js/src/vm/Interpreter-inl.h
@@ -564,17 +564,17 @@ GetObjectElementOperation(JSContext* cx,
 
 static MOZ_ALWAYS_INLINE bool
 GetPrimitiveElementOperation(JSContext* cx, JSOp op, JS::HandleValue receiver,
                              HandleValue key, MutableHandleValue res)
 {
     MOZ_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
     // FIXME: Bug 1234324 We shouldn't be boxing here.
-    RootedObject boxed(cx, ToObjectFromStackForPropertyAccess(cx, receiver, key));
+    RootedObject boxed(cx, ToObjectFromStack(cx, receiver));
     if (!boxed) {
         return false;
     }
 
     do {
         uint32_t index;
         if (IsDefinitelyIndex(key, &index)) {
             if (GetElementNoGC(cx, boxed, receiver, index, res.address())) {
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -263,17 +263,17 @@ GetImportOperation(JSContext* cx, Interp
     return FetchName<GetNameMode::Normal>(cx, env, pobj, name, prop, vp);
 }
 
 static bool
 SetPropertyOperation(JSContext* cx, JSOp op, HandleValue lval, HandleId id, HandleValue rval)
 {
     MOZ_ASSERT(op == JSOP_SETPROP || op == JSOP_STRICTSETPROP);
 
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, lval, id));
+    RootedObject obj(cx, ToObjectFromStack(cx, lval));
     if (!obj) {
         return false;
     }
 
     ObjectOpResult result;
     return SetProperty(cx, obj, id, rval, lval, result) &&
            result.checkStrictErrorOrWarning(cx, obj, id, op == JSOP_STRICTSETPROP);
 }
@@ -1624,20 +1624,20 @@ HandleError(JSContext* cx, InterpreterRe
 #define PUSH_SYMBOL(s)           REGS.sp++->setSymbol(s)
 #define PUSH_STRING(s)           do { REGS.sp++->setString(s); cx->debugOnlyCheck(REGS.sp[-1]); } while (0)
 #define PUSH_OBJECT(obj)         do { REGS.sp++->setObject(obj); cx->debugOnlyCheck(REGS.sp[-1]); } while (0)
 #define PUSH_OBJECT_OR_NULL(obj) do { REGS.sp++->setObjectOrNull(obj); cx->debugOnlyCheck(REGS.sp[-1]); } while (0)
 #define PUSH_MAGIC(magic)        REGS.sp++->setMagic(magic)
 #define POP_COPY_TO(v)           (v) = *--REGS.sp
 #define POP_RETURN_VALUE()       REGS.fp()->setReturnValue(*--REGS.sp)
 
-#define FETCH_OBJECT(cx, n, obj, key)                                         \
+#define FETCH_OBJECT(cx, n, obj)                                              \
     JS_BEGIN_MACRO                                                            \
         HandleValue val = REGS.stackHandleAt(n);                              \
-        obj = ToObjectFromStackForPropertyAccess((cx), (val), (key));         \
+        obj = ToObjectFromStack((cx), (val));                                 \
         if (!obj)                                                             \
             goto error;                                                       \
     JS_END_MACRO
 
 /*
  * Same for JSOP_SETNAME and JSOP_SETPROP, which differ only slightly but
  * remain distinct for the decompiler.
  */
@@ -3012,17 +3012,17 @@ END_CASE(JSOP_DELNAME)
 
 CASE(JSOP_DELPROP)
 CASE(JSOP_STRICTDELPROP)
 {
     static_assert(JSOP_DELPROP_LENGTH == JSOP_STRICTDELPROP_LENGTH,
                   "delprop and strictdelprop must be the same size");
     ReservedRooted<jsid> id(&rootId0, NameToId(script->getName(REGS.pc)));
     ReservedRooted<JSObject*> obj(&rootObject0);
-    FETCH_OBJECT(cx, -1, obj, id);
+    FETCH_OBJECT(cx, -1, obj);
 
     ObjectOpResult result;
     if (!DeleteProperty(cx, obj, id, result)) {
         goto error;
     }
     if (!result && JSOp(*REGS.pc) == JSOP_STRICTDELPROP) {
         result.reportError(cx, obj, id);
         goto error;
@@ -3034,18 +3034,19 @@ END_CASE(JSOP_DELPROP)
 
 CASE(JSOP_DELELEM)
 CASE(JSOP_STRICTDELELEM)
 {
     static_assert(JSOP_DELELEM_LENGTH == JSOP_STRICTDELELEM_LENGTH,
                   "delelem and strictdelelem must be the same size");
     /* Fetch the left part and resolve it to a non-null object. */
     ReservedRooted<JSObject*> obj(&rootObject0);
+    FETCH_OBJECT(cx, -2, obj);
+
     ReservedRooted<Value> propval(&rootValue0, REGS.sp[-1]);
-    FETCH_OBJECT(cx, -2, obj, propval);
 
     ObjectOpResult result;
     ReservedRooted<jsid> id(&rootId0);
     if (!ToPropertyKey(cx, propval, &id)) {
         goto error;
     }
     if (!DeleteProperty(cx, obj, id, result)) {
         goto error;
@@ -3314,17 +3315,17 @@ END_CASE(JSOP_GETELEM_SUPER)
 
 CASE(JSOP_SETELEM)
 CASE(JSOP_STRICTSETELEM)
 {
     static_assert(JSOP_SETELEM_LENGTH == JSOP_STRICTSETELEM_LENGTH,
                   "setelem and strictsetelem must be the same size");
     HandleValue receiver = REGS.stackHandleAt(-3);
     ReservedRooted<JSObject*> obj(&rootObject0);
-    obj = ToObjectFromStackForPropertyAccess(cx, receiver, REGS.stackHandleAt(-2));
+    obj = ToObjectFromStack(cx, receiver);
     if (!obj) {
         goto error;
     }
     ReservedRooted<jsid> id(&rootId0);
     FETCH_ELEMENT_ID(-2, id);
     HandleValue value = REGS.stackHandleAt(-1);
     if (!SetObjectElementOperation(cx, obj, id, value, receiver, *REGS.pc == JSOP_STRICTSETELEM)) {
         goto error;
@@ -4911,17 +4912,17 @@ js::GetProperty(JSContext* cx, HandleVal
         }
 
         if (GetPropertyPure(cx, proto, NameToId(name), vp.address())) {
             return true;
         }
     }
 
     RootedValue receiver(cx, v);
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, v, name));
+    RootedObject obj(cx, ToObjectFromStack(cx, v));
     if (!obj) {
         return false;
     }
 
     return GetProperty(cx, obj, receiver, name, vp);
 }
 
 JSObject*
@@ -5066,17 +5067,17 @@ js::GetAndClearException(JSContext* cx, 
     // Allow interrupting deeply nested exception handling.
     return CheckForInterrupt(cx);
 }
 
 template <bool strict>
 bool
 js::DeletePropertyJit(JSContext* cx, HandleValue v, HandlePropertyName name, bool* bp)
 {
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, v, name));
+    RootedObject obj(cx, ToObjectFromStack(cx, v));
     if (!obj) {
         return false;
     }
 
     RootedId id(cx, NameToId(name));
     ObjectOpResult result;
     if (!DeleteProperty(cx, obj, id, result)) {
         return false;
@@ -5097,17 +5098,17 @@ template bool js::DeletePropertyJit<true
                                            bool* bp);
 template bool js::DeletePropertyJit<false>(JSContext* cx, HandleValue val, HandlePropertyName name,
                                            bool* bp);
 
 template <bool strict>
 bool
 js::DeleteElementJit(JSContext* cx, HandleValue val, HandleValue index, bool* bp)
 {
-    RootedObject obj(cx, ToObjectFromStackForPropertyAccess(cx, val, index));
+    RootedObject obj(cx, ToObjectFromStack(cx, val));
     if (!obj) {
         return false;
     }
 
     RootedId id(cx);
     if (!ToPropertyKey(cx, index, &id)) {
         return false;
     }
--- a/js/src/vm/JSContext.cpp
+++ b/js/src/vm/JSContext.cpp
@@ -943,27 +943,21 @@ js::ReportIsNotDefined(JSContext* cx, Ha
 void
 js::ReportIsNotDefined(JSContext* cx, HandlePropertyName name)
 {
     RootedId id(cx, NameToId(name));
     ReportIsNotDefined(cx, id);
 }
 
 void
-js::ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, bool reportScanStack)
+js::ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v)
 {
     MOZ_ASSERT(v.isNullOrUndefined());
 
-    if (!reportScanStack) {
-        JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
-                                  v.isNull() ? "null" : "undefined", "object");
-        return;
-    }
-
-    UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, nullptr);
+    UniqueChars bytes = DecompileValueGenerator(cx, spindex, v, nullptr);
     if (!bytes) {
         return;
     }
 
     if (strcmp(bytes.get(), js_undefined_str) == 0 || strcmp(bytes.get(), js_null_str) == 0) {
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_NO_PROPERTIES, bytes.get());
     } else if (v.isUndefined()) {
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, bytes.get(),
@@ -971,54 +965,16 @@ js::ReportIsNullOrUndefinedForPropertyAc
     } else {
         MOZ_ASSERT(v.isNull());
         JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_UNEXPECTED_TYPE, bytes.get(),
                                  js_null_str);
     }
 }
 
 void
-js::ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, HandleId key,
-                                             bool reportScanStack)
-{
-    MOZ_ASSERT(v.isNullOrUndefined());
-
-    UniqueChars keyBytes = IdToPrintableUTF8(cx, key, IdToPrintableBehavior::IdIsPropertyKey);
-    if (!keyBytes) {
-        return;
-    }
-
-    if (!reportScanStack) {
-        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL,
-                                 keyBytes.get(),
-                                 v.isUndefined() ? js_undefined_str : js_null_str);
-        return;
-    }
-
-    UniqueChars bytes = DecompileValueGenerator(cx, JSDVG_SEARCH_STACK, v, nullptr);
-    if (!bytes) {
-        return;
-    }
-
-    if (strcmp(bytes.get(), js_undefined_str) == 0 || strcmp(bytes.get(), js_null_str) == 0) {
-        JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL,
-                                 keyBytes.get(), bytes.get());
-    } else {
-        const char* actual = v.isUndefined() ? js_undefined_str : js_null_str;
-        if (JSID_IS_INT(key)) {
-            JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_ELEMENT_FAIL_EXPR,
-                                     bytes.get(), actual, keyBytes.get());
-        } else {
-            JS_ReportErrorNumberUTF8(cx, GetErrorMessage, nullptr, JSMSG_PROPERTY_FAIL_EXPR,
-                                     bytes.get(), actual, keyBytes.get());
-        }
-    }
-}
-
-void
 js::ReportMissingArg(JSContext* cx, HandleValue v, unsigned arg)
 {
     char argbuf[11];
     UniqueChars bytes;
 
     SprintfLiteral(argbuf, "%u", arg);
     if (IsFunctionObject(v)) {
         RootedAtom name(cx, v.toObject().as<JSFunction>().explicitName());
--- a/js/src/vm/JSContext.h
+++ b/js/src/vm/JSContext.h
@@ -1082,20 +1082,17 @@ ReportIsNotDefined(JSContext* cx, Handle
 
 extern void
 ReportIsNotDefined(JSContext* cx, HandleId id);
 
 /*
  * Report an attempt to access the property of a null or undefined value (v).
  */
 extern void
-ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, bool reportScanStack);
-extern void
-ReportIsNullOrUndefinedForPropertyAccess(JSContext* cx, HandleValue v, HandleId key,
-                                         bool reportScanStack);
+ReportIsNullOrUndefined(JSContext* cx, int spindex, HandleValue v);
 
 extern void
 ReportMissingArg(JSContext* cx, js::HandleValue v, unsigned arg);
 
 /*
  * Report error using js_DecompileValueGenerator(cx, spindex, v, fallback) as
  * the first argument for the error message. If the error message has less
  * then 3 arguments, use null for arg1 or arg2.
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -3487,70 +3487,21 @@ js::PrimitiveToObject(JSContext* cx, con
  */
 JSObject*
 js::ToObjectSlow(JSContext* cx, JS::HandleValue val, bool reportScanStack)
 {
     MOZ_ASSERT(!val.isMagic());
     MOZ_ASSERT(!val.isObject());
 
     if (val.isNullOrUndefined()) {
-        ReportIsNullOrUndefinedForPropertyAccess(cx, val, reportScanStack);
-        return nullptr;
-    }
-
-    return PrimitiveToObject(cx, val);
-}
-
-JSObject*
-js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleId key,
-                                  bool reportScanStack)
-{
-    MOZ_ASSERT(!val.isMagic());
-    MOZ_ASSERT(!val.isObject());
-
-    if (val.isNullOrUndefined()) {
-        ReportIsNullOrUndefinedForPropertyAccess(cx, val, key, reportScanStack);
-        return nullptr;
-    }
-
-    return PrimitiveToObject(cx, val);
-}
-
-JSObject*
-js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandlePropertyName key,
-                                  bool reportScanStack)
-{
-    MOZ_ASSERT(!val.isMagic());
-    MOZ_ASSERT(!val.isObject());
-
-    if (val.isNullOrUndefined()) {
-        RootedId keyId(cx, NameToId(key));
-        ReportIsNullOrUndefinedForPropertyAccess(cx, val, keyId, reportScanStack);
-        return nullptr;
-    }
-
-    return PrimitiveToObject(cx, val);
-}
-
-JSObject*
-js::ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleValue keyValue,
-                                  bool reportScanStack)
-{
-    MOZ_ASSERT(!val.isMagic());
-    MOZ_ASSERT(!val.isObject());
-
-    if (val.isNullOrUndefined()) {
-        RootedId key(cx);
-        if (keyValue.isPrimitive()) {
-            if (!ValueToId<CanGC>(cx, keyValue, &key)) {
-                return nullptr;
-            }
-            ReportIsNullOrUndefinedForPropertyAccess(cx, val, key, reportScanStack);
+        if (reportScanStack) {
+            ReportIsNullOrUndefined(cx, JSDVG_SEARCH_STACK, val);
         } else {
-            ReportIsNullOrUndefinedForPropertyAccess(cx, val, reportScanStack);
+            JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr, JSMSG_CANT_CONVERT_TO,
+                                      val.isNull() ? "null" : "undefined", "object");
         }
         return nullptr;
     }
 
     return PrimitiveToObject(cx, val);
 }
 
 Value
--- a/js/src/vm/JSObject.h
+++ b/js/src/vm/JSObject.h
@@ -908,51 +908,16 @@ MOZ_ALWAYS_INLINE JSObject*
 ToObjectFromStack(JSContext* cx, HandleValue vp)
 {
     if (vp.isObject()) {
         return &vp.toObject();
     }
     return js::ToObjectSlow(cx, vp, true);
 }
 
-JSObject*
-ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleId key,
-                              bool reportScanStack);
-JSObject*
-ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandlePropertyName key,
-                              bool reportScanStack);
-JSObject*
-ToObjectSlowForPropertyAccess(JSContext* cx, JS::HandleValue val, HandleValue keyValue,
-                              bool reportScanStack);
-
-MOZ_ALWAYS_INLINE JSObject*
-ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandleId key)
-{
-    if (vp.isObject()) {
-        return &vp.toObject();
-    }
-    return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
-}
-MOZ_ALWAYS_INLINE JSObject*
-ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandlePropertyName key)
-{
-    if (vp.isObject()) {
-        return &vp.toObject();
-    }
-    return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
-}
-MOZ_ALWAYS_INLINE JSObject*
-ToObjectFromStackForPropertyAccess(JSContext* cx, HandleValue vp, HandleValue key)
-{
-    if (vp.isObject()) {
-        return &vp.toObject();
-    }
-    return js::ToObjectSlowForPropertyAccess(cx, vp, key, true);
-}
-
 template<XDRMode mode>
 XDRResult
 XDRObjectLiteral(XDRState<mode>* xdr, MutableHandleObject obj);
 
 /*
  * Report a TypeError: "so-and-so is not an object".
  * Using NotNullObject is usually less code.
  */
--- a/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
+++ b/toolkit/components/extensions/test/xpcshell/test_ext_contentscript_create_iframe.js
@@ -119,18 +119,17 @@ add_task(async function test_contentscri
     try {
       manifest = win.browser.runtime.getManifest();
     } catch (e) {
       manifestException = e;
     }
 
     Assert.ok(!manifest, "manifest should be undefined");
 
-    Assert.equal(String(manifestException),
-                 `TypeError: win.browser.runtime is undefined; can't access its "getManifest" property`,
+    Assert.equal(String(manifestException), "TypeError: win.browser.runtime is undefined",
                  "expected exception received");
 
     let getManifestException = win.testGetManifestException();
 
     Assert.equal(getManifestException, "TypeError: can't access dead object",
                  "expected exception received");
   });