Parse.h 45 KB

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