Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tests for optional chaining #2263

Closed
DanielRosenwasser opened this issue Jul 30, 2019 · 15 comments
Closed

Add tests for optional chaining #2263

DanielRosenwasser opened this issue Jul 30, 2019 · 15 comments
Labels

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Jul 30, 2019

Filing an issue to add tests for https://github.com/tc39/proposal-optional-chaining/

Statement List

  • UpdateExpression[Yield, Await]

      • OptionalExpression[Yield, Await]
        • MemberExpression[Yield, Await] (member-expression.js)
          • PrimaryExpression[?Yield, ?Await]
            • this
            • IdentifierReference[?Yield, ?Await]
              • Identifier
            • Literal
            • ArrayLiteral[?Yield, ?Await]
            • ObjectLiteral[?Yield, ?Await]
            • FunctionExpression
            • ClassExpression[?Yield, ?Await]
            • GeneratorExpression
            • AsyncFunctionExpression
            • AsyncGeneratorExpression
            • RegularExpressionLiteral
            • TemplateLiteral[?Yield, ?Await, ~Tagged]
            • CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
          • MemberExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]]
          • MemberExpression[?Yield, ?Await].IdentifierName
          • MemberExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await, +Tagged]
          • SuperProperty[?Yield, ?Await]
          • MetaProperty
          • newMemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await]
        • CallExpression[Yield, Await] (call-expression.js)
          • CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
          • SuperCall[?Yield, ?Await]
          • CallExpression[?Yield, ?Await]Arguments[?Yield, ?Await]
          • CallExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]]
          • CallExpression[?Yield, ?Await].IdentifierName
          • CallExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await, +Tagged]
        • OptionalExpression[Yield, Await]
          • MemberExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
          • CallExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
          • OptionalExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
      • OptionalExpression[no LineTerminator here]++ (invalid) (update-expression.js)
      • OptionalExpression[no LineTerminator here]-- (invalid) (update-expression.js)
      • ++OptionalExpression[?Yield, ?Await] (invalid) (update-expression.js)
      • --OptionalExpression[?Yield, ?]Await] (invalid) (update-expression.js)
  • AssignmentExpression[In, Yield, Await] (assignment-expression.js)

      • ConditionalExpression[?In, ?Yield, ?Await]
      • ArrowFunction[?In, ?Yield, ?Await]
      • AsyncArrowFunction[?In, ?Yield, ?Await]
      • OptionalExpression[Yield?, Await?] = AssignmentExpression[?In, ?Yield, ?Await] (invalid)
      • OptionalExpression AssignmentOperatorAssignmentExpression[?In, ?Yield, ?Await] (invalid)
  • DestructuringAssignmentTarget[Yield, Await] (assignment-expression.js)

    • OptionalExpression[?Yield, ?Await]
  • IterationStatement[Yield, Await, Return]: (iteration-statement.js)

      • doStatement[?Yield, ?Await, ?Return] while(Expression[+In, ?Yield, ?Await]);
      • while(Expression[+In, ?Yield, ?Await]) Statement[?Yield, ?Await, ?Return]
      • for([lookahead ∉ { let [ }]Expression[~In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for(varVariableDeclarationList[~In, ?Yield, ?Await];Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for(LexicalDeclaration[~In, ?Yield, ?Await]Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for([lookahead ∉ { let [ }]LeftHandSideExpression[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(varForBinding[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(ForDeclaration[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for([lookahead ≠ let]LeftHandSideExpression[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(varForBinding[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(ForDeclaration[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
  • ClassHeritage[Yield, Await]: (class-heritage.js)

      • extends OptionalExpression[?Yield, ?Await]

Async Function

  • UpdateExpression[Yield, Await]

      • OptionalExpression[Yield, Await]
        • MemberExpression[Yield, Await] (async-member-expression.js)
          • PrimaryExpression[?Yield, ?Await]
            • this
            • IdentifierReference[?Yield, ?Await]
              • Identifier
              • await Identifier
            • Literal
            • ArrayLiteral[?Yield, ?Await]
            • ObjectLiteral[?Yield, ?Await]
            • FunctionExpression
            • ClassExpression[?Yield, ?Await]
            • GeneratorExpression
            • AsyncFunctionExpression
            • AsyncGeneratorExpression
            • RegularExpressionLiteral
            • TemplateLiteral[?Yield, ?Await, ~Tagged]
            • CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
          • MemberExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]]
          • MemberExpression[?Yield, ?Await].IdentifierName
          • MemberExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await, +Tagged]
          • SuperProperty[?Yield, ?Await]
          • MetaProperty
          • newMemberExpression[?Yield, ?Await]Arguments[?Yield, ?Await]
        • CallExpression[Yield, Await] (async-call-expression.js)
          • CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
          • SuperCall[?Yield, ?Await]
          • CallExpression[?Yield, ?Await]Arguments[?Yield, ?Await]
          • CallExpression[?Yield, ?Await][Expression[+In, ?Yield, ?Await]]
          • CallExpression[?Yield, ?Await].IdentifierName
          • CallExpression[?Yield, ?Await]TemplateLiteral[?Yield, ?Await, +Tagged]
        • OptionalExpression[Yield, Await]
          • MemberExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
          • CallExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
          • OptionalExpression[?Yield, ?Await]OptionalChain[?Yield, ?Await]
      • OptionalExpression[no LineTerminator here]++ (invalid) (async-update-expression.js)
      • OptionalExpression[no LineTerminator here]-- (invalid) (async-update-expression.js)
      • ++OptionalExpression[?Yield, ?Await] (invalid) (async-update-expression.js)
      • --OptionalExpression[?Yield, ?]Await] (invalid) (async-update-expression.js)
  • AssignmentExpression[In, Yield, Await] (async-assignment-expression.js)

      • ConditionalExpression[?In, ?Yield, ?Await]
      • ArrowFunction[?In, ?Yield, ?Await]
      • AsyncArrowFunction[?In, ?Yield, ?Await]
      • OptionalExpression[Yield?, Await?] = AssignmentExpression[?In, ?Yield, ?Await] (invalid)
      • OptionalExpression AssignmentOperatorAssignmentExpression[?In, ?Yield, ?Await] (invalid)
  • DestructuringAssignmentTarget[Yield, Await] (async-assignment-expression.js)

    • OptionalExpression[?Yield, ?Await]
  • IterationStatement[Yield, Await, Return]: (async-iteration-statement.js)

      • doStatement[?Yield, ?Await, ?Return] while(Expression[+In, ?Yield, ?Await]);
      • while(Expression[+In, ?Yield, ?Await]) Statement[?Yield, ?Await, ?Return]
      • for([lookahead ∉ { let [ }]Expression[~In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for(varVariableDeclarationList[~In, ?Yield, ?Await];Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for(LexicalDeclaration[~In, ?Yield, ?Await]Expression[+In, ?Yield, ?Await]opt;Expression[+In, ?Yield, ?Await]opt)Statement[?Yield, ?Await, ?Return]
      • for([lookahead ∉ { let [ }]LeftHandSideExpression[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(varForBinding[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(ForDeclaration[?Yield, ?Await]inExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for([lookahead ≠ let]LeftHandSideExpression[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(varForBinding[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • for(ForDeclaration[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • [+Await]forawait([lookahead ≠ let]LeftHandSideExpression[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • [+Await]forawait(varForBinding[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]
      • [+Await]forawait(ForDeclaration[?Yield, ?Await]ofAssignmentExpression[+In, ?Yield, ?Await])Statement[?Yield, ?Await, ?Return]

Iterator Function

  • UpdateExpression[Yield, Await]

      • OptionalExpression[Yield, Await]
        • MemberExpression[Yield, Await] (iterator-member-expression.js)
          • PrimaryExpression[?Yield, ?Await]
            • this
            • IdentifierReference[?Yield, ?Await]
              • yield Identifier
  • AssignmentExpression[In, Yield, Await] (iterator-assignment-expression.js)

      • [+Yield]YieldExpression[?In, ?Await]
@leobalter
Copy link
Member

We already have an initial PR:

#2212

@leobalter
Copy link
Member

I updated the OT with the checklist contents produced by @bcoe.

@bcoe
Copy link
Contributor

bcoe commented Jul 31, 2019

@leobalter @DanielRosenwasser if we're happy with this check list as a start, I'll put some open source time in this weekend and work my way through a bunch of the cases; I love this sort of work.

@DanielRosenwasser
Copy link
Member Author

Only if you don't view it as an inconvenience - otherwise, I think it'd be awesome if you're up for it 😄

Leo will know more about the contribution process - ways that make it more approachable etc.

@leobalter
Copy link
Member

This checklist is pretty comprehensive and I believe it's a great start. We can add interesting edgy cases along the way as we identify them.

BTW: one edgy case that I discussed with my team this week, based on #2262:

var stored = [];
var x = {
  set y(v) { stored.push(`set y with ${v}`); }
  get y() { stored.push('get y'); }
};
// dstr assignment
[ x?.y = 1 ] = [ 42 ];
assert.sameValue(stored.length, 1);
assert.sameValue(stored[0], 42);

@ljharb
Copy link
Member

ljharb commented Aug 1, 2019

Im confused; why would optional chaining be permitted in a destructuring context?

@leobalter
Copy link
Member

leobalter commented Aug 1, 2019 via email

@leobalter
Copy link
Member

Well, https://tc39.es/proposal-optional-chaining/#sec-static-semantics-static-semantics-isvalidsimpleassignmenttarget

There is an explicit exception for this grammar, so [x.y = 1] = [42] remains valid while [x?.y = 1] = [42] is a parse error. We still need test for that, this is a documented and expected error.

@bcoe
Copy link
Contributor

bcoe commented Aug 12, 2019

it would be good to add tests for the edge-cases demonstrated here:

v8/v8@ceb7bd5#diff-9b0c860cbf7e0482f43ad30124ee9f9bR92

Mainly:

  • super?.foo calls.
  • new?.bar calls.

@bcoe
Copy link
Contributor

bcoe commented Aug 12, 2019

CC: @devsnek 👋 saw you've already done some initial implementation work in V8, awesome 😄

we're gradually fleshing out a thorough set of tests here which you can run against, let me know if you bump into any issues.

@bcoe
Copy link
Contributor

bcoe commented Aug 30, 2019

Just a quick update, I have started work on the async tests for optional chaining (have just been fairly busy with a few other tasks).

@bcoe
Copy link
Contributor

bcoe commented Nov 11, 2019

@DanielRosenwasser @leobalter @rkirsling, it feels like we could still improve coverage for Stage 4 in December. I saw the rollback of #2411, where should we ultimately end up in terms of generated tests vs., hand written tests, is it worth continuing to work down the check-lists we've written up ... alternatively, perhaps we're feeling that we've covered a healthy number of productions?

@leobalter
Copy link
Member

@bcoe would you be able (time-wise) to update the coverage list or flag parts missing in the coverage?

We can make a work effort after that or as you said, define coverage is reasonable enough. WDYT?

@bcoe
Copy link
Contributor

bcoe commented Nov 14, 2019

@leobalter I'll make an effort to put some work into it this weekend, at least summarizing some of the productions we didn't quite hit yet.

I definitely do think we're getting to the point where we have a healthy number of tests, but I think there are some areas we could flesh out more (as an example for and while statements).

@bcoe
Copy link
Contributor

bcoe commented Nov 25, 2019

@leobalter @jridgewell @DanielRosenwasser, I'm feeling pretty good about our initial suite of tests (once we land #2429 which addresses some regressions @jridgewell brought up).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants