-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Optional chaining #6973
base: master
Are you sure you want to change the base?
Optional chaining #6973
Conversation
f4d884a
to
cc54764
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.
I think this looks neater than my version was, though struggling to follow how it handles every branch. What happens if you do a function call in an optional chain does it crash?
(Not going to merge until we have some significant test coverage)
I'm currently working on function calls. Edit: Function call should work now but |
No copy of expression result needed anymore
The jitted code currently crashes at this assertion (causing the test-failures) ChakraCore/lib/Backend/GlobOpt.cpp Line 11384 in 1f6e17c
|
aae4d9f
to
a9a1c70
Compare
b132685
to
9904051
Compare
d8841a9
to
1a46f30
Compare
1a46f30
to
8baa9e6
Compare
5958fb4
to
8c4eddf
Compare
EmitOptionalChainWrapper(pexpr->AsParseNodeUni(), byteCodeGenerator, funcInfo, [&](ParseNode *innerNode) { | ||
EmitDelete(innerNode, innerNode, byteCodeGenerator, funcInfo); | ||
}); | ||
pnode->location = pexpr->location; |
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.
We "copy" the value from the knopOptChain
node to the knopDelete
node
|
||
// emit chain expression | ||
// Every `?.` node will call `EmitNullPropagation` | ||
// `EmitNullPropagation` short-circuits to `skipLabel` in case of a nullish value | ||
emitChainContent(innerNode); | ||
pnodeOptChain->location = innerNode->location; |
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.
Instead of acquiring a tmp I copy the location of pnodeOptChain
to innerNode
(In case the caller has already aquired a tmp)
innerNode->location = pnodeOptChain->location; |
And copy it back after emitting innerNode
(In case the location was NoRegister
and the emission of innerNode
aquired a tmp)
pnodeOptChain->location = innerNode->location; |
default: | ||
{ | ||
Emit(pexpr, byteCodeGenerator, funcInfo, false); | ||
funcInfo->ReleaseLoc(pexpr); | ||
byteCodeGenerator->Writer()->Reg2( | ||
Js::OpCode::Delete_A, funcInfo->AcquireLoc(pnode), pexpr->location); | ||
break; | ||
} |
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.
JavascriptOperators::Delete
does only return true
. Why can't we just emit bytecode to load true
?
Is this because of getter/setter side-effects?
ChakraCore/lib/Runtime/Language/JavascriptOperators.cpp
Lines 534 to 539 in 05790ae
Var JavascriptOperators::Delete(Var var, ScriptContext* scriptContext) | |
{ | |
JIT_HELPER_NOT_REENTRANT_NOLOCK_HEADER(Op_Delete); | |
return scriptContext->GetLibrary()->GetTrue(); | |
JIT_HELPER_END(Op_Delete); | |
} |
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.
Sorry for the delay, I was confused when I first looked at this; it appears this OpCode is used only in this one location in the bytecodeemitter and is for a no_op delete, as far as I can see we could indeed replace it with LdTrue and delete the logic for OpCode:Delete_A and the relevant code paths.
00c00c3
to
55dea9f
Compare
This PR aims to add support for the stage-4 proposal optional-chaining.
It's inspired by the work of @rhuanjl but uses a more hacky approach to parsing.
Goals
ToDo
eval?.('a')
)eval
)delete
this
(a.b)().c
should be equivalent toa.b().c
a?.[++x]
++x
should not be evaluated ifa
isnull
orundefined
a?.3:0
(ternary) astkOptChain
(?.
)tmp
-renaming foreval
resulteval("foo?.()")
oreval("foo?.property")
apply
call optimization?Only triggered for 2 nested
for
loops with assignmentChakraCore/test/loop/loopinversion.js
Lines 60 to 66 in e26c81f
Out of scope
EmitInvoke
(seems unused)Spec: Optional Chains
Fixes #6349