Parse.h 42 KB

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