Disallow for-in initializers that use let (bug 617288, r=brendan).

This commit is contained in:
David Anderson 2011-01-10 16:58:22 -08:00
Родитель 74c6a2a4ed
Коммит 465388a7f4
10 изменённых файлов: 40 добавлений и 163 удалений

Просмотреть файл

@ -347,3 +347,5 @@ MSG_DEF(JSMSG_BAD_CLONE_VERSION, 264, 0, JSEXN_ERR, "unsupported structured
MSG_DEF(JSMSG_CANT_CLONE_OBJECT, 265, 0, JSEXN_TYPEERR, "can't clone object")
MSG_DEF(JSMSG_NON_NATIVE_SCOPE, 266, 0, JSEXN_TYPEERR, "non-native scope object")
MSG_DEF(JSMSG_STRICT_FUNCTION_STATEMENT, 267, 0, JSEXN_SYNTAXERR, "in strict mode code, functions may be declared only at top level or immediately within another function")
MSG_DEF(JSMSG_INVALID_FOR_IN_INIT, 268, 0, JSEXN_SYNTAXERR, "for-in loop let declaration may not have an initializer")

Просмотреть файл

@ -5133,10 +5133,9 @@ Parser::forStatement()
pn1->pn_xflags |= PNX_FORINVAR;
/*
* Rewrite 'for (<decl> x = i in o)' where <decl> is 'let',
* 'var', or 'const' to hoist the initializer or the entire
* decl out of the loop head. TOK_VAR is the type for both
* 'var' and 'const'.
* Rewrite 'for (<decl> x = i in o)' where <decl> is 'var' or
* 'const' to hoist the initializer or the entire decl out of
* the loop head. TOK_VAR is the type for both 'var' and 'const'.
*/
pn2 = pn1->pn_head;
if ((pn2->pn_type == TOK_NAME && pn2->maybeExpr())
@ -5144,76 +5143,52 @@ Parser::forStatement()
|| pn2->pn_type == TOK_ASSIGN
#endif
) {
#if JS_HAS_BLOCK_SCOPE
if (tt == TOK_LET) {
reportErrorNumber(pn2, JSREPORT_ERROR, JSMSG_INVALID_FOR_IN_INIT);
return NULL;
}
#endif /* JS_HAS_BLOCK_SCOPE */
pnseq = ListNode::create(tc);
if (!pnseq)
return NULL;
pnseq->pn_type = TOK_SEQ;
pnseq->pn_pos.begin = pn->pn_pos.begin;
#if JS_HAS_BLOCK_SCOPE
if (tt == TOK_LET) {
/*
* Hoist just the 'i' from 'for (let x = i in o)' to
* before the loop, glued together via pnseq.
*/
JSParseNode *pn3 = UnaryNode::create(tc);
if (!pn3)
return NULL;
pn3->pn_type = TOK_SEMI;
pn3->pn_op = JSOP_NOP;
JSParseNode *pn4;
dflag = PND_INITIALIZED;
/*
* All of 'var x = i' is hoisted above 'for (x in o)',
* so clear PNX_FORINVAR.
*
* Request JSOP_POP here since the var is for a simple
* name (it is not a destructuring binding's left-hand
* side) and it has an initializer.
*/
pn1->pn_xflags &= ~PNX_FORINVAR;
pn1->pn_xflags |= PNX_POPVAR;
pnseq->initList(pn1);
#if JS_HAS_DESTRUCTURING
if (pn2->pn_type == TOK_ASSIGN) {
pn4 = pn2->pn_right;
pn2 = pn1->pn_head = pn2->pn_left;
} else
#endif
{
pn4 = pn2->pn_expr;
pn2->pn_expr = NULL;
}
if (!RebindLets(pn4, tc))
if (pn2->pn_type == TOK_ASSIGN) {
pn1 = CloneParseTree(pn2->pn_left, tc);
if (!pn1)
return NULL;
pn3->pn_pos = pn4->pn_pos;
pn3->pn_kid = pn4;
pnseq->initList(pn3);
} else
#endif /* JS_HAS_BLOCK_SCOPE */
{
dflag = PND_INITIALIZED;
/*
* All of 'var x = i' is hoisted above 'for (x in o)',
* so clear PNX_FORINVAR.
*
* Request JSOP_POP here since the var is for a simple
* name (it is not a destructuring binding's left-hand
* side) and it has an initializer.
*/
pn1->pn_xflags &= ~PNX_FORINVAR;
pn1->pn_xflags |= PNX_POPVAR;
pnseq->initList(pn1);
#if JS_HAS_DESTRUCTURING
if (pn2->pn_type == TOK_ASSIGN) {
pn1 = CloneParseTree(pn2->pn_left, tc);
if (!pn1)
return NULL;
} else
#endif
{
JS_ASSERT(pn2->pn_type == TOK_NAME);
pn1 = NameNode::create(pn2->pn_atom, tc);
if (!pn1)
return NULL;
pn1->pn_type = TOK_NAME;
pn1->pn_op = JSOP_NAME;
pn1->pn_pos = pn2->pn_pos;
if (pn2->pn_defn)
LinkUseToDef(pn1, (JSDefinition *) pn2, tc);
}
pn2 = pn1;
{
JS_ASSERT(pn2->pn_type == TOK_NAME);
pn1 = NameNode::create(pn2->pn_atom, tc);
if (!pn1)
return NULL;
pn1->pn_type = TOK_NAME;
pn1->pn_op = JSOP_NAME;
pn1->pn_pos = pn2->pn_pos;
if (pn2->pn_defn)
LinkUseToDef(pn1, (JSDefinition *) pn2, tc);
}
pn2 = pn1;
}
}

Просмотреть файл

@ -1,6 +1,5 @@
url-prefix ../../jsreftest.html?test=js1_7/decompilation/
skip script regress-346642-01.js # obsolete test
script regress-348904.js
script regress-349493.js
script regress-349499.js
skip script regress-349602.js # obsolete test

Просмотреть файл

@ -1,66 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is JavaScript Engine testing utilities.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Jesse Ruderman
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
//-----------------------------------------------------------------------------
var BUGNUMBER = 348904;
var summary = 'decompilation for "let" in lvalue part of for..in';
var actual = '';
var expect = '';
//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------
function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);
var f = function () { for (let i = 3 in {}); }
actual = f + '';
expect = 'function () {\n for (let i in {}) {\n }\n}';
compareSource(expect, actual, summary);
var f = function () { for (let i = (y = 4) in {}); }
actual = f + '';
expect = 'function () {\n y = 4;\n for (let i in {}) {\n }\n}';
compareSource(expect, actual, summary);
exitFunc ('test');
}

