+ return m_lexer->nextTokenIsColon();
+ }
+
+ ALWAYS_INLINE bool consume(JSTokenType expected, unsigned flags = 0)
+ {
+ bool result = m_token.m_type == expected;
+ if (result)
+ next(flags);
+ return result;
+ }
+
+ void printUnexpectedTokenText(WTF::PrintStream&);
+ ALWAYS_INLINE String getToken() {
+ SourceProvider* sourceProvider = m_source->provider();
+ return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset);
+ }
+
+ ALWAYS_INLINE bool match(JSTokenType expected)
+ {
+ return m_token.m_type == expected;
+ }
+
+ ALWAYS_INLINE bool isofToken()
+ {
+ return m_token.m_type == IDENT && *m_token.m_data.ident == m_vm->propertyNames->of;
+ }
+
+ ALWAYS_INLINE unsigned tokenStart()
+ {
+ return m_token.m_location.startOffset;
+ }
+
+ ALWAYS_INLINE const JSTextPosition& tokenStartPosition()
+ {
+ return m_token.m_startPosition;
+ }
+
+ ALWAYS_INLINE int tokenLine()
+ {
+ return m_token.m_location.line;
+ }
+
+ ALWAYS_INLINE int tokenColumn()
+ {
+ return tokenStart() - tokenLineStart();
+ }
+
+ ALWAYS_INLINE const JSTextPosition& tokenEndPosition()
+ {
+ return m_token.m_endPosition;
+ }
+
+ ALWAYS_INLINE unsigned tokenLineStart()
+ {
+ return m_token.m_location.lineStartOffset;
+ }
+
+ ALWAYS_INLINE const JSTokenLocation& tokenLocation()
+ {
+ return m_token.m_location;
+ }
+
+ void setErrorMessage(String msg)
+ {
+ m_errorMessage = msg;
+ }
+
+ NEVER_INLINE void logError(bool);
+ template <typename A> NEVER_INLINE void logError(bool, const A&);
+ template <typename A, typename B> NEVER_INLINE void logError(bool, const A&, const B&);
+ template <typename A, typename B, typename C> NEVER_INLINE void logError(bool, const A&, const B&, const C&);
+ template <typename A, typename B, typename C, typename D> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&);
+ template <typename A, typename B, typename C, typename D, typename E> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&);
+ template <typename A, typename B, typename C, typename D, typename E, typename F> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&);
+ template <typename A, typename B, typename C, typename D, typename E, typename F, typename G> NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&, const G&);
+
+ NEVER_INLINE void updateErrorWithNameAndMessage(const char* beforeMsg, String name, const char* afterMsg)
+ {
+ m_errorMessage = makeString(beforeMsg, " '", name, "' ", afterMsg);
+ }
+
+ NEVER_INLINE void updateErrorMessage(const char* msg)
+ {
+ ASSERT(msg);
+ m_errorMessage = String(msg);
+ ASSERT(!m_errorMessage.isNull());
+ }
+
+ void startLoop() { currentScope()->startLoop(); }
+ void endLoop() { currentScope()->endLoop(); }
+ void startSwitch() { currentScope()->startSwitch(); }
+ void endSwitch() { currentScope()->endSwitch(); }
+ void setStrictMode() { currentScope()->setStrictMode(); }
+ bool strictMode() { return currentScope()->strictMode(); }
+ bool isValidStrictMode() { return currentScope()->isValidStrictMode(); }
+ bool declareParameter(const Identifier* ident) { return currentScope()->declareParameter(ident); }
+ Scope::BindingResult declareBoundParameter(const Identifier* ident) { return currentScope()->declareBoundParameter(ident); }
+ bool breakIsValid()
+ {
+ ScopeRef current = currentScope();
+ while (!current->breakIsValid()) {
+ if (!current.hasContainingScope())
+ return false;
+ current = current.containingScope();
+ }
+ return true;
+ }
+ bool continueIsValid()
+ {
+ ScopeRef current = currentScope();
+ while (!current->continueIsValid()) {
+ if (!current.hasContainingScope())
+ return false;
+ current = current.containingScope();
+ }
+ return true;
+ }
+ void pushLabel(const Identifier* label, bool isLoop) { currentScope()->pushLabel(label, isLoop); }
+ void popLabel() { currentScope()->popLabel(); }
+ ScopeLabelInfo* getLabel(const Identifier* label)
+ {
+ ScopeRef current = currentScope();
+ ScopeLabelInfo* result = 0;
+ while (!(result = current->getLabel(label))) {
+ if (!current.hasContainingScope())
+ return 0;
+ current = current.containingScope();
+ }
+ return result;
+ }
+
+ template <class TreeBuilder> TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode);
+ template <class TreeBuilder> TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0);
+ template <class TreeBuilder> TreeStatement parseFunctionDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseVarDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseConstDeclaration(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseDoWhileStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseWhileStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseForStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseBreakStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseContinueStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseReturnStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseThrowStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseWithStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseSwitchStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeClauseList parseSwitchClauses(TreeBuilder&);
+ template <class TreeBuilder> TreeClause parseSwitchDefaultClause(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseTryStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseDebuggerStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseExpressionStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseExpressionOrLabelStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseIfStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeStatement parseBlockStatement(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseExpression(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseAssignmentExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseBinaryExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseUnaryExpression(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseMemberExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&);
+ template <class TreeBuilder> NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&);
+ enum SpreadMode { AllowSpread, DontAllowSpread };
+ template <class TreeBuilder> ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode);
+ template <class TreeBuilder> TreeProperty parseProperty(TreeBuilder&, bool strict);
+ template <class TreeBuilder> ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&);
+ template <class TreeBuilder> ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&);
+ template <class TreeBuilder> TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd);
+ template <class TreeBuilder> NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&);
+
+ template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth);
+ template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0);
+ template <class TreeBuilder> NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&);
+ template <class TreeBuilder> NEVER_INLINE bool parseFunctionInfo(TreeBuilder&, FunctionRequirements, FunctionParseMode, bool nameIsInContainingScope, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn);
+ ALWAYS_INLINE int isBinaryOperator(JSTokenType);
+ bool allowAutomaticSemicolon();
+
+ bool autoSemiColon()
+ {
+ if (m_token.m_type == SEMICOLON) {
+ next();
+ return true;
+ }
+ return allowAutomaticSemicolon();
+ }
+
+ bool canRecurse()
+ {
+ return m_vm->isSafeToRecurse();
+ }
+
+ const JSTextPosition& lastTokenEndPosition() const
+ {
+ return m_lastTokenEndPosition;
+ }
+
+ bool hasError() const
+ {
+ return !m_errorMessage.isNull();
+ }
+
+ struct SavePoint {
+ int startOffset;
+ unsigned oldLineStartOffset;
+ unsigned oldLastLineNumber;
+ unsigned oldLineNumber;
+ };
+
+ ALWAYS_INLINE SavePoint createSavePoint()
+ {
+ ASSERT(!hasError());
+ SavePoint result;
+ result.startOffset = m_token.m_location.startOffset;
+ result.oldLineStartOffset = m_token.m_location.lineStartOffset;
+ result.oldLastLineNumber = m_lexer->lastLineNumber();
+ result.oldLineNumber = m_lexer->lineNumber();
+ return result;
+ }
+
+ ALWAYS_INLINE void restoreSavePoint(const SavePoint& savePoint)
+ {
+ m_errorMessage = String();
+ m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset);
+ next();
+ m_lexer->setLastLineNumber(savePoint.oldLastLineNumber);
+ m_lexer->setLineNumber(savePoint.oldLineNumber);
+ }
+
+ struct ParserState {
+ int assignmentCount;
+ int nonLHSCount;
+ int nonTrivialExpressionCount;
+ };
+
+ ALWAYS_INLINE ParserState saveState()
+ {
+ ParserState result;
+ result.assignmentCount = m_assignmentCount;
+ result.nonLHSCount = m_nonLHSCount;
+ result.nonTrivialExpressionCount = m_nonTrivialExpressionCount;
+ return result;
+ }
+
+ ALWAYS_INLINE void restoreState(const ParserState& state)
+ {
+ m_assignmentCount = state.assignmentCount;
+ m_nonLHSCount = state.nonLHSCount;
+ m_nonTrivialExpressionCount = state.nonTrivialExpressionCount;
+
+ }
+
+
+ VM* m_vm;
+ const SourceCode* m_source;
+ ParserArena* m_arena;
+ OwnPtr<LexerType> m_lexer;
+
+ bool m_hasStackOverflow;
+ String m_errorMessage;
+ JSToken m_token;
+ bool m_allowsIn;
+ JSTextPosition m_lastTokenEndPosition;
+ int m_assignmentCount;
+ int m_nonLHSCount;
+ bool m_syntaxAlreadyValidated;
+ int m_statementDepth;
+ int m_nonTrivialExpressionCount;
+ const Identifier* m_lastIdentifier;
+ const Identifier* m_lastFunctionName;
+ RefPtr<SourceProviderCache> m_functionCache;
+ SourceElements* m_sourceElements;
+ bool m_parsingBuiltin;
+ ParserArenaData<DeclarationStacks::VarStack>* m_varDeclarations;
+ ParserArenaData<DeclarationStacks::FunctionStack>* m_funcDeclarations;
+ IdentifierSet m_capturedVariables;
+ Vector<RefPtr<StringImpl>> m_closedVariables;
+ CodeFeatures m_features;
+ int m_numConstants;
+
+ struct DepthManager {
+ DepthManager(int* depth)
+ : m_originalDepth(*depth)
+ , m_depth(depth)
+ {