[parser] Skipping inner funcs: add more tests.
These tests already pass. BUG=v8:5516 Change-Id: I7f4796cca98aa6c276143d83bcb018a67e0cbe55 Reviewed-on: https://chromium-review.googlesource.com/506193 Commit-Queue: Marja Hölttä <marja@chromium.org> Reviewed-by: Daniel Vogelheim <vogelheim@chromium.org> Cr-Commit-Position: refs/heads/master@{#45327}
This commit is contained in:
parent
a1de6262bf
commit
fab691b8ba
@ -76,45 +76,102 @@ TEST(PreParserScopeAnalysis) {
|
||||
bool strict_outer;
|
||||
bool strict_test_function;
|
||||
bool arrow;
|
||||
std::vector<unsigned> location; // "Directions" to the relevant scope.
|
||||
} outers[] = {
|
||||
// Normal case (test function at the laziness boundary):
|
||||
{"(function outer() { ", "})();", " function test(%s) { %s }",
|
||||
"(function test(%s) { %s })()", false, false, false},
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function test(%s) { %s }",
|
||||
"(function test(%s) { %s })()",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
{0, 0}},
|
||||
|
||||
// Test function deeper:
|
||||
{"(function outer() { ", "})();",
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function inner() { function test(%s) { %s } }",
|
||||
"(function inner() { function test(%s) { %s } })()", false, false,
|
||||
false},
|
||||
"(function inner() { function test(%s) { %s } })()",
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
{0, 0}},
|
||||
|
||||
// Arrow functions (they can never be at the laziness boundary):
|
||||
{"(function outer() { ", "})();", " function inner() { (%s) => { %s } }",
|
||||
"(function inner() { (%s) => { %s } })()", false, false, true},
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function inner() { (%s) => { %s } }",
|
||||
"(function inner() { (%s) => { %s } })()",
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
{0, 0}},
|
||||
|
||||
// Repeat the above mentioned cases w/ outer function declaring itself
|
||||
// strict:
|
||||
{"(function outer() { 'use strict'; ", "})();",
|
||||
" function test(%s) { %s }", "(function test(%s) { %s })()", true, false,
|
||||
false},
|
||||
{"(function outer() { 'use strict'; ", "})();",
|
||||
{"(function outer() { 'use strict'; ",
|
||||
"})();",
|
||||
" function test(%s) { %s }",
|
||||
"(function test(%s) { %s })()",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
{0, 0}},
|
||||
{"(function outer() { 'use strict'; ",
|
||||
"})();",
|
||||
" function inner() { function test(%s) { %s } }",
|
||||
"(function inner() { function test(%s) { %s } })()", true, false, false},
|
||||
{"(function outer() { 'use strict'; ", "})();",
|
||||
"(function inner() { function test(%s) { %s } })()",
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
{0, 0}},
|
||||
{"(function outer() { 'use strict'; ",
|
||||
"})();",
|
||||
" function inner() { (%s) => { %s } }",
|
||||
"(function inner() { (%s) => { %s } })()", true, false, true},
|
||||
"(function inner() { (%s) => { %s } })()",
|
||||
true,
|
||||
false,
|
||||
true,
|
||||
{0, 0}},
|
||||
|
||||
// ... and with the test function declaring itself strict:
|
||||
{"(function outer() { ", "})();",
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function test(%s) { 'use strict'; %s }",
|
||||
"(function test(%s) { 'use strict'; %s })()", false, true, false},
|
||||
{"(function outer() { ", "})();",
|
||||
"(function test(%s) { 'use strict'; %s })()",
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
{0, 0}},
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function inner() { function test(%s) { 'use strict'; %s } }",
|
||||
"(function inner() { function test(%s) { 'use strict'; %s } })()", false,
|
||||
true, false},
|
||||
{"(function outer() { ", "})();",
|
||||
"(function inner() { function test(%s) { 'use strict'; %s } })()",
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
{0, 0}},
|
||||
{"(function outer() { ",
|
||||
"})();",
|
||||
" function inner() { (%s) => { 'use strict'; %s } }",
|
||||
"(function inner() { (%s) => { 'use strict'; %s } })()", false, true,
|
||||
true},
|
||||
"(function inner() { (%s) => { 'use strict'; %s } })()",
|
||||
false,
|
||||
true,
|
||||
true,
|
||||
{0, 0}},
|
||||
|
||||
// Methods containing skippable functions. Cannot test at the laziness
|
||||
// boundary, since there's no way to force eager parsing of a method.
|
||||
{"class MyClass { mymethod() {",
|
||||
"} }",
|
||||
" function test(%s) { %s }",
|
||||
"(function test(%s) { %s })()",
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
// The default constructor is scope 0 inside the class.
|
||||
{0, 1, 0}},
|
||||
|
||||
// FIXME(marja): Generators and async functions
|
||||
};
|
||||
@ -166,6 +223,15 @@ TEST(PreParserScopeAnalysis) {
|
||||
{"if (true) { const var1 = 5; }"},
|
||||
{"const var1 = 5; function f() { var1; }"},
|
||||
|
||||
// Functions.
|
||||
{"function f1() { let var2; }"},
|
||||
{"var var1 = function f1() { let var2; }"},
|
||||
{"let var1 = function f1() { let var2; }"},
|
||||
{"const var1 = function f1() { let var2; }"},
|
||||
{"var var1 = function() { let var2; }"},
|
||||
{"let var1 = function() { let var2; }"},
|
||||
{"const var1 = function() { let var2; }"},
|
||||
|
||||
// Redeclarations.
|
||||
{"var var1; var var1;"},
|
||||
{"var var1; var var1; var1 = 5;"},
|
||||
@ -491,6 +557,9 @@ TEST(PreParserScopeAnalysis) {
|
||||
"{name9: var9, name10: var10}, ...var11",
|
||||
"", SKIP_STRICT_FUNCTION, false},
|
||||
|
||||
// Complicated cases from bugs.
|
||||
{"var1 = {} = {}", "", SKIP_STRICT_FUNCTION, false},
|
||||
|
||||
// Destructuring rest. Because we can.
|
||||
{"var1, ...[var2]", "", SKIP_STRICT_FUNCTION},
|
||||
{"var1, ...[var2]", "() => { var2; }", SKIP_STRICT_FUNCTION},
|
||||
@ -551,6 +620,24 @@ TEST(PreParserScopeAnalysis) {
|
||||
// Classes
|
||||
// FIXME(marja): Add more complex class cases.
|
||||
{"class MyClass {}"},
|
||||
{"var1 = class MyClass {}"},
|
||||
{"var var1 = class MyClass {}"},
|
||||
{"let var1 = class MyClass {}"},
|
||||
{"const var1 = class MyClass {}"},
|
||||
{"var var1 = class {}"},
|
||||
{"let var1 = class {}"},
|
||||
{"const var1 = class {}"},
|
||||
|
||||
{"class MyClass { m() {} }"},
|
||||
{"class MyClass { m() { var var1; } }"},
|
||||
{"class MyClass { m() { var var1 = 11; } }"},
|
||||
{"class MyClass { m() { var var1; function foo() { var1 = 11; } } }"},
|
||||
|
||||
{"class MyClass { static m() {} }"},
|
||||
{"class MyClass { static m() { var var1; } }"},
|
||||
{"class MyClass { static m() { var var1 = 11; } }"},
|
||||
{"class MyClass { static m() { var var1; function foo() { var1 = 11; } } "
|
||||
"}"},
|
||||
};
|
||||
|
||||
for (unsigned outer_ix = 0; outer_ix < arraysize(outers); ++outer_ix) {
|
||||
@ -630,9 +717,8 @@ TEST(PreParserScopeAnalysis) {
|
||||
CHECK(i::parsing::ParseProgram(&eager_normal, isolate));
|
||||
CHECK(i::Compiler::Analyze(&eager_normal, isolate));
|
||||
|
||||
i::Scope* normal_scope =
|
||||
eager_normal.literal()->scope()->inner_scope()->inner_scope();
|
||||
CHECK_NOT_NULL(normal_scope);
|
||||
i::Scope* normal_scope = i::ScopeTestHelper::FindScope(
|
||||
eager_normal.literal()->scope(), outers[outer_ix].location);
|
||||
CHECK_NULL(normal_scope->sibling());
|
||||
CHECK(normal_scope->is_function_scope());
|
||||
|
||||
@ -643,11 +729,8 @@ TEST(PreParserScopeAnalysis) {
|
||||
// Don't run scope analysis (that would obviously decide the correct
|
||||
// allocation for the variables).
|
||||
|
||||
i::Scope* unallocated_scope = eager_using_scope_data.literal()
|
||||
->scope()
|
||||
->inner_scope()
|
||||
->inner_scope();
|
||||
CHECK_NOT_NULL(unallocated_scope);
|
||||
i::Scope* unallocated_scope = i::ScopeTestHelper::FindScope(
|
||||
eager_using_scope_data.literal()->scope(), outers[outer_ix].location);
|
||||
CHECK_NULL(unallocated_scope->sibling());
|
||||
CHECK(unallocated_scope->is_function_scope());
|
||||
|
||||
|
@ -59,6 +59,20 @@ class ScopeTestHelper {
|
||||
CompareScopes(baseline_inner, scope_inner, precise_maybe_assigned);
|
||||
}
|
||||
}
|
||||
|
||||
// Finds a scope given a start point and directions to it (which inner scope
|
||||
// to pick).
|
||||
static Scope* FindScope(Scope* scope, const std::vector<unsigned>& location) {
|
||||
for (auto n : location) {
|
||||
scope = scope->inner_scope();
|
||||
CHECK_NOT_NULL(scope);
|
||||
while (n-- > 0) {
|
||||
scope = scope->sibling();
|
||||
CHECK_NOT_NULL(scope);
|
||||
}
|
||||
}
|
||||
return scope;
|
||||
}
|
||||
};
|
||||
} // namespace internal
|
||||
} // namespace v8
|
||||
|
@ -3529,14 +3529,7 @@ static void TestMaybeAssigned(Input input, const char* variable, bool module,
|
||||
i::Variable* var;
|
||||
{
|
||||
// Find the variable.
|
||||
for (auto it = input.location.begin(); it != input.location.end(); ++it) {
|
||||
unsigned n = *it;
|
||||
scope = scope->inner_scope();
|
||||
while (n-- > 0) {
|
||||
scope = scope->sibling();
|
||||
}
|
||||
}
|
||||
CHECK_NOT_NULL(scope);
|
||||
scope = i::ScopeTestHelper::FindScope(scope, input.location);
|
||||
const i::AstRawString* var_name =
|
||||
info->ast_value_factory()->GetOneByteString(variable);
|
||||
var = scope->Lookup(var_name);
|
||||
|
Loading…
Reference in New Issue
Block a user