Skip to content

Commit 8ffa08e

Browse files
committed
AsyncIteration
1 parent 1481d95 commit 8ffa08e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2409
-146
lines changed

lib/Backend/JnHelperMethodList.h

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -518,15 +518,20 @@ HELPERCALL(NewPropIdArrForCompProps, Js::InterpreterStackFrame::OP_NewPropIdArrF
518518
HELPERCALL(StPropIdArrFromVar, Js::InterpreterStackFrame::OP_StPropIdArrFromVar, 0)
519519

520520

521-
HELPERCALLCHK(LdHomeObj, Js::JavascriptOperators::OP_LdHomeObj, AttrCanNotBeReentrant)
522-
HELPERCALLCHK(LdFuncObj, Js::JavascriptOperators::OP_LdFuncObj, AttrCanNotBeReentrant)
523-
HELPERCALLCHK(SetHomeObj, Js::JavascriptOperators::OP_SetHomeObj, AttrCanNotBeReentrant)
524-
HELPERCALLCHK(LdHomeObjProto, Js::JavascriptOperators::OP_LdHomeObjProto, AttrCanNotBeReentrant)
525-
HELPERCALLCHK(LdFuncObjProto, Js::JavascriptOperators::OP_LdFuncObjProto, AttrCanNotBeReentrant)
526-
527-
HELPERCALLCHK(ImportCall, Js::JavascriptOperators::OP_ImportCall, 0)
528-
529-
HELPERCALLCHK(ResumeYield, Js::JavascriptOperators::OP_ResumeYield, AttrCanThrow)
521+
HELPERCALLCHK(LdHomeObj, Js::JavascriptOperators::OP_LdHomeObj, AttrCanNotBeReentrant)
522+
HELPERCALLCHK(LdFuncObj, Js::JavascriptOperators::OP_LdFuncObj, AttrCanNotBeReentrant)
523+
HELPERCALLCHK(SetHomeObj, Js::JavascriptOperators::OP_SetHomeObj, AttrCanNotBeReentrant)
524+
HELPERCALLCHK(LdHomeObjProto, Js::JavascriptOperators::OP_LdHomeObjProto, AttrCanNotBeReentrant)
525+
HELPERCALLCHK(LdFuncObjProto, Js::JavascriptOperators::OP_LdFuncObjProto, AttrCanNotBeReentrant)
526+
527+
HELPERCALLCHK(ImportCall, Js::JavascriptOperators::OP_ImportCall, 0)
528+
HELPERCALLCHK(NewAsyncFromSyncIterator, Js::JavascriptOperators::OP_NewAsyncFromSyncIterator, AttrCanNotBeReentrant)
529+
530+
HELPERCALLCHK(AsyncYieldIsReturn, Js::JavascriptOperators::OP_AsyncYieldIsReturn, AttrCanNotBeReentrant)
531+
HELPERCALLCHK(ResumeYield, Js::JavascriptOperators::OP_ResumeYield, AttrCanThrow)
532+
HELPERCALL(AsyncYieldStar, Js::InterpreterStackFrame::OP_AsyncYieldStar, AttrCanNotBeReentrant)
533+
HELPERCALL(AsyncYield, Js::InterpreterStackFrame::OP_AsyncYield, AttrCanNotBeReentrant)
534+
HELPERCALL(Await, Js::InterpreterStackFrame::OP_Await, AttrCanNotBeReentrant)
530535

531536
#if DBG
532537
HELPERCALL(IntRangeCheckFailure, Js::JavascriptNativeOperators::IntRangeCheckFailure, AttrCanNotBeReentrant)

lib/Backend/Lower.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2938,6 +2938,58 @@ Lowerer::LowerRange(IR::Instr *instrStart, IR::Instr *instrEnd, bool defaultDoFa
29382938
break;
29392939
}
29402940

2941+
case Js::OpCode::NewAsyncFromSyncIterator:
2942+
{
2943+
IR::Opnd *src1Opnd = instr->UnlinkSrc1();
2944+
2945+
LoadScriptContext(instr);
2946+
m_lowererMD.LoadHelperArgument(instr, src1Opnd);
2947+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperNewAsyncFromSyncIterator);
2948+
2949+
break;
2950+
}
2951+
2952+
case Js::OpCode::Await:
2953+
{
2954+
IR::Opnd *srcOpnd1 = instr->UnlinkSrc1();
2955+
IR::Opnd *srcOpnd2 = instr->UnlinkSrc2();
2956+
LoadScriptContext(instr);
2957+
m_lowererMD.LoadHelperArgument(instr, srcOpnd2);
2958+
m_lowererMD.LoadHelperArgument(instr, srcOpnd1);
2959+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperAwait);
2960+
break;
2961+
}
2962+
2963+
case Js::OpCode::AsyncYield:
2964+
{
2965+
IR::Opnd *srcOpnd1 = instr->UnlinkSrc1();
2966+
IR::Opnd *srcOpnd2 = instr->UnlinkSrc2();
2967+
LoadScriptContext(instr);
2968+
m_lowererMD.LoadHelperArgument(instr, srcOpnd2);
2969+
m_lowererMD.LoadHelperArgument(instr, srcOpnd1);
2970+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperAsyncYield);
2971+
break;
2972+
}
2973+
2974+
case Js::OpCode::AsyncYieldIsReturn:
2975+
{
2976+
IR::Opnd *srcOpnd1 = instr->UnlinkSrc1();
2977+
m_lowererMD.LoadHelperArgument(instr, srcOpnd1);
2978+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperAsyncYieldIsReturn);
2979+
break;
2980+
}
2981+
2982+
case Js::OpCode::AsyncYieldStar:
2983+
{
2984+
IR::Opnd *srcOpnd1 = instr->UnlinkSrc1();
2985+
IR::Opnd *srcOpnd2 = instr->UnlinkSrc2();
2986+
LoadScriptContext(instr);
2987+
m_lowererMD.LoadHelperArgument(instr, srcOpnd2);
2988+
m_lowererMD.LoadHelperArgument(instr, srcOpnd1);
2989+
m_lowererMD.ChangeToHelperCall(instr, IR::HelperAsyncYieldStar);
2990+
break;
2991+
}
2992+
29412993
case Js::OpCode::Yield:
29422994
{
29432995
instr->FreeSrc1(); // Source is not actually used by the backend other than to calculate lifetime

lib/Common/ConfigFlagsList.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,6 +701,7 @@ PHASE(All)
701701
#define DEFAULT_CONFIG_ESObjectGetOwnPropertyDescriptors (true)
702702
#define DEFAULT_CONFIG_ESDynamicImport (false)
703703
#define DEFAULT_CONFIG_ESExportNsAs (true)
704+
#define DEFAULT_CONFIG_ES2018AsyncIteration (false)
704705

705706
#define DEFAULT_CONFIG_ESSharedArrayBuffer (false)
706707

@@ -1178,6 +1179,7 @@ FLAGPR (Boolean, ES6, ES6Unscopables , "Enable ES6 With Statem
11781179
FLAGPR (Boolean, ES6, ES6RegExSticky , "Enable ES6 RegEx sticky flag" , DEFAULT_CONFIG_ES6RegExSticky)
11791180
FLAGPR (Boolean, ES6, ES2018RegExDotAll , "Enable ES2018 RegEx dotAll flag" , DEFAULT_CONFIG_ES2018RegExDotAll)
11801181
FLAGPR (Boolean, ES6, ESExportNsAs , "Enable ES experimental export * as name" , DEFAULT_CONFIG_ESExportNsAs)
1182+
FLAGPR (Boolean, ES6, ES2018AsyncIteration , "Enable ES2018 Async Iteration" , DEFAULT_CONFIG_ES2018AsyncIteration)
11811183

11821184
#ifndef COMPILE_DISABLE_ES6RegExPrototypeProperties
11831185
#define COMPILE_DISABLE_ES6RegExPrototypeProperties 0

lib/Jsrt/JsrtDebugUtils.cpp

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,7 @@ void JsrtDebugUtils::AddPropertyType(Js::DynamicObject * object, Js::IDiagObject
271271
case Js::TypeIds_WeakSet:
272272
case Js::TypeIds_SymbolObject:
273273
case Js::TypeIds_Generator:
274+
case Js::TypeIds_AsyncFromSyncIterator:
274275
case Js::TypeIds_Promise:
275276
case Js::TypeIds_GlobalObject:
276277
case Js::TypeIds_SpreadArgument:
@@ -428,9 +429,9 @@ const char16 * JsrtDebugUtils::GetClassName(Js::TypeId typeId)
428429
case Js::TypeIds_MapIterator:
429430
case Js::TypeIds_SetIterator:
430431
case Js::TypeIds_StringIterator:
431-
return _u("Object");
432+
return _u("Object");
432433

433-
case Js::TypeIds_Proxy: return _u("Proxy");
434+
case Js::TypeIds_Proxy: return _u("Proxy");
434435
case Js::TypeIds_Array:
435436
case Js::TypeIds_NativeIntArray:
436437
#if ENABLE_COPYONACCESS_ARRAY
@@ -440,45 +441,46 @@ const char16 * JsrtDebugUtils::GetClassName(Js::TypeId typeId)
440441
case Js::TypeIds_ES5Array:
441442
case Js::TypeIds_CharArray:
442443
case Js::TypeIds_BoolArray:
443-
return _u("Array");
444+
return _u("Array");
444445

445446
case Js::TypeIds_Date:
446447
case Js::TypeIds_VariantDate:
447-
return _u("Date");
448-
449-
case Js::TypeIds_RegEx: return _u("RegExp");
450-
case Js::TypeIds_Error: return _u("Error");
451-
case Js::TypeIds_BooleanObject: return _u("Boolean");
452-
case Js::TypeIds_NumberObject: return _u("Number");
453-
case Js::TypeIds_StringObject: return _u("String");
454-
case Js::TypeIds_Arguments: return _u("Object");
455-
case Js::TypeIds_ArrayBuffer: return _u("ArrayBuffer");
456-
case Js::TypeIds_Int8Array: return _u("Int8Array");
457-
case Js::TypeIds_Uint8Array: return _u("Uint8Array");
458-
case Js::TypeIds_Uint8ClampedArray: return _u("Uint8ClampedArray");
459-
case Js::TypeIds_Int16Array: return _u("Int16Array");
460-
case Js::TypeIds_Uint16Array: return _u("Uint16Array");
461-
case Js::TypeIds_Int32Array: return _u("Int32Array");
462-
case Js::TypeIds_Uint32Array: return _u("Uint32Array");
463-
case Js::TypeIds_Float32Array: return _u("Float32Array");
464-
case Js::TypeIds_Float64Array: return _u("Float64Array");
465-
case Js::TypeIds_Int64Array: return _u("Int64Array");
466-
case Js::TypeIds_Uint64Array: return _u("Uint64Array");
467-
case Js::TypeIds_DataView: return _u("DataView");
468-
case Js::TypeIds_Map: return _u("Map");
469-
case Js::TypeIds_Set: return _u("Set");
470-
case Js::TypeIds_WeakMap: return _u("WeakMap");
471-
case Js::TypeIds_WeakSet: return _u("WeakSet");
472-
case Js::TypeIds_SymbolObject: return _u("Symbol");
473-
case Js::TypeIds_Generator: return _u("Generator");
474-
case Js::TypeIds_Promise: return _u("Promise");
475-
case Js::TypeIds_GlobalObject: return _u("Object");
476-
case Js::TypeIds_SpreadArgument: return _u("Spread");
448+
return _u("Date");
449+
450+
case Js::TypeIds_RegEx: return _u("RegExp");
451+
case Js::TypeIds_Error: return _u("Error");
452+
case Js::TypeIds_BooleanObject: return _u("Boolean");
453+
case Js::TypeIds_NumberObject: return _u("Number");
454+
case Js::TypeIds_StringObject: return _u("String");
455+
case Js::TypeIds_Arguments: return _u("Object");
456+
case Js::TypeIds_ArrayBuffer: return _u("ArrayBuffer");
457+
case Js::TypeIds_Int8Array: return _u("Int8Array");
458+
case Js::TypeIds_Uint8Array: return _u("Uint8Array");
459+
case Js::TypeIds_Uint8ClampedArray: return _u("Uint8ClampedArray");
460+
case Js::TypeIds_Int16Array: return _u("Int16Array");
461+
case Js::TypeIds_Uint16Array: return _u("Uint16Array");
462+
case Js::TypeIds_Int32Array: return _u("Int32Array");
463+
case Js::TypeIds_Uint32Array: return _u("Uint32Array");
464+
case Js::TypeIds_Float32Array: return _u("Float32Array");
465+
case Js::TypeIds_Float64Array: return _u("Float64Array");
466+
case Js::TypeIds_Int64Array: return _u("Int64Array");
467+
case Js::TypeIds_Uint64Array: return _u("Uint64Array");
468+
case Js::TypeIds_DataView: return _u("DataView");
469+
case Js::TypeIds_Map: return _u("Map");
470+
case Js::TypeIds_Set: return _u("Set");
471+
case Js::TypeIds_WeakMap: return _u("WeakMap");
472+
case Js::TypeIds_WeakSet: return _u("WeakSet");
473+
case Js::TypeIds_SymbolObject: return _u("Symbol");
474+
case Js::TypeIds_Generator: return _u("Generator");
475+
case Js::TypeIds_AsyncFromSyncIterator: return _u("AsyncFromSyncIterator");
476+
case Js::TypeIds_Promise: return _u("Promise");
477+
case Js::TypeIds_GlobalObject: return _u("Object");
478+
case Js::TypeIds_SpreadArgument: return _u("Spread");
477479
#ifdef ENABLE_WASM
478-
case Js::TypeIds_WebAssemblyModule: return _u("WebAssembly.Module");
479-
case Js::TypeIds_WebAssemblyInstance:return _u("WebAssembly.Instance");
480-
case Js::TypeIds_WebAssemblyMemory: return _u("WebAssembly.Memory");
481-
case Js::TypeIds_WebAssemblyTable: return _u("WebAssembly.Table");
480+
case Js::TypeIds_WebAssemblyModule: return _u("WebAssembly.Module");
481+
case Js::TypeIds_WebAssemblyInstance: return _u("WebAssembly.Instance");
482+
case Js::TypeIds_WebAssemblyMemory: return _u("WebAssembly.Memory");
483+
case Js::TypeIds_WebAssemblyTable: return _u("WebAssembly.Table");
482484
#endif
483485
default:
484486
Assert(false);

lib/Parser/Parse.cpp

Lines changed: 51 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6639,7 +6639,10 @@ void Parser::ParseFncName(ParseNodeFnc * pnodeFnc, ushort flags, IdentPtr* pFncN
66396639
{
66406640
if (pnodeFnc->IsGenerator())
66416641
{
6642-
Error(ERRsyntax);
6642+
if (!m_scriptContext->GetConfig()->IsES2018AsyncIterationEnabled())
6643+
{
6644+
Error(ERRExperimental);
6645+
}
66436646
}
66446647
pnodeFnc->SetIsAsync();
66456648
}
@@ -10214,9 +10217,26 @@ ParseNodePtr Parser::ParseStatement()
1021410217
ParseNodeBlock * pnodeBlock = nullptr;
1021510218
ParseNodePtr *ppnodeScopeSave = nullptr;
1021610219
ParseNodePtr *ppnodeExprScopeSave = nullptr;
10220+
bool isForAwait = false;
1021710221

1021810222
ichMin = this->GetScanner()->IchMinTok();
10219-
ChkNxtTok(tkLParen, ERRnoLparen);
10223+
10224+
this->GetScanner()->Scan();
10225+
if (m_token.tk == tkAWAIT || (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.await))
10226+
{
10227+
if (!this->GetScanner()->AwaitIsKeywordRegion())
10228+
{
10229+
Error(ERRBadAwait); // for await () in a non-async function
10230+
}
10231+
if (!m_scriptContext->GetConfig()->IsES2018AsyncIterationEnabled())
10232+
{
10233+
Error(ERRExperimental);
10234+
}
10235+
isForAwait = true;
10236+
this->GetScanner()->Scan();
10237+
}
10238+
ChkCurTok(tkLParen, ERRnoLparen);
10239+
1022010240
pnodeBlock = StartParseBlock<buildAST>(PnodeBlockType::Regular, ScopeType_Block);
1022110241
if (buildAST)
1022210242
{
@@ -10343,6 +10363,11 @@ ParseNodePtr Parser::ParseStatement()
1034310363
bool isForOf = (m_token.tk != tkIN);
1034410364
Assert(!isForOf || (m_token.tk == tkID && m_token.GetIdentifier(this->GetHashTbl()) == wellKnownPropertyPids.of));
1034510365

10366+
if (isForAwait && !isForOf)
10367+
{
10368+
Error(ERRTokenAfter, _u("in"), _u("for await"));
10369+
}
10370+
1034610371
if ((buildAST && nullptr == pnodeT) || !fForInOrOfOkay)
1034710372
{
1034810373
if (isForOf)
@@ -10370,7 +10395,11 @@ ParseNodePtr Parser::ParseStatement()
1037010395
ParseNodeForInOrForOf * pnodeForInOrForOf = nullptr;
1037110396
if (buildAST)
1037210397
{
10373-
if (isForOf)
10398+
if (isForAwait)
10399+
{
10400+
pnodeForInOrForOf = CreateNodeForOpT<knopForAwaitOf>(ichMin);
10401+
}
10402+
else if (isForOf)
1037410403
{
1037510404
pnodeForInOrForOf = CreateNodeForOpT<knopForOf>(ichMin);
1037610405
}
@@ -10385,7 +10414,7 @@ ParseNodePtr Parser::ParseStatement()
1038510414

1038610415
TrackAssignment<true>(pnodeT, nullptr);
1038710416
}
10388-
PushStmt<buildAST>(&stmt, pnodeForInOrForOf, isForOf ? knopForOf : knopForIn, pLabelIdList);
10417+
PushStmt<buildAST>(&stmt, pnodeForInOrForOf, isForAwait ? knopForAwaitOf : (isForOf ? knopForOf : knopForIn), pLabelIdList);
1038910418
ParseNodePtr pnodeBody = ParseStatement<buildAST>();
1039010419

1039110420
if (buildAST)
@@ -10402,6 +10431,11 @@ ParseNodePtr Parser::ParseStatement()
1040210431
Error(ERRDestructInit);
1040310432
}
1040410433

10434+
if (isForAwait)
10435+
{
10436+
Error(ERRValidIfFollowedBy, _u("'for await'"), _u("'of'"));
10437+
}
10438+
1040510439
ChkCurTok(tkSColon, ERRnoSemic);
1040610440
ParseNodePtr pnodeCond = nullptr;
1040710441
if (m_token.tk != tkSColon)
@@ -11640,6 +11674,7 @@ void Parser::InitPids()
1164011674
wellKnownPropertyPids.get = this->GetHashTbl()->PidHashNameLen(g_ssym_get.sz, g_ssym_get.cch);
1164111675
wellKnownPropertyPids.set = this->GetHashTbl()->PidHashNameLen(g_ssym_set.sz, g_ssym_set.cch);
1164211676
wellKnownPropertyPids.let = this->GetHashTbl()->PidHashNameLen(g_ssym_let.sz, g_ssym_let.cch);
11677+
wellKnownPropertyPids.await = this->GetHashTbl()->PidHashNameLen(g_ssym_await.sz, g_ssym_await.cch);
1164311678
wellKnownPropertyPids.constructor = this->GetHashTbl()->PidHashNameLen(g_ssym_constructor.sz, g_ssym_constructor.cch);
1164411679
wellKnownPropertyPids.prototype = this->GetHashTbl()->PidHashNameLen(g_ssym_prototype.sz, g_ssym_prototype.cch);
1164511680
wellKnownPropertyPids.__proto__ = this->GetHashTbl()->PidHashNameLen(_u("__proto__"), sizeof("__proto__") - 1);
@@ -12677,6 +12712,9 @@ ParseNode* Parser::CopyPnode(ParseNode *pnode) {
1267712712
case knopForOf:
1267812713
Assert(false);
1267912714
break;
12715+
case knopForAwaitOf:
12716+
Assert(false);
12717+
break;
1268012718
//PTNODE(knopReturn , "return" ,None ,Uni ,fnopNone)
1268112719
case knopReturn: {
1268212720
ParseNode* copyNode = CreateNodeForOpT<knopReturn>(pnode->ichMin, pnode->ichLim);
@@ -13485,6 +13523,7 @@ void PrintScopesWIndent(ParseNode *pnode, int indentAmt) {
1348513523
case knopFor: scope = pnode->AsParseNodeFor()->pnodeBlock; firstOnly = true; break;
1348613524
case knopForIn: scope = pnode->AsParseNodeForInOrForOf()->pnodeBlock; firstOnly = true; break;
1348713525
case knopForOf: scope = pnode->AsParseNodeForInOrForOf()->pnodeBlock; firstOnly = true; break;
13526+
case knopForAwaitOf: scope = pnode->AsParseNodeForInOrForOf()->pnodeBlock; firstOnly = true; break;
1348813527
}
1348913528
if (scope) {
1349013529
Output::Print(_u("[%4d, %4d): "), scope->ichMin, scope->ichLim);
@@ -14118,6 +14157,14 @@ void PrintPnodeWIndent(ParseNode *pnode, int indentAmt) {
1411814157
PrintPnodeWIndent(pnode->AsParseNodeForInOrForOf()->pnodeObj, indentAmt + INDENT_SIZE);
1411914158
PrintPnodeWIndent(pnode->AsParseNodeForInOrForOf()->pnodeBody, indentAmt + INDENT_SIZE);
1412014159
break;
14160+
case knopForAwaitOf:
14161+
Indent(indentAmt);
14162+
Output::Print(_u("forAwaitOf\n"));
14163+
PrintScopesWIndent(pnode, indentAmt + INDENT_SIZE);
14164+
PrintPnodeWIndent(pnode->AsParseNodeForInOrForOf()->pnodeLval, indentAmt + INDENT_SIZE);
14165+
PrintPnodeWIndent(pnode->AsParseNodeForInOrForOf()->pnodeObj, indentAmt + INDENT_SIZE);
14166+
PrintPnodeWIndent(pnode->AsParseNodeForInOrForOf()->pnodeBody, indentAmt + INDENT_SIZE);
14167+
break;
1412114168
//PTNODE(knopReturn , "return" ,None ,Uni ,fnopNone)
1412214169
case knopReturn:
1412314170
Indent(indentAmt);

lib/Parser/Parse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ class Parser
474474
IdentPtr set;
475475
IdentPtr get;
476476
IdentPtr let;
477+
IdentPtr await;
477478
IdentPtr constructor;
478479
IdentPtr prototype;
479480
IdentPtr __proto__;

lib/Parser/pnodewalk.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,9 @@ class ParseNodeWalker : public WalkerPolicy
483483
case knopForOf:
484484
return WalkForInOrForOf(pnode->AsParseNodeForInOrForOf(), context);
485485

486+
case knopForAwaitOf:
487+
return WalkForInOrForOf(pnode->AsParseNodeForInOrForOf(), context);
488+
486489
//PTNODE(knopReturn , "return" ,None ,Uni ,fnopNone)
487490
case knopReturn:
488491
return WalkReturn(pnode->AsParseNodeReturn(), context);

lib/Parser/ptlist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ PTNODE(knopWhile , "while" , Nop , While , fnopNotExp
135135
PTNODE(knopDoWhile , "do-while" , Nop , While , fnopNotExprStmt|fnopCleanup|fnopBreak|fnopContinue , "DoWhileStmt" )
136136
PTNODE(knopForIn , "for in" , Nop , ForInOrForOf, fnopNotExprStmt|fnopCleanup|fnopBreak|fnopContinue , "ForInStmt" )
137137
PTNODE(knopForOf , "for of" , Nop , ForInOrForOf, fnopNotExprStmt|fnopCleanup|fnopBreak|fnopContinue , "ForOfStmt" )
138+
PTNODE(knopForAwaitOf , "for await of" , Nop , ForInOrForOf, fnopNotExprStmt|fnopCleanup|fnopBreak|fnopContinue , "ForAwaitOfStmt" )
138139
PTNODE(knopBlock , "{}" , Nop , Block , fnopNotExprStmt|fnopAllowDefer, "Block" )
139140
PTNODE(knopStrTemplate, "``" , Nop , StrTemplate , fnopNone , "StringTemplateDecl" )
140141
PTNODE(knopWith , "with" , Nop , With , fnopNotExprStmt , "WithStmt" )

0 commit comments

Comments
 (0)