Title: [197947] trunk/Source/_javascript_Core
Revision
197947
Author
[email protected]
Date
2016-03-10 11:41:37 -0800 (Thu, 10 Mar 2016)

Log Message

Assignment to new.target should be an early error
https://bugs.webkit.org/show_bug.cgi?id=151148

Reviewed by Mark Lam.

This patch makes it so that any form of assignment to new.target
is an early syntax error.

* parser/ASTBuilder.h:
(JSC::ASTBuilder::createNewTargetExpr):
(JSC::ASTBuilder::isNewTarget):
(JSC::ASTBuilder::createResolve):
* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseAssignmentExpression):
(JSC::Parser<LexerType>::parseUnaryExpression):
* parser/SyntaxChecker.h:
(JSC::SyntaxChecker::createThisExpr):
(JSC::SyntaxChecker::createSuperExpr):
(JSC::SyntaxChecker::createNewTargetExpr):
(JSC::SyntaxChecker::isNewTarget):
(JSC::SyntaxChecker::createResolve):
(JSC::SyntaxChecker::createObjectLiteral):
* tests/es6.yaml:
* tests/stress/new-target-syntax-errors.js: Added.
(shouldBeSyntaxError):
(shouldNotBeSyntaxError):
* tests/stress/new-target.js:
(Constructor):
(doWeirdThings):
(noAssign): Deleted.
(catch): Deleted.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/_javascript_Core/ChangeLog (197946 => 197947)


--- trunk/Source/_javascript_Core/ChangeLog	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/ChangeLog	2016-03-10 19:41:37 UTC (rev 197947)
@@ -1,3 +1,37 @@
+2016-03-10  Saam barati  <[email protected]>
+
+        Assignment to new.target should be an early error
+        https://bugs.webkit.org/show_bug.cgi?id=151148
+
+        Reviewed by Mark Lam.
+
+        This patch makes it so that any form of assignment to new.target
+        is an early syntax error.
+
+        * parser/ASTBuilder.h:
+        (JSC::ASTBuilder::createNewTargetExpr):
+        (JSC::ASTBuilder::isNewTarget):
+        (JSC::ASTBuilder::createResolve):
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseAssignmentExpression):
+        (JSC::Parser<LexerType>::parseUnaryExpression):
+        * parser/SyntaxChecker.h:
+        (JSC::SyntaxChecker::createThisExpr):
+        (JSC::SyntaxChecker::createSuperExpr):
+        (JSC::SyntaxChecker::createNewTargetExpr):
+        (JSC::SyntaxChecker::isNewTarget):
+        (JSC::SyntaxChecker::createResolve):
+        (JSC::SyntaxChecker::createObjectLiteral):
+        * tests/es6.yaml:
+        * tests/stress/new-target-syntax-errors.js: Added.
+        (shouldBeSyntaxError):
+        (shouldNotBeSyntaxError):
+        * tests/stress/new-target.js:
+        (Constructor):
+        (doWeirdThings):
+        (noAssign): Deleted.
+        (catch): Deleted.
+
 2016-03-08  Skachkov Oleksandr  <[email protected]>
 
         How we load new.target in arrow functions is broken

Modified: trunk/Source/_javascript_Core/parser/ASTBuilder.h (197946 => 197947)


--- trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/parser/ASTBuilder.h	2016-03-10 19:41:37 UTC (rev 197947)
@@ -182,6 +182,7 @@
         usesNewTarget();
         return new (m_parserArena) NewTargetNode(location);
     }
+    NO_RETURN_DUE_TO_CRASH bool isNewTarget(ExpressionNode*) { RELEASE_ASSERT_NOT_REACHED(); }
     ExpressionNode* createResolve(const JSTokenLocation& location, const Identifier& ident, const JSTextPosition& start, const JSTextPosition& end)
     {
         if (m_vm->propertyNames->arguments == ident)

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (197946 => 197947)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2016-03-10 19:41:37 UTC (rev 197947)
@@ -3040,6 +3040,10 @@
         }
         m_parserState.nonTrivialExpressionCount++;
         hadAssignment = true;
