Skip to content

Commit e58e250

Browse files
committed
Experimental Internal Commands
1 parent 8b38076 commit e58e250

22 files changed

+1752
-1576
lines changed

lib/Common/ConfigFlagsList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,6 +1102,7 @@ FLAGR(Boolean, SkipSplitOnNoResult, "If the result of Regex split isn't used, sk
11021102
FLAGNR(String, TestEtwDll , "Path of the TestEtwEventSink DLL", nullptr)
11031103
#endif
11041104
#ifdef ENABLE_TEST_HOOKS
1105+
FLAGNR(Boolean, EnableInternalCommands, "Enable certain internal instructions within JS files - intended for library code only," , false)
11051106
FLAGNR(Boolean, Force32BitByteCode, "Force CC to generate 32bit bytecode intended only for regenerating bytecode headers.", false)
11061107
#endif
11071108

lib/Parser/Parse.cpp

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,13 @@ Parser::Parser(Js::ScriptContext* scriptContext, BOOL strictMode, PageAllocator
128128

129129
// init PID members
130130
InitPids();
131+
132+
#ifdef ENABLE_TEST_HOOKS
133+
if (scriptContext->GetConfig()->IsInternalCommandsEnabled())
134+
{
135+
InitInternalCommandPids();
136+
}
137+
#endif
131138
}
132139

133140
Parser::~Parser(void)
@@ -2626,6 +2633,74 @@ void Parser::CheckForDuplicateExportEntry(ModuleImportOrExportEntryList* exportE
26262633
}
26272634
}
26282635

