Reland of [parsing] Fix maybe-assigned for loop variables. (patchset #1 id:1 of https://codereview.chromium.org/2679263002/ )
Reason for revert: False alarm, bot hiccup Original issue's description: > Revert of [parsing] Fix maybe-assigned for loop variables. (patchset #3 id:40001 of https://codereview.chromium.org/2673403003/ ) > > Reason for revert: > Speculative revert because of https://codereview.chromium.org/2679163002/. > > Original issue's description: > > [parsing] Fix maybe-assigned for loop variables. > > > > Due to hoisting, the value of a 'var'-declared variable may actually change even > > if the code contains only the "initial" assignment, namely when that assignment > > occurs inside a loop. For example: > > > > let i = 10; > > do { var x = i } while (i--): > > > > As a simple and very conservative approximation of this, we explicitly mark > > as maybe-assigned any non-lexical variable whose "declaration" does not > > syntactically occur in the function scope. (In the example above, it > > occurs in a block scope.) > > > > BUG=v8:5636 > > > > Review-Url: https://codereview.chromium.org/2673403003 > > Cr-Commit-Position: refs/heads/master@{#42989} > > Committed:a33fcd663b
> > TBR=marja@chromium.org,adamk@chromium.org,neis@chromium.org > # Skipping CQ checks because original CL landed less than 1 days ago. > NOPRESUBMIT=true > NOTREECHECKS=true > NOTRY=true > BUG=v8:5636 > > Review-Url: https://codereview.chromium.org/2679263002 > Cr-Commit-Position: refs/heads/master@{#43010} > Committed:f3ae5ccf57
TBR=marja@chromium.org,adamk@chromium.org,neis@chromium.org # Skipping CQ checks because original CL landed less than 1 days ago. NOPRESUBMIT=true NOTREECHECKS=true NOTRY=true BUG=v8:5636 Review-Url: https://codereview.chromium.org/2686663002 Cr-Commit-Position: refs/heads/master@{#43013}
This commit is contained in:
parent
96e4f6145b
commit
5f9c89af70
@ -181,6 +181,7 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
bool* sloppy_mode_block_scope_function_redefinition,
|
||||
bool* ok);
|
||||
|
||||
// The return value is meaningful only if FLAG_preparser_scope_analysis is on.
|
||||
Variable* DeclareVariableName(const AstRawString* name, VariableMode mode);
|
||||
|
||||
// Declarations list.
|
||||
|
@ -1347,6 +1347,24 @@ class ParserBase {
|
||||
return expression->IsObjectLiteral() || expression->IsArrayLiteral();
|
||||
}
|
||||
|
||||
// Due to hoisting, the value of a 'var'-declared variable may actually change
|
||||
// even if the code contains only the "initial" assignment, namely when that
|
||||
// assignment occurs inside a loop. For example:
|
||||
//
|
||||
// let i = 10;
|
||||
// do { var x = i } while (i--):
|
||||
//
|
||||
// As a simple and very conservative approximation of this, we explicitly mark
|
||||
// as maybe-assigned any non-lexical variable whose initializing "declaration"
|
||||
// does not syntactically occur in the function scope. (In the example above,
|
||||
// it occurs in a block scope.)
|
||||
//
|
||||
// Note that non-lexical variables include temporaries, which may also get
|
||||
// assigned inside a loop due to the various rewritings that the parser
|
||||
// performs.
|
||||
//
|
||||
static void MarkLoopVariableAsAssigned(Scope* scope, Variable* var);
|
||||
|
||||
// Keep track of eval() calls since they disable all local variable
|
||||
// optimizations. This checks if expression is an eval call, and if yes,
|
||||
// forwards the information to scope.
|
||||
@ -5698,8 +5716,12 @@ typename ParserBase<Impl>::StatementT ParserBase<Impl>::ParseStandardForLoop(
|
||||
return loop;
|
||||
}
|
||||
|
||||
#undef CHECK_OK
|
||||
#undef CHECK_OK_CUSTOM
|
||||
template <typename Impl>
|
||||
void ParserBase<Impl>::MarkLoopVariableAsAssigned(Scope* scope, Variable* var) {
|
||||
if (!IsLexicalVariableMode(var->mode()) && !scope->is_function_scope()) {
|
||||
var->set_maybe_assigned();
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
void ParserBase<Impl>::ObjectLiteralChecker::CheckDuplicateProto(
|
||||
@ -5751,6 +5773,8 @@ void ParserBase<Impl>::ClassLiteralChecker::CheckClassMethodName(
|
||||
}
|
||||
}
|
||||
|
||||
#undef CHECK_OK
|
||||
#undef CHECK_OK_CUSTOM
|
||||
#undef CHECK_OK_VOID
|
||||
|
||||
} // namespace internal
|
||||
|
@ -177,6 +177,8 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
|
||||
// If there's no initializer, we're done.
|
||||
if (value == nullptr) return;
|
||||
|
||||
MarkLoopVariableAsAssigned(var_init_scope, proxy->var());
|
||||
|
||||
// A declaration of the form:
|
||||
//
|
||||
// var v = x;
|
||||
|
@ -310,8 +310,14 @@ void PreParser::DeclareAndInitializeVariables(
|
||||
DCHECK(track_unresolved_variables_);
|
||||
for (auto variable : *(declaration->pattern.variables_)) {
|
||||
declaration_descriptor->scope->RemoveUnresolved(variable);
|
||||
scope()->DeclareVariableName(variable->raw_name(),
|
||||
declaration_descriptor->mode);
|
||||
Variable* var = scope()->DeclareVariableName(
|
||||
variable->raw_name(), declaration_descriptor->mode);
|
||||
if (FLAG_preparser_scope_analysis) {
|
||||
MarkLoopVariableAsAssigned(declaration_descriptor->scope, var);
|
||||
// This is only necessary if there is an initializer, but we don't have
|
||||
// that information here. Consequently, the preparser sometimes says
|
||||
// maybe-assigned where the parser (correctly) says never-assigned.
|
||||
}
|
||||
if (names) {
|
||||
names->Add(variable->raw_name(), zone());
|
||||
}
|
||||
|
@ -30,268 +30,274 @@ TEST(PreParserScopeAnalysis) {
|
||||
const char* eager_inner = "(function inner(%s) { %s })()";
|
||||
|
||||
struct {
|
||||
bool precise_maybe_assigned;
|
||||
const char* params;
|
||||
const char* source;
|
||||
} inners[] = {
|
||||
// Simple cases
|
||||
{"", "var1;"},
|
||||
{"", "var1 = 5;"},
|
||||
{"", "if (true) {}"},
|
||||
{"", "function f1() {}"},
|
||||
{1, "", "var1;"},
|
||||
{1, "", "var1 = 5;"},
|
||||
{1, "", "if (true) {}"},
|
||||
{1, "", "function f1() {}"},
|
||||
|
||||
// Var declarations and assignments.
|
||||
{"", "var var1;"},
|
||||
{"", "var var1; var1 = 5;"},
|
||||
{"", "if (true) { var var1; }"},
|
||||
{"", "if (true) { var var1; var1 = 5; }"},
|
||||
{"", "var var1; function f() { var1; }"},
|
||||
{"", "var var1; var1 = 5; function f() { var1; }"},
|
||||
{"", "var var1; function f() { var1 = 5; }"},
|
||||
{1, "", "var var1;"},
|
||||
{1, "", "var var1; var1 = 5;"},
|
||||
{0, "", "if (true) { var var1; }"},
|
||||
{1, "", "if (true) { var var1; var1 = 5; }"},
|
||||
{1, "", "var var1; function f() { var1; }"},
|
||||
{1, "", "var var1; var1 = 5; function f() { var1; }"},
|
||||
{1, "", "var var1; function f() { var1 = 5; }"},
|
||||
|
||||
// Let declarations and assignments.
|
||||
{"", "let var1;"},
|
||||
{"", "let var1; var1 = 5;"},
|
||||
{"", "if (true) { let var1; }"},
|
||||
{"", "if (true) { let var1; var1 = 5; }"},
|
||||
{"", "let var1; function f() { var1; }"},
|
||||
{"", "let var1; var1 = 5; function f() { var1; }"},
|
||||
{"", "let var1; function f() { var1 = 5; }"},
|
||||
{1, "", "let var1;"},
|
||||
{1, "", "let var1; var1 = 5;"},
|
||||
{1, "", "if (true) { let var1; }"},
|
||||
{1, "", "if (true) { let var1; var1 = 5; }"},
|
||||
{1, "", "let var1; function f() { var1; }"},
|
||||
{1, "", "let var1; var1 = 5; function f() { var1; }"},
|
||||
{1, "", "let var1; function f() { var1 = 5; }"},
|
||||
|
||||
// Const declarations.
|
||||
{"", "const var1 = 5;"},
|
||||
{"", "if (true) { const var1 = 5; }"},
|
||||
{"", "const var1 = 5; function f() { var1; }"},
|
||||
{1, "", "const var1 = 5;"},
|
||||
{1, "", "if (true) { const var1 = 5; }"},
|
||||
{1, "", "const var1 = 5; function f() { var1; }"},
|
||||
|
||||
// Redeclarations.
|
||||
{"", "var var1; var var1;"},
|
||||
{"", "var var1; var var1; var1 = 5;"},
|
||||
{"", "var var1; if (true) { var var1; }"},
|
||||
{"", "if (true) { var var1; var var1; }"},
|
||||
{"", "var var1; if (true) { var var1; var1 = 5; }"},
|
||||
{"", "if (true) { var var1; var var1; var1 = 5; }"},
|
||||
{"", "var var1; var var1; function f() { var1; }"},
|
||||
{"", "var var1; var var1; function f() { var1 = 5; }"},
|
||||
{1, "", "var var1; var var1;"},
|
||||
{1, "", "var var1; var var1; var1 = 5;"},
|
||||
{1, "", "var var1; if (true) { var var1; }"},
|
||||
{1, "", "if (true) { var var1; var var1; }"},
|
||||
{1, "", "var var1; if (true) { var var1; var1 = 5; }"},
|
||||
{1, "", "if (true) { var var1; var var1; var1 = 5; }"},
|
||||
{1, "", "var var1; var var1; function f() { var1; }"},
|
||||
{1, "", "var var1; var var1; function f() { var1 = 5; }"},
|
||||
|
||||
// Shadowing declarations.
|
||||
{"", "var var1; if (true) { var var1; }"},
|
||||
{"", "var var1; if (true) { let var1; }"},
|
||||
{"", "let var1; if (true) { let var1; }"},
|
||||
{1, "", "var var1; if (true) { var var1; }"},
|
||||
{1, "", "var var1; if (true) { let var1; }"},
|
||||
{1, "", "let var1; if (true) { let var1; }"},
|
||||
|
||||
{"", "var var1; if (true) { const var1 = 0; }"},
|
||||
{"", "const var1 = 0; if (true) { const var1 = 0; }"},
|
||||
{1, "", "var var1; if (true) { const var1 = 0; }"},
|
||||
{1, "", "const var1 = 0; if (true) { const var1 = 0; }"},
|
||||
|
||||
// Arguments and this.
|
||||
{"", "arguments;"},
|
||||
{"", "arguments = 5;"},
|
||||
{"", "if (true) { arguments; }"},
|
||||
{"", "if (true) { arguments = 5; }"},
|
||||
{"", "function f() { arguments; }"},
|
||||
{"", "function f() { arguments = 5; }"},
|
||||
{1, "", "arguments;"},
|
||||
{1, "", "arguments = 5;"},
|
||||
{1, "", "if (true) { arguments; }"},
|
||||
{1, "", "if (true) { arguments = 5; }"},
|
||||
{1, "", "function f() { arguments; }"},
|
||||
{1, "", "function f() { arguments = 5; }"},
|
||||
|
||||
{"", "this;"},
|
||||
{"", "if (true) { this; }"},
|
||||
{"", "function f() { this; }"},
|
||||
{1, "", "this;"},
|
||||
{1, "", "if (true) { this; }"},
|
||||
{1, "", "function f() { this; }"},
|
||||
|
||||
// Variable called "arguments"
|
||||
{"", "var arguments;"},
|
||||
{"", "var arguments; arguments = 5;"},
|
||||
{"", "if (true) { var arguments; }"},
|
||||
{"", "if (true) { var arguments; arguments = 5; }"},
|
||||
{"", "var arguments; function f() { arguments; }"},
|
||||
{"", "var arguments; arguments = 5; function f() { arguments; }"},
|
||||
{"", "var arguments; function f() { arguments = 5; }"},
|
||||
{1, "", "var arguments;"},
|
||||
{1, "", "var arguments; arguments = 5;"},
|
||||
{0, "", "if (true) { var arguments; }"},
|
||||
{1, "", "if (true) { var arguments; arguments = 5; }"},
|
||||
{1, "", "var arguments; function f() { arguments; }"},
|
||||
{1, "", "var arguments; arguments = 5; function f() { arguments; }"},
|
||||
{1, "", "var arguments; function f() { arguments = 5; }"},
|
||||
|
||||
{"", "let arguments;"},
|
||||
{"", "let arguments; arguments = 5;"},
|
||||
{"", "if (true) { let arguments; }"},
|
||||
{"", "if (true) { let arguments; arguments = 5; }"},
|
||||
{"", "let arguments; function f() { arguments; }"},
|
||||
{"", "let arguments; arguments = 5; function f() { arguments; }"},
|
||||
{"", "let arguments; function f() { arguments = 5; }"},
|
||||
{1, "", "let arguments;"},
|
||||
{1, "", "let arguments; arguments = 5;"},
|
||||
{1, "", "if (true) { let arguments; }"},
|
||||
{1, "", "if (true) { let arguments; arguments = 5; }"},
|
||||
{1, "", "let arguments; function f() { arguments; }"},
|
||||
{1, "", "let arguments; arguments = 5; function f() { arguments; }"},
|
||||
{1, "", "let arguments; function f() { arguments = 5; }"},
|
||||
|
||||
{"", "const arguments = 5;"},
|
||||
{"", "if (true) { const arguments = 5; }"},
|
||||
{"", "const arguments = 5; function f() { arguments; }"},
|
||||
{1, "", "const arguments = 5;"},
|
||||
{1, "", "if (true) { const arguments = 5; }"},
|
||||
{1, "", "const arguments = 5; function f() { arguments; }"},
|
||||
|
||||
// Destructuring declarations.
|
||||
{"", "var [var1, var2] = [1, 2];"},
|
||||
{"", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{"", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{"", "var [var1, ...var2] = [1, 2, 3];"},
|
||||
{1, "", "var [var1, var2] = [1, 2];"},
|
||||
{1, "", "var [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{1, "", "var [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{1, "", "var [var1, ...var2] = [1, 2, 3];"},
|
||||
|
||||
{"", "var {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{"",
|
||||
{1, "", "var {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{1, "",
|
||||
"var {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
|
||||
{"", "var {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
{1, "",
|
||||
"var {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
|
||||
{"", "let [var1, var2] = [1, 2];"},
|
||||
{"", "let [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{"", "let [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{"", "let [var1, ...var2] = [1, 2, 3];"},
|
||||
{1, "", "let [var1, var2] = [1, 2];"},
|
||||
{1, "", "let [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{1, "", "let [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{1, "", "let [var1, ...var2] = [1, 2, 3];"},
|
||||
|
||||
{"", "let {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{"",
|
||||
{1, "", "let {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{1, "",
|
||||
"let {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
|
||||
{"", "let {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
{1, "",
|
||||
"let {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
|
||||
{"", "const [var1, var2] = [1, 2];"},
|
||||
{"", "const [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{"", "const [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{"", "const [var1, ...var2] = [1, 2, 3];"},
|
||||
{1, "", "const [var1, var2] = [1, 2];"},
|
||||
{1, "", "const [var1, var2, [var3, var4]] = [1, 2, [3, 4]];"},
|
||||
{1, "", "const [{var1: var2}, {var3: var4}] = [{var1: 1}, {var3: 2}];"},
|
||||
{1, "", "const [var1, ...var2] = [1, 2, 3];"},
|
||||
|
||||
{"", "const {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{"",
|
||||
{1, "", "const {var1: var2, var3: var4} = {var1: 1, var3: 2};"},
|
||||
{1, "",
|
||||
"const {var1: var2, var3: {var4: var5}} = {var1: 1, var3: {var4: 2}};"},
|
||||
{"", "const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
{1, "",
|
||||
"const {var1: var2, var3: [var4, var5]} = {var1: 1, var3: [2, 3]};"},
|
||||
|
||||
// Referencing the function variable.
|
||||
{"", "inner;"},
|
||||
{"", "function f1() { f1; }"},
|
||||
{"", "function f1() { inner; }"},
|
||||
{"", "function f1() { function f2() { f1; } }"},
|
||||
{"", "function arguments() {}"},
|
||||
{"", "function f1() {} function f1() {}"},
|
||||
{"", "var f1; function f1() {}"},
|
||||
{1, "", "inner;"},
|
||||
{1, "", "function f1() { f1; }"},
|
||||
{1, "", "function f1() { inner; }"},
|
||||
{1, "", "function f1() { function f2() { f1; } }"},
|
||||
{1, "", "function arguments() {}"},
|
||||
{1, "", "function f1() {} function f1() {}"},
|
||||
{1, "", "var f1; function f1() {}"},
|
||||
|
||||
// Assigning to the function variable.
|
||||
{"", "inner = 3;"},
|
||||
{"", "function f1() { f1 = 3; }"},
|
||||
{"", "function f1() { f1; } f1 = 3;"},
|
||||
{"", "function arguments() {} arguments = 8"},
|
||||
{"", "function f1() {} f1 = 3; function f1() {}"},
|
||||
{1, "", "inner = 3;"},
|
||||
{1, "", "function f1() { f1 = 3; }"},
|
||||
{1, "", "function f1() { f1; } f1 = 3;"},
|
||||
{1, "", "function arguments() {} arguments = 8"},
|
||||
{1, "", "function f1() {} f1 = 3; function f1() {}"},
|
||||
|
||||
// Evals.
|
||||
{"", "var var1; eval('');"},
|
||||
{"", "var var1; function f1() { eval(''); }"},
|
||||
{"", "let var1; eval('');"},
|
||||
{"", "let var1; function f1() { eval(''); }"},
|
||||
{"", "const var1 = 10; eval('');"},
|
||||
{"", "const var1 = 10; function f1() { eval(''); }"},
|
||||
{1, "", "var var1; eval('');"},
|
||||
{1, "", "var var1; function f1() { eval(''); }"},
|
||||
{1, "", "let var1; eval('');"},
|
||||
{1, "", "let var1; function f1() { eval(''); }"},
|
||||
{1, "", "const var1 = 10; eval('');"},
|
||||
{1, "", "const var1 = 10; function f1() { eval(''); }"},
|
||||
|
||||
// Standard for loops.
|
||||
{"", "for (var var1 = 0; var1 < 10; ++var1) { }"},
|
||||
{"", "for (let var1 = 0; var1 < 10; ++var1) { }"},
|
||||
{"", "for (const var1 = 0; var1 < 10; ++var1) { }"},
|
||||
{1, "", "for (var var1 = 0; var1 < 10; ++var1) { }"},
|
||||
{1, "", "for (let var1 = 0; var1 < 10; ++var1) { }"},
|
||||
{1, "", "for (const var1 = 0; var1 < 10; ++var1) { }"},
|
||||
|
||||
{"",
|
||||
{1, "",
|
||||
"for (var var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"for (let var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"for (const var1 = 0; var1 < 10; ++var1) { function foo() { var1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"'use strict'; for (var var1 = 0; var1 < 10; ++var1) { function foo() { "
|
||||
"var1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"'use strict'; for (let var1 = 0; var1 < 10; ++var1) { function foo() { "
|
||||
"var1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"'use strict'; for (const var1 = 0; var1 < 10; ++var1) { function foo() "
|
||||
"{ 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]) { }"},
|
||||
{1, "", "for (var1 of [1, 2]) { }"},
|
||||
{1, "", "for (var var1 of [1, 2]) { }"},
|
||||
{1, "", "for (let var1 of [1, 2]) { }"},
|
||||
{1, "", "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; }"},
|
||||
{1, "", "for (var1 of [1, 2]) { var1; }"},
|
||||
{1, "", "for (var var1 of [1, 2]) { var1; }"},
|
||||
{1, "", "for (let var1 of [1, 2]) { var1; }"},
|
||||
{1, "", "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; }"},
|
||||
{1, "", "for (var1 of [1, 2]) { var1 = 0; }"},
|
||||
{1, "", "for (var var1 of [1, 2]) { var1 = 0; }"},
|
||||
{1, "", "for (let var1 of [1, 2]) { var1 = 0; }"},
|
||||
{1, "", "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; } }"},
|
||||
{1, "", "for (var1 of [1, 2]) { function foo() { var1; } }"},
|
||||
{1, "", "for (var var1 of [1, 2]) { function foo() { var1; } }"},
|
||||
{1, "", "for (let var1 of [1, 2]) { function foo() { var1; } }"},
|
||||
{1, "", "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; } }"},
|
||||
{1, "", "for (var1 of [1, 2]) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (var var1 of [1, 2]) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (let var1 of [1, 2]) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "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}) { }"},
|
||||
{1, "", "for (var1 in {a: 6}) { }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { }"},
|
||||
{1, "", "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; }"},
|
||||
{1, "", "for (var1 in {a: 6}) { var1; }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { var1; }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { var1; }"},
|
||||
{1, "", "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; }"},
|
||||
{1, "", "for (var1 in {a: 6}) { var1 = 0; }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { var1 = 0; }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { var1 = 0; }"},
|
||||
{1, "", "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; } }"},
|
||||
{1, "", "for (var1 in {a: 6}) { function foo() { var1; } }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { function foo() { var1; } }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { function foo() { var1; } }"},
|
||||
{1, "", "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; } }"},
|
||||
{1, "", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "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; } }"},
|
||||
{1, "", "for (var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (var var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (let var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
{1, "", "for (const var1 in {a: 6}) { function foo() { var1 = 0; } }"},
|
||||
|
||||
// Loops without declarations
|
||||
{"", "var var1 = 0; for ( ; var1 < 2; ++var1) { }"},
|
||||
{"",
|
||||
{1, "", "var var1 = 0; for ( ; var1 < 2; ++var1) { }"},
|
||||
{1, "",
|
||||
"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; } }"},
|
||||
{"",
|
||||
{1, "", "var var1 = 0; for ( ; var1 > 2; ) { }"},
|
||||
{1, "", "var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1; } }"},
|
||||
{1, "",
|
||||
"var var1 = 0; for ( ; var1 > 2; ) { function foo() { var1 = 6; } }"},
|
||||
|
||||
{"", "var var1 = 0; for(var1; var1 < 2; ++var1) { }"},
|
||||
{"",
|
||||
{1, "", "var var1 = 0; for(var1; var1 < 2; ++var1) { }"},
|
||||
{1, "",
|
||||
"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; } }"},
|
||||
{"",
|
||||
{1, "", "var var1 = 0; for (var1; var1 > 2; ) { }"},
|
||||
{1, "",
|
||||
"var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1; } }"},
|
||||
{1, "",
|
||||
"var var1 = 0; for (var1; var1 > 2; ) { function foo() { var1 = 6; } }"},
|
||||
|
||||
// Sloppy block functions.
|
||||
{"", "if (true) { function f1() {} }"},
|
||||
{"", "if (true) { function f1() {} function f1() {} }"},
|
||||
{"", "if (true) { if (true) { function f1() {} } }"},
|
||||
{"", "if (true) { if (true) { function f1() {} function f1() {} } }"},
|
||||
{"", "if (true) { function f1() {} f1 = 3; }"},
|
||||
{1, "", "if (true) { function f1() {} }"},
|
||||
{1, "", "if (true) { function f1() {} function f1() {} }"},
|
||||
{1, "", "if (true) { if (true) { function f1() {} } }"},
|
||||
{1, "", "if (true) { if (true) { function f1() {} function f1() {} } }"},
|
||||
{1, "", "if (true) { function f1() {} f1 = 3; }"},
|
||||
|
||||
{"", "if (true) { function f1() {} function foo() { f1; } }"},
|
||||
{"", "if (true) { function f1() {} } function foo() { f1; }"},
|
||||
{"",
|
||||
{1, "", "if (true) { function f1() {} function foo() { f1; } }"},
|
||||
{1, "", "if (true) { function f1() {} } function foo() { f1; }"},
|
||||
{1, "",
|
||||
"if (true) { function f1() {} function f1() {} function foo() { f1; } "
|
||||
"}"},
|
||||
{"",
|
||||
{1, "",
|
||||
"if (true) { function f1() {} function f1() {} } function foo() { f1; "
|
||||
"}"},
|
||||
{"",
|
||||
{1, "",
|
||||
"if (true) { if (true) { function f1() {} } function foo() { f1; } }"},
|
||||
{"",
|
||||
{1, "",
|
||||
"if (true) { if (true) { function f1() {} function f1() {} } function "
|
||||
"foo() { f1; } }"},
|
||||
{"", "if (true) { function f1() {} f1 = 3; function foo() { f1; } }"},
|
||||
{"", "if (true) { function f1() {} f1 = 3; } function foo() { f1; }"},
|
||||
{1, "", "if (true) { function f1() {} f1 = 3; function foo() { f1; } }"},
|
||||
{1, "", "if (true) { function f1() {} f1 = 3; } function foo() { f1; }"},
|
||||
|
||||
{"", "function inner2() { if (true) { function f1() {} } }"},
|
||||
{"", "function inner2() { if (true) { function f1() {} f1 = 3; } }"},
|
||||
{1, "", "function inner2() { if (true) { function f1() {} } }"},
|
||||
{1, "", "function inner2() { if (true) { function f1() {} f1 = 3; } }"},
|
||||
|
||||
{"", "var f1 = 1; if (true) { function f1() {} }"},
|
||||
{"", "var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"},
|
||||
{1, "", "var f1 = 1; if (true) { function f1() {} }"},
|
||||
{1, "",
|
||||
"var f1 = 1; if (true) { function f1() {} } function foo() { f1; }"},
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(inners); ++i) {
|
||||
@ -358,6 +364,7 @@ TEST(PreParserScopeAnalysis) {
|
||||
|
||||
size_t index = 0;
|
||||
i::ScopeTestHelper::CompareScopeToData(
|
||||
scope, lazy_info.preparsed_scope_data(), index);
|
||||
scope, lazy_info.preparsed_scope_data(), index,
|
||||
inners[i].precise_maybe_assigned);
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ class ScopeTestHelper {
|
||||
}
|
||||
|
||||
static void CompareScopeToData(Scope* scope, const PreParsedScopeData* data,
|
||||
size_t& index) {
|
||||
size_t& index, bool precise_maybe_assigned) {
|
||||
CHECK_EQ(data->backing_store_[index++], scope->scope_type());
|
||||
CHECK_EQ(data->backing_store_[index++], scope->start_position());
|
||||
CHECK_EQ(data->backing_store_[index++], scope->end_position());
|
||||
@ -70,14 +70,19 @@ class ScopeTestHelper {
|
||||
}
|
||||
#endif
|
||||
CHECK_EQ(data->backing_store_[index++], local->location());
|
||||
if (precise_maybe_assigned) {
|
||||
CHECK_EQ(data->backing_store_[index++], local->maybe_assigned());
|
||||
} else {
|
||||
STATIC_ASSERT(kMaybeAssigned > kNotAssigned);
|
||||
CHECK_GE(data->backing_store_[index++], local->maybe_assigned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Scope* inner = scope->inner_scope(); inner != nullptr;
|
||||
inner = inner->sibling()) {
|
||||
if (!ScopeTreeIsHidden(inner)) {
|
||||
CompareScopeToData(inner, data, index);
|
||||
CompareScopeToData(inner, data, index, precise_maybe_assigned);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3495,6 +3495,365 @@ TEST(MaybeAssignedParameters) {
|
||||
}
|
||||
}
|
||||
|
||||
struct Input {
|
||||
bool assigned;
|
||||
std::string source;
|
||||
std::vector<unsigned> location; // "Directions" to the relevant scope.
|
||||
};
|
||||
|
||||
static void TestMaybeAssigned(i::Zone* zone, Input input, const char* variable,
|
||||
bool module, bool allow_lazy_parsing) {
|
||||
i::Factory* factory = CcTest::i_isolate()->factory();
|
||||
i::Handle<i::String> string =
|
||||
factory->InternalizeUtf8String(input.source.c_str());
|
||||
string->PrintOn(stdout);
|
||||
printf("\n");
|
||||
i::Handle<i::Script> script = factory->NewScript(string);
|
||||
|
||||
std::unique_ptr<i::ParseInfo> info;
|
||||
info = std::unique_ptr<i::ParseInfo>(new i::ParseInfo(zone, script));
|
||||
info->set_module(module);
|
||||
info->set_allow_lazy_parsing(allow_lazy_parsing);
|
||||
|
||||
CHECK(i::parsing::ParseProgram(info.get()));
|
||||
CHECK(i::Compiler::Analyze(info.get()));
|
||||
|
||||
CHECK_NOT_NULL(info->literal());
|
||||
i::Scope* scope = info->literal()->scope();
|
||||
CHECK(!scope->AsDeclarationScope()->was_lazily_parsed());
|
||||
CHECK_NULL(scope->sibling());
|
||||
CHECK(module ? scope->is_module_scope() : scope->is_script_scope());
|
||||
|
||||
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);
|
||||
const i::AstRawString* var_name =
|
||||
info->ast_value_factory()->GetOneByteString(variable);
|
||||
var = scope->Lookup(var_name);
|
||||
}
|
||||
|
||||
CHECK(var->is_used());
|
||||
STATIC_ASSERT(true == i::kMaybeAssigned);
|
||||
CHECK_EQ(input.assigned, var->maybe_assigned() == i::kMaybeAssigned);
|
||||
}
|
||||
|
||||
static Input wrap(Input input) {
|
||||
Input result;
|
||||
result.assigned = input.assigned;
|
||||
result.source = "function WRAPPED() { " + input.source + " }";
|
||||
result.location.push_back(0);
|
||||
for (auto n : input.location) {
|
||||
result.location.push_back(n);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(MaybeAssignedInsideLoop) {
|
||||
i::Isolate* isolate = CcTest::i_isolate();
|
||||
i::HandleScope scope(isolate);
|
||||
LocalContext env;
|
||||
i::Zone zone(isolate->allocator(), ZONE_NAME);
|
||||
|
||||
std::vector<unsigned> top; // Can't use {} in initializers below.
|
||||
|
||||
Input module_and_script_tests[] = {
|
||||
{1, "for (j=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for (j=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for (j=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for (j=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for (j=x; j<10; ++j) { let foo = j }", {0}},
|
||||
{0, "for (j=x; j<10; ++j) { let [foo] = [j] }", {0}},
|
||||
{0, "for (j=x; j<10; ++j) { const foo = j }", {0}},
|
||||
{0, "for (j=x; j<10; ++j) { const [foo] = [j] }", {0}},
|
||||
{0, "for (j=x; j<10; ++j) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for ({j}=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for ({j}=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for ({j}=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for ({j}=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for ({j}=x; j<10; ++j) { let foo = j }", {0}},
|
||||
{0, "for ({j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
|
||||
{0, "for ({j}=x; j<10; ++j) { const foo = j }", {0}},
|
||||
{0, "for ({j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
|
||||
{0, "for ({j}=x; j<10; ++j) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var j=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for (var j=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for (var j=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for (var j=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for (var j=x; j<10; ++j) { let foo = j }", {0}},
|
||||
{0, "for (var j=x; j<10; ++j) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var j=x; j<10; ++j) { const foo = j }", {0}},
|
||||
{0, "for (var j=x; j<10; ++j) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var j=x; j<10; ++j) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var {j}=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for (var {j}=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for (var {j}=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for (var {j}=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for (var {j}=x; j<10; ++j) { let foo = j }", {0}},
|
||||
{0, "for (var {j}=x; j<10; ++j) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var {j}=x; j<10; ++j) { const foo = j }", {0}},
|
||||
{0, "for (var {j}=x; j<10; ++j) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (let j=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for (let j=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for (let j=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for (let j=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for (let j=x; j<10; ++j) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (let j=x; j<10; ++j) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let j=x; j<10; ++j) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (let j=x; j<10; ++j) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let j=x; j<10; ++j) { function foo() {return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "for (let {j}=x; j<10; ++j) { foo = j }", top},
|
||||
{1, "for (let {j}=x; j<10; ++j) { [foo] = [j] }", top},
|
||||
{1, "for (let {j}=x; j<10; ++j) { var foo = j }", top},
|
||||
{1, "for (let {j}=x; j<10; ++j) { var [foo] = [j] }", top},
|
||||
{0, "for (let {j}=x; j<10; ++j) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (let {j}=x; j<10; ++j) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let {j}=x; j<10; ++j) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (let {j}=x; j<10; ++j) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let {j}=x; j<10; ++j) { function foo(){return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "for (j of x) { foo = j }", top},
|
||||
{1, "for (j of x) { [foo] = [j] }", top},
|
||||
{1, "for (j of x) { var foo = j }", top},
|
||||
{1, "for (j of x) { var [foo] = [j] }", top},
|
||||
{0, "for (j of x) { let foo = j }", {0}},
|
||||
{0, "for (j of x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (j of x) { const foo = j }", {0}},
|
||||
{0, "for (j of x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (j of x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for ({j} of x) { foo = j }", top},
|
||||
{1, "for ({j} of x) { [foo] = [j] }", top},
|
||||
{1, "for ({j} of x) { var foo = j }", top},
|
||||
{1, "for ({j} of x) { var [foo] = [j] }", top},
|
||||
{0, "for ({j} of x) { let foo = j }", {0}},
|
||||
{0, "for ({j} of x) { let [foo] = [j] }", {0}},
|
||||
{0, "for ({j} of x) { const foo = j }", {0}},
|
||||
{0, "for ({j} of x) { const [foo] = [j] }", {0}},
|
||||
{0, "for ({j} of x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var j of x) { foo = j }", top},
|
||||
{1, "for (var j of x) { [foo] = [j] }", top},
|
||||
{1, "for (var j of x) { var foo = j }", top},
|
||||
{1, "for (var j of x) { var [foo] = [j] }", top},
|
||||
{0, "for (var j of x) { let foo = j }", {0}},
|
||||
{0, "for (var j of x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var j of x) { const foo = j }", {0}},
|
||||
{0, "for (var j of x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var j of x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var {j} of x) { foo = j }", top},
|
||||
{1, "for (var {j} of x) { [foo] = [j] }", top},
|
||||
{1, "for (var {j} of x) { var foo = j }", top},
|
||||
{1, "for (var {j} of x) { var [foo] = [j] }", top},
|
||||
{0, "for (var {j} of x) { let foo = j }", {0}},
|
||||
{0, "for (var {j} of x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var {j} of x) { const foo = j }", {0}},
|
||||
{0, "for (var {j} of x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var {j} of x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (let j of x) { foo = j }", top},
|
||||
{1, "for (let j of x) { [foo] = [j] }", top},
|
||||
{1, "for (let j of x) { var foo = j }", top},
|
||||
{1, "for (let j of x) { var [foo] = [j] }", top},
|
||||
{0, "for (let j of x) { let foo = j }", {0, 2, 0}},
|
||||
{0, "for (let j of x) { let [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (let j of x) { const foo = j }", {0, 2, 0}},
|
||||
{0, "for (let j of x) { const [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (let j of x) { function foo() {return j} }", {0, 2, 0}},
|
||||
|
||||
{1, "for (let {j} of x) { foo = j }", top},
|
||||
{1, "for (let {j} of x) { [foo] = [j] }", top},
|
||||
{1, "for (let {j} of x) { var foo = j }", top},
|
||||
{1, "for (let {j} of x) { var [foo] = [j] }", top},
|
||||
{0, "for (let {j} of x) { let foo = j }", {0, 2, 0}},
|
||||
{0, "for (let {j} of x) { let [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (let {j} of x) { const foo = j }", {0, 2, 0}},
|
||||
{0, "for (let {j} of x) { const [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (let {j} of x) { function foo() {return j} }", {0, 2, 0}},
|
||||
|
||||
{1, "for (const j of x) { foo = j }", top},
|
||||
{1, "for (const j of x) { [foo] = [j] }", top},
|
||||
{1, "for (const j of x) { var foo = j }", top},
|
||||
{1, "for (const j of x) { var [foo] = [j] }", top},
|
||||
{0, "for (const j of x) { let foo = j }", {0, 2, 0}},
|
||||
{0, "for (const j of x) { let [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (const j of x) { const foo = j }", {0, 2, 0}},
|
||||
{0, "for (const j of x) { const [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (const j of x) { function foo() {return j} }", {0, 2, 0}},
|
||||
|
||||
{1, "for (const {j} of x) { foo = j }", top},
|
||||
{1, "for (const {j} of x) { [foo] = [j] }", top},
|
||||
{1, "for (const {j} of x) { var foo = j }", top},
|
||||
{1, "for (const {j} of x) { var [foo] = [j] }", top},
|
||||
{0, "for (const {j} of x) { let foo = j }", {0, 2, 0}},
|
||||
{0, "for (const {j} of x) { let [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (const {j} of x) { const foo = j }", {0, 2, 0}},
|
||||
{0, "for (const {j} of x) { const [foo] = [j] }", {0, 2, 0}},
|
||||
{0, "for (const {j} of x) { function foo() {return j} }", {0, 2, 0}},
|
||||
|
||||
{1, "for (j in x) { foo = j }", top},
|
||||
{1, "for (j in x) { [foo] = [j] }", top},
|
||||
{1, "for (j in x) { var foo = j }", top},
|
||||
{1, "for (j in x) { var [foo] = [j] }", top},
|
||||
{0, "for (j in x) { let foo = j }", {0}},
|
||||
{0, "for (j in x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (j in x) { const foo = j }", {0}},
|
||||
{0, "for (j in x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (j in x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for ({j} in x) { foo = j }", top},
|
||||
{1, "for ({j} in x) { [foo] = [j] }", top},
|
||||
{1, "for ({j} in x) { var foo = j }", top},
|
||||
{1, "for ({j} in x) { var [foo] = [j] }", top},
|
||||
{0, "for ({j} in x) { let foo = j }", {0}},
|
||||
{0, "for ({j} in x) { let [foo] = [j] }", {0}},
|
||||
{0, "for ({j} in x) { const foo = j }", {0}},
|
||||
{0, "for ({j} in x) { const [foo] = [j] }", {0}},
|
||||
{0, "for ({j} in x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var j in x) { foo = j }", top},
|
||||
{1, "for (var j in x) { [foo] = [j] }", top},
|
||||
{1, "for (var j in x) { var foo = j }", top},
|
||||
{1, "for (var j in x) { var [foo] = [j] }", top},
|
||||
{0, "for (var j in x) { let foo = j }", {0}},
|
||||
{0, "for (var j in x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var j in x) { const foo = j }", {0}},
|
||||
{0, "for (var j in x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var j in x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (var {j} in x) { foo = j }", top},
|
||||
{1, "for (var {j} in x) { [foo] = [j] }", top},
|
||||
{1, "for (var {j} in x) { var foo = j }", top},
|
||||
{1, "for (var {j} in x) { var [foo] = [j] }", top},
|
||||
{0, "for (var {j} in x) { let foo = j }", {0}},
|
||||
{0, "for (var {j} in x) { let [foo] = [j] }", {0}},
|
||||
{0, "for (var {j} in x) { const foo = j }", {0}},
|
||||
{0, "for (var {j} in x) { const [foo] = [j] }", {0}},
|
||||
{0, "for (var {j} in x) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "for (let j in x) { foo = j }", top},
|
||||
{1, "for (let j in x) { [foo] = [j] }", top},
|
||||
{1, "for (let j in x) { var foo = j }", top},
|
||||
{1, "for (let j in x) { var [foo] = [j] }", top},
|
||||
{0, "for (let j in x) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (let j in x) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let j in x) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (let j in x) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let j in x) { function foo() {return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "for (let {j} in x) { foo = j }", top},
|
||||
{1, "for (let {j} in x) { [foo] = [j] }", top},
|
||||
{1, "for (let {j} in x) { var foo = j }", top},
|
||||
{1, "for (let {j} in x) { var [foo] = [j] }", top},
|
||||
{0, "for (let {j} in x) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (let {j} in x) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let {j} in x) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (let {j} in x) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (let {j} in x) { function foo() {return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "for (const j in x) { foo = j }", top},
|
||||
{1, "for (const j in x) { [foo] = [j] }", top},
|
||||
{1, "for (const j in x) { var foo = j }", top},
|
||||
{1, "for (const j in x) { var [foo] = [j] }", top},
|
||||
{0, "for (const j in x) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (const j in x) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (const j in x) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (const j in x) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (const j in x) { function foo() {return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "for (const {j} in x) { foo = j }", top},
|
||||
{1, "for (const {j} in x) { [foo] = [j] }", top},
|
||||
{1, "for (const {j} in x) { var foo = j }", top},
|
||||
{1, "for (const {j} in x) { var [foo] = [j] }", top},
|
||||
{0, "for (const {j} in x) { let foo = j }", {0, 0, 0}},
|
||||
{0, "for (const {j} in x) { let [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (const {j} in x) { const foo = j }", {0, 0, 0}},
|
||||
{0, "for (const {j} in x) { const [foo] = [j] }", {0, 0, 0}},
|
||||
{0, "for (const {j} in x) { function foo() {return j} }", {0, 0, 0}},
|
||||
|
||||
{1, "while (j) { foo = j }", top},
|
||||
{1, "while (j) { [foo] = [j] }", top},
|
||||
{1, "while (j) { var foo = j }", top},
|
||||
{1, "while (j) { var [foo] = [j] }", top},
|
||||
{0, "while (j) { let foo = j }", {0}},
|
||||
{0, "while (j) { let [foo] = [j] }", {0}},
|
||||
{0, "while (j) { const foo = j }", {0}},
|
||||
{0, "while (j) { const [foo] = [j] }", {0}},
|
||||
{0, "while (j) { function foo() {return j} }", {0}},
|
||||
|
||||
{1, "do { foo = j } while (j)", top},
|
||||
{1, "do { [foo] = [j] } while (j)", top},
|
||||
{1, "do { var foo = j } while (j)", top},
|
||||
{1, "do { var [foo] = [j] } while (j)", top},
|
||||
{0, "do { let foo = j } while (j)", {0}},
|
||||
{0, "do { let [foo] = [j] } while (j)", {0}},
|
||||
{0, "do { const foo = j } while (j)", {0}},
|
||||
{0, "do { const [foo] = [j] } while (j)", {0}},
|
||||
{0, "do { function foo() {return j} } while (j)", {0}},
|
||||
};
|
||||
|
||||
Input script_only_tests[] = {
|
||||
{1, "for (j=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for ({j}=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for (var j=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for (var {j}=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for (let j=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for (let {j}=x; j<10; ++j) { function foo() {return j} }", top},
|
||||
{1, "for (j of x) { function foo() {return j} }", top},
|
||||
{1, "for ({j} of x) { function foo() {return j} }", top},
|
||||
{1, "for (var j of x) { function foo() {return j} }", top},
|
||||
{1, "for (var {j} of x) { function foo() {return j} }", top},
|
||||
{1, "for (let j of x) { function foo() {return j} }", top},
|
||||
{1, "for (let {j} of x) { function foo() {return j} }", top},
|
||||
{1, "for (const j of x) { function foo() {return j} }", top},
|
||||
{1, "for (const {j} of x) { function foo() {return j} }", top},
|
||||
{1, "for (j in x) { function foo() {return j} }", top},
|
||||
{1, "for ({j} in x) { function foo() {return j} }", top},
|
||||
{1, "for (var j in x) { function foo() {return j} }", top},
|
||||
{1, "for (var {j} in x) { function foo() {return j} }", top},
|
||||
{1, "for (let j in x) { function foo() {return j} }", top},
|
||||
{1, "for (let {j} in x) { function foo() {return j} }", top},
|
||||
{1, "for (const j in x) { function foo() {return j} }", top},
|
||||
{1, "for (const {j} in x) { function foo() {return j} }", top},
|
||||
{1, "while (j) { function foo() {return j} }", top},
|
||||
{1, "do { function foo() {return j} } while (j)", top},
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < arraysize(module_and_script_tests); ++i) {
|
||||
Input input = module_and_script_tests[i];
|
||||
for (unsigned module = 0; module <= 1; ++module) {
|
||||
for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
|
||||
++allow_lazy_parsing) {
|
||||
TestMaybeAssigned(&zone, input, "foo", module, allow_lazy_parsing);
|
||||
}
|
||||
TestMaybeAssigned(&zone, wrap(input), "foo", module, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned i = 0; i < arraysize(script_only_tests); ++i) {
|
||||
Input input = script_only_tests[i];
|
||||
for (unsigned allow_lazy_parsing = 0; allow_lazy_parsing <= 1;
|
||||
++allow_lazy_parsing) {
|
||||
TestMaybeAssigned(&zone, input, "foo", false, allow_lazy_parsing);
|
||||
}
|
||||
TestMaybeAssigned(&zone, wrap(input), "foo", false, false);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(MaybeAssignedTopLevel) {
|
||||
i::Isolate* isolate = CcTest::i_isolate();
|
||||
i::HandleScope scope(isolate);
|
||||
|
22
test/mjsunit/regress/regress-5636-1.js
Normal file
22
test/mjsunit/regress/regress-5636-1.js
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax --function-context-specialization
|
||||
|
||||
function f(n) {
|
||||
var a = [];
|
||||
function g() { return x }
|
||||
for (var i = 0; i < n; ++i) {
|
||||
var x = i;
|
||||
a[i] = g;
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
g();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
var a = f(3);
|
||||
assertEquals(3, a.length);
|
||||
assertEquals(2, a[0]());
|
||||
assertEquals(2, a[1]());
|
||||
assertEquals(2, a[2]());
|
23
test/mjsunit/regress/regress-5636-2.js
Normal file
23
test/mjsunit/regress/regress-5636-2.js
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2016 the V8 project authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
// Flags: --allow-natives-syntax
|
||||
|
||||
function f(n) {
|
||||
"use asm";
|
||||
var a = [];
|
||||
function g() { return x }
|
||||
for (var i = 0; i < n; ++i) {
|
||||
var x = i;
|
||||
a[i] = g;
|
||||
%OptimizeFunctionOnNextCall(g);
|
||||
g();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
var a = f(3);
|
||||
assertEquals(3, a.length);
|
||||
assertEquals(2, a[0]());
|
||||
assertEquals(2, a[1]());
|
||||
assertEquals(2, a[2]());
|
Loading…
Reference in New Issue
Block a user