Parse.h 41 KB

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