Title: [282968] trunk
Revision
282968
Author
ross.kirsl...@sony.com
Date
2021-09-23 10:24:52 -0700 (Thu, 23 Sep 2021)

Log Message

[JSC] Handle syntactic production for `#x in expr` correctly
https://bugs.webkit.org/show_bug.cgi?id=230668

Reviewed by Yusuke Suzuki.

JSTests:

* stress/private-in.js: Add tests.
* test262/expectations.yaml: Mark two test cases as passing.

Source/_javascript_Core:

The production for `#x in expr` is easy to get wrong.

    RelationalExpression[In, Yield, Await] :
        ShiftExpression[?Yield, ?Await]
        RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await]
        RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await]
        RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await]
        RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await]
        RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await]
        [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await]
        [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]

We were ensuring that a standalone private name `#x` is always followed by operator `in`;
this patch further ensures that that particular `in` can't have its LHS misparsed as a RelationalExpression.

* parser/Parser.cpp:
(JSC::Parser<LexerType>::parseBinaryExpression):
Verify the precedence of the topmost operator on the stack (if any) when parsing standalone `#x`.

Modified Paths

Diff

Modified: trunk/JSTests/ChangeLog (282967 => 282968)


--- trunk/JSTests/ChangeLog	2021-09-23 17:23:39 UTC (rev 282967)
+++ trunk/JSTests/ChangeLog	2021-09-23 17:24:52 UTC (rev 282968)
@@ -1,3 +1,13 @@
+2021-09-23  Ross Kirsling  <ross.kirsl...@sony.com>
+
+        [JSC] Handle syntactic production for `#x in expr` correctly
+        https://bugs.webkit.org/show_bug.cgi?id=230668
+
+        Reviewed by Yusuke Suzuki.
+
+        * stress/private-in.js: Add tests.
+        * test262/expectations.yaml: Mark two test cases as passing.
+
 2021-09-22  Yusuke Suzuki  <ysuz...@apple.com>
 
         [JSC] Filter algorithmic numbering systems from enumeration data

Modified: trunk/JSTests/stress/private-in.js (282967 => 282968)


--- trunk/JSTests/stress/private-in.js	2021-09-23 17:23:39 UTC (rev 282967)
+++ trunk/JSTests/stress/private-in.js	2021-09-23 17:24:52 UTC (rev 282968)
@@ -2,6 +2,22 @@
   if (!b) throw new Error;
 }
 
