michael@0: // This file was written by Andy Wingo and originally michael@0: // contributed to V8 as generators-runtime.js, available here: michael@0: // michael@0: // http://code.google.com/p/v8/source/browse/branches/bleeding_edge/test/mjsunit/harmony/generators-runtime.js michael@0: michael@0: // Test aspects of the generator runtime. michael@0: michael@0: // See http://people.mozilla.org/~jorendorff/es6-draft.html#sec-15.19.3. michael@0: michael@0: function assertSyntaxError(str) { michael@0: assertThrowsInstanceOf(Function(str), SyntaxError); michael@0: } michael@0: michael@0: michael@0: function f() { } michael@0: function* g() { yield 1; } michael@0: var GeneratorFunctionPrototype = Object.getPrototypeOf(g); michael@0: var GeneratorFunction = GeneratorFunctionPrototype.constructor; michael@0: var GeneratorObjectPrototype = GeneratorFunctionPrototype.prototype; michael@0: // FIXME: This should be a symbol. michael@0: var std_iterator = "@@iterator"; michael@0: michael@0: michael@0: // A generator function should have the same set of properties as any michael@0: // other function. michael@0: function TestGeneratorFunctionInstance() { michael@0: var f_own_property_names = Object.getOwnPropertyNames(f); michael@0: var g_own_property_names = Object.getOwnPropertyNames(g); michael@0: michael@0: f_own_property_names.sort(); michael@0: g_own_property_names.sort(); michael@0: michael@0: assertDeepEq(f_own_property_names, g_own_property_names); michael@0: var i; michael@0: for (i = 0; i < f_own_property_names.length; i++) { michael@0: var prop = f_own_property_names[i]; michael@0: var f_desc = Object.getOwnPropertyDescriptor(f, prop); michael@0: var g_desc = Object.getOwnPropertyDescriptor(g, prop); michael@0: assertEq(f_desc.configurable, g_desc.configurable, prop); michael@0: assertEq(f_desc.writable, g_desc.writable, prop); michael@0: assertEq(f_desc.enumerable, g_desc.enumerable, prop); michael@0: } michael@0: } michael@0: TestGeneratorFunctionInstance(); michael@0: michael@0: michael@0: // Generators have an additional object interposed in the chain between michael@0: // themselves and Function.prototype. michael@0: function TestGeneratorFunctionPrototype() { michael@0: // Sanity check. michael@0: assertEq(Object.getPrototypeOf(f), Function.prototype); michael@0: assertNotEq(GeneratorFunctionPrototype, Function.prototype); michael@0: assertEq(Object.getPrototypeOf(GeneratorFunctionPrototype), michael@0: Function.prototype); michael@0: assertEq(Object.getPrototypeOf(function* () {}), michael@0: GeneratorFunctionPrototype); michael@0: } michael@0: TestGeneratorFunctionPrototype(); michael@0: michael@0: michael@0: // Functions that we associate with generator objects are actually defined by michael@0: // a common prototype. michael@0: function TestGeneratorObjectPrototype() { michael@0: assertEq(Object.getPrototypeOf(GeneratorObjectPrototype), michael@0: Object.prototype); michael@0: assertEq(Object.getPrototypeOf((function*(){yield 1}).prototype), michael@0: GeneratorObjectPrototype); michael@0: michael@0: var expected_property_names = ["next", "throw", "constructor", std_iterator]; michael@0: var found_property_names = michael@0: Object.getOwnPropertyNames(GeneratorObjectPrototype); michael@0: michael@0: expected_property_names.sort(); michael@0: found_property_names.sort(); michael@0: michael@0: assertDeepEq(found_property_names, expected_property_names); michael@0: } michael@0: TestGeneratorObjectPrototype(); michael@0: michael@0: michael@0: // This tests the object that would be called "GeneratorFunction", if it were michael@0: // like "Function". michael@0: function TestGeneratorFunction() { michael@0: assertEq(GeneratorFunctionPrototype, GeneratorFunction.prototype); michael@0: assertTrue(g instanceof GeneratorFunction); michael@0: michael@0: assertEq(Function, Object.getPrototypeOf(GeneratorFunction)); michael@0: assertTrue(g instanceof Function); michael@0: michael@0: assertEq("function* g() { yield 1; }", g.toString()); michael@0: michael@0: // Not all functions are generators. michael@0: assertTrue(f instanceof Function); // Sanity check. michael@0: assertFalse(f instanceof GeneratorFunction); michael@0: michael@0: assertTrue((new GeneratorFunction()) instanceof GeneratorFunction); michael@0: assertTrue(GeneratorFunction() instanceof GeneratorFunction); michael@0: michael@0: assertTrue(GeneratorFunction('yield 1') instanceof GeneratorFunction); michael@0: assertTrue(GeneratorFunction('return 1') instanceof GeneratorFunction); michael@0: assertTrue(GeneratorFunction('a', 'yield a') instanceof GeneratorFunction); michael@0: assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction); michael@0: assertTrue(GeneratorFunction('a', 'return a') instanceof GeneratorFunction); michael@0: assertSyntaxError("GeneratorFunction('yield', 'return yield')"); michael@0: assertTrue(GeneratorFunction('with (x) return foo;') instanceof GeneratorFunction); michael@0: assertSyntaxError("GeneratorFunction('\"use strict\"; with (x) return foo;')"); michael@0: michael@0: // Doesn't matter particularly what string gets serialized, as long michael@0: // as it contains "function*" and "yield 10". michael@0: assertEq(GeneratorFunction('yield 10').toString(), michael@0: "function* anonymous() {\nyield 10\n}"); michael@0: } michael@0: TestGeneratorFunction(); michael@0: michael@0: michael@0: function TestPerGeneratorPrototype() { michael@0: assertNotEq((function*(){}).prototype, (function*(){}).prototype); michael@0: assertNotEq((function*(){}).prototype, g.prototype); michael@0: assertEq(typeof GeneratorFunctionPrototype, "object"); michael@0: assertEq(g.prototype.__proto__.constructor, GeneratorFunctionPrototype, "object"); michael@0: assertEq(Object.getPrototypeOf(g.prototype), GeneratorObjectPrototype); michael@0: assertFalse(g.prototype instanceof Function); michael@0: assertEq(typeof (g.prototype), "object"); michael@0: michael@0: assertDeepEq(Object.getOwnPropertyNames(g.prototype), []); michael@0: } michael@0: TestPerGeneratorPrototype(); michael@0: michael@0: michael@0: if (typeof reportCompare == "function") michael@0: reportCompare(true, true);