Skip to content

Commit 133f30a

Browse files
Kevin SmithKevin Smith
authored andcommitted
Add support for optional catch binding syntax
1 parent ff490af commit 133f30a

File tree

9 files changed

+246
-54
lines changed

9 files changed

+246
-54
lines changed

lib/Parser/Parse.cpp

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9751,15 +9751,21 @@ ParseNodeCatch * Parser::ParseCatch()
97519751
ichMin = this->GetScanner()->IchMinTok();
97529752
}
97539753
this->GetScanner()->Scan(); //catch
9754-
ChkCurTok(tkLParen, ERRnoLparen); //catch(
97559754

97569755
bool isPattern = false;
9757-
if (tkID != m_token.tk)
9756+
bool hasParam = false;
9757+
9758+
if (tkLParen == m_token.tk)
97589759
{
9759-
isPattern = IsES6DestructuringEnabled() && IsPossiblePatternStart();
9760-
if (!isPattern)
9760+
hasParam = true;
9761+
this->GetScanner()->Scan(); //catch(
9762+
if (tkID != m_token.tk)
97619763
{
9762-
IdentifierExpectedError(m_token);
9764+
isPattern = IsES6DestructuringEnabled() && IsPossiblePatternStart();
9765+
if (!isPattern)
9766+
{
9767+
IdentifierExpectedError(m_token);
9768+
}
97639769
}
97649770
}
97659771

@@ -9807,7 +9813,7 @@ ParseNodeCatch * Parser::ParseCatch()
98079813
pnode->scope = scope;
98089814
}
98099815
}
9810-
else
9816+
else if (hasParam)
98119817
{
98129818
if (IsStrictMode())
98139819
{
@@ -9851,13 +9857,24 @@ ParseNodeCatch * Parser::ParseCatch()
98519857

98529858
this->GetScanner()->Scan();
98539859
}
9860+
else
9861+
{
9862+
if (buildAST)
9863+
{
9864+
pnode->scope = pnodeCatchScope->scope;
9865+
}
9866+
}
98549867

98559868
charcount_t ichLim;
98569869
if (buildAST)
98579870
{
98589871
ichLim = this->GetScanner()->IchLimTok();
98599872
}
9860-
ChkCurTok(tkRParen, ERRnoRparen); //catch(id[:expr])
9873+
9874+
if (hasParam)
9875+
{
9876+
ChkCurTok(tkRParen, ERRnoRparen); //catch(id[:expr])
9877+
}
98619878

98629879
if (tkLCurly != m_token.tk)
98639880
{
@@ -13878,7 +13895,9 @@ void PrintPnodeWIndent(ParseNode *pnode, int indentAmt) {
1387813895
Output::Print(_u("ComputedProperty\n"));
1387913896
PrintPnodeWIndent(pnode->AsParseNodeUni()->pnode1, indentAmt + INDENT_SIZE);
1388013897
break;
13881-
13898+
case knopParamPattern:
13899+
PrintPnodeWIndent(pnode->AsParseNodeParamPattern()->pnode1, indentAmt);
13900+
break;
1388213901
//PTNODE(knopMember , ":" ,None ,Bin ,fnopBin)
1388313902
case knopMember:
1388413903
case knopMemberShort:
@@ -14159,7 +14178,7 @@ void PrintFormalsWIndent(ParseNode *pnodeArgs, int indentAmt)
1415914178
{
1416014179
for (ParseNode *pnode = pnodeArgs; pnode != nullptr; pnode = pnode->GetFormalNext())
1416114180
{
14162-
PrintPnodeWIndent(pnode->nop == knopParamPattern ? pnode->AsParseNodeParamPattern()->pnode1 : pnode, indentAmt);
14181+
PrintPnodeWIndent(pnode, indentAmt);
1416314182
}
1416414183
}
1416514184

lib/Parser/ptree.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,7 @@ ParseNodeTry::ParseNodeTry(OpCode nop, charcount_t ichMin, charcount_t ichLim)
602602
}
603603

604604
ParseNodeCatch::ParseNodeCatch(OpCode nop, charcount_t ichMin, charcount_t ichLim)
605-
: ParseNodeStmt(nop, ichMin, ichLim)
605+
: ParseNodeStmt(nop, ichMin, ichLim), pnodeParam(nullptr)
606606
{
607607
}
608608

lib/Parser/ptree.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,9 @@ class ParseNodeCatch : public ParseNodeStmt
10361036
public:
10371037
ParseNodeCatch(OpCode nop, charcount_t ichMin, charcount_t ichLim);
10381038

1039+
bool HasPatternParam() { return pnodeParam != nullptr && pnodeParam->nop == knopParamPattern; }
1040+
bool HasParam() { return pnodeParam != nullptr; }
1041+
10391042
ParseNodePtr GetParam() { return pnodeParam; }
10401043
void SetParam(ParseNodeName * pnode) { pnodeParam = pnode; }
10411044
void SetParam(ParseNodeParamPattern * pnode) { pnodeParam = pnode; }

lib/Runtime/ByteCode/ByteCodeEmitter.cpp

Lines changed: 25 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -4014,13 +4014,13 @@ void ByteCodeGenerator::StartEmitCatch(ParseNodeCatch *pnodeCatch)
40144014
scope->SetIsObject();
40154015
}
40164016

4017-
ParseNode * pnodeParam = pnodeCatch->GetParam();
4018-
if (pnodeParam->nop == knopParamPattern)
4017+
if (pnodeCatch->HasPatternParam())
40194018
{
4019+
ParseNode *pnode1 = pnodeCatch->GetParam()->AsParseNodeParamPattern()->pnode1;
40204020
scope->SetCapturesAll(funcInfo->GetCallsEval() || funcInfo->GetChildCallsEval());
40214021
scope->SetMustInstantiate(scope->Count() > 0 && (scope->GetMustInstantiate() || scope->GetCapturesAll() || funcInfo->IsGlobalFunction()));
40224022

4023-
Parser::MapBindIdentifier(pnodeParam->AsParseNodeParamPattern()->pnode1, [&](ParseNodePtr item)
4023+
Parser::MapBindIdentifier(pnode1, [&](ParseNodePtr item)
40244024
{
40254025
Symbol *sym = item->AsParseNodeVar()->sym;
40264026
if (funcInfo->IsGlobalFunction())
@@ -4034,13 +4034,10 @@ void ByteCodeGenerator::StartEmitCatch(ParseNodeCatch *pnodeCatch)
40344034
sym->EnsureScopeSlot(this, funcInfo);
40354035
}
40364036
});
4037-
4038-
// In the case of pattern we will always going to push the scope.
4039-
PushScope(scope);
40404037
}
4041-
else
4038+
else if (pnodeCatch->HasParam())
40424039
{
4043-
Symbol *sym = pnodeParam->AsParseNodeName()->sym;
4040+
Symbol *sym = pnodeCatch->GetParam()->AsParseNodeName()->sym;
40444041

40454042
// Catch object is stored in the catch scope if there may be an ambiguous lookup or a var declaration that hides it.
40464043
scope->SetCapturesAll(funcInfo->GetCallsEval() || funcInfo->GetChildCallsEval() || sym->GetHasNonLocalReference());
@@ -4061,9 +4058,9 @@ void ByteCodeGenerator::StartEmitCatch(ParseNodeCatch *pnodeCatch)
40614058
sym->EnsureScopeSlot(this, funcInfo);
40624059
}
40634060
}
4064-
4065-
PushScope(scope);
40664061
}
4062+
4063+
PushScope(scope);
40674064
}
40684065

