Commit 01c2b455 authored by marja's avatar marja Committed by Commit bot

[parser] Skipping inner funcs: produce the same scopes / variables for loops.

BUG=v8:5516
R=vogelheim@chromium.org

Review-Url: https://codereview.chromium.org/2673313003
Cr-Commit-Position: refs/heads/master@{#42957}
parent ea7dc87c
...@@ -1967,14 +1967,13 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info, ...@@ -1967,14 +1967,13 @@ void Parser::DesugarBindingInForEachStatement(ForInfo* for_info,
bool is_for_var_of = bool is_for_var_of =
for_info->mode == ForEachStatement::ITERATE && for_info->mode == ForEachStatement::ITERATE &&
for_info->parsing_result.descriptor.mode == VariableMode::VAR; for_info->parsing_result.descriptor.mode == VariableMode::VAR;
bool collect_names =
IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
is_for_var_of;
PatternRewriter::DeclareAndInitializeVariables( PatternRewriter::DeclareAndInitializeVariables(
this, each_initialization_block, &descriptor, &decl, this, each_initialization_block, &descriptor, &decl,
(IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) || collect_names ? &for_info->bound_names : nullptr, CHECK_OK_VOID);
is_for_var_of)
? &for_info->bound_names
: nullptr,
CHECK_OK_VOID);
// Annex B.3.5 prohibits the form // Annex B.3.5 prohibits the form
// `try {} catch(e) { for (var e of {}); }` // `try {} catch(e) { for (var e of {}); }`
......
...@@ -307,6 +307,7 @@ void PreParser::DeclareAndInitializeVariables( ...@@ -307,6 +307,7 @@ void PreParser::DeclareAndInitializeVariables(
ZoneList<const AstRawString*>* names, bool* ok) { ZoneList<const AstRawString*>* names, bool* ok) {
if (declaration->pattern.variables_ != nullptr) { if (declaration->pattern.variables_ != nullptr) {
DCHECK(FLAG_lazy_inner_functions); DCHECK(FLAG_lazy_inner_functions);
DCHECK(track_unresolved_variables_);
for (auto variable : *(declaration->pattern.variables_)) { for (auto variable : *(declaration->pattern.variables_)) {
declaration_descriptor->scope->RemoveUnresolved(variable); declaration_descriptor->scope->RemoveUnresolved(variable);
scope()->DeclareVariableName(variable->raw_name(), scope()->DeclareVariableName(variable->raw_name(),
......
...@@ -1320,14 +1320,30 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1320,14 +1320,30 @@ class PreParser : public ParserBase<PreParser> {
PreParserExpression* each_variable, bool* ok) { PreParserExpression* each_variable, bool* ok) {
if (track_unresolved_variables_) { if (track_unresolved_variables_) {
DCHECK(for_info->parsing_result.declarations.length() == 1); DCHECK(for_info->parsing_result.declarations.length() == 1);
bool is_for_var_of =
for_info->mode == ForEachStatement::ITERATE &&
for_info->parsing_result.descriptor.mode == VariableMode::VAR;
bool collect_names =
IsLexicalVariableMode(for_info->parsing_result.descriptor.mode) ||
is_for_var_of;
DeclareAndInitializeVariables( DeclareAndInitializeVariables(
PreParserStatement::Default(), &for_info->parsing_result.descriptor, PreParserStatement::Default(), &for_info->parsing_result.descriptor,
&for_info->parsing_result.declarations[0], nullptr, ok); &for_info->parsing_result.declarations[0],
collect_names ? &for_info->bound_names : nullptr, ok);
} }
} }
V8_INLINE PreParserStatement CreateForEachStatementTDZ( V8_INLINE PreParserStatement CreateForEachStatementTDZ(
PreParserStatement init_block, const ForInfo& for_info, bool* ok) { PreParserStatement init_block, const ForInfo& for_info, bool* ok) {
if (track_unresolved_variables_) {
if (IsLexicalVariableMode(for_info.parsing_result.descriptor.mode)) {
for (auto name : for_info.bound_names) {
scope()->DeclareVariableName(name, LET);
}
return PreParserStatement::Default();
}
}
return init_block; return init_block;
} }
...@@ -1337,9 +1353,11 @@ class PreParser : public ParserBase<PreParser> { ...@@ -1337,9 +1353,11 @@ class PreParser : public ParserBase<PreParser> {
PreParserStatement body, Scope* inner_scope, const ForInfo& for_info, PreParserStatement body, Scope* inner_scope, const ForInfo& for_info,
bool* ok) { bool* ok) {
// See Parser::DesugarLexicalBindingsInForStatement. // See Parser::DesugarLexicalBindingsInForStatement.
for (int i = 0; i < for_info.bound_names.length(); i++) { if (track_unresolved_variables_) {
inner_scope->DeclareVariableName(for_info.bound_names[i], for (auto name : for_info.bound_names) {
for_info.parsing_result.descriptor.mode); inner_scope->DeclareVariableName(
name, for_info.parsing_result.descriptor.mode);
}
} }
return loop; return loop;
} }
......
...@@ -9211,11 +9211,13 @@ TEST(PreParserScopeAnalysis) { ...@@ -9211,11 +9211,13 @@ TEST(PreParserScopeAnalysis) {
const char* params; const char* params;
const char* source; const char* source;
} inners[] = { } inners[] = {
// Simple cases
{"", "var1;"}, {"", "var1;"},
{"", "var1 = 5;"}, {"", "var1 = 5;"},
{"", "if (true) {}"}, {"", "if (true) {}"},
{"", "function f1() {}"}, {"", "function f1() {}"},
// Var declarations and assignments.
{"", "var var1;"}, {"", "var var1;"},
{"", "var var1; var1 = 5;"}, {"", "var var1; var1 = 5;"},
{"", "if (true) { var var1; }"}, {"", "if (true) { var var1; }"},
...@@ -9224,6 +9226,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9224,6 +9226,7 @@ TEST(PreParserScopeAnalysis) {
{"", "var var1; var1 = 5; function f() { var1; }"}, {"", "var var1; var1 = 5; function f() { var1; }"},
{"", "var var1; function f() { var1 = 5; }"}, {"", "var var1; function f() { var1 = 5; }"},
// Let declarations and assignments.
{"", "let var1;"}, {"", "let var1;"},
{"", "let var1; var1 = 5;"}, {"", "let var1; var1 = 5;"},
{"", "if (true) { let var1; }"}, {"", "if (true) { let var1; }"},
...@@ -9232,10 +9235,12 @@ TEST(PreParserScopeAnalysis) { ...@@ -9232,10 +9235,12 @@ TEST(PreParserScopeAnalysis) {
{"", "let var1; var1 = 5; function f() { var1; }"}, {"", "let var1; var1 = 5; function f() { var1; }"},
{"", "let var1; function f() { var1 = 5; }"}, {"", "let var1; function f() { var1 = 5; }"},
// Const declarations.
{"", "const var1 = 5;"}, {"", "const var1 = 5;"},
{"", "if (true) { const var1 = 5; }"}, {"", "if (true) { const var1 = 5; }"},
{"", "const var1 = 5; function f() { var1; }"}, {"", "const var1 = 5; function f() { var1; }"},
// Redeclarations.
{"", "var var1; var var1;"}, {"", "var var1; var var1;"},
{"", "var var1; var var1; var1 = 5;"}, {"", "var var1; var var1; var1 = 5;"},
{"", "var var1; if (true) { var var1; }"}, {"", "var var1; if (true) { var var1; }"},
...@@ -9245,6 +9250,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9245,6 +9250,7 @@ TEST(PreParserScopeAnalysis) {
{"", "var var1; var var1; function f() { var1; }"}, {"", "var var1; var var1; function f() { var1; }"},
{"", "var var1; var var1; function f() { var1 = 5; }"}, {"", "var var1; var var1; function f() { var1 = 5; }"},
// Shadowing declarations.
{"", "var var1; if (true) { var var1; }"}, {"", "var var1; if (true) { var var1; }"},
{"", "var var1; if (true) { let var1; }"}, {"", "var var1; if (true) { let var1; }"},
{"", "let var1; if (true) { let var1; }"}, {"", "let var1; if (true) { let var1; }"},
...@@ -9252,6 +9258,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9252,6 +9258,7 @@ TEST(PreParserScopeAnalysis) {
{"", "var var1; if (true) { const var1 = 0; }"}, {"", "var var1; if (true) { const var1 = 0; }"},
{"", "const var1 = 0; if (true) { const var1 = 0; }"}, {"", "const var1 = 0; if (true) { const var1 = 0; }"},
// Variable called "arguments"
{"", "arguments;"}, {"", "arguments;"},
{"", "arguments = 5;"}, {"", "arguments = 5;"},
{"", "function f() { arguments; }"}, {"", "function f() { arguments; }"},
...@@ -9277,6 +9284,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9277,6 +9284,7 @@ TEST(PreParserScopeAnalysis) {
{"", "if (true) { const arguments = 5; }"}, {"", "if (true) { const arguments = 5; }"},
{"", "const arguments = 5; function f() { arguments; }"}, {"", "const arguments = 5; function f() { arguments; }"},
// Destructuring declarations.
{"", "var [var1, var2] = [1, 2];"}, {"", "var [var1, var2] = [1, 2];"},
{"", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"}, {"", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
{"", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"}, {"", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
...@@ -9307,6 +9315,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9307,6 +9315,7 @@ TEST(PreParserScopeAnalysis) {
"const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"}, "const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
{"", "const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"}, {"", "const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
// Referencing the function variable.
{"", "inner;"}, {"", "inner;"},
{"", "function f1() { f1; }"}, {"", "function f1() { f1; }"},
{"", "function f1() { inner; }"}, {"", "function f1() { inner; }"},
...@@ -9315,12 +9324,14 @@ TEST(PreParserScopeAnalysis) { ...@@ -9315,12 +9324,14 @@ TEST(PreParserScopeAnalysis) {
{"", "function f1() {} function f1() {}"}, {"", "function f1() {} function f1() {}"},
{"", "var f1; function f1() {}"}, {"", "var f1; function f1() {}"},
// Assigning to the function variable.
{"", "inner = 3;"}, {"", "inner = 3;"},
{"", "function f1() { f1 = 3; }"}, {"", "function f1() { f1 = 3; }"},
{"", "function f1() { f1; } f1 = 3;"}, {"", "function f1() { f1; } f1 = 3;"},
{"", "function arguments() {} arguments = 8"}, {"", "function arguments() {} arguments = 8"},
{"", "function f1() {} f1 = 3; function f1() {}"}, {"", "function f1() {} f1 = 3; function f1() {}"},
// Evals.
{"", "var var1; eval('');"}, {"", "var var1; eval('');"},
{"", "var var1; function f1() { eval(''); }"}, {"", "var var1; function f1() { eval(''); }"},
{"", "let var1; eval('');"}, {"", "let var1; eval('');"},
...@@ -9328,6 +9339,7 @@ TEST(PreParserScopeAnalysis) { ...@@ -9328,6 +9339,7 @@ TEST(PreParserScopeAnalysis) {
{"", "const var1 = 10; eval('');"}, {"", "const var1 = 10; eval('');"},
{"", "const var1 = 10; function f1() { eval(''); }"}, {"", "const var1 = 10; function f1() { eval(''); }"},
// Standard for loops.
{"", "for (var var1 = 0; var1 < 10; ++var1) { }"}, {"", "for (var var1 = 0; var1 < 10; ++var1) { }"},
{"", "for (let var1 = 0; var1 < 10; ++var1) { }"}, {"", "for (let var1 = 0; var1 < 10; ++var1) { }"},
{"", "for (const var1 = 0; var1 < 10; ++var1) { }"}, {"", "for (const var1 = 0; var1 < 10; ++var1) { }"},
...@@ -9348,6 +9360,85 @@ TEST(PreParserScopeAnalysis) { ...@@ -9348,6 +9360,85 @@ TEST(PreParserScopeAnalysis) {
"'use strict'; for (const var1 = 0; var1 < 10; ++var1) { function foo() " "'use strict'; for (const var1 = 0; var1 < 10; ++var1) { function foo() "
"{ var1; } }"}, "{ var1; } }"},
// For of loops
{"", "for (var1 of [1, 2]) { }"},
{"", "for (var var1 of [1, 2]) { }"},
{"", "for (let var1 of [1, 2]) { }"},
{"", "for (const var1 of [1, 2]) { }"},
{"", "for (var1 of [1, 2]) { var1; }"},
{"", "for (var var1 of [1, 2]) { var1; }"},
{"", "for (let var1 of [1, 2]) { var1; }"},
{"", "for (const var1 of [1, 2]) { var1; }"},
{"", "for (var1 of [1, 2]) { var1 = 0; }"},
{"", "for (var var1 of [1, 2]) { var1 = 0; }"},
{"", "for (let var1 of [1, 2]) { var1 = 0; }"},
{"", "for (const var1 of [1, 2]) { var1 = 0; }"},
{"", "for (var1 of [1, 2]) { function foo() { var1; } }"},
{"", "for (var var1 of [1, 2]) { function foo() { var1; } }"},
{"", "for (let var1 of [1, 2]) { function foo() { var1; } }"},
{"", "for (const var1 of [1, 2]) { function foo() { var1; } }"},
{"", "for (var1 of [1, 2]) { function foo() { var1 = 0; } }"},
{"", "for (var var1 of [1, 2]) { function foo() { var1 = 0; } }"},
{"", "for (let var1 of [1, 2]) { function foo() { var1 = 0; } }"},
{"", "for (const var1 of [1, 2]) { function foo() { var1 = 0; } }"},
// For in loops
{"", "for (var1 in {a: 6}) { }"},
{"", "for (var var1 in {a: 6}) { }"},
{"", "for (let var1 in {a: 6}) { }"},
{"", "for (const var1 in {a: 6}) { }"},
{"", "for (var1 in {a: 6}) { var1; }"},
{"", "for (var var1 in {a: 6}) { var1; }"},
{"", "for (let var1 in {a: 6}) { var1; }"},
{"", "for (const var1 in {a: 6}) { var1; }"},
{"", "for (var1 in {a: 6}) { var1 = 0; }"},
{"", "for (var var1 in {a: 6}) { var1 = 0; }"},
{"", "for (let var1 in {a: 6}) { var1 = 0; }"},
{"", "for (const var1 in {a: 6}) { var1 = 0; }"},
{"", "for (var1 in {a: 6}) { function foo() { var1; } }"},
{"", "for (var var1 in {a: 6}) { function foo() { var1; } }"},
{"", "for (let var1 in {a: 6}) { function foo() { var1; } }"},
{"", "for (const var1 in {a: 6}) { function foo() { var1; } }"},
{"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
{"", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"},
// Loops without declarations
{"", "var var1 = 0; for ( ; var1 < 2; ++var1) { }"},
{"",
"var var1 = 0; for ( ; var1 < 2; ++var1) { function foo() { var1; } }"},
{"", "var var1 = 0; for ( ; var1 > 2; ) { }"},
{"", "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1; } }"},
{"",
"var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1 = 6; } }"},
{"", "var var1 = 0; for(var1; var1 < 2; ++var1) { }"},
{"",
"var var1 = 0; for (var1; var1 < 2; ++var1) { function foo() { var1; } "
"}"},
{"", "var var1 = 0; for (var1; var1 > 2; ) { }"},
{"", "var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1; } }"},
{"",
"var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1 = 6; } }"},
// FIXME(marja): Add test cases for special variables (this, arguments
// etc) referred to in the for loop conditions.
// Sloppy block functions.
{"", "if (true) { function f1() {} }"}, {"", "if (true) { function f1() {} }"},
{"", "if (true) { function f1() {} function f1() {} }"}, {"", "if (true) { function f1() {} function f1() {} }"},
{"", "if (true) { if (true) { function f1() {} } }"}, {"", "if (true) { if (true) { function f1() {} } }"},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment