|
1 // This file was written by Andy Wingo <wingo@igalia.com> and originally |
|
2 // contributed to V8 as generators-runtime.js, available here: |
|
3 // |
|
4 // http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-runtime.js |
|
5 |
|
6 // Test aspects of the generator runtime. |
|
7 |
|
8 // See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3. |
|
9 |
|
10 function assertSyntaxError(str) { |
|
11 assertThrowsInstanceOf(Function(str), SyntaxError); |
|
12 } |
|
13 |
|
14 |
|
15 function f() { } |
|
16 function* g() { yield 1; } |
|
17 var GeneratorFunctionPrototype = Object.getPrototypeOf(g); |
|
18 var GeneratorFunction = GeneratorFunctionPrototype.constructor; |
|
19 var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; |
|
20 // FIXME: This should be a symbol. |
|
21 var std_iterator = "@@iterator"; |
|
22 |
|
23 |
|
24 // A generator function should have the same set of properties as any |
|
25 // other function. |
|
26 function TestGeneratorFunctionInstance() { |
|
27 var f_own_property_names = Object.getOwnPropertyNames(f); |
|
28 var g_own_property_names = Object.getOwnPropertyNames(g); |
|
29 |
|
30 f_own_property_names.sort(); |
|
31 g_own_property_names.sort(); |
|
32 |
|
33 assertDeepEq(f_own_property_names, g_own_property_names); |
|
34 var i; |
|
35 for (i = 0; i < f_own_property_names.length; i++) { |
|
36 var prop = f_own_property_names[i]; |
|
37 var f_desc = Object.getOwnPropertyDescriptor(f, prop); |
|
38 var g_desc = Object.getOwnPropertyDescriptor(g, prop); |
|
39 assertEq(f_desc.configurable, g_desc.configurable, prop); |
|
40 assertEq(f_desc.writable, g_desc.writable, prop); |
|
41 assertEq(f_desc.enumerable, g_desc.enumerable, prop); |
|
42 } |
|
43 } |
|
44 TestGeneratorFunctionInstance(); |
|
45 |
|
46 |
|
47 // Generators have an additional object interposed in the chain between |
|
48 // themselves and Function.prototype. |
|
49 function TestGeneratorFunctionPrototype() { |
|
50 // Sanity check. |
|
51 assertEq(Object.getPrototypeOf(f), Function.prototype); |
|
52 assertNotEq(GeneratorFunctionPrototype, Function.prototype); |
|
53 assertEq(Object.getPrototypeOf(GeneratorFunctionPrototype), |
|
54 Function.prototype); |
|
55 assertEq(Object.getPrototypeOf(function* () {}), |
|
56 GeneratorFunctionPrototype); |
|
57 } |
|
58 TestGeneratorFunctionPrototype(); |
|
59 |
|
60 |
|
61 // Functions that we associate with generator objects are actually defined by |
|
62 // a common prototype. |
|
63 function TestGeneratorObjectPrototype() { |
|
64 assertEq(Object.getPrototypeOf(GeneratorObjectPrototype), |
|
65 Object.prototype); |
|
66 assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype), |
|
67 GeneratorObjectPrototype); |
|
68 |
|
69 var expected_property_names = ["next", "throw", "constructor", std_iterator]; |
|
70 var found_property_names = |
|
71 Object.getOwnPropertyNames(GeneratorObjectPrototype); |
|
72 |
|
73 expected_property_names.sort(); |
|
74 found_property_names.sort(); |
|
75 |
|
76 assertDeepEq(found_property_names, expected_property_names); |
|
77 } |
|
78 TestGeneratorObjectPrototype(); |
|
79 |
|
80 |
|
81 // This tests the object that would be called "GeneratorFunction", if it were |
|
82 // like "Function". |
|
83 function TestGeneratorFunction() { |
|
84 assertEq(GeneratorFunctionPrototype, GeneratorFunction.prototype); |
|
85 assertTrue(g instanceof GeneratorFunction); |
|
86 |
|
87 assertEq(Function, Object.getPrototypeOf(GeneratorFunction)); |
|
88 assertTrue(g instanceof Function); |
|
89 |
|
90 assertEq("function* g() { yield 1; }", g.toString()); |
|
91 |
|
92 // Not all functions are generators. |
|
93 assertTrue(f instanceof Function); // Sanity check. |
|
94 assertFalse(f instanceof GeneratorFunction); |
|
95 |
|
96 assertTrue((new GeneratorFunction()) instanceof GeneratorFunction); |
|
97 assertTrue(GeneratorFunction() instanceof GeneratorFunction); |
|
98 |
|
99 assertTrue(GeneratorFunction('yield 1') instanceof GeneratorFunction); |
|
100 assertTrue(GeneratorFunction('return 1') instanceof GeneratorFunction); |
|
101 assertTrue(GeneratorFunction('a', 'yield a') instanceof GeneratorFunction); |
|
102 assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction); |
|
103 assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction); |
|
104 assertSyntaxError("GeneratorFunction('yield', 'return yield')"); |
|
105 assertTrue(GeneratorFunction('with (x) return foo;') instanceof GeneratorFunction); |
|
106 assertSyntaxError("GeneratorFunction('\"use strict\"; with (x) return foo;')"); |
|
107 |
|
108 // Doesn't matter particularly what string gets serialized, as long |
|
109 // as it contains "function*" and "yield 10". |
|
110 assertEq(GeneratorFunction('yield 10').toString(), |
|
111 "function* anonymous() {\nyield 10\n}"); |
|
112 } |
|
113 TestGeneratorFunction(); |
|
114 |
|
115 |
|
116 function TestPerGeneratorPrototype() { |
|
117 assertNotEq((function*(){}).prototype, (function*(){}).prototype); |
|
118 assertNotEq((function*(){}).prototype, g.prototype); |
|
119 assertEq(typeof GeneratorFunctionPrototype, "object"); |
|
120 assertEq(g.prototype.__proto__.constructor, GeneratorFunctionPrototype, "object"); |
|
121 assertEq(Object.getPrototypeOf(g.prototype), GeneratorObjectPrototype); |
|
122 assertFalse(g.prototype instanceof Function); |
|
123 assertEq(typeof (g.prototype), "object"); |
|
124 |
|
125 assertDeepEq(Object.getOwnPropertyNames(g.prototype), []); |
|
126 } |
|
127 TestPerGeneratorPrototype(); |
|
128 |
|
129 |
|
130 if (typeof reportCompare == "function") |
|
131 reportCompare(true, true); |