Parse.h 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  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. koplLco, // ??
  23. koplBor, // |
  24. koplXor, // ^
  25. koplBan, // &
  26. koplEqu, // == !=
  27. koplCmp, // < <= > >=
  28. koplShf, // << >> >>>
  29. koplAdd, // + -
  30. koplMul, // * / %
  31. koplExpo, // **
  32. koplUni, // unary operators
  33. koplLim
  34. };
  35. enum ParseType
  36. {
  37. ParseType_Upfront,
  38. ParseType_Deferred
  39. };
  40. enum DestructuringInitializerContext
  41. {
  42. DIC_None,
  43. DIC_ShouldNotParseInitializer, // e.g. We don't want to parse the initializer even though we found assignment
  44. DIC_ForceErrorOnInitializer, // e.g. Catch param where we explicitly want to raise an error when the initializer found
  45. };
  46. enum ScopeType: int;
  47. enum SymbolType : byte;
  48. // Representation of a label used when no AST is being built.
  49. struct LabelId
  50. {
  51. IdentPtr pid;
  52. struct LabelId* next;
  53. };
  54. typedef ArenaAllocator ParseNodeAllocator;
  55. /***************************************************************************
  56. Parser object.
  57. ***************************************************************************/
  58. class CompileScriptException;
  59. class Parser;
  60. class SourceContextInfo;
  61. struct BlockIdsStack;
  62. class Span;
  63. class BackgroundParser;
  64. struct BackgroundParseItem;
  65. struct PnClass;
  66. class HashTbl;
  67. struct PidRefStack;
  68. struct DeferredFunctionStub;
  69. struct BlockInfoStack;
  70. struct StmtNest
  71. {
  72. union
  73. {
  74. struct
  75. {
  76. ParseNodeStmt * pnodeStmt; // This statement node.
  77. };
  78. struct
  79. {
  80. bool isDeferred : 1;
  81. OpCode op; // This statement operation.
  82. };
  83. };
  84. LabelId* pLabelId; // Labels for this statement.
  85. StmtNest *pstmtOuter; // Enclosing statement.
  86. inline OpCode GetNop() const
  87. {
  88. AnalysisAssert(isDeferred || pnodeStmt != nullptr);
  89. return isDeferred ? op : pnodeStmt->nop;
  90. }
  91. };
  92. struct ParseContext
  93. {
  94. LPCUTF8 pszSrc;
  95. size_t offset;
  96. size_t length;
  97. charcount_t characterOffset;
  98. int nextBlockId;
  99. ULONG grfscr;
  100. ULONG lineNumber;
  101. ParseNodeProg * pnodeProg;
  102. SourceContextInfo* sourceContextInfo;
  103. BlockInfoStack* currentBlockInfo;
  104. bool strictMode;
  105. bool isUtf8;
  106. };
  107. // DeferredFunctionStub is part of the parser state cache we serialize and restore in an
  108. // attempt to avoid doing another upfront parse of the same source.
  109. // Each deferred stub contains information needed to identify the function location in source,
  110. // flags for the function, the set of names captured by this function, and links to deferred
  111. // stubs for further nested functions.
  112. // These stubs are only created for defer-parsed functions and we create one stub for each
  113. // nested function. When we fully parse the defer-parsed function, we will use information
  114. // in these stubs to skip scanning the nested functions again.
  115. //
  116. // Example code:
  117. // let a, b;
  118. // function foo() {
  119. // function bar() {
  120. // return a;
  121. // }
  122. // function baz() {
  123. // return b;
  124. // }
  125. // }
  126. //
  127. // Deferred stubs for foo:
  128. // capturedNames: { a, b }
  129. // nestedCount: 2
  130. // deferredStubs :
  131. // [
  132. // // 0 = bar:
  133. // {
  134. // capturedNames: { a }
  135. // nestedCount: 0
  136. // deferredStubs : nullptr
  137. // ...
  138. // },
  139. // // 1 = baz:
  140. // {
  141. // capturedNames: { b }
  142. // nestedCount: 0
  143. // deferredStubs : nullptr
  144. // ...
  145. // }
  146. // ]
  147. // ...
  148. struct DeferredFunctionStub
  149. {
  150. Field(RestorePoint) restorePoint;
  151. Field(FncFlags) fncFlags;
  152. Field(uint) nestedCount;
  153. Field(charcount_t) ichMin;
  154. // Number of names captured by this function.
  155. // This is used as length for capturedNameSerializedIds but should
  156. // also be equal to the length of capturedNamePointers when
  157. // capturedNamePointers is not nullptr.
  158. Field(uint) capturedNameCount;
  159. // After the parser memory is cleaned-up, we no longer have access to
  160. // the IdentPtrs allocated from the Parser arena. We keep a list of
  161. // ids into the string table deserialized from the parser state cache.
  162. // This list is Recycler-allocated.
  163. Field(int *) capturedNameSerializedIds;
  164. // The set of names which are captured by this function.
  165. // A function captures a name when it references a name not defined within
  166. // the function.
  167. // A function also captures all names captured by nested functions.
  168. // The IdentPtrs in this set and the set itself are allocated from Parser
  169. // arena memory.
  170. Field(IdentPtrSet *) capturedNamePointers;
  171. // List of deferred stubs for further nested functions.
  172. // Length of this list is equal to nestedCount.
  173. Field(DeferredFunctionStub *) deferredStubs;
  174. Field(Js::ByteCodeCache *) byteCodeCache;
  175. };
  176. template <bool nullTerminated> class UTF8EncodingPolicyBase;
  177. typedef UTF8EncodingPolicyBase<false> NotNullTerminatedUTF8EncodingPolicy;
  178. template <typename T> class Scanner;
  179. namespace Js
  180. {
  181. class ParseableFunctionInfo;
  182. class FunctionBody;
  183. template <bool isGuestArena>
  184. class TempArenaAllocatorWrapper;
  185. };
  186. class Parser
  187. {
  188. typedef Scanner<NotNullTerminatedUTF8EncodingPolicy> Scanner_t;
  189. public:
  190. #if DEBUG
  191. Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false, size_t size = sizeof(Parser));
  192. #else
  193. Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false);
  194. #endif
  195. ~Parser(void);
  196. Js::ScriptContext* GetScriptContext() const { return m_scriptContext; }
  197. void ReleaseTemporaryGuestArena();
  198. bool IsCreatingStateCache();
  199. #if ENABLE_BACKGROUND_PARSING
  200. bool IsBackgroundParser() const { return m_isInBackground; }
  201. bool IsDoingFastScan() const { return m_doingFastScan; }
  202. #else
  203. bool IsBackgroundParser() const { return false; }
  204. bool IsDoingFastScan() const { return false; }
  205. #endif
  206. bool GetIsInParsingArgList() const { return m_isInParsingArgList; }
  207. void SetIsInParsingArgList(bool set) { m_isInParsingArgList = set; }
  208. bool GetHasDestructuringPattern() const { return m_hasDestructuringPattern; }
  209. void SetHasDestructuringPattern(bool set) { m_hasDestructuringPattern = set; }
  210. ParseNode* CopyPnode(ParseNode* pnode);
  211. ArenaAllocator *GetAllocator() { return &m_nodeAllocator;}
  212. size_t GetSourceLength() { return m_length; }
  213. size_t GetOriginalSourceLength() { return m_originalLength; }
  214. static ULONG GetDeferralThreshold(bool isProfileLoaded);
  215. BOOL WillDeferParse(Js::LocalFunctionId functionId);
  216. BOOL IsDeferredFnc();
  217. void ReduceDeferredScriptLength(size_t chars);
  218. static DeferredFunctionStub * BuildDeferredStubTree(ParseNodeFnc *pnodeFnc, Recycler *recycler);
  219. void RestorePidRefForSym(Symbol *sym);
  220. HRESULT ValidateSyntax(LPCUTF8 pszSrc, size_t encodedCharCount, bool isGenerator, bool isAsync, CompileScriptException *pse, void (Parser::*validateFunction)());
  221. // 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
  222. // 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.
  223. // This is important in Javascript because Javascript engines are required not to report invalid UTF-16 sequences and to consider
  224. // the UTF-16 characters pre-canonicalization. Converting this UTF-16 with invalid sequences to valid UTF-8 and back would cause
  225. // all invalid UTF-16 sequences to be replaced by one or more Unicode replacement characters (0xFFFD), losing the original
  226. // invalid sequences.
  227. HRESULT ParseCesu8Source(__out ParseNodeProg ** parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
  228. Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
  229. // Should be called when the source is UTF-8 and invalid UTF-8 sequences should be replaced with the unicode replacement character
  230. // (0xFFFD). Security concerns require externally produced UTF-8 only allow valid UTF-8 otherwise an attacker could use invalid
  231. // UTF-8 sequences to fool a filter and cause Javascript to be executed that might otherwise have been rejected.
  232. HRESULT ParseUtf8Source(__out ParseNodeProg ** parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
  233. Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
  234. // Used by deferred parsing to parse a deferred function.
  235. HRESULT ParseSourceWithOffset(__out ParseNodeProg ** parseTree, LPCUTF8 pSrc, size_t offset, size_t cbLength, charcount_t cchOffset,
  236. bool isCesu8, ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber,
  237. SourceContextInfo * sourceContextInfo, Js::ParseableFunctionInfo* functionInfo);
  238. protected:
  239. static uint BuildDeferredStubTreeHelper(ParseNodeBlock* pnodeBlock, DeferredFunctionStub* deferredStubs, uint currentStubIndex, uint deferredStubCount, Recycler *recycler);
  240. void ShiftCurrDeferredStubToChildFunction(ParseNodeFnc* pnodeFnc, ParseNodeFnc* pnodeFncParent);
  241. HRESULT ParseSourceInternal(
  242. __out ParseNodeProg ** parseTree, LPCUTF8 pszSrc, size_t offsetInBytes,
  243. size_t lengthInCodePoints, charcount_t offsetInChars, bool isUtf8,
  244. ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber, SourceContextInfo * sourceContextInfo);
  245. ParseNodeProg * Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcount_t charOffset, bool isUtf8, ULONG grfscr, ULONG lineNumber,
  246. Js::LocalFunctionId * nextFunctionId, CompileScriptException *pse);
  247. private:
  248. /***********************************************************************
  249. Core members.
  250. ***********************************************************************/
  251. ParseNodeAllocator m_nodeAllocator;
  252. int32 m_cactIdentToNodeLookup;
  253. uint32 m_grfscr;
  254. size_t m_length; // source length in characters excluding comments and literals
  255. size_t m_originalLength; // source length in characters excluding comments and literals
  256. Js::LocalFunctionId * m_nextFunctionId;
  257. SourceContextInfo* m_sourceContextInfo;
  258. #if ENABLE_BACKGROUND_PARSING
  259. bool m_hasParallelJob;
  260. bool m_isInBackground;
  261. bool m_doingFastScan;
  262. #endif
  263. bool m_tempGuestArenaReleased;
  264. int m_nextBlockId;
  265. AutoRecyclerRootPtr<Js::TempArenaAllocatorWrapper<true>> m_tempGuestArena;
  266. // RegexPattern objects created for literal regexes are recycler-allocated and need to be kept alive until the function body
  267. // is created during byte code generation. The RegexPattern pointer is stored in a temporary guest
  268. // arena for that purpose. This list is then unregistered from the guest arena at the end of parsing/scanning.
  269. SList<UnifiedRegex::RegexPattern *, ArenaAllocator> m_registeredRegexPatterns;
  270. protected:
  271. Js::ScriptContext* m_scriptContext;
  272. HashTbl * GetHashTbl() { return this->GetScanner()->GetHashTbl(); }
  273. LPCWSTR GetTokenString(tokens token);
  274. __declspec(noreturn) void Error(HRESULT hr, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""));
  275. private:
  276. __declspec(noreturn) void Error(HRESULT hr, ParseNodePtr pnode);
  277. __declspec(noreturn) void Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""));
  278. __declspec(noreturn) static void OutOfMemory();
  279. void EnsureStackAvailable();
  280. void IdentifierExpectedError(const Token& token);
  281. bool CheckForDirective(bool* pIsUseStrict, bool* pIsUseAsm, bool* pIsOctalInString);
  282. bool CheckStrictModeStrPid(IdentPtr pid);
  283. bool CheckAsmjsModeStrPid(IdentPtr pid);
  284. bool CheckContextualKeyword(IdentPtr keywordPid)
  285. {
  286. if (m_token.tk == tkID && !GetScanner()->LastIdentifierHasEscape())
  287. {
  288. IdentPtr pid = m_token.GetIdentifier(GetHashTbl());
  289. return pid == keywordPid;
  290. }
  291. return false;
  292. }
  293. bool IsCurBlockInLoop() const;
  294. void InitPids();
  295. /***********************************************************************
  296. Members needed just for parsing.
  297. ***********************************************************************/
  298. protected:
  299. Token m_token;
  300. Scanner_t m_scan;
  301. Scanner_t const * GetScanner() const { return &m_scan; }
  302. Scanner_t * GetScanner() { return &m_scan; }
  303. void AddAstSize(int size);
  304. void AddAstSizeAllowDefer(int size);
  305. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT() { return CreateNodeForOpT<nop>(this->GetScanner()->IchMinTok()); }
  306. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT(charcount_t ichMin) { return CreateNodeForOpT<nop>(ichMin, this->GetScanner()->IchLimTok()); }
  307. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateNodeForOpT(charcount_t ichMin, charcount_t ichLim);
  308. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT() { return CreateAllowDeferNodeForOpT<nop>(this->GetScanner()->IchMinTok()); }
  309. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT(charcount_t ichMin) { return CreateAllowDeferNodeForOpT<nop>(ichMin, this->GetScanner()->IchLimTok()); }
  310. template <OpCode nop> typename OpCodeTrait<nop>::ParseNodeType * CreateAllowDeferNodeForOpT(charcount_t ichMin, charcount_t ichLim);
  311. public:
  312. // create nodes using arena allocator; used by AST transformation
  313. template <OpCode nop>
  314. static typename OpCodeTrait<nop>::ParseNodeType * StaticCreateNodeT(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0)
  315. {
  316. return Anew(alloc, typename OpCodeTrait<nop>::ParseNodeType, nop, ichMin, ichLim);
  317. }
  318. static ParseNodeBin * StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0);
  319. static ParseNodeBlock * StaticCreateBlockNode(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, int blockId = -1, PnodeBlockType blockType = PnodeBlockType::Regular);
  320. static ParseNodeVar * StaticCreateTempNode(ParseNode* initExpr, ArenaAllocator* alloc);
  321. static ParseNodeUni * StaticCreateTempRef(ParseNode* tempNode, ArenaAllocator* alloc);
  322. private:
  323. ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnodeOp);
  324. ParseNodeUni * CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_t ichMin, charcount_t ichLim);
  325. ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  326. ParseNodeBin * CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim);
  327. ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3);
  328. ParseNodeTri * CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3, charcount_t ichMin, charcount_t ichLim);
  329. ParseNodeBlock * CreateBlockNode(PnodeBlockType blockType = PnodeBlockType::Regular);
  330. ParseNodeBlock * CreateBlockNode(charcount_t ichMin, charcount_t ichLim, PnodeBlockType blockType = PnodeBlockType::Regular);
  331. ParseNodeVar * CreateDeclNode(OpCode nop, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl = true);
  332. ParseNodeInt * CreateIntNode(int32 lw);
  333. ParseNodeStr * CreateStrNode(IdentPtr pid);
  334. ParseNodeBigInt * CreateBigIntNode(IdentPtr pid);
  335. ParseNodeName * CreateNameNode(IdentPtr pid);
  336. ParseNodeName * CreateNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);
  337. ParseNodeSpecialName * CreateSpecialNameNode(IdentPtr pid, PidRefStack * ref, charcount_t ichMin, charcount_t ichLim);
  338. ParseNodeSuperReference * CreateSuperReferenceNode(OpCode nop, ParseNodeSpecialName * pnode1, ParseNodePtr pnode2);
  339. ParseNodeProg * CreateProgNode(bool isModuleSource, ULONG lineNumber);
  340. ParseNodeCall * CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
  341. ParseNodeCall * CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, charcount_t ichMin, charcount_t ichLim);
  342. ParseNodeSuperCall * CreateSuperCallNode(ParseNodeSpecialName * pnode1, ParseNodePtr pnode2);
  343. ParseNodeFnc * CreateDummyFuncNode(bool fDeclaration);
  344. ParseNodeParamPattern * CreateParamPatternNode(ParseNodePtr pnode1);
  345. ParseNodeParamPattern * CreateDummyParamPatternNode(charcount_t ichMin);
  346. ParseNodeObjLit * CreateObjectPatternNode(ParseNodePtr pnodeMemberList, charcount_t ichMin, charcount_t ichLim, bool convertToPattern=false);
  347. Symbol* AddDeclForPid(ParseNodeVar * pnode, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl);
  348. void CheckRedeclarationErrorForBlockId(IdentPtr pid, int blockId);
  349. public:
  350. #if ENABLE_BACKGROUND_PARSING
  351. void PrepareForBackgroundParse();
  352. void AddFastScannedRegExpNode(ParseNodePtr const pnode);
  353. void AddBackgroundRegExpNode(ParseNodePtr const pnode);
  354. void AddBackgroundParseItem(BackgroundParseItem *const item);
  355. void FinishBackgroundRegExpNodes();
  356. void FinishBackgroundPidRefs(BackgroundParseItem *const item, bool isOtherParser);
  357. void WaitForBackgroundJobs(BackgroundParser *bgp, CompileScriptException *pse);
  358. HRESULT ParseFunctionInBackground(ParseNodeFnc * pnodeFnc, ParseContext *parseContext, bool topLevelDeferred, CompileScriptException *pse);
  359. #endif
  360. void CheckPidIsValid(IdentPtr pid, bool autoArgumentsObject = false);
  361. void AddVarDeclToBlock(ParseNodeVar *pnode);
  362. // Add a var declaration. Only use while parsing. Assumes m_ppnodeVar is pointing to the right place already
  363. ParseNodeVar * CreateVarDeclNode(IdentPtr pid, SymbolType symbolType, bool autoArgumentsObject = false, ParseNodePtr pnodeFnc = NULL, bool checkReDecl = true);
  364. // Add a var declaration, during parse tree rewriting. Will setup m_ppnodeVar for the given pnodeFnc
  365. ParseNodeVar * AddVarDeclNode(IdentPtr pid, ParseNodeFnc * pnodeFnc);
  366. // Add a 'const' or 'let' declaration.
  367. ParseNodeVar * CreateBlockScopedDeclNode(IdentPtr pid, OpCode nodeType);
  368. void RegisterRegexPattern(UnifiedRegex::RegexPattern *const regexPattern);
  369. #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
  370. LPCWSTR GetParseType() const
  371. {
  372. switch(m_parseType)
  373. {
  374. case ParseType_Upfront:
  375. return _u("Upfront");
  376. case ParseType_Deferred:
  377. return _u("Deferred");
  378. }
  379. Assert(false);
  380. return NULL;
  381. }
  382. #endif
  383. void CaptureContext(ParseContext *parseContext) const;
  384. void RestoreContext(ParseContext *const parseContext);
  385. int GetLastBlockId() const { Assert(m_nextBlockId > 0); return m_nextBlockId - 1; }
  386. private:
  387. ParseNodeFnc * m_currentNodeNonLambdaFunc; // current function or NULL
  388. ParseNodeFnc * m_currentNodeNonLambdaDeferredFunc; // current function or NULL
  389. ParseNodeFnc * m_currentNodeFunc; // current function or NULL
  390. ParseNodeFnc * m_currentNodeDeferredFunc; // current function or NULL
  391. ParseNodeProg * m_currentNodeProg; // current program
  392. DeferredFunctionStub *m_currDeferredStub;
  393. uint m_currDeferredStubCount;
  394. int32 * m_pCurrentAstSize;
  395. ParseNodePtr * m_ppnodeScope; // function list tail
  396. ParseNodePtr * m_ppnodeExprScope; // function expression list tail
  397. ParseNodePtr * m_ppnodeVar; // variable list tail
  398. bool m_inDeferredNestedFunc; // true if parsing a function in deferred mode, nested within the current node
  399. bool m_reparsingLambdaParams;
  400. bool m_disallowImportExportStmt;
  401. bool m_isInParsingArgList;
  402. bool m_hasDestructuringPattern;
  403. // This bool is used for deferring the shorthand initializer error ( {x = 1}) - as it is allowed in the destructuring grammar.
  404. bool m_hasDeferredShorthandInitError;
  405. bool m_deferEllipsisError;
  406. bool m_deferCommaError;
  407. uint * m_pnestedCount; // count of functions nested at one level below the current node
  408. struct WellKnownPropertyPids
  409. {
  410. IdentPtr arguments;
  411. IdentPtr async;
  412. IdentPtr eval;
  413. IdentPtr set;
  414. IdentPtr get;
  415. IdentPtr let;
  416. IdentPtr await;
  417. IdentPtr constructor;
  418. IdentPtr prototype;
  419. IdentPtr __proto__;
  420. IdentPtr of;
  421. IdentPtr target;
  422. IdentPtr from;
  423. IdentPtr as;
  424. IdentPtr meta;
  425. IdentPtr _default;
  426. IdentPtr _star; // Special '*' identifier for modules
  427. IdentPtr _this; // Special 'this' identifier
  428. IdentPtr _newTarget; // Special new.target identifier
  429. IdentPtr _super; // Special super identifier
  430. IdentPtr _superConstructor; // Special super constructor identifier
  431. IdentPtr _importMeta; // Special import.meta identifier
  432. };
  433. WellKnownPropertyPids wellKnownPropertyPids;
  434. charcount_t m_sourceLim; // The actual number of characters parsed.
  435. Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
  436. ParseType m_parseType;
  437. uint m_arrayDepth;
  438. uint m_funcInArrayDepth; // Count func depth within array literal
  439. charcount_t m_funcInArray;
  440. uint m_scopeCountNoAst;
  441. // Used for issuing spread and rest errors when there is ambiguity with lambda parameter lists and parenthesized expressions
  442. uint m_funcParenExprDepth;
  443. RestorePoint m_deferEllipsisErrorLoc;
  444. RestorePoint m_deferCommaErrorLoc;
  445. 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
  446. StmtNest *m_pstmtCur; // current statement or NULL
  447. BlockInfoStack *m_currentBlockInfo;
  448. Scope *m_currentScope;
  449. BackgroundParseItem *currBackgroundParseItem;
  450. BackgroundParseItem *backgroundParseItems;
  451. typedef DList<ParseNodePtr, ArenaAllocator> NodeDList;
  452. NodeDList* fastScannedRegExpNodes;
  453. BlockIdsStack *m_currentDynamicBlock;
  454. int GetCurrentDynamicBlockId() const;
  455. void AppendFunctionToScopeList(bool fDeclaration, ParseNodeFnc * pnodeFnc);
  456. // block scoped content helpers
  457. void SetCurrentStatement(StmtNest *stmt);
  458. ParseNodeBlock* GetCurrentBlock();
  459. ParseNodeBlock* GetFunctionBlock();
  460. BlockInfoStack* GetCurrentBlockInfo();
  461. BlockInfoStack* GetCurrentFunctionBlockInfo();
  462. ParseNodeFnc *GetCurrentFunctionNode();
  463. ParseNodeFnc *GetCurrentNonLambdaFunctionNode();
  464. bool NextTokenConfirmsLetDecl() const { return m_token.tk == tkID || m_token.tk == tkLBrack || m_token.tk == tkLCurly || m_token.IsReservedWord(); }
  465. 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(); }
  466. template<bool buildAST>
  467. void PushStmt(StmtNest *pStmt, ParseNodeStmt * pnode, OpCode op, LabelId* pLabelIdList)
  468. {
  469. if (buildAST)
  470. {
  471. pnode->grfnop = 0;
  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. _Out_opt_ bool* looseCoalesce = nullptr);
  812. template<bool buildAST> ParseNodePtr ParseTerm(
  813. BOOL fAllowCall = TRUE,
  814. LPCOLESTR pNameHint = nullptr,
  815. uint32 *pHintLength = nullptr,
  816. uint32 *pShortNameOffset = nullptr,
  817. _Inout_opt_ IdentToken* pToken = nullptr,
  818. bool fUnaryOrParen = false,
  819. BOOL fCanAssignToCall = TRUE,
  820. _Out_opt_ BOOL* pfCanAssign = nullptr,
  821. _Inout_opt_ BOOL* pfLikelyPattern = nullptr,
  822. _Out_opt_ bool* pfIsDotOrIndex = nullptr,
  823. _Inout_opt_ charcount_t *plastRParen = nullptr,
  824. _Out_opt_ bool* looseCoalesce = nullptr);
  825. template<bool buildAST> ParseNodePtr ParsePostfixOperators(
  826. ParseNodePtr pnode,
  827. BOOL fAllowCall,
  828. BOOL fInNew,
  829. BOOL isAsyncExpr,
  830. BOOL fCanAssignToCallResult,
  831. BOOL *pfCanAssign,
  832. _Inout_ IdentToken* pToken,
  833. _Out_opt_ bool* pfIsDotOrIndex = nullptr);
  834. void ThrowNewTargetSyntaxErrForGlobalScope();
  835. template<bool buildAST> IdentPtr ParseMetaProperty(
  836. tokens metaParentKeyword,
  837. charcount_t ichMin,
  838. _Out_opt_ BOOL* pfCanAssign = nullptr);
  839. void CheckIfImportOrExportStatementValidHere();
  840. bool IsTopLevelModuleFunc();
  841. void MakeModuleAsync();
  842. template<bool buildAST> ParseNodePtr ParseImport();
  843. template<bool buildAST> void ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma = false);
  844. template<bool buildAST> ParseNodePtr ParseImportCall();
  845. template<bool buildAST> ParseNodePtr ParseExportDeclaration(bool *needTerminator = nullptr);
  846. template<bool buildAST> ParseNodePtr ParseDefaultExportClause();
  847. template<bool buildAST> void ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* importOrExportEntryList, bool isExportClause);
  848. template<bool buildAST> IdentPtr ParseImportOrExportFromClause(bool throwIfNotFound);
  849. BOOL NodeIsIdent(ParseNodePtr pnode, IdentPtr pid);
  850. BOOL NodeIsEvalName(ParseNodePtr pnode);
  851. BOOL NodeIsSuperName(ParseNodePtr pnode);
  852. BOOL IsJSONValid(ParseNodePtr pnodeExpr)
  853. {
  854. OpCode jnop = (knopNeg == pnodeExpr->nop) ? pnodeExpr->AsParseNodeUni()->pnode1->nop : pnodeExpr->nop;
  855. if (knopNeg == pnodeExpr->nop)
  856. {
  857. return (knopInt == jnop || knopFlt == jnop);
  858. }
  859. else
  860. {
  861. return (knopInt == jnop || knopFlt == jnop ||
  862. knopStr == jnop || knopNull == jnop ||
  863. knopTrue == jnop || knopFalse == jnop ||
  864. knopObject == jnop || knopArray == jnop);
  865. }
  866. }
  867. BOOL IsConstantInFunctionCall(ParseNodePtr pnode);
  868. BOOL IsConstantInArrayLiteral(ParseNodePtr pnode);
  869. ParseNodePtr ConvertMemberToMemberPattern(ParseNodePtr pnodeMember);
  870. ParseNodeUni * ConvertObjectToObjectPattern(ParseNodePtr pnodeMemberList);
  871. ParseNodePtr GetRightSideNodeFromPattern(ParseNodePtr pnode);
  872. ParseNodePtr ConvertArrayToArrayPattern(ParseNodePtr pnode);
  873. ParseNodePtr ConvertToPattern(ParseNodePtr pnode);
  874. void AppendToList(ParseNodePtr * node, ParseNodePtr nodeToAppend);
  875. bool IsPossiblePatternStart() const { return m_token.tk == tkLCurly || m_token.tk == tkLBrack; }
  876. bool IsPostFixOperators() const
  877. {
  878. return m_token.tk == tkLParen ||
  879. m_token.tk == tkLBrack ||
  880. m_token.tk == tkDot ||
  881. m_token.tk == tkStrTmplBasic ||
  882. m_token.tk == tkStrTmplBegin;
  883. }
  884. template<bool buildAST> ParseNodeStmt * ParseTryCatchFinally();
  885. template<bool buildAST> ParseNodeTry * ParseTry();
  886. template<bool buildAST> ParseNodeCatch * ParseCatch();
  887. template<bool buildAST> ParseNodeFinally * ParseFinally();
  888. template<bool buildAST> ParseNodeCase * ParseCase(ParseNodePtr *ppnodeBody);
  889. template<bool buildAST> ParseNodeRegExp * ParseRegExp();
  890. template <bool buildAST>
  891. ParseNodeUni * ParseDestructuredArrayLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  892. template <bool buildAST>
  893. ParseNodeUni * ParseDestructuredObjectLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
  894. template <bool buildAST>
  895. ParseNodePtr ParseDestructuredLiteral(tokens declarationType,
  896. bool isDecl,
  897. bool topLevel = true,
  898. DestructuringInitializerContext initializerContext = DIC_None,
  899. bool allowIn = true,
  900. BOOL *forInOfOkay = nullptr,
  901. BOOL *nativeForOkay = nullptr);
  902. template <bool buildAST>
  903. ParseNodePtr ParseDestructuredVarDecl(tokens declarationType, bool isDecl, bool *hasSeenRest, bool topLevel = true, bool allowEmptyExpression = true, bool isObjectPattern = false);
  904. template <bool buildAST>
  905. ParseNodePtr ParseDestructuredInitializer(ParseNodeUni * lhsNode,
  906. bool isDecl,
  907. bool topLevel,
  908. DestructuringInitializerContext initializerContext,
  909. bool allowIn,
  910. BOOL *forInOfOkay,
  911. BOOL *nativeForOkay);
  912. template<bool CheckForNegativeInfinity> static bool IsNaNOrInfinityLiteral(LPCOLESTR str);
  913. void ParseDestructuredLiteralWithScopeSave(tokens declarationType,
  914. bool isDecl,
  915. bool topLevel,
  916. DestructuringInitializerContext initializerContext = DIC_None,
  917. bool allowIn = true);
  918. public:
  919. void ValidateSourceElementList();
  920. void ValidateFormals();
  921. bool IsStrictMode() const;
  922. BOOL ExpectingExternalSource();
  923. IdentPtr GetArgumentsPid() const { return wellKnownPropertyPids.arguments; }
  924. IdentPtr GetEvalPid() const { return wellKnownPropertyPids.eval; }
  925. IdentPtr GetTargetPid() const { return wellKnownPropertyPids.target; }
  926. IdentPtr GetMetaPid() const { return wellKnownPropertyPids.meta; }
  927. BackgroundParseItem *GetCurrBackgroundParseItem() const { return currBackgroundParseItem; }
  928. void SetCurrBackgroundParseItem(BackgroundParseItem *item) { currBackgroundParseItem = item; }
  929. private:
  930. void DeferOrEmitPotentialSpreadError(ParseNodePtr pnodeT);
  931. template<bool buildAST> void TrackAssignment(ParseNodePtr pnodeT, IdentToken* pToken);
  932. PidRefStack* PushPidRef(IdentPtr pid);
  933. PidRefStack* FindOrAddPidRef(IdentPtr pid, int blockId, Js::LocalFunctionId funcId);
  934. void RemovePrevPidRef(IdentPtr pid, PidRefStack *lastRef);
  935. void SetPidRefsInScopeDynamic(IdentPtr pid, int blockId);
  936. void RestoreScopeInfo(Js::ScopeInfo * scopeInfo);
  937. void FinishScopeInfo(Js::ScopeInfo * scopeInfo);
  938. bool LabelExists(IdentPtr pid, LabelId* pLabelIdList);
  939. LabelId* CreateLabelId(IdentPtr pid);
  940. void AddToNodeList(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  941. void AddToNodeListEscapedUse(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
  942. void ChkCurTokNoScan(int tk, int wErr, LPCWSTR stringOne = _u(""), LPCWSTR stringTwo = _u(""))
  943. {
  944. if (m_token.tk != tk)
  945. {
  946. Error(wErr, stringOne, stringTwo);
  947. }
  948. }
  949. void ChkCurTok(int tk, int wErr)
  950. {
  951. if (m_token.tk != tk)
  952. {
  953. Error(wErr);
  954. }
  955. else
  956. {
  957. this->GetScanner()->Scan();
  958. }
  959. }
  960. void ChkNxtTok(int tk, int wErr)
  961. {
  962. this->GetScanner()->Scan();
  963. ChkCurTok(tk, wErr);
  964. }
  965. template <class Fn>
  966. void FinishFunctionsInScope(ParseNodePtr pnodeScopeList, Fn fn);
  967. void FinishDeferredFunction(ParseNodeBlock * pnodeScopeList);
  968. /***********************************************************************
  969. Misc
  970. ***********************************************************************/
  971. bool m_UsesArgumentsAtGlobal; // "arguments" used at global code.
  972. BOOL m_fUseStrictMode; // ES5 Use Strict mode. In AST mode this is a global flag; in NoAST mode it is pushed and popped.
  973. bool m_InAsmMode; // Currently parsing Asm.Js module
  974. bool m_deferAsmJs;
  975. BOOL m_fExpectExternalSource;
  976. BOOL m_deferringAST;
  977. BOOL m_stoppedDeferredParse;
  978. enum FncDeclFlag : ushort
  979. {
  980. fFncNoFlgs = 0,
  981. fFncDeclaration = 1 << 0,
  982. fFncNoArg = 1 << 1,
  983. fFncOneArg = 1 << 2, //Force exactly one argument.
  984. fFncNoName = 1 << 3,
  985. fFncLambda = 1 << 4,
  986. fFncMethod = 1 << 5,
  987. fFncClassMember = 1 << 6,
  988. fFncGenerator = 1 << 7,
  989. fFncAsync = 1 << 8,
  990. fFncModule = 1 << 9,
  991. fFncClassConstructor = 1 << 10,
  992. fFncBaseClassConstructor = 1 << 11,
  993. };
  994. //
  995. // If we need the scanner to force PID creation temporarily, use this auto object
  996. // to turn scanner deferred parsing off temporarily and restore at destructor.
  997. //
  998. class AutoTempForcePid
  999. {
  1000. private:
  1001. Scanner_t* m_scanner;
  1002. bool m_forcePid;
  1003. BYTE m_oldScannerDeferredParseFlags;
  1004. public:
  1005. AutoTempForcePid(Scanner_t* scanner, bool forcePid)
  1006. : m_scanner(scanner), m_forcePid(forcePid)
  1007. {
  1008. if (forcePid)
  1009. {
  1010. m_oldScannerDeferredParseFlags = scanner->SetDeferredParse(FALSE);
  1011. }
  1012. }
  1013. ~AutoTempForcePid()
  1014. {
  1015. if (m_forcePid)
  1016. {
  1017. m_scanner->SetDeferredParseFlags(m_oldScannerDeferredParseFlags);
  1018. }
  1019. }
  1020. };
  1021. class AutoMarkInParsingArgs
  1022. {
  1023. public:
  1024. AutoMarkInParsingArgs(Parser * parser)
  1025. : m_parser(parser)
  1026. {
  1027. m_prevState = m_parser->GetIsInParsingArgList();
  1028. m_prevDestructuringState = m_parser->GetHasDestructuringPattern();
  1029. m_parser->SetHasDestructuringPattern(false);
  1030. m_parser->SetIsInParsingArgList(true);
  1031. }
  1032. ~AutoMarkInParsingArgs()
  1033. {
  1034. m_parser->SetIsInParsingArgList(m_prevState);
  1035. if (!m_prevState)
  1036. {
  1037. m_parser->SetHasDestructuringPattern(false);
  1038. }
  1039. else
  1040. {
  1041. // Reset back to previous state only when the current call node does not have usage of destructuring expression.
  1042. if (!m_parser->GetHasDestructuringPattern())
  1043. {
  1044. m_parser->SetHasDestructuringPattern(m_prevDestructuringState);
  1045. }
  1046. }
  1047. }
  1048. private:
  1049. Parser *m_parser;
  1050. bool m_prevState;
  1051. bool m_prevDestructuringState;
  1052. };
  1053. public:
  1054. charcount_t GetSourceIchLim() { return m_sourceLim; }
  1055. static BOOL NodeEqualsName(ParseNodePtr pnode, LPCOLESTR sz, uint32 cch);
  1056. };