40694066
void ByteCodeGenerator::EndEmitCatch(ParseNodeCatch *pnodeCatch)
@@ -11614,33 +11611,27 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1161411611
byteCodeGenerator->Writer()->Empty(Js::OpCode::Leave);
1161511612
byteCodeGenerator->Writer()->Br(pnodeTryCatch->breakLabel);
1161611613
byteCodeGenerator->Writer()->MarkLabel(catchLabel);
11617-
11618-
ParseNode *pnodeObj = pnodeCatch->GetParam();
11619-
Assert(pnodeObj);
11620-
11621-
Js::RegSlot location;
11622-
11623-
bool acquiredTempLocation = false;
1162411614

11615+
Js::RegSlot location = Js::Constants::NoRegister;
1162511616
Js::DebuggerScope *debuggerScope = nullptr;
1162611617
Js::DebuggerScopePropertyFlags debuggerPropertyFlags = Js::DebuggerScopePropertyFlags_CatchObject;
11618+
ParseNode *tempLocationNode = nullptr;
1162711619

11628-
bool isPattern = pnodeObj->nop == knopParamPattern;
11629-
11630-
if (isPattern)
11620+
if (pnodeCatch->HasPatternParam())
1163111621
{
11632-
location = pnodeObj->AsParseNodeParamPattern()->location;
11622+
location = pnodeCatch->GetParam()->AsParseNodeParamPattern()->location;
1163311623
}
11634-
else
11624+
else if (pnodeCatch->HasParam())
1163511625
{
11636-
location = pnodeObj->AsParseNodeName()->sym->GetLocation();
11626+
location = pnodeCatch->GetParam()->AsParseNodeName()->sym->GetLocation();
1163711627
}
1163811628

