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

Side by Side Diff: src/parser.cc

Issue 1219853004: [es6] Initial support for let/const bindings in sloppy mode (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Updated tests and comments Created 5 years, 5 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 unified diff | Download patch
« no previous file with comments | « no previous file | src/preparser.h » ('j') | test/mjsunit/harmony/block-let-semantics-sloppy.js » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/v8.h" 5 #include "src/v8.h"
6 6
7 #include "src/api.h" 7 #include "src/api.h"
8 #include "src/ast.h" 8 #include "src/ast.h"
9 #include "src/ast-literal-reindexer.h" 9 #include "src/ast-literal-reindexer.h"
10 #include "src/bailout-reason.h" 10 #include "src/bailout-reason.h"
(...skipping 1369 matching lines...) Expand 10 before | Expand all | Expand 10 after
1380 } 1380 }
1381 return ParseClassDeclaration(NULL, ok); 1381 return ParseClassDeclaration(NULL, ok);
1382 case Token::CONST: 1382 case Token::CONST:
1383 if (allow_const()) { 1383 if (allow_const()) {
1384 return ParseVariableStatement(kStatementListItem, NULL, ok); 1384 return ParseVariableStatement(kStatementListItem, NULL, ok);
1385 } 1385 }
1386 break; 1386 break;
1387 case Token::VAR: 1387 case Token::VAR:
1388 return ParseVariableStatement(kStatementListItem, NULL, ok); 1388 return ParseVariableStatement(kStatementListItem, NULL, ok);
1389 case Token::LET: 1389 case Token::LET:
1390 if (is_strict(language_mode())) { 1390 if (allow_let()) {
1391 return ParseVariableStatement(kStatementListItem, NULL, ok); 1391 return ParseVariableStatement(kStatementListItem, NULL, ok);
1392 } 1392 }
1393 break; 1393 break;
1394 default: 1394 default:
1395 break; 1395 break;
1396 } 1396 }
1397 return ParseStatement(NULL, ok); 1397 return ParseStatement(NULL, ok);
1398 } 1398 }
1399 1399
1400 1400
(...skipping 641 matching lines...) Expand 10 before | Expand all | Expand 10 after
2042 // functions. The function CheckConflictingVarDeclarations checks for 2042 // functions. The function CheckConflictingVarDeclarations checks for
2043 // var and let bindings from different scopes whereas this is a check for 2043 // var and let bindings from different scopes whereas this is a check for
2044 // conflicting declarations within the same scope. This check also covers 2044 // conflicting declarations within the same scope. This check also covers
2045 // the special case 2045 // the special case
2046 // 2046 //
2047 // function () { let x; { var x; } } 2047 // function () { let x; { var x; } }
2048 // 2048 //
2049 // because the var declaration is hoisted to the function scope where 'x' 2049 // because the var declaration is hoisted to the function scope where 'x'
2050 // is already bound. 2050 // is already bound.
2051 DCHECK(IsDeclaredVariableMode(var->mode())); 2051 DCHECK(IsDeclaredVariableMode(var->mode()));
2052 if (is_strict(language_mode())) { 2052 if (is_strict(language_mode()) || allow_harmony_sloppy()) {
2053 // In harmony we treat re-declarations as early errors. See 2053 // In harmony we treat re-declarations as early errors. See
2054 // ES5 16 for a definition of early errors. 2054 // ES5 16 for a definition of early errors.
2055 if (declaration_kind == DeclarationDescriptor::NORMAL) { 2055 if (declaration_kind == DeclarationDescriptor::NORMAL) {
2056 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name); 2056 ParserTraits::ReportMessage(MessageTemplate::kVarRedeclaration, name);
2057 } else { 2057 } else {
2058 ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe); 2058 ParserTraits::ReportMessage(MessageTemplate::kStrictParamDupe);
2059 } 2059 }
2060 *ok = false; 2060 *ok = false;
2061 return nullptr; 2061 return nullptr;
2062 } 2062 }
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 pos, FunctionLiteral::DECLARATION, 2200 pos, FunctionLiteral::DECLARATION,
2201 FunctionLiteral::NORMAL_ARITY, CHECK_OK); 2201 FunctionLiteral::NORMAL_ARITY, CHECK_OK);
2202 // Even if we're not at the top-level of the global or a function 2202 // Even if we're not at the top-level of the global or a function
2203 // scope, we treat it as such and introduce the function with its 2203 // scope, we treat it as such and introduce the function with its
2204 // initial value upon entering the corresponding scope. 2204 // initial value upon entering the corresponding scope.
2205 // In ES6, a function behaves as a lexical binding, except in 2205 // In ES6, a function behaves as a lexical binding, except in
2206 // a script scope, or the initial scope of eval or another function. 2206 // a script scope, or the initial scope of eval or another function.
2207 VariableMode mode = 2207 VariableMode mode =
2208 is_strong(language_mode()) 2208 is_strong(language_mode())
2209 ? CONST 2209 ? CONST
2210 : is_strict(language_mode()) && 2210 : (is_strict(language_mode()) || allow_harmony_sloppy()) &&
2211 !(scope_->is_script_scope() || scope_->is_eval_scope() || 2211 !(scope_->is_script_scope() || scope_->is_eval_scope() ||
2212 scope_->is_function_scope()) 2212 scope_->is_function_scope())
2213 ? LET 2213 ? LET
2214 : VAR; 2214 : VAR;
2215 VariableProxy* proxy = NewUnresolved(name, mode); 2215 VariableProxy* proxy = NewUnresolved(name, mode);
2216 Declaration* declaration = 2216 Declaration* declaration =
2217 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos); 2217 factory()->NewFunctionDeclaration(proxy, mode, fun, scope_, pos);
2218 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK); 2218 Declare(declaration, DeclarationDescriptor::NORMAL, true, CHECK_OK);
2219 if (names) names->Add(name, zone()); 2219 if (names) names->Add(name, zone());
2220 return factory()->NewEmptyStatement(RelocInfo::kNoPosition); 2220 return factory()->NewEmptyStatement(RelocInfo::kNoPosition);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
2280 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET; 2280 is_strong(language_mode()) ? Token::INIT_CONST : Token::INIT_LET;
2281 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos); 2281 Assignment* assignment = factory()->NewAssignment(init_op, proxy, value, pos);
2282 Statement* assignment_statement = 2282 Statement* assignment_statement =
2283 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition); 2283 factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition);
2284 if (names) names->Add(name, zone()); 2284 if (names) names->Add(name, zone());
2285 return assignment_statement; 2285 return assignment_statement;
2286 } 2286 }
2287 2287
2288 2288
2289 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) { 2289 Block* Parser::ParseBlock(ZoneList<const AstRawString*>* labels, bool* ok) {
2290 if (is_strict(language_mode())) { 2290 if (is_strict(language_mode()) || allow_harmony_sloppy()) {
2291 return ParseScopedBlock(labels, ok); 2291 return ParseScopedBlock(labels, ok);
2292 } 2292 }
2293 2293
2294 // Block :: 2294 // Block ::
2295 // '{' Statement* '}' 2295 // '{' Statement* '}'
2296 2296
2297 // Note that a Block does not introduce a new execution scope! 2297 // Note that a Block does not introduce a new execution scope!
2298 // (ECMA-262, 3rd, 12.2) 2298 // (ECMA-262, 3rd, 12.2)
2299 // 2299 //
2300 // Construct block expecting 16 statements. 2300 // Construct block expecting 16 statements.
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after
2432 return; 2432 return;
2433 } 2433 }
2434 Consume(Token::VAR); 2434 Consume(Token::VAR);
2435 } else if (peek() == Token::CONST && allow_const()) { 2435 } else if (peek() == Token::CONST && allow_const()) {
2436 Consume(Token::CONST); 2436 Consume(Token::CONST);
2437 if (is_sloppy(language_mode()) && allow_legacy_const()) { 2437 if (is_sloppy(language_mode()) && allow_legacy_const()) {
2438 parsing_result->descriptor.mode = CONST_LEGACY; 2438 parsing_result->descriptor.mode = CONST_LEGACY;
2439 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY; 2439 parsing_result->descriptor.init_op = Token::INIT_CONST_LEGACY;
2440 ++use_counts_[v8::Isolate::kLegacyConst]; 2440 ++use_counts_[v8::Isolate::kLegacyConst];
2441 } else { 2441 } else {
2442 DCHECK(is_strict(language_mode())); 2442 DCHECK(is_strict(language_mode()) || allow_harmony_sloppy());
2443 DCHECK(var_context != kStatement); 2443 DCHECK(var_context != kStatement);
2444 parsing_result->descriptor.mode = CONST; 2444 parsing_result->descriptor.mode = CONST;
2445 parsing_result->descriptor.init_op = Token::INIT_CONST; 2445 parsing_result->descriptor.init_op = Token::INIT_CONST;
2446 } 2446 }
2447 parsing_result->descriptor.is_const = true; 2447 parsing_result->descriptor.is_const = true;
2448 parsing_result->descriptor.needs_init = true; 2448 parsing_result->descriptor.needs_init = true;
2449 } else if (peek() == Token::LET && is_strict(language_mode())) { 2449 } else if (peek() == Token::LET && allow_let()) {
2450 Consume(Token::LET); 2450 Consume(Token::LET);
2451 DCHECK(var_context != kStatement); 2451 DCHECK(var_context != kStatement);
2452 parsing_result->descriptor.mode = LET; 2452 parsing_result->descriptor.mode = LET;
2453 parsing_result->descriptor.needs_init = true; 2453 parsing_result->descriptor.needs_init = true;
2454 parsing_result->descriptor.init_op = Token::INIT_LET; 2454 parsing_result->descriptor.init_op = Token::INIT_LET;
2455 } else { 2455 } else {
2456 UNREACHABLE(); // by current callers 2456 UNREACHABLE(); // by current callers
2457 } 2457 }
2458 2458
2459 parsing_result->descriptor.declaration_scope = 2459 parsing_result->descriptor.declaration_scope =
(...skipping 1031 matching lines...) Expand 10 before | Expand all | Expand 10 after
3491 Scope* saved_scope = scope_; 3491 Scope* saved_scope = scope_;
3492 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE); 3492 Scope* for_scope = NewScope(scope_, BLOCK_SCOPE);
3493 scope_ = for_scope; 3493 scope_ = for_scope;
3494 Expect(Token::FOR, CHECK_OK); 3494 Expect(Token::FOR, CHECK_OK);
3495 Expect(Token::LPAREN, CHECK_OK); 3495 Expect(Token::LPAREN, CHECK_OK);
3496 for_scope->set_start_position(scanner()->location().beg_pos); 3496 for_scope->set_start_position(scanner()->location().beg_pos);
3497 bool is_let_identifier_expression = false; 3497 bool is_let_identifier_expression = false;
3498 DeclarationParsingResult parsing_result; 3498 DeclarationParsingResult parsing_result;
3499 if (peek() != Token::SEMICOLON) { 3499 if (peek() != Token::SEMICOLON) {
3500 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) || 3500 if (peek() == Token::VAR || (peek() == Token::CONST && allow_const()) ||
3501 (peek() == Token::LET && is_strict(language_mode()))) { 3501 (peek() == Token::LET && allow_let())) {
3502 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK); 3502 ParseVariableDeclarations(kForStatement, &parsing_result, CHECK_OK);
3503 is_const = parsing_result.descriptor.mode == CONST; 3503 is_const = parsing_result.descriptor.mode == CONST;
3504 3504
3505 int num_decl = parsing_result.declarations.length(); 3505 int num_decl = parsing_result.declarations.length();
3506 bool accept_IN = num_decl >= 1; 3506 bool accept_IN = num_decl >= 1;
3507 bool accept_OF = true; 3507 bool accept_OF = true;
3508 ForEachStatement::VisitMode mode; 3508 ForEachStatement::VisitMode mode;
3509 int each_beg_pos = scanner()->location().beg_pos; 3509 int each_beg_pos = scanner()->location().beg_pos;
3510 int each_end_pos = scanner()->location().end_pos; 3510 int each_end_pos = scanner()->location().end_pos;
3511 3511
(...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after
3966 // in all normal cases, function declarations are fully hoisted to a 3966 // in all normal cases, function declarations are fully hoisted to a
3967 // declaration scope and compiled relative to that. 3967 // declaration scope and compiled relative to that.
3968 // - (2) is the case iff the current declaration scope is still the original 3968 // - (2) is the case iff the current declaration scope is still the original
3969 // one relative to the deserialized scope chain. Otherwise we must be 3969 // one relative to the deserialized scope chain. Otherwise we must be
3970 // compiling a function in an inner declaration scope in the eval, e.g. a 3970 // compiling a function in an inner declaration scope in the eval, e.g. a
3971 // nested function, and hoisting works normally relative to that. 3971 // nested function, and hoisting works normally relative to that.
3972 Scope* declaration_scope = scope_->DeclarationScope(); 3972 Scope* declaration_scope = scope_->DeclarationScope();
3973 Scope* original_declaration_scope = original_scope_->DeclarationScope(); 3973 Scope* original_declaration_scope = original_scope_->DeclarationScope();
3974 Scope* scope = function_type == FunctionLiteral::DECLARATION && 3974 Scope* scope = function_type == FunctionLiteral::DECLARATION &&
3975 is_sloppy(language_mode()) && 3975 is_sloppy(language_mode()) &&
3976 !allow_harmony_sloppy() &&
3976 (original_scope_ == original_declaration_scope || 3977 (original_scope_ == original_declaration_scope ||
3977 declaration_scope != original_declaration_scope) 3978 declaration_scope != original_declaration_scope)
3978 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind) 3979 ? NewScope(declaration_scope, FUNCTION_SCOPE, kind)
3979 : NewScope(scope_, FUNCTION_SCOPE, kind); 3980 : NewScope(scope_, FUNCTION_SCOPE, kind);
3980 ZoneList<Statement*>* body = NULL; 3981 ZoneList<Statement*>* body = NULL;
3981 int materialized_literal_count = -1; 3982 int materialized_literal_count = -1;
3982 int expected_property_count = -1; 3983 int expected_property_count = -1;
3983 DuplicateFinder duplicate_finder(scanner()->unicode_cache()); 3984 DuplicateFinder duplicate_finder(scanner()->unicode_cache());
3984 ExpressionClassifier formals_classifier(&duplicate_finder); 3985 ExpressionClassifier formals_classifier(&duplicate_finder);
3985 FunctionLiteral::EagerCompileHint eager_compile_hint = 3986 FunctionLiteral::EagerCompileHint eager_compile_hint =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
4023 4024
4024 // If we have a named function expression, we add a local variable 4025 // If we have a named function expression, we add a local variable
4025 // declaration to the body of the function with the name of the 4026 // declaration to the body of the function with the name of the
4026 // function and let it refer to the function itself (closure). 4027 // function and let it refer to the function itself (closure).
4027 // NOTE: We create a proxy and resolve it here so that in the 4028 // NOTE: We create a proxy and resolve it here so that in the
4028 // future we can change the AST to only refer to VariableProxies 4029 // future we can change the AST to only refer to VariableProxies
4029 // instead of Variables and Proxis as is the case now. 4030 // instead of Variables and Proxis as is the case now.
4030 Variable* fvar = NULL; 4031 Variable* fvar = NULL;
4031 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY; 4032 Token::Value fvar_init_op = Token::INIT_CONST_LEGACY;
4032 if (function_type == FunctionLiteral::NAMED_EXPRESSION) { 4033 if (function_type == FunctionLiteral::NAMED_EXPRESSION) {
4033 if (is_strict(language_mode())) { 4034 bool use_strict_const = is_strict(language_mode()) ||
4035 (!allow_legacy_const() && allow_harmony_sloppy());
4036 if (use_strict_const) {
4034 fvar_init_op = Token::INIT_CONST; 4037 fvar_init_op = Token::INIT_CONST;
4035 } 4038 }
4036 VariableMode fvar_mode = 4039 VariableMode fvar_mode = use_strict_const ? CONST : CONST_LEGACY;
4037 is_strict(language_mode()) ? CONST : CONST_LEGACY;
4038 DCHECK(function_name != NULL); 4040 DCHECK(function_name != NULL);
4039 fvar = new (zone()) 4041 fvar = new (zone())
4040 Variable(scope_, function_name, fvar_mode, Variable::NORMAL, 4042 Variable(scope_, function_name, fvar_mode, Variable::NORMAL,
4041 kCreatedInitialized, kNotAssigned); 4043 kCreatedInitialized, kNotAssigned);
4042 VariableProxy* proxy = factory()->NewVariableProxy(fvar); 4044 VariableProxy* proxy = factory()->NewVariableProxy(fvar);
4043 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration( 4045 VariableDeclaration* fvar_declaration = factory()->NewVariableDeclaration(
4044 proxy, fvar_mode, scope_, RelocInfo::kNoPosition); 4046 proxy, fvar_mode, scope_, RelocInfo::kNoPosition);
4045 scope_->DeclareFunctionVar(fvar_declaration); 4047 scope_->DeclareFunctionVar(fvar_declaration);
4046 } 4048 }
4047 4049
(...skipping 1894 matching lines...) Expand 10 before | Expand all | Expand 10 after
5942 Expression* Parser::SpreadCallNew(Expression* function, 5944 Expression* Parser::SpreadCallNew(Expression* function,
5943 ZoneList<v8::internal::Expression*>* args, 5945 ZoneList<v8::internal::Expression*>* args,
5944 int pos) { 5946 int pos) {
5945 args->InsertAt(0, function, zone()); 5947 args->InsertAt(0, function, zone());
5946 5948
5947 return factory()->NewCallRuntime( 5949 return factory()->NewCallRuntime(
5948 ast_value_factory()->reflect_construct_string(), NULL, args, pos); 5950 ast_value_factory()->reflect_construct_string(), NULL, args, pos);
5949 } 5951 }
5950 } // namespace internal 5952 } // namespace internal
5951 } // namespace v8 5953 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/preparser.h » ('j') | test/mjsunit/harmony/block-let-semantics-sloppy.js » ('J')

Powered by Google App Engine
This is Rietveld 408576698