Parse.h 47 KB

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