Parse.h 51 KB

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