+        if (!TreeBuilder::CreatesAST) { // We only need to do this check with the syntax checker.
+            if (UNLIKELY(context.isNewTarget(lhs)))
+                internalFailWithMessage(false, "new.target can't be the left hand side of an assignment _expression_");
+        }
         context.assignmentStackAppend(assignmentStack, lhs, start, tokenStartPosition(), m_parserState.assignmentCount, op);
         start = tokenStartPosition();
         m_parserState.assignmentCount++;
@@ -4005,6 +4009,10 @@
             failWithMessage("Cannot parse subexpression of ", operatorString(true, lastOperator), "operator");
         failWithMessage("Cannot parse member _expression_");
     }
+    if (!TreeBuilder::CreatesAST) { // We only need to do this check with the syntax checker.
+        if (UNLIKELY(lastOperator && context.isNewTarget(expr)))
+            internalFailWithMessage(false, "new.target can't come after a prefix operator");
+    }
     bool isEvalOrArguments = false;
     if (strictMode() && !m_syntaxAlreadyValidated) {
         if (context.isResolve(expr))
@@ -4013,6 +4021,10 @@
     failIfTrueIfStrict(isEvalOrArguments && modifiesExpr, "Cannot modify '", m_parserState.lastIdentifier->impl(), "' in strict mode");
     switch (m_token.m_type) {
     case PLUSPLUS:
+        if (!TreeBuilder::CreatesAST) { // We only need to do this check with the syntax checker.
+            if (UNLIKELY(context.isNewTarget(expr)))
+                internalFailWithMessage(false, "new.target can't come before a postfix operator");
+        }
         m_parserState.nonTrivialExpressionCount++;
         m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpPlusPlus, subExprStart, lastTokenEndPosition(), tokenEndPosition());
@@ -4023,6 +4035,10 @@
         next();
         break;
     case MINUSMINUS:
+        if (!TreeBuilder::CreatesAST) { // We only need to do this check with the syntax checker.
+            if (UNLIKELY(context.isNewTarget(expr)))
+                internalFailWithMessage(false, "new.target can't come before a postfix operator");
+        }
         m_parserState.nonTrivialExpressionCount++;
         m_parserState.nonLHSCount++;
         expr = context.makePostfixNode(location, expr, OpMinusMinus, subExprStart, lastTokenEndPosition(), tokenEndPosition());

Modified: trunk/Source/_javascript_Core/parser/SyntaxChecker.h (197946 => 197947)


--- trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/parser/SyntaxChecker.h	2016-03-10 19:41:37 UTC (rev 197947)
@@ -160,6 +160,7 @@
     ExpressionType createThisExpr(const JSTokenLocation&, ThisTDZMode) { return ThisExpr; }
     ExpressionType createSuperExpr(const JSTokenLocation&) { return SuperExpr; }
     ExpressionType createNewTargetExpr(const JSTokenLocation&) { return NewTargetExpr; }
+    ALWAYS_INLINE bool isNewTarget(ExpressionType type) { return type == NewTargetExpr; }
     ExpressionType createResolve(const JSTokenLocation&, const Identifier&, int, int) { return ResolveExpr; }
     ExpressionType createObjectLiteral(const JSTokenLocation&) { return ObjectLiteralExpr; }
     ExpressionType createObjectLiteral(const JSTokenLocation&, int) { return ObjectLiteralExpr; }

Modified: trunk/Source/_javascript_Core/tests/es6.yaml (197946 => 197947)


--- trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/tests/es6.yaml	2016-03-10 19:41:37 UTC (rev 197947)
@@ -875,7 +875,7 @@
 - path: es6/miscellaneous_RegExp_constructor_can_alter_flags.js
   cmd: runES6 :fail
 - path: es6/new.target_assignment_is_an_early_error.js
-  cmd: runES6 :fail
+  cmd: runES6 :normal
 - path: es6/non-strict_function_semantics_hoisted_block-level_function_declaration.js
   cmd: runES6 :fail
 - path: es6/Promise_is_subclassable_Promise.all.js

Added: trunk/Source/_javascript_Core/tests/stress/new-target-syntax-errors.js (0 => 197947)


--- trunk/Source/_javascript_Core/tests/stress/new-target-syntax-errors.js	                        (rev 0)
+++ trunk/Source/_javascript_Core/tests/stress/new-target-syntax-errors.js	2016-03-10 19:41:37 UTC (rev 197947)
@@ -0,0 +1,86 @@
+function shouldBeSyntaxError(str) {
+    let failed = true;
+    try {
+        new Function(str);
+    } catch(e) {
+        if (e instanceof SyntaxError)
+            failed = false;
+    }
+    
+    if (failed)
+        throw new Error("Did not throw syntax error: " + str);
+}
+
+function shouldNotBeSyntaxError(str) {
+    let failed = false;
+    try {
+        new Function(str);
+    } catch(e) {
+        if (e instanceof SyntaxError && e.message.indexOf("new.target") !== -1)
+            failed = true;
+    }
+    
+    if (failed)
+        throw new Error("Did throw a syntax error: " + str);
+}
+
+
+let operators = ["=", "+=", "-=", "*=", "<<=", ">>=", ">>>=", "&=", "^=", "|=", "%="];
+for (let operator of operators) {
+    let functionBody = `new.target ${operator} 20`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `foo = new.target ${operator} 20`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `foo ${operator} new.target ${operator} 20`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `new.target ${operator} foo *= 40`;
+    shouldBeSyntaxError(functionBody);
+
+
+    // Make sure our tests cases our sound and they should not be syntax errors if new.target is replaced by foo
+    functionBody = `foo ${operator} 20`;
+    shouldNotBeSyntaxError(functionBody);
+
+    functionBody = `foo = foo ${operator} 20`;
+    shouldNotBeSyntaxError(functionBody);
+
+    functionBody = `foo ${operator} foo ${operator} 20`;
+    shouldNotBeSyntaxError(functionBody);
+
+    functionBody = `foo ${operator} foo *= 40`;
+    shouldNotBeSyntaxError(functionBody);
+}
+
+let prePostFixOperators = ["++", "--"];
+for (let operator of prePostFixOperators) {
+    let functionBody = `${operator}new.target`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `foo = ${operator}new.target`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `${operator}foo`;
+    shouldNotBeSyntaxError(functionBody);
+
+    functionBody = `foo = ${operator}foo`;
+    shouldNotBeSyntaxError(functionBody);
+}
+
+for (let operator of prePostFixOperators) {
+    let functionBody = `new.target${operator}`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `foo = new.target${operator}`;
+    shouldBeSyntaxError(functionBody);
+
+    functionBody = `foo${operator}`;
+    shouldNotBeSyntaxError(functionBody);
+
+    functionBody = `foo = foo${operator}`;
+    shouldNotBeSyntaxError(functionBody);
+}
+
+shouldBeSyntaxError(`({foo: new.target} = {foo:20})`);

Modified: trunk/Source/_javascript_Core/tests/stress/new-target.js (197946 => 197947)


--- trunk/Source/_javascript_Core/tests/stress/new-target.js	2016-03-10 19:26:32 UTC (rev 197946)
+++ trunk/Source/_javascript_Core/tests/stress/new-target.js	2016-03-10 19:41:37 UTC (rev 197947)
@@ -33,21 +33,6 @@
 }
 new Constructor();
 
-function noAssign() {
-    new.target = 1;
-}
-
-try {
-    new noAssign();
-    passed = false;
-} catch(e) { }
-try {
-    noAssign();
-    passed = false;
-} catch(e) { }
-
-test(passed, true, "new.target should not be a reference");
-
 // This is mostly to test that calling new on new.target deos the right thing.
 function doWeirdThings(arg) {
     if (new.target) {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to