Parse.h 41 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #pragma once
  6. #include <crtdefs.h>
  7. #include "ParseFlags.h"
  8. // Operator precedence levels
  9. enum
  10. {
  11. koplNo, // not an operator
  12. koplCma, // ,
  13. koplSpr, // ...
  14. koplAsg, // = += etc
  15. koplQue, // ?:
  16. koplLor, // ||
  17. koplLan, // &&
  18. koplBor, // |
  19. koplXor, // ^
  20. koplBan, // &
  21. koplEqu, // == !=
  22. koplCmp, // < <= > >=
  23. koplShf, // << >> >>>
  24. koplAdd, // + -
  25. koplExpo, // **
  26. koplMul, // * / %
  27. koplUni, // unary operators
  28. koplLim
  29. };
  30. enum ParseType
  31. {
  32. ParseType_Upfront,
  33. ParseType_Deferred
  34. };
  35. enum DestructuringInitializerContext
  36. {
  37. DIC_None,
  38. DIC_ShouldNotParseInitializer, // e.g. We don't want to parse the initializer even though we found assignment
  39. DIC_ForceErrorOnInitializer, // e.g. Catch param where we explicitly want to raise an error when the initializer found
  40. };
  41. enum ScopeType;
  42. enum SymbolType : byte;
  43. // Representation of a label used when no AST is being built.
  44. struct LabelId
  45. {
  46. IdentPtr pid;
  47. struct LabelId* next;
  48. };
  49. typedef ArenaAllocator ParseNodeAllocator;
  50. /***************************************************************************
  51. Parser object.
  52. ***************************************************************************/
  53. class CompileScriptException;
  54. class Parser;
  55. class SourceContextInfo;
  56. struct BlockIdsStack;
  57. class Span;
  58. class BackgroundParser;
  59. struct BackgroundParseItem;
  60. struct PnClass;
  61. class HashTbl;
  62. typedef void (*ParseErrorCallback)(void *data, charcount_t position, charcount_t length, HRESULT hr);
  63. struct PidRefStack;
  64. struct DeferredFunctionStub;
  65. DeferredFunctionStub * BuildDeferredStubTree(ParseNode *pnodeFnc, Recycler *recycler);
  66. struct StmtNest;
  67. struct BlockInfoStack;
  68. struct ParseContext
  69. {
  70. LPCUTF8 pszSrc;
  71. size_t offset;
  72. size_t length;
  73. charcount_t characterOffset;
  74. int nextBlockId;
  75. ULONG grfscr;
  76. ULONG lineNumber;
  77. ParseNodePtr pnodeProg;
  78. SourceContextInfo* sourceContextInfo;
  79. BlockInfoStack* currentBlockInfo;
  80. bool strictMode;
  81. bool fromExternal;
  82. };
  83. template <bool nullTerminated> class UTF8EncodingPolicyBase;
  84. typedef UTF8EncodingPolicyBase<false> NotNullTerminatedUTF8EncodingPolicy;
  85. template <typename T> class Scanner;
  86. namespace Js
  87. {
  88. class ParseableFunctionInfo;
  89. class FunctionBody;
  90. };
  91. class Parser
  92. {
  93. typedef Scanner<NotNullTerminatedUTF8EncodingPolicy> Scanner_t;
  94. private:
  95. template <OpCode nop> static int GetNodeSize();
  96. #define PTNODE(nop,sn,pc,nk,ok,json) template <> static int GetNodeSize<nop>() { return kcbPn##nk; };
  97. #include "ptlist.h"
  98. template <OpCode nop> static ParseNodePtr StaticAllocNode(ArenaAllocator * alloc)
  99. {
  100. ParseNodePtr pnode = (ParseNodePtr)alloc->Alloc(GetNodeSize<nop>());
  101. Assert(pnode != nullptr);
  102. return pnode;
  103. }
  104. public:
  105. #if DEBUG
  106. Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false, size_t size = sizeof(Parser));
  107. #else
  108. Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false);
  109. #endif
  110. ~Parser(void);
  111. Js::ScriptContext* GetScriptContext() const { return m_scriptContext; }
  112. void ClearScriptContext() { m_scriptContext = nullptr; }
  113. bool IsBackgroundParser() const { return m_isInBackground; }
  114. bool IsDoingFastScan() const { return m_doingFastScan; }
  115. static IdentPtr PidFromNode(ParseNodePtr pnode);
  116. ParseNode* CopyPnode(ParseNode* pnode);
  117. IdentPtr GenerateIdentPtr(__ecount(len) wchar_t* name,long len);
  118. ArenaAllocator *GetAllocator() { return &m_nodeAllocator;}
  119. size_t GetSourceLength() { return m_length; }
  120. size_t GetOriginalSourceLength() { return m_originalLength; }
  121. static ULONG GetDeferralThreshold(bool isProfileLoaded);
  122. BOOL DeferredParse(Js::LocalFunctionId functionId);
  123. BOOL IsDeferredFnc();
  124. void ReduceDeferredScriptLength(size_t chars);
  125. void RestorePidRefForSym(Symbol *sym);
  126. HRESULT ValidateSyntax(LPCUTF8 pszSrc, size_t encodedCharCount, bool isGenerator, bool isAsync, CompileScriptException *pse, void (Parser::*validateFunction)());
  127. // Should be called when the UTF-8 source was produced from UTF-16. This is really CESU-8 source in that it encodes surrogate pairs
  128. // as 2 three byte sequences instead of 4 bytes as required by UTF-8. It also is a lossless conversion of invalid UTF-16 sequences.
  129. // This is important in Javascript because Javascript engines are required not to report invalid UTF-16 sequences and to consider
  130. // the UTF-16 characters pre-canonicalization. Converting this UTF-16 with invalid sequences to valid UTF-8 and back would cause
  131. // all invalid UTF-16 sequences to be replaced by one or more Unicode replacement characters (0xFFFD), losing the original
  132. // invalid sequences.
  133. HRESULT ParseCesu8Source(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
  134. Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
  135. // Should be called when the source is UTF-8 and invalid UTF-8 sequences should be replaced with the unicode replacement character
  136. // (0xFFFD). Security concerns require externally produced UTF-8 only allow valid UTF-8 otherwise an attacker could use invalid
  137. // UTF-8 sequences to fool a filter and cause Javascript to be executed that might otherwise have been rejected.
  138. HRESULT ParseUtf8Source(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
  139. Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
  140. // Used by deferred parsing to parse a deferred function.
  141. HRESULT ParseSourceWithOffset(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t offset, size_t cbLength, charcount_t cchOffset,
  142. bool isCesu8, ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber,
  143. SourceContextInfo * sourceContextInfo, Js::ParseableFunctionInfo* functionInfo);
  144. protected:
  145. HRESULT ParseSourceInternal(
  146. __out ParseNodePtr* parseTree, LPCUTF8 pszSrc, size_t offsetInBytes,
  147. size_t lengthInCodePoints, charcount_t offsetInChars, bool fromExternal,
  148. ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber, SourceContextInfo * sourceContextInfo);
  149. ParseNodePtr Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcount_t charOffset, ULONG grfscr, ULONG lineNumber,
  150. Js::LocalFunctionId * nextFunctionId, CompileScriptException *pse);
  151. private:
  152. /***********************************************************************
  153. Core members.
  154. ***********************************************************************/
  155. ParseNodeAllocator m_nodeAllocator;
  156. long m_cactIdentToNodeLookup;
  157. ulong m_grfscr;
  158. size_t m_length; // source length in characters excluding comments and literals
  159. size_t m_originalLength; // source length in characters excluding comments and literals
  160. Js::LocalFunctionId * m_nextFunctionId;
  161. SourceContextInfo* m_sourceContextInfo;
  162. ParseErrorCallback m_errorCallback;
  163. void * m_errorCallbackData;
  164. BOOL m_uncertainStructure;
  165. bool m_hasParallelJob;
  166. bool m_doingFastScan;
  167. Span m_asgToConst;
  168. int m_nextBlockId;
  169. // RegexPattern objects created for literal regexes are recycler-allocated and need to be kept alive until the function body
  170. // is created during byte code generation. The RegexPattern pointer is stored in the script context's guest
  171. // arena for that purpose. This list is then unregistered from the guest arena at the end of parsing/scanning.
  172. SList<UnifiedRegex::RegexPattern *, ArenaAllocator> m_registeredRegexPatterns;
  173. protected:
  174. Js::ScriptContext* m_scriptContext;
  175. HashTbl * m_phtbl;
  176. ErrHandler m_err;
  177. static const uint HASH_TABLE_SIZE = 256;
  178. __declspec(noreturn) void Error(HRESULT hr);
  179. private:
  180. __declspec(noreturn) void Error(HRESULT hr, ParseNodePtr pnode);
  181. __declspec(noreturn) void Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim);
  182. __declspec(noreturn) static void OutOfMemory();
  183. void GenerateCode(ParseNodePtr pnode, void *pvUser, long cbUser,
  184. LPCOLESTR pszSrc, long cchSrc, LPCOLESTR pszTitle);
  185. void EnsureStackAvailable();
  186. void IdentifierExpectedError(const Token& token);
  187. bool CheckForDirective(bool* pIsUseStrict, bool* pIsUseAsm, bool* pIsOctalInString);
  188. bool CheckStrictModeStrPid(IdentPtr pid);
  189. bool CheckAsmjsModeStrPid(IdentPtr pid);
  190. void InitPids();
  191. /***********************************************************************
  192. Members needed just for parsing.
  193. ***********************************************************************/
  194. protected:
  195. Token m_token;
  196. Scanner_t* m_pscan;
  197. public:
  198. // create nodes using arena allocator; used by AST transformation
  199. template <OpCode nop>
  200. static ParseNodePtr StaticCreateNodeT(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0);
  201. static ParseNodePtr StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1,ParseNodePtr pnode2,ArenaAllocator* alloc);
  202. static ParseNodePtr StaticCreateBlockNode(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, int blockId = -1, PnodeBlockType blockType = PnodeBlockType::Regular);
  203. ParseNodePtr CreateNode(OpCode nop, charcount_t ichMin,charcount_t ichLim);
  204. ParseNodePtr CreateDummyFuncNode(bool fDeclaration);
  205. ParseNodePtr CreateTriNode(OpCode nop, ParseNodePtr pnode1,
  206. ParseNodePtr pnode2, ParseNodePtr pnode3,
  207. charcount_t ichMin,charcount_t ichLim);
  208. ParseNodePtr CreateTempNode(ParseNode* initExpr);
  209. ParseNodePtr CreateTempRef(ParseNode* tempNode);
  210. ParseNodePtr CreateNode(OpCode nop) { return CreateNode(nop, m_pscan? m_pscan->IchMinTok() : 0); }
  211. ParseNodePtr CreateDeclNode(OpCode nop, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl = true);
  212. Symbol* AddDeclForPid(ParseNodePtr pnode, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl);
  213. ParseNodePtr CreateNameNode(IdentPtr pid)
  214. {
  215. ParseNodePtr pnode = CreateNode(knopName);
  216. pnode->sxPid.pid = pid;
  217. pnode->sxPid.sym=NULL;
  218. pnode->sxPid.symRef=NULL;
  219. return pnode;
  220. }
  221. ParseNodePtr CreateBlockNode(PnodeBlockType blockType = PnodeBlockType::Regular)
  222. {
  223. ParseNodePtr pnode = CreateNode(knopBlock);
  224. InitBlockNode(pnode, m_nextBlockId++, blockType);
  225. return pnode;
  226. }
  227. // Creating parse nodes.
  228. ParseNodePtr CreateNode(OpCode nop, charcount_t ichMin);
  229. ParseNodePtr CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3);
  230. ParseNodePtr CreateIntNode(long lw);
  231. ParseNodePtr CreateStrNode(IdentPtr pid);
  232. ParseNodePtr CreateUniNode(OpCode nop, ParseNodePtr pnodeOp);
  233. ParseNodePtr CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  234. ParseNodePtr CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  235. // Create parse node with token limis
  236. template <OpCode nop>
  237. ParseNodePtr CreateNodeT(charcount_t ichMin,charcount_t ichLim);
  238. ParseNodePtr CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_t ichMin,charcount_t ichLim);
  239. ParseNodePtr CreateBlockNode(charcount_t ichMin,charcount_t ichLim, PnodeBlockType blockType = PnodeBlockType::Regular);
  240. ParseNodePtr CreateNameNode(IdentPtr pid,charcount_t ichMin,charcount_t ichLim);
  241. ParseNodePtr CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2,
  242. charcount_t ichMin,charcount_t ichLim);
  243. ParseNodePtr CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2,
  244. charcount_t ichMin,charcount_t ichLim);
  245. void PrepareScanner(bool fromExternal);
  246. void PrepareForBackgroundParse();
  247. void AddFastScannedRegExpNode(ParseNodePtr const pnode);
  248. void AddBackgroundRegExpNode(ParseNodePtr const pnode);
  249. void AddBackgroundParseItem(BackgroundParseItem *const item);
  250. void FinishBackgroundRegExpNodes();
  251. void FinishBackgroundPidRefs(BackgroundParseItem *const item, bool isOtherParser);
  252. void WaitForBackgroundJobs(BackgroundParser *bgp, CompileScriptException *pse);
  253. HRESULT ParseFunctionInBackground(ParseNodePtr pnodeFunc, ParseContext *parseContext, bool topLevelDeferred, CompileScriptException *pse);
  254. void CheckPidIsValid(IdentPtr pid, bool autoArgumentsObject = false);
  255. void AddVarDeclToBlock(ParseNode *pnode);
  256. // Add a var declaration. Only use while parsing. Assumes m_ppnodeVar is pointing to the right place already
  257. ParseNodePtr CreateVarDeclNode(IdentPtr pid, SymbolType symbolType, bool autoArgumentsObject = false, ParseNodePtr pnodeFnc = NULL, bool checkReDecl = true);
  258. // Add a var declaration, during parse tree rewriting. Will setup m_ppnodeVar for the given pnodeFnc
  259. ParseNodePtr AddVarDeclNode(IdentPtr pid, ParseNodePtr pnodeFnc);
  260. // Add a 'const' or 'let' declaration.
  261. ParseNodePtr CreateBlockScopedDeclNode(IdentPtr pid, OpCode nodeType);
  262. void RegisterRegexPattern(UnifiedRegex::RegexPattern *const regexPattern);
  263. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  264. WCHAR* GetParseType() const
  265. {
  266. switch(m_parseType)
  267. {
  268. case ParseType_Upfront:
  269. return L"Upfront";
  270. case ParseType_Deferred:
  271. return L"Deferred";
  272. }
  273. Assert(false);
  274. return NULL;
  275. }
  276. #endif
  277. void CaptureContext(ParseContext *parseContext) const;
  278. void RestoreContext(ParseContext *const parseContext);
  279. int GetLastBlockId() const { Assert(m_nextBlockId > 0); return m_nextBlockId - 1; }
  280. private:
  281. template <OpCode nop> ParseNodePtr CreateNodeWithScanner();
  282. template <OpCode nop> ParseNodePtr CreateNodeWithScanner(charcount_t ichMin);
  283. ParseNodePtr CreateStrNodeWithScanner(IdentPtr pid);
  284. ParseNodePtr CreateIntNodeWithScanner(long lw);
  285. ParseNodePtr CreateProgNodeWithScanner(bool isModuleSource);
  286. static void InitNode(OpCode nop,ParseNodePtr pnode);
  287. static void InitBlockNode(ParseNodePtr pnode, int blockId, PnodeBlockType blockType);
  288. private:
  289. ParseNodePtr m_currentNodeNonLambdaFunc; // current function or NULL
  290. ParseNodePtr m_currentNodeNonLambdaDeferredFunc; // current function or NULL
  291. ParseNodePtr m_currentNodeFunc; // current function or NULL
  292. ParseNodePtr m_currentNodeDeferredFunc; // current function or NULL
  293. ParseNodePtr m_currentNodeProg; // current program
  294. DeferredFunctionStub *m_currDeferredStub;
  295. long * m_pCurrentAstSize;
  296. ParseNodePtr * m_ppnodeScope; // function list tail
  297. ParseNodePtr * m_ppnodeExprScope; // function expression list tail
  298. ParseNodePtr * m_ppnodeVar; // variable list tail
  299. bool m_inDeferredNestedFunc; // true if parsing a function in deferred mode, nested within the current node
  300. bool m_isInBackground;
  301. // This bool is used for deferring the shorthand initializer error ( {x = 1}) - as it is allowed in the destructuring grammar.
  302. bool m_hasDeferredShorthandInitError;
  303. uint * m_pnestedCount; // count of functions nested at one level below the current node
  304. struct WellKnownPropertyPids
  305. {
  306. IdentPtr arguments;
  307. IdentPtr async;
  308. IdentPtr eval;
  309. IdentPtr set;
  310. IdentPtr get;
  311. IdentPtr let;
  312. IdentPtr constructor;
  313. IdentPtr prototype;
  314. IdentPtr __proto__;
  315. IdentPtr of;
  316. IdentPtr target;
  317. IdentPtr from;
  318. IdentPtr as;
  319. IdentPtr default;
  320. IdentPtr _star; // Special '*' identifier for modules
  321. IdentPtr _starDefaultStar; // Special '*default*' identifier for modules
  322. };
  323. WellKnownPropertyPids wellKnownPropertyPids;
  324. charcount_t m_sourceLim; // The actual number of characters parsed.
  325. Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
  326. ParseType m_parseType;
  327. uint m_arrayDepth;
  328. uint m_funcInArrayDepth; // Count func depth within array literal
  329. charcount_t m_funcInArray;
  330. uint m_scopeCountNoAst;
  331. /*
  332. * Parsing states for super restriction
  333. */
  334. static const uint ParsingSuperRestrictionState_SuperDisallowed = 0;
  335. static const uint ParsingSuperRestrictionState_SuperCallAndPropertyAllowed = 1;
  336. static const uint ParsingSuperRestrictionState_SuperPropertyAllowed = 2;
  337. uint m_parsingSuperRestrictionState;
  338. friend class AutoParsingSuperRestrictionStateRestorer;
  339. // Used for issuing spread and rest errors when there is ambiguity with parameter list and parenthesized expressions
  340. uint m_parenDepth;
  341. bool m_deferEllipsisError;
  342. RestorePoint m_EllipsisErrLoc;
  343. uint m_tryCatchOrFinallyDepth; // Used to determine if parsing is currently in a try/catch/finally block in order to throw error on yield expressions inside them
  344. StmtNest *m_pstmtCur; // current statement or NULL
  345. BlockInfoStack *m_currentBlockInfo;
  346. Scope *m_currentScope;
  347. BackgroundParseItem *currBackgroundParseItem;
  348. BackgroundParseItem *backgroundParseItems;
  349. typedef DList<ParseNodePtr, ArenaAllocator> NodeDList;
  350. NodeDList* fastScannedRegExpNodes;
  351. BlockIdsStack *m_currentDynamicBlock;
  352. int GetCurrentDynamicBlockId() const;
  353. void AppendFunctionToScopeList(bool fDeclaration, ParseNodePtr pnodeFnc);
  354. // block scoped content helpers
  355. void SetCurrentStatement(StmtNest *stmt);
  356. ParseNode* GetCurrentBlock();
  357. ParseNode* GetFunctionBlock();
  358. BlockInfoStack* GetCurrentBlockInfo();
  359. BlockInfoStack* GetCurrentFunctionBlockInfo();
  360. ParseNode *GetCurrentFunctionNode();
  361. ParseNode *GetCurrentNonLamdaFunctionNode();
  362. bool IsNodeAllowedForDeferParse(OpCode op) {return !this->m_deferringAST ||
  363. (op == knopBlock || op == knopVarDecl || op == knopConstDecl || op == knopLetDecl || op == knopFncDecl); }
  364. bool NextTokenConfirmsLetDecl() const { return m_token.tk == tkID || m_token.tk == tkLBrack || m_token.tk == tkLCurly || m_token.IsReservedWord(); }
  365. bool NextTokenIsPropertyNameStart() const { return m_token.tk == tkID || m_token.tk == tkStrCon || m_token.tk == tkIntCon || m_token.tk == tkFltCon || m_token.tk == tkLBrack || m_token.IsReservedWord(); }
  366. template<bool buildAST>
  367. void PushStmt(StmtNest *pStmt, ParseNodePtr pnode, OpCode op, ParseNodePtr pnodeLab, LabelId* pLabelIdList)
  368. {
  369. AssertMem(pStmt);
  370. if (buildAST)
  371. {
  372. AssertNodeMem(pnode);
  373. AssertNodeMemN(pnodeLab);
  374. pnode->sxStmt.grfnop = 0;
  375. pnode->sxStmt.pnodeOuter = (NULL == m_pstmtCur) ? NULL : m_pstmtCur->pnodeStmt;
  376. pStmt->pnodeStmt = pnode;
  377. pStmt->pnodeLab = pnodeLab;
  378. }
  379. else
  380. {
  381. // Assign to pnodeStmt rather than op so that we initialize the whole field.
  382. pStmt->pnodeStmt = 0;
  383. pStmt->isDeferred = true;
  384. pStmt->op = op;
  385. pStmt->pLabelId = pLabelIdList;
  386. }
  387. pStmt->pstmtOuter = m_pstmtCur;
  388. SetCurrentStatement(pStmt);
  389. }
  390. void PopStmt(StmtNest *pStmt);
  391. BlockInfoStack *PushBlockInfo(ParseNodePtr pnodeBlock);
  392. void PopBlockInfo();
  393. void PushDynamicBlock();
  394. void PopDynamicBlock();
  395. ParseNodePtr PnodeLabel(IdentPtr pid, ParseNodePtr pnodeLabels);
  396. void MarkEvalCaller()
  397. {
  398. if (m_currentNodeFunc)
  399. {
  400. ParseNodePtr pnodeFunc = GetCurrentFunctionNode();
  401. pnodeFunc->sxFnc.SetCallsEval(true);
  402. }
  403. ParseNode *pnodeBlock = GetCurrentBlock();
  404. if (pnodeBlock != NULL)
  405. {
  406. pnodeBlock->sxBlock.SetCallsEval(true);
  407. PushDynamicBlock();
  408. }
  409. }
  410. public:
  411. IdentPtrList* GetRequestedModulesList();
  412. ModuleImportEntryList* GetModuleImportEntryList();
  413. ModuleExportEntryList* GetModuleLocalExportEntryList();
  414. ModuleExportEntryList* GetModuleIndirectExportEntryList();
  415. ModuleExportEntryList* GetModuleStarExportEntryList();
  416. protected:
  417. IdentPtrList* EnsureRequestedModulesList();
  418. ModuleImportEntryList* EnsureModuleImportEntryList();
  419. ModuleExportEntryList* EnsureModuleLocalExportEntryList();
  420. ModuleExportEntryList* EnsureModuleIndirectExportEntryList();
  421. ModuleExportEntryList* EnsureModuleStarExportEntryList();
  422. void AddModuleImportEntry(ModuleImportEntryList* importEntryList, IdentPtr importName, IdentPtr localName, IdentPtr moduleRequest, ParseNodePtr declNode);
  423. void AddModuleExportEntry(ModuleExportEntryList* exportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest);
  424. void AddModuleLocalExportEntry(ParseNodePtr varDeclNode);
  425. ParseNodePtr CreateModuleImportDeclNode(IdentPtr pid);
  426. public:
  427. WellKnownPropertyPids* names(){ return &wellKnownPropertyPids; }
  428. IdentPtr CreatePid(__in_ecount(len) LPCOLESTR name, charcount_t len)
  429. {
  430. return m_phtbl->PidHashNameLen(name, len);
  431. }
  432. bool KnownIdent(__in_ecount(len) LPCOLESTR name, charcount_t len)
  433. {
  434. return m_phtbl->Contains(name, len);
  435. }
  436. template <typename THandler>
  437. static void ForEachItemRefInList(ParseNodePtr *list, THandler handler)
  438. {
  439. ParseNodePtr *current = list;
  440. while (current != nullptr && (*current) != nullptr)
  441. {
  442. if ((*current)->nop == knopList)
  443. {
  444. handler(&(*current)->sxBin.pnode1);
  445. // Advance to the next node
  446. current = &(*current)->sxBin.pnode2;
  447. }
  448. else
  449. {
  450. // The last node
  451. handler(current);
  452. current = nullptr;
  453. }
  454. }
  455. }
  456. template <typename THandler>
  457. static void ForEachItemInList(ParseNodePtr list, THandler handler)
  458. {
  459. ForEachItemRefInList(&list, [&](ParseNodePtr * item) {
  460. Assert(item != nullptr);
  461. handler(*item);
  462. });
  463. }
  464. template <class THandler>
  465. static void MapBindIdentifierFromElement(ParseNodePtr elementNode, THandler handler)
  466. {
  467. ParseNodePtr bindIdentNode = elementNode;
  468. if (bindIdentNode->nop == knopAsg)
  469. {
  470. bindIdentNode = bindIdentNode->sxBin.pnode1;
  471. }
  472. else if (bindIdentNode->nop == knopEllipsis)
  473. {
  474. bindIdentNode = bindIdentNode->sxUni.pnode1;
  475. }
  476. if (bindIdentNode->IsPattern())
  477. {
  478. MapBindIdentifier(bindIdentNode, handler);
  479. }
  480. else if (bindIdentNode->IsVarLetOrConst())
  481. {
  482. handler(bindIdentNode);
  483. }
  484. else
  485. {
  486. AssertMsg(bindIdentNode->nop == knopEmpty, "Invalid bind identifier");
  487. }
  488. }
  489. template <class THandler>
  490. static void MapBindIdentifier(ParseNodePtr patternNode, THandler handler)
  491. {
  492. if (patternNode->nop == knopAsg)
  493. {
  494. patternNode = patternNode->sxBin.pnode1;
  495. }
  496. Assert(patternNode->IsPattern());
  497. if (patternNode->nop == knopArrayPattern)
  498. {
  499. ForEachItemInList(patternNode->sxArrLit.pnode1, [&](ParseNodePtr item) {
  500. MapBindIdentifierFromElement(item, handler);
  501. });
  502. }
  503. else
  504. {
  505. ForEachItemInList(patternNode->sxUni.pnode1, [&](ParseNodePtr item) {
  506. Assert(item->nop == knopObjectPatternMember);
  507. MapBindIdentifierFromElement(item->sxBin.pnode2, handler);
  508. });
  509. }
  510. }
  511. private:
  512. struct IdentToken
  513. {
  514. tokens tk;
  515. IdentPtr pid;
  516. charcount_t ichMin;
  517. charcount_t ichLim;
  518. IdentToken()
  519. : tk(tkNone), pid(NULL)
  520. {
  521. }
  522. };
  523. void CheckArguments(ParseNodePtr pnode);
  524. void CheckArgumentsUse(IdentPtr pid, ParseNodePtr pnodeFnc);
  525. void CheckStrictModeEvalArgumentsUsage(IdentPtr pid, ParseNodePtr pnode = NULL);
  526. // environments on which the strict mode is set, if found
  527. enum StrictModeEnvironment
  528. {
  529. SM_NotUsed, // StrictMode environment is don't care
  530. SM_OnGlobalCode, // The current environment is a global code
  531. SM_OnFunctionCode, // The current environment is a function code
  532. SM_DeferredParse // StrictMode used in deferred parse cases
  533. };
  534. template<bool buildAST> ParseNodePtr ParseArrayLiteral();
  535. template<bool buildAST> ParseNodePtr ParseStatement();
  536. template<bool buildAST> ParseNodePtr ParseVariableDeclaration(
  537. tokens declarationType,
  538. charcount_t ichMin,
  539. BOOL fAllowIn = TRUE,
  540. BOOL* pfForInOk = nullptr,
  541. BOOL singleDefOnly = FALSE,
  542. BOOL allowInit = TRUE,
  543. BOOL isTopVarParse = TRUE,
  544. BOOL isFor = FALSE,
  545. BOOL* nativeForOk = nullptr);
  546. BOOL TokIsForInOrForOf();
  547. template<bool buildAST>
  548. void ParseStmtList(
  549. ParseNodePtr *ppnodeList,
  550. ParseNodePtr **pppnodeLast = NULL,
  551. StrictModeEnvironment smEnvironment = SM_NotUsed,
  552. const bool isSourceElementList = false,
  553. bool* strictModeOn = NULL);
  554. bool FastScanFormalsAndBody();
  555. bool ScanAheadToFunctionEnd(uint count);
  556. bool DoParallelParse(ParseNodePtr pnodeFnc) const;
  557. // TODO: We should really call this StartScope and separate out the notion of scopes and blocks;
  558. // blocks refer to actual curly braced syntax, whereas scopes contain symbols. All blocks have
  559. // a scope, but some statements like for loops or the with statement introduce a block-less scope.
  560. template<bool buildAST> ParseNodePtr StartParseBlock(PnodeBlockType blockType, ScopeType scopeType, ParseNodePtr pnodeLabel = NULL, LabelId* pLabelId = NULL);
  561. template<bool buildAST> ParseNodePtr StartParseBlockWithCapacity(PnodeBlockType blockType, ScopeType scopeType, int capacity);
  562. template<bool buildAST> ParseNodePtr StartParseBlockHelper(PnodeBlockType blockType, Scope *scope, ParseNodePtr pnodeLabel, LabelId* pLabelId);
  563. void PushFuncBlockScope(ParseNodePtr pnodeBlock, ParseNodePtr **ppnodeScopeSave, ParseNodePtr **ppnodeExprScopeSave);
  564. void PopFuncBlockScope(ParseNodePtr *ppnodeScopeSave, ParseNodePtr *ppnodeExprScopeSave);
  565. template<bool buildAST> ParseNodePtr ParseBlock(ParseNodePtr pnodeLabel, LabelId* pLabelId);
  566. void FinishParseBlock(ParseNode *pnodeBlock, bool needScanRCurly = true);
  567. void FinishParseFncExprScope(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncExprScope);
  568. template<const bool backgroundPidRefs>
  569. void BindPidRefs(BlockInfoStack *blockInfo, uint maxBlockId = (uint)-1);
  570. void BindPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint maxBlockId = (uint)-1);
  571. void BindConstPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint maxBlockId = (uint)-1);
  572. template<const bool constBinding>
  573. void BindPidRefsInScopeImpl(IdentPtr pid, Symbol *sym, int blockId, uint maxBlockId = (uint)-1);
  574. void PushScope(Scope *scope);
  575. void PopScope(Scope *scope);
  576. template<bool buildAST> ParseNodePtr ParseArgList(bool *pCallOfConstants, uint16 *pSpreadArgCount, uint16 * pCount);
  577. template<bool buildAST> ParseNodePtr ParseArrayList(bool *pArrayOfTaggedInts, bool *pArrayOfInts, bool *pArrayOfNumbers, bool *pHasMissingValues, uint *count, uint *spreadCount);
  578. template<bool buildAST> ParseNodePtr ParseMemberList(LPCOLESTR pNameHint, ulong *pHintLength, tokens declarationType = tkNone);
  579. template<bool buildAST> ParseNodePtr ParseSuper(ParseNodePtr pnode, bool fAllowCall);
  580. // Used to determine the type of JavaScript object member.
  581. // The values can be combined using bitwise OR.
  582. // specifically, it is valid to have getter and setter at the same time.
  583. enum MemberType
  584. {
  585. MemberTypeDataProperty = 1 << 0, // { foo: 1 },
  586. MemberTypeGetter = 1 << 1, // { get foo() }
  587. MemberTypeSetter = 1 << 2, // { set foo(arg) {} }
  588. MemberTypeMethod = 1 << 3, // { foo() {} }
  589. MemberTypeIdentifier = 1 << 4 // { foo } (shorthand for { foo: foo })
  590. };
  591. // Used to map JavaScript object member name to member type.
  592. typedef JsUtil::BaseDictionary<WCHAR*, MemberType, ArenaAllocator, PrimeSizePolicy> MemberNameToTypeMap;
  593. static MemberNameToTypeMap* CreateMemberNameMap(ArenaAllocator* pAllocator);
  594. template<bool buildAST> void ParseComputedName(ParseNodePtr* ppnodeName, LPCOLESTR* ppNameHint, LPCOLESTR* ppFullNameHint = nullptr, ulong *pNameLength = nullptr, ulong *pShortNameOffset = nullptr);
  595. template<bool buildAST> ParseNodePtr ParseMemberGetSet(OpCode nop, LPCOLESTR* ppNameHint);
  596. template<bool buildAST> ParseNodePtr ParseFncDecl(ushort flags, LPCOLESTR pNameHint = NULL, const bool needsPIDOnRCurlyScan = false, bool resetParsingSuperRestrictionState = true, bool fUnaryOrParen = false);
  597. template<bool buildAST> bool ParseFncNames(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, ushort flags, ParseNodePtr **pLastNodeRef);
  598. template<bool buildAST> void ParseFncFormals(ParseNodePtr pnodeFnc, ushort flags);
  599. template<bool buildAST> bool ParseFncDeclHelper(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, LPCOLESTR pNameHint, ushort flags, bool *pHasName, bool fUnaryOrParen, bool noStmtContext, bool *pNeedScanRCurly);
  600. template<bool buildAST> void ParseExpressionLambdaBody(ParseNodePtr pnodeFnc);
  601. bool FncDeclAllowedWithoutContext(ushort flags);
  602. void FinishFncDecl(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, ParseNodePtr *lastNodeRef);
  603. void ParseTopLevelDeferredFunc(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, LPCOLESTR pNameHint);
  604. void ParseNestedDeferredFunc(ParseNodePtr pnodeFnc, bool fLambda, bool *pNeedScanRCurly, bool *pStrictModeTurnedOn);
  605. void CheckStrictFormalParameters();
  606. void AddArgumentsNodeToVars(ParseNodePtr pnodeFnc);
  607. void UpdateOrCheckForDuplicateInFormals(IdentPtr pid, SList<IdentPtr> *formals);
  608. void TransformAsyncFncDeclAST(ParseNodePtr *pnodeBody, bool fLambda);
  609. ParseNodePtr CreateAsyncSpawnGenerator();
  610. LPCOLESTR GetFunctionName(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint);
  611. uint CalculateFunctionColumnNumber();
  612. template<bool buildAST> ParseNodePtr GenerateEmptyConstructor(bool extends = false);
  613. IdentPtr ParseClassPropertyName(IdentPtr * hint);
  614. template<bool buildAST> ParseNodePtr ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, ulong *pHintLength, ulong *pShortNameOffset);
  615. template<bool buildAST> ParseNodePtr ParseStringTemplateDecl(ParseNodePtr pnodeTagFnc);
  616. // This is used in the es6 class pattern.
  617. LPCOLESTR ConstructFinalHintNode(IdentPtr pClassName, IdentPtr pMemberName, IdentPtr pGetSet, bool isStatic, ulong* nameLength, ulong* pShortNameOffset, bool isComputedName = false, LPCOLESTR pMemberNameHint = nullptr);
  618. // Construct the name from the parse node.
  619. LPCOLESTR FormatPropertyString(LPCOLESTR propertyString, ParseNodePtr pNode, ulong *fullNameHintLength, ulong *pShortNameOffset);
  620. LPCOLESTR ConstructNameHint(ParseNodePtr pNode, ulong* fullNameHintLength, ulong *pShortNameOffset);
  621. LPCOLESTR AppendNameHints(IdentPtr left, IdentPtr right, ulong *pNameLength, ulong *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  622. LPCOLESTR AppendNameHints(IdentPtr left, LPCOLESTR right, ulong *pNameLength, ulong *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  623. LPCOLESTR AppendNameHints(LPCOLESTR left, IdentPtr right, ulong *pNameLength, ulong *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  624. LPCOLESTR AppendNameHints(LPCOLESTR left, LPCOLESTR right, ulong *pNameLength, ulong *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  625. LPCOLESTR AppendNameHints(LPCOLESTR leftStr, ulong leftLen, LPCOLESTR rightStr, ulong rightLen, ulong *pNameLength, ulong *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  626. WCHAR * AllocateStringOfLength(ulong length);
  627. void FinishFncNode(ParseNodePtr pnodeFnc);
  628. template<bool buildAST> bool ParseOptionalExpr(
  629. ParseNodePtr* pnode,
  630. bool fUnaryOrParen = false,
  631. int oplMin = koplNo,
  632. BOOL *pfCanAssign = NULL,
  633. BOOL fAllowIn = TRUE,
  634. BOOL fAllowEllipsis = FALSE,
  635. _Inout_opt_ IdentToken* pToken = NULL);
  636. template<bool buildAST> ParseNodePtr ParseExpr(
  637. int oplMin = koplNo,
  638. BOOL *pfCanAssign = NULL,
  639. BOOL fAllowIn = TRUE,
  640. BOOL fAllowEllipsis = FALSE,
  641. LPCOLESTR pHint = NULL,
  642. ulong *pHintLength = nullptr,
  643. ulong *pShortNameOffset = nullptr,
  644. _Inout_opt_ IdentToken* pToken = NULL,
  645. bool fUnaryOrParen = false,
  646. _Inout_opt_ bool* pfLikelyPattern = nullptr);
  647. template<bool buildAST> ParseNodePtr ParseTerm(
  648. BOOL fAllowCall = TRUE,
  649. LPCOLESTR pNameHint = nullptr,
  650. ulong *pHintLength = nullptr,
  651. ulong *pShortNameOffset = nullptr,
  652. _Inout_opt_ IdentToken* pToken = nullptr,
  653. bool fUnaryOrParen = false,
  654. _Out_opt_ BOOL* pfCanAssign = nullptr,
  655. _Inout_opt_ BOOL* pfLikelyPattern = nullptr);
  656. template<bool buildAST> ParseNodePtr ParsePostfixOperators(ParseNodePtr pnode,
  657. BOOL fAllowCall, BOOL fInNew, BOOL *pfCanAssign, _Inout_ IdentToken* pToken);
  658. void ThrowNewTargetSyntaxErrForGlobalScope();
  659. template<bool buildAST> ParseNodePtr ParseMetaProperty(
  660. tokens metaParentKeyword,
  661. charcount_t ichMin,
  662. _Out_opt_ BOOL* pfCanAssign = nullptr);
  663. bool IsImportOrExportStatementValidHere();
  664. template<bool buildAST> ParseNodePtr ParseImportDeclaration();
  665. template<bool buildAST> void ParseImportClause(ModuleImportEntryList* importEntryList, bool parsingAfterComma = false);
  666. template<bool buildAST> ParseNodePtr ParseExportDeclaration();
  667. template<bool buildAST> void ParseNamedImportOrExportClause(ModuleImportEntryList* importEntryList, ModuleExportEntryList* exportEntryList, bool isExportClause);
  668. template<bool buildAST> IdentPtr ParseImportOrExportFromClause(bool throwIfNotFound);
  669. BOOL NodeIsIdent(ParseNodePtr pnode, IdentPtr pid);
  670. BOOL NodeIsEvalName(ParseNodePtr pnode);
  671. BOOL IsJSONValid(ParseNodePtr pnodeExpr)
  672. {
  673. OpCode jnop = (knopNeg == pnodeExpr->nop) ? pnodeExpr->sxUni.pnode1->nop : pnodeExpr->nop;
  674. if (knopNeg == pnodeExpr->nop)
  675. {
  676. return (knopInt == jnop || knopFlt == jnop);
  677. }
  678. else
  679. {
  680. return (knopInt == jnop || knopFlt == jnop ||
  681. knopStr == jnop || knopNull == jnop ||
  682. knopTrue == jnop || knopFalse == jnop ||
  683. knopObject == jnop || knopArray == jnop);
  684. }
  685. }
  686. BOOL IsConstantInFunctionCall(ParseNodePtr pnode);
  687. BOOL IsConstantInArrayLiteral(ParseNodePtr pnode);
  688. ParseNodePtr CreateParamPatternNode(ParseNodePtr pnode1);
  689. ParseNodePtr ConvertMemberToMemberPattern(ParseNodePtr pnodeMember);
  690. ParseNodePtr ConvertObjectToObjectPattern(ParseNodePtr pnodeMemberList);
  691. ParseNodePtr GetRightSideNodeFromPattern(ParseNodePtr pnode);
  692. ParseNodePtr ConvertArrayToArrayPattern(ParseNodePtr pnode);
  693. ParseNodePtr ConvertToPattern(ParseNodePtr pnode);
  694. void AppendToList(ParseNodePtr * node, ParseNodePtr nodeToAppend);
  695. bool IsES6DestructuringEnabled() const;
  696. bool IsPossiblePatternStart() const { return m_token.tk == tkLCurly || m_token.tk == tkLBrack; }
  697. bool IsPostFixOperators() const
  698. {
  699. return m_token.tk == tkLParen ||
  700. m_token.tk == tkLBrack ||
  701. m_token.tk == tkDot ||
  702. m_token.tk == tkStrTmplBasic ||
  703. m_token.tk == tkStrTmplBegin;
  704. }
  705. template<bool buildAST> ParseNodePtr ParseTryCatchFinally();
  706. template<bool buildAST> ParseNodePtr ParseTry();
  707. template<bool buildAST> ParseNodePtr ParseCatch();
  708. template<bool buildAST> ParseNodePtr ParseFinally();
  709. template<bool buildAST> ParseNodePtr ParseCase(ParseNodePtr *ppnodeBody);
  710. template<bool buildAST> ParseNodePtr ParseRegExp();
  711. template <bool buildAST>
  712. ParseNodePtr ParseDestructuredArrayLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  713. template <bool buildAST>
  714. ParseNodePtr ParseDestructuredObjectLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  715. template <bool buildAST>
  716. ParseNodePtr ParseDestructuredLiteral(tokens declarationType,
  717. bool isDecl,
  718. bool topLevel = true,
  719. DestructuringInitializerContext initializerContext = DIC_None,
  720. bool allowIn = true,
  721. BOOL *forInOfOkay = nullptr,
  722. BOOL *nativeForOkay = nullptr);
  723. template <bool buildAST>
  724. ParseNodePtr ParseDestructuredVarDecl(tokens declarationType, bool isDecl, bool *hasSeenRest, bool topLevel = true);
  725. template <bool buildAST>
  726. ParseNodePtr ParseDestructuredInitializer(ParseNodePtr lhsNode,
  727. bool isDecl,
  728. bool topLevel,
  729. DestructuringInitializerContext initializerContext,
  730. bool allowIn,
  731. BOOL *forInOfOkay,
  732. BOOL *nativeForOkay);
  733. template<bool CheckForNegativeInfinity> static bool IsNaNOrInfinityLiteral(LPCOLESTR str);
  734. void ParseDestructuredLiteralWithScopeSave(tokens declarationType,
  735. bool isDecl,
  736. bool topLevel,
  737. DestructuringInitializerContext initializerContext = DIC_None,
  738. bool allowIn = true);
  739. public:
  740. void ValidateSourceElementList();
  741. void ValidateFormals();
  742. bool IsStrictMode() const;
  743. BOOL ExpectingExternalSource();
  744. IdentPtr GetArgumentsPid() const { return wellKnownPropertyPids.arguments; }
  745. IdentPtr GetEvalPid() const { return wellKnownPropertyPids.eval; }
  746. IdentPtr GetTargetPid() const { return wellKnownPropertyPids.target; }
  747. BackgroundParseItem *GetCurrBackgroundParseItem() const { return currBackgroundParseItem; }
  748. void SetCurrBackgroundParseItem(BackgroundParseItem *item) { currBackgroundParseItem = item; }
  749. void Release()
  750. {
  751. RELEASEPTR(m_pscan);
  752. RELEASEPTR(m_phtbl);
  753. }
  754. private:
  755. void DeferOrEmitPotentialSpreadError(ParseNodePtr pnodeT);
  756. template<bool buildAST> void TrackAssignment(ParseNodePtr pnodeT, IdentToken* pToken, charcount_t ichMin, charcount_t ichLim);
  757. PidRefStack* PushPidRef(IdentPtr pid);
  758. PidRefStack* FindOrAddPidRef(IdentPtr pid, int blockId, int maxScopeId = -1);
  759. void RemovePrevPidRef(IdentPtr pid, PidRefStack *lastRef);
  760. void SetPidRefsInScopeDynamic(IdentPtr pid, int blockId);
  761. void RestoreScopeInfo(Js::FunctionBody* functionBody);
  762. void FinishScopeInfo(Js::FunctionBody* functionBody);
  763. BOOL PnodeLabelNoAST(IdentToken* pToken, LabelId* pLabelIdList);
  764. LabelId* CreateLabelId(IdentToken* pToken);
  765. void AddToNodeList(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  766. void AddToNodeListEscapedUse(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  767. void ChkCurTokNoScan(int tk, int wErr)
  768. {
  769. if (m_token.tk != tk)
  770. {
  771. Error(wErr);
  772. }
  773. }
  774. void ChkCurTok(int tk, int wErr)
  775. {
  776. if (m_token.tk != tk)
  777. {
  778. Error(wErr);
  779. }
  780. else
  781. {
  782. m_pscan->Scan();
  783. }
  784. }
  785. void ChkNxtTok(int tk, int wErr)
  786. {
  787. m_pscan->Scan();
  788. ChkCurTok(tk, wErr);
  789. }
  790. template <class Fn>
  791. void VisitFunctionsInScope(ParseNodePtr pnodeScopeList, Fn fn);
  792. void FinishDeferredFunction(ParseNodePtr pnodeScopeList);
  793. /***********************************************************************
  794. Misc
  795. ***********************************************************************/
  796. bool m_UsesArgumentsAtGlobal; // "arguments" used at global code.
  797. BOOL m_fUseStrictMode; // ES5 Use Strict mode. In AST mode this is a global flag; in NoAST mode it is pushed and popped.
  798. bool m_InAsmMode; // Currently parsing Asm.Js module
  799. bool m_deferAsmJs;
  800. BOOL m_fExpectExternalSource;
  801. BOOL m_deferringAST;
  802. BOOL m_stoppedDeferredParse;
  803. enum FncDeclFlag : ushort
  804. {
  805. fFncNoFlgs = 0,
  806. fFncDeclaration = 1 << 0,
  807. fFncNoArg = 1 << 1,
  808. fFncOneArg = 1 << 2, //Force exactly one argument.
  809. fFncNoName = 1 << 3,
  810. fFncLambda = 1 << 4,
  811. fFncMethod = 1 << 5,
  812. fFncClassMember = 1 << 6,
  813. fFncGenerator = 1 << 7,
  814. fFncAsync = 1 << 8,
  815. };
  816. //
  817. // If we need the scanner to force PID creation temporarily, use this auto object
  818. // to turn scanner deferred parsing off temporarily and restore at destructor.
  819. //
  820. class AutoTempForcePid
  821. {
  822. private:
  823. Scanner_t* m_scanner;
  824. bool m_forcePid;
  825. BYTE m_oldScannerDeferredParseFlags;
  826. public:
  827. AutoTempForcePid(Scanner_t* scanner, bool forcePid)
  828. : m_scanner(scanner), m_forcePid(forcePid)
  829. {
  830. if (forcePid)
  831. {
  832. m_oldScannerDeferredParseFlags = scanner->SetDeferredParse(FALSE);
  833. }
  834. }
  835. ~AutoTempForcePid()
  836. {
  837. if (m_forcePid)
  838. {
  839. m_scanner->SetDeferredParseFlags(m_oldScannerDeferredParseFlags);
  840. }
  841. }
  842. };
  843. public:
  844. charcount_t GetSourceIchLim() { return m_sourceLim; }
  845. static BOOL NodeEqualsName(ParseNodePtr pnode, LPCOLESTR sz, ulong cch);
  846. };