generators-apis.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. // ES6 Generators APIs tests -- verifies built-in API objects and properties
  6. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  7. var globObj = this;
  8. function checkAttributes(name, o, p, a) {
  9. var desc = Object.getOwnPropertyDescriptor(o, p);
  10. var msgPrefix = "Property " + p.toString() + " on " + name + " is ";
  11. assert.isTrue(!!desc, msgPrefix + "not found; there is no descriptor");
  12. assert.areEqual(a.writable, desc.writable, msgPrefix + (a.writable ? "" : "not") + " writable");
  13. assert.areEqual(a.enumerable, desc.enumerable, msgPrefix + (a.enumerable ? "" : "not") + " enumerable");
  14. assert.areEqual(a.configurable, desc.configurable, msgPrefix + (a.configurable ? "" : "not") + " configurable");
  15. }
  16. var tests = [
  17. {
  18. name: "GeneratorFunction is not exposed on the global object",
  19. body: function () {
  20. assert.isFalse(globObj.hasOwnProperty("GeneratorFunction"), "Global object does not have property named GeneratorFunction");
  21. }
  22. },
  23. {
  24. name: "Generator function object instances have length, name, and prototype properties",
  25. body: function () {
  26. function* gf() { }
  27. assert.isTrue(gf.hasOwnProperty("length"), "Generator function objects have a 'length' property");
  28. assert.isTrue(gf.hasOwnProperty("name"), "Generator function objects have a 'name' property");
  29. assert.isTrue(gf.hasOwnProperty("prototype"), "Generator function objects have a 'prototype' property");
  30. checkAttributes("gf", gf, "length", { writable: false, enumerable: false, configurable: true });
  31. checkAttributes("gf", gf, "name", { writable: false, enumerable: false, configurable: true });
  32. checkAttributes("gf", gf, "prototype", { writable: true, enumerable: false, configurable: false });
  33. function gf2(a, b, c) { }
  34. assert.areEqual(0, gf.length, "Generator function object's 'length' property matches the number of parameters (0)");
  35. assert.areEqual(3, gf2.length, "Generator function object's 'length' property matches the number of parameters (3)");
  36. assert.areEqual("gf", gf.name, "Generator function object's 'name' property matches the function's name");
  37. assert.isFalse(gf.prototype.hasOwnProperty("constructor"), "Generator function prototype objects do not get a 'constructor' property");
  38. }
  39. },
  40. {
  41. name: "arguments and caller properties are absent regardless of strictness",
  42. body: function () {
  43. function* gf() { }
  44. assert.isFalse(gf.hasOwnProperty("arguments"), "Generator function objects do not have an 'arguments' property");
  45. assert.isFalse(gf.hasOwnProperty("caller"), "Generator function objects do not have a 'caller' property");
  46. // Test JavascriptGeneratorFunction APIs that special case PropertyIds::caller and ::arguments
  47. Object.setPrototypeOf(gf, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
  48. assert.isFalse("arguments" in gf, "Has operation on 'arguments' property returns false initially");
  49. assert.areEqual(undefined, gf.arguments, "Get operation on 'arguments' property returns undefined initially");
  50. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gf, "arguments"), "No property descriptor for 'arguments' initially");
  51. assert.isTrue(delete gf.arguments, "Delete operation on 'arguments' property returns true");
  52. assert.areEqual(0, gf.arguments = 0, "Set operation on 'arguments' creates new property with assigned value");
  53. assert.isTrue("arguments" in gf, "Has operation on 'arguments' property returns true now");
  54. assert.areEqual(0, gf.arguments, "Get operation on 'arguments' property returns property value now");
  55. checkAttributes("gf", gf, "arguments", { writable: true, enumerable: true, configurable: true });
  56. assert.isTrue(delete gf.arguments, "Delete operation on 'arguments' property still returns true");
  57. assert.isFalse(gf.hasOwnProperty("arguments"), "'arguments' property is gone");
  58. assert.isFalse("caller" in gf, "Has operation on 'caller' property returns false initially");
  59. assert.areEqual(undefined, gf.caller, "Get operation on 'caller' property returns undefined initially");
  60. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gf, "caller"), "No property descriptor for 'caller' initially");
  61. assert.isTrue(delete gf.caller, "Delete operation on 'caller' property returns true");
  62. assert.areEqual(0, gf.caller = 0, "Set operation on 'caller' creates new property with assigned value");
  63. assert.isTrue("caller" in gf, "Has operation on 'caller' property returns true now");
  64. assert.areEqual(0, gf.caller, "Get operation on 'caller' property returns property value now");
  65. checkAttributes("gf", gf, "caller", { writable: true, enumerable: true, configurable: true });
  66. assert.isTrue(delete gf.caller, "Delete operation on 'caller' property still returns true");
  67. assert.isFalse(gf.hasOwnProperty("caller"), "'caller' property is gone");
  68. function* gfstrict() { "use strict"; }
  69. assert.isFalse(gfstrict.hasOwnProperty("arguments"), "Strict mode generator function objects do not have an 'arguments' property");
  70. assert.isFalse(gfstrict.hasOwnProperty("caller"), "Strict mode generator function objects do not have a 'caller' property");
  71. Object.setPrototypeOf(gfstrict, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
  72. assert.isFalse("arguments" in gfstrict, "Has operation on 'arguments' property returns false initially for a strict mode generator function");
  73. assert.areEqual(undefined, gfstrict.arguments, "Get operation on 'arguments' property returns undefined initially for a strict mode generator function");
  74. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gfstrict, "arguments"), "No property descriptor for 'arguments' initially for a strict mode generator function");
  75. assert.isTrue(delete gfstrict.arguments, "Delete operation on 'arguments' property returns true initially for a strict mode generator function");
  76. assert.areEqual(0, gfstrict.arguments = 0, "Set operation on 'arguments' creates new property with assigned value for a strict mode generator function");
  77. assert.isTrue("arguments" in gfstrict, "Has operation on 'arguments' property returns true now for a strict mode generator function");
  78. assert.areEqual(0, gfstrict.arguments, "Get operation on 'arguments' property returns property value now for a strict mode generator function");
  79. checkAttributes("gfstrict", gfstrict, "arguments", { writable: true, enumerable: true, configurable: true });
  80. assert.isTrue(delete gfstrict.arguments, "Delete operation on 'arguments' property still returns true for a strict mode generator function");
  81. assert.isFalse(gfstrict.hasOwnProperty("arguments"), "'arguments' property is gone for a strict mode generator function");
  82. assert.isFalse("caller" in gfstrict, "Has operation on 'caller' property returns false initially for a strict mode generator function");
  83. assert.areEqual(undefined, gfstrict.caller, "Get operation on 'caller' property returns undefined initially for a strict mode generator function");
  84. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(gfstrict, "caller"), "No property descriptor for 'caller' initially for a strict mode generator function");
  85. assert.isTrue(delete gfstrict.caller, "Delete operation on 'caller' property returns true initially for a strict mode generator function");
  86. assert.areEqual(0, gfstrict.caller = 0, "Set operation on 'caller' creates new property with assigned value for a strict mode generator function");
  87. assert.isTrue("caller" in gfstrict, "Has operation on 'caller' property returns true now for a strict mode generator function");
  88. assert.areEqual(0, gfstrict.caller, "Get operation on 'caller' property returns property value now for a strict mode generator function");
  89. checkAttributes("gfstrict", gfstrict, "caller", { writable: true, enumerable: true, configurable: true });
  90. assert.isTrue(delete gfstrict.caller, "Delete operation on 'caller' property still returns true for a strict mode generator function");
  91. assert.isFalse(gfstrict.hasOwnProperty("caller"), "'caller' property is gone for a strict mode generator function");
  92. }
  93. },
  94. {
  95. name: "Generator functions' length property is the number of formal parameters",
  96. body: function () {
  97. function* gf0() { }
  98. function* gf1(a) { }
  99. function* gf5(a,b,c,d,e) { }
  100. assert.areEqual(0, gf0.length, "Generator function with no formal parameters has length 0");
  101. assert.areEqual(1, gf1.length, "Generator function with one formal parameter has length 1");
  102. assert.areEqual(5, gf5.length, "Generator function with five formal parameters has length 5");
  103. }
  104. },
  105. {
  106. name: "Generator function instances have GeneratorFunction.prototype as their prototype and it has the specified properties and prototype",
  107. body: function () {
  108. function* gf() { }
  109. var generatorFunctionPrototype = Object.getPrototypeOf(gf);
  110. assert.areEqual(Function.prototype, Object.getPrototypeOf(generatorFunctionPrototype), "GeneratorFunction.prototype's prototype is Function.prototype");
  111. assert.isTrue(generatorFunctionPrototype.hasOwnProperty("constructor"), "GeneratorFunction.prototype has 'constructor' property");
  112. assert.isTrue(generatorFunctionPrototype.hasOwnProperty("prototype"), "GeneratorFunction.prototype has 'prototype' property");
  113. assert.isTrue(generatorFunctionPrototype.hasOwnProperty(Symbol.toStringTag), "GeneratorFunction.prototype has [Symbol.toStringTag] property");
  114. checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, "constructor", { writable: false, enumerable: false, configurable: true });
  115. checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, "prototype", { writable: false, enumerable: false, configurable: true });
  116. checkAttributes("GeneratorFunction.prototype", generatorFunctionPrototype, Symbol.toStringTag, { writable: false, enumerable: false, configurable: true });
  117. assert.areEqual("GeneratorFunction", generatorFunctionPrototype[Symbol.toStringTag], "GeneratorFunction.prototype's [Symbol.toStringTag] property is 'GeneratorFunction'");
  118. }
  119. },
  120. {
  121. name: "GeneratorFunction constructor is the value of the constructor property of GeneratorFunction.prototype and has the specified properties and prototype",
  122. body: function () {
  123. function* gf() { }
  124. var generatorFunctionPrototype = Object.getPrototypeOf(gf);
  125. var generatorFunctionConstructor = generatorFunctionPrototype.constructor;
  126. assert.areEqual(Function, Object.getPrototypeOf(generatorFunctionConstructor), "GeneratorFunction's prototype is Function");
  127. assert.isTrue(generatorFunctionConstructor.hasOwnProperty("name"), "GeneratorFunction has 'name' property");
  128. assert.isTrue(generatorFunctionConstructor.hasOwnProperty("length"), "GeneratorFunction has 'length' property");
  129. assert.isTrue(generatorFunctionConstructor.hasOwnProperty("prototype"), "GeneratorFunction has 'prototype' property");
  130. checkAttributes("GeneratorFunction", generatorFunctionConstructor, "name", { writable: false, enumerable: false, configurable: true });
  131. checkAttributes("GeneratorFunction", generatorFunctionConstructor, "length", { writable: false, enumerable: false, configurable: true });
  132. checkAttributes("GeneratorFunction", generatorFunctionConstructor, "prototype", { writable: false, enumerable: false, configurable: false });
  133. assert.areEqual("GeneratorFunction", generatorFunctionConstructor.name, "GeneratorFunction's 'name' property is 'GeneratorFunction'");
  134. assert.areEqual(generatorFunctionPrototype, generatorFunctionConstructor.prototype, "GeneratorFunction's 'prototype' property is GeneratorFunction.prototype");
  135. assert.areEqual(1, generatorFunctionConstructor.length, "GeneratorFunction's 'length' property is 1");
  136. }
  137. },
  138. {
  139. name: "Generator prototype is the value of the prototype property of GeneratorFunction.prototype and has the specified properties and prototype",
  140. body: function () {
  141. function* gf() { }
  142. var generatorFunctionPrototype = Object.getPrototypeOf(gf);
  143. var generatorPrototype = generatorFunctionPrototype.prototype;
  144. var iteratorPrototype = Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()));
  145. assert.areEqual(iteratorPrototype, Object.getPrototypeOf(generatorPrototype), "Generator prototype's prototype is %IteratorPrototype%");
  146. assert.isTrue(generatorPrototype.hasOwnProperty("constructor"), "Generator prototype has 'constructor' property");
  147. assert.isTrue(generatorPrototype.hasOwnProperty("next"), "Generator prototype has 'next' property");
  148. assert.isTrue(generatorPrototype.hasOwnProperty("throw"), "Generator prototype has 'throw' property");
  149. assert.isTrue(generatorPrototype.hasOwnProperty("return"), "Generator prototype has 'return' property");
  150. assert.isFalse(generatorPrototype.hasOwnProperty(Symbol.iterator), "Generator prototype does not have [Symbol.iterator] property");
  151. assert.isTrue(generatorPrototype.hasOwnProperty(Symbol.toStringTag), "Generator prototype has [Symbol.toStringTag] property");
  152. checkAttributes("Generator prototype", generatorPrototype, "constructor", { writable: false, enumerable: false, configurable: true });
  153. checkAttributes("Generator prototype", generatorPrototype, "next", { writable: true, enumerable: false, configurable: true });
  154. checkAttributes("Generator prototype", generatorPrototype, "return", { writable: true, enumerable: false, configurable: true });
  155. checkAttributes("Generator prototype", generatorPrototype, "throw", { writable: true, enumerable: false, configurable: true });
  156. checkAttributes("Generator prototype", generatorPrototype, Symbol.toStringTag, { writable: false, enumerable: false, configurable: true });
  157. assert.areEqual(generatorFunctionPrototype, generatorPrototype.constructor, "Generator prototype's 'constructor' property is GeneratorFunction.prototype");
  158. assert.areEqual("Generator", generatorPrototype[Symbol.toStringTag], "Generator prototype's [Symbol.toStringTag] property is 'Generator'");
  159. }
  160. },
  161. {
  162. name: "Generator object prototype by default is the function's .prototype property value whose prototype is the Generator prototype",
  163. body: function () {
  164. function* gf() { }
  165. var generatorFunctionPrototype = Object.getPrototypeOf(gf);
  166. var generatorPrototype = generatorFunctionPrototype.prototype;
  167. var g = gf();
  168. assert.areEqual(generatorPrototype, Object.getPrototypeOf(Object.getPrototypeOf(g)), "Generator object's prototype is an object whose prototype is Generator prototype");
  169. assert.areEqual(Object.getPrototypeOf(g), gf.prototype, "Generator object's prototype comes from generator function's .prototype property");
  170. assert.isTrue(g instanceof gf, "Generator object is instance of the generator function");
  171. }
  172. },
  173. {
  174. name: "Generator function's arguments.callee should be equal to the generator function object itself",
  175. body: function () {
  176. function* gf() {
  177. assert.isTrue(arguments.callee === gf, "arguments.callee should be the same function object pointed to by gf");
  178. }
  179. gf().next();
  180. }
  181. },
  182. ];
  183. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });