Parse.h 51 KB

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