Skip to content

Commit

Permalink
#430: fix reversions with legacy generators, restore/new tests
Browse files Browse the repository at this point in the history
  • Loading branch information
classilla committed Aug 25, 2017
1 parent a9e9d0b commit a05b152
Show file tree
Hide file tree
Showing 16 changed files with 190 additions and 12 deletions.
52 changes: 40 additions & 12 deletions js/src/frontend/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5910,7 +5910,7 @@ Parser<ParseHandler>::forStatement(YieldHandling yieldHandling)
if (matched) {
iflags = JSITER_FOREACH;
isForEach = true;
addTelemetry(JSCompartment::DeprecatedForEach);
//addTelemetry(JSCompartment::DeprecatedForEach);
if (versionNumber() < JSVERSION_LATEST) {
if (!report(ParseWarning, pc->sc->strict(), null(), JSMSG_DEPRECATED_FOR_EACH))
return null();
Expand Down Expand Up @@ -8392,7 +8392,7 @@ Parser<FullParseHandler>::legacyComprehensionTail(ParseNode* bodyExpr, unsigned
return null();
if (matched) {
pn2->pn_iflags |= JSITER_FOREACH;
addTelemetry(JSCompartment::DeprecatedForEach);
//addTelemetry(JSCompartment::DeprecatedForEach);
if (versionNumber() < JSVERSION_LATEST) {
if (!report(ParseWarning, pc->sc->strict(), pn2, JSMSG_DEPRECATED_FOR_EACH))
return null();
Expand Down Expand Up @@ -10084,16 +10084,6 @@ Parser<ParseHandler>::primaryExpr(YieldHandling yieldHandling, TripledotHandling
}
}

template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
return expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
}

// Legacy generator comprehensions can appear anywhere an expression is
// enclosed in parentheses, even if those parentheses are part of statement
// syntax or a function call:
Expand All @@ -10111,6 +10101,44 @@ Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHan
// sum(x*x for (x in y)); // ok
// sum(for (x of y) x*x); // SyntaxError: needs more parens
//
template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
TripledotHandling tripledotHandling,
PossibleError* possibleError)
{
MOZ_ASSERT(tokenStream.isCurrentTokenType(TOK_LP));
uint32_t begin = pos().begin;
uint32_t startYieldOffset = pc->lastYieldOffset;

Node pn = expr(inHandling, yieldHandling, tripledotHandling, possibleError, PredictInvoked);
if (!pn)
return null();

#if JS_HAS_GENERATOR_EXPRS
bool matched;
if (!tokenStream.matchToken(&matched, TOK_FOR))
return null();
if (matched) {
if (pc->lastYieldOffset != startYieldOffset) {
reportWithOffset(ParseError, false, pc->lastYieldOffset,
JSMSG_BAD_GENEXP_BODY, js_yield_str);
return null();
}
if (handler.isUnparenthesizedCommaExpression(pn)) {
report(ParseError, false, null(), JSMSG_BAD_GENERATOR_SYNTAX);
return null();
}
pn = legacyGeneratorExpr(pn);
if (!pn)
return null();
handler.setBeginPosition(pn, begin);
}
#endif /* JS_HAS_GENERATOR_EXPRS */

return pn;
}

template <typename ParseHandler>
typename ParseHandler::Node
Parser<ParseHandler>::exprInParens(InHandling inHandling, YieldHandling yieldHandling,
Expand Down
4 changes: 4 additions & 0 deletions js/src/jit-test/tests/arguments/defaults-bug790424.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
function f1(g=((function () { return 4; }) for (x of [1]))) {
return g.next()();
}
assertEq(f1(), 4);
1 change: 1 addition & 0 deletions js/src/jit-test/tests/arguments/defaults-strict-mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ assertEq(f3()()(), true);
// These should be okay.
function f4(f=(function () { with (Object) {} }), g=(function () { "use strict"; })) {}
function f5(g=(function () { "use strict"; }), f=(function () { with (Object) {} })) {}
function f6(f=(function () { return (x for (y in (function g() {}))); })) {}

assertThrowsInstanceOf(function () {
eval("'use strict'; function f(a=delete x) { }");
Expand Down
7 changes: 7 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// No 'arguments' binding in genexprs at toplevel.

load(libdir + "asserts.js");

delete this.arguments; // it is defined in the shell
var iter = (arguments for (x of [1]));
assertThrowsInstanceOf(() => iter.next(), ReferenceError);
4 changes: 4 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// 'arguments' is lexically scoped in genexprs at toplevel.

var arguments = 8;
assertEq((arguments for (x of [1])).next(), 8);
6 changes: 6 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// 'arguments' is lexically scoped in genexpr in toplevel let-block.

{
let arguments = [];
assertEq((arguments for (p in {a: 1})).next(), arguments);
}
7 changes: 7 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// 'arguments' is lexically scoped in genexpr in function.

function f() {
assertEq((arguments for (x of [0])).next(),
(arguments for (y of [1])).next());
}
f();
8 changes: 8 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-5.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// 'arguments' binding can be closed over and outlives the function activation.

function f() {
return (arguments for (x of [1]));
}

var args = f("ponies").next();
assertEq(args[0], "ponies");
12 changes: 12 additions & 0 deletions js/src/jit-test/tests/arguments/genexpr-6.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// 'arguments' works in nested genexprs.

function f() {
return ((((((arguments for (u of [0]))
for (v of [1]))
for (w of [2]))
for (x of [3]))
for (y of [4]))
for (z of [5]));
}
var args = f("ponies").next().next().next().next().next().next();
assertEq(args[0], "ponies");
10 changes: 10 additions & 0 deletions js/src/jit-test/tests/basic/bug790629-1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// 'this' in generator-expression in strict-mode toplevel
// is the same as global 'this'.

"use strict";

var it1 = (this for (x of [0]));
assertEq(it1.next(), this);

var it2 = (this for (x of (this for (y of (this for (z of [0]))))));
assertEq(it2.next(), this);
11 changes: 11 additions & 0 deletions js/src/jit-test/tests/basic/bug790629-2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 'this' in escaping generator-expression in a method
// is the same as 'this' in the enclosing method.

var obj = {
f: function () {
assertEq(this, obj);
return (this for (x of [0]));
}
};

assertEq(obj.f().next(), obj);
11 changes: 11 additions & 0 deletions js/src/jit-test/tests/basic/bug790629-3.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 'this' in escaping generator-expression in a method
// is the same as 'this' in the enclosing method
// even if the method does not otherwise use 'this'.

var obj = {
f: function () {
return (this for (x of [0]));
}
};

assertEq(obj.f().next(), obj);
13 changes: 13 additions & 0 deletions js/src/jit-test/tests/basic/bug790629-4.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 'this' in a generator-expression non-strict function produces the expected
// object.

Number.prototype.iters = function () {
return [(this for (x of [0])),
(this for (y of [0]))];
};

var [a, b] = (3).iters();
var three = a.next();
assertEq(Object.prototype.toString.call(three), '[object Number]');
assertEq(+three, 3);
assertEq(b.next(), three);
12 changes: 12 additions & 0 deletions js/src/jit-test/tests/basic/testLet.js
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,18 @@ test('try {for (let x in eval("throw x")) {}} catch (e) {return e;}', undefined,
test('try {for each (let x in x) {eval("throw x");}} catch (e) {return e;}', ['ponies'], undefined);
test('for each (let {x: y, y: x} in [{x: x, y: x}]) {return y;}', undefined, undefined);

// genexps
test('return (i for (i in x)).next();', {ponies:true});
test('return (eval("i") for (i in x)).next();', {ponies:true});
test('return (eval("i") for (i in eval("x"))).next();', {ponies:true});
test('try {return (eval("throw i") for (i in x)).next();} catch (e) {return e;}', {ponies:true});

// array comprehension
test('return [i for (i in x)][0];', {ponies:true});
test('return [eval("i") for (i in x)][0];', {ponies:true});
test('return [eval("i") for (i in eval("x"))][0];', {ponies:true});
test('try {return [eval("throw i") for (i in x)][0];} catch (e) {return e;}', {ponies:true});

// don't forget about switch craziness
test('var y = 3;switch (function () {return eval("y");}()) {case 3:let y;return x;default:;}');
test('switch (x) {case 3:let y;return 3;case 4:let z;return 4;default:return x;}');
Expand Down
14 changes: 14 additions & 0 deletions js/src/jit-test/tests/tenfourfox/legacy-generator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// array comprehensions
var data = "abcdefg";
var hexString = [
data.charCodeAt(i) for (i in data) if (data.charCodeAt(i) < 100)
].join(",");
assertEq(hexString, "97,98,99");

// generator comprehensions
var it = [1, 2, 3, 5, 8, 10, 13];
var w = (i*2 for (i of it) if (i & 1));
assertEq(w.next(), 2);
assertEq(w.next(), 6);
assertEq(w.next(), 10);
assertEq(w.next(), 26);
30 changes: 30 additions & 0 deletions js/src/tests/js1_8/regress-380237-02.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */


//-----------------------------------------------------------------------------
var BUGNUMBER = 380237;
var summary = 'Decompilation of generator expressions';
var actual = '';
var expect = '';


//-----------------------------------------------------------------------------
test();
//-----------------------------------------------------------------------------

function test()
{
enterFunc ('test');
printBugNumber(BUGNUMBER);
printStatus (summary);

var f = function() { g = (d for (d in [0])); g.next(); };
expect = 'function() { g = (d for (d in [0])); g.next(); }';
actual = f + '';
compareSource(expect, actual, summary);

exitFunc ('test');
}

0 comments on commit a05b152

Please sign in to comment.