2
0

Parse.h 44 KB

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