michael@0: // This file was written by Andy Wingo and originally michael@0: // contributed to V8 as generators-parsing.js, available here: michael@0: // michael@0: // http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-parsing.js michael@0: michael@0: function assertSyntaxError(str) { michael@0: var msg; michael@0: var evil = eval; michael@0: try { michael@0: // Non-direct eval. michael@0: evil(str); michael@0: } catch (exc) { michael@0: if (exc instanceof SyntaxError) michael@0: return; michael@0: msg = "Assertion failed: expected SyntaxError, got " + exc; michael@0: } michael@0: if (msg === undefined) michael@0: msg = "Assertion failed: expected SyntaxError, but no exception thrown"; michael@0: throw new Error(msg + " - " + str); michael@0: } michael@0: michael@0: // Yield statements. michael@0: function* g() { yield 3; yield 4; } michael@0: michael@0: // Yield expressions. michael@0: function* g() { (yield 3) + (yield 4); } michael@0: michael@0: // You can have a generator in strict mode. michael@0: function* g() { "use strict"; yield 3; yield 4; } michael@0: michael@0: // Generators can have return statements also, which internally parse to a kind michael@0: // of yield expression. michael@0: function* g() { yield 1; return; } michael@0: function* g() { yield 1; return 2; } michael@0: function* g() { yield 1; return 2; yield "dead"; } michael@0: michael@0: // Generator expression. michael@0: (function* () { yield 3; }); michael@0: michael@0: // Named generator expression. michael@0: (function* g() { yield 3; }); michael@0: michael@0: // Generators do not have to contain yield expressions. michael@0: function* g() { } michael@0: michael@0: // YieldExpressions can occur in the RHS of a YieldExpression. michael@0: function* g() { yield yield 1; } michael@0: function* g() { yield 3 + (yield 4); } michael@0: michael@0: // Generator definitions with a name of "yield" are not specifically ruled out michael@0: // by the spec, as the `yield' name is outside the generator itself. However, michael@0: // in strict-mode, "yield" is an invalid identifier. michael@0: function* yield() { (yield 3) + (yield 4); } michael@0: assertSyntaxError("function* yield() { 'use strict'; (yield 3) + (yield 4); }"); michael@0: michael@0: // In classic mode, yield is a normal identifier, outside of generators. michael@0: function yield(yield) { yield: yield (yield + yield (0)); } michael@0: michael@0: // Yield is always valid as a key in an object literal. michael@0: ({ yield: 1 }); michael@0: function* g() { yield ({ yield: 1 }) } michael@0: function* g() { yield ({ get yield() { return 1; }}) } michael@0: michael@0: // Yield is a valid property name. michael@0: function* g(obj) { yield obj.yield; } michael@0: michael@0: // Checks that yield is a valid label in classic mode, but not valid in a strict michael@0: // mode or in generators. michael@0: function f() { yield: 1 } michael@0: assertSyntaxError("function f() { 'use strict'; yield: 1 }") michael@0: assertSyntaxError("function* g() { yield: 1 }") michael@0: michael@0: // Yield is only a keyword in the body of the generator, not in nested michael@0: // functions. michael@0: function* g() { function f(yield) { yield (yield + yield (0)); } } michael@0: michael@0: // Yield needs a RHS. michael@0: assertSyntaxError("function* g() { yield; }"); michael@0: michael@0: // Yield in a generator is not an identifier. michael@0: assertSyntaxError("function* g() { yield = 10; }"); michael@0: michael@0: // Yield binds very loosely, so this parses as "yield (3 + yield 4)", which is michael@0: // invalid. michael@0: assertSyntaxError("function* g() { yield 3 + yield 4; }"); michael@0: michael@0: // Yield is still a future-reserved-word in strict mode michael@0: assertSyntaxError("function f() { 'use strict'; var yield = 13; }"); michael@0: michael@0: // The name of the NFE is let-bound in G, so is invalid. michael@0: assertSyntaxError("function* g() { yield (function yield() {}); }"); michael@0: michael@0: // In generators, yield is invalid as a formal argument name. michael@0: assertSyntaxError("function* g(yield) { yield (10); }"); michael@0: michael@0: if (typeof reportCompare == "function") michael@0: reportCompare(true, true);