2636+
#ifdef ENABLE_TEST_HOOKS
2637+
template<bool buildAST>
2638+
ParseNodePtr Parser::ParseInternalCommand()
2639+
{
2640+
this->GetScanner()->Scan();
2641+
if (m_token.tk != tkID)
2642+
{
2643+
Error(ERRTokenAfter, GetTokenString(m_token.tk), _u("@@"));
2644+
}
2645+
charcount_t ichMin = this->GetScanner()->IchMinTok();
2646+
2647+
// find the command type
2648+
InternalCommandType type;
2649+
IdentPtr id = m_token.GetIdentifier(GetHashTbl());
2650+
2651+
if (id == internalCommandPids.Conv_Num)
2652+
{
2653+
type = InternalCommandType::Conv_Num;
2654+
}
2655+
else if (id == internalCommandPids.Conv_Obj)
2656+
{
2657+
type = InternalCommandType::Conv_Obj;
2658+
}
2659+
else
2660+
{
2661+
Error(ERRTokenAfter, m_token.GetIdentifier(GetHashTbl())->Psz(), _u("@@"));
2662+
}
2663+
2664+
// parse the parameters - currently only accept identifiers
2665+
this->GetScanner()->Scan();
2666+
ChkCurTok(tkLParen, ERRnoLparen);
2667+
ParseNodePtr params = nullptr;
2668+
ParseNodePtr * lastParam = nullptr;
2669+
ParseNodePtr currentParam = nullptr;
2670+
2671+
for (;;)
2672+
{
2673+
currentParam = ParseExpr<buildAST>(0);
2674+
if (buildAST)
2675+
{
2676+
AddToNodeListEscapedUse(&params, &lastParam, currentParam);
2677+
}
2678+
2679+
if (m_token.tk == tkComma)
2680+
{
2681+
this->GetScanner()->Scan();
2682+
}
2683+
else if (m_token.tk == tkRParen)
2684+
{
2685+
this->GetScanner()->Scan();
2686+
break;
2687+
}
2688+
else
2689+
{
2690+
Error(ERRTokenAfter, GetTokenString(m_token.tk), GetTokenString(this->GetScanner()->GetPrevious()));
2691+
}
2692+
}
2693+
2694+
ParseNodePtr command = nullptr;
2695+
if (buildAST)
2696+
{
2697+
command = Anew(&m_nodeAllocator, ParseNodeInternalCommand, ichMin, this->GetScanner()->IchLimTok(), type, params);
2698+
}
2699+
2700+
return command;
2701+
}
2702+
#endif
2703+
26292704
template<bool buildAST>
26302705
void Parser::ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma)
26312706
{
@@ -3744,6 +3819,16 @@ ParseNodePtr Parser::ParseTerm(BOOL fAllowCall,
37443819
}
37453820
break;
37463821

3822+
#ifdef ENABLE_TEST_HOOKS
3823+
case tkIntCommand:
3824+
if (!m_scriptContext->GetConfig()->IsInternalCommandsEnabled())
3825+
{
3826+
Error(ERRTokenAfter, _u("@@"), GetTokenString(GetScanner()->GetPrevious()));
3827+
}
3828+
pnode = ParseInternalCommand<buildAST>();
3829+
break;
3830+
#endif
3831+
37473832
#if ENABLE_BACKGROUND_PARSING
37483833
case tkCASE:
37493834
{
@@ -11775,6 +11860,14 @@ void Parser::InitPids()
1177511860
wellKnownPropertyPids._importMeta = this->GetHashTbl()->PidHashNameLen(_u("*import.meta*"), sizeof("*import.meta*") - 1);
1177611861
}
1177711862

11863+
#ifdef ENABLE_TEST_HOOKS
11864+
void Parser::InitInternalCommandPids()
11865+
{
11866+
internalCommandPids.Conv_Num = this->GetHashTbl()->PidHashNameLen(_u("Conv_Num"), sizeof("Conv_Num") - 1);
11867+
internalCommandPids.Conv_Obj = this->GetHashTbl()->PidHashNameLen(_u("Conv_Obj"), sizeof("Conv_Obj") - 1);
11868+
}
11869+
#endif
11870+
1177811871
void Parser::RestoreScopeInfo(Js::ScopeInfo * scopeInfo)
1177911872
{
1178011873
if (!scopeInfo)

lib/Parser/Parse.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ class Parser
342342

343343
void InitPids();
344344

345+
#ifdef ENABLE_TEST_HOOKS
346+
void InitInternalCommandPids();
347+
#endif
348+
345349
/***********************************************************************
346350
Members needed just for parsing.
347351
***********************************************************************/
@@ -504,6 +508,15 @@ class Parser
504508

505509
WellKnownPropertyPids wellKnownPropertyPids;
506510

511+
#ifdef ENABLE_TEST_HOOKS
512+
struct InternalCommandPids
513+
{
514+
IdentPtr Conv_Num;
515+
IdentPtr Conv_Obj;
516+
};
517+
InternalCommandPids internalCommandPids;
518+
#endif
519+
507520
charcount_t m_sourceLim; // The actual number of characters parsed.
508521

509522
Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
@@ -975,6 +988,10 @@ class Parser
975988
charcount_t ichMin,
976989
_Out_opt_ BOOL* pfCanAssign = nullptr);
977990

991+
#ifdef ENABLE_TEST_HOOKS
992+
template<bool buildAST> ParseNodePtr ParseInternalCommand();
993+
#endif
994+
978995
void CheckIfImportOrExportStatementValidHere();
979996
bool IsTopLevelModuleFunc();
980997

lib/Parser/Scan.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2195,6 +2195,16 @@ tokens Scanner<EncodingPolicy>::ScanCore(bool identifyKwds)
21952195
token = this->ScanStringConstant((OLECHAR)ch, &pchT);
21962196
p = pchT;
21972197
break;
2198+
#ifdef ENABLE_TEST_HOOKS
2199+
case '@':
2200+
if (this->PeekFirst(p,last) != '@')
2201+
{
2202+
goto LDefault;
2203+
}
2204+
p++;
2205+
token = tkIntCommand;
2206+
break;
2207+
#endif
21982208
}
21992209

22002210
break;

lib/Parser/kwd-lsc.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ TOK_DCL(tkEllipsis , No, knopNone ,Spr, knopEllipsis ) // ...
173173
TOK_DCL(tkLParen , No, knopNone , No, knopNone ) // (
174174
TOK_DCL(tkLBrack , No, knopNone , No, knopNone ) // [
175175
TOK_DCL(tkDot , No, knopNone , No, knopNone ) // .
176+
#ifdef ENABLE_TEST_HOOKS
177+
TOK_DCL(tkIntCommand , No, knopNone , No, knopNone ) //@@
178+
#endif
176179

177180
// String template tokens
178181
TOK_DCL(tkStrTmplBasic , No, knopNone , No, knopNone ) // `...`

lib/Parser/pnodewalk.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,10 @@ class ParseNodeWalker : public WalkerPolicy
536536
case knopExportDefault:
537537
return Walk(pnode->AsParseNodeExportDefault()->pnodeExpr, context);
538538

