| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- #include "ParseFlags.h"
- namespace Js
- {
- class ScopeInfo;
- };
- // Operator precedence levels
- enum
- {
- koplNo, // not an operator
- koplCma, // ,
- koplSpr, // ...
- koplAsg, // = += etc
- koplQue, // ?:
- koplLor, // ||
- koplLan, // &&
- koplBor, // |
- koplXor, // ^
- koplBan, // &
- koplEqu, // == !=
- koplCmp, // < <= > >=
- koplShf, // << >> >>>
- koplAdd, // + -
- koplMul, // * / %
- koplExpo, // **
- koplUni, // unary operators
- koplLim
- };
- enum ParseType
- {
- ParseType_Upfront,
- ParseType_Deferred
- };
- enum DestructuringInitializerContext
- {
- DIC_None,
- DIC_ShouldNotParseInitializer, // e.g. We don't want to parse the initializer even though we found assignment
- DIC_ForceErrorOnInitializer, // e.g. Catch param where we explicitly want to raise an error when the initializer found
- };
- enum ScopeType: int;
- enum SymbolType : byte;
- // Representation of a label used when no AST is being built.
- struct LabelId
- {
- IdentPtr pid;
- struct LabelId* next;
- };
- typedef ArenaAllocator ParseNodeAllocator;
- /***************************************************************************
- Parser object.
- ***************************************************************************/
- class CompileScriptException;
- class Parser;
- class SourceContextInfo;
- struct BlockIdsStack;
- class Span;
- class BackgroundParser;
- struct BackgroundParseItem;
- struct PnClass;
- class HashTbl;
- typedef void (*ParseErrorCallback)(void *data, charcount_t position, charcount_t length, HRESULT hr);
- struct PidRefStack;
- struct DeferredFunctionStub;
- DeferredFunctionStub * BuildDeferredStubTree(ParseNode *pnodeFnc, Recycler *recycler);
- struct StmtNest;
- struct BlockInfoStack;
- struct ParseContext
- {
- LPCUTF8 pszSrc;
- size_t offset;
- size_t length;
- charcount_t characterOffset;
- int nextBlockId;
- ULONG grfscr;
- ULONG lineNumber;
- ParseNodePtr pnodeProg;
- SourceContextInfo* sourceContextInfo;
- BlockInfoStack* currentBlockInfo;
- bool strictMode;
- bool fromExternal;
- };
- template <bool nullTerminated> class UTF8EncodingPolicyBase;
- typedef UTF8EncodingPolicyBase<false> NotNullTerminatedUTF8EncodingPolicy;
- template <typename T> class Scanner;
- namespace Js
- {
- class ParseableFunctionInfo;
- class FunctionBody;
- };
- class Parser
- {
- typedef Scanner<NotNullTerminatedUTF8EncodingPolicy> Scanner_t;
- private:
- template <OpCode nop> static int GetNodeSize();
- template <OpCode nop> static ParseNodePtr StaticAllocNode(ArenaAllocator * alloc)
- {
- ParseNodePtr pnode = (ParseNodePtr)alloc->Alloc(GetNodeSize<nop>());
- Assert(pnode != nullptr);
- return pnode;
- }
- public:
- #if DEBUG
- Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false, size_t size = sizeof(Parser));
- #else
- Parser(Js::ScriptContext* scriptContext, BOOL strictMode = FALSE, PageAllocator *alloc = nullptr, bool isBackground = false);
- #endif
- ~Parser(void);
- Js::ScriptContext* GetScriptContext() const { return m_scriptContext; }
- void ClearScriptContext() { m_scriptContext = nullptr; }
- bool IsBackgroundParser() const { return m_isInBackground; }
- bool IsDoingFastScan() const { return m_doingFastScan; }
- static IdentPtr PidFromNode(ParseNodePtr pnode);
- ParseNode* CopyPnode(ParseNode* pnode);
- ArenaAllocator *GetAllocator() { return &m_nodeAllocator;}
- size_t GetSourceLength() { return m_length; }
- size_t GetOriginalSourceLength() { return m_originalLength; }
- static ULONG GetDeferralThreshold(bool isProfileLoaded);
- BOOL DeferredParse(Js::LocalFunctionId functionId);
- BOOL IsDeferredFnc();
- void ReduceDeferredScriptLength(size_t chars);
- void RestorePidRefForSym(Symbol *sym);
- HRESULT ValidateSyntax(LPCUTF8 pszSrc, size_t encodedCharCount, bool isGenerator, bool isAsync, CompileScriptException *pse, void (Parser::*validateFunction)());
- // 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
- // 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.
- // This is important in Javascript because Javascript engines are required not to report invalid UTF-16 sequences and to consider
- // the UTF-16 characters pre-canonicalization. Converting this UTF-16 with invalid sequences to valid UTF-8 and back would cause
- // all invalid UTF-16 sequences to be replaced by one or more Unicode replacement characters (0xFFFD), losing the original
- // invalid sequences.
- HRESULT ParseCesu8Source(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
- Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
- // Should be called when the source is UTF-8 and invalid UTF-8 sequences should be replaced with the unicode replacement character
- // (0xFFFD). Security concerns require externally produced UTF-8 only allow valid UTF-8 otherwise an attacker could use invalid
- // UTF-8 sequences to fool a filter and cause Javascript to be executed that might otherwise have been rejected.
- HRESULT ParseUtf8Source(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t length, ULONG grfsrc, CompileScriptException *pse,
- Js::LocalFunctionId * nextFunctionId, SourceContextInfo * sourceContextInfo);
- // Used by deferred parsing to parse a deferred function.
- HRESULT ParseSourceWithOffset(__out ParseNodePtr* parseTree, LPCUTF8 pSrc, size_t offset, size_t cbLength, charcount_t cchOffset,
- bool isCesu8, ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber,
- SourceContextInfo * sourceContextInfo, Js::ParseableFunctionInfo* functionInfo);
- protected:
- HRESULT ParseSourceInternal(
- __out ParseNodePtr* parseTree, LPCUTF8 pszSrc, size_t offsetInBytes,
- size_t lengthInCodePoints, charcount_t offsetInChars, bool fromExternal,
- ULONG grfscr, CompileScriptException *pse, Js::LocalFunctionId * nextFunctionId, ULONG lineNumber, SourceContextInfo * sourceContextInfo);
- ParseNodePtr Parse(LPCUTF8 pszSrc, size_t offset, size_t length, charcount_t charOffset, ULONG grfscr, ULONG lineNumber,
- Js::LocalFunctionId * nextFunctionId, CompileScriptException *pse);
- private:
- /***********************************************************************
- Core members.
- ***********************************************************************/
- ParseNodeAllocator m_nodeAllocator;
- int32 m_cactIdentToNodeLookup;
- uint32 m_grfscr;
- size_t m_length; // source length in characters excluding comments and literals
- size_t m_originalLength; // source length in characters excluding comments and literals
- Js::LocalFunctionId * m_nextFunctionId;
- SourceContextInfo* m_sourceContextInfo;
- ParseErrorCallback m_errorCallback;
- void * m_errorCallbackData;
- BOOL m_uncertainStructure;
- bool m_hasParallelJob;
- bool m_doingFastScan;
- int m_nextBlockId;
- // RegexPattern objects created for literal regexes are recycler-allocated and need to be kept alive until the function body
- // is created during byte code generation. The RegexPattern pointer is stored in the script context's guest
- // arena for that purpose. This list is then unregistered from the guest arena at the end of parsing/scanning.
- SList<UnifiedRegex::RegexPattern *, ArenaAllocator> m_registeredRegexPatterns;
- protected:
- Js::ScriptContext* m_scriptContext;
- HashTbl * m_phtbl;
- static const uint HASH_TABLE_SIZE = 256;
- __declspec(noreturn) void Error(HRESULT hr);
- private:
- __declspec(noreturn) void Error(HRESULT hr, ParseNodePtr pnode);
- __declspec(noreturn) void Error(HRESULT hr, charcount_t ichMin, charcount_t ichLim);
- __declspec(noreturn) static void OutOfMemory();
- void GenerateCode(ParseNodePtr pnode, void *pvUser, int32 cbUser,
- LPCOLESTR pszSrc, int32 cchSrc, LPCOLESTR pszTitle);
- void EnsureStackAvailable();
- void IdentifierExpectedError(const Token& token);
- bool CheckForDirective(bool* pIsUseStrict, bool* pIsUseAsm, bool* pIsOctalInString);
- bool CheckStrictModeStrPid(IdentPtr pid);
- bool CheckAsmjsModeStrPid(IdentPtr pid);
- bool IsCurBlockInLoop() const;
- void InitPids();
- /***********************************************************************
- Members needed just for parsing.
- ***********************************************************************/
- protected:
- Token m_token;
- Scanner_t* m_pscan;
- public:
- // create nodes using arena allocator; used by AST transformation
- template <OpCode nop>
- static ParseNodePtr StaticCreateNodeT(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0)
- {
- ParseNodePtr pnode = StaticAllocNode<nop>(alloc);
- InitNode(nop,pnode);
- // default - may be changed
- pnode->ichMin = ichMin;
- pnode->ichLim = ichLim;
- return pnode;
- }
- static ParseNodePtr StaticCreateBinNode(OpCode nop, ParseNodePtr pnode1,ParseNodePtr pnode2,ArenaAllocator* alloc);
- static ParseNodePtr StaticCreateBlockNode(ArenaAllocator* alloc, charcount_t ichMin = 0, charcount_t ichLim = 0, int blockId = -1, PnodeBlockType blockType = PnodeBlockType::Regular);
- ParseNodePtr CreateNode(OpCode nop, charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateDummyFuncNode(bool fDeclaration);
- ParseNodePtr CreateTriNode(OpCode nop, ParseNodePtr pnode1,
- ParseNodePtr pnode2, ParseNodePtr pnode3,
- charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateTempNode(ParseNode* initExpr);
- ParseNodePtr CreateTempRef(ParseNode* tempNode);
- ParseNodePtr CreateNode(OpCode nop) { return CreateNode(nop, m_pscan? m_pscan->IchMinTok() : 0); }
- ParseNodePtr CreateDeclNode(OpCode nop, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl = true, bool *isRedecl = nullptr);
- Symbol* AddDeclForPid(ParseNodePtr pnode, IdentPtr pid, SymbolType symbolType, bool errorOnRedecl, bool *isRedecl = nullptr);
- ParseNodePtr CreateNameNode(IdentPtr pid)
- {
- ParseNodePtr pnode = CreateNode(knopName);
- pnode->sxPid.pid = pid;
- pnode->sxPid.sym=NULL;
- pnode->sxPid.symRef=NULL;
- return pnode;
- }
- ParseNodePtr CreateBlockNode(PnodeBlockType blockType = PnodeBlockType::Regular)
- {
- ParseNodePtr pnode = CreateNode(knopBlock);
- InitBlockNode(pnode, m_nextBlockId++, blockType);
- return pnode;
- }
- // Creating parse nodes.
- ParseNodePtr CreateNode(OpCode nop, charcount_t ichMin);
- ParseNodePtr CreateTriNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2, ParseNodePtr pnode3);
- ParseNodePtr CreateIntNode(int32 lw);
- ParseNodePtr CreateStrNode(IdentPtr pid);
- ParseNodePtr CreateUniNode(OpCode nop, ParseNodePtr pnodeOp);
- ParseNodePtr CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
- ParseNodePtr CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2);
- // Create parse node with token limis
- template <OpCode nop>
- ParseNodePtr CreateNodeT(charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateUniNode(OpCode nop, ParseNodePtr pnode1, charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateBlockNode(charcount_t ichMin,charcount_t ichLim, PnodeBlockType blockType = PnodeBlockType::Regular);
- ParseNodePtr CreateNameNode(IdentPtr pid,charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateBinNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2,
- charcount_t ichMin,charcount_t ichLim);
- ParseNodePtr CreateCallNode(OpCode nop, ParseNodePtr pnode1, ParseNodePtr pnode2,
- charcount_t ichMin,charcount_t ichLim);
- void PrepareScanner(bool fromExternal);
- void PrepareForBackgroundParse();
- void AddFastScannedRegExpNode(ParseNodePtr const pnode);
- #if ENABLE_BACKGROUND_PARSING
- void AddBackgroundRegExpNode(ParseNodePtr const pnode);
- void AddBackgroundParseItem(BackgroundParseItem *const item);
- void FinishBackgroundRegExpNodes();
- void FinishBackgroundPidRefs(BackgroundParseItem *const item, bool isOtherParser);
- void WaitForBackgroundJobs(BackgroundParser *bgp, CompileScriptException *pse);
- HRESULT ParseFunctionInBackground(ParseNodePtr pnodeFunc, ParseContext *parseContext, bool topLevelDeferred, CompileScriptException *pse);
- #endif
- void CheckPidIsValid(IdentPtr pid, bool autoArgumentsObject = false);
- void AddVarDeclToBlock(ParseNode *pnode);
- // Add a var declaration. Only use while parsing. Assumes m_ppnodeVar is pointing to the right place already
- ParseNodePtr CreateVarDeclNode(IdentPtr pid, SymbolType symbolType, bool autoArgumentsObject = false, ParseNodePtr pnodeFnc = NULL, bool checkReDecl = true, bool *isRedecl = nullptr);
- // Add a var declaration, during parse tree rewriting. Will setup m_ppnodeVar for the given pnodeFnc
- ParseNodePtr AddVarDeclNode(IdentPtr pid, ParseNodePtr pnodeFnc);
- // Add a 'const' or 'let' declaration.
- ParseNodePtr CreateBlockScopedDeclNode(IdentPtr pid, OpCode nodeType);
- void RegisterRegexPattern(UnifiedRegex::RegexPattern *const regexPattern);
- #ifdef ENABLE_DEBUG_CONFIG_OPTIONS
- LPCWSTR GetParseType() const
- {
- switch(m_parseType)
- {
- case ParseType_Upfront:
- return _u("Upfront");
- case ParseType_Deferred:
- return _u("Deferred");
- }
- Assert(false);
- return NULL;
- }
- #endif
- void CaptureContext(ParseContext *parseContext) const;
- void RestoreContext(ParseContext *const parseContext);
- int GetLastBlockId() const { Assert(m_nextBlockId > 0); return m_nextBlockId - 1; }
- private:
- template <OpCode nop> ParseNodePtr CreateNodeWithScanner();
- template <OpCode nop> ParseNodePtr CreateNodeWithScanner(charcount_t ichMin);
- ParseNodePtr CreateStrNodeWithScanner(IdentPtr pid);
- ParseNodePtr CreateIntNodeWithScanner(int32 lw);
- ParseNodePtr CreateProgNodeWithScanner(bool isModuleSource);
- static void InitNode(OpCode nop,ParseNodePtr pnode);
- static void InitBlockNode(ParseNodePtr pnode, int blockId, PnodeBlockType blockType);
- private:
- ParseNodePtr m_currentNodeNonLambdaFunc; // current function or NULL
- ParseNodePtr m_currentNodeNonLambdaDeferredFunc; // current function or NULL
- ParseNodePtr m_currentNodeFunc; // current function or NULL
- ParseNodePtr m_currentNodeDeferredFunc; // current function or NULL
- ParseNodePtr m_currentNodeProg; // current program
- DeferredFunctionStub *m_currDeferredStub;
- DeferredFunctionStub *m_prevSiblingDeferredStub;
- int32 * m_pCurrentAstSize;
- ParseNodePtr * m_ppnodeScope; // function list tail
- ParseNodePtr * m_ppnodeExprScope; // function expression list tail
- ParseNodePtr * m_ppnodeVar; // variable list tail
- bool m_inDeferredNestedFunc; // true if parsing a function in deferred mode, nested within the current node
- bool m_isInBackground;
- bool m_reparsingLambdaParams;
- // This bool is used for deferring the shorthand initializer error ( {x = 1}) - as it is allowed in the destructuring grammar.
- bool m_hasDeferredShorthandInitError;
- uint * m_pnestedCount; // count of functions nested at one level below the current node
- struct WellKnownPropertyPids
- {
- IdentPtr arguments;
- IdentPtr async;
- IdentPtr eval;
- IdentPtr set;
- IdentPtr get;
- IdentPtr let;
- IdentPtr constructor;
- IdentPtr prototype;
- IdentPtr __proto__;
- IdentPtr of;
- IdentPtr target;
- IdentPtr from;
- IdentPtr as;
- IdentPtr _default;
- IdentPtr _star; // Special '*' identifier for modules
- IdentPtr _starDefaultStar; // Special '*default*' identifier for modules
- };
- WellKnownPropertyPids wellKnownPropertyPids;
- charcount_t m_sourceLim; // The actual number of characters parsed.
- Js::ParseableFunctionInfo* m_functionBody; // For a deferred parsed function, the function body is non-null
- ParseType m_parseType;
- uint m_arrayDepth;
- uint m_funcInArrayDepth; // Count func depth within array literal
- charcount_t m_funcInArray;
- uint m_scopeCountNoAst;
- /*
- * Parsing states for super restriction
- */
- static const uint ParsingSuperRestrictionState_SuperDisallowed = 0;
- static const uint ParsingSuperRestrictionState_SuperCallAndPropertyAllowed = 1;
- static const uint ParsingSuperRestrictionState_SuperPropertyAllowed = 2;
- uint m_parsingSuperRestrictionState;
- friend class AutoParsingSuperRestrictionStateRestorer;
- // Used for issuing spread and rest errors when there is ambiguity with parameter list and parenthesized expressions
- uint m_parenDepth;
- bool m_deferEllipsisError;
- RestorePoint m_EllipsisErrLoc;
- 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
- StmtNest *m_pstmtCur; // current statement or NULL
- BlockInfoStack *m_currentBlockInfo;
- Scope *m_currentScope;
- BackgroundParseItem *currBackgroundParseItem;
- BackgroundParseItem *backgroundParseItems;
- typedef DList<ParseNodePtr, ArenaAllocator> NodeDList;
- NodeDList* fastScannedRegExpNodes;
- BlockIdsStack *m_currentDynamicBlock;
- int GetCurrentDynamicBlockId() const;
- void AppendFunctionToScopeList(bool fDeclaration, ParseNodePtr pnodeFnc);
- // block scoped content helpers
- void SetCurrentStatement(StmtNest *stmt);
- ParseNode* GetCurrentBlock();
- ParseNode* GetFunctionBlock();
- BlockInfoStack* GetCurrentBlockInfo();
- BlockInfoStack* GetCurrentFunctionBlockInfo();
- ParseNode *GetCurrentFunctionNode();
- ParseNode *GetCurrentNonLambdaFunctionNode();
- bool IsNodeAllowedInCurrentDeferralState(OpCode op)
- {
- if (!this->m_deferringAST)
- {
- return true;
- }
- switch(op)
- {
- case knopBlock:
- case knopVarDecl:
- case knopConstDecl:
- case knopLetDecl:
- case knopFncDecl:
- case knopName:
- return true;
- default:
- return false;
- }
- }
- bool NextTokenConfirmsLetDecl() const { return m_token.tk == tkID || m_token.tk == tkLBrack || m_token.tk == tkLCurly || m_token.IsReservedWord(); }
- 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(); }
- template<bool buildAST>
- void PushStmt(StmtNest *pStmt, ParseNodePtr pnode, OpCode op, ParseNodePtr pnodeLab, LabelId* pLabelIdList)
- {
- AssertMem(pStmt);
- if (buildAST)
- {
- AssertNodeMem(pnode);
- AssertNodeMemN(pnodeLab);
- pnode->sxStmt.grfnop = 0;
- pnode->sxStmt.pnodeOuter = (NULL == m_pstmtCur) ? NULL : m_pstmtCur->pnodeStmt;
- pStmt->pnodeStmt = pnode;
- pStmt->pnodeLab = pnodeLab;
- }
- else
- {
- // Assign to pnodeStmt rather than op so that we initialize the whole field.
- pStmt->pnodeStmt = 0;
- pStmt->isDeferred = true;
- pStmt->op = op;
- pStmt->pLabelId = pLabelIdList;
- }
- pStmt->pstmtOuter = m_pstmtCur;
- SetCurrentStatement(pStmt);
- }
- void PopStmt(StmtNest *pStmt);
- BlockInfoStack *PushBlockInfo(ParseNodePtr pnodeBlock);
- void PopBlockInfo();
- void PushDynamicBlock();
- void PopDynamicBlock();
- ParseNodePtr PnodeLabel(IdentPtr pid, ParseNodePtr pnodeLabels);
- void MarkEvalCaller()
- {
- if (this->GetCurrentFunctionNode())
- {
- ParseNodePtr pnodeFunc = GetCurrentFunctionNode();
- pnodeFunc->sxFnc.SetCallsEval(true);
- }
- ParseNode *pnodeBlock = GetCurrentBlock();
- if (pnodeBlock != NULL)
- {
- pnodeBlock->sxBlock.SetCallsEval(true);
- PushDynamicBlock();
- }
- }
- struct ParserState
- {
- ParseNodePtr *m_ppnodeScopeSave;
- ParseNodePtr *m_ppnodeExprScopeSave;
- charcount_t m_funcInArraySave;
- int32 *m_pCurrentAstSizeSave;
- uint m_funcInArrayDepthSave;
- uint m_nestedCountSave;
- int m_nextBlockId;
- #if DEBUG
- // For very basic validation purpose - to check that we are not going restore to some other block.
- BlockInfoStack *m_currentBlockInfo;
- #endif
- };
- // This function is going to capture some of the important current state of the parser to an object. Once we learn
- // that we need to reparse the grammar again we could use RestoreStateFrom to restore that state to the parser.
- void CaptureState(ParserState *state);
- void RestoreStateFrom(ParserState *state);
- // Future recommendation : Consider consolidating Parser::CaptureState and Scanner::Capture together if we do CaptureState more often.
- public:
- IdentPtrList* GetRequestedModulesList();
- ModuleImportOrExportEntryList* GetModuleImportEntryList();
- ModuleImportOrExportEntryList* GetModuleLocalExportEntryList();
- ModuleImportOrExportEntryList* GetModuleIndirectExportEntryList();
- ModuleImportOrExportEntryList* GetModuleStarExportEntryList();
- protected:
- IdentPtrList* EnsureRequestedModulesList();
- ModuleImportOrExportEntryList* EnsureModuleImportEntryList();
- ModuleImportOrExportEntryList* EnsureModuleLocalExportEntryList();
- ModuleImportOrExportEntryList* EnsureModuleIndirectExportEntryList();
- ModuleImportOrExportEntryList* EnsureModuleStarExportEntryList();
- void AddModuleSpecifier(IdentPtr moduleRequest);
- ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, IdentPtr importName, IdentPtr localName, IdentPtr exportName, IdentPtr moduleRequest);
- ModuleImportOrExportEntry* AddModuleImportOrExportEntry(ModuleImportOrExportEntryList* importOrExportEntryList, ModuleImportOrExportEntry* importOrExportEntry);
- void AddModuleLocalExportEntry(ParseNodePtr varDeclNode);
- void CheckForDuplicateExportEntry(ModuleImportOrExportEntryList* exportEntryList, IdentPtr exportName);
- ParseNodePtr CreateModuleImportDeclNode(IdentPtr localName);
- void MarkIdentifierReferenceIsModuleExport(IdentPtr localName);
- public:
- WellKnownPropertyPids* names(){ return &wellKnownPropertyPids; }
- IdentPtr CreatePid(__in_ecount(len) LPCOLESTR name, charcount_t len)
- {
- return m_phtbl->PidHashNameLen(name, len);
- }
- bool KnownIdent(__in_ecount(len) LPCOLESTR name, charcount_t len)
- {
- return m_phtbl->Contains(name, len);
- }
- template <typename THandler>
- static void ForEachItemRefInList(ParseNodePtr *list, THandler handler)
- {
- ParseNodePtr *current = list;
- while (current != nullptr && (*current) != nullptr)
- {
- if ((*current)->nop == knopList)
- {
- handler(&(*current)->sxBin.pnode1);
- // Advance to the next node
- current = &(*current)->sxBin.pnode2;
- }
- else
- {
- // The last node
- handler(current);
- current = nullptr;
- }
- }
- }
- template <typename THandler>
- static void ForEachItemInList(ParseNodePtr list, THandler handler)
- {
- ForEachItemRefInList(&list, [&](ParseNodePtr * item) {
- Assert(item != nullptr);
- handler(*item);
- });
- }
- template <class THandler>
- static void MapBindIdentifierFromElement(ParseNodePtr elementNode, THandler handler)
- {
- ParseNodePtr bindIdentNode = elementNode;
- if (bindIdentNode->nop == knopAsg)
- {
- bindIdentNode = bindIdentNode->sxBin.pnode1;
- }
- else if (bindIdentNode->nop == knopEllipsis)
- {
- bindIdentNode = bindIdentNode->sxUni.pnode1;
- }
- if (bindIdentNode->IsPattern())
- {
- MapBindIdentifier(bindIdentNode, handler);
- }
- else if (bindIdentNode->IsVarLetOrConst())
- {
- handler(bindIdentNode);
- }
- else
- {
- AssertMsg(bindIdentNode->nop == knopEmpty, "Invalid bind identifier");
- }
- }
- template <class THandler>
- static void MapBindIdentifier(ParseNodePtr patternNode, THandler handler)
- {
- if (patternNode->nop == knopAsg)
- {
- patternNode = patternNode->sxBin.pnode1;
- }
- Assert(patternNode->IsPattern());
- if (patternNode->nop == knopArrayPattern)
- {
- ForEachItemInList(patternNode->sxArrLit.pnode1, [&](ParseNodePtr item) {
- MapBindIdentifierFromElement(item, handler);
- });
- }
- else
- {
- ForEachItemInList(patternNode->sxUni.pnode1, [&](ParseNodePtr item) {
- Assert(item->nop == knopObjectPatternMember);
- MapBindIdentifierFromElement(item->sxBin.pnode2, handler);
- });
- }
- }
- private:
- struct IdentToken
- {
- tokens tk;
- IdentPtr pid;
- charcount_t ichMin;
- charcount_t ichLim;
- IdentToken()
- : tk(tkNone), pid(NULL)
- {
- }
- };
- void CheckArguments(ParseNodePtr pnode);
- void CheckArgumentsUse(IdentPtr pid, ParseNodePtr pnodeFnc);
- void CheckStrictModeEvalArgumentsUsage(IdentPtr pid, ParseNodePtr pnode = NULL);
- // environments on which the strict mode is set, if found
- enum StrictModeEnvironment
- {
- SM_NotUsed, // StrictMode environment is don't care
- SM_OnGlobalCode, // The current environment is a global code
- SM_OnFunctionCode, // The current environment is a function code
- SM_DeferredParse // StrictMode used in deferred parse cases
- };
- template<bool buildAST> ParseNodePtr ParseArrayLiteral();
- template<bool buildAST> ParseNodePtr ParseStatement();
- template<bool buildAST> ParseNodePtr ParseVariableDeclaration(
- tokens declarationType,
- charcount_t ichMin,
- BOOL fAllowIn = TRUE,
- BOOL* pfForInOk = nullptr,
- BOOL singleDefOnly = FALSE,
- BOOL allowInit = TRUE,
- BOOL isTopVarParse = TRUE,
- BOOL isFor = FALSE,
- BOOL* nativeForOk = nullptr);
- BOOL TokIsForInOrForOf();
- template<bool buildAST>
- void ParseStmtList(
- ParseNodePtr *ppnodeList,
- ParseNodePtr **pppnodeLast = NULL,
- StrictModeEnvironment smEnvironment = SM_NotUsed,
- const bool isSourceElementList = false,
- bool* strictModeOn = NULL);
- bool FastScanFormalsAndBody();
- bool ScanAheadToFunctionEnd(uint count);
- bool DoParallelParse(ParseNodePtr pnodeFnc) const;
- // TODO: We should really call this StartScope and separate out the notion of scopes and blocks;
- // blocks refer to actual curly braced syntax, whereas scopes contain symbols. All blocks have
- // a scope, but some statements like for loops or the with statement introduce a block-less scope.
- template<bool buildAST> ParseNodePtr StartParseBlock(PnodeBlockType blockType, ScopeType scopeType, ParseNodePtr pnodeLabel = NULL, LabelId* pLabelId = NULL);
- template<bool buildAST> ParseNodePtr StartParseBlockWithCapacity(PnodeBlockType blockType, ScopeType scopeType, int capacity);
- template<bool buildAST> ParseNodePtr StartParseBlockHelper(PnodeBlockType blockType, Scope *scope, ParseNodePtr pnodeLabel, LabelId* pLabelId);
- void PushFuncBlockScope(ParseNodePtr pnodeBlock, ParseNodePtr **ppnodeScopeSave, ParseNodePtr **ppnodeExprScopeSave);
- void PopFuncBlockScope(ParseNodePtr *ppnodeScopeSave, ParseNodePtr *ppnodeExprScopeSave);
- template<bool buildAST> ParseNodePtr ParseBlock(ParseNodePtr pnodeLabel, LabelId* pLabelId);
- void FinishParseBlock(ParseNode *pnodeBlock, bool needScanRCurly = true);
- void FinishParseFncExprScope(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncExprScope);
- template<const bool backgroundPidRefs>
- void BindPidRefs(BlockInfoStack *blockInfo, uint maxBlockId = (uint)-1);
- void BindPidRefsInScope(IdentPtr pid, Symbol *sym, int blockId, uint maxBlockId = (uint)-1);
- void MarkEscapingRef(ParseNodePtr pnode, IdentToken *pToken);
- void SetNestedFuncEscapes() const;
- void SetSymHasNonLocalReference(Symbol *sym);
- void PushScope(Scope *scope);
- void PopScope(Scope *scope);
- template<bool buildAST> ParseNodePtr ParseArgList(bool *pCallOfConstants, uint16 *pSpreadArgCount, uint16 * pCount);
- template<bool buildAST> ParseNodePtr ParseArrayList(bool *pArrayOfTaggedInts, bool *pArrayOfInts, bool *pArrayOfNumbers, bool *pHasMissingValues, uint *count, uint *spreadCount);
- template<bool buildAST> ParseNodePtr ParseMemberList(LPCOLESTR pNameHint, uint32 *pHintLength, tokens declarationType = tkNone);
- template<bool buildAST> ParseNodePtr ParseSuper(ParseNodePtr pnode, bool fAllowCall);
- // Used to determine the type of JavaScript object member.
- // The values can be combined using bitwise OR.
- // specifically, it is valid to have getter and setter at the same time.
- enum MemberType
- {
- MemberTypeDataProperty = 1 << 0, // { foo: 1 },
- MemberTypeGetter = 1 << 1, // { get foo() }
- MemberTypeSetter = 1 << 2, // { set foo(arg) {} }
- MemberTypeMethod = 1 << 3, // { foo() {} }
- MemberTypeIdentifier = 1 << 4 // { foo } (shorthand for { foo: foo })
- };
- // Used to map JavaScript object member name to member type.
- typedef JsUtil::BaseDictionary<WCHAR*, MemberType, ArenaAllocator, PrimeSizePolicy> MemberNameToTypeMap;
- static MemberNameToTypeMap* CreateMemberNameMap(ArenaAllocator* pAllocator);
- template<bool buildAST> void ParseComputedName(ParseNodePtr* ppnodeName, LPCOLESTR* ppNameHint, LPCOLESTR* ppFullNameHint = nullptr, uint32 *pNameLength = nullptr, uint32 *pShortNameOffset = nullptr);
- template<bool buildAST> ParseNodePtr ParseMemberGetSet(OpCode nop, LPCOLESTR* ppNameHint);
- template<bool buildAST> ParseNodePtr ParseFncDecl(ushort flags, LPCOLESTR pNameHint = NULL, const bool needsPIDOnRCurlyScan = false, bool resetParsingSuperRestrictionState = true, bool fUnaryOrParen = false);
- template<bool buildAST> bool ParseFncNames(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, ushort flags, ParseNodePtr **pLastNodeRef);
- template<bool buildAST> void ParseFncFormals(ParseNodePtr pnodeFnc, ParseNodePtr pnodeParentFnc, ushort flags);
- template<bool buildAST> bool ParseFncDeclHelper(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, ushort flags, bool *pHasName, bool fUnaryOrParen, bool noStmtContext, bool *pNeedScanRCurly, bool skipFormals = false);
- template<bool buildAST> void ParseExpressionLambdaBody(ParseNodePtr pnodeFnc);
- template<bool buildAST> void UpdateCurrentNodeFunc(ParseNodePtr pnodeFnc, bool fLambda);
- bool FncDeclAllowedWithoutContext(ushort flags);
- void FinishFncDecl(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint, ParseNodePtr *lastNodeRef, bool skipCurlyBraces = false);
- void ParseTopLevelDeferredFunc(ParseNodePtr pnodeFnc, ParseNodePtr pnodeFncParent, LPCOLESTR pNameHint);
- void ParseNestedDeferredFunc(ParseNodePtr pnodeFnc, bool fLambda, bool *pNeedScanRCurly, bool *pStrictModeTurnedOn);
- void CheckStrictFormalParameters();
- ParseNodePtr AddArgumentsNodeToVars(ParseNodePtr pnodeFnc);
- void UpdateArgumentsNode(ParseNodePtr pnodeFnc, ParseNodePtr argNode);
- void UpdateOrCheckForDuplicateInFormals(IdentPtr pid, SList<IdentPtr> *formals);
- LPCOLESTR GetFunctionName(ParseNodePtr pnodeFnc, LPCOLESTR pNameHint);
- uint CalculateFunctionColumnNumber();
- template<bool buildAST> ParseNodePtr GenerateEmptyConstructor(bool extends = false);
- template<bool buildAST> ParseNodePtr GenerateModuleFunctionWrapper();
- IdentPtr ParseClassPropertyName(IdentPtr * hint);
- template<bool buildAST> ParseNodePtr ParseClassDecl(BOOL isDeclaration, LPCOLESTR pNameHint, uint32 *pHintLength, uint32 *pShortNameOffset);
- template<bool buildAST> ParseNodePtr ParseStringTemplateDecl(ParseNodePtr pnodeTagFnc);
- // This is used in the es6 class pattern.
- LPCOLESTR ConstructFinalHintNode(IdentPtr pClassName, IdentPtr pMemberName, IdentPtr pGetSet, bool isStatic, uint32* nameLength, uint32* pShortNameOffset, bool isComputedName = false, LPCOLESTR pMemberNameHint = nullptr);
- // Construct the name from the parse node.
- LPCOLESTR FormatPropertyString(LPCOLESTR propertyString, ParseNodePtr pNode, uint32 *fullNameHintLength, uint32 *pShortNameOffset);
- LPCOLESTR ConstructNameHint(ParseNodePtr pNode, uint32* fullNameHintLength, uint32 *pShortNameOffset);
- LPCOLESTR AppendNameHints(IdentPtr left, IdentPtr right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
- LPCOLESTR AppendNameHints(IdentPtr left, LPCOLESTR right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
- LPCOLESTR AppendNameHints(LPCOLESTR left, IdentPtr right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
- LPCOLESTR AppendNameHints(LPCOLESTR left, LPCOLESTR right, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
- LPCOLESTR AppendNameHints(LPCOLESTR leftStr, uint32 leftLen, LPCOLESTR rightStr, uint32 rightLen, uint32 *pNameLength, uint32 *pShortNameOffset, bool ignoreAddDotWithSpace = false, bool wrapInBrackets = false);
- WCHAR * AllocateStringOfLength(ULONG length);
- void FinishFncNode(ParseNodePtr pnodeFnc);
- template<bool buildAST> bool ParseOptionalExpr(
- ParseNodePtr* pnode,
- bool fUnaryOrParen = false,
- int oplMin = koplNo,
- BOOL *pfCanAssign = NULL,
- BOOL fAllowIn = TRUE,
- BOOL fAllowEllipsis = FALSE,
- _Inout_opt_ IdentToken* pToken = NULL);
- template<bool buildAST> ParseNodePtr ParseExpr(
- int oplMin = koplNo,
- BOOL *pfCanAssign = NULL,
- BOOL fAllowIn = TRUE,
- BOOL fAllowEllipsis = FALSE,
- LPCOLESTR pHint = NULL,
- uint32 *pHintLength = nullptr,
- uint32 *pShortNameOffset = nullptr,
- _Inout_opt_ IdentToken* pToken = NULL,
- bool fUnaryOrParen = false,
- _Inout_opt_ bool* pfLikelyPattern = nullptr,
- _Inout_opt_ charcount_t *plastRParen = nullptr);
- template<bool buildAST> ParseNodePtr ParseTerm(
- BOOL fAllowCall = TRUE,
- LPCOLESTR pNameHint = nullptr,
- uint32 *pHintLength = nullptr,
- uint32 *pShortNameOffset = nullptr,
- _Inout_opt_ IdentToken* pToken = nullptr,
- bool fUnaryOrParen = false,
- _Out_opt_ BOOL* pfCanAssign = nullptr,
- _Inout_opt_ BOOL* pfLikelyPattern = nullptr,
- _Out_opt_ bool* pfIsDotOrIndex = nullptr,
- _Inout_opt_ charcount_t *plastRParen = nullptr);
- template<bool buildAST> ParseNodePtr ParsePostfixOperators(
- ParseNodePtr pnode,
- BOOL fAllowCall,
- BOOL fInNew,
- BOOL isAsyncExpr,
- BOOL *pfCanAssign,
- _Inout_ IdentToken* pToken,
- _Out_opt_ bool* pfIsDotOrIndex = nullptr);
- void ThrowNewTargetSyntaxErrForGlobalScope();
- template<bool buildAST> ParseNodePtr ParseMetaProperty(
- tokens metaParentKeyword,
- charcount_t ichMin,
- _Out_opt_ BOOL* pfCanAssign = nullptr);
- bool IsImportOrExportStatementValidHere();
- template<bool buildAST> ParseNodePtr ParseImport();
- template<bool buildAST> void ParseImportClause(ModuleImportOrExportEntryList* importEntryList, bool parsingAfterComma = false);
- template<bool buildAST> ParseNodePtr ParseImportCall();
- template<bool buildAST> ParseNodePtr ParseExportDeclaration();
- template<bool buildAST> ParseNodePtr ParseDefaultExportClause();
- template<bool buildAST> void ParseNamedImportOrExportClause(ModuleImportOrExportEntryList* importOrExportEntryList, bool isExportClause);
- template<bool buildAST> IdentPtr ParseImportOrExportFromClause(bool throwIfNotFound);
- BOOL NodeIsIdent(ParseNodePtr pnode, IdentPtr pid);
- BOOL NodeIsEvalName(ParseNodePtr pnode);
- BOOL IsJSONValid(ParseNodePtr pnodeExpr)
- {
- OpCode jnop = (knopNeg == pnodeExpr->nop) ? pnodeExpr->sxUni.pnode1->nop : pnodeExpr->nop;
- if (knopNeg == pnodeExpr->nop)
- {
- return (knopInt == jnop || knopFlt == jnop);
- }
- else
- {
- return (knopInt == jnop || knopFlt == jnop ||
- knopStr == jnop || knopNull == jnop ||
- knopTrue == jnop || knopFalse == jnop ||
- knopObject == jnop || knopArray == jnop);
- }
- }
- BOOL IsConstantInFunctionCall(ParseNodePtr pnode);
- BOOL IsConstantInArrayLiteral(ParseNodePtr pnode);
- ParseNodePtr CreateParamPatternNode(ParseNodePtr pnode1);
- ParseNodePtr ConvertMemberToMemberPattern(ParseNodePtr pnodeMember);
- ParseNodePtr ConvertObjectToObjectPattern(ParseNodePtr pnodeMemberList);
- ParseNodePtr GetRightSideNodeFromPattern(ParseNodePtr pnode);
- ParseNodePtr ConvertArrayToArrayPattern(ParseNodePtr pnode);
- ParseNodePtr ConvertToPattern(ParseNodePtr pnode);
- void AppendToList(ParseNodePtr * node, ParseNodePtr nodeToAppend);
- bool IsES6DestructuringEnabled() const;
- bool IsPossiblePatternStart() const { return m_token.tk == tkLCurly || m_token.tk == tkLBrack; }
- bool IsPostFixOperators() const
- {
- return m_token.tk == tkLParen ||
- m_token.tk == tkLBrack ||
- m_token.tk == tkDot ||
- m_token.tk == tkStrTmplBasic ||
- m_token.tk == tkStrTmplBegin;
- }
- template<bool buildAST> ParseNodePtr ParseTryCatchFinally();
- template<bool buildAST> ParseNodePtr ParseTry();
- template<bool buildAST> ParseNodePtr ParseCatch();
- template<bool buildAST> ParseNodePtr ParseFinally();
- template<bool buildAST> ParseNodePtr ParseCase(ParseNodePtr *ppnodeBody);
- template<bool buildAST> ParseNodePtr ParseRegExp();
- template <bool buildAST>
- ParseNodePtr ParseDestructuredArrayLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
- template <bool buildAST>
- ParseNodePtr ParseDestructuredObjectLiteral(tokens declarationType, bool isDecl, bool topLevel = true);
- template <bool buildAST>
- ParseNodePtr ParseDestructuredLiteral(tokens declarationType,
- bool isDecl,
- bool topLevel = true,
- DestructuringInitializerContext initializerContext = DIC_None,
- bool allowIn = true,
- BOOL *forInOfOkay = nullptr,
- BOOL *nativeForOkay = nullptr);
- template <bool buildAST>
- ParseNodePtr ParseDestructuredVarDecl(tokens declarationType, bool isDecl, bool *hasSeenRest, bool topLevel = true, bool allowEmptyExpression = true);
- template <bool buildAST>
- ParseNodePtr ParseDestructuredInitializer(ParseNodePtr lhsNode,
- bool isDecl,
- bool topLevel,
- DestructuringInitializerContext initializerContext,
- bool allowIn,
- BOOL *forInOfOkay,
- BOOL *nativeForOkay);
- template<bool CheckForNegativeInfinity> static bool IsNaNOrInfinityLiteral(LPCOLESTR str);
- void ParseDestructuredLiteralWithScopeSave(tokens declarationType,
- bool isDecl,
- bool topLevel,
- DestructuringInitializerContext initializerContext = DIC_None,
- bool allowIn = true);
- public:
- void ValidateSourceElementList();
- void ValidateFormals();
- bool IsStrictMode() const;
- BOOL ExpectingExternalSource();
- IdentPtr GetArgumentsPid() const { return wellKnownPropertyPids.arguments; }
- IdentPtr GetEvalPid() const { return wellKnownPropertyPids.eval; }
- IdentPtr GetTargetPid() const { return wellKnownPropertyPids.target; }
- BackgroundParseItem *GetCurrBackgroundParseItem() const { return currBackgroundParseItem; }
- void SetCurrBackgroundParseItem(BackgroundParseItem *item) { currBackgroundParseItem = item; }
- void Release()
- {
- RELEASEPTR(m_pscan);
- RELEASEPTR(m_phtbl);
- }
- private:
- void DeferOrEmitPotentialSpreadError(ParseNodePtr pnodeT);
- template<bool buildAST> void TrackAssignment(ParseNodePtr pnodeT, IdentToken* pToken);
- PidRefStack* PushPidRef(IdentPtr pid);
- PidRefStack* FindOrAddPidRef(IdentPtr pid, int blockId, Js::LocalFunctionId funcId);
- void RemovePrevPidRef(IdentPtr pid, PidRefStack *lastRef);
- void SetPidRefsInScopeDynamic(IdentPtr pid, int blockId);
- void RestoreScopeInfo(Js::ScopeInfo * scopeInfo);
- void FinishScopeInfo(Js::ScopeInfo * scopeInfo);
- BOOL PnodeLabelNoAST(IdentToken* pToken, LabelId* pLabelIdList);
- LabelId* CreateLabelId(IdentToken* pToken);
- void AddToNodeList(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
- void AddToNodeListEscapedUse(ParseNode ** ppnodeList, ParseNode *** pppnodeLast, ParseNode * pnodeAdd);
- void ChkCurTokNoScan(int tk, int wErr)
- {
- if (m_token.tk != tk)
- {
- Error(wErr);
- }
- }
- void ChkCurTok(int tk, int wErr)
- {
- if (m_token.tk != tk)
- {
- Error(wErr);
- }
- else
- {
- m_pscan->Scan();
- }
- }
- void ChkNxtTok(int tk, int wErr)
- {
- m_pscan->Scan();
- ChkCurTok(tk, wErr);
- }
- template <class Fn>
- void FinishFunctionsInScope(ParseNodePtr pnodeScopeList, Fn fn);
- void FinishDeferredFunction(ParseNodePtr pnodeScopeList);
- /***********************************************************************
- Misc
- ***********************************************************************/
- bool m_UsesArgumentsAtGlobal; // "arguments" used at global code.
- BOOL m_fUseStrictMode; // ES5 Use Strict mode. In AST mode this is a global flag; in NoAST mode it is pushed and popped.
- bool m_InAsmMode; // Currently parsing Asm.Js module
- bool m_deferAsmJs;
- BOOL m_fExpectExternalSource;
- BOOL m_deferringAST;
- BOOL m_stoppedDeferredParse;
- enum FncDeclFlag : ushort
- {
- fFncNoFlgs = 0,
- fFncDeclaration = 1 << 0,
- fFncNoArg = 1 << 1,
- fFncOneArg = 1 << 2, //Force exactly one argument.
- fFncNoName = 1 << 3,
- fFncLambda = 1 << 4,
- fFncMethod = 1 << 5,
- fFncClassMember = 1 << 6,
- fFncGenerator = 1 << 7,
- fFncAsync = 1 << 8,
- fFncModule = 1 << 9,
- };
- //
- // If we need the scanner to force PID creation temporarily, use this auto object
- // to turn scanner deferred parsing off temporarily and restore at destructor.
- //
- class AutoTempForcePid
- {
- private:
- Scanner_t* m_scanner;
- bool m_forcePid;
- BYTE m_oldScannerDeferredParseFlags;
- public:
- AutoTempForcePid(Scanner_t* scanner, bool forcePid)
- : m_scanner(scanner), m_forcePid(forcePid)
- {
- if (forcePid)
- {
- m_oldScannerDeferredParseFlags = scanner->SetDeferredParse(FALSE);
- }
- }
- ~AutoTempForcePid()
- {
- if (m_forcePid)
- {
- m_scanner->SetDeferredParseFlags(m_oldScannerDeferredParseFlags);
- }
- }
- };
- public:
- charcount_t GetSourceIchLim() { return m_sourceLim; }
- static BOOL NodeEqualsName(ParseNodePtr pnode, LPCOLESTR sz, uint32 cch);
- };
- #define PTNODE(nop,sn,pc,nk,ok,json) \
- template<> inline int Parser::GetNodeSize<nop>() { return kcbPn##nk; }
- #include "ptlist.h"
|