Просмотреть файл

@ -160,11 +160,6 @@ function test()
actual = f + '';
compareSource(expect, actual, summary + ': 21');
f = (function() { for ( let [a,b]=[c,d] in [3]) { } })
expect = 'function() { [c, d]; for ( let [a,b] in [3]) { } }';
actual = f + '';
compareSource(expect, actual, summary + ': 22');
f = function () { while(1) [a] = [b]; }
expect = 'function () { while(true) {[a] = [b];} } ';
actual = f + '';

Просмотреть файл

@ -85,16 +85,6 @@ function test()
(function(q){return q;} for each (\u3056 in []))
// =====
try
{
for(let x = <{x}/> in <y/>) x2;
}
catch(ex)
{
}
// =====
for(

Просмотреть файл

@ -54,15 +54,6 @@ function test()
// ------- Comment #98 From Gary Kwong [:nth10sd]
try
{
for(let [x] = (x) in []) {}
// Assertion failure: !(pnu->pn_dflags & PND_BOUND), at ../jsemit.cpp:1818
}
catch(ex)
{
}
uneval(function(){(Number(0) for each (NaN in []) for each (x4 in this))});
// Assertion failure: pos == 0, at ../jsopcode.cpp:2963

Просмотреть файл

@ -74,10 +74,6 @@ function test()
// =====
function this ({x}) { function x(){} }
// Assertion failure: cg->stackDepth == stackDepth, at ../jsemit.cpp:3664
// =====
for(let x = [ "" for (y in /x/g ) if (x)] in (""));
// Assertion failure: !(pnu->pn_dflags & PND_BOUND), at ../jsemit.cpp:1818
// =====
(function(){const x = 0, y = delete x;})()

Просмотреть файл

@ -598,13 +598,9 @@ assertError("for each (const [x,y,z] in foo);", SyntaxError);
// destructuring in for-in and for-each-in loop heads with initializers
assertStmt("for (var {a:x,b:y,c:z} = 22 in foo);", forInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (let {a:x,b:y,c:z} = 22 in foo);", forInStmt(letDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (var [x,y,z] = 22 in foo);", forInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for (let [x,y,z] = 22 in foo);", forInStmt(letDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (var {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(varDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (let {a:x,b:y,c:z} = 22 in foo);", forEachInStmt(letDecl([{ id: axbycz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (var [x,y,z] = 22 in foo);", forEachInStmt(varDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertStmt("for each (let [x,y,z] = 22 in foo);", forEachInStmt(letDecl([{ id: xyz, init: lit(22) }]), ident("foo"), emptyStmt));
assertError("for (x = 22 in foo);", SyntaxError);
assertError("for ({a:x,b:y,c:z} = 22 in foo);", SyntaxError);
assertError("for ([x,y,z] = 22 in foo);", SyntaxError);

Просмотреть файл

@ -964,7 +964,6 @@ js1_7/block/regress-352907.js
js1_7/block/regress-376410.js
js1_7/block/regress-396900.js
js1_7/block/regress-411279.js
js1_7/decompilation/regress-348904.js
js1_7/decompilation/regress-349493.js
js1_7/decompilation/regress-349499.js
js1_7/decompilation/regress-349633.js