diff options
Diffstat (limited to 'deps/v8/src/preparser.h')
-rw-r--r-- | deps/v8/src/preparser.h | 262 |
1 files changed, 141 insertions, 121 deletions
diff --git a/deps/v8/src/preparser.h b/deps/v8/src/preparser.h index 080b772873..6733658579 100644 --- a/deps/v8/src/preparser.h +++ b/deps/v8/src/preparser.h @@ -1,29 +1,6 @@ // Copyright 2012 the V8 project authors. All rights reserved. -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following -// disclaimer in the documentation and/or other materials provided -// with the distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. #ifndef V8_PREPARSER_H #define V8_PREPARSER_H @@ -228,8 +205,8 @@ class ParserBase : public Traits { FunctionState* outer_function_state_; typename Traits::Type::Scope** scope_stack_; typename Traits::Type::Scope* outer_scope_; - Isolate* isolate_; // Only used by ParserTraits. int saved_ast_node_id_; // Only used by ParserTraits. + typename Traits::Type::Zone* extra_param_; typename Traits::Type::Factory factory_; friend class ParserTraits; @@ -425,6 +402,13 @@ class ParserBase : public Traits { ExpressionT ParseMemberExpressionContinuation(ExpressionT expression, bool* ok); + // Checks if the expression is a valid reference expression (e.g., on the + // left-hand side of assignments). Although ruled out by ECMA as early errors, + // we allow calls for web compatibility and rewrite them to a runtime throw. + ExpressionT CheckAndRewriteReferenceExpression( + ExpressionT expression, + Scanner::Location location, const char* message, bool* ok); + // Used to detect duplicates in object literals. Each of the values // kGetterProperty, kSetterProperty and kValueProperty represents // a type of object literal property. When parsing a property, its @@ -589,10 +573,14 @@ class PreParserExpression { return PreParserExpression(kPropertyExpression); } + static PreParserExpression Call() { + return PreParserExpression(kCallExpression); + } + bool IsIdentifier() { return (code_ & kIdentifierFlag) != 0; } - // Only works corretly if it is actually an identifier expression. PreParserIdentifier AsIdentifier() { + ASSERT(IsIdentifier()); return PreParserIdentifier( static_cast<PreParserIdentifier::Type>(code_ >> kIdentifierShift)); } @@ -611,13 +599,14 @@ class PreParserExpression { return code_ == kPropertyExpression || code_ == kThisPropertyExpression; } - bool IsValidLeftHandSide() { + bool IsCall() { return code_ == kCallExpression; } + + bool IsValidReferenceExpression() { return IsIdentifier() || IsProperty(); } // At the moment PreParser doesn't track these expression types. bool IsFunctionLiteral() const { return false; } - bool IsCall() const { return false; } bool IsCallNew() const { return false; } PreParserExpression AsFunctionLiteral() { return *this; } @@ -651,7 +640,8 @@ class PreParserExpression { // 2 least significant bits for flags. kThisExpression = 1 << 2, kThisPropertyExpression = 2 << 2, - kPropertyExpression = 3 << 2 + kPropertyExpression = 3 << 2, + kCallExpression = 4 << 2 }; explicit PreParserExpression(int expression_code) : code_(expression_code) {} @@ -674,6 +664,67 @@ class PreParserExpressionList { }; +class PreParserStatement { + public: + static PreParserStatement Default() { + return PreParserStatement(kUnknownStatement); + } + + static PreParserStatement FunctionDeclaration() { + return PreParserStatement(kFunctionDeclaration); + } + + // Creates expression statement from expression. + // Preserves being an unparenthesized string literal, possibly + // "use strict". + static PreParserStatement ExpressionStatement( + PreParserExpression expression) { + if (expression.IsUseStrictLiteral()) { + return PreParserStatement(kUseStrictExpressionStatement); + } + if (expression.IsStringLiteral()) { + return PreParserStatement(kStringLiteralExpressionStatement); + } + return Default(); + } + + bool IsStringLiteral() { + return code_ == kStringLiteralExpressionStatement; + } + + bool IsUseStrictLiteral() { + return code_ == kUseStrictExpressionStatement; + } + + bool IsFunctionDeclaration() { + return code_ == kFunctionDeclaration; + } + + private: + enum Type { + kUnknownStatement, + kStringLiteralExpressionStatement, + kUseStrictExpressionStatement, + kFunctionDeclaration + }; + + explicit PreParserStatement(Type code) : code_(code) {} + Type code_; +}; + + + +// PreParserStatementList doesn't actually store the statements because +// the PreParser does not need them. +class PreParserStatementList { + public: + // These functions make list->Add(some_expression) work as no-ops. + PreParserStatementList() {} + PreParserStatementList* operator->() { return this; } + void Add(PreParserStatement, void*) {} +}; + + class PreParserScope { public: explicit PreParserScope(PreParserScope* outer_scope, ScopeType scope_type) @@ -782,7 +833,7 @@ class PreParserFactory { PreParserExpression NewCall(PreParserExpression expression, PreParserExpressionList arguments, int pos) { - return PreParserExpression::Default(); + return PreParserExpression::Call(); } PreParserExpression NewCallNew(PreParserExpression expression, PreParserExpressionList arguments, @@ -817,6 +868,7 @@ class PreParserTraits { typedef PreParserExpression Literal; typedef PreParserExpressionList ExpressionList; typedef PreParserExpressionList PropertyList; + typedef PreParserStatementList StatementList; // For constructing objects returned by the traversing functions. typedef PreParserFactory Factory; @@ -829,7 +881,7 @@ class PreParserTraits { template<typename FunctionState> static void SetUpFunctionState(FunctionState* function_state, void*) {} template<typename FunctionState> - static void TearDownFunctionState(FunctionState* function_state) {} + static void TearDownFunctionState(FunctionState* function_state, void*) {} // Helper functions for recursive descent. static bool IsEvalOrArguments(PreParserIdentifier identifier) { @@ -845,6 +897,10 @@ class PreParserTraits { return expression.IsIdentifier(); } + static PreParserIdentifier AsIdentifier(PreParserExpression expression) { + return expression.AsIdentifier(); + } + static bool IsBoilerplateProperty(PreParserExpression property) { // PreParser doesn't count boilerplate properties. return false; @@ -883,10 +939,6 @@ class PreParserTraits { return expression; } - // Checks LHS expression for assignment and prefix/postfix increment/decrement - // in strict mode. - void CheckStrictModeLValue(PreParserExpression expression, bool* ok); - bool ShortcutNumericLiteralBinaryExpression(PreParserExpression* x, PreParserExpression y, Token::Value op, @@ -901,6 +953,18 @@ class PreParserTraits { return PreParserExpression::Default(); } + PreParserExpression NewThrowReferenceError(const char* type, int pos) { + return PreParserExpression::Default(); + } + PreParserExpression NewThrowSyntaxError( + const char* type, Handle<Object> arg, int pos) { + return PreParserExpression::Default(); + } + PreParserExpression NewThrowTypeError( + const char* type, Handle<Object> arg, int pos) { + return PreParserExpression::Default(); + } + // Reporting errors. void ReportMessageAt(Scanner::Location location, const char* message, @@ -968,6 +1032,10 @@ class PreParserTraits { return PreParserExpressionList(); } + static PreParserStatementList NewStatementList(int size, void* zone) { + return PreParserStatementList(); + } + static PreParserExpressionList NewPropertyList(int size, void* zone) { return PreParserExpressionList(); } @@ -1004,6 +1072,7 @@ class PreParser : public ParserBase<PreParserTraits> { public: typedef PreParserIdentifier Identifier; typedef PreParserExpression Expression; + typedef PreParserStatement Statement; enum PreParseResult { kPreParseStackOverflow, @@ -1065,52 +1134,6 @@ class PreParser : public ParserBase<PreParserTraits> { kHasNoInitializers }; - class Statement { - public: - static Statement Default() { - return Statement(kUnknownStatement); - } - - static Statement FunctionDeclaration() { - return Statement(kFunctionDeclaration); - } - - // Creates expression statement from expression. - // Preserves being an unparenthesized string literal, possibly - // "use strict". - static Statement ExpressionStatement(Expression expression) { - if (expression.IsUseStrictLiteral()) { - return Statement(kUseStrictExpressionStatement); - } - if (expression.IsStringLiteral()) { - return Statement(kStringLiteralExpressionStatement); - } - return Default(); - } - - bool IsStringLiteral() { - return code_ == kStringLiteralExpressionStatement; - } - - bool IsUseStrictLiteral() { - return code_ == kUseStrictExpressionStatement; - } - - bool IsFunctionDeclaration() { - return code_ == kFunctionDeclaration; - } - - private: - enum Type { - kUnknownStatement, - kStringLiteralExpressionStatement, - kUseStrictExpressionStatement, - kFunctionDeclaration - }; - - explicit Statement(Type code) : code_(code) {} - Type code_; - }; enum SourceElements { kUnknownSourceElements @@ -1158,11 +1181,6 @@ class PreParser : public ParserBase<PreParserTraits> { bool* ok); void ParseLazyFunctionLiteralBody(bool* ok); - // Logs the currently parsed literal as a symbol in the preparser data. - void LogSymbol(); - // Log the currently parsed string literal. - Expression GetStringSymbol(); - bool CheckInOrOf(bool accept_OF); }; @@ -1181,8 +1199,8 @@ ParserBase<Traits>::FunctionState::FunctionState( outer_function_state_(*function_state_stack), scope_stack_(scope_stack), outer_scope_(*scope_stack), - isolate_(NULL), saved_ast_node_id_(0), + extra_param_(extra_param), factory_(extra_param) { *scope_stack_ = scope; *function_state_stack = this; @@ -1194,7 +1212,7 @@ template<class Traits> ParserBase<Traits>::FunctionState::~FunctionState() { *scope_stack_ = outer_scope_; *function_state_stack_ = outer_function_state_; - Traits::TearDownFunctionState(this); + Traits::TearDownFunctionState(this, extra_param_); } @@ -1695,16 +1713,8 @@ ParserBase<Traits>::ParseAssignmentExpression(bool accept_IN, bool* ok) { return expression; } - if (!expression->IsValidLeftHandSide()) { - this->ReportMessageAt(lhs_location, "invalid_lhs_in_assignment", true); - *ok = false; - return this->EmptyExpression(); - } - - if (strict_mode() == STRICT) { - // Assignment to eval or arguments is disallowed in strict mode. - this->CheckStrictModeLValue(expression, CHECK_OK); - } + expression = this->CheckAndRewriteReferenceExpression( + expression, lhs_location, "invalid_lhs_in_assignment", CHECK_OK); expression = this->MarkExpressionAsLValue(expression); Token::Value op = Next(); // Get assignment operator. @@ -1864,17 +1874,9 @@ ParserBase<Traits>::ParseUnaryExpression(bool* ok) { } else if (Token::IsCountOp(op)) { op = Next(); Scanner::Location lhs_location = scanner()->peek_location(); - ExpressionT expression = ParseUnaryExpression(CHECK_OK); - if (!expression->IsValidLeftHandSide()) { - ReportMessageAt(lhs_location, "invalid_lhs_in_prefix_op", true); - *ok = false; - return this->EmptyExpression(); - } - - if (strict_mode() == STRICT) { - // Prefix expression operand in strict mode may not be eval or arguments. - this->CheckStrictModeLValue(expression, CHECK_OK); - } + ExpressionT expression = this->ParseUnaryExpression(CHECK_OK); + expression = this->CheckAndRewriteReferenceExpression( + expression, lhs_location, "invalid_lhs_in_prefix_op", CHECK_OK); this->MarkExpressionAsLValue(expression); return factory()->NewCountOperation(op, @@ -1898,16 +1900,8 @@ ParserBase<Traits>::ParsePostfixExpression(bool* ok) { ExpressionT expression = this->ParseLeftHandSideExpression(CHECK_OK); if (!scanner()->HasAnyLineTerminatorBeforeNext() && Token::IsCountOp(peek())) { - if (!expression->IsValidLeftHandSide()) { - ReportMessageAt(lhs_location, "invalid_lhs_in_postfix_op", true); - *ok = false; - return this->EmptyExpression(); - } - - if (strict_mode() == STRICT) { - // Postfix expression operand in strict mode may not be eval or arguments. - this->CheckStrictModeLValue(expression, CHECK_OK); - } + expression = this->CheckAndRewriteReferenceExpression( + expression, lhs_location, "invalid_lhs_in_postfix_op", CHECK_OK); expression = this->MarkExpressionAsLValue(expression); Token::Value next = Next(); @@ -2051,7 +2045,7 @@ ParserBase<Traits>::ParseMemberExpression(bool* ok) { Consume(Token::FUNCTION); int function_token_position = position(); bool is_generator = allow_generators() && Check(Token::MUL); - IdentifierT name; + IdentifierT name = this->EmptyIdentifier(); bool is_strict_reserved_name = false; Scanner::Location function_name_location = Scanner::Location::invalid(); FunctionLiteral::FunctionType function_type = @@ -2117,6 +2111,32 @@ ParserBase<Traits>::ParseMemberExpressionContinuation(ExpressionT expression, } +template <typename Traits> +typename ParserBase<Traits>::ExpressionT +ParserBase<Traits>::CheckAndRewriteReferenceExpression( + ExpressionT expression, + Scanner::Location location, const char* message, bool* ok) { + if (strict_mode() == STRICT && this->IsIdentifier(expression) && + this->IsEvalOrArguments(this->AsIdentifier(expression))) { + this->ReportMessageAt(location, "strict_eval_arguments", false); + *ok = false; + return this->EmptyExpression(); + } else if (expression->IsValidReferenceExpression()) { + return expression; + } else if (expression->IsCall()) { + // If it is a call, make it a runtime error for legacy web compatibility. + // Rewrite `expr' to `expr[throw ReferenceError]'. + int pos = location.beg_pos; + ExpressionT error = this->NewThrowReferenceError(message, pos); + return factory()->NewProperty(expression, error, pos); + } else { + this->ReportMessageAt(location, message, true); + *ok = false; + return this->EmptyExpression(); + } +} + + #undef CHECK_OK #undef CHECK_OK_CUSTOM |