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