+function shouldNotThrow(script) {
+    eval(script);
+}
+
+function shouldThrowSyntaxError(script) {
+    let error;
+    try {
+        eval(script);
+    } catch (e) {
+        error = e;
+    }
+
+    if (!(error instanceof SyntaxError))
+        throw new Error('Expected SyntaxError!');
+}
+
 function shouldThrowTypeError(func) {
     let error;
     try {
@@ -59,3 +75,14 @@
 
 for (let i = 0; i < 10000; i++)
   test();
+
+shouldNotThrow(() => { class C { #x; f() { 0 == #x in {}; } } });
+shouldNotThrow(() => { class C { #x; f() { 0 != #x in {}; } } });
+shouldNotThrow(() => { class C { #x; f() { 0 === #x in {}; } } });
+shouldNotThrow(() => { class C { #x; f() { 0 !== #x in {}; } } });
+shouldThrowSyntaxError('class C { #x; f() { 0 < #x in {}; } }');
+shouldThrowSyntaxError('class C { #x; f() { 0 > #x in {}; } }');
+shouldThrowSyntaxError('class C { #x; f() { 0 <= #x in {}; } }');
+shouldThrowSyntaxError('class C { #x; f() { 0 >= #x in {}; } }');
+shouldThrowSyntaxError('class C { #x; f() { 0 instanceof #x in {}; } }');
+shouldThrowSyntaxError('class C { #x; f() { 0 in #x in {}; } }');

Modified: trunk/JSTests/test262/expectations.yaml (282967 => 282968)


--- trunk/JSTests/test262/expectations.yaml	2021-09-23 17:23:39 UTC (rev 282967)
+++ trunk/JSTests/test262/expectations.yaml	2021-09-23 17:24:52 UTC (rev 282968)
@@ -1595,9 +1595,6 @@
   default: 'Test262Error: Expected a SyntaxError to be thrown but no exception was thrown at all'
 test/language/expressions/generators/scope-param-rest-elem-var-open.js:
   default: 'Test262Error: Expected SameValue(«outside», «inside») to be true'
-test/language/expressions/in/private-field-in-nested.js:
-  default: 'Test262: This statement should not be evaluated.'
-  strict mode: 'Test262: This statement should not be evaluated.'
 test/language/expressions/instanceof/prototype-getter-with-primitive.js:
   default: "Test262Error: getter for 'prototype' called"
   strict mode: "Test262Error: getter for 'prototype' called"

Modified: trunk/Source/_javascript_Core/ChangeLog (282967 => 282968)


--- trunk/Source/_javascript_Core/ChangeLog	2021-09-23 17:23:39 UTC (rev 282967)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-09-23 17:24:52 UTC (rev 282968)
@@ -1,3 +1,29 @@
+2021-09-23  Ross Kirsling  <ross.kirsl...@sony.com>
+
+        [JSC] Handle syntactic production for `#x in expr` correctly
+        https://bugs.webkit.org/show_bug.cgi?id=230668
+
+        Reviewed by Yusuke Suzuki.
+
+        The production for `#x in expr` is easy to get wrong.
+
+            RelationalExpression[In, Yield, Await] :
+                ShiftExpression[?Yield, ?Await]
+                RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await]
+                RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await]
+                RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await]
+                RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await]
+                RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await]
+                [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await]
+                [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
+
+        We were ensuring that a standalone private name `#x` is always followed by operator `in`;
+        this patch further ensures that that particular `in` can't have its LHS misparsed as a RelationalExpression.
+
+        * parser/Parser.cpp:
+        (JSC::Parser<LexerType>::parseBinaryExpression):
+        Verify the precedence of the topmost operator on the stack (if any) when parsing standalone `#x`.
+
 2021-09-22  Mikhail R. Gadelha  <mikh...@igalia.com>
 
         Null pointer dereference in JSC::GetByStatus

Modified: trunk/Source/_javascript_Core/parser/Parser.cpp (282967 => 282968)


--- trunk/Source/_javascript_Core/parser/Parser.cpp	2021-09-23 17:23:39 UTC (rev 282967)
+++ trunk/Source/_javascript_Core/parser/Parser.cpp	2021-09-23 17:24:52 UTC (rev 282968)
@@ -4238,6 +4238,7 @@
     bool hasLogicalOperator = false;
     bool hasCoalesceOperator = false;
 
+    int previousOperator = 0;
     while (true) {
         JSTextPosition exprStart = tokenStartPosition();
         int initialAssignments = m_parserState.assignmentCount;
@@ -4250,7 +4251,7 @@
             currentScope()->usePrivateName(*ident);
             m_seenPrivateNameUseInNonReparsingFunctionMode = true;
             next();
-            semanticFailIfTrue(m_token.m_type != INTOKEN, "Bare private name can only be used as the left-hand side of an `in` _expression_");
+            semanticFailIfTrue(m_token.m_type != INTOKEN || previousOperator >= INTOKEN, "Bare private name can only be used as the left-hand side of an `in` _expression_");
             current = context.createPrivateIdentifierNode(location, *ident);
         } else
             current = parseUnaryExpression(context);
@@ -4307,6 +4308,7 @@
             context.operatorStackPop(operatorStackDepth);
         }
         context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
+        previousOperator = operatorToken;
     }
     while (operatorStackDepth) {
         ASSERT(operandStackDepth > 1);
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to