// This file was written by Andy Wingo 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(\n) {\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);