summaryrefslogtreecommitdiff
path: root/deps/v8/src/preparser.h
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/preparser.h')
-rw-r--r--deps/v8/src/preparser.h262
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