-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Optional chaining #6973
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
base: master
Are you sure you want to change the base?
Optional chaining #6973
Changes from 1 commit
b2f5f1b
8e9abda
2f84eb1
6538ef0
a33799e
caccbc6
2cde756
f833213
d2377a4
6a2c0ec
e3820ec
cc54764
9e11b34
2498b2d
63093df
6e7d935
9369845
ba32362
c8297ec
8baa9e6
8c4eddf
f48dc1b
05790ae
3b5d8d5
a18431e
d96b76b
0abf9c2
a2709e7
8210f62
629cb8a
55dea9f
2aaa1c9
835a4fa
72aac4a
174e7bf
4b61a6f
eaa44b6
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -60,12 +60,13 @@ static void EmitOptionalChainWrapper(ParseNodeUni *pnodeOptChain, ByteCodeGenera | |||||
// Copy values from wrapper to inner expression | ||||||
ParseNodePtr innerNode = pnodeOptChain->pnode1; | ||||||
innerNode->isUsed = pnodeOptChain->isUsed; | ||||||
innerNode->location = funcInfo->AcquireLoc(pnodeOptChain); | ||||||
innerNode->location = pnodeOptChain->location; | ||||||
|
||||||
// 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 commentThe reason will be displayed to describe this comment to others. Learn more. Instead of acquiring a tmp I copy the location of
And copy it back after emitting
|
||||||
|
||||||
Js::ByteCodeLabel doneLabel = Js::Constants::NoRegister; | ||||||
if (pnodeOptChain->isUsed) | ||||||
|
@@ -89,6 +90,7 @@ static void EmitOptionalChainWrapper(ParseNodeUni *pnodeOptChain, ByteCodeGenera | |||||
byteCodeGenerator->Writer()->Reg2(Js::OpCode::Ld_A_ReuseLoc, pnodeOptChain->location, funcInfo->undefinedConstantRegister); | ||||||
byteCodeGenerator->Writer()->MarkLabel(doneLabel); | ||||||
} | ||||||
|
||||||
funcInfo->currentOptionalChainSkipLabel = previousSkipLabel; | ||||||
} | ||||||
|
||||||
|
@@ -11209,6 +11211,81 @@ void TrackGlobalIntAssignments(ParseNodePtr pnode, ByteCodeGenerator * byteCodeG | |||||
} | ||||||
} | ||||||
|
||||||
static void EmitDelete(ParseNode *pnode, ParseNode *pexpr, ByteCodeGenerator *byteCodeGenerator, FuncInfo *funcInfo) { | ||||||
switch (pexpr->nop) | ||||||
{ | ||||||
case knopOptChain: | ||||||
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 commentThe reason will be displayed to describe this comment to others. Learn more. We "copy" the value from the |
||||||
break; | ||||||
case knopName: | ||||||
{ | ||||||
ParseNodeName *pnodeName = pexpr->AsParseNodeName(); | ||||||
if (pnodeName->IsSpecialName()) | ||||||
{ | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdTrue, pnode->location); | ||||||
} | ||||||
else | ||||||
{ | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->EmitPropDelete(pnode->location, pnodeName->sym, pnodeName->pid, funcInfo); | ||||||
} | ||||||
break; | ||||||
} | ||||||
case knopDot: | ||||||
{ | ||||||
ParseNodeBin *pnodeDot = pexpr->AsParseNodeBin(); | ||||||
ParseNode *pnode1 = pnodeDot->pnode1; | ||||||
ParseNode *pnode2 = pnodeDot->pnode2; | ||||||
|
||||||
if (ByteCodeGenerator::IsSuper(pnode1)) | ||||||
{ | ||||||
byteCodeGenerator->Writer()->W1(Js::OpCode::RuntimeReferenceError, SCODE_CODE(JSERR_DeletePropertyWithSuper)); | ||||||
|
||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdUndef, pnode->location); | ||||||
} | ||||||
else | ||||||
{ | ||||||
Emit(pnode1, byteCodeGenerator, funcInfo, false); | ||||||
EmitNullPropagation(pnode1->location, byteCodeGenerator, funcInfo, pnodeDot->isNullPropagating); | ||||||
|
||||||
funcInfo->ReleaseLoc(pnode1); | ||||||
Js::PropertyId propertyId = pnode2->AsParseNodeName()->PropertyIdFromNameNode(); | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Property(Js::OpCode::DeleteFld, pnode->location, pnode1->location, | ||||||
funcInfo->FindOrAddReferencedPropertyId(propertyId), byteCodeGenerator->forceStrictModeForClassComputedPropertyName); | ||||||
} | ||||||
|
||||||
break; | ||||||
} | ||||||
case knopIndex: | ||||||
{ | ||||||
ParseNodeBin *pnodeIndex = pexpr->AsParseNodeBin(); | ||||||
ParseNode *pnode1 = pnodeIndex->pnode1; | ||||||
ParseNode *pnode2 = pnodeIndex->pnode2; | ||||||
|
||||||
EmitBinaryOpnds(pnode1, pnode2, byteCodeGenerator, funcInfo, Js::Constants::NoRegister, pnodeIndex->isNullPropagating); | ||||||
funcInfo->ReleaseLoc(pnode2); | ||||||
funcInfo->ReleaseLoc(pnode1); | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Element(Js::OpCode::DeleteElemI_A, pnode->location, pnode1->location, pnode2->location); | ||||||
break; | ||||||
} | ||||||
default: | ||||||
{ | ||||||
Emit(pexpr, byteCodeGenerator, funcInfo, false); | ||||||
funcInfo->ReleaseLoc(pexpr); | ||||||
byteCodeGenerator->Writer()->Reg2( | ||||||
Js::OpCode::Delete_A, funcInfo->AcquireLoc(pnode), pexpr->location); | ||||||
break; | ||||||
} | ||||||
ShortDevelopment marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
} | ||||||
} | ||||||
|
||||||
void Emit(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, FuncInfo* funcInfo, BOOL fReturnValue, bool isConstructorCall, bool isTopLevel) | ||||||
{ | ||||||
if (pnode == nullptr) | ||||||
|
@@ -11570,63 +11647,7 @@ void Emit(ParseNode* pnode, ByteCodeGenerator* byteCodeGenerator, FuncInfo* func | |||||
{ | ||||||
ParseNode *pexpr = pnode->AsParseNodeUni()->pnode1; | ||||||
byteCodeGenerator->StartStatement(pnode); | ||||||
switch (pexpr->nop) | ||||||
{ | ||||||
case knopName: | ||||||
{ | ||||||
ParseNodeName * pnodeName = pexpr->AsParseNodeName(); | ||||||
if (pnodeName->IsSpecialName()) | ||||||
{ | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdTrue, pnode->location); | ||||||
} | ||||||
else | ||||||
{ | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->EmitPropDelete(pnode->location, pnodeName->sym, pnodeName->pid, funcInfo); | ||||||
} | ||||||
break; | ||||||
} | ||||||
case knopDot: | ||||||
{ | ||||||
if (ByteCodeGenerator::IsSuper(pexpr->AsParseNodeBin()->pnode1)) | ||||||
{ | ||||||
byteCodeGenerator->Writer()->W1(Js::OpCode::RuntimeReferenceError, SCODE_CODE(JSERR_DeletePropertyWithSuper)); | ||||||
|
||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Reg1(Js::OpCode::LdUndef, pnode->location); | ||||||
} | ||||||
else | ||||||
{ | ||||||
Emit(pexpr->AsParseNodeBin()->pnode1, byteCodeGenerator, funcInfo, false); | ||||||
|
||||||
funcInfo->ReleaseLoc(pexpr->AsParseNodeBin()->pnode1); | ||||||
Js::PropertyId propertyId = pexpr->AsParseNodeBin()->pnode2->AsParseNodeName()->PropertyIdFromNameNode(); | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Property(Js::OpCode::DeleteFld, pnode->location, pexpr->AsParseNodeBin()->pnode1->location, | ||||||
funcInfo->FindOrAddReferencedPropertyId(propertyId), byteCodeGenerator->forceStrictModeForClassComputedPropertyName); | ||||||
} | ||||||
|
||||||
break; | ||||||
} | ||||||
case knopIndex: | ||||||
{ | ||||||
EmitBinaryOpnds(pexpr->AsParseNodeBin()->pnode1, pexpr->AsParseNodeBin()->pnode2, byteCodeGenerator, funcInfo); | ||||||
funcInfo->ReleaseLoc(pexpr->AsParseNodeBin()->pnode2); | ||||||
funcInfo->ReleaseLoc(pexpr->AsParseNodeBin()->pnode1); | ||||||
funcInfo->AcquireLoc(pnode); | ||||||
byteCodeGenerator->Writer()->Element(Js::OpCode::DeleteElemI_A, pnode->location, pexpr->AsParseNodeBin()->pnode1->location, pexpr->AsParseNodeBin()->pnode2->location); | ||||||
break; | ||||||
} | ||||||
default: | ||||||
{ | ||||||
Emit(pexpr, byteCodeGenerator, funcInfo, false); | ||||||
funcInfo->ReleaseLoc(pexpr); | ||||||
byteCodeGenerator->Writer()->Reg2( | ||||||
Js::OpCode::Delete_A, funcInfo->AcquireLoc(pnode), pexpr->location); | ||||||
break; | ||||||
} | ||||||
} | ||||||
EmitDelete(pnode, pexpr, byteCodeGenerator, funcInfo); | ||||||
byteCodeGenerator->EndStatement(pnode); | ||||||
break; | ||||||
} | ||||||
|
Uh oh!
There was an error while loading. Please reload this page.