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

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