[JSC] Invalid AssignmentTargetType should be an early error.
authorross.kirsling@sony.com <ross.kirsling@sony.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 May 2019 20:08:22 +0000 (20:08 +0000)
committerross.kirsling@sony.com <ross.kirsling@sony.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 16 May 2019 20:08:22 +0000 (20:08 +0000)
https://bugs.webkit.org/show_bug.cgi?id=197603

Reviewed by Keith Miller.

JSTests:

* test262/expectations.yaml:
Update expectations to reflect new SyntaxErrors.
(Ideally, these should all be viewed as passing in the near future.)

* stress/async-await-basic.js:
* stress/big-int-literals.js:
Update tests to reflect new SyntaxErrors.

* ChakraCore.yaml:
* ChakraCore/test/EH/try6.baseline-jsc:
* ChakraCore/test/Error/variousErrors3.baseline-jsc: Added.
Update baselines to reflect new SyntaxErrors.

Source/JavaScriptCore:

Since ES6, expressions like 0++, ++0, 0 = 0, and 0 += 0 are all specified as early errors:
  https://tc39.github.io/ecma262/#sec-update-expressions-static-semantics-early-errors
  https://tc39.github.io/ecma262/#sec-assignment-operators-static-semantics-early-errors

We currently throw late ReferenceErrors for these -- let's turn them into early SyntaxErrors.
(This is based on the expectation that https://github.com/tc39/ecma262/pull/1527 will be accepted;
if that doesn't come to pass, we can subsequently introduce early ReferenceError and revise these.)

* bytecompiler/NodesCodegen.cpp:
(JSC::PostfixNode::emitBytecode): Add an assert for "function call LHS" case.
(JSC::PrefixNode::emitBytecode): Add an assert for "function call LHS" case.

* parser/ASTBuilder.h:
(JSC::ASTBuilder::isLocation): Added.
(JSC::ASTBuilder::isAssignmentLocation): Fix misleading parameter name.
(JSC::ASTBuilder::isFunctionCall): Added.
(JSC::ASTBuilder::makeAssignNode): Add an assert for "function call LHS" case.
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::isLocation): Added.
(JSC::SyntaxChecker::isAssignmentLocation): Fix incorrect definition and align with ASTBuilder.
(JSC::SyntaxChecker::isFunctionCall): Added.
* parser/Nodes.h:
(JSC::ExpressionNode::isFunctionCall const): Added.
Ensure that the parser can check whether an expression node is a function call.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::isSimpleAssignmentTarget): Added.
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parseUnaryExpression): See below.
* parser/Parser.h:
Throw SyntaxError whenever an assignment or update expression's target is invalid.
Unfortunately, it seems that web compatibility obliges us to exempt the "function call LHS" case in sloppy mode.
(https://github.com/tc39/ecma262/issues/257#issuecomment-195106880)

Additional cleanup items:
  - Make use of `semanticFailIfTrue` for `isMetaProperty` checks, as it's equivalent.
  - Rename `requiresLExpr` to `hasPrefixUpdateOp` since it's now confusing,
    and get rid of `modifiesExpr` since it refers to the exact same condition.
  - Stop setting `lastOperator` near the end -- one case was incorrect and regardless neither is used.

LayoutTests:

* fast/events/window-onerror4-expected.txt:
* ietestcenter/Javascript/11.13.1-1-1-expected.txt:
* ietestcenter/Javascript/11.13.1-1-2-expected.txt:
* ietestcenter/Javascript/11.13.1-1-3-expected.txt:
* ietestcenter/Javascript/11.13.1-1-4-expected.txt:
* js/basic-strict-mode-expected.txt:
* js/dom/assign-expected.txt:
* js/dom/line-column-numbers-expected.txt:
* js/dom/line-column-numbers.html:
* js/dom/postfix-syntax-expected.txt:
* js/dom/prefix-syntax-expected.txt:
* js/dom/script-tests/line-column-numbers.js:
* js/function-toString-parentheses-expected.txt:
* js/parser-syntax-check-expected.txt:
* js/parser-xml-close-comment-expected.txt:
* js/script-tests/function-toString-parentheses.js:
* js/script-tests/parser-syntax-check.js:
Update tests & expectations to reflect new SyntaxErrors.

* js/script-tests/toString-prefix-postfix-preserve-parens.js:
* js/toString-prefix-postfix-preserve-parens-expected.txt:
None of the prefix/postfix tests make sense here now that they're all SyntaxErrors;
remove them and just leave the typeof tests.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@245406 268f45cc-cd09-0410-ab3c-d52691b4dbfc

34 files changed:
JSTests/ChakraCore.yaml
JSTests/ChakraCore/test/EH/try6.baseline-jsc
JSTests/ChakraCore/test/Error/variousErrors3.baseline-jsc [new file with mode: 0644]
JSTests/ChangeLog
JSTests/stress/async-await-basic.js
JSTests/stress/big-int-literals.js
JSTests/test262/expectations.yaml
LayoutTests/ChangeLog
LayoutTests/fast/events/window-onerror4-expected.txt
LayoutTests/ietestcenter/Javascript/11.13.1-1-1-expected.txt
LayoutTests/ietestcenter/Javascript/11.13.1-1-2-expected.txt
LayoutTests/ietestcenter/Javascript/11.13.1-1-3-expected.txt
LayoutTests/ietestcenter/Javascript/11.13.1-1-4-expected.txt
LayoutTests/js/basic-strict-mode-expected.txt
LayoutTests/js/dom/assign-expected.txt
LayoutTests/js/dom/line-column-numbers-expected.txt
LayoutTests/js/dom/line-column-numbers.html
LayoutTests/js/dom/postfix-syntax-expected.txt
LayoutTests/js/dom/prefix-syntax-expected.txt
LayoutTests/js/dom/script-tests/line-column-numbers.js
LayoutTests/js/function-toString-parentheses-expected.txt
LayoutTests/js/parser-syntax-check-expected.txt
LayoutTests/js/parser-xml-close-comment-expected.txt
LayoutTests/js/script-tests/function-toString-parentheses.js
LayoutTests/js/script-tests/parser-syntax-check.js
LayoutTests/js/script-tests/toString-prefix-postfix-preserve-parens.js
LayoutTests/js/toString-prefix-postfix-preserve-parens-expected.txt
Source/JavaScriptCore/ChangeLog
Source/JavaScriptCore/bytecompiler/NodesCodegen.cpp
Source/JavaScriptCore/parser/ASTBuilder.h
Source/JavaScriptCore/parser/Nodes.h
Source/JavaScriptCore/parser/Parser.cpp
Source/JavaScriptCore/parser/Parser.h
Source/JavaScriptCore/parser/SyntaxChecker.h

index 59f00a5..2ad0fd0 100644 (file)
 - path: ChakraCore/test/Error/CallNonFunction.js
   cmd: runChakra :baseline, "NoException", "CallNonFunction_3.baseline-jsc", []
 - path: ChakraCore/test/Error/variousErrors.js
-  cmd: runChakra :baseline, "NoException", "variousErrors3.baseline", []
+  cmd: runChakra :baseline, "NoException", "variousErrors3.baseline-jsc", []
 - path: ChakraCore/test/Error/bug560940.js
   cmd: runChakra :pass, "NoException", "", []
 - path: ChakraCore/test/Error/inlineSameFunc.js
index 8896d1f..83510b7 100644 (file)
@@ -16,4 +16,4 @@ Inner foobaz 2
        Finally bar 2
 Except foobaz 2 thrown
 english (passed)
-ReferenceError: Postfix ++ operator applied to value that is not a reference.
+SyntaxError: Postfix ++ operator applied to value that is not a reference.
diff --git a/JSTests/ChakraCore/test/Error/variousErrors3.baseline-jsc b/JSTests/ChakraCore/test/Error/variousErrors3.baseline-jsc
new file mode 100644 (file)
index 0000000..e1dc4e0
--- /dev/null
@@ -0,0 +1,8 @@
+42 = 42 :: SyntaxError
+'x' = 42 :: SyntaxError
+true = 42 :: SyntaxError
+null = 42 :: SyntaxError
+delete this .. true
+delete true .. true
+delete 10 .. true
+delete null .. true
index 33d8b0a..e68c826 100644 (file)
@@ -1,3 +1,23 @@
+2019-05-16  Ross Kirsling  <ross.kirsling@sony.com>
+
+        [JSC] Invalid AssignmentTargetType should be an early error.
+        https://bugs.webkit.org/show_bug.cgi?id=197603
+
+        Reviewed by Keith Miller.
+
+        * test262/expectations.yaml:
+        Update expectations to reflect new SyntaxErrors.
+        (Ideally, these should all be viewed as passing in the near future.)
+
+        * stress/async-await-basic.js:
+        * stress/big-int-literals.js:
+        Update tests to reflect new SyntaxErrors.
+
+        * ChakraCore.yaml:
+        * ChakraCore/test/EH/try6.baseline-jsc:
+        * ChakraCore/test/Error/variousErrors3.baseline-jsc: Added.
+        Update baselines to reflect new SyntaxErrors.
+
 2019-05-15  Saam Barati  <sbarati@apple.com>
 
         Bound liveness of SetArgumentMaybe nodes when maximal flush insertion phase is enabled
index dfeefef..0eb23b0 100644 (file)
@@ -270,28 +270,15 @@ var awaitEpression = async (value) => {
     var t3 = !!!!!await Promise.resolve(true);
     log.push('step 5 ' + t3);
 
-    try {
-        var t4 = ++await 1;
-    } catch(e) {
-        if (e instanceof ReferenceError) {
-            log.push('step 6 ');
-        } 
-    }
-
-    try {
-        var t5 = --await 1;
-    } catch(e) {
-        if (e instanceof ReferenceError) {
-            log.push('step 7');
-        } 
-    }
+    shouldThrowSyntaxError("var t4 = ++await 1;");
+    shouldThrowSyntaxError("var t5 = --await 1;");
 
     return void await 'test';
 };
 log = [];
 
 shouldBeAsync(undefined, () => awaitEpression(5));
-shouldBe("start:5 step 1 step 2 -2 step 3 12345 step 4 -54321 step 5 false step 6  step 7", log.join(" "));
+shouldBe("start:5 step 1 step 2 -2 step 3 12345 step 4 -54321 step 5 false", log.join(" "));
 
 // MethoodDefinition SyntaxErrors
 shouldThrowSyntaxError("var obj = { async foo : true };", "Unexpected token ':'. Expected a parenthesis for argument list.");
index 6c48090..54957e8 100644 (file)
@@ -104,10 +104,4 @@ assertThrowSyntaxError("0xfnn");
 assertThrowSyntaxError("100nn");
 assertThrowSyntaxError("1a0nn");
 assertThrowSyntaxError("10E20n");
-
-try {
-    eval("--10n");
-    assert(false);
-} catch(e) {
-    assert(e instanceof ReferenceError);
-}
+assertThrowSyntaxError("--10n");
index 3fa025f..e37273d 100644 (file)
@@ -1807,7 +1807,7 @@ test/language/arguments-object/mapped/nonconfigurable-nonwritable-descriptors-se
 test/language/arguments-object/mapped/nonconfigurable-nonwritable-descriptors-set-by-param.js:
   default: 'Test262Error: Expected obj[0] to have configurable:false.'
 test/language/asi/S7.9_A5.7_T1.js:
-  default: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: The prefix-increment operator requires a reference expression.'
   strict mode: 'SyntaxError: The prefix-increment operator requires a reference expression.'
 test/language/block-scope/syntax/redeclaration/async-function-name-redeclaration-attempt-with-async-function.js:
   default: 'Test262: This statement should not be evaluated.'
@@ -2060,29 +2060,29 @@ test/language/expressions/assignment/fn-name-lhs-member.js:
   default: 'Test262Error: Expected SameValue(«true», Â«false») to be true'
   strict mode: 'Test262Error: Expected SameValue(«true», Â«false») to be true'
 test/language/expressions/assignment/non-simple-target.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/assignment/target-boolean.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/assignment/target-cover-newtarget.js:
   default: "SyntaxError: new.target can't be the left hand side of an assignment expression."
   strict mode: "SyntaxError: new.target can't be the left hand side of an assignment expression."
 test/language/expressions/assignment/target-cover-yieldexpr.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/assignment/target-newtarget.js:
   default: "SyntaxError: new.target can't be the left hand side of an assignment expression."
   strict mode: "SyntaxError: new.target can't be the left hand side of an assignment expression."
 test/language/expressions/assignment/target-null.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/assignment/target-number.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/assignment/target-string.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/async-arrow-function/await-as-param-ident-nested-arrow-parameter-position.js:
   default: 'Test262: This statement should not be evaluated.'
   strict mode: 'Test262: This statement should not be evaluated.'
@@ -2090,11 +2090,11 @@ test/language/expressions/async-arrow-function/await-as-param-nested-arrow-body-
   default: 'Test262: This statement should not be evaluated.'
   strict mode: 'Test262: This statement should not be evaluated.'
 test/language/expressions/async-function/early-errors-expression-not-simple-assignment-target.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/await/early-errors-await-not-simple-assignment-target.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/call/eval-realm-indirect.js:
   default: 'Test262Error: Expected SameValue(«inside», Â«outside») to be true'
 test/language/expressions/call/eval-spread-empty-leading.js:
@@ -2300,92 +2300,92 @@ test/language/expressions/compound-assignment/S11.13.2_A7.9_T4.js:
   default: 'Test262Error: Expected true but got false'
   strict mode: 'Test262Error: Expected true but got false'
 test/language/expressions/compound-assignment/add-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/btws-and-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/btws-or-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/btws-xor-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/div-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/left-shift-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/mod-div-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/mult-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/right-shift-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/subtract-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/compound-assignment/u-right-shift-non-simple.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/conditional/in-branch-1.js:
   default: "SyntaxError: Unexpected keyword 'in'. Expected ':' in ternary operator."
   strict mode: "SyntaxError: Unexpected keyword 'in'. Expected ':' in ternary operator."
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-1-update-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-10-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-11-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-12-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-13-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-14-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-15-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-16-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-17-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-2-update-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Postfix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Postfix -- operator applied to value that is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-3-update-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-4-update-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-5-lhs-equals-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-6-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-7-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-8-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/dynamic-import/syntax/invalid/invalid-asssignmenttargettype-reference-error-9-lhs-assignment-operator-assignment-expression.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/function/name.js:
   default: 'Test262Error: Expected SameValue(«true», Â«false») to be true'
   strict mode: 'Test262Error: Expected SameValue(«true», Â«false») to be true'
@@ -2477,8 +2477,8 @@ test/language/expressions/postfix-decrement/target-cover-newtarget.js:
   default: "SyntaxError: new.target can't come before a postfix operator."
   strict mode: "SyntaxError: new.target can't come before a postfix operator."
 test/language/expressions/postfix-decrement/target-cover-yieldexpr.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Postfix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Postfix -- operator applied to value that is not a reference.'
 test/language/expressions/postfix-decrement/target-newtarget.js:
   default: "SyntaxError: new.target can't come before a postfix operator."
   strict mode: "SyntaxError: new.target can't come before a postfix operator."
@@ -2500,8 +2500,8 @@ test/language/expressions/postfix-increment/target-cover-newtarget.js:
   default: "SyntaxError: new.target can't come before a postfix operator."
   strict mode: "SyntaxError: new.target can't come before a postfix operator."
 test/language/expressions/postfix-increment/target-cover-yieldexpr.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
 test/language/expressions/postfix-increment/target-newtarget.js:
   default: "SyntaxError: new.target can't come before a postfix operator."
   strict mode: "SyntaxError: new.target can't come before a postfix operator."
@@ -2523,8 +2523,8 @@ test/language/expressions/prefix-decrement/target-cover-newtarget.js:
   default: "SyntaxError: new.target can't come after a prefix operator."
   strict mode: "SyntaxError: new.target can't come after a prefix operator."
 test/language/expressions/prefix-decrement/target-cover-yieldexpr.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
 test/language/expressions/prefix-decrement/target-newtarget.js:
   default: "SyntaxError: new.target can't come after a prefix operator."
   strict mode: "SyntaxError: new.target can't come after a prefix operator."
@@ -2546,8 +2546,8 @@ test/language/expressions/prefix-increment/target-cover-newtarget.js:
   default: "SyntaxError: new.target can't come after a prefix operator."
   strict mode: "SyntaxError: new.target can't come after a prefix operator."
 test/language/expressions/prefix-increment/target-cover-yieldexpr.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
+  strict mode: 'SyntaxError: Prefix -- operator applied to value that is not a reference.'
 test/language/expressions/prefix-increment/target-newtarget.js:
   default: "SyntaxError: new.target can't come after a prefix operator."
   strict mode: "SyntaxError: new.target can't come after a prefix operator."
@@ -2555,8 +2555,8 @@ test/language/expressions/super/call-proto-not-ctor.js:
   default: 'Test262Error: did not perform ArgumentsListEvaluation Expected SameValue(«true», Â«false») to be true'
   strict mode: 'Test262Error: did not perform ArgumentsListEvaluation Expected SameValue(«true», Â«false») to be true'
 test/language/expressions/this/S11.1.1_A1.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/expressions/yield/star-iterable.js:
   default: 'Test262Error: First result `done` flag Expected SameValue(«false», Â«undefined») to be true'
   strict mode: 'Test262Error: First result `done` flag Expected SameValue(«false», Â«undefined») to be true'
@@ -2777,10 +2777,16 @@ test/language/module-code/eval-self-once.js:
   module: "SyntaxError: Unexpected identifier 'as'. Expected 'from' before exported module name."
 test/language/module-code/instn-once.js:
   module: "SyntaxError: Unexpected identifier 'as'. Expected 'from' before exported module name."
+test/language/module-code/instn-resolve-empty-export.js:
+  module: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
+test/language/module-code/instn-resolve-empty-import.js:
+  module: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
+test/language/module-code/instn-resolve-err-reference.js:
+  module: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
 test/language/module-code/instn-resolve-order-depth.js:
   module: "SyntaxError: 'break' is only valid inside a switch or loop statement."
 test/language/module-code/instn-resolve-order-src.js:
-  module: "SyntaxError: 'break' is only valid inside a switch or loop statement."
+  module: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
 test/language/module-code/instn-star-as-props-dflt-skip.js:
   module: "SyntaxError: Unexpected identifier 'as'. Expected 'from' before exported module name."
 test/language/module-code/instn-star-props-nrml.js:
@@ -2800,7 +2806,7 @@ test/language/module-code/parse-err-hoist-lex-fun.js:
 test/language/module-code/parse-err-hoist-lex-gen.js:
   module: 'Test262: This statement should not be evaluated.'
 test/language/module-code/parse-err-reference.js:
-  module: 'Test262: This statement should not be evaluated.'
+  module: 'SyntaxError: Postfix ++ operator applied to value that is not a reference.'
 test/language/statements/class/class-name-ident-await-escaped.js:
   default: "SyntaxError: Unexpected escaped characters in keyword token: 'aw\\u0061it'"
   strict mode: "SyntaxError: Unexpected escaped characters in keyword token: 'aw\\u0061it'"
@@ -3174,17 +3180,17 @@ test/language/statements/while/let-array-with-newline.js:
 test/language/statements/with/let-array-with-newline.js:
   default: 'Test262: This statement should not be evaluated.'
 test/language/types/boolean/S8.3_A2.1.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/types/boolean/S8.3_A2.2.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/types/reference/S8.7.2_A1_T1.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/types/reference/S8.7.2_A1_T2.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
+  default: 'SyntaxError: Left side of assignment is not a reference.'
+  strict mode: 'SyntaxError: Left side of assignment is not a reference.'
 test/language/types/reference/put-value-prop-base-primitive-realm.js:
   default: 'Test262Error: number Expected SameValue(«0», Â«1») to be true'
   strict mode: 'Test262Error: number Expected SameValue(«0», Â«1») to be true'
index 0b6abe6..5386f04 100644 (file)
@@ -1,3 +1,34 @@
+2019-05-16  Ross Kirsling  <ross.kirsling@sony.com>
+
+        [JSC] Invalid AssignmentTargetType should be an early error.
+        https://bugs.webkit.org/show_bug.cgi?id=197603
+
+        Reviewed by Keith Miller.
+
+        * fast/events/window-onerror4-expected.txt:
+        * ietestcenter/Javascript/11.13.1-1-1-expected.txt:
+        * ietestcenter/Javascript/11.13.1-1-2-expected.txt:
+        * ietestcenter/Javascript/11.13.1-1-3-expected.txt:
+        * ietestcenter/Javascript/11.13.1-1-4-expected.txt:
+        * js/basic-strict-mode-expected.txt:
+        * js/dom/assign-expected.txt:
+        * js/dom/line-column-numbers-expected.txt:
+        * js/dom/line-column-numbers.html:
+        * js/dom/postfix-syntax-expected.txt:
+        * js/dom/prefix-syntax-expected.txt:
+        * js/dom/script-tests/line-column-numbers.js:
+        * js/function-toString-parentheses-expected.txt:
+        * js/parser-syntax-check-expected.txt:
+        * js/parser-xml-close-comment-expected.txt:
+        * js/script-tests/function-toString-parentheses.js:
+        * js/script-tests/parser-syntax-check.js:
+        Update tests & expectations to reflect new SyntaxErrors.
+
+        * js/script-tests/toString-prefix-postfix-preserve-parens.js:
+        * js/toString-prefix-postfix-preserve-parens-expected.txt:
+        None of the prefix/postfix tests make sense here now that they're all SyntaxErrors;
+        remove them and just leave the typeof tests.
+
 2019-05-16  Youenn Fablet  <youenn@apple.com>
 
         Layout Test http/wpt/cache-storage/cache-quota-add.any.html is a flaky failure
index 0a49a26..a35b58e 100644 (file)
@@ -1,4 +1,4 @@
 You should see a log record if window.onerror is working properly for this test.Bug 8519.
 
-Error caught successfully: ReferenceError: Left side of assignment is not a reference. File: undefined Line: 1 Column: 3 Error: ReferenceError: Left side of assignment is not a reference.
+Error caught successfully: SyntaxError: Left side of assignment is not a reference. File: window-onerror4.html Line: 16 Column: 9 Error: SyntaxError: Left side of assignment is not a reference.
 
index a37ae34..95b2737 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS ES5Harness.preconditionPassed is true
-PASS ES5Harness.testPassed is true
+FAIL ES5Harness.testPassed should be true (of type boolean). Was undefined (of type undefined).
 PASS successfullyParsed is true
 
 TEST COMPLETE
index eb825b8..be22e41 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS ES5Harness.preconditionPassed is true
-PASS ES5Harness.testPassed is true
+FAIL ES5Harness.testPassed should be true (of type boolean). Was undefined (of type undefined).
 PASS successfullyParsed is true
 
 TEST COMPLETE
index e1e02a5..64fbb02 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS ES5Harness.preconditionPassed is true
-PASS ES5Harness.testPassed is true
+FAIL ES5Harness.testPassed should be true (of type boolean). Was undefined (of type undefined).
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 272f992..7305ee9 100644 (file)
@@ -4,7 +4,7 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
 
 
 PASS ES5Harness.preconditionPassed is true
-PASS ES5Harness.testPassed is true
+FAIL ES5Harness.testPassed should be true (of type boolean). Was undefined (of type undefined).
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 7316ad4..fc33b85 100644 (file)
@@ -133,17 +133,17 @@ PASS (function(){'use strict'; function f() { --arguments }}) threw exception Sy
 PASS 'use strict'; function f() { arguments-- } threw exception SyntaxError: 'arguments' cannot be modified in strict mode..
 PASS (function(){'use strict'; function f() { arguments-- }}) threw exception SyntaxError: 'arguments' cannot be modified in strict mode..
 PASS global.eval('"use strict"; if (0) ++arguments; true;') threw exception SyntaxError: Cannot modify 'arguments' in strict mode..
-PASS 'use strict'; ++(1, eval) threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
+PASS 'use strict'; ++(1, eval) threw exception SyntaxError: Prefix ++ operator applied to value that is not a reference..
 PASS (function(){'use strict'; ++(1, eval)}) threw exception SyntaxError: Cannot modify 'eval' in strict mode..
-PASS 'use strict'; ++(1, 2, 3, eval) threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
+PASS 'use strict'; ++(1, 2, 3, eval) threw exception SyntaxError: Prefix ++ operator applied to value that is not a reference..
 PASS (function(){'use strict'; ++(1, 2, 3, eval)}) threw exception SyntaxError: Cannot modify 'eval' in strict mode..
-PASS 'use strict'; (1, eval)++ threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
+PASS 'use strict'; (1, eval)++ threw exception SyntaxError: Postfix ++ operator applied to value that is not a reference..
 PASS (function(){'use strict'; (1, eval)++}) threw exception SyntaxError: Cannot modify 'eval' in strict mode..
-PASS 'use strict'; --(1, eval) threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
+PASS 'use strict'; --(1, eval) threw exception SyntaxError: Prefix -- operator applied to value that is not a reference..
 PASS (function(){'use strict'; --(1, eval)}) threw exception SyntaxError: Cannot modify 'eval' in strict mode..
-PASS 'use strict'; (1, eval)-- threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
+PASS 'use strict'; (1, eval)-- threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
 PASS (function(){'use strict'; (1, eval)--}) threw exception SyntaxError: 'eval' cannot be modified in strict mode..
-PASS 'use strict'; (1, 2, 3, eval)-- threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
+PASS 'use strict'; (1, 2, 3, eval)-- threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
 PASS (function(){'use strict'; (1, 2, 3, eval)--}) threw exception SyntaxError: 'eval' cannot be modified in strict mode..
 PASS 'use strict'; function f() { ++(1, arguments) } threw exception SyntaxError: Cannot modify 'arguments' in strict mode..
 PASS (function(){'use strict'; function f() { ++(1, arguments) }}) threw exception SyntaxError: Cannot modify 'arguments' in strict mode..
index 27ab287..a215905 100644 (file)
@@ -13,8 +13,8 @@ PASS y, x = 7; x is 7
 PASS ((x)) = 8; x is 8
 PASS ((window.x)) = 9; x is 9
 PASS ((window["x"])) = 10; x is 10
-PASS (y, x) = "FAIL"; threw exception ReferenceError: Left side of assignment is not a reference..
-PASS (true ? x : y) = "FAIL"; threw exception ReferenceError: Left side of assignment is not a reference..
+PASS (y, x) = "FAIL"; threw exception SyntaxError: Left side of assignment is not a reference..
+PASS (true ? x : y) = "FAIL"; threw exception SyntaxError: Left side of assignment is not a reference..
 PASS x++ = "FAIL"; threw exception SyntaxError: Left hand side of operator '=' must be a reference..
 PASS successfullyParsed is true
 
index 7fbd84e..86d065c 100644 (file)
@@ -138,12 +138,12 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     19   g at line-column-numbers.html:190:30
 
 --> Case 21 Stack Trace:
-    0   toFuzz21 at line-column-numbers.html:206:26
-    1   global code at line-column-numbers.html:209:13
+    0   eval at [native code]
+    1   global code at line-column-numbers.html:205:9
 
 --> Case 22 Stack Trace:
-    0   toFuzz22 at line-column-numbers.html:220:36
-    1   global code at line-column-numbers.html:224:13
+    0   toFuzz22 at line-column-numbers.html:221:36
+    1   global code at line-column-numbers.html:225:13
 
 --> Case 1 Stack Trace:
     0   global code at line-column-numbers.js:3:26
@@ -280,12 +280,12 @@ On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE
     19   g at line-column-numbers.js:127:30
 
 --> Case 21 Stack Trace:
-    0   toFuzz21b at line-column-numbers.js:141:26
-    1   global code at line-column-numbers.js:144:14
+    0   eval at [native code]
+    1   global code at line-column-numbers.js:140:9
 
 --> Case 22 Stack Trace:
-    0   toFuzz22b at line-column-numbers.js:153:36
-    1   global code at line-column-numbers.js:157:14
+    0   toFuzz22b at line-column-numbers.js:154:36
+    1   global code at line-column-numbers.js:158:14
 
 PASS successfullyParsed is true
 
index 094a927..f816053 100644 (file)
@@ -202,11 +202,12 @@ try {
 <script>testId++;</script>
 <script>
 try {
-    function toFuzz21() {
-        if (PriorityQueue.prototype.doSort() instanceof (this ^= function() {
-        })) return 2; 
-    }
-    toFuzz21();
+    eval(
+        "function toFuzz21() {\n" +
+        "    if (PriorityQueue.prototype.doSort() instanceof (this ^= function () {})) return 2;\n" +
+        "}\n" +
+        "toFuzz21();"
+    );
 } catch(e) {
     printStack(e.stack);
 }
index 891c4e5..2562f30 100644 (file)
@@ -13,8 +13,8 @@ PASS (y, x++) is 6
 PASS ((x))++ is 7
 PASS ((window.x))++ is 8
 PASS ((window["x"]))++ is 9
-PASS (y, x)++ threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
-PASS (true ? x : y)++ threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
+PASS (y, x)++ threw exception SyntaxError: Postfix ++ operator applied to value that is not a reference..
+PASS (true ? x : y)++ threw exception SyntaxError: Postfix ++ operator applied to value that is not a reference..
 PASS x++++ threw exception SyntaxError: Unexpected token '++'.
 PASS x is 0
 PASS y is 0
index a65672a..837e10a 100644 (file)
@@ -13,9 +13,9 @@ PASS (y, ++x) is 7
 PASS ++((x)) is 8
 PASS ++((window.x)) is 9
 PASS ++((window["x"])) is 10
-PASS ++(y, x) threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS ++(true ? x : y) threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS ++++x threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
+PASS ++(y, x) threw exception SyntaxError: Prefix ++ operator applied to value that is not a reference..
+PASS ++(true ? x : y) threw exception SyntaxError: Prefix ++ operator applied to value that is not a reference..
+PASS ++++x threw exception SyntaxError: The prefix-increment operator requires a reference expression..
 PASS successfullyParsed is true
 
 TEST COMPLETE
index 88119ed..456f0d7 100644 (file)
@@ -137,11 +137,12 @@ try {
 // Case 21: Regression test from https://bugs.webkit.org/show_bug.cgi?id=118662
 testId++;
 try {
-    function toFuzz21b() {
-        if (PriorityQueue.prototype.doSort() instanceof (this ^= function() {
-        })) return 2; 
-    }
-    toFuzz21b();
+    eval(
+        "function toFuzz21() {\n" +
+        "    if (PriorityQueue.prototype.doSort() instanceof (this ^= function () {})) return 2;\n" +
+        "}\n" +
+        "toFuzz21();"
+    );
 } catch(e) {
     printStack(e.stack);
 }
index 9d66640..8f4a088 100644 (file)
@@ -217,7 +217,7 @@ PASS compileAndSerialize('a = b + c') is 'a = b + c'
 PASS compileAndSerialize('(a = b) + c') is '(a = b) + c'
 PASS compileAndSerialize('a = (b + c)') is 'a = (b + c)'
 PASS compileAndSerialize('a + b = c') threw exception SyntaxError: Left hand side of operator '=' must be a reference..
-PASS compileAndSerialize('(a + b) = c') is '(a + b) = c'
+PASS compileAndSerialize('(a + b) = c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b = c)') is 'a + (b = c)'
 PASS compileAndSerialize('a *= b *= c') is 'a *= b *= c'
 PASS compileAndSerialize('(a *= b) *= c') is '(a *= b) *= c'
@@ -229,7 +229,7 @@ PASS compileAndSerialize('a *= b + c') is 'a *= b + c'
 PASS compileAndSerialize('(a *= b) + c') is '(a *= b) + c'
 PASS compileAndSerialize('a *= (b + c)') is 'a *= (b + c)'
 PASS compileAndSerialize('a + b *= c') threw exception SyntaxError: Left hand side of operator '*=' must be a reference..
-PASS compileAndSerialize('(a + b) *= c') is '(a + b) *= c'
+PASS compileAndSerialize('(a + b) *= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b *= c)') is 'a + (b *= c)'
 PASS compileAndSerialize('a /= b /= c') is 'a /= b /= c'
 PASS compileAndSerialize('(a /= b) /= c') is '(a /= b) /= c'
@@ -241,7 +241,7 @@ PASS compileAndSerialize('a /= b + c') is 'a /= b + c'
 PASS compileAndSerialize('(a /= b) + c') is '(a /= b) + c'
 PASS compileAndSerialize('a /= (b + c)') is 'a /= (b + c)'
 PASS compileAndSerialize('a + b /= c') threw exception SyntaxError: Left hand side of operator '/=' must be a reference..
-PASS compileAndSerialize('(a + b) /= c') is '(a + b) /= c'
+PASS compileAndSerialize('(a + b) /= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b /= c)') is 'a + (b /= c)'
 PASS compileAndSerialize('a %= b %= c') is 'a %= b %= c'
 PASS compileAndSerialize('(a %= b) %= c') is '(a %= b) %= c'
@@ -253,7 +253,7 @@ PASS compileAndSerialize('a %= b + c') is 'a %= b + c'
 PASS compileAndSerialize('(a %= b) + c') is '(a %= b) + c'
 PASS compileAndSerialize('a %= (b + c)') is 'a %= (b + c)'
 PASS compileAndSerialize('a + b %= c') threw exception SyntaxError: Left hand side of operator '%=' must be a reference..
-PASS compileAndSerialize('(a + b) %= c') is '(a + b) %= c'
+PASS compileAndSerialize('(a + b) %= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b %= c)') is 'a + (b %= c)'
 PASS compileAndSerialize('a += b += c') is 'a += b += c'
 PASS compileAndSerialize('(a += b) += c') is '(a += b) += c'
@@ -265,7 +265,7 @@ PASS compileAndSerialize('a += b + c') is 'a += b + c'
 PASS compileAndSerialize('(a += b) + c') is '(a += b) + c'
 PASS compileAndSerialize('a += (b + c)') is 'a += (b + c)'
 PASS compileAndSerialize('a + b += c') threw exception SyntaxError: Left hand side of operator '+=' must be a reference..
-PASS compileAndSerialize('(a + b) += c') is '(a + b) += c'
+PASS compileAndSerialize('(a + b) += c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b += c)') is 'a + (b += c)'
 PASS compileAndSerialize('a -= b -= c') is 'a -= b -= c'
 PASS compileAndSerialize('(a -= b) -= c') is '(a -= b) -= c'
@@ -277,7 +277,7 @@ PASS compileAndSerialize('a -= b + c') is 'a -= b + c'
 PASS compileAndSerialize('(a -= b) + c') is '(a -= b) + c'
 PASS compileAndSerialize('a -= (b + c)') is 'a -= (b + c)'
 PASS compileAndSerialize('a + b -= c') threw exception SyntaxError: Left hand side of operator '-=' must be a reference..
-PASS compileAndSerialize('(a + b) -= c') is '(a + b) -= c'
+PASS compileAndSerialize('(a + b) -= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b -= c)') is 'a + (b -= c)'
 PASS compileAndSerialize('a <<= b <<= c') is 'a <<= b <<= c'
 PASS compileAndSerialize('(a <<= b) <<= c') is '(a <<= b) <<= c'
@@ -289,7 +289,7 @@ PASS compileAndSerialize('a <<= b + c') is 'a <<= b + c'
 PASS compileAndSerialize('(a <<= b) + c') is '(a <<= b) + c'
 PASS compileAndSerialize('a <<= (b + c)') is 'a <<= (b + c)'
 PASS compileAndSerialize('a + b <<= c') threw exception SyntaxError: Left hand side of operator '<<=' must be a reference..
-PASS compileAndSerialize('(a + b) <<= c') is '(a + b) <<= c'
+PASS compileAndSerialize('(a + b) <<= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b <<= c)') is 'a + (b <<= c)'
 PASS compileAndSerialize('a >>= b >>= c') is 'a >>= b >>= c'
 PASS compileAndSerialize('(a >>= b) >>= c') is '(a >>= b) >>= c'
@@ -301,7 +301,7 @@ PASS compileAndSerialize('a >>= b + c') is 'a >>= b + c'
 PASS compileAndSerialize('(a >>= b) + c') is '(a >>= b) + c'
 PASS compileAndSerialize('a >>= (b + c)') is 'a >>= (b + c)'
 PASS compileAndSerialize('a + b >>= c') threw exception SyntaxError: Left hand side of operator '>>=' must be a reference..
-PASS compileAndSerialize('(a + b) >>= c') is '(a + b) >>= c'
+PASS compileAndSerialize('(a + b) >>= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b >>= c)') is 'a + (b >>= c)'
 PASS compileAndSerialize('a >>>= b >>>= c') is 'a >>>= b >>>= c'
 PASS compileAndSerialize('(a >>>= b) >>>= c') is '(a >>>= b) >>>= c'
@@ -313,7 +313,7 @@ PASS compileAndSerialize('a >>>= b + c') is 'a >>>= b + c'
 PASS compileAndSerialize('(a >>>= b) + c') is '(a >>>= b) + c'
 PASS compileAndSerialize('a >>>= (b + c)') is 'a >>>= (b + c)'
 PASS compileAndSerialize('a + b >>>= c') threw exception SyntaxError: Left hand side of operator '>>>=' must be a reference..
-PASS compileAndSerialize('(a + b) >>>= c') is '(a + b) >>>= c'
+PASS compileAndSerialize('(a + b) >>>= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b >>>= c)') is 'a + (b >>>= c)'
 PASS compileAndSerialize('a &= b &= c') is 'a &= b &= c'
 PASS compileAndSerialize('(a &= b) &= c') is '(a &= b) &= c'
@@ -325,7 +325,7 @@ PASS compileAndSerialize('a &= b + c') is 'a &= b + c'
 PASS compileAndSerialize('(a &= b) + c') is '(a &= b) + c'
 PASS compileAndSerialize('a &= (b + c)') is 'a &= (b + c)'
 PASS compileAndSerialize('a + b &= c') threw exception SyntaxError: Left hand side of operator '&=' must be a reference..
-PASS compileAndSerialize('(a + b) &= c') is '(a + b) &= c'
+PASS compileAndSerialize('(a + b) &= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b &= c)') is 'a + (b &= c)'
 PASS compileAndSerialize('a ^= b ^= c') is 'a ^= b ^= c'
 PASS compileAndSerialize('(a ^= b) ^= c') is '(a ^= b) ^= c'
@@ -337,7 +337,7 @@ PASS compileAndSerialize('a ^= b + c') is 'a ^= b + c'
 PASS compileAndSerialize('(a ^= b) + c') is '(a ^= b) + c'
 PASS compileAndSerialize('a ^= (b + c)') is 'a ^= (b + c)'
 PASS compileAndSerialize('a + b ^= c') threw exception SyntaxError: Left hand side of operator '^=' must be a reference..
-PASS compileAndSerialize('(a + b) ^= c') is '(a + b) ^= c'
+PASS compileAndSerialize('(a + b) ^= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b ^= c)') is 'a + (b ^= c)'
 PASS compileAndSerialize('a |= b |= c') is 'a |= b |= c'
 PASS compileAndSerialize('(a |= b) |= c') is '(a |= b) |= c'
@@ -349,7 +349,7 @@ PASS compileAndSerialize('a |= b + c') is 'a |= b + c'
 PASS compileAndSerialize('(a |= b) + c') is '(a |= b) + c'
 PASS compileAndSerialize('a |= (b + c)') is 'a |= (b + c)'
 PASS compileAndSerialize('a + b |= c') threw exception SyntaxError: Left hand side of operator '|=' must be a reference..
-PASS compileAndSerialize('(a + b) |= c') is '(a + b) |= c'
+PASS compileAndSerialize('(a + b) |= c') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerialize('a + (b |= c)') is 'a + (b |= c)'
 PASS compileAndSerialize('delete a + b') is 'delete a + b'
 PASS compileAndSerialize('(delete a) + b') is '(delete a) + b'
@@ -368,12 +368,12 @@ PASS compileAndSerialize('!typeof a') is '!typeof a'
 PASS compileAndSerialize('!(typeof a)') is '!(typeof a)'
 PASS compileAndSerialize('++a + b') is '++a + b'
 PASS compileAndSerialize('(++a) + b') is '(++a) + b'
-PASS compileAndSerialize('++(a + b)') is '++(a + b)'
+PASS compileAndSerialize('++(a + b)') threw exception SyntaxError: Prefix ++ operator applied to value that is not a reference..
 PASS compileAndSerialize('!++a') is '!++a'
 PASS compileAndSerialize('!(++a)') is '!(++a)'
 PASS compileAndSerialize('--a + b') is '--a + b'
 PASS compileAndSerialize('(--a) + b') is '(--a) + b'
-PASS compileAndSerialize('--(a + b)') is '--(a + b)'
+PASS compileAndSerialize('--(a + b)') threw exception SyntaxError: Prefix -- operator applied to value that is not a reference..
 PASS compileAndSerialize('!--a') is '!--a'
 PASS compileAndSerialize('!(--a)') is '!(--a)'
 PASS compileAndSerialize('+ a + b') is '+ a + b'
@@ -398,10 +398,10 @@ PASS compileAndSerialize('!!a') is '!!a'
 PASS compileAndSerialize('!(!a)') is '!(!a)'
 PASS compileAndSerialize('!a++') is '!a++'
 PASS compileAndSerialize('!(a++)') is '!(a++)'
-PASS compileAndSerialize('(!a)++') is '(!a)++'
+PASS compileAndSerialize('(!a)++') threw exception SyntaxError: Postfix ++ operator applied to value that is not a reference..
 PASS compileAndSerialize('!a--') is '!a--'
 PASS compileAndSerialize('!(a--)') is '!(a--)'
-PASS compileAndSerialize('(!a)--') is '(!a)--'
+PASS compileAndSerialize('(!a)--') threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
 PASS compileAndSerialize('(-1)[a]') is '(-1)[a]'
 PASS compileAndSerialize('(-1)[a] = b') is '(-1)[a] = b'
 PASS compileAndSerialize('(-1)[a] += b') is '(-1)[a] += b'
@@ -441,42 +441,42 @@ PASS compileAndSerialize('(1).a += b') is '(1).a += b'
 PASS compileAndSerialize('(1).a++') is '(1).a++'
 PASS compileAndSerialize('++(1).a') is '++(1).a'
 PASS compileAndSerialize('(1).a()') is '(1).a()'
-PASS compileAndSerialize('(-1) = a') is '(-1) = a'
-PASS compileAndSerialize('(- 0) = a') is '(- 0) = a'
-PASS compileAndSerialize('1 = a') is '1 = a'
-PASS compileAndSerialize('(-1) *= a') is '(-1) *= a'
-PASS compileAndSerialize('(- 0) *= a') is '(- 0) *= a'
-PASS compileAndSerialize('1 *= a') is '1 *= a'
-PASS compileAndSerialize('(-1) /= a') is '(-1) /= a'
-PASS compileAndSerialize('(- 0) /= a') is '(- 0) /= a'
-PASS compileAndSerialize('1 /= a') is '1 /= a'
-PASS compileAndSerialize('(-1) %= a') is '(-1) %= a'
-PASS compileAndSerialize('(- 0) %= a') is '(- 0) %= a'
-PASS compileAndSerialize('1 %= a') is '1 %= a'
-PASS compileAndSerialize('(-1) += a') is '(-1) += a'
-PASS compileAndSerialize('(- 0) += a') is '(- 0) += a'
-PASS compileAndSerialize('1 += a') is '1 += a'
-PASS compileAndSerialize('(-1) -= a') is '(-1) -= a'
-PASS compileAndSerialize('(- 0) -= a') is '(- 0) -= a'
-PASS compileAndSerialize('1 -= a') is '1 -= a'
-PASS compileAndSerialize('(-1) <<= a') is '(-1) <<= a'
-PASS compileAndSerialize('(- 0) <<= a') is '(- 0) <<= a'
-PASS compileAndSerialize('1 <<= a') is '1 <<= a'
-PASS compileAndSerialize('(-1) >>= a') is '(-1) >>= a'
-PASS compileAndSerialize('(- 0) >>= a') is '(- 0) >>= a'
-PASS compileAndSerialize('1 >>= a') is '1 >>= a'
-PASS compileAndSerialize('(-1) >>>= a') is '(-1) >>>= a'
-PASS compileAndSerialize('(- 0) >>>= a') is '(- 0) >>>= a'
-PASS compileAndSerialize('1 >>>= a') is '1 >>>= a'
-PASS compileAndSerialize('(-1) &= a') is '(-1) &= a'
-PASS compileAndSerialize('(- 0) &= a') is '(- 0) &= a'
-PASS compileAndSerialize('1 &= a') is '1 &= a'
-PASS compileAndSerialize('(-1) ^= a') is '(-1) ^= a'
-PASS compileAndSerialize('(- 0) ^= a') is '(- 0) ^= a'
-PASS compileAndSerialize('1 ^= a') is '1 ^= a'
-PASS compileAndSerialize('(-1) |= a') is '(-1) |= a'
-PASS compileAndSerialize('(- 0) |= a') is '(- 0) |= a'
-PASS compileAndSerialize('1 |= a') is '1 |= a'
+PASS compileAndSerialize('(-1) = a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) = a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 = a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) *= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) *= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 *= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) /= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) /= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 /= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) %= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) %= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 %= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) += a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) += a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 += a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) -= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) -= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 -= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) <<= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) <<= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 <<= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) >>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) >>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 >>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) >>>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) >>>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 >>>= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) &= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) &= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 &= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) ^= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) ^= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 ^= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(-1) |= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('(- 0) |= a') threw exception SyntaxError: Left side of assignment is not a reference..
+PASS compileAndSerialize('1 |= a') threw exception SyntaxError: Left side of assignment is not a reference..
 PASS compileAndSerializeLeftmostTest('({ }).x') is '({ }).x'
 PASS compileAndSerializeLeftmostTest('x = { }') is 'x = { }'
 PASS compileAndSerializeLeftmostTest('(function () { })()') is '(function () { })()'
index 12f08f5..d1a44c5 100644 (file)
@@ -24,32 +24,32 @@ PASS Invalid: "new -a". Produced the following syntax error: "SyntaxError: Unexp
 PASS Invalid: "function f() { new -a }". Produced the following syntax error: "SyntaxError: Unexpected token '-'"
 PASS Valid:   "new (-1)" with TypeError
 PASS Valid:   "function f() { new (-1) }"
-PASS Valid:   "a: b: c: new f(x++)++" with ReferenceError
-PASS Valid:   "function f() { a: b: c: new f(x++)++ }"
+PASS Invalid: "a: b: c: new f(x++)++". Produced the following syntax error: "SyntaxError: Postfix ++ operator applied to value that is not a reference."
+PASS Invalid: "function f() { a: b: c: new f(x++)++ }". Produced the following syntax error: "SyntaxError: Postfix ++ operator applied to value that is not a reference."
 PASS Valid:   "(a)++" with ReferenceError
 PASS Valid:   "function f() { (a)++ }"
-PASS Valid:   "(1--).x" with ReferenceError
-PASS Valid:   "function f() { (1--).x }"
+PASS Invalid: "(1--).x". Produced the following syntax error: "SyntaxError: Postfix -- operator applied to value that is not a reference."
+PASS Invalid: "function f() { (1--).x }". Produced the following syntax error: "SyntaxError: Postfix -- operator applied to value that is not a reference."
 PASS Invalid: "a-- ++". Produced the following syntax error: "SyntaxError: Unexpected token '++'"
 PASS Invalid: "function f() { a-- ++ }". Produced the following syntax error: "SyntaxError: Unexpected token '++'"
 PASS Invalid: "(a:) --b". Produced the following syntax error: "SyntaxError: Unexpected token ':'. Expected ')' to end a compound expression."
 PASS Invalid: "function f() { (a:) --b }". Produced the following syntax error: "SyntaxError: Unexpected token ':'. Expected ')' to end a compound expression."
-PASS Valid:   "++ -- ++ a" with ReferenceError
-PASS Valid:   "function f() { ++ -- ++ a }"
-PASS Valid:   "++ new new a ++" with ReferenceError
-PASS Valid:   "function f() { ++ new new a ++ }"
+PASS Invalid: "++ -- ++ a". Produced the following syntax error: "SyntaxError: The prefix-increment operator requires a reference expression."
+PASS Invalid: "function f() { ++ -- ++ a }". Produced the following syntax error: "SyntaxError: The prefix-increment operator requires a reference expression."
+PASS Invalid: "++ new new a ++". Produced the following syntax error: "SyntaxError: Prefix ++ operator applied to value that is not a reference."
+PASS Invalid: "function f() { ++ new new a ++ }". Produced the following syntax error: "SyntaxError: Prefix ++ operator applied to value that is not a reference."
 PASS Valid:   "delete void 0"
 PASS Valid:   "function f() { delete void 0 }"
 PASS Invalid: "delete the void". Produced the following syntax error: "SyntaxError: Unexpected keyword 'void'. Parse error."
 PASS Invalid: "function f() { delete the void }". Produced the following syntax error: "SyntaxError: Unexpected keyword 'void'. Parse error."
 PASS Invalid: "(a++". Produced the following syntax error: "SyntaxError: Unexpected end of script"
 PASS Invalid: "function f() { (a++ }". Produced the following syntax error: "SyntaxError: Unexpected token '}'. Expected ')' to end a compound expression."
-PASS Valid:   "++a--" with ReferenceError
-PASS Valid:   "function f() { ++a-- }"
-PASS Valid:   "++((a))--" with ReferenceError
-PASS Valid:   "function f() { ++((a))-- }"
-PASS Valid:   "(a.x++)++" with ReferenceError
-PASS Valid:   "function f() { (a.x++)++ }"
+PASS Invalid: "++a--". Produced the following syntax error: "SyntaxError: The increment operator requires a reference expression."
+PASS Invalid: "function f() { ++a-- }". Produced the following syntax error: "SyntaxError: The increment operator requires a reference expression."
+PASS Invalid: "++((a))--". Produced the following syntax error: "SyntaxError: The increment operator requires a reference expression."
+PASS Invalid: "function f() { ++((a))-- }". Produced the following syntax error: "SyntaxError: The increment operator requires a reference expression."
+PASS Invalid: "(a.x++)++". Produced the following syntax error: "SyntaxError: Postfix ++ operator applied to value that is not a reference."
+PASS Invalid: "function f() { (a.x++)++ }". Produced the following syntax error: "SyntaxError: Postfix ++ operator applied to value that is not a reference."
 PASS Invalid: "1: null". Produced the following syntax error: "SyntaxError: Unexpected token ':'. Parse error."
 PASS Invalid: "function f() { 1: null }". Produced the following syntax error: "SyntaxError: Unexpected token ':'. Parse error."
 PASS Invalid: "+-!~". Produced the following syntax error: "SyntaxError: Unexpected end of script"
@@ -110,16 +110,16 @@ PASS Valid:   "- - true % 5"
 PASS Valid:   "function f() { - - true % 5 }"
 PASS Invalid: "- false = 3". Produced the following syntax error: "SyntaxError: Left hand side of operator '=' must be a reference."
 PASS Invalid: "function f() { - false = 3 }". Produced the following syntax error: "SyntaxError: Left hand side of operator '=' must be a reference."
-PASS Valid:   "a: b: c: (1 + null) = 3" with ReferenceError
-PASS Valid:   "function f() { a: b: c: (1 + null) = 3 }"
+PASS Invalid: "a: b: c: (1 + null) = 3". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { a: b: c: (1 + null) = 3 }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Valid:   "a[2] = b.l += c /= 4 * 7 ^ !6" with ReferenceError
 PASS Valid:   "function f() { a[2] = b.l += c /= 4 * 7 ^ !6 }"
 PASS Invalid: "a + typeof b += c in d". Produced the following syntax error: "SyntaxError: Left hand side of operator '+=' must be a reference."
 PASS Invalid: "function f() { a + typeof b += c in d }". Produced the following syntax error: "SyntaxError: Left hand side of operator '+=' must be a reference."
 PASS Invalid: "typeof a &= typeof b". Produced the following syntax error: "SyntaxError: Left hand side of operator '&=' must be a reference."
 PASS Invalid: "function f() { typeof a &= typeof b }". Produced the following syntax error: "SyntaxError: Left hand side of operator '&=' must be a reference."
-PASS Valid:   "a: ((typeof (a))) >>>= a || b.l && c" with ReferenceError
-PASS Valid:   "function f() { a: ((typeof (a))) >>>= a || b.l && c }"
+PASS Invalid: "a: ((typeof (a))) >>>= a || b.l && c". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { a: ((typeof (a))) >>>= a || b.l && c }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Valid:   "a: b: c[a /= f[a %= b]].l[c[x] = 7] -= a ? b <<= f : g" with ReferenceError
 PASS Valid:   "function f() { a: b: c[a /= f[a %= b]].l[c[x] = 7] -= a ? b <<= f : g }"
 PASS Valid:   "-void+x['y'].l == x.l != 5 - f[7]" with ReferenceError
@@ -127,8 +127,8 @@ PASS Valid:   "function f() { -void+x['y'].l == x.l != 5 - f[7] }"
 Function calls (and new with arguments)
 PASS Valid:   "a()()()" with ReferenceError
 PASS Valid:   "function f() { a()()() }"
-PASS Valid:   "s: l: a[2](4 == 6, 5 = 6)(f[4], 6)" with ReferenceError
-PASS Valid:   "function f() { s: l: a[2](4 == 6, 5 = 6)(f[4], 6) }"
+PASS Invalid: "s: l: a[2](4 == 6, 5 = 6)(f[4], 6)". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { s: l: a[2](4 == 6, 5 = 6)(f[4], 6) }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Valid:   "s: eval(a.apply(), b.call(c[5] - f[7]))" with ReferenceError
 PASS Valid:   "function f() { s: eval(a.apply(), b.call(c[5] - f[7])) }"
 PASS Invalid: "a(". Produced the following syntax error: "SyntaxError: Unexpected end of script"
@@ -357,8 +357,8 @@ PASS Valid:   "const  a = void 7 - typeof 8, b = 8"
 PASS Valid:   "function f() { const  a = void 7 - typeof 8, b = 8 }"
 PASS Invalid: "const a, a, a = void 7 - typeof 8, a = 8". Produced the following syntax error: "SyntaxError: Unexpected token ','. const declared variable 'a' must have an initializer."
 PASS Invalid: "function f() { const a, a, a = void 7 - typeof 8, a = 8 }". Produced the following syntax error: "SyntaxError: Unexpected token ','. const declared variable 'a' must have an initializer."
-PASS Valid:   "const x_x = 6 /= 7 ? e : f" with ReferenceError
-PASS Valid:   "function f() { const x_x = 6 /= 7 ? e : f }"
+PASS Invalid: "const x_x = 6 /= 7 ? e : f". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { const x_x = 6 /= 7 ? e : f }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Invalid: "var a = ?". Produced the following syntax error: "SyntaxError: Unexpected token '?'"
 PASS Invalid: "function f() { var a = ? }". Produced the following syntax error: "SyntaxError: Unexpected token '?'"
 PASS Invalid: "const a = *7". Produced the following syntax error: "SyntaxError: Unexpected token '*'"
@@ -504,8 +504,8 @@ PASS Valid:   "for ((a ? b : c) in c) break" with ReferenceError
 PASS Valid:   "function f() { for ((a ? b : c) in c) break }"
 PASS Valid:   "for (var a in b in c) break" with ReferenceError
 PASS Valid:   "function f() { for (var a in b in c) break }"
-PASS Valid:   "for (var a = 5 += 6 in b) break" with ReferenceError
-PASS Valid:   "function f() { for (var a = 5 += 6 in b) break }"
+PASS Invalid: "for (var a = 5 += 6 in b) break". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { for (var a = 5 += 6 in b) break }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Valid:   "for (var a = foo('should be hit') in b) break" with ReferenceError
 PASS Valid:   "function f() { for (var a = foo('should be hit') in b) break }"
 PASS Invalid: "for (var a += 5 in b) break". Produced the following syntax error: "SyntaxError: Unexpected token '+='. Expected either 'in' or 'of' in enumeration syntax."
@@ -524,8 +524,8 @@ PASS Invalid: "for (var a = (b in c in d) break". Produced the following syntax
 PASS Invalid: "function f() { for (var a = (b in c in d) break }". Produced the following syntax error: "SyntaxError: Unexpected keyword 'break'. Expected either 'in' or 'of' in enumeration syntax."
 PASS Invalid: "for (var (a) in b) { }". Produced the following syntax error: "SyntaxError: Unexpected token '('. Expected a parameter pattern or a ')' in parameter list."
 PASS Invalid: "function f() { for (var (a) in b) { } }". Produced the following syntax error: "SyntaxError: Unexpected token '('. Expected a parameter pattern or a ')' in parameter list."
-PASS Valid:   "for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}" with ReferenceError
-PASS Valid:   "function f() { for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {} }"
+PASS Invalid: "for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}". Produced the following syntax error: "SyntaxError: The decrement operator requires a reference expression."
+PASS Invalid: "function f() { for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {} }". Produced the following syntax error: "SyntaxError: The decrement operator requires a reference expression."
 PASS Invalid: "for (var {a} = 20 in b) { }". Produced the following syntax error: "SyntaxError: Cannot assign to the loop variable inside a for-in loop header."
 PASS Invalid: "function f() { for (var {a} = 20 in b) { } }". Produced the following syntax error: "SyntaxError: Cannot assign to the loop variable inside a for-in loop header."
 PASS Invalid: "for (var {a} = 20 of b) { }". Produced the following syntax error: "SyntaxError: Cannot assign to the loop variable inside a for-of loop header."
@@ -878,8 +878,8 @@ PASS Valid:   "if (0) obj.foo\u03bb; "
 PASS Valid:   "function f() { if (0) obj.foo\u03bb;  }"
 PASS Valid:   "if (0) new a(b+c).d = 5"
 PASS Valid:   "function f() { if (0) new a(b+c).d = 5 }"
-PASS Valid:   "if (0) new a(b+c) = 5"
-PASS Valid:   "function f() { if (0) new a(b+c) = 5 }"
+PASS Invalid: "if (0) new a(b+c) = 5". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { if (0) new a(b+c) = 5 }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Valid:   "([1 || 1].a = 1)"
 PASS Valid:   "function f() { ([1 || 1].a = 1) }"
 PASS Valid:   "({a: 1 || 1}.a = 1)"
@@ -1043,14 +1043,14 @@ PASS Valid:   "({a}=1)()" with TypeError
 PASS Valid:   "function f() { ({a}=1)() }"
 PASS Valid:   "({a:a}=1)()" with TypeError
 PASS Valid:   "function f() { ({a:a}=1)() }"
-PASS Valid:   "({a}=1)=1" with ReferenceError
-PASS Valid:   "function f() { ({a}=1)=1 }"
-PASS Valid:   "({a:a}=1)=1" with ReferenceError
-PASS Valid:   "function f() { ({a:a}=1)=1 }"
-PASS Valid:   "({a}=1=1)" with ReferenceError
-PASS Valid:   "function f() { ({a}=1=1) }"
-PASS Valid:   "({a:a}=1=1)" with ReferenceError
-PASS Valid:   "function f() { ({a:a}=1=1) }"
+PASS Invalid: "({a}=1)=1". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { ({a}=1)=1 }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "({a:a}=1)=1". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { ({a:a}=1)=1 }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "({a}=1=1)". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { ({a}=1=1) }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "({a:a}=1=1)". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
+PASS Invalid: "function f() { ({a:a}=1=1) }". Produced the following syntax error: "SyntaxError: Left side of assignment is not a reference."
 PASS Invalid: "var {x}". Produced the following syntax error: "SyntaxError: Unexpected end of script"
 PASS Invalid: "function f() { var {x} }". Produced the following syntax error: "SyntaxError: Unexpected token '}'. Expected an initializer in destructuring variable declaration."
 PASS Invalid: "var {x, y}". Produced the following syntax error: "SyntaxError: Unexpected end of script"
index 06dfd6c..8ecf14c 100644 (file)
@@ -3,11 +3,11 @@ Test to ensure correct handling of --> as a single line comment when at the begi
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS 'should be a syntax error' --> threw exception SyntaxError: Unexpected end of script.
-PASS /**/ 1--> threw exception SyntaxError: Unexpected end of script.
-PASS /**/ 1 --> threw exception SyntaxError: Unexpected end of script.
-PASS 1 /**/--> threw exception SyntaxError: Unexpected end of script.
-PASS 1 /**/ --> threw exception SyntaxError: Unexpected end of script.
+PASS 'should be a syntax error' --> threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
+PASS /**/ 1--> threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
+PASS /**/ 1 --> threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
+PASS 1 /**/--> threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
+PASS 1 /**/ --> threw exception SyntaxError: Postfix -- operator applied to value that is not a reference..
 PASS 1/*
 */--> is 1
 PASS 1/*
index d648b4e..81ce13f 100644 (file)
@@ -104,7 +104,7 @@ for (i = 0; i < assignmentOperators.length; ++i) {
         testRightAssociativeSame("=", op);
     testLowerFirst(op, "+");
     shouldThrow("compileAndSerialize('a + b " + op + " c')");
-    testKeepParentheses("(a + b) " + op + " c");
+    shouldThrow("compileAndSerialize('(a + b) " + op + " c')");
     testKeepParentheses("a + (b " + op + " c)");
 }
 
@@ -115,7 +115,10 @@ for (i = 0; i < prefixOperators.length; ++i) {
     var op = prefixOperators[i] + prefixOperatorSpace[i];
     testKeepParentheses("" + op + "a + b");
     testOptionalParentheses("(" + op + "a) + b");
-    testKeepParentheses("" + op + "(a + b)");
+    if (prefixOperators[i] !== "++" && prefixOperators[i] !== "--")
+        testKeepParentheses("" + op + "(a + b)");
+    else
+        shouldThrow("compileAndSerialize('" + op + "(a + b)')");
     testKeepParentheses("!" + op + "a");
     testOptionalParentheses("!(" + op + "a)");
 }
@@ -123,11 +126,11 @@ for (i = 0; i < prefixOperators.length; ++i) {
 
 testKeepParentheses("!a++");
 testOptionalParentheses("!(a++)");
-testKeepParentheses("(!a)++");
+shouldThrow("compileAndSerialize('(!a)++')");
 
 testKeepParentheses("!a--");
 testOptionalParentheses("!(a--)");
-testKeepParentheses("(!a)--");
+shouldThrow("compileAndSerialize('(!a)--')");
 
 testKeepParentheses("(-1)[a]");
 testKeepParentheses("(-1)[a] = b");
@@ -182,9 +185,9 @@ testKeepParentheses("(1).a()");
 
 for (i = 0; i < assignmentOperators.length; ++i) {
     var op = assignmentOperators[i];
-    testKeepParentheses("(-1) " + op + " a");
-    testKeepParentheses("(- 0) " + op + " a");
-    testKeepParentheses("1 " + op + " a");
+    shouldThrow("compileAndSerialize('(-1) " + op + " a')");
+    shouldThrow("compileAndSerialize('(- 0) " + op + " a')");
+    shouldThrow("compileAndSerialize('1 " + op + " a')");
 }
 
 shouldBe("compileAndSerializeLeftmostTest('({ }).x')", "'({ }).x'");
index 26a0d13..c49c90b 100644 (file)
@@ -83,19 +83,19 @@ invalid("a.'l'");
 valid  ("a: +~!new a");
 invalid("new -a");
 valid  ("new (-1)")
-valid  ("a: b: c: new f(x++)++")
+invalid("a: b: c: new f(x++)++")
 valid  ("(a)++");
-valid  ("(1--).x");
+invalid("(1--).x");
 invalid("a-- ++");
 invalid("(a:) --b");
-valid  ("++ -- ++ a");
-valid  ("++ new new a ++");
+invalid("++ -- ++ a");
+invalid("++ new new a ++");
 valid  ("delete void 0");
 invalid("delete the void");
 invalid("(a++");
-valid  ("++a--");
-valid  ("++((a))--");
-valid  ("(a.x++)++");
+invalid("++a--");
+invalid("++((a))--");
+invalid("(a.x++)++");
 invalid("1: null");
 invalid("+-!~");
 invalid("+-!~((");
@@ -131,18 +131,18 @@ valid  ("a in b instanceof delete -c");
 invalid("a in instanceof b.l");
 valid  ("- - true % 5");
 invalid("- false = 3");
-valid  ("a: b: c: (1 + null) = 3");
+invalid("a: b: c: (1 + null) = 3");
 valid  ("a[2] = b.l += c /= 4 * 7 ^ !6");
 invalid("a + typeof b += c in d");
 invalid("typeof a &= typeof b");
-valid  ("a: ((typeof (a))) >>>= a || b.l && c");
+invalid("a: ((typeof (a))) >>>= a || b.l && c");
 valid  ("a: b: c[a /= f[a %= b]].l[c[x] = 7] -= a ? b <<= f : g");
 valid  ("-void+x['y'].l == x.l != 5 - f[7]");
 
 debug  ("Function calls (and new with arguments)");
 
 valid  ("a()()()");
-valid  ("s: l: a[2](4 == 6, 5 = 6)(f[4], 6)");
+invalid("s: l: a[2](4 == 6, 5 = 6)(f[4], 6)");
 valid  ("s: eval(a.apply(), b.call(c[5] - f[7]))");
 invalid("a(");
 invalid("a(5");
@@ -268,7 +268,7 @@ invalid("var var = 3");
 valid  ("var varr = 3 in 1");
 valid  ("const  a = void 7 - typeof 8, b = 8");
 invalid("const a, a, a = void 7 - typeof 8, a = 8");
-valid  ("const x_x = 6 /= 7 ? e : f");
+invalid("const x_x = 6 /= 7 ? e : f");
 invalid("var a = ?");
 invalid("const a = *7");
 invalid("var a = :)");
@@ -345,7 +345,7 @@ valid  ("for ((a, b) in c) break");
 invalid("for (a ? b : c in c) break");
 valid  ("for ((a ? b : c) in c) break");
 valid  ("for (var a in b in c) break");
-valid("for (var a = 5 += 6 in b) break");
+invalid("for (var a = 5 += 6 in b) break");
 valid("for (var a = foo('should be hit') in b) break");
 invalid("for (var a += 5 in b) break");
 invalid("for (var a = in b) break");
@@ -355,7 +355,7 @@ invalid("for (var a, b = 8 in b) break");
 valid("for (var a = (b in c) in d) break");
 invalid("for (var a = (b in c in d) break");
 invalid("for (var (a) in b) { }");
-valid  ("for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}");
+invalid("for (var a = 7, b = c < d >= d ; f()[6]++ ; --i()[1]++ ) {}");
 invalid("for (var {a} = 20 in b) { }");
 invalid("for (var {a} = 20 of b) { }");
 invalid("for (var {a} = 20 in b) { }");
@@ -543,7 +543,7 @@ valid("if (0) obj.foo$; ")
 valid("if (0) obj.foo_; ")
 valid("if (0) obj.foo\\u03bb; ")
 valid("if (0) new a(b+c).d = 5");
-valid("if (0) new a(b+c) = 5");
+invalid("if (0) new a(b+c) = 5");
 valid("([1 || 1].a = 1)");
 valid("({a: 1 || 1}.a = 1)");
 
@@ -631,10 +631,10 @@ valid("delete ({a}=1)")
 valid("delete ({a:a}=1)")
 valid("({a}=1)()")
 valid("({a:a}=1)()")
-valid("({a}=1)=1")
-valid("({a:a}=1)=1")
-valid("({a}=1=1)")
-valid("({a:a}=1=1)")
+invalid("({a}=1)=1")
+invalid("({a:a}=1)=1")
+invalid("({a}=1=1)")
+invalid("({a:a}=1=1)")
 invalid("var {x}")
 invalid("var {x, y}")
 invalid("var {x} = 20, {x, y}")
index c923e7d..d294558 100644 (file)
@@ -1,61 +1,7 @@
 description(
-"This test checks that toString() round-trip on a function that has prefix, postfix and typeof operators applied to group expression will not remove the grouping. Also checks that evaluation of such a expression produces run-time exception"
+"This test checks that toString() round-trip on a function that has a typeof operator applied to a group expression will not remove the grouping."
 );
 
-function postfix_should_preserve_parens(x, y, z) {
-    (x, y)++;
-    return y;
-}
-
-function prefix_should_preserve_parens(x, y, z) {
-    ++(x, y);
-    return x;
-
-}
-
-function both_should_preserve_parens(x, y, z) {
-    ++(x, y)--;
-    return x;
-
-}
-
-function postfix_should_preserve_parens_multi(x, y, z) {
-    (((x, y)))--;
-    return x;
-}
-
-function prefix_should_preserve_parens_multi(x, y, z) {
-    --(((x, y)));
-    return x;
-}
-
-function both_should_preserve_parens_multi(x, y, z) {
-    ++(((x, y)))--;
-    return x;
-}
-
-function postfix_should_preserve_parens_multi1(x, y, z) {
-    (((x)), y)--;
-    return x;
-}
-
-function prefix_should_preserve_parens_multi1(x, y, z) {
-    --(((x)), y);
-    return x;
-}
-
-function prefix_should_preserve_parens_multi2(x, y, z) {
-    var z = 0;
-    --(((x), y), z);
-    return x;
-}
-
-function postfix_should_preserve_parens_multi2(x, y, z) {
-    var z = 0;
-    (((x), y) ,z)++;
-    return x;
-}
-
 // if these return a variable (such as y) instead of
 // the result of typeof, this means that the parenthesis
 // got lost somewhere.
@@ -91,17 +37,6 @@ function testToString(fn) {
 
 }
 
-function testToStringAndRTFailure(fn)
-{
-    testToString(fn);
-
-    // check that function call produces run-time exception
-    shouldThrow(""+fn+ "(1, 2, 3);");
-
-    // check that function call produces run-time exception after eval(unevalf)
-    shouldThrow("eval(unevalf("+fn+ "))(1, 2, 3);");
-}
-
 function testToStringAndReturn(fn, p1, p2, retval)
 {
 
@@ -114,17 +49,6 @@ function testToStringAndReturn(fn, p1, p2, retval)
     shouldBe("eval(unevalf("+fn+ "))" + "(" + p1 + ", " + p2 +");", retval);
 }
 
-
-testToStringAndRTFailure("prefix_should_preserve_parens");
-testToStringAndRTFailure("postfix_should_preserve_parens");
-testToStringAndRTFailure("both_should_preserve_parens");
-testToStringAndRTFailure("prefix_should_preserve_parens_multi");
-testToStringAndRTFailure("postfix_should_preserve_parens_multi");
-testToStringAndRTFailure("prefix_should_preserve_parens_multi1");
-testToStringAndRTFailure("postfix_should_preserve_parens_multi1");
-testToStringAndRTFailure("prefix_should_preserve_parens_multi2");
-testToStringAndRTFailure("postfix_should_preserve_parens_multi2");
-
 testToStringAndReturn("typeof_should_preserve_parens", "'a'", 1, "'number'");
 testToStringAndReturn("typeof_should_preserve_parens1", "'a'", 1, "'number'");
 testToStringAndReturn("typeof_should_preserve_parens2", "'a'", 1, "'number'");
index 036fedb..b7e3aa1 100644 (file)
@@ -1,44 +1,8 @@
-This test checks that toString() round-trip on a function that has prefix, postfix and typeof operators applied to group expression will not remove the grouping. Also checks that evaluation of such a expression produces run-time exception
+This test checks that toString() round-trip on a function that has a typeof operator applied to a group expression will not remove the grouping.
 
 On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
 
 
-PASS unevalf(eval(unevalf(prefix_should_preserve_parens))) is unevalf(prefix_should_preserve_parens)
-PASS /.*\(+x\)*, y\)/.test(unevalf(prefix_should_preserve_parens)) is true
-PASS prefix_should_preserve_parens(1, 2, 3); threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS eval(unevalf(prefix_should_preserve_parens))(1, 2, 3); threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(postfix_should_preserve_parens))) is unevalf(postfix_should_preserve_parens)
-PASS /.*\(+x\)*, y\)/.test(unevalf(postfix_should_preserve_parens)) is true
-PASS postfix_should_preserve_parens(1, 2, 3); threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
-PASS eval(unevalf(postfix_should_preserve_parens))(1, 2, 3); threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(both_should_preserve_parens))) is unevalf(both_should_preserve_parens)
-PASS /.*\(+x\)*, y\)/.test(unevalf(both_should_preserve_parens)) is true
-PASS both_should_preserve_parens(1, 2, 3); threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS eval(unevalf(both_should_preserve_parens))(1, 2, 3); threw exception ReferenceError: Prefix ++ operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(prefix_should_preserve_parens_multi))) is unevalf(prefix_should_preserve_parens_multi)
-PASS /.*\(+x\)*, y\)/.test(unevalf(prefix_should_preserve_parens_multi)) is true
-PASS prefix_should_preserve_parens_multi(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS eval(unevalf(prefix_should_preserve_parens_multi))(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(postfix_should_preserve_parens_multi))) is unevalf(postfix_should_preserve_parens_multi)
-PASS /.*\(+x\)*, y\)/.test(unevalf(postfix_should_preserve_parens_multi)) is true
-PASS postfix_should_preserve_parens_multi(1, 2, 3); threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
-PASS eval(unevalf(postfix_should_preserve_parens_multi))(1, 2, 3); threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(prefix_should_preserve_parens_multi1))) is unevalf(prefix_should_preserve_parens_multi1)
-PASS /.*\(+x\)*, y\)/.test(unevalf(prefix_should_preserve_parens_multi1)) is true
-PASS prefix_should_preserve_parens_multi1(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS eval(unevalf(prefix_should_preserve_parens_multi1))(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(postfix_should_preserve_parens_multi1))) is unevalf(postfix_should_preserve_parens_multi1)
-PASS /.*\(+x\)*, y\)/.test(unevalf(postfix_should_preserve_parens_multi1)) is true
-PASS postfix_should_preserve_parens_multi1(1, 2, 3); threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
-PASS eval(unevalf(postfix_should_preserve_parens_multi1))(1, 2, 3); threw exception ReferenceError: Postfix -- operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(prefix_should_preserve_parens_multi2))) is unevalf(prefix_should_preserve_parens_multi2)
-PASS /.*\(+x\)*, y\)/.test(unevalf(prefix_should_preserve_parens_multi2)) is true
-PASS prefix_should_preserve_parens_multi2(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS eval(unevalf(prefix_should_preserve_parens_multi2))(1, 2, 3); threw exception ReferenceError: Prefix -- operator applied to value that is not a reference..
-PASS unevalf(eval(unevalf(postfix_should_preserve_parens_multi2))) is unevalf(postfix_should_preserve_parens_multi2)
-PASS /.*\(+x\)*, y\)/.test(unevalf(postfix_should_preserve_parens_multi2)) is true
-PASS postfix_should_preserve_parens_multi2(1, 2, 3); threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
-PASS eval(unevalf(postfix_should_preserve_parens_multi2))(1, 2, 3); threw exception ReferenceError: Postfix ++ operator applied to value that is not a reference..
 PASS unevalf(eval(unevalf(typeof_should_preserve_parens))) is unevalf(typeof_should_preserve_parens)
 PASS /.*\(+x\)*, y\)/.test(unevalf(typeof_should_preserve_parens)) is true
 PASS typeof_should_preserve_parens('a', 1); is 'number'
index 5b4da47..c550636 100644 (file)
@@ -1,3 +1,50 @@
+2019-05-16  Ross Kirsling  <ross.kirsling@sony.com>
+
+        [JSC] Invalid AssignmentTargetType should be an early error.
+        https://bugs.webkit.org/show_bug.cgi?id=197603
+
+        Reviewed by Keith Miller.
+
+        Since ES6, expressions like 0++, ++0, 0 = 0, and 0 += 0 are all specified as early errors:
+          https://tc39.github.io/ecma262/#sec-update-expressions-static-semantics-early-errors
+          https://tc39.github.io/ecma262/#sec-assignment-operators-static-semantics-early-errors
+
+        We currently throw late ReferenceErrors for these -- let's turn them into early SyntaxErrors.
+        (This is based on the expectation that https://github.com/tc39/ecma262/pull/1527 will be accepted;
+        if that doesn't come to pass, we can subsequently introduce early ReferenceError and revise these.)
+
+        * bytecompiler/NodesCodegen.cpp:
+        (JSC::PostfixNode::emitBytecode): Add an assert for "function call LHS" case.
+        (JSC::PrefixNode::emitBytecode): Add an assert for "function call LHS" case.
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::isLocation): Added.
+        (JSC::ASTBuilder::isAssignmentLocation): Fix misleading parameter name.
+        (JSC::ASTBuilder::isFunctionCall): Added.
+        (JSC::ASTBuilder::makeAssignNode): Add an assert for "function call LHS" case.
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::isLocation): Added.
+        (JSC::SyntaxChecker::isAssignmentLocation): Fix incorrect definition and align with ASTBuilder.
+        (JSC::SyntaxChecker::isFunctionCall): Added.
+        * parser/Nodes.h:
+        (JSC::ExpressionNode::isFunctionCall const): Added.
+        Ensure that the parser can check whether an expression node is a function call.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::isSimpleAssignmentTarget): Added.
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        (JSC::Parser<LexerType>::parseUnaryExpression): See below.
+        * parser/Parser.h:
+        Throw SyntaxError whenever an assignment or update expression's target is invalid.
+        Unfortunately, it seems that web compatibility obliges us to exempt the "function call LHS" case in sloppy mode.
+        (https://github.com/tc39/ecma262/issues/257#issuecomment-195106880)
+
+        Additional cleanup items:
+          - Make use of `semanticFailIfTrue` for `isMetaProperty` checks, as it's equivalent.
+          - Rename `requiresLExpr` to `hasPrefixUpdateOp` since it's now confusing,
+            and get rid of `modifiesExpr` since it refers to the exact same condition.
+          - Stop setting `lastOperator` near the end -- one case was incorrect and regardless neither is used.
+
 2019-05-15  Saam Barati  <sbarati@apple.com>
 
         Bound liveness of SetArgumentMaybe nodes when maximal flush insertion phase is enabled
index 21301da..629d416 100644 (file)
@@ -1666,6 +1666,7 @@ RegisterID* PostfixNode::emitBytecode(BytecodeGenerator& generator, RegisterID*
     if (m_expr->isDotAccessorNode())
         return emitDot(generator, dst);
 
+    ASSERT(m_expr->isFunctionCall());
     return emitThrowReferenceError(generator, m_operator == OpPlusPlus
         ? "Postfix ++ operator applied to value that is not a reference."_s
         : "Postfix -- operator applied to value that is not a reference."_s);
@@ -1879,6 +1880,7 @@ RegisterID* PrefixNode::emitBytecode(BytecodeGenerator& generator, RegisterID* d
     if (m_expr->isDotAccessorNode())
         return emitDot(generator, dst);
 
+    ASSERT(m_expr->isFunctionCall());
     return emitThrowReferenceError(generator, m_operator == OpPlusPlus
         ? "Prefix ++ operator applied to value that is not a reference."_s
         : "Prefix -- operator applied to value that is not a reference."_s);
index e321221..dc878c5 100644 (file)
@@ -627,9 +627,14 @@ public:
         return pattern->isBindingNode();
     }
 
-    bool isAssignmentLocation(const Expression& pattern)
+    bool isLocation(const Expression& node)
     {
-        return pattern->isAssignmentLocation();
+        return node->isLocation();
+    }
+
+    bool isAssignmentLocation(const Expression& node)
+    {
+        return node->isAssignmentLocation();
     }
 
     bool isObjectLiteral(const Expression& node)
@@ -647,6 +652,11 @@ public:
         return isObjectLiteral(node) || isArrayLiteral(node);
     }
 
+    bool isFunctionCall(const Expression& node)
+    {
+        return node->isFunctionCall();
+    }
+
     bool shouldSkipPauseLocation(StatementNode* statement) const
     {
         return !statement || statement->isLabel();
@@ -1467,8 +1477,10 @@ ExpressionNode* ASTBuilder::makeBinaryNode(const JSTokenLocation& location, int
 
 ExpressionNode* ASTBuilder::makeAssignNode(const JSTokenLocation& location, ExpressionNode* loc, Operator op, ExpressionNode* expr, bool locHasAssignments, bool exprHasAssignments, const JSTextPosition& start, const JSTextPosition& divot, const JSTextPosition& end)
 {
-    if (!loc->isLocation())
+    if (!loc->isLocation()) {
+        ASSERT(loc->isFunctionCall());
         return new (m_parserArena) AssignErrorNode(location, divot, start, end);
+    }
 
     if (loc->isResolveNode()) {
         ResolveNode* resolve = static_cast<ResolveNode*>(loc);
index 728f736..60ba5ee 100644 (file)
@@ -204,6 +204,7 @@ namespace JSC {
         virtual bool isImportMeta() const { return false; }
         virtual bool isBytecodeIntrinsicNode() const { return false; }
         virtual bool isBinaryOpNode() const { return false; }
+        virtual bool isFunctionCall() const { return false; }
 
         virtual void emitBytecodeInConditionContext(BytecodeGenerator&, Label&, Label&, FallThroughMode);
 
@@ -869,6 +870,8 @@ namespace JSC {
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool isFunctionCall() const override { return true; }
+
         ArgumentsNode* m_args;
     };
 
@@ -879,6 +882,8 @@ namespace JSC {
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool isFunctionCall() const override { return true; }
+
         ExpressionNode* m_expr;
         ArgumentsNode* m_args;
     };
@@ -890,6 +895,8 @@ namespace JSC {
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool isFunctionCall() const override { return true; }
+
         const Identifier& m_ident;
         ArgumentsNode* m_args;
     };
@@ -901,6 +908,8 @@ namespace JSC {
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool isFunctionCall() const override { return true; }
+
         ExpressionNode* m_base;
         ExpressionNode* m_subscript;
         ArgumentsNode* m_args;
@@ -915,6 +924,8 @@ namespace JSC {
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
     protected:
+        bool isFunctionCall() const override { return true; }
+
         ExpressionNode* m_base;
         const Identifier& m_ident;
         ArgumentsNode* m_args;
@@ -945,6 +956,8 @@ namespace JSC {
     private:
         RegisterID* emitBytecode(BytecodeGenerator&, RegisterID* = 0) override;
 
+        bool isFunctionCall() const override { return m_type == Type::Function; }
+
         EmitterType m_emitter;
         const Identifier& m_ident;
         ArgumentsNode* m_args;
index a3b851c..45ac908 100644 (file)
@@ -3631,6 +3631,14 @@ template <typename TreeBuilder> NEVER_INLINE const char* Parser<LexerType>::meta
     RELEASE_ASSERT_NOT_REACHED();
     return "error";
 }
+
+template <typename LexerType>
+template <typename TreeBuilder> bool Parser<LexerType>::isSimpleAssignmentTarget(TreeBuilder& context, TreeExpression expr)
+{
+    // Web compatibility concerns prevent us from handling a function call LHS as an early error in sloppy mode.
+    // This behavior is currently unspecified, but see: https://github.com/tc39/ecma262/issues/257#issuecomment-195106880
+    return context.isLocation(expr) || (!strictMode() && context.isFunctionCall(expr));
+}
     
 template <typename LexerType>
 template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmentExpression(TreeBuilder& context, ExpressionErrorClassifier& classifier)
@@ -3737,8 +3745,8 @@ template <typename TreeBuilder> TreeExpression Parser<LexerType>::parseAssignmen
         }
         m_parserState.nonTrivialExpressionCount++;
         hadAssignment = true;
-        if (UNLIKELY(context.isMetaProperty(lhs)))
-            internalFailWithMessage(false, metaPropertyName(context, lhs), " can't be the left hand side of an assignment expression");
+        semanticFailIfTrue(context.isMetaProperty(lhs), metaPropertyName(context, lhs), " can't be the left hand side of an assignment expression");
+        semanticFailIfFalse(isSimpleAssignmentTarget(context, lhs), "Left side of assignment is not a reference");
         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
         start = tokenStartPosition();
         m_parserState.assignmentCount++;
@@ -4929,8 +4937,7 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress
     typename TreeBuilder::UnaryExprContext unaryExprContext(context);
     AllowInOverride allowInOverride(this);
     int tokenStackDepth = 0;
-    bool modifiesExpr = false;
-    bool requiresLExpr = false;
+    bool hasPrefixUpdateOp = false;
     unsigned lastOperator = 0;
 
     if (UNLIKELY(match(AWAIT) && currentFunctionScope()->isAsyncFunctionBoundary()))
@@ -4939,20 +4946,17 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress
     JSTokenLocation location(tokenLocation());
 
     while (isUnaryOp(m_token.m_type)) {
-        if (strictMode()) {
-            switch (m_token.m_type) {
-            case PLUSPLUS:
-            case MINUSMINUS:
-            case AUTOPLUSPLUS:
-            case AUTOMINUSMINUS:
-                semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
-                modifiesExpr = true;
-                requiresLExpr = true;
-                break;
-            default:
-                semanticFailIfTrue(requiresLExpr, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
-                break;
-            }
+        switch (m_token.m_type) {
+        case PLUSPLUS:
+        case MINUSMINUS:
+        case AUTOPLUSPLUS:
+        case AUTOMINUSMINUS:
+            semanticFailIfTrue(hasPrefixUpdateOp, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
+            hasPrefixUpdateOp = true;
+            break;
+        default:
+            semanticFailIfTrue(hasPrefixUpdateOp, "The ", operatorString(true, lastOperator), " operator requires a reference expression");
+            break;
         }
         lastOperator = m_token.m_type;
         m_parserState.nonLHSCount++;
@@ -4968,37 +4972,37 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress
             failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
         failWithMessage("Cannot parse member expression");
     }
-    if (UNLIKELY(isUpdateOp(static_cast<JSTokenType>(lastOperator)) && context.isMetaProperty(expr)))
-        internalFailWithMessage(false, metaPropertyName(context, expr), " can't come after a prefix operator");
+    if (isUpdateOp(static_cast<JSTokenType>(lastOperator))) {
+        semanticFailIfTrue(context.isMetaProperty(expr), metaPropertyName(context, expr), " can't come after a prefix operator");
+        semanticFailIfFalse(isSimpleAssignmentTarget(context, expr), "Prefix ", lastOperator == PLUSPLUS ? "++" : "--", " operator applied to value that is not a reference");
+    }
     bool isEvalOrArguments = false;
     if (strictMode()) {
         if (context.isResolve(expr))
             isEvalOrArguments = *m_parserState.lastIdentifier == m_vm->propertyNames->eval || *m_parserState.lastIdentifier == m_vm->propertyNames->arguments;
     }
-    failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
+    failIfTrueIfStrict(isEvalOrArguments && hasPrefixUpdateOp, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
     switch (m_token.m_type) {
     case PLUSPLUS:
-        if (UNLIKELY(context.isMetaProperty(expr)))
-            internalFailWithMessage(false, metaPropertyName(context, expr), " can't come before a postfix operator");
+        semanticFailIfTrue(context.isMetaProperty(expr), metaPropertyName(context, expr), " can't come before a postfix operator");
+        semanticFailIfFalse(isSimpleAssignmentTarget(context, expr), "Postfix ++ operator applied to value that is not a reference");
         m_parserState.nonTrivialExpressionCount++;
         m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
         m_parserState.assignmentCount++;
         failIfTrueIfStrict(isEvalOrArguments, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
-        semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
-        lastOperator = PLUSPLUS;
+        semanticFailIfTrue(hasPrefixUpdateOp, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
         next();
         break;
     case MINUSMINUS:
-        if (UNLIKELY(context.isMetaProperty(expr)))
-            internalFailWithMessage(false, metaPropertyName(context, expr), " can't come before a postfix operator");
+        semanticFailIfTrue(context.isMetaProperty(expr), metaPropertyName(context, expr), " can't come before a postfix operator");
+        semanticFailIfFalse(isSimpleAssignmentTarget(context, expr), "Postfix -- operator applied to value that is not a reference");
         m_parserState.nonTrivialExpressionCount++;
         m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
         m_parserState.assignmentCount++;
         failIfTrueIfStrict(isEvalOrArguments, "'", m_parserState.lastIdentifier->impl(), "' cannot be modified in strict mode");
-        semanticFailIfTrue(requiresLExpr, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
-        lastOperator = PLUSPLUS;
+        semanticFailIfTrue(hasPrefixUpdateOp, "The ", operatorString(false, lastOperator), " operator requires a reference expression");
         next();
         break;
     default:
@@ -5006,10 +5010,6 @@ template <class TreeBuilder> TreeExpression Parser<LexerType>::parseUnaryExpress
     }
     
     JSTextPosition end = lastTokenEndPosition();
-
-    if (!TreeBuilder::CreatesAST && (!strictMode()))
-        return expr;
-
     while (tokenStackDepth) {
         switch (context.unaryTokenStackLastType(tokenStackDepth)) {
         case EXCLAMATION:
index 8158993..10a3121 100644 (file)
@@ -1665,6 +1665,8 @@ private:
 
     template <class TreeBuilder> NEVER_INLINE const char* metaPropertyName(TreeBuilder&, TreeExpression);
 
+    template <class TreeBuilder> ALWAYS_INLINE bool isSimpleAssignmentTarget(TreeBuilder&, TreeExpression);
+
     ALWAYS_INLINE int isBinaryOperator(JSTokenType);
     bool allowAutomaticSemicolon();
     
index 97cfadb..419958b 100644 (file)
@@ -393,11 +393,16 @@ public:
         return pattern == BindingDestructuring;
     }
 
-    bool isAssignmentLocation(ExpressionType type)
+    bool isLocation(ExpressionType type)
     {
         return type == ResolveExpr || type == DotExpr || type == BracketExpr;
     }
 
+    bool isAssignmentLocation(ExpressionType type)
+    {
+        return isLocation(type) || type == DestructuringAssignment;
+    }
+
     bool isObjectLiteral(ExpressionType type)
     {
         return type == ObjectLiteralExpr;
@@ -413,6 +418,11 @@ public:
         return isObjectLiteral(type) || isArrayLiteral(type);
     }
 
+    bool isFunctionCall(ExpressionType type)
+    {
+        return type == CallExpr;
+    }
+
     bool shouldSkipPauseLocation(int) const { return true; }
 
     void setEndOffset(int, int) { }