blob: d327034dfe1a6f3df1067c1c528e18980ddeb70d [file] [log] [blame]
//-------------------------------------------------------------------------------------------------------
// Copyright (C) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
//-------------------------------------------------------------------------------------------------------
// ES6 Generators APIs tests -- verifies built-in API objects and properties
WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
var globObj = this;
function checkAttributes(name, o, p, a) {
var desc = Object.getOwnPropertyDescriptor(o, p);
var msgPrefix = "Property " + p.toString() + " on " + name + " is ";
assert.isTrue(!!desc, msgPrefix + "not found; there is no descriptor");
assert.areEqual(a.writable, desc.writable, msgPrefix + (a.writable ? "" : "not") + " writable");
assert.areEqual(a.enumerable, desc.enumerable, msgPrefix + (a.enumerable ? "" : "not") + " enumerable");
assert.areEqual(a.configurable, desc.configurable, msgPrefix + (a.configurable ? "" : "not") + " configurable");
}
var tests = [
{
name: "GeneratorFunction is not exposed on the global object",
body: function () {
assert.isFalse(globObj.hasOwnProperty("GeneratorFunction"), "Global object does not have property named GeneratorFunction");
}
},
{
name: "Generator function object instances have length, name, and prototype properties",
body: function () {
function* gf() { }
assert.isTrue(gf.hasOwnProperty("length"), "Generator function objects have a 'length' property");
assert.isTrue(gf.hasOwnProperty("name"), "Generator function objects have a 'name' property");
assert.isTrue(gf.hasOwnProperty("prototype"), "Generator function objects have a 'prototype' property");
checkAttributes("gf", gf, "length", { writable: false, enumerable: false, configurable: true });
checkAttributes("gf", gf, "name", { writable: false, enumerable: false, configurable: true });
checkAttributes("gf", gf, "prototype", { writable: true, enumerable: false, configurable: false });
function gf2(a, b, c) { }
assert.areEqual(0, gf.length, "Generator function object's 'length' property matches the number of parameters (0)");
assert.areEqual(3, gf2.length, "Generator function object's 'length' property matches the number of parameters (3)");
assert.areEqual("gf", gf.name, "Generator function object's 'name' property matches the function's name");
assert.isFalse(gf.prototype.hasOwnProperty("constructor"), "Generator function prototype objects do not get a 'constructor' property");
}
},
{
name: "arguments and caller properties are absent regardless of strictness",
body: function () {
function* gf() { }
assert.isFalse(gf.hasOwnProperty("arguments"), "Generator function objects do not have an 'arguments' property");
assert.isFalse(gf.hasOwnProperty("caller"), "Generator function objects do not have a 'caller' property");
// Test JavascriptGeneratorFunction APIs that special case PropertyIds::caller and ::arguments
Object.setPrototypeOf(gf, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
assert.isFalse("arguments" in gf, "Has operation on 'arguments' property returns false initially");
assert.areEqual(undefined, gf.arguments, "Get operation on 'arguments' property returns undefined initially");
assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gf, "arguments"), "No property descriptor for 'arguments' initially");
assert.isTrue(delete gf.arguments, "Delete operation on 'arguments' property returns true");
assert.areEqual(0, gf.arguments = 0, "Set operation on 'arguments' creates new property with assigned value");
assert.isTrue("arguments" in gf, "Has operation on 'arguments' property returns true now");
assert.areEqual(0, gf.arguments, "Get operation on 'arguments' property returns property value now");
checkAttributes("gf", gf, "arguments", { writable: true, enumerable: true, configurable: true });
assert.isTrue(delete gf.arguments, "Delete operation on 'arguments' property still returns true");
assert.isFalse(gf.hasOwnProperty("arguments"), "'arguments' property is gone");
assert.isFalse("caller" in gf, "Has operation on 'caller' property returns false initially");
assert.areEqual(undefined, gf.caller, "Get operation on 'caller' property returns undefined initially");
assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gf, "caller"), "No property descriptor for 'caller' initially");
assert.isTrue(delete gf.caller, "Delete operation on 'caller' property returns true");
assert.areEqual(0, gf.caller = 0, "Set operation on 'caller' creates new property with assigned value");
assert.isTrue("caller" in gf, "Has operation on 'caller' property returns true now");
assert.areEqual(0, gf.caller, "Get operation on 'caller' property returns property value now");
checkAttributes("gf", gf, "caller", { writable: true, enumerable: true, configurable: true });
assert.isTrue(delete gf.caller, "Delete operation on 'caller' property still returns true");
assert.isFalse(gf.hasOwnProperty("caller"), "'caller' property is gone");
function* gfstrict() { "use strict"; }
assert.isFalse(gfstrict.hasOwnProperty("arguments"), "Strict mode generator function objects do not have an 'arguments' property");
assert.isFalse(gfstrict.hasOwnProperty("caller"), "Strict mode generator function objects do not have a 'caller' property");
Object.setPrototypeOf(gfstrict, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
assert.isFalse("arguments" in gfstrict, "Has operation on 'arguments' property returns false initially for a strict mode generator function");
assert.areEqual(undefined, gfstrict.arguments, "Get operation on 'arguments' property returns undefined initially for a strict mode generator function");
assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gfstrict, "arguments"), "No property descriptor for 'arguments' initially for a strict mode generator function");
assert.isTrue(delete gfstrict.arguments, "Delete operation on 'arguments' property returns true initially for a strict mode generator function");
assert.areEqual(0, gfstrict.arguments = 0, "Set operation on 'arguments' creates new property with assigned value for a strict mode generator function");
assert.isTrue("arguments" in gfstrict, "Has operation on 'arguments' property returns true now for a strict mode generator function");
assert.areEqual(0, gfstrict.arguments, "Get operation on 'arguments' property returns property value now for a strict mode generator function");
checkAttributes("gfstrict", gfstrict, "arguments", { writable: true, enumerable: true, configurable: true });
assert.isTrue(delete gfstrict.arguments, "Delete operation on 'arguments' property still returns true for a strict mode generator function");
assert.isFalse(gfstrict.hasOwnProperty("arguments"), "'arguments' property is gone for a strict mode generator function");
assert.isFalse("caller" in gfstrict, "Has operation on 'caller' property returns false initially for a strict mode generator function");
assert.areEqual(undefined, gfstrict.caller, "Get operation on 'caller' property returns undefined initially for a strict mode generator function");
assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gfstrict, "caller"), "No property descriptor for 'caller' initially for a strict mode generator function");
assert.isTrue(delete gfstrict.caller, "Delete operation on 'caller' property returns true initially for a strict mode generator function");
assert.areEqual(0, gfstrict.caller = 0, "Set operation on 'caller' creates new property with assigned value for a strict mode generator function");
assert.isTrue("caller" in gfstrict, "Has operation on 'caller' property returns true now for a strict mode generator function");
assert.areEqual(0, gfstrict.caller, "Get operation on 'caller' property returns property value now for a strict mode generator function");
checkAttributes("gfstrict", gfstrict, "caller", { writable: true, enumerable: true, configurable: true });
assert.isTrue(delete gfstrict.caller, "Delete operation on 'caller' property still returns true for a strict mode generator function");
assert.isFalse(gfstrict.hasOwnProperty("caller"), "'caller' property is gone for a strict mode generator function");
}
},
{
name: "Generator functions' length property is the number of formal parameters",
body: function () {
function* gf0() { }
function* gf1(a) { }
function* gf5(a,b,c,d,e) { }
assert.areEqual(0, gf0.length, "Generator function with no formal parameters has length 0");
assert.areEqual(1, gf1.length, "Generator function with one formal parameter has length 1");
assert.areEqual(5, gf5.length, "Generator function with five formal parameters has length 5");
}
},
{
name: "Generator function instances have GeneratorFunction.prototype as their prototype and it has the specified properties and prototype",
body: function () {
function* gf() { }
var generatorFunctionPrototype = Object.getPrototypeOf(gf);
assert.areEqual(Function.prototype, Object.getPrototypeOf(generatorFunctionPrototype), "GeneratorFunction.prototype's prototype is Function.prototype");
assert.isTrue(generatorFunctionPrototype.hasOwnProperty("constructor"), "GeneratorFunction.prototype has 'constructor' property");
assert.isTrue(generatorFunctionPrototype.hasOwnProperty("prototype"), "GeneratorFunction.prototype has 'prototype' property");
assert.isTrue(generatorFunctionPrototype.hasOwnProperty(Symbol.toStringTag), "GeneratorFunction.prototype has [Symbol.toStringTag] property");
checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, "constructor", { writable: false, enumerable: false, configurable: true });
checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, "prototype", { writable: false, enumerable: false, configurable: true });
checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, Symbol.toStringTag, { writable: false, enumerable: false, configurable: true });
assert.areEqual("GeneratorFunction", generatorFunctionPrototype[Symbol.toStringTag], "GeneratorFunction.prototype's [Symbol.toStringTag] property is 'GeneratorFunction'");
}
},
{
name: "GeneratorFunction constructor is the value of the constructor property of GeneratorFunction.prototype and has the specified properties and prototype",
body: function () {
function* gf() { }
var generatorFunctionPrototype = Object.getPrototypeOf(gf);
var generatorFunctionConstructor = generatorFunctionPrototype.constructor;
assert.areEqual(Function, Object.getPrototypeOf(generatorFunctionConstructor), "GeneratorFunction's prototype is Function");
assert.isTrue(generatorFunctionConstructor.hasOwnProperty("name"), "GeneratorFunction has 'name' property");
assert.isTrue(generatorFunctionConstructor.hasOwnProperty("length"), "GeneratorFunction has 'length' property");
assert.isTrue(generatorFunctionConstructor.hasOwnProperty("prototype"), "GeneratorFunction has 'prototype' property");
checkAttributes("GeneratorFunction", generatorFunctionConstructor, "name", { writable: false, enumerable: false, configurable: true });
checkAttributes("GeneratorFunction", generatorFunctionConstructor, "length", { writable: false, enumerable: false, configurable: true });
checkAttributes("GeneratorFunction", generatorFunctionConstructor, "prototype", { writable: false, enumerable: false, configurable: false });
assert.areEqual("GeneratorFunction", generatorFunctionConstructor.name, "GeneratorFunction's 'name' property is 'GeneratorFunction'");
assert.areEqual(generatorFunctionPrototype, generatorFunctionConstructor.prototype, "GeneratorFunction's 'prototype' property is GeneratorFunction.prototype");
assert.areEqual(1, generatorFunctionConstructor.length, "GeneratorFunction's 'length' property is 1");
}
},
{
name: "Generator prototype is the value of the prototype property of GeneratorFunction.prototype and has the specified properties and prototype",
body: function () {
function* gf() { }
var generatorFunctionPrototype = Object.getPrototypeOf(gf);
var generatorPrototype = generatorFunctionPrototype.prototype;
var iteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
assert.areEqual(iteratorPrototype, Object.getPrototypeOf(generatorPrototype), "Generator prototype's prototype is %IteratorPrototype%");
assert.isTrue(generatorPrototype.hasOwnProperty("constructor"), "Generator prototype has 'constructor' property");
assert.isTrue(generatorPrototype.hasOwnProperty("next"), "Generator prototype has 'next' property");
assert.isTrue(generatorPrototype.hasOwnProperty("throw"), "Generator prototype has 'throw' property");
assert.isTrue(generatorPrototype.hasOwnProperty("return"), "Generator prototype has 'return' property");
assert.isFalse(generatorPrototype.hasOwnProperty(Symbol.iterator), "Generator prototype does not have [Symbol.iterator] property");
assert.isTrue(generatorPrototype.hasOwnProperty(Symbol.toStringTag), "Generator prototype has [Symbol.toStringTag] property");
checkAttributes("Generator prototype", generatorPrototype, "constructor", { writable: false, enumerable: false, configurable: true });
checkAttributes("Generator prototype", generatorPrototype, "next", { writable: true, enumerable: false, configurable: true });
checkAttributes("Generator prototype", generatorPrototype, "return", { writable: true, enumerable: false, configurable: true });
checkAttributes("Generator prototype", generatorPrototype, "throw", { writable: true, enumerable: false, configurable: true });
checkAttributes("Generator prototype", generatorPrototype, Symbol.toStringTag, { writable: false, enumerable: false, configurable: true });
assert.areEqual(generatorFunctionPrototype, generatorPrototype.constructor, "Generator prototype's 'constructor' property is GeneratorFunction.prototype");
assert.areEqual("Generator", generatorPrototype[Symbol.toStringTag], "Generator prototype's [Symbol.toStringTag] property is 'Generator'");
}
},
{
name: "Generator object prototype by default is the function's .prototype property value whose prototype is the Generator prototype",
body: function () {
function* gf() { }
var generatorFunctionPrototype = Object.getPrototypeOf(gf);
var generatorPrototype = generatorFunctionPrototype.prototype;
var g = gf();
assert.areEqual(generatorPrototype, Object.getPrototypeOf(Object.getPrototypeOf(g)), "Generator object's prototype is an object whose prototype is Generator prototype");
assert.areEqual(Object.getPrototypeOf(g), gf.prototype, "Generator object's prototype comes from generator function's .prototype property");
assert.isTrue(g instanceof gf, "Generator object is instance of the generator function");
}
},
{
name: "Generator function's arguments.callee should be equal to the generator function object itself",
body: function () {
function* gf() {
assert.isTrue(arguments.callee === gf, "arguments.callee should be the same function object pointed to by gf");
}
gf().next();
}
},
];
testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });