summaryrefslogtreecommitdiffstats
path: root/js/src/tests/ecma_6/Generators/runtime.js
blob: c4d3bb6a666b3f4122f487f174b0d6c70a09d661 (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
// This file was written by Andy Wingo <wingo@igalia.com> and originally
// contributed to V8 as generators-runtime.js, available here:
//
// http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-runtime.js

// Test aspects of the generator runtime.

// See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3.

function assertSyntaxError(str) {
    assertThrowsInstanceOf(Function(str), SyntaxError);
}


function f() { }
function* g() { yield 1; }
var GeneratorFunctionPrototype = Object.getPrototypeOf(g);
var GeneratorFunction = GeneratorFunctionPrototype.constructor;
var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype;


// A generator function should have the same set of properties as any
// other function.
function TestGeneratorFunctionInstance() {
    var f_own_property_names = Object.getOwnPropertyNames(f);
    var g_own_property_names = Object.getOwnPropertyNames(g);

    f_own_property_names.sort();
    g_own_property_names.sort();

    assertDeepEq(f_own_property_names, g_own_property_names);
    var i;
    for (i = 0; i < f_own_property_names.length; i++) {
        var prop = f_own_property_names[i];
        var f_desc = Object.getOwnPropertyDescriptor(f, prop);
        var g_desc = Object.getOwnPropertyDescriptor(g, prop);
        assertEq(f_desc.configurable, g_desc.configurable, prop);
        assertEq(f_desc.writable, g_desc.writable, prop);
        assertEq(f_desc.enumerable, g_desc.enumerable, prop);
    }
}
TestGeneratorFunctionInstance();


// Generators have an additional object interposed in the chain between
// themselves and Function.prototype.
function TestGeneratorFunctionPrototype() {
    // Sanity check.
    assertEq(Object.getPrototypeOf(f), Function.prototype);
    assertNotEq(GeneratorFunctionPrototype, Function.prototype);
    assertEq(Object.getPrototypeOf(GeneratorFunctionPrototype),
               Function.prototype);
    assertEq(Object.getPrototypeOf(function* () {}),
               GeneratorFunctionPrototype);
}
TestGeneratorFunctionPrototype();


// Functions that we associate with generator objects are actually defined by
// a common prototype.
function TestGeneratorObjectPrototype() {
    // %GeneratorPrototype% must inherit from %IteratorPrototype%.
    var iterProto = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
    assertEq(Object.getPrototypeOf(GeneratorObjectPrototype),
             iterProto);
    assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype),
             GeneratorObjectPrototype);

    var expected_property_names = ["next", "return", "throw", "constructor"];
    var found_property_names =
        Object.getOwnPropertyNames(GeneratorObjectPrototype);

    expected_property_names.sort();
    found_property_names.sort();

    assertDeepEq(found_property_names, expected_property_names);
    assertDeepEq(Object.getOwnPropertySymbols(GeneratorObjectPrototype), [Symbol.toStringTag]);
}
TestGeneratorObjectPrototype();


// This tests the object that would be called "GeneratorFunction", if it were
// like "Function".
function TestGeneratorFunction() {
    assertEq(GeneratorFunctionPrototype, GeneratorFunction.prototype);
    assertTrue(g instanceof GeneratorFunction);

    assertEq(Function, Object.getPrototypeOf(GeneratorFunction));
    assertTrue(g instanceof Function);

    assertEq("function* g() { yield 1; }", g.toString());

    // Not all functions are generators.
    assertTrue(f instanceof Function);  // Sanity check.
    assertFalse(f instanceof GeneratorFunction);

    assertTrue((new GeneratorFunction()) instanceof GeneratorFunction);
    assertTrue(GeneratorFunction() instanceof GeneratorFunction);

    assertTrue(GeneratorFunction('yield 1') instanceof GeneratorFunction);
    assertTrue(GeneratorFunction('return 1') instanceof GeneratorFunction);
    assertTrue(GeneratorFunction('a', 'yield a') instanceof GeneratorFunction);
    assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction);
    assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction);
    assertSyntaxError("GeneratorFunction('yield', 'return yield')");
    assertTrue(GeneratorFunction('with (x) return foo;') instanceof GeneratorFunction);
    assertSyntaxError("GeneratorFunction('\"use strict\"; with (x) return foo;')");

    // Doesn't matter particularly what string gets serialized, as long
    // as it contains "function*" and "yield 10".
    assertEq(GeneratorFunction('yield 10').toString(),
             "function* anonymous() {\nyield 10\n}");
}
TestGeneratorFunction();


function TestPerGeneratorPrototype() {
    assertNotEq((function*(){}).prototype, (function*(){}).prototype);
    assertNotEq((function*(){}).prototype, g.prototype);
    assertEq(typeof GeneratorFunctionPrototype, "object");
    assertEq(g.prototype.__proto__.constructor, GeneratorFunctionPrototype, "object");
    assertEq(Object.getPrototypeOf(g.prototype), GeneratorObjectPrototype);
    assertFalse(g.prototype instanceof Function);
    assertEq(typeof (g.prototype), "object");

    assertDeepEq(Object.getOwnPropertyNames(g.prototype), []);
}
TestPerGeneratorPrototype();


if (typeof reportCompare == "function")
    reportCompare(true, true);