Parse.h 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230
  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, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""));
  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 CheckContextualKeyword(IdentPtr keywordPid)
  284. {
  285. if (m_token.tk == tkID && !GetScanner()->LastIdentifierHasEscape())
  286. {
  287. IdentPtr pid = m_token.GetIdentifier(GetHashTbl());
  288. return pid == keywordPid;
  289. }
  290. return false;
  291. }
  292. bool IsCurBlockInLoop() const;
  293. void InitPids();
  294. /***********************************************************************
  295. Members needed just for parsing.
  296. ***********************************************************************/
  297. protected:
  298. Token m_token;
  299. Scanner_t m_scan;
  300. Scanner_t const * GetScanner() const { return &m_scan; }
  301. Scanner_t * GetScanner() { return &m_scan; }
  302. void AddAstSize(int size);
  303. void AddAstSizeAllowDefer(int size);
  304. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT() { return CreateNodeForOpT<nop>(this->GetScanner()->IchMinTok()); }
  305. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT(charcount_t ichMin) { return CreateNodeForOpT<nop>(ichMin, this->GetScanner()->IchLimTok()); }
  306. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT(charcount_t ichMin, charcount_t ichLim);
  307. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT() { return CreateAllowDeferNodeForOpT<nop>(this->GetScanner()->IchMinTok()); }
  308. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT(charcount_t ichMin) { return CreateAllowDeferNodeForOpT<nop>(ichMin, this->GetScanner()->IchLimTok()); }
  309. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT(charcount_t ichMin, charcount_t ichLim);
  310. public:
  311. // create nodes using arena allocator; used by AST transformation
  312. template <OpCode nop>
  313. static typename OpCodeTrait<nop>::ParseNodeType * StaticCreateNodeT(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0)
  314. {
  315. return Anew(alloc, typename OpCodeTrait<nop>::ParseNodeType, nop, ichMin, ichLim);
  316. }
  317. static ParseNodeBin * StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0);
  318. static ParseNodeBlock * StaticCreateBlockNode(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, int blockId = -1, PnodeBlockType blockType = PnodeBlockType::Regular);
  319. static ParseNodeVar * StaticCreateTempNode(ParseNode* initExpr, ArenaAllocator* alloc);
  320. static ParseNodeUni * StaticCreateTempRef(ParseNode* tempNode, ArenaAllocator* alloc);
  321. private:
  322. ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnodeOp);
  323. ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_t ichMin, charcount_t ichLim);
  324. ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  325. ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim);
  326. ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3);
  327. ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3, charcount_t ichMin, charcount_t ichLim);
  328. ParseNodeBlock * CreateBlockNode(PnodeBlockType blockType = PnodeBlockType::Regular);
  329. ParseNodeBlock * CreateBlockNode(charcount_t ichMin, charcount_t ichLim, PnodeBlockType blockType = PnodeBlockType::Regular);
  330. ParseNodeVar * CreateDeclNode(OpCode nop, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl = true);
  331. ParseNodeInt * CreateIntNode(int32 lw);
  332. ParseNodeStr * CreateStrNode(IdentPtr pid);
  333. ParseNodeBigInt * CreateBigIntNode(IdentPtr pid);
  334. ParseNodeName * CreateNameNode(IdentPtr pid);
  335. ParseNodeName * CreateNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);
  336. ParseNodeSpecialName * CreateSpecialNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);
  337. ParseNodeSuperReference * CreateSuperReferenceNode(OpCode nop, ParseNodeSpecialName * pnode1, ParseNodePtr pnode2);
  338. ParseNodeProg * CreateProgNode(bool isModuleSource, ULONG lineNumber);
  339. ParseNodeCall * CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  340. ParseNodeCall * CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim);
  341. ParseNodeSuperCall * CreateSuperCallNode(ParseNodeSpecialName * pnode1, ParseNodePtr pnode2);
  342. ParseNodeFnc * CreateDummyFuncNode(bool fDeclaration);
  343. ParseNodeParamPattern * CreateParamPatternNode(ParseNodePtr pnode1);
  344. ParseNodeParamPattern * CreateDummyParamPatternNode(charcount_t ichMin);
  345. ParseNodeObjLit * CreateObjectPatternNode(ParseNodePtr pnodeMemberList, charcount_t ichMin, charcount_t ichLim, bool convertToPattern=false);
  346. Symbol* AddDeclForPid(ParseNodeVar * pnode, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl);
  347. void CheckRedeclarationErrorForBlockId(IdentPtr pid, int blockId);
  348. public:
  349. #if ENABLE_BACKGROUND_PARSING
  350. void PrepareForBackgroundParse();
  351. void AddFastScannedRegExpNode(ParseNodePtr const pnode);
  352. void AddBackgroundRegExpNode(ParseNodePtr const pnode);
  353. void AddBackgroundParseItem(BackgroundParseItem *const item);
  354. void FinishBackgroundRegExpNodes();
  355. void FinishBackgroundPidRefs(BackgroundParseItem *const item, bool isOtherParser);
  356. void WaitForBackgroundJobs(BackgroundParser *bgp, CompileScriptException *pse);
  357. HRESULT ParseFunctionInBackground(ParseNodeFnc * pnodeFnc, ParseContext *parseContext, bool topLevelDeferred, CompileScriptException *pse);
  358. #endif
  359. void CheckPidIsValid(IdentPtr pid, bool autoArgumentsObject = false);
  360. void AddVarDeclToBlock(ParseNodeVar *pnode);
  361. // Add a var declaration. Only use while parsing. Assumes m_ppnodeVar is pointing to the right place already
  362. ParseNodeVar * CreateVarDeclNode(IdentPtr pid, SymbolType symbolType, bool autoArgumentsObject = false, ParseNodePtr pnodeFnc = NULL, bool checkReDecl = true);
  363. // Add a var declaration, during parse tree rewriting. Will setup m_ppnodeVar for the given pnodeFnc
  364. ParseNodeVar * AddVarDeclNode(IdentPtr pid, ParseNodeFnc * pnodeFnc);
  365. // Add a 'const' or 'let' declaration.
  366. ParseNodeVar * CreateBlockScopedDeclNode(IdentPtr pid, OpCode nodeType);
  367. void RegisterRegexPattern(UnifiedRegex::RegexPattern *const regexPattern);
  368. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  369. LPCWSTR GetParseType() const
  370. {
  371. switch(m_parseType)
  372. {
  373. case ParseType_Upfront:
  374. return _u("Upfront");
  375. case ParseType_Deferred:
  376. return _u("Deferred");
  377. }
  378. Assert(false);
  379. return NULL;
  380. }
  381. #endif
  382. void CaptureContext(ParseContext *parseContext) const;
  383. void RestoreContext(ParseContext *const parseContext);
  384. int GetLastBlockId() const { Assert(m_nextBlockId > 0); return m_nextBlockId - 1; }
  385. private:
  386. ParseNodeFnc * m_currentNodeNonLambdaFunc; // current function or NULL
  387. ParseNodeFnc * m_currentNodeNonLambdaDeferredFunc; // current function or NULL
  388. ParseNodeFnc * m_currentNodeFunc; // current function or NULL
  389. ParseNodeFnc * m_currentNodeDeferredFunc; // current function or NULL
  390. ParseNodeProg * m_currentNodeProg; // current program
  391. DeferredFunctionStub *m_currDeferredStub;
  392. uint m_currDeferredStubCount;
  393. int32 * m_pCurrentAstSize;
  394. ParseNodePtr * m_ppnodeScope; // function list tail
  395. ParseNodePtr * m_ppnodeExprScope; // function expression list tail
  396. ParseNodePtr * m_ppnodeVar; // variable list tail
  397. bool m_inDeferredNestedFunc; // true if parsing a function in deferred mode, nested within the current node
  398. bool m_reparsingLambdaParams;
  399. bool m_disallowImportExportStmt;
  400. bool m_isInParsingArgList;
  401. bool m_hasDestructuringPattern;
  402. // This bool is used for deferring the shorthand initializer error ( {x = 1}) - as it is allowed in the destructuring grammar.
  403. bool m_hasDeferredShorthandInitError;
  404. bool m_deferEllipsisError;
  405. bool m_deferCommaError;
  406. uint * m_pnestedCount; // count of functions nested at one level below the current node
  407. struct WellKnownPropertyPids
  408. {
  409. IdentPtr arguments;
  410. IdentPtr async;
  411. IdentPtr eval;
  412. IdentPtr set;
  413. IdentPtr get;
  414. IdentPtr let;
  415. IdentPtr await;
  416. IdentPtr constructor;
  417. IdentPtr prototype;
  418. IdentPtr __proto__;
  419. IdentPtr of;
  420. IdentPtr target;
  421. IdentPtr from;
  422. IdentPtr as;
  423. IdentPtr meta;
  424. IdentPtr _default;
  425. IdentPtr _star; // Special '*' identifier for modules
  426. IdentPtr _this; // Special 'this' identifier
  427. IdentPtr _newTarget; // Special new.target identifier
  428. IdentPtr _super; // Special super identifier
  429. IdentPtr _superConstructor; // Special super constructor identifier
  430. IdentPtr _importMeta; // Special import.meta identifier
  431. };
  432. WellKnownPropertyPids wellKnownPropertyPids;
  433. charcount_t m_sourceLim; // The actual number of characters parsed.
  434. Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
  435. ParseType m_parseType;
  436. uint m_arrayDepth;
  437. uint m_funcInArrayDepth; // Count func depth within array literal
  438. charcount_t m_funcInArray;
  439. uint m_scopeCountNoAst;
  440. // Used for issuing spread and rest errors when there is ambiguity with lambda parameter lists and parenthesized expressions
  441. uint m_funcParenExprDepth;
  442. RestorePoint m_deferEllipsisErrorLoc;
  443. RestorePoint m_deferCommaErrorLoc;
  444. 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
  445. StmtNest *m_pstmtCur; // current statement or NULL
  446. BlockInfoStack *m_currentBlockInfo;
  447. Scope *m_currentScope;
  448. BackgroundParseItem *currBackgroundParseItem;
  449. BackgroundParseItem *backgroundParseItems;
  450. typedef DList<ParseNodePtr, ArenaAllocator> NodeDList;
  451. NodeDList* fastScannedRegExpNodes;
  452. BlockIdsStack *m_currentDynamicBlock;
  453. int GetCurrentDynamicBlockId() const;
  454. void AppendFunctionToScopeList(bool fDeclaration, ParseNodeFnc * pnodeFnc);
  455. // block scoped content helpers
  456. void SetCurrentStatement(StmtNest *stmt);
  457. ParseNodeBlock* GetCurrentBlock();
  458. ParseNodeBlock* GetFunctionBlock();
  459. BlockInfoStack* GetCurrentBlockInfo();
  460. BlockInfoStack* GetCurrentFunctionBlockInfo();
  461. ParseNodeFnc *GetCurrentFunctionNode();
  462. ParseNodeFnc *GetCurrentNonLambdaFunctionNode();
  463. bool NextTokenConfirmsLetDecl() const { return m_token.tk == tkID || m_token.tk == tkLBrack || m_token.tk == tkLCurly || m_token.IsReservedWord(); }
  464. 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(); }
  465. template<bool buildAST>
  466. void PushStmt(StmtNest *pStmt, ParseNodeStmt * pnode, OpCode op, LabelId* pLabelIdList)
  467. {
  468. if (buildAST)
  469. {
  470. pnode->grfnop = 0;
  471. pnode->pnodeOuter = (NULL == m_pstmtCur) ? NULL : m_pstmtCur->pnodeStmt;
  472. pStmt->pnodeStmt = pnode;
  473. }
  474. else
  475. {
  476. // Assign to pnodeStmt rather than op so that we initialize the whole field.
  477. pStmt->pnodeStmt = 0;
  478. pStmt->isDeferred = true;
  479. pStmt->op = op;
  480. }
  481. pStmt->pLabelId = pLabelIdList;
  482. pStmt->pstmtOuter = m_pstmtCur;
  483. SetCurrentStatement(pStmt);
  484. }
  485. void PopStmt(StmtNest *pStmt);
  486. BlockInfoStack *PushBlockInfo(ParseNodeBlock * pnodeBlock);
  487. void PopBlockInfo();
  488. void PushDynamicBlock();
  489. void PopDynamicBlock();
  490. void MarkEvalCaller()
  491. {
  492. if (this->GetCurrentFunctionNode())
  493. {
  494. ParseNodeFnc *pnodeFunc = GetCurrentFunctionNode();
  495. pnodeFunc->SetCallsEval(true);
  496. }
  497. ParseNodeBlock *pnodeBlock = GetCurrentBlock();
  498. if (pnodeBlock != NULL)
  499. {
  500. pnodeBlock->SetCallsEval(true);
  501. PushDynamicBlock();
  502. }
  503. }
  504. struct ParserState
  505. {
  506. ParseNodePtr *m_ppnodeScopeSave;
  507. ParseNodePtr *m_ppnodeExprScopeSave;
  508. charcount_t m_funcInArraySave;
  509. int32 *m_pCurrentAstSizeSave;
  510. uint m_funcInArrayDepthSave;
  511. uint m_nestedCountSave;
  512. int m_nextBlockId;
  513. #if DEBUG
  514. // For very basic validation purpose - to check that we are not going restore to some other block.
  515. BlockInfoStack *m_currentBlockInfo;
  516. #endif
  517. };
  518. class AutoDeferErrorsRestore
  519. {
  520. public:
  521. AutoDeferErrorsRestore(Parser *p)
  522. : m_parser(p)
  523. {
  524. m_deferEllipsisErrorSave = m_parser->m_deferEllipsisError;
  525. m_deferCommaError = m_parser->m_deferCommaError;
  526. m_ellipsisErrorLocSave = m_parser->m_deferEllipsisErrorLoc;
  527. m_commaErrorLocSave = m_parser->m_deferCommaErrorLoc;
  528. }
  529. ~AutoDeferErrorsRestore()
  530. {
  531. m_parser->m_deferEllipsisError = m_deferEllipsisErrorSave;
  532. m_parser->m_deferCommaError = m_deferCommaError;
  533. m_parser->m_deferEllipsisErrorLoc = m_ellipsisErrorLocSave;
  534. m_parser->m_deferCommaErrorLoc = m_commaErrorLocSave;
  535. }
  536. private:
  537. Parser *m_parser;
  538. RestorePoint m_ellipsisErrorLocSave;
  539. RestorePoint m_commaErrorLocSave;
  540. bool m_deferEllipsisErrorSave;
  541. bool m_deferCommaError;
  542. };
  543. // This function is going to capture some of the important current state of the parser to an object. Once we learn
  544. // that we need to reparse the grammar again we could use RestoreStateFrom to restore that state to the parser.
  545. void CaptureState(ParserState *state);
  546. void RestoreStateFrom(ParserState *state);
  547. // Future recommendation : Consider consolidating Parser::CaptureState and Scanner::Capture together if we do CaptureState more often.
  548. public:
  549. IdentPtrList* GetRequestedModulesList();
  550. ModuleImportOrExportEntryList* GetModuleImportEntryList();
  551. ModuleImportOrExportEntryList* GetModuleLocalExportEntryList();
  552. ModuleImportOrExportEntryList* GetModuleIndirectExportEntryList();
  553. ModuleImportOrExportEntryList* GetModuleStarExportEntryList();
  554. protected:
  555. IdentPtrList* EnsureRequestedModulesList();
  556. ModuleImportOrExportEntryList* EnsureModuleImportEntryList();
  557. ModuleImportOrExportEntryList* EnsureModuleLocalExportEntryList();
  558. ModuleImportOrExportEntryList* EnsureModuleIndirectExportEntryList();
  559. ModuleImportOrExportEntryList* EnsureModuleStarExportEntryList();
  560. void AddModuleSpecifier(IdentPtr moduleRequest);
  561. ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest, charcount_t offsetForError = 0);
  562. ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, ModuleImportOrExportEntry* importOrExportEntry);
  563. void AddModuleLocalExportEntry(ParseNodePtr varDeclNode);
  564. void CheckForDuplicateExportEntry(IdentPtr exportName);
  565. void CheckForDuplicateExportEntry(ModuleImportOrExportEntryList* exportEntryList, IdentPtr exportName);
  566. void VerifyModuleLocalExportEntries();
  567. ParseNodeVar * CreateModuleImportDeclNode(IdentPtr localName);
  568. public:
  569. WellKnownPropertyPids* names(){ return &wellKnownPropertyPids; }
  570. IdentPtr CreatePid(__in_ecount(len) LPCOLESTR name, charcount_t len)
  571. {
  572. return this->GetHashTbl()->PidHashNameLen(name, len);
  573. }
  574. bool KnownIdent(__in_ecount(len) LPCOLESTR name, charcount_t len)
  575. {
  576. return this->GetHashTbl()->Contains(name, len);
  577. }
  578. template <typename THandler>
  579. static void ForEachItemRefInList(ParseNodePtr *list, THandler handler)
  580. {
  581. ParseNodePtr *current = list;
  582. while (current != nullptr && (*current) != nullptr)
  583. {
  584. if ((*current)->nop == knopList)
  585. {
  586. handler(&(*current)->AsParseNodeBin()->pnode1);
  587. // Advance to the next node
  588. current = &(*current)->AsParseNodeBin()->pnode2;
  589. }
  590. else
  591. {
  592. // The last node
  593. handler(current);
  594. current = nullptr;
  595. }
  596. }
  597. }
  598. template <typename THandler>
  599. static void ForEachItemInList(ParseNodePtr list, THandler handler)
  600. {
  601. ForEachItemRefInList(&list, [&](ParseNodePtr * item) {
  602. Assert(item != nullptr);
  603. handler(*item);
  604. });
  605. }
  606. template <class THandler>
  607. static void MapBindIdentifierFromElement(ParseNodePtr elementNode, THandler handler)
  608. {
  609. ParseNodePtr bindIdentNode = elementNode;
  610. if (bindIdentNode->nop == knopAsg)
  611. {
  612. bindIdentNode = bindIdentNode->AsParseNodeBin()->pnode1;
  613. }
  614. else if (bindIdentNode->nop == knopEllipsis)
  615. {
  616. bindIdentNode = bindIdentNode->AsParseNodeUni()->pnode1;
  617. }
  618. if (bindIdentNode->IsPattern())
  619. {
  620. MapBindIdentifier(bindIdentNode, handler);
  621. }
  622. else if (bindIdentNode->IsVarLetOrConst())
  623. {
  624. handler(bindIdentNode);
  625. }
  626. else
  627. {
  628. AssertMsg(bindIdentNode->nop == knopEmpty, "Invalid bind identifier");
  629. }
  630. }
  631. template <class THandler>
  632. static void MapBindIdentifier(ParseNodePtr patternNode, THandler handler)
  633. {
  634. if (patternNode->nop == knopAsg)
  635. {
  636. patternNode = patternNode->AsParseNodeBin()->pnode1;
  637. }
  638. Assert(patternNode->IsPattern());
  639. if (patternNode->nop == knopArrayPattern)
  640. {
  641. ForEachItemInList(patternNode->AsParseNodeArrLit()->pnode1, [&](ParseNodePtr item) {
  642. MapBindIdentifierFromElement(item, handler);
  643. });
  644. }
  645. else
  646. {
  647. ForEachItemInList(patternNode->AsParseNodeUni()->pnode1, [&](ParseNodePtr item) {
  648. Assert(item->nop == knopObjectPatternMember || item->nop == knopEllipsis);
  649. if (item->nop == knopObjectPatternMember)
  650. {
  651. MapBindIdentifierFromElement(item->AsParseNodeBin()->pnode2, handler);
  652. }
  653. else
  654. {
  655. MapBindIdentifierFromElement(item->AsParseNodeUni()->pnode1, handler);
  656. }
  657. });
  658. }
  659. }
  660. private:
  661. struct IdentToken
  662. {
  663. tokens tk;
  664. IdentPtr pid;
  665. charcount_t ichMin;
  666. charcount_t ichLim;
  667. IdentToken()
  668. : tk(tkNone), pid(NULL)
  669. {
  670. }
  671. };
  672. void CheckArguments(ParseNodePtr pnode);
  673. void CheckArgumentsUse(IdentPtr pid, ParseNodeFnc * pnodeFnc);
  674. void CheckStrictModeEvalArgumentsUsage(IdentPtr pid, ParseNodePtr pnode = NULL);
  675. // environments on which the strict mode is set, if found
  676. enum StrictModeEnvironment
  677. {
  678. SM_NotUsed, // StrictMode environment is don't care
  679. SM_OnGlobalCode, // The current environment is a global code
  680. SM_OnFunctionCode, // The current environment is a function code
  681. SM_DeferredParse // StrictMode used in deferred parse cases
  682. };
  683. template<bool buildAST> ParseNodeArrLit * ParseArrayLiteral();
  684. template<bool buildAST> ParseNodePtr ParseStatement();
  685. template<bool buildAST> ParseNodePtr ParseVariableDeclaration(
  686. tokens declarationType,
  687. charcount_t ichMin,
  688. BOOL fAllowIn = TRUE,
  689. BOOL* pfForInOk = nullptr,
  690. BOOL singleDefOnly = FALSE,
  691. BOOL allowInit = TRUE,
  692. BOOL isTopVarParse = TRUE,
  693. BOOL isFor = FALSE,
  694. BOOL* nativeForOk = nullptr);
  695. BOOL TokIsForInOrForOf();
  696. template<bool buildAST>
  697. void ParseStmtList(
  698. ParseNodePtr *ppnodeList,
  699. ParseNodePtr **pppnodeLast = NULL,
  700. StrictModeEnvironment smEnvironment = SM_NotUsed,
  701. const bool isSourceElementList = false,
  702. bool* strictModeOn = NULL);
  703. #if ENABLE_BACKGROUND_PARSING
  704. bool FastScanFormalsAndBody();
  705. #endif
  706. bool ScanAheadToFunctionEnd(uint count);
  707. bool DoParallelParse(ParseNodeFnc * pnodeFnc) const;
  708. // TODO: We should really call this StartScope and separate out the notion of scopes and blocks;
  709. // blocks refer to actual curly braced syntax, whereas scopes contain symbols. All blocks have
  710. // a scope, but some statements like for loops or the with statement introduce a block-less scope.
  711. template<bool buildAST> ParseNodeBlock * StartParseBlock(PnodeBlockType blockType, ScopeType scopeType, LabelId* pLabelId = nullptr);
  712. template<bool buildAST> ParseNodeBlock * StartParseBlockWithCapacity(PnodeBlockType blockType, ScopeType scopeType, int capacity);
  713. template<bool buildAST> ParseNodeBlock * StartParseBlockHelper(PnodeBlockType blockType, Scope *scope, LabelId* pLabelId);
  714. void PushFuncBlockScope(ParseNodeBlock * pnodeBlock, ParseNodePtr **ppnodeScopeSave, ParseNodePtr **ppnodeExprScopeSave);
  715. void PopFuncBlockScope(ParseNodePtr *ppnodeScopeSave, ParseNodePtr *ppnodeExprScopeSave);
  716. template<bool buildAST> ParseNodeBlock * ParseBlock(LabelId* pLabelId);
  717. void FinishParseBlock(ParseNodeBlock * pnodeBlock, bool needScanRCurly = true);
  718. void FinishParseFncExprScope(ParseNodeFnc * pnodeFnc, ParseNodeBlock * pnodeFncExprScope);
  719. bool IsSpecialName(IdentPtr pid);
  720. void CreateSpecialSymbolDeclarations(ParseNodeFnc * pnodeFnc);
  721. ParseNodeSpecialName * ReferenceSpecialName(IdentPtr pid, charcount_t ichMin = 0, charcount_t ichLim = 0, bool createNode = false);
  722. ParseNodeVar * CreateSpecialVarDeclIfNeeded(ParseNodeFnc * pnodeFnc, IdentPtr pid, bool forceCreate = false);
  723. void ProcessCapturedNames(ParseNodeFnc* pnodeFnc);
  724. void AddNestedCapturedNames(ParseNodeFnc* pnodeChildFnc);
  725. template<const bool backgroundPidRefs>
  726. void BindPidRefs(BlockInfoStack *blockInfo, uint maxBlockId = (uint)-1);
  727. void BindPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint maxBlockId = (uint)-1);
  728. void MarkEscapingRef(ParseNodePtr pnode, IdentToken *pToken);
  729. void SetNestedFuncEscapes() const;
  730. void SetSymHasNonLocalReference(Symbol *sym);
  731. void PushScope(Scope *scope);
  732. void PopScope(Scope *scope);
  733. template<bool buildAST> ParseNodePtr ParseArgList(bool *pCallOfConstants, uint16 *pSpreadArgCount, uint16 * pCount);
  734. template<bool buildAST> ParseNodePtr ParseArrayList(bool *pArrayOfTaggedInts, bool *pArrayOfInts, bool *pArrayOfNumbers, bool *pHasMissingValues, uint *count, uint *spreadCount);
  735. template<bool buildAST> ParseNodePtr ParseMemberList(LPCOLESTR pNameHint, uint32 *pHintLength, tokens declarationType = tkNone);
  736. template<bool buildAST> IdentPtr ParseSuper(bool fAllowCall);
  737. bool IsTerminateToken(bool fAllowIn);
  738. // Used to determine the type of JavaScript object member.
  739. // The values can be combined using bitwise OR.
  740. // specifically, it is valid to have getter and setter at the same time.
  741. enum MemberType
  742. {
  743. MemberTypeDataProperty = 1 << 0, // { foo: 1 },
  744. MemberTypeGetter = 1 << 1, // { get foo() }
  745. MemberTypeSetter = 1 << 2, // { set foo(arg) {} }
  746. MemberTypeMethod = 1 << 3, // { foo() {} }
  747. MemberTypeIdentifier = 1 << 4 // { foo } (shorthand for { foo: foo })
  748. };
  749. // Used to map JavaScript object member name to member type.
  750. typedef JsUtil::BaseDictionary<WCHAR*, MemberType, ArenaAllocator, PrimeSizePolicy> MemberNameToTypeMap;
  751. static MemberNameToTypeMap* CreateMemberNameMap(ArenaAllocator* pAllocator);
  752. template<bool buildAST> void ParseComputedName(ParseNodePtr* ppnodeName, LPCOLESTR* ppNameHint, LPCOLESTR* ppFullNameHint = nullptr, uint32 *pNameLength = nullptr, uint32 *pShortNameOffset = nullptr);
  753. template<bool buildAST> ParseNodeBin * ParseMemberGetSet(OpCode nop, LPCOLESTR* ppNameHint,size_t iecpMin, charcount_t ichMin);
  754. template<bool buildAST> ParseNode * ParseFncDeclCheckScope(ushort flags, bool fAllowIn = true);
  755. 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);
  756. template<bool buildAST> ParseNodeFnc * ParseFncDeclInternal(ushort flags, LPCOLESTR pNameHint, const bool needsPIDOnRCurlyScan, bool fUnaryOrParen, bool noStmtContext, SuperRestrictionState::State superRestrictionState = SuperRestrictionState::Disallowed, bool fAllowIn = true);
  757. template<bool buildAST> void ParseFncName(ParseNodeFnc * pnodeFnc, ushort flags, IdentPtr* pFncNamePid = nullptr);
  758. template<bool buildAST> void ParseFncFormals(ParseNodeFnc * pnodeFnc, ParseNodeFnc * pnodeParentFnc, ushort flags, bool isTopLevelDeferredFunc = false);
  759. 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);
  760. template<bool buildAST> void ParseExpressionLambdaBody(ParseNodeFnc * pnodeFnc, bool fAllowIn = true);
  761. template<bool buildAST> void UpdateCurrentNodeFunc(ParseNodeFnc * pnodeFnc, bool fLambda);
  762. bool FncDeclAllowedWithoutContext(ushort flags);
  763. void FinishFncDecl(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint, bool fLambda, bool skipCurlyBraces = false, bool fAllowIn = true);
  764. void ParseTopLevelDeferredFunc(ParseNodeFnc * pnodeFnc, ParseNodeFnc * pnodeFncParent, LPCOLESTR pNameHint, bool fLambda, bool *pNeedScanRCurly = nullptr, bool fAllowIn = true);
  765. void ParseNestedDeferredFunc(ParseNodeFnc * pnodeFnc, bool fLambda, bool *pNeedScanRCurly, bool *pStrictModeTurnedOn, bool fAllowIn = true);
  766. void CheckStrictFormalParameters();
  767. ParseNodeVar * AddArgumentsNodeToVars(ParseNodeFnc * pnodeFnc);
  768. ParseNodeVar * InsertVarAtBeginning(ParseNodeFnc * pnodeFnc, IdentPtr pid);
  769. ParseNodeVar * CreateSpecialVarDeclNode(ParseNodeFnc * pnodeFnc, IdentPtr pid);
  770. void UpdateArgumentsNode(ParseNodeFnc * pnodeFnc, ParseNodeVar * argNode);
  771. void UpdateOrCheckForDuplicateInFormals(IdentPtr pid, SList<IdentPtr> *formals);
  772. LPCOLESTR GetFunctionName(ParseNodeFnc * pnodeFnc, LPCOLESTR pNameHint);
  773. uint CalculateFunctionColumnNumber();
  774. template<bool buildAST> ParseNodeFnc * GenerateEmptyConstructor(bool extends = false);
  775. template<bool buildAST> ParseNodePtr GenerateModuleFunctionWrapper();
  776. IdentPtr ParseClassPropertyName(IdentPtr * hint);
  777. template<bool buildAST> ParseNodeClass * ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, uint32 *pHintLength, uint32 *pShortNameOffset);
  778. template<bool buildAST> ParseNodePtr ParseStringTemplateDecl(ParseNodePtr pnodeTagFnc);
  779. // This is used in the es6 class pattern.
  780. LPCOLESTR ConstructFinalHintNode(IdentPtr pClassName, IdentPtr pMemberName, IdentPtr pGetSet, bool isStatic, uint32* nameLength, uint32* pShortNameOffset, bool isComputedName = false, LPCOLESTR pMemberNameHint = nullptr);
  781. // Construct the name from the parse node.
  782. LPCOLESTR FormatPropertyString(LPCOLESTR propertyString, ParseNodePtr pNode, uint32 *fullNameHintLength, uint32 *pShortNameOffset);
  783. LPCOLESTR ConstructNameHint(ParseNodeBin * pNode, uint32* fullNameHintLength, uint32 *pShortNameOffset);
  784. LPCOLESTR AppendNameHints(IdentPtr left, IdentPtr right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  785. LPCOLESTR AppendNameHints(IdentPtr left, LPCOLESTR right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  786. LPCOLESTR AppendNameHints(LPCOLESTR left, IdentPtr right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  787. LPCOLESTR AppendNameHints(LPCOLESTR left, LPCOLESTR right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  788. LPCOLESTR AppendNameHints(LPCOLESTR leftStr, uint32 leftLen, LPCOLESTR rightStr, uint32 rightLen, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
  789. WCHAR * AllocateStringOfLength(ULONG length);
  790. void FinishFncNode(ParseNodeFnc * pnodeFnc, bool fAllowIn = true);
  791. template<bool buildAST> bool ParseOptionalExpr(
  792. ParseNodePtr* pnode,
  793. bool fUnaryOrParen = false,
  794. int oplMin = koplNo,
  795. BOOL *pfCanAssign = NULL,
  796. BOOL fAllowIn = TRUE,
  797. BOOL fAllowEllipsis = FALSE,
  798. _Inout_opt_ IdentToken* pToken = NULL);
  799. template<bool buildAST> ParseNodePtr ParseExpr(
  800. int oplMin = koplNo,
  801. BOOL *pfCanAssign = NULL,
  802. BOOL fAllowIn = TRUE,
  803. BOOL fAllowEllipsis = FALSE,
  804. LPCOLESTR pHint = NULL,
  805. uint32 *pHintLength = nullptr,
  806. uint32 *pShortNameOffset = nullptr,
  807. _Inout_opt_ IdentToken* pToken = NULL,
  808. bool fUnaryOrParen = false,
  809. _Inout_opt_ bool* pfLikelyPattern = nullptr,
  810. _Inout_opt_ charcount_t *plastRParen = nullptr);
  811. template<bool buildAST> ParseNodePtr ParseTerm(
  812. BOOL fAllowCall = TRUE,
  813. LPCOLESTR pNameHint = nullptr,
  814. uint32 *pHintLength = nullptr,
  815. uint32 *pShortNameOffset = nullptr,
  816. _Inout_opt_ IdentToken* pToken = nullptr,
  817. bool fUnaryOrParen = false,
  818. BOOL fCanAssignToCall = TRUE,
  819. _Out_opt_ BOOL* pfCanAssign = nullptr,
  820. _Inout_opt_ BOOL* pfLikelyPattern = nullptr,
  821. _Out_opt_ bool* pfIsDotOrIndex = nullptr,
  822. _Inout_opt_ charcount_t *plastRParen = nullptr);
  823. template<bool buildAST> ParseNodePtr ParsePostfixOperators(
  824. ParseNodePtr pnode,
  825. BOOL fAllowCall,
  826. BOOL fInNew,
  827. BOOL isAsyncExpr,
  828. BOOL fCanAssignToCallResult,
  829. BOOL *pfCanAssign,
  830. _Inout_ IdentToken* pToken,
  831. _Out_opt_ bool* pfIsDotOrIndex = nullptr);
  832. void ThrowNewTargetSyntaxErrForGlobalScope();
  833. template<bool buildAST> IdentPtr ParseMetaProperty(
  834. tokens metaParentKeyword,
  835. charcount_t ichMin,
  836. _Out_opt_ BOOL* pfCanAssign = nullptr);
  837. bool IsImportOrExportStatementValidHere();
  838. bool IsTopLevelModuleFunc();
  839. template<bool buildAST> ParseNodePtr ParseImport();
  840. template<bool buildAST> void ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma = false);
  841. template<bool buildAST> ParseNodePtr ParseImportCall();
  842. template<bool buildAST> ParseNodePtr ParseExportDeclaration(bool *needTerminator = nullptr);
  843. template<bool buildAST> ParseNodePtr ParseDefaultExportClause();
  844. template<bool buildAST> void ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* importOrExportEntryList, bool isExportClause);
  845. template<bool buildAST> IdentPtr ParseImportOrExportFromClause(bool throwIfNotFound);
  846. BOOL NodeIsIdent(ParseNodePtr pnode, IdentPtr pid);
  847. BOOL NodeIsEvalName(ParseNodePtr pnode);
  848. BOOL NodeIsSuperName(ParseNodePtr pnode);
  849. BOOL IsJSONValid(ParseNodePtr pnodeExpr)
  850. {
  851. OpCode jnop = (knopNeg == pnodeExpr->nop) ? pnodeExpr->AsParseNodeUni()->pnode1->nop : pnodeExpr->nop;
  852. if (knopNeg == pnodeExpr->nop)
  853. {
  854. return (knopInt == jnop || knopFlt == jnop);
  855. }
  856. else
  857. {
  858. return (knopInt == jnop || knopFlt == jnop ||
  859. knopStr == jnop || knopNull == jnop ||
  860. knopTrue == jnop || knopFalse == jnop ||
  861. knopObject == jnop || knopArray == jnop);
  862. }
  863. }
  864. BOOL IsConstantInFunctionCall(ParseNodePtr pnode);
  865. BOOL IsConstantInArrayLiteral(ParseNodePtr pnode);
  866. ParseNodePtr ConvertMemberToMemberPattern(ParseNodePtr pnodeMember);
  867. ParseNodeUni * ConvertObjectToObjectPattern(ParseNodePtr pnodeMemberList);
  868. ParseNodePtr GetRightSideNodeFromPattern(ParseNodePtr pnode);
  869. ParseNodePtr ConvertArrayToArrayPattern(ParseNodePtr pnode);
  870. ParseNodePtr ConvertToPattern(ParseNodePtr pnode);
  871. void AppendToList(ParseNodePtr * node, ParseNodePtr nodeToAppend);
  872. bool IsES6DestructuringEnabled() const;
  873. bool IsPossiblePatternStart() const { return m_token.tk == tkLCurly || m_token.tk == tkLBrack; }
  874. bool IsPostFixOperators() const
  875. {
  876. return m_token.tk == tkLParen ||
  877. m_token.tk == tkLBrack ||
  878. m_token.tk == tkDot ||
  879. m_token.tk == tkStrTmplBasic ||
  880. m_token.tk == tkStrTmplBegin;
  881. }
  882. template<bool buildAST> ParseNodeStmt * ParseTryCatchFinally();
  883. template<bool buildAST> ParseNodeTry * ParseTry();
  884. template<bool buildAST> ParseNodeCatch * ParseCatch();
  885. template<bool buildAST> ParseNodeFinally * ParseFinally();
  886. template<bool buildAST> ParseNodeCase * ParseCase(ParseNodePtr *ppnodeBody);
  887. template<bool buildAST> ParseNodeRegExp * ParseRegExp();
  888. template <bool buildAST>
  889. ParseNodeUni * ParseDestructuredArrayLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  890. template <bool buildAST>
  891. ParseNodeUni * ParseDestructuredObjectLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  892. template <bool buildAST>
  893. ParseNodePtr ParseDestructuredLiteral(tokens declarationType,
  894. bool isDecl,
  895. bool topLevel = true,
  896. DestructuringInitializerContext initializerContext = DIC_None,
  897. bool allowIn = true,
  898. BOOL *forInOfOkay = nullptr,
  899. BOOL *nativeForOkay = nullptr);
  900. template <bool buildAST>
  901. ParseNodePtr ParseDestructuredVarDecl(tokens declarationType, bool isDecl, bool *hasSeenRest, bool topLevel = true, bool allowEmptyExpression = true, bool isObjectPattern = false);
  902. template <bool buildAST>
  903. ParseNodePtr ParseDestructuredInitializer(ParseNodeUni * lhsNode,
  904. bool isDecl,
  905. bool topLevel,
  906. DestructuringInitializerContext initializerContext,
  907. bool allowIn,
  908. BOOL *forInOfOkay,
  909. BOOL *nativeForOkay);
  910. template<bool CheckForNegativeInfinity> static bool IsNaNOrInfinityLiteral(LPCOLESTR str);
  911. void ParseDestructuredLiteralWithScopeSave(tokens declarationType,
  912. bool isDecl,
  913. bool topLevel,
  914. DestructuringInitializerContext initializerContext = DIC_None,
  915. bool allowIn = true);
  916. public:
  917. void ValidateSourceElementList();
  918. void ValidateFormals();
  919. bool IsStrictMode() const;
  920. BOOL ExpectingExternalSource();
  921. IdentPtr GetArgumentsPid() const { return wellKnownPropertyPids.arguments; }
  922. IdentPtr GetEvalPid() const { return wellKnownPropertyPids.eval; }
  923. IdentPtr GetTargetPid() const { return wellKnownPropertyPids.target; }
  924. IdentPtr GetMetaPid() const { return wellKnownPropertyPids.meta; }
  925. BackgroundParseItem *GetCurrBackgroundParseItem() const { return currBackgroundParseItem; }
  926. void SetCurrBackgroundParseItem(BackgroundParseItem *item) { currBackgroundParseItem = item; }
  927. private:
  928. void DeferOrEmitPotentialSpreadError(ParseNodePtr pnodeT);
  929. template<bool buildAST> void TrackAssignment(ParseNodePtr pnodeT, IdentToken* pToken);
  930. PidRefStack* PushPidRef(IdentPtr pid);
  931. PidRefStack* FindOrAddPidRef(IdentPtr pid, int blockId, Js::LocalFunctionId funcId);
  932. void RemovePrevPidRef(IdentPtr pid, PidRefStack *lastRef);
  933. void SetPidRefsInScopeDynamic(IdentPtr pid, int blockId);
  934. void RestoreScopeInfo(Js::ScopeInfo * scopeInfo);
  935. void FinishScopeInfo(Js::ScopeInfo * scopeInfo);
  936. bool LabelExists(IdentPtr pid, LabelId* pLabelIdList);
  937. LabelId* CreateLabelId(IdentPtr pid);
  938. void AddToNodeList(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  939. void AddToNodeListEscapedUse(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  940. void ChkCurTokNoScan(int tk, int wErr, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""))
  941. {
  942. if (m_token.tk != tk)
  943. {
  944. Error(wErr, stringOne, stringTwo);
  945. }
  946. }
  947. void ChkCurTok(int tk, int wErr)
  948. {
  949. if (m_token.tk != tk)
  950. {
  951. Error(wErr);
  952. }
  953. else
  954. {
  955. this->GetScanner()->Scan();
  956. }
  957. }
  958. void ChkNxtTok(int tk, int wErr)
  959. {
  960. this->GetScanner()->Scan();
  961. ChkCurTok(tk, wErr);
  962. }
  963. template <class Fn>
  964. void FinishFunctionsInScope(ParseNodePtr pnodeScopeList, Fn fn);
  965. void FinishDeferredFunction(ParseNodeBlock * pnodeScopeList);
  966. /***********************************************************************
  967. Misc
  968. ***********************************************************************/
  969. bool m_UsesArgumentsAtGlobal; // "arguments" used at global code.
  970. BOOL m_fUseStrictMode; // ES5 Use Strict mode. In AST mode this is a global flag; in NoAST mode it is pushed and popped.
  971. bool m_InAsmMode; // Currently parsing Asm.Js module
  972. bool m_deferAsmJs;
  973. BOOL m_fExpectExternalSource;
  974. BOOL m_deferringAST;
  975. BOOL m_stoppedDeferredParse;
  976. enum FncDeclFlag : ushort
  977. {
  978. fFncNoFlgs = 0,
  979. fFncDeclaration = 1 << 0,
  980. fFncNoArg = 1 << 1,
  981. fFncOneArg = 1 << 2, //Force exactly one argument.
  982. fFncNoName = 1 << 3,
  983. fFncLambda = 1 << 4,
  984. fFncMethod = 1 << 5,
  985. fFncClassMember = 1 << 6,
  986. fFncGenerator = 1 << 7,
  987. fFncAsync = 1 << 8,
  988. fFncModule = 1 << 9,
  989. fFncClassConstructor = 1 << 10,
  990. fFncBaseClassConstructor = 1 << 11,
  991. };
  992. //
  993. // If we need the scanner to force PID creation temporarily, use this auto object
  994. // to turn scanner deferred parsing off temporarily and restore at destructor.
  995. //
  996. class AutoTempForcePid
  997. {
  998. private:
  999. Scanner_t* m_scanner;
  1000. bool m_forcePid;
  1001. BYTE m_oldScannerDeferredParseFlags;
  1002. public:
  1003. AutoTempForcePid(Scanner_t* scanner, bool forcePid)
  1004. : m_scanner(scanner), m_forcePid(forcePid)
  1005. {
  1006. if (forcePid)
  1007. {
  1008. m_oldScannerDeferredParseFlags = scanner->SetDeferredParse(FALSE);
  1009. }
  1010. }
  1011. ~AutoTempForcePid()
  1012. {
  1013. if (m_forcePid)
  1014. {
  1015. m_scanner->SetDeferredParseFlags(m_oldScannerDeferredParseFlags);
  1016. }
  1017. }
  1018. };
  1019. class AutoMarkInParsingArgs
  1020. {
  1021. public:
  1022. AutoMarkInParsingArgs(Parser * parser)
  1023. : m_parser(parser)
  1024. {
  1025. m_prevState = m_parser->GetIsInParsingArgList();
  1026. m_prevDestructuringState = m_parser->GetHasDestructuringPattern();
  1027. m_parser->SetHasDestructuringPattern(false);
  1028. m_parser->SetIsInParsingArgList(true);
  1029. }
  1030. ~AutoMarkInParsingArgs()
  1031. {
  1032. m_parser->SetIsInParsingArgList(m_prevState);
  1033. if (!m_prevState)
  1034. {
  1035. m_parser->SetHasDestructuringPattern(false);
  1036. }
  1037. else
  1038. {
  1039. // Reset back to previous state only when the current call node does not have usage of destructuring expression.
  1040. if (!m_parser->GetHasDestructuringPattern())
  1041. {
  1042. m_parser->SetHasDestructuringPattern(m_prevDestructuringState);
  1043. }
  1044. }
  1045. }
  1046. private:
  1047. Parser *m_parser;
  1048. bool m_prevState;
  1049. bool m_prevDestructuringState;
  1050. };
  1051. public:
  1052. charcount_t GetSourceIchLim() { return m_sourceLim; }
  1053. static BOOL NodeEqualsName(ParseNodePtr pnode, LPCOLESTR sz, uint32 cch);
  1054. };