Commit 7ffdb519 authored by dslomov's avatar dslomov Committed by Commit bot

[destructuring] Grand for statement parsing unification.

Also support patterns in ``for (var p in/of ...)``

This CL extends the rewriting we used to do for ``for (let p in/of...)`` to
``for (var p in/of ...)``. For all for..in/of loop declaring variable,
we rewrite
   for (var/let/const pattern in/of e) b
into
   for (x' in/of e) { var/let/const pattern = e; b }

This adds a small complication for debugger: for a statement
   for (var v in/of e) ...
we used to have
   var v;
   for (v in/of e) ...
and there was a separate breakpoint on ``var v`` line.
This breakpoint is actually useless since it is immediately followed by
a breakpoint on evaluation of ``e``, so this CL removes that breakpoint
location.

Similiraly, for let, it used to be that
  for (let v in/of e) ...
became
  for (x' in/of e) { let v; v  = x'; ... }
``let v``generetaed a useless breakpoint (with the location at the
loop's head. This CL removes that breakpoint as well.

R=arv@chromium.org,rossberg@chromium.org
BUG=v8:811
LOG=N

Review URL: https://codereview.chromium.org/1149043005

Cr-Commit-Position: refs/heads/master@{#28565}
parent a40e85d6
This diff is collapsed.
......@@ -950,7 +950,8 @@ class Parser : public ParserBase<ParserTraits> {
VariableMode mode;
bool is_const;
bool needs_init;
int pos;
int declaration_pos;
int initialization_pos;
Token::Value init_op;
};
......
......@@ -51,7 +51,8 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
const AstRawString* name = pattern->raw_name();
VariableProxy* proxy = parser->NewUnresolved(name, descriptor_->mode);
Declaration* declaration = factory()->NewVariableDeclaration(
proxy, descriptor_->mode, descriptor_->scope, descriptor_->pos);
proxy, descriptor_->mode, descriptor_->scope,
descriptor_->declaration_pos);
Variable* var = parser->Declare(declaration, descriptor_->mode != VAR, ok_);
if (!*ok_) return;
DCHECK_NOT_NULL(var);
......@@ -126,7 +127,9 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
ZoneList<Expression*>* arguments =
new (zone()) ZoneList<Expression*>(3, zone());
// We have at least 1 parameter.
arguments->Add(factory()->NewStringLiteral(name, descriptor_->pos), zone());
arguments->Add(
factory()->NewStringLiteral(name, descriptor_->declaration_pos),
zone());
CallRuntime* initialize;
if (descriptor_->is_const) {
......@@ -140,13 +143,14 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
initialize = factory()->NewCallRuntime(
ast_value_factory()->initialize_const_global_string(),
Runtime::FunctionForId(Runtime::kInitializeConstGlobal), arguments,
descriptor_->pos);
descriptor_->initialization_pos);
} else {
// Add language mode.
// We may want to pass singleton to avoid Literal allocations.
LanguageMode language_mode = initialization_scope->language_mode();
arguments->Add(
factory()->NewNumberLiteral(language_mode, descriptor_->pos), zone());
arguments->Add(factory()->NewNumberLiteral(language_mode,
descriptor_->declaration_pos),
zone());
// Be careful not to assign a value to the global variable if
// we're in a with. The initialization value should not
......@@ -160,7 +164,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
initialize = factory()->NewCallRuntime(
ast_value_factory()->initialize_var_global_string(),
Runtime::FunctionForId(Runtime::kInitializeVarGlobal), arguments,
descriptor_->pos);
descriptor_->declaration_pos);
} else {
initialize = NULL;
}
......@@ -184,7 +188,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
DCHECK_NOT_NULL(proxy->var());
DCHECK_NOT_NULL(value);
Assignment* assignment = factory()->NewAssignment(
descriptor_->init_op, proxy, value, descriptor_->pos);
descriptor_->init_op, proxy, value, descriptor_->initialization_pos);
block_->AddStatement(
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
zone());
......@@ -200,7 +204,7 @@ void Parser::PatternRewriter::VisitVariableProxy(VariableProxy* pattern) {
// property).
VariableProxy* proxy = initialization_scope->NewUnresolved(factory(), name);
Assignment* assignment = factory()->NewAssignment(
descriptor_->init_op, proxy, value, descriptor_->pos);
descriptor_->init_op, proxy, value, descriptor_->initialization_pos);
block_->AddStatement(
factory()->NewExpressionStatement(assignment, RelocInfo::kNoPosition),
zone());
......
......@@ -6525,6 +6525,32 @@ TEST(DestructuringNegativeTests) {
}
TEST(DestructuringDisallowPatternsInForVarIn) {
i::FLAG_harmony_destructuring = true;
static const ParserFlag always_flags[] = {kAllowHarmonyDestructuring};
const char* context_data[][2] = {
{"", ""}, {"function f() {", "}"}, {NULL, NULL}};
// clang-format off
const char* error_data[] = {
"for (var {x} = {} in null);",
"for (var {x} = {} of null);",
"for (let x = {} in null);",
"for (let x = {} of null);",
NULL};
// clang-format on
RunParserSyncTest(context_data, error_data, kError, NULL, 0, always_flags,
arraysize(always_flags));
// clang-format off
const char* success_data[] = {
"for (var x = {} in null);",
NULL};
// clang-format on
RunParserSyncTest(context_data, success_data, kSuccess, NULL, 0, always_flags,
arraysize(always_flags));
}
TEST(SpreadArray) {
i::FLAG_harmony_spread_arrays = true;
......
......@@ -81,28 +81,28 @@ Debug.setListener(listener);
f();
Debug.setListener(null); // Break z
print(JSON.stringify(log));
print("log:\n"+ JSON.stringify(log));
// The let declaration differs from var in that the loop variable
// is declared in every iteration.
var expected = [
// Entry
"a2","b2",
// Empty for-in-var: var decl, get enumerable
"c7","c16",
// Empty for-in-var: get enumerable
"c16",
// Empty for-in: get enumerable
"d12",
// For-in-var: var decl, get enumerable, assign, body, assign, body, ...
"e7","e16","e11","E4","e11","E4","e11","E4","e11",
// For-in-var: get enumerable, assign, body, assign, body, ...
"e16","e11","E4","e11","E4","e11","E4","e11",
// For-in: get enumerable, assign, body, assign, body, ...
"f12","f7","F4","f7","F4","f7","F4","f7",
// For-in-let: get enumerable, next, new let, body, next, new let, ...
"g16","g11","g7","G4","g11","g7","G4","g11","g7","G4","g11",
// For-of-var: var decl, next(), body, next(), body, ...
"h7","h16","H4","h16","H4","h16","H4","h16",
// For-in-let: get enumerable, next, body, next, ...
"g16","g11","G4","g11","G4","g11","G4","g11",
// For-of-var: next(), body, next(), body, ...
"h16","H4","h16","H4","h16","H4","h16",
// For-of: next(), body, next(), body, ...
"i12","I4","i12","I4","i12","I4","i12",
// For-of-let: next(), new let, body, next(), new let, ...
"j16","j7","J4","j16","j7","J4","j16","j7","J4","j16",
// For-of-let: next(), body, next(), ...
"j16","J4","j16","J4","j16","J4","j16",
// For-var: var decl, condition, body, next, condition, body, ...
"k7","k20","K4","k23","k20","K4","k23","k20","K4","k23","k20",
// For: init, condition, body, next, condition, body, ...
......@@ -110,6 +110,7 @@ var expected = [
// Exit.
"y0","z0",
]
print("expected:\n"+ JSON.stringify(log));
assertArrayEquals(expected, log);
assertEquals(48, s);
......
......@@ -645,8 +645,7 @@
assertSame(-(i+1), fy());
}
var o = { 'a1':1, 'b2':2 };
o.__proto__ = null;
var o = { __proto__:null, 'a1':1, 'b2':2 };
let sx = '';
let sy = '';
for (let [x,y] in o) {
......@@ -656,3 +655,34 @@
assertEquals('ab', sx);
assertEquals('12', sy);
}());
(function TestForEachVars() {
var a = [{x:1, y:-1}, {x:2,y:-2}, {x:3,y:-3}];
var sumX = 0;
var sumY = 0;
var fs = [];
for (var {x,y} of a) {
sumX += x;
sumY += y;
fs.push({fx : function() { return x; }, fy : function() { return y }});
}
assertSame(6, sumX);
assertSame(-6, sumY);
assertSame(3, fs.length);
for (var i = 0; i < fs.length; i++) {
var {fx,fy} = fs[i];
assertSame(3, fx());
assertSame(-3, fy());
}
var o = { __proto__:null, 'a1':1, 'b2':2 };
var sx = '';
var sy = '';
for (var [x,y] in o) {
sx += x;
sy += y;
}
assertEquals('ab', sx);
assertEquals('12', sy);
}());
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