Parse.h 50 KB

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