From 63daa2aa42a276b4a1da2fd69d10a50871d28632 Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Tue, 1 Jul 2014 21:18:12 -0500 Subject: [PATCH] Bug 918828, part 3 - Update decompiler for JSOP_SYMBOL. This improves error messages when @@iterator is called implicitly. r=Waldo. --HG-- extra : rebase_source : b9edaa7be12bdfde40b38d3f413f10624c4f0dcf --- .../tests/basic/expression-autopsy.js | 4 +-- js/src/jsatom.cpp | 2 +- js/src/jsopcode.cpp | 7 +++++ .../tests/js1_8/regress/regress-469625-03.js | 2 +- .../js1_8_5/extensions/decompile-for-of.js | 26 +++++++++++++++++++ js/src/vm/Runtime.h | 4 +++ 6 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 js/src/tests/js1_8_5/extensions/decompile-for-of.js diff --git a/js/src/jit-test/tests/basic/expression-autopsy.js b/js/src/jit-test/tests/basic/expression-autopsy.js index ad2985d16ad..2d59ddab755 100644 --- a/js/src/jit-test/tests/basic/expression-autopsy.js +++ b/js/src/jit-test/tests/basic/expression-autopsy.js @@ -109,8 +109,8 @@ check("o[- (o)]"); // A few one off tests check_one("6", (function () { 6() }), " is not a function"); check_one("Array.prototype.reverse.call(...)", (function () { Array.prototype.reverse.call('123'); }), " is read-only"); -check_one("(intermediate value)[(intermediate value)](...).next(...).value", function () { var [{ x }] = [null, {}]; }, " is null"); -check_one("(intermediate value)[(intermediate value)](...).next(...).value", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); +check_one("(intermediate value)[Symbol.iterator](...).next(...).value", function () { var [{ x }] = [null, {}]; }, " is null"); +check_one("(intermediate value)[Symbol.iterator](...).next(...).value", function () { ieval("let (x) { var [a, b, [c0, c1]] = [x, x, x]; }") }, " is undefined"); // Check fallback behavior assertThrowsInstanceOf(function () { for (let x of undefined) {} }, TypeError); diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 6d11272e5da..f18c57c88d8 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -157,7 +157,7 @@ JSRuntime::initializeAtoms(JSContext *cx) if (!wellKnownSymbols) return false; - ImmutablePropertyNamePtr *descriptions = &commonNames->Symbol_iterator; + ImmutablePropertyNamePtr *descriptions = commonNames->wellKnownSymbolDescriptions(); ImmutableSymbolPtr *symbols = reinterpret_cast(wellKnownSymbols); for (size_t i = 0; i < JS::WellKnownSymbolLimit; i++) { JS::Symbol *symbol = JS::Symbol::new_(cx, JS::SymbolCode(i), descriptions[i]); diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index ecbca61a1ee..3147e4a4f3e 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -1540,6 +1540,13 @@ ExpressionDecompiler::decompilePC(jsbytecode *pc) return sprinter.printf("%d", GetBytecodeInteger(pc)) >= 0; case JSOP_STRING: return quote(loadAtom(pc), '"'); + case JSOP_SYMBOL: { + unsigned i = uint8_t(pc[1]); + MOZ_ASSERT(i < JS::WellKnownSymbolLimit); + if (i < JS::WellKnownSymbolLimit) + return write(cx->names().wellKnownSymbolDescriptions()[i]); + break; + } case JSOP_UNDEFINED: return write(js_undefined_str); case JSOP_THIS: diff --git a/js/src/tests/js1_8/regress/regress-469625-03.js b/js/src/tests/js1_8/regress/regress-469625-03.js index 2c3047bc92b..56b1dea69b5 100644 --- a/js/src/tests/js1_8/regress/regress-469625-03.js +++ b/js/src/tests/js1_8/regress/regress-469625-03.js @@ -26,7 +26,7 @@ function test() var [a, b, [c0, c1]] = [x, x, x]; } - expect = 'TypeError: (intermediate value)[(intermediate value)](...).next(...).value is null'; + expect = 'TypeError: (intermediate value)[Symbol.iterator](...).next(...).value is null'; actual = 'No Error'; try { diff --git a/js/src/tests/js1_8_5/extensions/decompile-for-of.js b/js/src/tests/js1_8_5/extensions/decompile-for-of.js new file mode 100644 index 00000000000..eb0658d130a --- /dev/null +++ b/js/src/tests/js1_8_5/extensions/decompile-for-of.js @@ -0,0 +1,26 @@ +// The decompiler can handle the implicit call to @@iterator in a for-of loop. + +var x; +function check(code) { + var s = "no exception thrown"; + try { + eval(code); + } catch (exc) { + s = exc.message; + } + assertEq(s, "x[Symbol.iterator] is not a function"); +} + +x = {}; +check("for (var v of x) throw fit;"); +check("[...x]"); +check("Math.hypot(...x)"); + +x[Symbol.iterator] = "potato"; +check("for (var v of x) throw fit;"); + +x[Symbol.iterator] = {}; +check("for (var v of x) throw fit;"); + +if (typeof reportCompare === "function") + reportCompare(0, 0, "ok"); diff --git a/js/src/vm/Runtime.h b/js/src/vm/Runtime.h index 91bf225f1c4..930aa75ffcf 100644 --- a/js/src/vm/Runtime.h +++ b/js/src/vm/Runtime.h @@ -400,6 +400,10 @@ struct JSAtomState #define PROPERTYNAME_FIELD(name, code, init, clasp) js::ImmutablePropertyNamePtr name; JS_FOR_EACH_PROTOTYPE(PROPERTYNAME_FIELD) #undef PROPERTYNAME_FIELD + + js::ImmutablePropertyNamePtr *wellKnownSymbolDescriptions() { + return &Symbol_iterator; + } }; namespace js {