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

Side by Side Diff: src/parser.cc

Issue 7756014: Detect conflicting variable bindings in harmony mode. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 9 years, 3 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 | Annotate | Revision Log
OLDNEW
1 // Copyright 2011 the V8 project authors. All rights reserved. 1 // Copyright 2011 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 629 matching lines...) Expand 10 before | Expand all | Expand 10 after
640 if (strict_mode == kStrictMode) { 640 if (strict_mode == kStrictMode) {
641 top_scope_->EnableStrictMode(); 641 top_scope_->EnableStrictMode();
642 } 642 }
643 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16); 643 ZoneList<Statement*>* body = new(zone()) ZoneList<Statement*>(16);
644 bool ok = true; 644 bool ok = true;
645 int beg_loc = scanner().location().beg_pos; 645 int beg_loc = scanner().location().beg_pos;
646 ParseSourceElements(body, Token::EOS, &ok); 646 ParseSourceElements(body, Token::EOS, &ok);
647 if (ok && top_scope_->is_strict_mode()) { 647 if (ok && top_scope_->is_strict_mode()) {
648 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok); 648 CheckOctalLiteral(beg_loc, scanner().location().end_pos, &ok);
649 } 649 }
650
651 if (ok && harmony_block_scoping_) {
652 CheckConflictingVarDeclarations(scope, &ok);
653 }
654
650 if (ok) { 655 if (ok) {
651 result = new(zone()) FunctionLiteral( 656 result = new(zone()) FunctionLiteral(
652 isolate(), 657 isolate(),
653 no_name, 658 no_name,
654 top_scope_, 659 top_scope_,
655 body, 660 body,
656 lexical_scope.materialized_literal_count(), 661 lexical_scope.materialized_literal_count(),
657 lexical_scope.expected_property_count(), 662 lexical_scope.expected_property_count(),
658 lexical_scope.only_simple_this_property_assignments(), 663 lexical_scope.only_simple_this_property_assignments(),
659 lexical_scope.this_property_assignments(), 664 lexical_scope.this_property_assignments(),
(...skipping 678 matching lines...) Expand 10 before | Expand all | Expand 10 after
1338 declaration_scope->is_strict_mode_eval_scope() || 1343 declaration_scope->is_strict_mode_eval_scope() ||
1339 declaration_scope->is_block_scope()) { 1344 declaration_scope->is_block_scope()) {
1340 // Declare the variable in the function scope. 1345 // Declare the variable in the function scope.
1341 var = declaration_scope->LocalLookup(name); 1346 var = declaration_scope->LocalLookup(name);
1342 if (var == NULL) { 1347 if (var == NULL) {
1343 // Declare the name. 1348 // Declare the name.
1344 var = declaration_scope->DeclareLocal(name, mode); 1349 var = declaration_scope->DeclareLocal(name, mode);
1345 } else { 1350 } else {
1346 // The name was declared before; check for conflicting re-declarations. 1351 // The name was declared before; check for conflicting re-declarations.
1347 // We have a conflict if either of the declarations is not a var. There 1352 // We have a conflict if either of the declarations is not a var. There
1348 // is similar code in runtime.cc in the Declare functions. 1353 // is similar code in runtime.cc in the Declare functions. Also the
1354 // function CheckNonConflictingScope checks for conflicting hoisting
1355 // of var declared variables.
Lasse Reichstein 2011/09/01 07:34:04 This checks only for a redeclaration in the same s
Steven 2011/09/01 15:01:33 Yes. Clarified it in the comment. On 2011/09/01 07
1349 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) { 1356 if ((mode != Variable::VAR) || (var->mode() != Variable::VAR)) {
1350 // We only have vars, consts and lets in declarations. 1357 // We only have vars, consts and lets in declarations.
1351 ASSERT(var->mode() == Variable::VAR || 1358 ASSERT(var->mode() == Variable::VAR ||
1352 var->mode() == Variable::CONST || 1359 var->mode() == Variable::CONST ||
1353 var->mode() == Variable::LET); 1360 var->mode() == Variable::LET);
1361 if (harmony_block_scoping_) {
1362 // In harmony mode we treat re-declarations as early errors. See
1363 // ES5 16 for a definition of early errors.
1364 SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
1365 const char* elms[2] = { "Variable", *c_string };
1366 Vector<const char*> args(elms, 2);
1367 ReportMessage("redeclaration", args);
1368 *ok = false;
1369 return NULL;
1370 }
1354 const char* type = (var->mode() == Variable::VAR) ? "var" : 1371 const char* type = (var->mode() == Variable::VAR) ? "var" :
1355 (var->mode() == Variable::CONST) ? "const" : "let"; 1372 (var->mode() == Variable::CONST) ? "const" : "let";
1356 Handle<String> type_string = 1373 Handle<String> type_string =
1357 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED); 1374 isolate()->factory()->NewStringFromUtf8(CStrVector(type), TENURED);
1358 Expression* expression = 1375 Expression* expression =
1359 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(), 1376 NewThrowTypeError(isolate()->factory()->redeclaration_symbol(),
1360 type_string, name); 1377 type_string, name);
1361 declaration_scope->SetIllegalRedeclaration(expression); 1378 declaration_scope->SetIllegalRedeclaration(expression);
1362 } 1379 }
1363 } 1380 }
1364 } 1381 }
1365 1382
1366 // We add a declaration node for every declaration. The compiler 1383 // We add a declaration node for every declaration. The compiler
1367 // will only generate code if necessary. In particular, declarations 1384 // will only generate code if necessary. In particular, declarations
1368 // for inner local variables that do not represent functions won't 1385 // for inner local variables that do not represent functions won't
1369 // result in any generated code. 1386 // result in any generated code.
1370 // 1387 //
1371 // Note that we always add an unresolved proxy even if it's not 1388 // Note that we always add an unresolved proxy even if it's not
1372 // used, simply because we don't know in this method (w/o extra 1389 // used, simply because we don't know in this method (w/o extra
1373 // parameters) if the proxy is needed or not. The proxy will be 1390 // parameters) if the proxy is needed or not. The proxy will be
1374 // bound during variable resolution time unless it was pre-bound 1391 // bound during variable resolution time unless it was pre-bound
1375 // below. 1392 // below.
1376 // 1393 //
1377 // WARNING: This will lead to multiple declaration nodes for the 1394 // WARNING: This will lead to multiple declaration nodes for the
1378 // same variable if it is declared several times. This is not a 1395 // same variable if it is declared several times. This is not a
1379 // semantic issue as long as we keep the source order, but it may be 1396 // semantic issue as long as we keep the source order, but it may be
1380 // a performance issue since it may lead to repeated 1397 // a performance issue since it may lead to repeated
1381 // Runtime::DeclareContextSlot() calls. 1398 // Runtime::DeclareContextSlot() calls.
1382 VariableProxy* proxy = declaration_scope->NewUnresolved(name, false); 1399 VariableProxy* proxy = declaration_scope->NewUnresolved(name, false);
1383 declaration_scope->AddDeclaration(new(zone()) Declaration(proxy, mode, fun)); 1400 declaration_scope->AddDeclaration(
1401 new(zone()) Declaration(proxy, mode, fun, top_scope_));
1384 1402
1385 // For global const variables we bind the proxy to a variable. 1403 // For global const variables we bind the proxy to a variable.
1386 if (mode == Variable::CONST && declaration_scope->is_global_scope()) { 1404 if (mode == Variable::CONST && declaration_scope->is_global_scope()) {
1387 ASSERT(resolve); // should be set by all callers 1405 ASSERT(resolve); // should be set by all callers
1388 Variable::Kind kind = Variable::NORMAL; 1406 Variable::Kind kind = Variable::NORMAL;
1389 var = new(zone()) Variable(declaration_scope, 1407 var = new(zone()) Variable(declaration_scope,
1390 name, 1408 name,
1391 Variable::CONST, 1409 Variable::CONST,
1392 true, 1410 true,
1393 kind); 1411 kind);
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
2200 Expect(Token::RPAREN, CHECK_OK); 2218 Expect(Token::RPAREN, CHECK_OK);
2201 2219
2202 if (peek() == Token::LBRACE) { 2220 if (peek() == Token::LBRACE) {
2203 // Rewrite the catch body { B } to a block: 2221 // Rewrite the catch body { B } to a block:
2204 // { { B } ExitContext; }. 2222 // { { B } ExitContext; }.
2205 Target target(&this->target_stack_, &catch_collector); 2223 Target target(&this->target_stack_, &catch_collector);
2206 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with()); 2224 catch_scope = NewScope(top_scope_, Scope::CATCH_SCOPE, inside_with());
2207 if (top_scope_->is_strict_mode()) { 2225 if (top_scope_->is_strict_mode()) {
2208 catch_scope->EnableStrictMode(); 2226 catch_scope->EnableStrictMode();
2209 } 2227 }
2210 catch_variable = catch_scope->DeclareLocal(name, Variable::VAR); 2228 Variable::Mode mode = harmony_block_scoping_
2229 ? Variable::LET : Variable::VAR;
2230 catch_variable = catch_scope->DeclareLocal(name, mode);
2211 catch_block = new(zone()) Block(isolate(), NULL, 2, false); 2231 catch_block = new(zone()) Block(isolate(), NULL, 2, false);
2212 2232
2213 Scope* saved_scope = top_scope_; 2233 Scope* saved_scope = top_scope_;
2214 top_scope_ = catch_scope; 2234 top_scope_ = catch_scope;
2215 Block* catch_body = ParseBlock(NULL, CHECK_OK); 2235 Block* catch_body = ParseBlock(NULL, CHECK_OK);
2216 top_scope_ = saved_scope; 2236 top_scope_ = saved_scope;
2217 catch_block->AddStatement(catch_body); 2237 catch_block->AddStatement(catch_body);
2218 catch_block->AddStatement(new(zone()) ExitContextStatement()); 2238 catch_block->AddStatement(new(zone()) ExitContextStatement());
2219 } else { 2239 } else {
2220 Expect(Token::LBRACE, CHECK_OK); 2240 Expect(Token::LBRACE, CHECK_OK);
(...skipping 1508 matching lines...) Expand 10 before | Expand all | Expand 10 after
3729 name_loc = scanner().location(); 3749 name_loc = scanner().location();
3730 } 3750 }
3731 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) { 3751 if (!dupe_loc.IsValid() && top_scope_->IsDeclared(param_name)) {
3732 has_duplicate_parameters = true; 3752 has_duplicate_parameters = true;
3733 dupe_loc = scanner().location(); 3753 dupe_loc = scanner().location();
3734 } 3754 }
3735 if (!reserved_loc.IsValid() && is_strict_reserved) { 3755 if (!reserved_loc.IsValid() && is_strict_reserved) {
3736 reserved_loc = scanner().location(); 3756 reserved_loc = scanner().location();
3737 } 3757 }
3738 3758
3739 top_scope_->DeclareParameter(param_name); 3759 top_scope_->DeclareParameter(param_name,
3760 harmony_block_scoping_
3761 ? Variable::LET
3762 : Variable::VAR);
3740 num_parameters++; 3763 num_parameters++;
3741 if (num_parameters > kMaxNumFunctionParameters) { 3764 if (num_parameters > kMaxNumFunctionParameters) {
3742 ReportMessageAt(scanner().location(), "too_many_parameters", 3765 ReportMessageAt(scanner().location(), "too_many_parameters",
3743 Vector<const char*>::empty()); 3766 Vector<const char*>::empty());
3744 *ok = false; 3767 *ok = false;
3745 return NULL; 3768 return NULL;
3746 } 3769 }
3747 done = (peek() == Token::RPAREN); 3770 done = (peek() == Token::RPAREN);
3748 if (!done) Expect(Token::COMMA, CHECK_OK); 3771 if (!done) Expect(Token::COMMA, CHECK_OK);
3749 } 3772 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
3856 if (reserved_loc.IsValid()) { 3879 if (reserved_loc.IsValid()) {
3857 ReportMessageAt(reserved_loc, "strict_reserved_word", 3880 ReportMessageAt(reserved_loc, "strict_reserved_word",
3858 Vector<const char*>::empty()); 3881 Vector<const char*>::empty());
3859 *ok = false; 3882 *ok = false;
3860 return NULL; 3883 return NULL;
3861 } 3884 }
3862 CheckOctalLiteral(start_pos, end_pos, CHECK_OK); 3885 CheckOctalLiteral(start_pos, end_pos, CHECK_OK);
3863 } 3886 }
3864 } 3887 }
3865 3888
3889 if (harmony_block_scoping_) {
3890 CheckConflictingVarDeclarations(scope, CHECK_OK);
3891 }
3892
3866 FunctionLiteral* function_literal = 3893 FunctionLiteral* function_literal =
3867 new(zone()) FunctionLiteral(isolate(), 3894 new(zone()) FunctionLiteral(isolate(),
3868 function_name, 3895 function_name,
3869 scope, 3896 scope,
3870 body, 3897 body,
3871 materialized_literal_count, 3898 materialized_literal_count,
3872 expected_property_count, 3899 expected_property_count,
3873 only_simple_this_property_assignments, 3900 only_simple_this_property_assignments,
3874 this_property_assignments, 3901 this_property_assignments,
3875 num_parameters, 3902 num_parameters,
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
4062 beg_pos <= octal.beg_pos && 4089 beg_pos <= octal.beg_pos &&
4063 octal.end_pos <= end_pos) { 4090 octal.end_pos <= end_pos) {
4064 ReportMessageAt(octal, "strict_octal_literal", 4091 ReportMessageAt(octal, "strict_octal_literal",
4065 Vector<const char*>::empty()); 4092 Vector<const char*>::empty());
4066 scanner().clear_octal_position(); 4093 scanner().clear_octal_position();
4067 *ok = false; 4094 *ok = false;
4068 } 4095 }
4069 } 4096 }
4070 4097
4071 4098
4099 void Parser::CheckConflictingVarDeclarations(Scope* scope, bool* ok) {
4100 Declaration* decl = scope->CheckConflictingVarDeclarations();
4101 if (decl != NULL) {
4102 // In harmony mode we treat conflicting variable bindinds as early
4103 // errors. See ES5 16 for a definition of early errors.
4104 Handle<String> name = decl->proxy()->name();
4105 SmartPointer<char> c_string = name->ToCString(DISALLOW_NULLS);
4106 const char* elms[2] = { "Variable", *c_string };
4107 Vector<const char*> args(elms, 2);
4108 ReportMessage("redeclaration", args);
Steven 2011/08/31 21:33:00 This ReportMessage should rather be a ReportMessag
4109 *ok = false;
4110 }
4111 }
4112
4113
4072 // This function reads an identifier name and determines whether or not it 4114 // This function reads an identifier name and determines whether or not it
4073 // is 'get' or 'set'. 4115 // is 'get' or 'set'.
4074 Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get, 4116 Handle<String> Parser::ParseIdentifierNameOrGetOrSet(bool* is_get,
4075 bool* is_set, 4117 bool* is_set,
4076 bool* ok) { 4118 bool* ok) {
4077 Handle<String> result = ParseIdentifierName(ok); 4119 Handle<String> result = ParseIdentifierName(ok);
4078 if (!*ok) return Handle<String>(); 4120 if (!*ok) return Handle<String>();
4079 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) { 4121 if (scanner().is_literal_ascii() && scanner().literal_length() == 3) {
4080 const char* token = scanner().literal_ascii_string().start(); 4122 const char* token = scanner().literal_ascii_string().start();
4081 *is_get = strncmp(token, "get", 3) == 0; 4123 *is_get = strncmp(token, "get", 3) == 0;
(...skipping 1101 matching lines...) Expand 10 before | Expand all | Expand 10 after
5183 result = parser.ParseProgram(source, 5225 result = parser.ParseProgram(source,
5184 info->is_global(), 5226 info->is_global(),
5185 info->StrictMode()); 5227 info->StrictMode());
5186 } 5228 }
5187 } 5229 }
5188 info->SetFunction(result); 5230 info->SetFunction(result);
5189 return (result != NULL); 5231 return (result != NULL);
5190 } 5232 }
5191 5233
5192 } } // namespace v8::internal 5234 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698