Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Unified Diff: src/parser.cc

Issue 196133017: Experimental parser: merge r19949 (Closed) Base URL: https://v8.googlecode.com/svn/branches/experimental/parser
Patch Set: Created 6 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/parser.h ('k') | src/platform.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/parser.cc
diff --git a/src/parser.cc b/src/parser.cc
index 68823e6c1f708a84cbba432187eac0972c397b43..3627bafb96eee79d5f785654004ec5b73a229379 100644
--- a/src/parser.cc
+++ b/src/parser.cc
@@ -33,7 +33,6 @@
#include "char-predicates-inl.h"
#include "codegen.h"
#include "compiler.h"
-#include "func-name-inferrer.h"
#include "messages.h"
#include "parser.h"
#include "platform.h"
@@ -213,13 +212,7 @@ Handle<String> Parser::LookupSymbol(int symbol_id) {
// count.
if (symbol_id < 0 ||
(pre_parse_data_ && symbol_id >= pre_parse_data_->symbol_count())) {
- if (scanner()->is_literal_ascii()) {
- return isolate()->factory()->InternalizeOneByteString(
- Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
- } else {
- return isolate()->factory()->InternalizeTwoByteString(
- scanner()->literal_utf16_string());
- }
+ return scanner()->AllocateInternalizedString(isolate_);
}
return LookupCachedSymbol(symbol_id);
}
@@ -234,13 +227,7 @@ Handle<String> Parser::LookupCachedSymbol(int symbol_id) {
}
Handle<String> result = symbol_cache_.at(symbol_id);
if (result.is_null()) {
- if (scanner()->is_literal_ascii()) {
- result = isolate()->factory()->InternalizeOneByteString(
- Vector<const uint8_t>::cast(scanner()->literal_ascii_string()));
- } else {
- result = isolate()->factory()->InternalizeTwoByteString(
- scanner()->literal_utf16_string());
- }
+ result = scanner()->AllocateInternalizedString(isolate_);
symbol_cache_.at(symbol_id) = result;
return result;
}
@@ -450,9 +437,68 @@ bool ParserTraits::IsEvalOrArguments(Handle<String> identifier) const {
}
+bool ParserTraits::IsThisProperty(Expression* expression) {
+ ASSERT(expression != NULL);
+ Property* property = expression->AsProperty();
+ return property != NULL &&
+ property->obj()->AsVariableProxy() != NULL &&
+ property->obj()->AsVariableProxy()->is_this();
+}
+
+
+void ParserTraits::CheckAssigningFunctionLiteralToProperty(Expression* left,
+ Expression* right) {
+ ASSERT(left != NULL);
+ if (left->AsProperty() != NULL &&
+ right->AsFunctionLiteral() != NULL) {
+ right->AsFunctionLiteral()->set_pretenure();
+ }
+}
+
+
+Expression* ParserTraits::ValidateAssignmentLeftHandSide(
+ Expression* expression) const {
+ ASSERT(expression != NULL);
+ if (!expression->IsValidLeftHandSide()) {
+ Handle<String> message =
+ parser_->isolate()->factory()->invalid_lhs_in_assignment_string();
+ expression = parser_->NewThrowReferenceError(message);
+ }
+ return expression;
+}
+
+
+Expression* ParserTraits::MarkExpressionAsLValue(Expression* expression) {
+ VariableProxy* proxy = expression != NULL
+ ? expression->AsVariableProxy()
+ : NULL;
+ if (proxy != NULL) proxy->MarkAsLValue();
+ return expression;
+}
+
+
+void ParserTraits::CheckStrictModeLValue(Expression* expression,
+ bool* ok) {
+ VariableProxy* lhs = expression != NULL
+ ? expression->AsVariableProxy()
+ : NULL;
+ if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
+ parser_->ReportMessage("strict_eval_arguments",
+ Vector<const char*>::empty());
+ *ok = false;
+ }
+}
+
+
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<const char*> args) {
+ if (parser_->stack_overflow()) {
+ // Suppress the error message (syntax error or such) in the presence of a
+ // stack overflow. The isolate allows only one pending exception at at time
+ // and we want to report the stack overflow later.
+ return;
+ }
MessageLocation location(parser_->script_,
source_location.beg_pos,
source_location.end_pos);
@@ -478,6 +524,12 @@ void ParserTraits::ReportMessage(const char* message,
void ParserTraits::ReportMessageAt(Scanner::Location source_location,
const char* message,
Vector<Handle<String> > args) {
+ if (parser_->stack_overflow()) {
+ // Suppress the error message (syntax error or such) in the presence of a
+ // stack overflow. The isolate allows only one pending exception at at time
+ // and we want to report the stack overflow later.
+ return;
+ }
MessageLocation location(parser_->script_,
source_location.beg_pos,
source_location.end_pos);
@@ -503,13 +555,7 @@ Handle<String> ParserTraits::GetSymbol(Scanner* scanner) {
Handle<String> ParserTraits::NextLiteralString(Scanner* scanner,
PretenureFlag tenured) {
- if (scanner->is_next_literal_ascii()) {
- return parser_->isolate_->factory()->NewStringFromAscii(
- scanner->next_literal_ascii_string(), tenured);
- } else {
- return parser_->isolate_->factory()->NewStringFromTwoByte(
- scanner->next_literal_utf16_string(), tenured);
- }
+ return scanner->AllocateNextLiteralString(parser_->isolate(), tenured);
}
@@ -520,7 +566,7 @@ Expression* ParserTraits::ThisExpression(
}
-Expression* ParserTraits::ExpressionFromLiteral(
+Literal* ParserTraits::ExpressionFromLiteral(
Token::Value token, int pos,
Scanner* scanner,
AstNodeFactory<AstConstructionVisitor>* factory) {
@@ -533,11 +579,7 @@ Expression* ParserTraits::ExpressionFromLiteral(
case Token::FALSE_LITERAL:
return factory->NewLiteral(isolate_factory->false_value(), pos);
case Token::NUMBER: {
- ASSERT(scanner->is_literal_ascii());
- double value = StringToDouble(parser_->isolate()->unicode_cache(),
- scanner->literal_ascii_string(),
- ALLOW_HEX | ALLOW_OCTAL |
- ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
+ double value = scanner->DoubleValue();
return factory->NewNumberLiteral(value, pos);
}
default:
@@ -577,18 +619,27 @@ Literal* ParserTraits::GetLiteralTheHole(
}
-Expression* ParserTraits::ParseObjectLiteral(bool* ok) {
- return parser_->ParseObjectLiteral(ok);
+Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
+ return parser_->ParseV8Intrinsic(ok);
}
-Expression* ParserTraits::ParseAssignmentExpression(bool accept_IN, bool* ok) {
- return parser_->ParseAssignmentExpression(accept_IN, ok);
+FunctionLiteral* ParserTraits::ParseFunctionLiteral(
+ Handle<String> name,
+ Scanner::Location function_name_location,
+ bool name_is_strict_reserved,
+ bool is_generator,
+ int function_token_position,
+ FunctionLiteral::FunctionType type,
+ bool* ok) {
+ return parser_->ParseFunctionLiteral(name, function_name_location,
+ name_is_strict_reserved, is_generator,
+ function_token_position, type, ok);
}
-Expression* ParserTraits::ParseV8Intrinsic(bool* ok) {
- return parser_->ParseV8Intrinsic(ok);
+Expression* ParserTraits::ParseConditionalExpression(bool accept_IN, bool* ok) {
+ return parser_->ParseConditionalExpression(accept_IN, ok);
}
@@ -606,7 +657,6 @@ Parser::Parser(CompilationInfo* info)
original_scope_(NULL),
target_stack_(NULL),
pre_parse_data_(NULL),
- fni_(NULL),
info_(info) {
ASSERT(!script_.is_null());
isolate_->set_ast_node_id(0);
@@ -682,7 +732,7 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
}
original_scope_ = scope;
if (info->is_eval()) {
- if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
+ if (!scope->is_global_scope() || info->strict_mode() == STRICT) {
scope = NewScope(scope, EVAL_SCOPE);
}
} else if (info->is_global()) {
@@ -703,16 +753,16 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
// Enters 'scope'.
FunctionState function_state(&function_state_, &scope_, scope, zone());
- scope_->SetLanguageMode(info->language_mode());
+ scope_->SetStrictMode(info->strict_mode());
ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16, zone());
bool ok = true;
int beg_pos = scanner()->location().beg_pos;
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
- if (ok && !scope_->is_classic_mode()) {
+ if (ok && strict_mode() == STRICT) {
CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
}
- if (ok && is_extended_mode()) {
+ if (ok && FLAG_harmony_scoping && strict_mode() == STRICT) {
CheckConflictingVarDeclarations(scope_, &ok);
}
@@ -817,11 +867,9 @@ FunctionLiteral* Parser::ParseLazy(Utf16CharacterStream* source) {
}
original_scope_ = scope;
FunctionState function_state(&function_state_, &scope_, scope, zone());
- ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
- ASSERT(scope->language_mode() != EXTENDED_MODE ||
- info()->is_extended_mode());
- ASSERT(info()->language_mode() == shared_info->language_mode());
- scope->SetLanguageMode(shared_info->language_mode());
+ ASSERT(scope->strict_mode() == SLOPPY || info()->strict_mode() == STRICT);
+ ASSERT(info()->strict_mode() == shared_info->strict_mode());
+ scope->SetStrictMode(shared_info->strict_mode());
FunctionLiteral::FunctionType function_type = shared_info->is_expression()
? (shared_info->is_anonymous()
? FunctionLiteral::ANONYMOUS_EXPRESSION
@@ -897,7 +945,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
Handle<String> directive = Handle<String>::cast(literal->value());
// Check "use strict" directive (ES5 14.1).
- if (scope_->is_classic_mode() &&
+ if (strict_mode() == SLOPPY &&
directive->Equals(isolate()->heap()->use_strict_string()) &&
token_loc.end_pos - token_loc.beg_pos ==
isolate()->heap()->use_strict_string()->length() + 2) {
@@ -914,9 +962,7 @@ void* Parser::ParseSourceElements(ZoneList<Statement*>* processor,
scope_ = scope;
mode_ = PARSE_EAGERLY;
}
- // TODO(ES6): Fix entering extended mode, once it is specified.
- scope_->SetLanguageMode(allow_harmony_scoping()
- ? EXTENDED_MODE : STRICT_MODE);
+ scope_->SetStrictMode(STRICT);
// "use strict" is the only directive for now.
directive_prologue = false;
}
@@ -1058,7 +1104,7 @@ Module* Parser::ParseModuleLiteral(bool* ok) {
Expect(Token::LBRACE, CHECK_OK);
scope->set_start_position(scanner()->location().beg_pos);
- scope->SetLanguageMode(EXTENDED_MODE);
+ scope->SetStrictMode(STRICT);
{
BlockState block_state(&scope_, scope);
@@ -1443,7 +1489,7 @@ Statement* Parser::ParseStatement(ZoneStringList* labels, bool* ok) {
// In Harmony mode, this case also handles the extension:
// Statement:
// GeneratorDeclaration
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
ReportMessageAt(scanner()->peek_location(), "strict_function");
*ok = false;
return NULL;
@@ -1488,7 +1534,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
// Similarly, strict mode eval scope does not leak variable declarations to
// the caller's scope so we declare all locals, too.
if (declaration_scope->is_function_scope() ||
- declaration_scope->is_strict_or_extended_eval_scope() ||
+ declaration_scope->is_strict_eval_scope() ||
declaration_scope->is_block_scope() ||
declaration_scope->is_module_scope() ||
declaration_scope->is_global_scope()) {
@@ -1521,8 +1567,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
// because the var declaration is hoisted to the function scope where 'x'
// is already bound.
ASSERT(IsDeclaredVariableMode(var->mode()));
- if (is_extended_mode()) {
- // In harmony mode we treat re-declarations as early errors. See
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ // In harmony we treat re-declarations as early errors. See
// ES5 16 for a definition of early errors.
SmartArrayPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
const char* elms[2] = { "Variable", c_string.get() };
@@ -1559,7 +1605,7 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
// Runtime::DeclareContextSlot() calls.
declaration_scope->AddDeclaration(declaration);
- if (mode == CONST && declaration_scope->is_global_scope()) {
+ if (mode == CONST_LEGACY && declaration_scope->is_global_scope()) {
// For global const variables we bind the proxy to a variable.
ASSERT(resolve); // should be set by all callers
Variable::Kind kind = Variable::NORMAL;
@@ -1567,8 +1613,8 @@ void Parser::Declare(Declaration* declaration, bool resolve, bool* ok) {
declaration_scope, name, mode, true, kind,
kNeedsInitialization, proxy->interface());
} else if (declaration_scope->is_eval_scope() &&
- declaration_scope->is_classic_mode()) {
- // For variable declarations in a non-strict eval scope the proxy is bound
+ declaration_scope->strict_mode() == SLOPPY) {
+ // For variable declarations in a sloppy eval scope the proxy is bound
// to a lookup variable to force a dynamic declaration using the
// DeclareContextSlot runtime function.
Variable::Kind kind = Variable::NORMAL;
@@ -1699,7 +1745,8 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
// In extended mode, a function behaves as a lexical binding, except in the
// global scope.
VariableMode mode =
- is_extended_mode() && !scope_->is_global_scope() ? LET : VAR;
+ FLAG_harmony_scoping &&
+ strict_mode() == STRICT && !scope_->is_global_scope() ? LET : VAR;
VariableProxy* proxy = NewUnresolved(name, mode, Interface::NewValue());
Declaration* declaration =
factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
@@ -1710,7 +1757,9 @@ Statement* Parser::ParseFunctionDeclaration(ZoneStringList* names, bool* ok) {
Block* Parser::ParseBlock(ZoneStringList* labels, bool* ok) {
- if (scope_->is_extended_mode()) return ParseScopedBlock(labels, ok);
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ return ParseScopedBlock(labels, ok);
+ }
// Block ::
// '{' Statement* '}'
@@ -1826,29 +1875,31 @@ Block* Parser::ParseVariableDeclarations(
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
//
- // However disallowing const in classic mode will break compatibility with
+ // However disallowing const in sloppy mode will break compatibility with
// existing pages. Therefore we keep allowing const with the old
- // non-harmony semantics in classic mode.
+ // non-harmony semantics in sloppy mode.
Consume(Token::CONST);
- switch (scope_->language_mode()) {
- case CLASSIC_MODE:
- mode = CONST;
- init_op = Token::INIT_CONST;
+ switch (strict_mode()) {
+ case SLOPPY:
+ mode = CONST_LEGACY;
+ init_op = Token::INIT_CONST_LEGACY;
break;
- case STRICT_MODE:
- ReportMessage("strict_const", Vector<const char*>::empty());
- *ok = false;
- return NULL;
- case EXTENDED_MODE:
- if (var_context == kStatement) {
- // In extended mode 'const' declarations are only allowed in source
- // element positions.
- ReportMessage("unprotected_const", Vector<const char*>::empty());
+ case STRICT:
+ if (FLAG_harmony_scoping) {
+ if (var_context == kStatement) {
+ // In strict mode 'const' declarations are only allowed in source
+ // element positions.
+ ReportMessage("unprotected_const", Vector<const char*>::empty());
+ *ok = false;
+ return NULL;
+ }
+ mode = CONST;
+ init_op = Token::INIT_CONST;
+ } else {
+ ReportMessage("strict_const", Vector<const char*>::empty());
*ok = false;
return NULL;
}
- mode = CONST_HARMONY;
- init_op = Token::INIT_CONST_HARMONY;
}
is_const = true;
needs_init = true;
@@ -1859,7 +1910,9 @@ Block* Parser::ParseVariableDeclarations(
//
// * It is a Syntax Error if the code that matches this production is not
// contained in extended code.
- if (!is_extended_mode()) {
+ //
+ // TODO(rossberg): make 'let' a legal identifier in sloppy mode.
+ if (!FLAG_harmony_scoping || strict_mode() == SLOPPY) {
ReportMessage("illegal_let", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -1964,7 +2017,7 @@ Block* Parser::ParseVariableDeclarations(
Expression* value = NULL;
int pos = -1;
// Harmony consts have non-optional initializers.
- if (peek() == Token::ASSIGN || mode == CONST_HARMONY) {
+ if (peek() == Token::ASSIGN || mode == CONST) {
Expect(Token::ASSIGN, CHECK_OK);
pos = position();
value = ParseAssignmentExpression(var_context != kForStatement, CHECK_OK);
@@ -2032,8 +2085,8 @@ Block* Parser::ParseVariableDeclarations(
} else {
// Add strict mode.
// We may want to pass singleton to avoid Literal allocations.
- LanguageMode language_mode = initialization_scope->language_mode();
- arguments->Add(factory()->NewNumberLiteral(language_mode, pos), zone());
+ StrictMode strict_mode = initialization_scope->strict_mode();
+ arguments->Add(factory()->NewNumberLiteral(strict_mode, pos), zone());
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
@@ -2333,7 +2386,7 @@ Statement* Parser::ParseWithStatement(ZoneStringList* labels, bool* ok) {
Expect(Token::WITH, CHECK_OK);
int pos = position();
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
ReportMessage("strict_mode_with", Vector<const char*>::empty());
*ok = false;
return NULL;
@@ -2485,7 +2538,8 @@ TryStatement* Parser::ParseTryStatement(bool* ok) {
Expect(Token::RPAREN, CHECK_OK);
Target target(&this->target_stack_, &catch_collector);
- VariableMode mode = is_extended_mode() ? LET : VAR;
+ VariableMode mode =
+ FLAG_harmony_scoping && strict_mode() == STRICT ? LET : VAR;
catch_variable =
catch_scope->DeclareLocal(name, mode, kCreatedInitialized);
@@ -2876,103 +2930,6 @@ Statement* Parser::ParseForStatement(ZoneStringList* labels, bool* ok) {
}
-// Precedence = 2
-Expression* Parser::ParseAssignmentExpression(bool accept_IN, bool* ok) {
- // AssignmentExpression ::
- // ConditionalExpression
- // YieldExpression
- // LeftHandSideExpression AssignmentOperator AssignmentExpression
-
- if (peek() == Token::YIELD && is_generator()) {
- return ParseYieldExpression(ok);
- }
-
- if (fni_ != NULL) fni_->Enter();
- Expression* expression = ParseConditionalExpression(accept_IN, CHECK_OK);
-
- if (!Token::IsAssignmentOp(peek())) {
- if (fni_ != NULL) fni_->Leave();
- // Parsed conditional expression only (no assignment).
- return expression;
- }
-
- // Signal a reference error if the expression is an invalid left-hand
- // side expression. We could report this as a syntax error here but
- // for compatibility with JSC we choose to report the error at
- // runtime.
- // TODO(ES5): Should change parsing for spec conformance.
- if (expression == NULL || !expression->IsValidLeftHandSide()) {
- Handle<String> message =
- isolate()->factory()->invalid_lhs_in_assignment_string();
- expression = NewThrowReferenceError(message);
- }
-
- if (!scope_->is_classic_mode()) {
- // Assignment to eval or arguments is disallowed in strict mode.
- CheckStrictModeLValue(expression, CHECK_OK);
- }
- MarkAsLValue(expression);
-
- Token::Value op = Next(); // Get assignment operator.
- int pos = position();
- Expression* right = ParseAssignmentExpression(accept_IN, CHECK_OK);
-
- // TODO(1231235): We try to estimate the set of properties set by
- // constructors. We define a new property whenever there is an
- // assignment to a property of 'this'. We should probably only add
- // properties if we haven't seen them before. Otherwise we'll
- // probably overestimate the number of properties.
- Property* property = expression ? expression->AsProperty() : NULL;
- if (op == Token::ASSIGN &&
- property != NULL &&
- property->obj()->AsVariableProxy() != NULL &&
- property->obj()->AsVariableProxy()->is_this()) {
- function_state_->AddProperty();
- }
-
- // If we assign a function literal to a property we pretenure the
- // literal so it can be added as a constant function property.
- if (property != NULL && right->AsFunctionLiteral() != NULL) {
- right->AsFunctionLiteral()->set_pretenure();
- }
-
- if (fni_ != NULL) {
- // Check if the right hand side is a call to avoid inferring a
- // name if we're dealing with "a = function(){...}();"-like
- // expression.
- if ((op == Token::INIT_VAR
- || op == Token::INIT_CONST
- || op == Token::ASSIGN)
- && (right->AsCall() == NULL && right->AsCallNew() == NULL)) {
- fni_->Infer();
- } else {
- fni_->RemoveLastFunction();
- }
- fni_->Leave();
- }
-
- return factory()->NewAssignment(op, expression, right, pos);
-}
-
-
-Expression* Parser::ParseYieldExpression(bool* ok) {
- // YieldExpression ::
- // 'yield' '*'? AssignmentExpression
- int pos = peek_position();
- Expect(Token::YIELD, CHECK_OK);
- Yield::Kind kind =
- Check(Token::MUL) ? Yield::DELEGATING : Yield::SUSPEND;
- Expression* generator_object = factory()->NewVariableProxy(
- function_state_->generator_object_variable());
- Expression* expression = ParseAssignmentExpression(false, CHECK_OK);
- Yield* yield = factory()->NewYield(generator_object, expression, kind, pos);
- if (kind == Yield::DELEGATING) {
- yield->set_index(function_state_->NextHandlerIndex());
- }
- return yield;
-}
-
-
// Precedence = 3
Expression* Parser::ParseConditionalExpression(bool accept_IN, bool* ok) {
// ConditionalExpression ::
@@ -3131,7 +3088,7 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
}
// "delete identifier" is a syntax error in strict mode.
- if (op == Token::DELETE && !scope_->is_classic_mode()) {
+ if (op == Token::DELETE && strict_mode() == STRICT) {
VariableProxy* operand = expression->AsVariableProxy();
if (operand != NULL && !operand->is_this()) {
ReportMessage("strict_delete", Vector<const char*>::empty());
@@ -3179,11 +3136,11 @@ Expression* Parser::ParseUnaryExpression(bool* ok) {
expression = NewThrowReferenceError(message);
}
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
// Prefix expression operand in strict mode may not be eval or arguments.
CheckStrictModeLValue(expression, CHECK_OK);
}
- MarkAsLValue(expression);
+ MarkExpressionAsLValue(expression);
return factory()->NewCountOperation(op,
true /* prefix */,
@@ -3213,11 +3170,11 @@ Expression* Parser::ParsePostfixExpression(bool* ok) {
expression = NewThrowReferenceError(message);
}
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
// Postfix expression operand in strict mode may not be eval or arguments.
CheckStrictModeLValue(expression, CHECK_OK);
}
- MarkAsLValue(expression);
+ MarkExpressionAsLValue(expression);
Token::Value next = Next();
expression =
@@ -3360,14 +3317,14 @@ Expression* Parser::ParseMemberExpression(bool* ok) {
Handle<String> name;
bool is_strict_reserved_name = false;
Scanner::Location function_name_location = Scanner::Location::invalid();
+ FunctionLiteral::FunctionType function_type =
+ FunctionLiteral::ANONYMOUS_EXPRESSION;
if (peek_any_identifier()) {
name = ParseIdentifierOrStrictReservedWord(&is_strict_reserved_name,
CHECK_OK);
function_name_location = scanner()->location();
+ function_type = FunctionLiteral::NAMED_EXPRESSION;
}
- FunctionLiteral::FunctionType function_type = name.is_null()
- ? FunctionLiteral::ANONYMOUS_EXPRESSION
- : FunctionLiteral::NAMED_EXPRESSION;
result = ParseFunctionLiteral(name,
function_name_location,
is_strict_reserved_name,
@@ -3490,289 +3447,6 @@ Handle<FixedArray> CompileTimeValue::GetElements(Handle<FixedArray> value) {
}
-Expression* Parser::ParseObjectLiteral(bool* ok) {
- // ObjectLiteral ::
- // '{' (
- // ((IdentifierName | String | Number) ':' AssignmentExpression)
- // | (('get' | 'set') (IdentifierName | String | Number) FunctionLiteral)
- // )*[','] '}'
-
- int pos = peek_position();
- ZoneList<ObjectLiteral::Property*>* properties =
- new(zone()) ZoneList<ObjectLiteral::Property*>(4, zone());
- int number_of_boilerplate_properties = 0;
- bool has_function = false;
-
- ObjectLiteralChecker checker(this, scope_->language_mode());
-
- Expect(Token::LBRACE, CHECK_OK);
-
- while (peek() != Token::RBRACE) {
- if (fni_ != NULL) fni_->Enter();
-
- Literal* key = NULL;
- Token::Value next = peek();
- int next_pos = peek_position();
-
- switch (next) {
- case Token::FUTURE_RESERVED_WORD:
- case Token::FUTURE_STRICT_RESERVED_WORD:
- case Token::IDENTIFIER: {
- bool is_getter = false;
- bool is_setter = false;
- Handle<String> id =
- ParseIdentifierNameOrGetOrSet(&is_getter, &is_setter, CHECK_OK);
- if (fni_ != NULL) fni_->PushLiteralName(id);
-
- if ((is_getter || is_setter) && peek() != Token::COLON) {
- // Special handling of getter and setter syntax:
- // { ... , get foo() { ... }, ... , set foo(v) { ... v ... } , ... }
- // We have already read the "get" or "set" keyword.
- Token::Value next = Next();
- bool is_keyword = Token::IsKeyword(next);
- if (next != i::Token::IDENTIFIER &&
- next != i::Token::FUTURE_RESERVED_WORD &&
- next != i::Token::FUTURE_STRICT_RESERVED_WORD &&
- next != i::Token::NUMBER &&
- next != i::Token::STRING &&
- !is_keyword) {
- // Unexpected token.
- ReportUnexpectedToken(next);
- *ok = false;
- return NULL;
- }
- // Validate the property.
- PropertyKind type = is_getter ? kGetterProperty : kSetterProperty;
- checker.CheckProperty(next, type, CHECK_OK);
- Handle<String> name = is_keyword
- ? isolate_->factory()->InternalizeUtf8String(Token::String(next))
- : GetSymbol();
- FunctionLiteral* value =
- ParseFunctionLiteral(name,
- scanner()->location(),
- false, // reserved words are allowed here
- false, // not a generator
- RelocInfo::kNoPosition,
- FunctionLiteral::ANONYMOUS_EXPRESSION,
- CHECK_OK);
- // Allow any number of parameters for compatibilty with JSC.
- // Specification only allows zero parameters for get and one for set.
- ObjectLiteral::Property* property =
- factory()->NewObjectLiteralProperty(is_getter, value, next_pos);
- if (ObjectLiteral::IsBoilerplateProperty(property)) {
- number_of_boilerplate_properties++;
- }
- properties->Add(property, zone());
- if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
- if (fni_ != NULL) {
- fni_->Infer();
- fni_->Leave();
- }
- continue; // restart the while
- }
- // Failed to parse as get/set property, so it's just a property
- // called "get" or "set".
- key = factory()->NewLiteral(id, next_pos);
- break;
- }
- case Token::STRING: {
- Consume(Token::STRING);
- Handle<String> string = GetSymbol();
- if (fni_ != NULL) fni_->PushLiteralName(string);
- uint32_t index;
- if (!string.is_null() && string->AsArrayIndex(&index)) {
- key = factory()->NewNumberLiteral(index, next_pos);
- break;
- }
- key = factory()->NewLiteral(string, next_pos);
- break;
- }
- case Token::NUMBER: {
- Consume(Token::NUMBER);
- ASSERT(scanner()->is_literal_ascii());
- double value = StringToDouble(isolate()->unicode_cache(),
- scanner()->literal_ascii_string(),
- ALLOW_HEX | ALLOW_OCTAL |
- ALLOW_IMPLICIT_OCTAL | ALLOW_BINARY);
- key = factory()->NewNumberLiteral(value, next_pos);
- break;
- }
- default:
- if (Token::IsKeyword(next)) {
- Consume(next);
- Handle<String> string = GetSymbol();
- key = factory()->NewLiteral(string, next_pos);
- } else {
- // Unexpected token.
- Token::Value next = Next();
- ReportUnexpectedToken(next);
- *ok = false;
- return NULL;
- }
- }
-
- // Validate the property
- checker.CheckProperty(next, kValueProperty, CHECK_OK);
-
- Expect(Token::COLON, CHECK_OK);
- Expression* value = ParseAssignmentExpression(true, CHECK_OK);
-
- ObjectLiteral::Property* property =
- factory()->NewObjectLiteralProperty(key, value);
-
- // Mark top-level object literals that contain function literals and
- // pretenure the literal so it can be added as a constant function
- // property.
- if (scope_->DeclarationScope()->is_global_scope() &&
- value->AsFunctionLiteral() != NULL) {
- has_function = true;
- value->AsFunctionLiteral()->set_pretenure();
- }
-
- // Count CONSTANT or COMPUTED properties to maintain the enumeration order.
- if (ObjectLiteral::IsBoilerplateProperty(property)) {
- number_of_boilerplate_properties++;
- }
- properties->Add(property, zone());
-
- // TODO(1240767): Consider allowing trailing comma.
- if (peek() != Token::RBRACE) Expect(Token::COMMA, CHECK_OK);
-
- if (fni_ != NULL) {
- fni_->Infer();
- fni_->Leave();
- }
- }
- Expect(Token::RBRACE, CHECK_OK);
-
- // Computation of literal_index must happen before pre parse bailout.
- int literal_index = function_state_->NextMaterializedLiteralIndex();
-
- return factory()->NewObjectLiteral(properties,
- literal_index,
- number_of_boilerplate_properties,
- has_function,
- pos);
-}
-
-
-ZoneList<Expression*>* Parser::ParseArguments(bool* ok) {
- // Arguments ::
- // '(' (AssignmentExpression)*[','] ')'
-
- ZoneList<Expression*>* result = new(zone()) ZoneList<Expression*>(4, zone());
- Expect(Token::LPAREN, CHECK_OK);
- bool done = (peek() == Token::RPAREN);
- while (!done) {
- Expression* argument = ParseAssignmentExpression(true, CHECK_OK);
- result->Add(argument, zone());
- if (result->length() > Code::kMaxArguments) {
- ReportMessageAt(scanner()->location(), "too_many_arguments");
- *ok = false;
- return NULL;
- }
- done = (peek() == Token::RPAREN);
- if (!done) Expect(Token::COMMA, CHECK_OK);
- }
- Expect(Token::RPAREN, CHECK_OK);
- return result;
-}
-
-
-class SingletonLogger : public ParserRecorder {
- public:
- SingletonLogger() : has_error_(false), start_(-1), end_(-1) { }
- virtual ~SingletonLogger() { }
-
- void Reset() { has_error_ = false; }
-
- virtual void LogFunction(int start,
- int end,
- int literals,
- int properties,
- LanguageMode mode) {
- ASSERT(!has_error_);
- start_ = start;
- end_ = end;
- literals_ = literals;
- properties_ = properties;
- mode_ = mode;
- };
-
- // Logs a symbol creation of a literal or identifier.
- virtual void LogAsciiSymbol(int start, Vector<const char> literal) { }
- virtual void LogUtf16Symbol(int start, Vector<const uc16> literal) { }
-
- // Logs an error message and marks the log as containing an error.
- // Further logging will be ignored, and ExtractData will return a vector
- // representing the error only.
- virtual void LogMessage(int start,
- int end,
- const char* message,
- const char* argument_opt) {
- if (has_error_) return;
- has_error_ = true;
- start_ = start;
- end_ = end;
- message_ = message;
- argument_opt_ = argument_opt;
- }
-
- virtual int function_position() { return 0; }
-
- virtual int symbol_position() { return 0; }
-
- virtual int symbol_ids() { return -1; }
-
- virtual Vector<unsigned> ExtractData() {
- UNREACHABLE();
- return Vector<unsigned>();
- }
-
- virtual void PauseRecording() { }
-
- virtual void ResumeRecording() { }
-
- bool has_error() { return has_error_; }
-
- int start() { return start_; }
- int end() { return end_; }
- int literals() {
- ASSERT(!has_error_);
- return literals_;
- }
- int properties() {
- ASSERT(!has_error_);
- return properties_;
- }
- LanguageMode language_mode() {
- ASSERT(!has_error_);
- return mode_;
- }
- const char* message() {
- ASSERT(has_error_);
- return message_;
- }
- const char* argument_opt() {
- ASSERT(has_error_);
- return argument_opt_;
- }
-
- private:
- bool has_error_;
- int start_;
- int end_;
- // For function entries.
- int literals_;
- int properties_;
- LanguageMode mode_;
- // For error messages.
- const char* message_;
- const char* argument_opt_;
-};
-
-
FunctionLiteral* Parser::ParseFunctionLiteral(
Handle<String> function_name,
Scanner::Location function_name_location,
@@ -3828,7 +3502,8 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
Scope* declaration_scope = scope_->DeclarationScope();
Scope* original_declaration_scope = original_scope_->DeclarationScope();
Scope* scope =
- function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
+ function_type == FunctionLiteral::DECLARATION &&
+ (!FLAG_harmony_scoping || strict_mode() == SLOPPY) &&
(original_scope_ == original_declaration_scope ||
declaration_scope != original_declaration_scope)
? NewScope(declaration_scope, FUNCTION_SCOPE)
@@ -3917,10 +3592,13 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// future we can change the AST to only refer to VariableProxies
// instead of Variables and Proxis as is the case now.
Variable* fvar = NULL;
- Token::Value fvar_init_op = Token::INIT_CONST;
+ Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
- if (is_extended_mode()) fvar_init_op = Token::INIT_CONST_HARMONY;
- VariableMode fvar_mode = is_extended_mode() ? CONST_HARMONY : CONST;
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
+ fvar_init_op = Token::INIT_CONST;
+ }
+ VariableMode fvar_mode = FLAG_harmony_scoping && strict_mode() == STRICT
+ ? CONST : CONST_LEGACY;
fvar = new(zone()) Variable(scope_,
function_name, fvar_mode, true /* is valid LHS */,
Variable::NORMAL, kCreatedInitialized, Interface::NewConst());
@@ -3990,7 +3668,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->end_position() - function_block_pos);
materialized_literal_count = entry.literal_count();
expected_property_count = entry.property_count();
- scope_->SetLanguageMode(entry.language_mode());
+ scope_->SetStrictMode(entry.strict_mode());
} else {
// This case happens when we have preparse data but it doesn't contain
// an entry for the function. As a safety net, fall back to eager
@@ -4038,7 +3716,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
scope->end_position() - function_block_pos);
materialized_literal_count = logger.literals();
expected_property_count = logger.properties();
- scope_->SetLanguageMode(logger.language_mode());
+ scope_->SetStrictMode(logger.strict_mode());
}
}
@@ -4102,7 +3780,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
// Validate strict mode. We can do this only after parsing the function,
// since the function can declare itself strict.
- if (!scope_->is_classic_mode()) {
+ if (strict_mode() == STRICT) {
if (IsEvalOrArguments(function_name)) {
ReportMessageAt(function_name_location, "strict_eval_arguments");
*ok = false;
@@ -4137,7 +3815,7 @@ FunctionLiteral* Parser::ParseFunctionLiteral(
dont_optimize_reason = factory()->visitor()->dont_optimize_reason();
}
- if (is_extended_mode()) {
+ if (FLAG_harmony_scoping && strict_mode() == STRICT) {
CheckConflictingVarDeclarations(scope, CHECK_OK);
}
@@ -4183,7 +3861,7 @@ PreParser::PreParseResult Parser::LazyParseFunctionLiteral(
allow_harmony_numeric_literals());
}
PreParser::PreParseResult result =
- reusable_preparser_->PreParseLazyFunction(scope_->language_mode(),
+ reusable_preparser_->PreParseLazyFunction(strict_mode(),
is_generator(),
logger);
return result;
@@ -4252,31 +3930,6 @@ Literal* Parser::GetLiteralUndefined(int position) {
}
-void Parser::MarkAsLValue(Expression* expression) {
- VariableProxy* proxy = expression != NULL
- ? expression->AsVariableProxy()
- : NULL;
-
- if (proxy != NULL) proxy->MarkAsLValue();
-}
-
-
-// Checks LHS expression for assignment and prefix/postfix increment/decrement
-// in strict mode.
-void Parser::CheckStrictModeLValue(Expression* expression,
- bool* ok) {
- ASSERT(!scope_->is_classic_mode());
- VariableProxy* lhs = expression != NULL
- ? expression->AsVariableProxy()
- : NULL;
-
- if (lhs != NULL && !lhs->is_this() && IsEvalOrArguments(lhs->name())) {
- ReportMessage("strict_eval_arguments", Vector<const char*>::empty());
- *ok = false;
- }
-}
-
-
void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
Declaration* decl = scope->CheckConflictingVarDeclarations();
if (decl != NULL) {
@@ -4994,7 +4647,7 @@ bool RegExpParser::ParseIntervalQuantifier(int* min_out, int* max_out) {
uc32 RegExpParser::ParseOctalLiteral() {
- ASSERT('0' <= current() && current() <= '7');
+ ASSERT(('0' <= current() && current() <= '7') || current() == kEndMarker);
// For compatibility with some other browsers (not all), we parse
// up to three octal digits with a value below 256.
uc32 value = current() - '0';
« no previous file with comments | « src/parser.h ('k') | src/platform.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698