-
Notifications
You must be signed in to change notification settings - Fork 471
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
feat: adding tests for optional chaining proposal #2212
Conversation
description: > | ||
Static Semantics: IsDestructuring | ||
LeftHandSideExpression: | ||
CallExpression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jridgewell @DanielRosenwasser @rkirsling, I read this rule as stating that destructuring is not supported in an optional chain, I also gathered that this was the outcome of:
tc39/proposal-optional-chaining#74
This test is failing because the current babel implementation supports destructuring.
Am I correct in my reading of this part of the proposal, if so I think we'll want to update the babel implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, it seems that IsDestructuring is only checked from ForIn/OfBodyEvaluation, and I think we're just saying that if you see an OptionalExpression as an LHS, then (just like a CallExpression) that's not an example of destructuring.
So I don't know that there's anything that needs to be tested here—note that this test doesn't actually involve an optional chain at present, and the linked idea about optional destructuring is something that would require additional syntax.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rkirsling I understand, it's the concept of "optional destructuring" that's out of scope, and the proposal was something along the lines of foo?.bar?
; my bad misreading that section of the spec.
I recommend you create a checklist of all the new productions possible by the new syntax rather than having just generic tests. Perhaps, one test here and there might work nice for feature check but there is still a big chunk of missing coverage here. |
@leobalter I fleshed out the issue body, based on your recommendations. Is that looking like what you were picturing, if so, any recommendations for naming conventions of tests? |
28cfd4f
to
c53665b
Compare
test/language/expressions/optional-chaining/early-errors-tail-position-template-string.js
Outdated
Show resolved
Hide resolved
test/language/expressions/optional-chaining/member-expression-optional-chain.js
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a lot of missing parts here even if the checklist seems like a good start.
The tests need to expand the syntactical productions rather than just picking one for each. This also miss other cases with the await and yield positions flagged in here.
Also: chaining the OptionalChain:
OptionalChain: OptionalChain [Expression]
OptionalChain . IdentifierName
OptionalChain Arguments
OptionalChain TemplateLiteral
and mixing these together too.
There is also a need to verify the grammar of the OptionalExpression into parts receiving a LeftHandSideExpression
, like e.g. LeftHandSideExpression AssignmentOperator AssignmentExpression
.
It also needs expansion for cases like
MemberExpression OptionalChain
CallExpression OptionalChain
OptionalExpression OptionalChain
expanding MemberExpression and CallExpression until a fair amount of cases.
I believe this will be a much longer work as it usually is for new syntax features. I'm not sure if we should start so much effort before Stage 3 for this feature as well. I'd rather wait a bit until the proposal finds a better stability.
}; | ||
|
||
// OptionalChain: ?.[Expression] | ||
assert.sameValue(11, arr?.[i + 1]); |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
assert.sameValue(11, arr?.[i + 1]); | ||
|
||
// OptionalChain: ?.IdentifierName | ||
assert.sameValue('hello', obj?.a); |
This comment was marked as outdated.
This comment was marked as outdated.
Sorry, something went wrong.
assert.sameValue('hello', obj?.a); | ||
|
||
// OptionalChain: ?.Arguments | ||
assert.sameValue(30, fn?.(10, 20)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And Arguments need to be expanded to more productions too. There are some cases and templates from the test generation parts that could be reused for these.
assert.sameValue(30, fn?.(10, 20)); | ||
|
||
// OptionalChain: OptionalChain [Expression] | ||
assert.sameValue(12, obj?.arr[i + 1]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once again, double exposition of Expression when you have [Expression][Expression] and all the multi combinations you can get here, same will go for the chain of possible productions.
info: | | ||
optional chain on recursive optional expression | ||
description: > | ||
Left-Hand-Side Expressions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the content for info and description are inverted in the test files.
test/language/expressions/optional-chaining/runtime-semantics-evaluation.js
Show resolved
Hide resolved
const a = {fn() {}}; | ||
|
||
a?.fn | ||
`hello`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not having expanding this to verify
a?.fn`hello`;
in the same line?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was specifically trying to address this section of the spec:
NOTE This production exists in order to prevent automatic semicolon insertion rules (11.9) to be applied to the following code.
... however, by adding a semi-colon to the end of the expression I was failing to actually exercise this behavior, I've split it into another test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for the clarification
|
||
const fn = () => { | ||
return {a: 33}; | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit:
function fn() {
return {a: 33};
}
}; | ||
|
||
assert.sameValue(33, fn()?.a); | ||
assert.sameValue(undefined, fn()?.b?.c); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this need to go to c? Could definitely sport replacing it with a throwing function call, or even ?.a
after ?.b
@leobalter I offered to review the spec text of optional chaining, as part of the entrance criteria for stage 3. Writing tests has been helping me better dive into edge-cases of the proposal, and get a better feel for the specification. I'd love to help see these tests further along, as it's a great learning experience. Would you rather that I close this draft until we've reached stage 3 approval? or is it okay if I continue putting some work into it. |
Closing is not necessary but we won't be able to merge the tests until it reaches stage 3. I'm ok to leave this open, including this new "Draft" option in the PR as a good flag. As I pointed out there is a good chunk of coverage to be done yet. I might wait until Stage 3 for another review, but feel free to ping me for any questions. |
@leobalter I made an effort to enumerate more test cases today, reading through the spec. Let me know if this is looking more like it. https://gist.github.com/bcoe/b0e6ae3f93f8c8b8f8559f4428187f25 Note, I put proposed file-names for the tests to the right of the productions. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are some few changes to let us land this PR. We can work on the extended coverage checklist through follow up PRs.
@@ -0,0 +1,17 @@ | |||
/*--- |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the copyright headers into each file? They are required to part tests correctly in different test runners used to consume Test262.
@@ -0,0 +1,17 @@ | |||
/*--- | |||
esid: pending |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please use esid: prod-OptionalExpression
instead of any pending in the test files.
esid: pending | ||
info: | | ||
optional chain on call expression | ||
description: > |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
invert usage of info and description. Description is the small line, info is the large chunk.
You may keep the block characters info: |
(pipe) and description: >
(greater than)
@leobalter I have a fairly light weekend, I'll make an effort to put in a few hours expanding the cases outlined in the gist. |
Sure! If you can first address the small items in here, I can already land these tests. I've wrote some other tests (related) to #2262 and it's just a very small chunk from the complete coverage. |
7081b52
to
bc393df
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The tests in this PR are correct. I have some follow ups I described in the comments.
|
||
$DONOTEVALUATE(); | ||
|
||
const a = {fn() {}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this can be a simple var a;
. To enable the test, all you need is to have a valid reference for a
.
Static Semantics: Early Errors | ||
OptionalChain: | ||
?.TemplateLiteral | ||
OptionalChain TemplateLiteral |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add the error part: It is a Syntax Error if any code matches this production.
// This production exists in order to prevent automatic semicolon | ||
// insertion rules. | ||
a?.fn | ||
`hello` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For a follow up PR: we are missing tests for the ?.TemplateLiteral
productions:
a?.`hello`
// and
a?.
`hello`
Also verify this is valid syntax:
`foo`?.bar
Static Semantics: Early Errors | ||
OptionalChain: | ||
?.TemplateLiteral | ||
OptionalChain TemplateLiteral |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add the error part: It is a Syntax Error if any code matches this production.
|
||
// CallExpression Arguments | ||
assert.sameValue(33, fn()?.a); | ||
assert.sameValue(undefined, fn()?.b); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
in a follow up PR, we should expand these to other types and checking property existence:
Currently the CallExpression evaluates to:
- An Object with the property
a
Missing:
- The CallExpression evaluates to falsy values
a. false
b. 0
c. ''
d. undefined // different behavior
e. null // same as undefined - CallExpression evaluates to other type values.
a. true
b. 1
c. NaN
d. 'undefined'
e. Symbol - Verify [[Get]] from the returned object properties
This test itself is good enough as a syntax test, these expansions are more useful for further evaluation of the results.
|
||
$DONOTEVALUATE(); | ||
|
||
const a = {fn() {}}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
name can be simplified here as well.
|
||
const nul = null; | ||
const undf = undefined; | ||
assert.sameValue(undefined, nul?.a); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
for a follow up:
var x = 0;
var y = null?.[(function() { x += 1 }())];
// assert value of x to verify if the `[Expression]` has got evaluated
// assert y is undefined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh! you did that in test/language/expressions/optional-chaining/short-circuiting.js
, nice!
|
||
const obj = {}; | ||
|
||
obj?.a = 33; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice!
@leobalter 🎉 I have this PR open on my fork of test262, which I've been adding a more thorough set of grammar productions to. I will make this PR official now that this has landed, and address your comments in it. |
starting to work on a few tests for optional chaining as I read and review the proposal:
Punctuators
Left-Hand-Side Expressions
OptionalExpression:
OptionalChain:
Static Semantics: IsValidSimpleAssignmentTarget