diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 2cdde8d0942d..57ddd567ae5e 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -2003,7 +2003,7 @@ bool BytecodeEmitter::emitCallIncDec(UnaryNode* incDec) { // The increment/decrement has no side effects, so proceed to throw for // invalid assignment target. - return emitUint16Operand(JSOP_THROWMSG, JSMSG_ASSIGN_TO_CALL); + return emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS); } bool BytecodeEmitter::emitDouble(double d) { @@ -4252,7 +4252,7 @@ bool BytecodeEmitter::emitAssignmentOrInit(ParseNodeKind kind, ParseNode* lhs, // Assignment to function calls is forbidden, but we have to make the // call first. Now we can throw. - if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_ASSIGN_TO_CALL)) { + if (!emitUint16Operand(JSOP_THROWMSG, JSMSG_BAD_LEFTSIDE_OF_ASS)) { return false; } diff --git a/js/src/jit-test/tests/basic/bug791465.js b/js/src/jit-test/tests/basic/bug791465.js index 13460a11f0e2..b3b2e2dd3156 100644 --- a/js/src/jit-test/tests/basic/bug791465.js +++ b/js/src/jit-test/tests/basic/bug791465.js @@ -66,10 +66,10 @@ var assignment_ops = [ "*=", "/=", "%=", ]; -var invalid_strict_funs_syntax_error = assignment_ops.map(op => ("'use strict'\n " + op + " 'not'")); +var invalid_strict_funs_referror = assignment_ops.map(op => ("'use strict'\n " + op + " 'not'")); // assignment with string literal as LHS is an early error, therefore we -// can only test for SyntaxError -for (var f of invalid_strict_funs_syntax_error) { - assertThrowsInstanceOf(function() { Function(f) }, SyntaxError); +// can only test for ReferenceError +for (var f of invalid_strict_funs_referror) { + assertThrowsInstanceOf(function() { Function(f) }, ReferenceError); } diff --git a/js/src/jit-test/tests/modules/import-meta-expression.js b/js/src/jit-test/tests/modules/import-meta-expression.js index e7562afaedbc..bf2c9e0d0ac0 100644 --- a/js/src/jit-test/tests/modules/import-meta-expression.js +++ b/js/src/jit-test/tests/modules/import-meta-expression.js @@ -80,6 +80,11 @@ function assertModuleParseThrowsSyntaxError(source) assertThrowsInstanceOf(() => parseAsModule(source), SyntaxError); } +function assertModuleParseThrowsReferenceError(source) +{ + assertThrowsInstanceOf(() => parseAsModule(source), ReferenceError); +} + assertModuleParseThrowsSyntaxError("import"); assertModuleParseThrowsSyntaxError("import."); assertModuleParseThrowsSyntaxError("import.met"); @@ -88,4 +93,5 @@ assertModuleParseThrowsSyntaxError("x = import"); assertModuleParseThrowsSyntaxError("x = import."); assertModuleParseThrowsSyntaxError("x = import.met"); assertModuleParseThrowsSyntaxError("x = import.metaa"); -assertModuleParseThrowsSyntaxError("import.meta = x"); + +assertModuleParseThrowsReferenceError("import.meta = x"); diff --git a/js/src/js.msg b/js/src/js.msg index 32339d68f275..08364260adab 100644 --- a/js/src/js.msg +++ b/js/src/js.msg @@ -119,8 +119,8 @@ MSG_DEF(JSMSG_JSON_BAD_PARSE, 3, JSEXN_SYNTAXERR, "JSON.parse: {0} at l MSG_DEF(JSMSG_JSON_CYCLIC_VALUE, 0, JSEXN_TYPEERR, "cyclic object value") // Runtime errors -MSG_DEF(JSMSG_ASSIGN_TO_CALL, 0, JSEXN_REFERENCEERR, "cannot assign to function call") MSG_DEF(JSMSG_BAD_INSTANCEOF_RHS, 1, JSEXN_TYPEERR, "invalid 'instanceof' operand {0}") +MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_REFERENCEERR, "invalid assignment left-hand side") MSG_DEF(JSMSG_BAD_PROTOTYPE, 1, JSEXN_TYPEERR, "'prototype' property of {0} is not an object") MSG_DEF(JSMSG_IN_NOT_OBJECT, 1, JSEXN_TYPEERR, "right-hand side of 'in' should be an object, got {0}") MSG_DEF(JSMSG_IN_STRING, 2, JSEXN_TYPEERR, "cannot use 'in' operator to search for '{0}' in '{1}'") @@ -196,7 +196,7 @@ MSG_DEF(JSMSG_BAD_ARROW_ARGS, 0, JSEXN_SYNTAXERR, "invalid arrow-functi MSG_DEF(JSMSG_BAD_BINDING, 1, JSEXN_SYNTAXERR, "redefining {0} is deprecated") MSG_DEF(JSMSG_BAD_CONST_DECL, 0, JSEXN_SYNTAXERR, "missing = in const declaration") MSG_DEF(JSMSG_BAD_CONTINUE, 0, JSEXN_SYNTAXERR, "continue must be inside loop") -MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_SYNTAXERR, "invalid destructuring assignment operator") +MSG_DEF(JSMSG_BAD_DESTRUCT_ASS, 0, JSEXN_REFERENCEERR, "invalid destructuring assignment operator") MSG_DEF(JSMSG_BAD_DESTRUCT_TARGET, 0, JSEXN_SYNTAXERR, "invalid destructuring target") MSG_DEF(JSMSG_BAD_DESTRUCT_PARENS, 0, JSEXN_SYNTAXERR, "destructuring patterns in assignments can't be parenthesized") MSG_DEF(JSMSG_BAD_DESTRUCT_DECL, 0, JSEXN_SYNTAXERR, "missing = in destructuring declaration") @@ -206,7 +206,6 @@ MSG_DEF(JSMSG_BAD_FOR_LEFTSIDE, 0, JSEXN_SYNTAXERR, "invalid for-in/of le MSG_DEF(JSMSG_LEXICAL_DECL_DEFINES_LET,0, JSEXN_SYNTAXERR, "a lexical declaration can't define a 'let' binding") MSG_DEF(JSMSG_LET_STARTING_FOROF_LHS, 0, JSEXN_SYNTAXERR, "an expression X in 'for (X of Y)' must not start with 'let'") MSG_DEF(JSMSG_BAD_INCOP_OPERAND, 0, JSEXN_SYNTAXERR, "invalid increment/decrement operand") -MSG_DEF(JSMSG_BAD_LEFTSIDE_OF_ASS, 0, JSEXN_SYNTAXERR, "invalid assignment left-hand side") MSG_DEF(JSMSG_BAD_METHOD_DEF, 0, JSEXN_SYNTAXERR, "bad method definition") MSG_DEF(JSMSG_BAD_POW_LEFTSIDE, 0, JSEXN_SYNTAXERR, "unparenthesized unary expression can't appear on the left-hand side of '**'") MSG_DEF(JSMSG_BAD_PROP_ID, 0, JSEXN_SYNTAXERR, "invalid property id") diff --git a/js/src/tests/jstests.list b/js/src/tests/jstests.list index 2d18e8883fe3..397e16eec0e8 100644 --- a/js/src/tests/jstests.list +++ b/js/src/tests/jstests.list @@ -394,6 +394,35 @@ skip script test262/intl402/Collator/prototype/compare/compare-function-name.js skip script test262/intl402/DateTimeFormat/prototype/format/format-function-name.js skip script test262/intl402/NumberFormat/prototype/format/format-function-name.js +# https://bugzilla.mozilla.org/show_bug.cgi?id=1340307 +skip script test262/language/module-code/instn-resolve-empty-export.js +skip script test262/language/module-code/instn-resolve-empty-import.js +skip script test262/language/module-code/instn-resolve-err-reference.js +skip script test262/language/module-code/instn-resolve-order-depth.js +skip script test262/language/module-code/instn-resolve-order-src.js +skip script test262/language/module-code/parse-err-reference.js +skip script test262/language/expressions/postfix-increment/target-cover-yieldexpr.js +skip script test262/language/expressions/postfix-increment/target-newtarget.js +skip script test262/language/expressions/postfix-increment/target-cover-newtarget.js +skip script test262/language/expressions/postfix-increment/non-simple.js +skip script test262/language/expressions/postfix-decrement/target-cover-yieldexpr.js +skip script test262/language/expressions/postfix-decrement/target-newtarget.js +skip script test262/language/expressions/postfix-decrement/target-cover-newtarget.js +skip script test262/language/expressions/postfix-decrement/non-simple.js +skip script test262/language/expressions/prefix-increment/target-cover-yieldexpr.js +skip script test262/language/expressions/prefix-increment/target-newtarget.js +skip script test262/language/expressions/prefix-increment/target-cover-newtarget.js +skip script test262/language/expressions/prefix-increment/non-simple.js +skip script test262/language/expressions/prefix-decrement/target-cover-yieldexpr.js +skip script test262/language/expressions/prefix-decrement/target-newtarget.js +skip script test262/language/expressions/prefix-decrement/target-cover-newtarget.js +skip script test262/language/expressions/prefix-decrement/non-simple.js +skip script test262/language/asi/S7.9_A5.7_T1.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-1-update-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-2-update-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-3-update-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-4-update-expression.js + # Dependent on evalInWorker, setSharedArrayBuffer, and # getSharedArrayBuffer, plus the test cases can't actually run in the # browser even if that were fixed, https://bugzil.la/1349863 @@ -489,6 +518,49 @@ skip script test262/built-ins/Proxy/construct/return-not-object-throws-null-real skip script test262/built-ins/Proxy/construct/return-not-object-throws-boolean-realm.js skip script test262/built-ins/Proxy/construct/return-not-object-throws-boolean-realm.js +# https://bugzilla.mozilla.org/show_bug.cgi?id=1556818 +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-5-lhs-equals-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-12-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-10-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-16-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-14-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-9-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-6-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-13-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-11-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-17-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-8-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-15-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/dynamic-import/syntax/invalid/invalid-assignmenttargettype-syntax-error-7-lhs-assignment-operator-assignment-expression.js +skip script test262/language/expressions/async-function/early-errors-expression-not-simple-assignment-target.js +skip script test262/language/expressions/async-generator/early-errors-expression-not-simple-assignment-target.js +skip script test262/language/expressions/await/early-errors-await-not-simple-assignment-target.js +skip script test262/language/expressions/assignment/non-simple-target.js +skip script test262/language/expressions/compound-assignment/mod-div-non-simple.js +skip script test262/language/expressions/compound-assignment/btws-and-non-simple.js +skip script test262/language/expressions/compound-assignment/left-shift-non-simple.js +skip script test262/language/expressions/compound-assignment/add-non-simple.js +skip script test262/language/expressions/compound-assignment/u-right-shift-non-simple.js +skip script test262/language/expressions/compound-assignment/mult-non-simple.js +skip script test262/language/expressions/compound-assignment/right-shift-non-simple.js +skip script test262/language/expressions/compound-assignment/div-non-simple.js +skip script test262/language/expressions/compound-assignment/btws-or-non-simple.js +skip script test262/language/expressions/compound-assignment/btws-xor-non-simple.js +skip script test262/language/expressions/compound-assignment/subtract-non-simple.js +skip script test262/language/expressions/assignment/target-cover-yieldexpr.js +skip script test262/language/expressions/assignment/target-newtarget.js +skip script test262/language/expressions/assignment/target-string.js +skip script test262/language/expressions/assignment/target-boolean.js +skip script test262/language/expressions/assignment/target-null.js +skip script test262/language/expressions/assignment/target-number.js +skip script test262/language/expressions/assignment/target-cover-newtarget.js +skip script test262/language/expressions/import.meta/syntax/invalid-assignment-target-assignment-expr.js +skip script test262/language/expressions/this/S11.1.1_A1.js +skip script test262/language/types/boolean/S8.3_A2.2.js +skip script test262/language/types/boolean/S8.3_A2.1.js +skip script test262/language/types/reference/S8.7.2_A1_T1.js +skip script test262/language/types/reference/S8.7.2_A1_T2.js + # https://bugzilla.mozilla.org/show_bug.cgi?id=1560300 skip script test262/built-ins/Promise/all/invoke-resolve-get-error-close.js skip script test262/built-ins/Promise/all/invoke-resolve-get-once-multiple-calls.js diff --git a/js/src/tests/non262/expressions/destructuring-pattern-parenthesized.js b/js/src/tests/non262/expressions/destructuring-pattern-parenthesized.js index 529fb5f71ea4..ef49fecf593a 100644 --- a/js/src/tests/non262/expressions/destructuring-pattern-parenthesized.js +++ b/js/src/tests/non262/expressions/destructuring-pattern-parenthesized.js @@ -57,10 +57,10 @@ function checkError(code, nonstrictErr, strictErr) } // Parenthesized destructuring patterns don't trigger grammar refinement, so we -// get the usual SyntaxError for an invalid assignment target, per +// get the currently-usual ReferenceError for an invalid assignment target, per // 12.14.1 second bullet. -checkError("var a, b; ([a, b]) = [1, 2];", SyntaxError, SyntaxError); -checkError("var a, b; ({a, b}) = { a: 1, b: 2 };", SyntaxError, SyntaxError); +checkError("var a, b; ([a, b]) = [1, 2];", ReferenceError, ReferenceError); +checkError("var a, b; ({a, b}) = { a: 1, b: 2 };", ReferenceError, ReferenceError); // *Nested* parenthesized destructuring patterns, on the other hand, do trigger // grammar refinement. But subtargets in a destructuring pattern must be @@ -122,8 +122,12 @@ if (classesEnabled()) checkError("var a, b; var obj = { x() { [(super[8 + {}] = 'motel')] = [1]; } };", SyntaxError, SyntaxError); // evade constant-folding } -checkError("var a, b; [f() = 'ohai', b] = [1, 2];", SyntaxError, SyntaxError); -checkError("var a, b; [(f()) = 'kthxbai', b] = [1, 2];", SyntaxError, SyntaxError); +// In strict mode, assignment to funcall *immediately* triggers ReferenceError +// before we can recognize this doesn't even match the destructuring grammar to +// begin with. Bleh. :-( Probably they should all be made SyntaxError in the +// specs; see . +checkError("var a, b; [f() = 'ohai', b] = [1, 2];", SyntaxError, ReferenceError); +checkError("var a, b; [(f()) = 'kthxbai', b] = [1, 2];", SyntaxError, ReferenceError); Function("var a, b; ({ a: (a), b} = { a: 1, b: 2 });")(); Function("var a, b; ({ a: (a) = 5, b} = { a: 1, b: 2 });")(); diff --git a/js/src/tests/non262/object/destructuring-shorthand-defaults.js b/js/src/tests/non262/object/destructuring-shorthand-defaults.js index 3ca240e0b785..a03dea2a2987 100644 --- a/js/src/tests/non262/object/destructuring-shorthand-defaults.js +++ b/js/src/tests/non262/object/destructuring-shorthand-defaults.js @@ -78,17 +78,25 @@ const SYNTAX_ERROR_STMTS = [ "true ? {x=1} : 1;", "false ? 1 : {x=1};", "{x=1} ? 2 : 3;", - // assignment - "({x} += {});", - "({x = 1}) = {x: 2};", ] for (var stmt of SYNTAX_ERROR_STMTS) { assertThrowsInstanceOf(() => { - Function(stmt); + eval(stmt); }, SyntaxError); } +const REFERENCE_ERROR_STMTS = [ + "({x} += {});", + "({x = 1}) = {x: 2};", +] + +for (var stmt of REFERENCE_ERROR_STMTS) { + assertThrowsInstanceOf(() => { + eval(stmt); + }, ReferenceError); +} + // A few tricky but acceptable cases: // see https://bugzilla.mozilla.org/show_bug.cgi?id=932080#c2 diff --git a/js/src/tests/non262/regress/regress-609617.js b/js/src/tests/non262/regress/regress-609617.js index 0a530ec53061..f588153d4c9f 100644 --- a/js/src/tests/non262/regress/regress-609617.js +++ b/js/src/tests/non262/regress/regress-609617.js @@ -37,11 +37,11 @@ for (var i = 0; i < lhs_prefix.length; i++) { assertEq(e.message, "invalid destructuring target"); } else { /* - * NB: JSOP_SETCALL throws only JSMSG_ASSIGN_TO_CALL, it does not + * NB: JSOP_SETCALL throws only JSMSG_BAD_LEFTSIDE_OF_ASS, it does not * specialize for ++ and -- as the compiler's error reporting does. See * the next section's forked assertEq code. */ - assertEq(e.message, "cannot assign to function call"); + assertEq(e.message, "invalid assignment left-hand side"); } } } @@ -71,7 +71,7 @@ try { eval("delete (foo('x') = 42);"); assertEq(0, -4); } catch (e) { - assertEq(e.message, "cannot assign to function call"); + assertEq(e.message, "invalid assignment left-hand side"); } assertEq(fooArg, 'x'); diff --git a/js/src/tests/non262/statements/for-in-with-assignment-syntax.js b/js/src/tests/non262/statements/for-in-with-assignment-syntax.js index 7540b4bd1b1a..4ac711e21e9b 100644 --- a/js/src/tests/non262/statements/for-in-with-assignment-syntax.js +++ b/js/src/tests/non262/statements/for-in-with-assignment-syntax.js @@ -35,31 +35,33 @@ const invalidSyntax = [ ]; for (let valid of validSyntax) { - Function(`for (${valid} = 0 in {});`); - assertThrowsInstanceOf(() => Function(`"use strict"; for (${valid} = 0 in {});`), + eval(`for (${valid} = 0 in {});`); + assertThrowsInstanceOf(() => eval(`"use strict"; for (${valid} = 0 in {});`), SyntaxError); } for (let invalid of invalidSyntax) { - assertThrowsInstanceOf(() => Function(`for (${invalid} = 0 in {});`), SyntaxError); + assertThrowsInstanceOf(() => eval(`for (${invalid} = 0 in {});`), SyntaxError); } // Invalid syntax, needs method context to parse. -assertThrowsInstanceOf(() => Function(`({ m() { for (super.p = 0 in {}); } })`), SyntaxError); -assertThrowsInstanceOf(() => Function(`({ m() { for (super[0] = 0 in {}); } })`), SyntaxError); +assertThrowsInstanceOf(() => eval(`({ m() { for (super.p = 0 in {}); } })`), SyntaxError); +assertThrowsInstanceOf(() => eval(`({ m() { for (super[0] = 0 in {}); } })`), SyntaxError); -assertThrowsInstanceOf(() => Function(`for (0 = 0 in {});`), SyntaxError); -assertThrowsInstanceOf(() => Function(`for (i++ = 0 in {});`), SyntaxError); -assertThrowsInstanceOf(() => Function(`for (new F() = 0 in {});`), SyntaxError); -assertThrowsInstanceOf(() => Function(`function f() { for (new.target = 0 in {}); }`), SyntaxError); -assertThrowsInstanceOf(() => Function(`class C extends D { constructor() { for (super() = 0 in {}); } }`), SyntaxError); +// Throws ReferenceError instead of SyntaxError, because we intermingle parsing +// and early error checking. +assertThrowsInstanceOf(() => eval(`for (0 = 0 in {});`), ReferenceError); +assertThrowsInstanceOf(() => eval(`for (i++ = 0 in {});`), ReferenceError); +assertThrowsInstanceOf(() => eval(`for (new F() = 0 in {});`), ReferenceError); +assertThrowsInstanceOf(() => eval(`function f() { for (new.target = 0 in {}); }`), ReferenceError); +assertThrowsInstanceOf(() => eval(`class C extends D { constructor() { for (super() = 0 in {}); } }`), ReferenceError); // Same as above, only this time don't make it look like we actually parse a for-in statement. -assertThrowsInstanceOf(() => Function(`for (0 = 0 #####`), SyntaxError); -assertThrowsInstanceOf(() => Function(`for (i++ = 0 #####`), SyntaxError); -assertThrowsInstanceOf(() => Function(`for (new F() = 0 #####`), SyntaxError); -assertThrowsInstanceOf(() => Function(`function f() { for (new.target = 0 #####`), SyntaxError); -assertThrowsInstanceOf(() => Function(`class C extends D { constructor() { for (super() = 0 #####`), SyntaxError); +assertThrowsInstanceOf(() => eval(`for (0 = 0 #####`), ReferenceError); +assertThrowsInstanceOf(() => eval(`for (i++ = 0 #####`), ReferenceError); +assertThrowsInstanceOf(() => eval(`for (new F() = 0 #####`), ReferenceError); +assertThrowsInstanceOf(() => eval(`function f() { for (new.target = 0 #####`), ReferenceError); +assertThrowsInstanceOf(() => eval(`class C extends D { constructor() { for (super() = 0 #####`), ReferenceError); if (typeof reportCompare === "function")