Changeset 282968 in webkit


Ignore:
Timestamp:
Sep 23, 2021 10:24:52 AM (10 months ago)
Author:
Ross Kirsling
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/JavaScriptCore:

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

RelationalExpression[In, Yield, Await] :

ShiftExpression?Await
RelationalExpression?Yield, ?Await < ShiftExpression?Await
RelationalExpression?Yield, ?Await > ShiftExpression?Await
RelationalExpression?Yield, ?Await <= ShiftExpression?Await
RelationalExpression?Yield, ?Await >= ShiftExpression?Await
RelationalExpression?Yield, ?Await instanceof ShiftExpression?Await
[+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression?Await
[+In] PrivateIdentifier in ShiftExpression?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.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/JSTests/ChangeLog

    r282925 r282968  
     12021-09-23  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [JSC] Handle syntactic production for `#x in expr` correctly
     4        https://bugs.webkit.org/show_bug.cgi?id=230668
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        * stress/private-in.js: Add tests.
     9        * test262/expectations.yaml: Mark two test cases as passing.
     10
    1112021-09-22  Yusuke Suzuki  <ysuzuki@apple.com>
    212
  • trunk/JSTests/stress/private-in.js

    r281429 r282968  
    11function assert(b) {
    22  if (!b) throw new Error;
     3}
     4
     5function shouldNotThrow(script) {
     6    eval(script);
     7}
     8
     9function shouldThrowSyntaxError(script) {
     10    let error;
     11    try {
     12        eval(script);
     13    } catch (e) {
     14        error = e;
     15    }
     16
     17    if (!(error instanceof SyntaxError))
     18        throw new Error('Expected SyntaxError!');
    319}
    420
     
    6076for (let i = 0; i < 10000; i++)
    6177  test();
     78
     79shouldNotThrow(() => { class C { #x; f() { 0 == #x in {}; } } });
     80shouldNotThrow(() => { class C { #x; f() { 0 != #x in {}; } } });
     81shouldNotThrow(() => { class C { #x; f() { 0 === #x in {}; } } });
     82shouldNotThrow(() => { class C { #x; f() { 0 !== #x in {}; } } });
     83shouldThrowSyntaxError('class C { #x; f() { 0 < #x in {}; } }');
     84shouldThrowSyntaxError('class C { #x; f() { 0 > #x in {}; } }');
     85shouldThrowSyntaxError('class C { #x; f() { 0 <= #x in {}; } }');
     86shouldThrowSyntaxError('class C { #x; f() { 0 >= #x in {}; } }');
     87shouldThrowSyntaxError('class C { #x; f() { 0 instanceof #x in {}; } }');
     88shouldThrowSyntaxError('class C { #x; f() { 0 in #x in {}; } }');
  • trunk/JSTests/test262/expectations.yaml

    r282925 r282968  
    15961596test/language/expressions/generators/scope-param-rest-elem-var-open.js:
    15971597  default: 'Test262Error: Expected SameValue(«outside», «inside») to be true'
    1598 test/language/expressions/in/private-field-in-nested.js:
    1599   default: 'Test262: This statement should not be evaluated.'
    1600   strict mode: 'Test262: This statement should not be evaluated.'
    16011598test/language/expressions/instanceof/prototype-getter-with-primitive.js:
    16021599  default: "Test262Error: getter for 'prototype' called"
  • trunk/Source/JavaScriptCore/ChangeLog

    r282950 r282968  
     12021-09-23  Ross Kirsling  <ross.kirsling@sony.com>
     2
     3        [JSC] Handle syntactic production for `#x in expr` correctly
     4        https://bugs.webkit.org/show_bug.cgi?id=230668
     5
     6        Reviewed by Yusuke Suzuki.
     7
     8        The production for `#x in expr` is easy to get wrong.
     9
     10            RelationalExpression[In, Yield, Await] :
     11                ShiftExpression[?Yield, ?Await]
     12                RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await]
     13                RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await]
     14                RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await]
     15                RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await]
     16                RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await]
     17                [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await]
     18                [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
     19
     20        We were ensuring that a standalone private name `#x` is always followed by operator `in`;
     21        this patch further ensures that that particular `in` can't have its LHS misparsed as a RelationalExpression.
     22
     23        * parser/Parser.cpp:
     24        (JSC::Parser<LexerType>::parseBinaryExpression):
     25        Verify the precedence of the topmost operator on the stack (if any) when parsing standalone `#x`.
     26
    1272021-09-22  Mikhail R. Gadelha  <mikhail@igalia.com>
    228
  • trunk/Source/JavaScriptCore/parser/Parser.cpp

    r281429 r282968  
    42394239    bool hasCoalesceOperator = false;
    42404240
     4241    int previousOperator = 0;
    42414242    while (true) {
    42424243        JSTextPosition exprStart = tokenStartPosition();
     
    42514252            m_seenPrivateNameUseInNonReparsingFunctionMode = true;
    42524253            next();
    4253             semanticFailIfTrue(m_token.m_type != INTOKEN, "Bare private name can only be used as the left-hand side of an `in` expression");
     4254            semanticFailIfTrue(m_token.m_type != INTOKEN || previousOperator >= INTOKEN, "Bare private name can only be used as the left-hand side of an `in` expression");
    42544255            current = context.createPrivateIdentifierNode(location, *ident);
    42554256        } else
     
    43084309        }
    43094310        context.operatorStackAppend(operatorStackDepth, operatorToken, precedence);
     4311        previousOperator = operatorToken;
    43104312    }
    43114313    while (operatorStackDepth) {
Note: See TracChangeset for help on using the changeset viewer.