539+
#ifdef ENABLE_TEST_HOOKS
540+
case knopIntCommand:
541+
return Walk(pnode->AsParseNodeInternalCommand()->params, context);
542+
#endif
539543
default:
540544
{
541545
uint fnop = ParseNode::Grfnop(pnode->nop);

lib/Parser/ptlist.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,8 @@ PTNODE(knopObjectPatternMember, "{:} = " , Nop , Bin , fnopBin
155155
PTNODE(knopArrayPattern, "[] = " , Nop , ArrLit , fnopUni , "ArrayAssignmentPattern" )
156156
PTNODE(knopParamPattern, "({[]})" , Nop , ParamPattern, fnopUni , "DestructurePattern" )
157157
PTNODE(knopExportDefault, "export default" , Nop , ExportDefault,fnopNone , "ExportDefault" )
158-
159-
158+
#ifdef ENABLE_TEST_HOOKS
159+
PTNODE(knopIntCommand, "intCommand" , Nop , None , fnopNone , "Internal Command" )
160+
#endif
160161
#undef PTNODE
161162
#undef OP

lib/Parser/ptree.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,14 @@ ParseNodeModule * ParseNode::AsParseNodeModule()
263263
return reinterpret_cast<ParseNodeModule*>(this);
264264
}
265265

266+
#ifdef ENABLE_TEST_HOOKS
267+
ParseNodeInternalCommand * ParseNode::AsParseNodeInternalCommand()
268+
{
269+
Assert(this->nop == knopIntCommand);
270+
return reinterpret_cast<ParseNodeInternalCommand *>(this);
271+
}
272+
#endif
273+
266274
IdentPtr ParseNode::name()
267275
{
268276
if (this->nop == knopStr)

lib/Parser/ptree.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ class ParseNodeForInOrForOf;
110110
class ParseNodeFnc;
111111
class ParseNodeProg;
112112
class ParseNodeModule;
113+
#ifdef ENABLE_TEST_HOOKS
114+
class ParseNodeInternalCommand;
115+
#endif
116+
113117

114118
class ParseNode
115119
{
@@ -163,6 +167,10 @@ class ParseNode
163167
ParseNodeProg * AsParseNodeProg();
164168
ParseNodeModule * AsParseNodeModule();
165169

170+
#ifdef ENABLE_TEST_HOOKS
171+
ParseNodeInternalCommand * AsParseNodeInternalCommand();
172+
#endif
173+
166174
static uint Grfnop(int nop)
167175
{
168176
Assert(nop < knopLim);
@@ -434,6 +442,26 @@ class ParseNodeObjLit : public ParseNodeUni
434442
DISABLE_SELF_CAST(ParseNodeObjLit);
435443
};
436444

445+
#ifdef ENABLE_TEST_HOOKS
446+
447+
typedef enum InternalCommandType
448+
{
449+
Conv_Num,
450+
Conv_Obj
451+
} InternalCommandType;
452+
453+
class ParseNodeInternalCommand : public ParseNode
454+
{
455+
public:
456+
ParseNodeInternalCommand(charcount_t ichMin, charcount_t ichLim, InternalCommandType type, ParseNodePtr parameters) :
457+
commandType(type), params(parameters), ParseNode(knopIntCommand, ichMin, ichLim) {}
458+
459+
InternalCommandType commandType;
460+
ParseNodePtr params;
461+
};
462+
#endif
463+
464+
437465
class FuncInfo;
438466

439467
enum PnodeBlockType : unsigned

lib/Runtime/Base/ThreadConfigFlagsList.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ FLAG_RELEASE(IsESSymbolDescriptionEnabled, ESSymbolDescription)
5555
FLAG_RELEASE(IsESGlobalThisEnabled, ESGlobalThis)
5656
FLAG_RELEASE(IsES2018AsyncIterationEnabled, ES2018AsyncIteration)
5757
#ifdef ENABLE_TEST_HOOKS
58+
FLAG_RELEASE(IsInternalCommandsEnabled, EnableInternalCommands)
5859
FLAG_RELEASE(Force32BitByteCode, Force32BitByteCode)
5960
#endif
6061
#ifdef ENABLE_PROJECTION

0 commit comments

Comments
 (0)