1163911629
if (location == Js::Constants::NoRegister)
1164011630
{
11641-
location = funcInfo->AcquireLoc(pnodeObj);
11642-
acquiredTempLocation = true;
11631+
tempLocationNode = pnodeCatch->HasParam() ? pnodeCatch->GetParam() : pnodeCatch;
11632+
location = funcInfo->AcquireLoc(tempLocationNode);
1164311633
}
11634+
1164411635
byteCodeGenerator->Writer()->Reg1(Js::OpCode::Catch, location);
1164511636

1164611637
Scope *scope = pnodeCatch->scope;
@@ -11656,7 +11647,6 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1165611647
}
1165711648
else
1165811649
{
11659-
1166011650
int index = Js::DebuggerScope::InvalidScopeIndex;
1166111651
debuggerScope = byteCodeGenerator->RecordStartScopeObject(pnodeTryCatch, Js::DiagCatchScopeInSlot, funcInfo->InnerScopeToRegSlot(scope), &index);
1166211652
byteCodeGenerator->Writer()->Num3(Js::OpCode::NewInnerScopeSlots, scope->GetInnerScopeIndex(), scope->GetScopeSlotCount() + Js::ScopeSlots::FirstSlotIndex, index);
@@ -11714,9 +11704,10 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1171411704
};
1171511705

