X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/4be4e30906bcb8ee30b4d189205cb70bad6707ce..81345200c95645a1b0d2635520f96ad55dfde63f:/parser/Parser.h?ds=sidebyside diff --git a/parser/Parser.h b/parser/Parser.h index ff30f1e..b88f209 100644 --- a/parser/Parser.h +++ b/parser/Parser.h @@ -72,32 +72,22 @@ class SourceCode; #define TreeFunctionBody typename TreeBuilder::FunctionBody #define TreeProperty typename TreeBuilder::Property #define TreePropertyList typename TreeBuilder::PropertyList +#define TreeDeconstructionPattern typename TreeBuilder::DeconstructionPattern COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens); enum SourceElementsMode { CheckForStrictMode, DontCheckForStrictMode }; enum FunctionRequirements { FunctionNoRequirements, FunctionNeedsName }; +enum FunctionParseMode { FunctionMode, GetterMode, SetterMode }; +enum DeconstructionKind { + DeconstructToVariables, + DeconstructToParameters, + DeconstructToExpressions +}; template inline bool isEvalNode() { return false; } template <> inline bool isEvalNode() { return true; } -struct DepthManager { - DepthManager(int* depth) - : m_originalDepth(*depth) - , m_depth(depth) - { - } - - ~DepthManager() - { - *m_depth = m_originalDepth; - } - -private: - int m_originalDepth; - int* m_depth; -}; - struct ScopeLabelInfo { ScopeLabelInfo(StringImpl* ident, bool isLoop) : m_ident(ident) @@ -202,6 +192,16 @@ struct Scope { return isValidStrictMode; } + bool hasDeclaredVariable(const Identifier& ident) + { + return m_declaredVariables.contains(ident.impl()); + } + + bool hasDeclaredParameter(const Identifier& ident) + { + return m_declaredParameters.contains(ident.impl()) || m_declaredVariables.contains(ident.impl()); + } + void declareWrite(const Identifier* ident) { ASSERT(m_strictMode); @@ -216,10 +216,36 @@ struct Scope { bool isArguments = m_vm->propertyNames->arguments == *ident; bool isValidStrictMode = m_declaredVariables.add(ident->string().impl()).isNewEntry && m_vm->propertyNames->eval != *ident && !isArguments; m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; + m_declaredParameters.add(ident->string().impl()); + if (isArguments) m_shadowsArguments = true; return isValidStrictMode; } + + enum BindingResult { + BindingFailed, + StrictBindingFailed, + BindingSucceeded + }; + BindingResult declareBoundParameter(const Identifier* ident) + { + bool isArguments = m_vm->propertyNames->arguments == *ident; + bool newEntry = m_declaredVariables.add(ident->string().impl()).isNewEntry; + bool isValidStrictMode = newEntry && m_vm->propertyNames->eval != *ident && !isArguments; + m_isValidStrictMode = m_isValidStrictMode && isValidStrictMode; + + if (isArguments) + m_shadowsArguments = true; + if (!newEntry) + return BindingFailed; + return isValidStrictMode ? BindingSucceeded : StrictBindingFailed; + } + + void getUsedVariables(IdentifierSet& usedVariables) + { + usedVariables.swap(m_usedVariables); + } void useVariable(const Identifier* ident, bool isEval) { @@ -253,18 +279,10 @@ struct Scope { return true; } - void getUncapturedWrittenVariables(IdentifierSet& writtenVariables) - { - IdentifierSet::iterator end = m_writtenVariables.end(); - for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) { - if (!m_declaredVariables.contains(*ptr)) - writtenVariables.add(*ptr); - } - } - - void getCapturedVariables(IdentifierSet& capturedVariables) + void getCapturedVariables(IdentifierSet& capturedVariables, bool& modifiedParameter) { if (m_needsFullActivation || m_usesEval) { + modifiedParameter = true; capturedVariables.swap(m_declaredVariables); return; } @@ -273,13 +291,23 @@ struct Scope { continue; capturedVariables.add(*ptr); } + modifiedParameter = false; + if (m_declaredParameters.size()) { + IdentifierSet::iterator end = m_writtenVariables.end(); + for (IdentifierSet::iterator ptr = m_writtenVariables.begin(); ptr != end; ++ptr) { + if (!m_declaredParameters.contains(*ptr)) + continue; + modifiedParameter = true; + break; + } + } } void setStrictMode() { m_strictMode = true; } bool strictMode() const { return m_strictMode; } bool isValidStrictMode() const { return m_isValidStrictMode; } bool shadowsArguments() const { return m_shadowsArguments; } - void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector >& vector) + void copyCapturedVariablesToVector(const IdentifierSet& capturedVariables, Vector>& vector) { IdentifierSet::iterator end = capturedVariables.end(); for (IdentifierSet::iterator it = capturedVariables.begin(); it != end; ++it) { @@ -326,6 +354,7 @@ private: typedef Vector LabelStack; OwnPtr m_labels; + IdentifierSet m_declaredParameters; IdentifierSet m_declaredVariables; IdentifierSet m_usedVariables; IdentifierSet m_closedVariables; @@ -369,7 +398,10 @@ public: ~Parser(); template - PassRefPtr parse(ParserError&); + PassRefPtr parse(ParserError&, bool needReparsingAdjustment); + + JSTextPosition positionBeforeLastNewline() const { return m_lexer->positionBeforeLastNewline(); } + Vector>&& closedVariables() { return WTF::move(m_closedVariables); } private: struct AllowInOverride { @@ -457,9 +489,31 @@ private: return m_scopeStack[i].declareVariable(ident); } + NEVER_INLINE bool hasDeclaredVariable(const Identifier& ident) + { + unsigned i = m_scopeStack.size() - 1; + ASSERT(i < m_scopeStack.size()); + while (!m_scopeStack[i].allowsNewDecls()) { + i--; + ASSERT(i < m_scopeStack.size()); + } + return m_scopeStack[i].hasDeclaredVariable(ident); + } + + NEVER_INLINE bool hasDeclaredParameter(const Identifier& ident) + { + unsigned i = m_scopeStack.size() - 1; + ASSERT(i < m_scopeStack.size()); + while (!m_scopeStack[i].allowsNewDecls()) { + i--; + ASSERT(i < m_scopeStack.size()); + } + return m_scopeStack[i].hasDeclaredParameter(ident); + } + void declareWrite(const Identifier* ident) { - if (!m_syntaxAlreadyValidated) + if (!m_syntaxAlreadyValidated || strictMode()) m_scopeStack.last().declareWrite(ident); } @@ -474,8 +528,7 @@ private: String parseInner(); void didFinishParsing(SourceElements*, ParserArenaData*, - ParserArenaData*, CodeFeatures, - int, int, IdentifierSet&); + ParserArenaData*, CodeFeatures, int, IdentifierSet&, const Vector>&&); // Used to determine type of error to report. bool isFunctionBodyNode(ScopeNode*) { return false; } @@ -483,20 +536,22 @@ private: ALWAYS_INLINE void next(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_location.line; - m_lastTokenEnd = m_token.m_location.endOffset; - m_lastTokenLineStart = m_token.m_location.lineStartOffset; - m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lex(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); + int lastLine = m_token.m_location.line; + int lastTokenEnd = m_token.m_location.endOffset; + int lastTokenLineStart = m_token.m_location.lineStartOffset; + m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); + m_lexer->setLastLineNumber(lastLine); + m_token.m_type = m_lexer->lex(&m_token, lexerFlags, strictMode()); } ALWAYS_INLINE void nextExpectIdentifier(unsigned lexerFlags = 0) { - m_lastLine = m_token.m_location.line; - m_lastTokenEnd = m_token.m_location.endOffset; - m_lastTokenLineStart = m_token.m_location.lineStartOffset; - m_lexer->setLastLineNumber(m_lastLine); - m_token.m_type = m_lexer->lexExpectIdentifier(&m_token.m_data, &m_token.m_location, lexerFlags, strictMode()); + int lastLine = m_token.m_location.line; + int lastTokenEnd = m_token.m_location.endOffset; + int lastTokenLineStart = m_token.m_location.lineStartOffset; + m_lastTokenEndPosition = JSTextPosition(lastLine, lastTokenEnd, lastTokenLineStart); + m_lexer->setLastLineNumber(lastLine); + m_token.m_type = m_lexer->lexExpectIdentifier(&m_token, lexerFlags, strictMode()); } ALWAYS_INLINE bool nextTokenIsColon() @@ -511,10 +566,11 @@ private: next(flags); return result; } - + + void printUnexpectedTokenText(WTF::PrintStream&); ALWAYS_INLINE String getToken() { SourceProvider* sourceProvider = m_source->provider(); - return sourceProvider->getRange(tokenStart(), tokenEnd()); + return sourceProvider->getRange(tokenStart(), tokenEndPosition().offset); } ALWAYS_INLINE bool match(JSTokenType expected) @@ -522,11 +578,21 @@ private: 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; @@ -537,9 +603,9 @@ private: return tokenStart() - tokenLineStart(); } - ALWAYS_INLINE unsigned tokenEnd() + ALWAYS_INLINE const JSTextPosition& tokenEndPosition() { - return m_token.m_location.endOffset; + return m_token.m_endPosition; } ALWAYS_INLINE unsigned tokenLineStart() @@ -552,277 +618,19 @@ private: return m_token.m_location; } - const char* getTokenName(JSTokenType tok) - { - switch (tok) { - case NULLTOKEN: - return "null"; - case TRUETOKEN: - return "true"; - case FALSETOKEN: - return "false"; - case BREAK: - return "break"; - case CASE: - return "case"; - case DEFAULT: - return "default"; - case FOR: - return "for"; - case NEW: - return "new"; - case VAR: - return "var"; - case CONSTTOKEN: - return "const"; - case CONTINUE: - return "continue"; - case FUNCTION: - return "function"; - case IF: - return "if"; - case THISTOKEN: - return "this"; - case DO: - return "do"; - case WHILE: - return "while"; - case SWITCH: - return "switch"; - case WITH: - return "with"; - case THROW: - return "throw"; - case TRY: - return "try"; - case CATCH: - return "catch"; - case FINALLY: - return "finally"; - case DEBUGGER: - return "debugger"; - case ELSE: - return "else"; - case OPENBRACE: - return "{"; - case CLOSEBRACE: - return "}"; - case OPENPAREN: - return "("; - case CLOSEPAREN: - return ")"; - case OPENBRACKET: - return "["; - case CLOSEBRACKET: - return "]"; - case COMMA: - return ","; - case QUESTION: - return "?"; - case SEMICOLON: - return ";"; - case COLON: - return ":"; - case DOT: - return "."; - case EQUAL: - return "="; - case PLUSEQUAL: - return "+="; - case MINUSEQUAL: - return "-="; - case MULTEQUAL: - return "*="; - case DIVEQUAL: - return "/="; - case LSHIFTEQUAL: - return "<<="; - case RSHIFTEQUAL: - return ">>="; - case URSHIFTEQUAL: - return ">>>="; - case ANDEQUAL: - return "&="; - case MODEQUAL: - return "%="; - case XOREQUAL: - return "^="; - case OREQUAL: - return "|="; - case AUTOPLUSPLUS: - case PLUSPLUS: - return "++"; - case AUTOMINUSMINUS: - case MINUSMINUS: - return "--"; - case EXCLAMATION: - return "!"; - case TILDE: - return "~"; - case TYPEOF: - return "typeof"; - case VOIDTOKEN: - return "void"; - case DELETETOKEN: - return "delete"; - case OR: - return "||"; - case AND: - return "&&"; - case BITOR: - return "|"; - case BITXOR: - return "^"; - case BITAND: - return "&"; - case EQEQ: - return "=="; - case NE: - return "!="; - case STREQ: - return "==="; - case STRNEQ: - return "!=="; - case LT: - return "<"; - case GT: - return ">"; - case LE: - return "<="; - case GE: - return ">="; - case INSTANCEOF: - return "instanceof"; - case INTOKEN: - return "in"; - case LSHIFT: - return "<<"; - case RSHIFT: - return ">>"; - case URSHIFT: - return ">>>"; - case PLUS: - return "+"; - case MINUS: - return "-"; - case TIMES: - return "*"; - case DIVIDE: - return "/"; - case MOD: - return "%"; - case RETURN: - case RESERVED_IF_STRICT: - case RESERVED: - case NUMBER: - case IDENT: - case STRING: - case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK: - case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: - case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK: - case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK: - case UNTERMINATED_STRING_LITERAL_ERRORTOK: - case INVALID_IDENTIFIER_ESCAPE_ERRORTOK: - case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: - case INVALID_NUMERIC_LITERAL_ERRORTOK: - case INVALID_OCTAL_NUMBER_ERRORTOK: - case INVALID_STRING_LITERAL_ERRORTOK: - case ERRORTOK: - case EOFTOK: - return 0; - case LastUntaggedToken: - break; - } - RELEASE_ASSERT_NOT_REACHED(); - return "internal error"; - } - - ALWAYS_INLINE void updateErrorMessageSpecialCase(JSTokenType expectedToken) - { - switch (expectedToken) { - case RESERVED_IF_STRICT: - m_errorMessage = "Use of reserved word '" + getToken() + "' in strict mode"; - return; - case RESERVED: - m_errorMessage = "Use of reserved word '" + getToken() + '\''; - return; - case NUMBER: - m_errorMessage = "Unexpected number '" + getToken() + '\''; - return; - case IDENT: - m_errorMessage = "Expected an identifier but found '" + getToken() + "' instead"; - return; - case STRING: - m_errorMessage = "Unexpected string " + getToken(); - return; - - case UNTERMINATED_IDENTIFIER_ESCAPE_ERRORTOK: - case UNTERMINATED_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: - m_errorMessage = "Incomplete unicode escape in identifier: '" + getToken() + '\''; - return; - case UNTERMINATED_MULTILINE_COMMENT_ERRORTOK: - m_errorMessage = "Unterminated multiline comment"; - return; - case UNTERMINATED_NUMERIC_LITERAL_ERRORTOK: - m_errorMessage = "Unterminated numeric literal '" + getToken() + '\''; - return; - case UNTERMINATED_STRING_LITERAL_ERRORTOK: - m_errorMessage = "Unterminated string literal '" + getToken() + '\''; - return; - case INVALID_IDENTIFIER_ESCAPE_ERRORTOK: - m_errorMessage = "Invalid escape in identifier: '" + getToken() + '\''; - return; - case INVALID_IDENTIFIER_UNICODE_ESCAPE_ERRORTOK: - m_errorMessage = "Invalid unicode escape in identifier: '" + getToken() + '\''; - return; - case INVALID_NUMERIC_LITERAL_ERRORTOK: - m_errorMessage = "Invalid numeric literal: '" + getToken() + '\''; - return; - case INVALID_OCTAL_NUMBER_ERRORTOK: - m_errorMessage = "Invalid use of octal: '" + getToken() + '\''; - return; - case INVALID_STRING_LITERAL_ERRORTOK: - m_errorMessage = "Invalid string literal: '" + getToken() + '\''; - return; - case ERRORTOK: - m_errorMessage = "Unrecognized token '" + getToken() + '\''; - return; - case EOFTOK: - m_errorMessage = ASCIILiteral("Unexpected EOF"); - return; - case RETURN: - m_errorMessage = ASCIILiteral("Return statements are only valid inside functions"); - return; - default: - RELEASE_ASSERT_NOT_REACHED(); - m_errorMessage = ASCIILiteral("internal error"); - return; - } - } - - NEVER_INLINE void updateErrorMessage() + void setErrorMessage(String msg) { - const char* name = getTokenName(m_token.m_type); - if (!name) - updateErrorMessageSpecialCase(m_token.m_type); - else - m_errorMessage = String::format("Unexpected token '%s'", name); - ASSERT(!m_errorMessage.isNull()); + m_errorMessage = msg; } - NEVER_INLINE void updateErrorMessage(JSTokenType expectedToken) - { - const char* name = getTokenName(expectedToken); - if (name) - m_errorMessage = String::format("Expected token '%s'", name); - else { - if (!getTokenName(m_token.m_type)) - updateErrorMessageSpecialCase(m_token.m_type); - else - updateErrorMessageSpecialCase(expectedToken); - } - ASSERT(!m_errorMessage.isNull()); - } + NEVER_INLINE void logError(bool); + template NEVER_INLINE void logError(bool, const A&); + template NEVER_INLINE void logError(bool, const A&, const B&); + template NEVER_INLINE void logError(bool, const A&, const B&, const C&); + template NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&); + template NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&); + template NEVER_INLINE void logError(bool, const A&, const B&, const C&, const D&, const E&, const F&); + template 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) { @@ -844,6 +652,7 @@ private: 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(); @@ -878,7 +687,7 @@ private: return result; } - template TreeSourceElements parseSourceElements(TreeBuilder&); + template TreeSourceElements parseSourceElements(TreeBuilder&, SourceElementsMode); template TreeStatement parseStatement(TreeBuilder&, const Identifier*& directive, unsigned* directiveLiteralLength = 0); template TreeStatement parseFunctionDeclaration(TreeBuilder&); template TreeStatement parseVarDeclaration(TreeBuilder&); @@ -899,7 +708,7 @@ private: template TreeStatement parseExpressionStatement(TreeBuilder&); template TreeStatement parseExpressionOrLabelStatement(TreeBuilder&); template TreeStatement parseIfStatement(TreeBuilder&); - template ALWAYS_INLINE TreeStatement parseBlockStatement(TreeBuilder&); + template TreeStatement parseBlockStatement(TreeBuilder&); template TreeExpression parseExpression(TreeBuilder&); template TreeExpression parseAssignmentExpression(TreeBuilder&); template ALWAYS_INLINE TreeExpression parseConditionalExpression(TreeBuilder&); @@ -909,14 +718,19 @@ private: template ALWAYS_INLINE TreeExpression parsePrimaryExpression(TreeBuilder&); template ALWAYS_INLINE TreeExpression parseArrayLiteral(TreeBuilder&); template ALWAYS_INLINE TreeExpression parseObjectLiteral(TreeBuilder&); - template ALWAYS_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&); - template ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&); - template ALWAYS_INLINE TreeProperty parseProperty(TreeBuilder&); + template NEVER_INLINE TreeExpression parseStrictObjectLiteral(TreeBuilder&); + enum SpreadMode { AllowSpread, DontAllowSpread }; + template ALWAYS_INLINE TreeArguments parseArguments(TreeBuilder&, SpreadMode); + template TreeProperty parseProperty(TreeBuilder&, bool strict); template ALWAYS_INLINE TreeFunctionBody parseFunctionBody(TreeBuilder&); template ALWAYS_INLINE TreeFormalParameterList parseFormalParameters(TreeBuilder&); - template ALWAYS_INLINE TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, const Identifier*& lastIdent, TreeExpression& lastInitializer, int& identStart, int& initStart, int& initEnd); - template ALWAYS_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder& context); - template bool parseFunctionInfo(TreeBuilder&, const Identifier*&, TreeFormalParameterList&, TreeFunctionBody&, unsigned& openBraceOffset, unsigned& closeBraceOffset, int& bodyStartLine, unsigned& bodyStartColumn); + template TreeExpression parseVarDeclarationList(TreeBuilder&, int& declarations, TreeDeconstructionPattern& lastPattern, TreeExpression& lastInitializer, JSTextPosition& identStart, JSTextPosition& initStart, JSTextPosition& initEnd); + template NEVER_INLINE TreeConstDeclList parseConstDeclarationList(TreeBuilder&); + + template NEVER_INLINE TreeDeconstructionPattern createBindingPattern(TreeBuilder&, DeconstructionKind, const Identifier&, int depth); + template NEVER_INLINE TreeDeconstructionPattern parseDeconstructionPattern(TreeBuilder&, DeconstructionKind, int depth = 0); + template NEVER_INLINE TreeDeconstructionPattern tryParseDeconstructionPatternExpression(TreeBuilder&); + template 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(); @@ -931,54 +745,94 @@ private: bool canRecurse() { - return m_stack.isSafeToRecurse(); + return m_vm->isSafeToRecurse(); } - int lastTokenEnd() const + const JSTextPosition& lastTokenEndPosition() const { - return m_lastTokenEnd; + return m_lastTokenEndPosition; } - unsigned lastTokenLine() const + bool hasError() const { - return m_lastLine; + return !m_errorMessage.isNull(); } - unsigned lastTokenLineStart() const + 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) { - return m_lastTokenLineStart; + m_errorMessage = String(); + m_lexer->setOffset(savePoint.startOffset, savePoint.oldLineStartOffset); + next(); + m_lexer->setLastLineNumber(savePoint.oldLastLineNumber); + m_lexer->setLineNumber(savePoint.oldLineNumber); } - bool hasError() const + struct ParserState { + int assignmentCount; + int nonLHSCount; + int nonTrivialExpressionCount; + }; + + ALWAYS_INLINE ParserState saveState() { - return !m_errorMessage.isNull(); + 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 m_lexer; - StackBounds m_stack; bool m_hasStackOverflow; String m_errorMessage; JSToken m_token; bool m_allowsIn; - unsigned m_lastLine; - int m_lastTokenEnd; - unsigned m_lastTokenLine; - unsigned m_lastTokenLineStart; + 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 m_functionCache; SourceElements* m_sourceElements; + bool m_parsingBuiltin; ParserArenaData* m_varDeclarations; ParserArenaData* m_funcDeclarations; IdentifierSet m_capturedVariables; + Vector> m_closedVariables; CodeFeatures m_features; int m_numConstants; @@ -1003,12 +857,12 @@ private: template template -PassRefPtr Parser::parse(ParserError& error) +PassRefPtr Parser::parse(ParserError& error, bool needReparsingAdjustment) { int errLine; String errMsg; - if (ParsedNode::scopeIsFunction) + if (ParsedNode::scopeIsFunction && needReparsingAdjustment) m_lexer->setIsReparsing(); m_sourceElements = 0; @@ -1017,7 +871,8 @@ PassRefPtr Parser::parse(ParserError& error) errMsg = String(); JSTokenLocation startLocation(tokenLocation()); - unsigned startColumn = m_source->startColumn(); + ASSERT(m_source->startColumn() > 0); + unsigned startColumn = m_source->startColumn() - 1; String parseError = parseInner(); @@ -1036,13 +891,15 @@ PassRefPtr Parser::parse(ParserError& error) RefPtr result; if (m_sourceElements) { JSTokenLocation endLocation; - endLocation.line = m_lexer->lastLineNumber(); + endLocation.line = m_lexer->lineNumber(); endLocation.lineStartOffset = m_lexer->currentLineStartOffset(); endLocation.startOffset = m_lexer->currentOffset(); + unsigned endColumn = endLocation.startOffset - endLocation.lineStartOffset; result = ParsedNode::create(m_vm, startLocation, endLocation, startColumn, + endColumn, m_sourceElements, m_varDeclarations ? &m_varDeclarations->data : 0, m_funcDeclarations ? &m_funcDeclarations->data : 0, @@ -1050,7 +907,7 @@ PassRefPtr Parser::parse(ParserError& error) *m_source, m_features, m_numConstants); - result->setLoc(m_source->firstLine(), m_lastLine, m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); + result->setLoc(m_source->firstLine(), m_lexer->lineNumber(), m_lexer->currentOffset(), m_lexer->currentLineStartOffset()); } else { // We can never see a syntax error when reparsing a function, since we should have // reported the error when parsing the containing program or eval code. So if we're @@ -1080,17 +937,29 @@ PassRefPtr Parser::parse(ParserError& error) } template -PassRefPtr parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error) +PassRefPtr parse(VM* vm, const SourceCode& source, FunctionParameters* parameters, const Identifier& name, JSParserStrictness strictness, JSParserMode parserMode, ParserError& error, JSTextPosition* positionBeforeLastNewline = 0, bool needReparsingAdjustment = false) { SamplingRegion samplingRegion("Parsing"); ASSERT(!source.provider()->source().isNull()); if (source.provider()->source().is8Bit()) { - Parser< Lexer > parser(vm, source, parameters, name, strictness, parserMode); - return parser.parse(error); + Parser> parser(vm, source, parameters, name, strictness, parserMode); + RefPtr result = parser.parse(error, needReparsingAdjustment); + if (positionBeforeLastNewline) + *positionBeforeLastNewline = parser.positionBeforeLastNewline(); + if (strictness == JSParseBuiltin) { + if (!result) + WTF::dataLog("Error compiling builtin: ", error.m_message, "\n"); + RELEASE_ASSERT(result); + result->setClosedVariables(parser.closedVariables()); + } + return result.release(); } - Parser< Lexer > parser(vm, source, parameters, name, strictness, parserMode); - return parser.parse(error); + Parser> parser(vm, source, parameters, name, strictness, parserMode); + RefPtr result = parser.parse(error, needReparsingAdjustment); + if (positionBeforeLastNewline) + *positionBeforeLastNewline = parser.positionBeforeLastNewline(); + return result.release(); } } // namespace