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

Side by Side Diff: src/parser.cc

Issue 22901010: Fix scoping of function declarations in eval inside non-trivial local scope (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 7 years, 4 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
« no previous file with comments | « src/parser.h ('k') | src/scopes.cc » ('j') | no next file with comments »
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 // 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 523 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 534
535 // ---------------------------------------------------------------------------- 535 // ----------------------------------------------------------------------------
536 // Implementation of Parser 536 // Implementation of Parser
537 537
538 Parser::Parser(CompilationInfo* info) 538 Parser::Parser(CompilationInfo* info)
539 : isolate_(info->isolate()), 539 : isolate_(info->isolate()),
540 symbol_cache_(0, info->zone()), 540 symbol_cache_(0, info->zone()),
541 script_(info->script()), 541 script_(info->script()),
542 scanner_(isolate_->unicode_cache()), 542 scanner_(isolate_->unicode_cache()),
543 reusable_preparser_(NULL), 543 reusable_preparser_(NULL),
544 top_scope_(NULL), 544 top_scope_(NULL),
Michael Starzinger 2013/08/23 08:56:30 Missing initialization of original_scope_(NULL) he
rossberg 2013/08/23 09:09:21 Done.
545 current_function_state_(NULL), 545 current_function_state_(NULL),
546 target_stack_(NULL), 546 target_stack_(NULL),
547 extension_(info->extension()), 547 extension_(info->extension()),
548 pre_parse_data_(NULL), 548 pre_parse_data_(NULL),
549 fni_(NULL), 549 fni_(NULL),
550 allow_natives_syntax_(false), 550 allow_natives_syntax_(false),
551 allow_lazy_(false), 551 allow_lazy_(false),
552 allow_generators_(false), 552 allow_generators_(false),
553 allow_for_of_(false), 553 allow_for_of_(false),
554 stack_overflow_(false), 554 stack_overflow_(false),
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
615 if (pre_parse_data_ != NULL) pre_parse_data_->Initialize(); 615 if (pre_parse_data_ != NULL) pre_parse_data_->Initialize();
616 616
617 Handle<String> no_name = isolate()->factory()->empty_string(); 617 Handle<String> no_name = isolate()->factory()->empty_string();
618 618
619 FunctionLiteral* result = NULL; 619 FunctionLiteral* result = NULL;
620 { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); 620 { Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
621 info->SetGlobalScope(scope); 621 info->SetGlobalScope(scope);
622 if (!info->context().is_null()) { 622 if (!info->context().is_null()) {
623 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone()); 623 scope = Scope::DeserializeScopeChain(*info->context(), scope, zone());
624 } 624 }
625 original_scope_ = scope;
625 if (info->is_eval()) { 626 if (info->is_eval()) {
626 if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) { 627 if (!scope->is_global_scope() || info->language_mode() != CLASSIC_MODE) {
627 scope = NewScope(scope, EVAL_SCOPE); 628 scope = NewScope(scope, EVAL_SCOPE);
628 } 629 }
629 } else if (info->is_global()) { 630 } else if (info->is_global()) {
630 scope = NewScope(scope, GLOBAL_SCOPE); 631 scope = NewScope(scope, GLOBAL_SCOPE);
631 } 632 }
632 scope->set_start_position(0); 633 scope->set_start_position(0);
633 scope->set_end_position(source->length()); 634 scope->set_end_position(source->length());
634 635
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
742 FunctionLiteral* result = NULL; 743 FunctionLiteral* result = NULL;
743 744
744 { 745 {
745 // Parse the function literal. 746 // Parse the function literal.
746 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE); 747 Scope* scope = NewScope(top_scope_, GLOBAL_SCOPE);
747 info()->SetGlobalScope(scope); 748 info()->SetGlobalScope(scope);
748 if (!info()->closure().is_null()) { 749 if (!info()->closure().is_null()) {
749 scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope, 750 scope = Scope::DeserializeScopeChain(info()->closure()->context(), scope,
750 zone()); 751 zone());
751 } 752 }
753 original_scope_ = scope;
752 FunctionState function_state(this, scope, isolate()); 754 FunctionState function_state(this, scope, isolate());
753 ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode()); 755 ASSERT(scope->language_mode() != STRICT_MODE || !info()->is_classic_mode());
754 ASSERT(scope->language_mode() != EXTENDED_MODE || 756 ASSERT(scope->language_mode() != EXTENDED_MODE ||
755 info()->is_extended_mode()); 757 info()->is_extended_mode());
756 ASSERT(info()->language_mode() == shared_info->language_mode()); 758 ASSERT(info()->language_mode() == shared_info->language_mode());
757 scope->SetLanguageMode(shared_info->language_mode()); 759 scope->SetLanguageMode(shared_info->language_mode());
758 FunctionLiteral::FunctionType function_type = shared_info->is_expression() 760 FunctionLiteral::FunctionType function_type = shared_info->is_expression()
759 ? (shared_info->is_anonymous() 761 ? (shared_info->is_anonymous()
760 ? FunctionLiteral::ANONYMOUS_EXPRESSION 762 ? FunctionLiteral::ANONYMOUS_EXPRESSION
761 : FunctionLiteral::NAMED_EXPRESSION) 763 : FunctionLiteral::NAMED_EXPRESSION)
(...skipping 3510 matching lines...) Expand 10 before | Expand all | Expand 10 after
4272 4274
4273 // We want a non-null handle as the function name. 4275 // We want a non-null handle as the function name.
4274 if (should_infer_name) { 4276 if (should_infer_name) {
4275 function_name = isolate()->factory()->empty_string(); 4277 function_name = isolate()->factory()->empty_string();
4276 } 4278 }
4277 4279
4278 int num_parameters = 0; 4280 int num_parameters = 0;
4279 // Function declarations are function scoped in normal mode, so they are 4281 // Function declarations are function scoped in normal mode, so they are
4280 // hoisted. In harmony block scoping mode they are block scoped, so they 4282 // hoisted. In harmony block scoping mode they are block scoped, so they
4281 // are not hoisted. 4283 // are not hoisted.
4284 //
4285 // One tricky case are function declarations in a local sloppy-mode eval:
4286 // their declaration is hoisted, but they still see the local scope. E.g.,
4287 //
4288 // function() {
4289 // var x=0
4290 // try {throw 1} catch (x) { eval("function g() { return x }") }
Michael Starzinger 2013/08/23 08:56:30 nit: A few white spaces missing here and in the li
rossberg 2013/08/23 09:09:21 Done.
4291 // return g()
4292 // }
4293 //
4294 // needs to return 1. To distinguish such cases, we need to detect
4295 // (1) whether a function stems from a sloppy eval, and
4296 // (2) whether it actually hoists across the eval.
4297 // Unfortunately, we do not represent sloppy eval scopes, so we do not have
4298 // either information available directly, especially not when lazily compiling
4299 // a function like 'g'. We hence rely on the following invariants:
4300 // - (1) is the case iff the innermost scope of the deserialized scope chain
4301 // under which we compile is _not_ a declaration scope. This holds because
4302 // in all normal cases, function declarations are fully hoisted to a
4303 // declaration scope and compiled relative to that.
4304 // - (2) is the case iff the current declaration scope is still the original
4305 // one relative to the deserialized scope chain. Otherwise we must be
4306 // compiling a function in an inner declaration scope in the eval, e.g. a
4307 // nested function, and hoisting works normally relative to that.
4308 Scope* declaration_scope = top_scope_->DeclarationScope();
4309 Scope* original_declaration_scope = original_scope_->DeclarationScope();
4282 Scope* scope = 4310 Scope* scope =
4283 (function_type == FunctionLiteral::DECLARATION && !is_extended_mode()) 4311 function_type == FunctionLiteral::DECLARATION && !is_extended_mode() &&
4284 ? NewScope(top_scope_->DeclarationScope(), FUNCTION_SCOPE) 4312 (original_scope_ == original_declaration_scope ||
4285 : NewScope(top_scope_, FUNCTION_SCOPE); 4313 declaration_scope != original_declaration_scope)
4314 ? NewScope(declaration_scope, FUNCTION_SCOPE)
4315 : NewScope(top_scope_, FUNCTION_SCOPE);
4286 ZoneList<Statement*>* body = NULL; 4316 ZoneList<Statement*>* body = NULL;
4287 int materialized_literal_count = -1; 4317 int materialized_literal_count = -1;
4288 int expected_property_count = -1; 4318 int expected_property_count = -1;
4289 int handler_count = 0; 4319 int handler_count = 0;
4290 FunctionLiteral::ParameterFlag duplicate_parameters = 4320 FunctionLiteral::ParameterFlag duplicate_parameters =
4291 FunctionLiteral::kNoDuplicateParameters; 4321 FunctionLiteral::kNoDuplicateParameters;
4292 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_ 4322 FunctionLiteral::IsParenthesizedFlag parenthesized = parenthesized_function_
4293 ? FunctionLiteral::kIsParenthesized 4323 ? FunctionLiteral::kIsParenthesized
4294 : FunctionLiteral::kNotParenthesized; 4324 : FunctionLiteral::kNotParenthesized;
4295 FunctionLiteral::IsGeneratorFlag generator = is_generator 4325 FunctionLiteral::IsGeneratorFlag generator = is_generator
(...skipping 1637 matching lines...) Expand 10 before | Expand all | Expand 10 after
5933 ASSERT(info()->isolate()->has_pending_exception()); 5963 ASSERT(info()->isolate()->has_pending_exception());
5934 } else { 5964 } else {
5935 result = ParseProgram(); 5965 result = ParseProgram();
5936 } 5966 }
5937 } 5967 }
5938 info()->SetFunction(result); 5968 info()->SetFunction(result);
5939 return (result != NULL); 5969 return (result != NULL);
5940 } 5970 }
5941 5971
5942 } } // namespace v8::internal 5972 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/parser.h ('k') | src/scopes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698