parse.h 40 KB

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