summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Generators/syntax.js
blob: b2fec3bcc3d109e99577c6d62e5c1e042745225c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// This file was written by Andy Wingo <wingo@igalia.com> 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 isn't let-bound in F/G, so this is valid.
function f() { (function yield() {}); }
function* g() { (function yield() {}); }

// The name of the NFE is let-bound in the function/generator expression, so this is invalid.
assertSyntaxError("function f() { (function* yield() {}); }");
assertSyntaxError("function* g() { (function* yield() {}); }");

// The name of the declaration is let-bound in F, so this is valid.
function f() { function yield() {} }
function f() { function* yield() {} }

// The name of the declaration is let-bound in G, so this is invalid.
assertSyntaxError("function* g() { function yield() {} }");
assertSyntaxError("function* g() { 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);