1171611706
ByteCodeGenerator::TryScopeRecord tryRecForCatch(Js::OpCode::ResumeCatch, catchLabel);
11717-
if (isPattern)
11707+
if (pnodeCatch->HasPatternParam())
1171811708
{
11719-
Parser::MapBindIdentifier(pnodeObj->AsParseNodeParamPattern()->pnode1, [&](ParseNodePtr item)
11709+
ParseNode *pnode1 = pnodeCatch->GetParam()->AsParseNodeParamPattern()->pnode1;
11710+
Parser::MapBindIdentifier(pnode1, [&](ParseNodePtr item)
1172011711
{
1172111712
Js::RegSlot itemLocation = item->AsParseNodeVar()->sym->GetLocation();
1172211713
if (itemLocation == Js::Constants::NoRegister)
@@ -11731,7 +11722,6 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1173111722

1173211723
// Now emitting bytecode for destructuring pattern
1173311724
byteCodeGenerator->StartStatement(pnodeCatch);
11734-
ParseNodePtr pnode1 = pnodeObj->AsParseNodeParamPattern()->pnode1;
1173511725
Assert(pnode1->IsPattern());
1173611726

1173711727
if (funcInfo->byteCodeFunction->IsCoroutine())
@@ -11742,12 +11732,13 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1174211732
EmitAssignment(nullptr, pnode1, location, byteCodeGenerator, funcInfo);
1174311733
byteCodeGenerator->EndStatement(pnodeCatch);
1174411734
}
11745-
else
11735+
else if (pnodeCatch->HasParam())
1174611736
{
11747-
ParamTrackAndInitialization(pnodeObj->AsParseNodeName()->sym, true /*initializeParam*/, location);
11737+
Symbol *sym = pnodeCatch->GetParam()->AsParseNodeName()->sym;
11738+
ParamTrackAndInitialization(sym, true /*initializeParam*/, location);
1174811739
if (scope->GetMustInstantiate())
1174911740
{
11750-
pnodeObj->AsParseNodeName()->sym->SetIsGlobalCatch(true);
11741+
sym->SetIsGlobalCatch(true);
1175111742
}
1175211743
byteCodeGenerator->Writer()->RecordCrossFrameEntryExitRecord(true);
1175311744

@@ -11769,14 +11760,13 @@ void Emit(ParseNode *pnode, ByteCodeGenerator *byteCodeGenerator, FuncInfo *func
1176911760
}
1177011761

1177111762
byteCodeGenerator->PopScope();
11772-
1177311763
byteCodeGenerator->RecordEndScopeObject(pnodeTryCatch);
1177411764

1177511765
funcInfo->ReleaseLoc(pnodeCatch->pnodeBody);
1177611766

11777-
if (acquiredTempLocation)
11767+
if (tempLocationNode != nullptr)
1177811768
{
11779-
funcInfo->ReleaseLoc(pnodeObj);
11769+
funcInfo->ReleaseLoc(tempLocationNode);
1178011770
}
1178111771

1178211772
byteCodeGenerator->Writer()->RecordCrossFrameEntryExitRecord(false);

lib/Runtime/ByteCode/ByteCodeGenerator.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3455,7 +3455,7 @@ void VisitNestedScopes(ParseNode* pnodeScopeList, ParseNode* pnodeParent, ByteCo
34553455
ParseNodeCatch * pnodeCatchScope = pnodeScope->AsParseNodeCatch();
34563456
PreVisitCatch(pnodeCatchScope, byteCodeGenerator);
34573457

3458-
if (pnodeCatchScope->GetParam()->nop != knopParamPattern)
3458+
if (pnodeCatchScope->HasParam() && !pnodeCatchScope->HasPatternParam())
34593459
{
34603460
Visit(pnodeCatchScope->GetParam(), byteCodeGenerator, prefix, postfix);
34613461
}
@@ -3636,11 +3636,10 @@ void PreVisitCatch(ParseNodeCatch *pnodeCatch, ByteCodeGenerator *byteCodeGenera
36363636
{
36373637
// Push the catch scope and add the catch expression to it.
36383638
byteCodeGenerator->StartBindCatch(pnodeCatch);
3639-
3640-
ParseNode * pnodeParam = pnodeCatch->GetParam();
3641-
if (pnodeParam->nop == knopParamPattern)
3639+
3640+
if (pnodeCatch->HasPatternParam())
36423641
{
3643-
ParseNodeParamPattern * pnodeParamPattern = pnodeParam->AsParseNodeParamPattern();
3642+
ParseNodeParamPattern * pnodeParamPattern = pnodeCatch->GetParam()->AsParseNodeParamPattern();
36443643
Parser::MapBindIdentifier(pnodeParamPattern->pnode1, [&](ParseNodePtr item)
36453644
{
36463645
Symbol *sym = item->AsParseNodeVar()->sym;
@@ -3655,9 +3654,9 @@ void PreVisitCatch(ParseNodeCatch *pnodeCatch, ByteCodeGenerator *byteCodeGenera
36553654
sym->SetIsBlockVar(true);
36563655
});
36573656
}
3658-
else
3657+
else if (pnodeCatch->HasParam())
36593658
{
3660-
ParseNodeName * pnodeName = pnodeParam->AsParseNodeName();
3659+
ParseNodeName * pnodeName = pnodeCatch->GetParam()->AsParseNodeName();
36613660
Symbol *sym = *pnodeName->GetSymRef();
36623661
Assert(sym->GetScope() == pnodeCatch->scope);
36633662
#if DBG_DUMP
@@ -3670,6 +3669,7 @@ void PreVisitCatch(ParseNodeCatch *pnodeCatch, ByteCodeGenerator *byteCodeGenera
36703669
sym->SetIsCatch(true);
36713670
pnodeName->sym = sym;
36723671
}
3672+
36733673
// This call will actually add the nested function symbols to the enclosing function scope (which is what we want).
36743674
AddFunctionsToScope(pnodeCatch->pnodeScopes, byteCodeGenerator);
36753675
}

test/DebuggerCommon/catchInspection.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,4 +242,18 @@ foo7();
242242
f();
243243
})();
244244

245-
WScript.Echo("Pass");
245+
(function foo() {
246+
var a = 1;
247+
try {
248+
throw -1;
249+
}
250+
catch { // catch scope
251+
let b = 2;
252+
(function g() {
253+
var c = 3;
254+
a; b; c; /**bp:locals(1)**/
255+
})();
256+
}
257+
})();
258+
259+
WScript.Echo("Pass");

test/DebuggerCommon/catchInspection.js.dbg.baseline

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -939,5 +939,54 @@
939939
"foo6": "function <large string>",
940940
"foo7": "function <large string>"
941941
}
942+
},
943+
{
944+
"this": {
945+
"Symbol.toStringTag": "string global",
946+
"top": "Object {...}",
947+
"startTest": "function <large string>",
948+
"bar": "function <large string>",
949+
"bar2": "function <large string>",
950+
"foo": "function <large string>",
951+
"foo1": "function <large string>",
952+
"foo10": "function <large string>",
953+
"foo11": "function <large string>",
954+
"foo2": "function <large string>",
955+
"foo3": "function <large string>",
956+
"foo5": "function <large string>",
957+
"foo6": "function <large string>",
958+
"foo7": "function <large string>"
959+
},
960+
"arguments": {
961+
"#__proto__": "Object {...}",
962+
"length": "number 0",
963+
"callee": "function <large string>",
964+
"Symbol.iterator": "function <large string>"
965+
},
966+
"locals": {
967+
"c": "number 3"
968+
},
969+
"scopes0": {
970+
"b": "number 2"
971+
},
972+
"scopes1": {
973+
"a": "number 1"
974+
},
975+
"globals": {
976+
"Symbol.toStringTag": "string global",
977+
"top": "Object {...}",
978+
"startTest": "function <large string>",
979+
"bar": "function <large string>",
980+
"bar2": "function <large string>",
981+
"foo": "function <large string>",
982+
"foo1": "function <large string>",
983+
"foo10": "function <large string>",
984+
"foo11": "function <large string>",
985+
"foo2": "function <large string>",
986+
"foo3": "function <large string>",
987+
"foo5": "function <large string>",
988+
"foo6": "function <large string>",
989+
"foo7": "function <large string>"
990+
}
942991
}
943-
]
992+
]

0 commit comments

Comments
 (0)