asyncawait-apis.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  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 Async Await API 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: "AsyncFunction is not exposed on the global object",
  19. body: function () {
  20. assert.isFalse(globObj.hasOwnProperty("AsyncFunction"), "Global object does not have property named AsyncFunction");
  21. }
  22. },
  23. {
  24. name: "Async function instances have length and name properties",
  25. body: function () {
  26. async function af() { }
  27. assert.isTrue(af.hasOwnProperty("length"), "Async function objects have a 'length' property");
  28. assert.isTrue(af.hasOwnProperty("name"), "Async function objects have a 'name' property");
  29. checkAttributes("af", af, "length", { writable: false, enumerable: false, configurable: true });
  30. checkAttributes("af", af, "name", { writable: false, enumerable: false, configurable: true });
  31. assert.areEqual(0, af.length, "Async function object's 'length' property matches the number of parameters (0)");
  32. assert.areEqual("af", af.name, "Async function object's 'name' property matches the function's name");
  33. async function af2(a, b, c) { }
  34. assert.areEqual(3, af2.length, "Async function object's 'length' property matches the number of parameters (3)");
  35. }
  36. },
  37. {
  38. name: "Async functions are not constructors and do not have a prototype property",
  39. body: function () {
  40. async function af() { }
  41. assert.throws(function () { new af(); }, TypeError, "Async functions cannot be used as constructors", "Function is not a constructor");
  42. assert.isFalse(af.hasOwnProperty("prototype"), "Async function objects do not have a 'prototype' property");
  43. }
  44. },
  45. {
  46. name: "Async functions do not have arguments nor caller properties regardless of strictness",
  47. body: function () {
  48. async function af() { }
  49. assert.isFalse(af.hasOwnProperty("arguments"), "Async function objects do not have an 'arguments' property");
  50. assert.isFalse(af.hasOwnProperty("caller"), "Async function objects do not have a 'caller' property");
  51. // Test JavascriptFunction APIs that special case PropertyIds::caller and ::arguments
  52. Object.setPrototypeOf(af, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
  53. assert.isFalse("arguments" in af, "Has operation on 'arguments' property returns false initially");
  54. assert.areEqual(undefined, af.arguments, "Get operation on 'arguments' property returns undefined initially");
  55. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(af, "arguments"), "No property descriptor for 'arguments' initially");
  56. assert.isTrue(delete af.arguments, "Delete operation on 'arguments' property returns true");
  57. assert.areEqual(0, af.arguments = 0, "Set operation on 'arguments' creates new property with assigned value");
  58. assert.isTrue("arguments" in af, "Has operation on 'arguments' property returns true now");
  59. assert.areEqual(0, af.arguments, "Get operation on 'arguments' property returns property value now");
  60. checkAttributes("af", af, "arguments", { writable: true, enumerable: true, configurable: true });
  61. assert.isTrue(delete af.arguments, "Delete operation on 'arguments' property still returns true");
  62. assert.isFalse(af.hasOwnProperty("arguments"), "'arguments' property is gone");
  63. assert.isFalse("caller" in af, "Has operation on 'caller' property returns false initially");
  64. assert.areEqual(undefined, af.caller, "Get operation on 'caller' property returns undefined initially");
  65. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(af, "caller"), "No property descriptor for 'caller' initially");
  66. assert.isTrue(delete af.caller, "Delete operation on 'caller' property returns true");
  67. assert.areEqual(0, af.caller = 0, "Set operation on 'caller' creates new property with assigned value");
  68. assert.isTrue("caller" in af, "Has operation on 'caller' property returns true now");
  69. assert.areEqual(0, af.caller, "Get operation on 'caller' property returns property value now");
  70. checkAttributes("af", af, "caller", { writable: true, enumerable: true, configurable: true });
  71. assert.isTrue(delete af.caller, "Delete operation on 'caller' property still returns true");
  72. assert.isFalse(af.hasOwnProperty("caller"), "'caller' property is gone");
  73. async function afstrict() { "use strict"; }
  74. assert.isFalse(afstrict.hasOwnProperty("arguments"), "Strict mode async function objects do not have an 'arguments' property");
  75. assert.isFalse(afstrict.hasOwnProperty("caller"), "Strict mode async function objects do not have a 'caller' property");
  76. Object.setPrototypeOf(afstrict, Object.prototype); // Remove Function.prototype so we don't find its 'caller' and 'arguments' in these operations
  77. assert.isFalse("arguments" in afstrict, "Has operation on 'arguments' property returns false initially for a strict mode async function");
  78. assert.areEqual(undefined, afstrict.arguments, "Get operation on 'arguments' property returns undefined initially for a strict mode async function");
  79. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(afstrict, "arguments"), "No property descriptor for 'arguments' initially for a strict mode async function");
  80. assert.isTrue(delete afstrict.arguments, "Delete operation on 'arguments' property returns true initially for a strict mode async function");
  81. assert.areEqual(0, afstrict.arguments = 0, "Set operation on 'arguments' creates new property with assigned value for a strict mode async function");
  82. assert.isTrue("arguments" in afstrict, "Has operation on 'arguments' property returns true now for a strict mode async function");
  83. assert.areEqual(0, afstrict.arguments, "Get operation on 'arguments' property returns property value now for a strict mode async function");
  84. checkAttributes("afstrict", afstrict, "arguments", { writable: true, enumerable: true, configurable: true });
  85. assert.isTrue(delete afstrict.arguments, "Delete operation on 'arguments' property still returns true for a strict mode async function");
  86. assert.isFalse(afstrict.hasOwnProperty("arguments"), "'arguments' property is gone for a strict mode async function");
  87. assert.isFalse("caller" in afstrict, "Has operation on 'caller' property returns false initially for a strict mode async function");
  88. assert.areEqual(undefined, afstrict.caller, "Get operation on 'caller' property returns undefined initially for a strict mode async function");
  89. assert.areEqual(undefined, Object.getOwnPropertyDescriptor(afstrict, "caller"), "No property descriptor for 'caller' initially for a strict mode async function");
  90. assert.isTrue(delete afstrict.caller, "Delete operation on 'caller' property returns true initially for a strict mode async function");
  91. assert.areEqual(0, afstrict.caller = 0, "Set operation on 'caller' creates new property with assigned value for a strict mode async function");
  92. assert.isTrue("caller" in afstrict, "Has operation on 'caller' property returns true now for a strict mode async function");
  93. assert.areEqual(0, afstrict.caller, "Get operation on 'caller' property returns property value now for a strict mode async function");
  94. checkAttributes("afstrict", afstrict, "caller", { writable: true, enumerable: true, configurable: true });
  95. assert.isTrue(delete afstrict.caller, "Delete operation on 'caller' property still returns true for a strict mode async function");
  96. assert.isFalse(afstrict.hasOwnProperty("caller"), "'caller' property is gone for a strict mode async function");
  97. }
  98. },
  99. {
  100. name: "Async function instances have %AsyncFunctionPrototype% as their prototype and it has the specifies properties and prototype",
  101. body: function () {
  102. async function af() { }
  103. var asyncFunctionPrototype = Object.getPrototypeOf(af);
  104. assert.areEqual(Function.prototype, Object.getPrototypeOf(asyncFunctionPrototype), "%AsyncFunctionPrototype%'s prototype is Function.prototype");
  105. assert.isTrue(asyncFunctionPrototype.hasOwnProperty("constructor"), "%AsyncFunctionPrototype% has 'constructor' property");
  106. assert.isTrue(asyncFunctionPrototype.hasOwnProperty(Symbol.toStringTag), "%AsyncFunctionPrototype% has [Symbol.toStringTag] property");
  107. checkAttributes("%AsyncFunctionPrototype%", asyncFunctionPrototype, "constructor", { writable: false, enumerable: false, configurable: true });
  108. checkAttributes("%AsyncFunctionPrototype%", asyncFunctionPrototype, Symbol.toStringTag, { writable: false, enumerable: false, configurable: true });
  109. assert.areEqual("AsyncFunction", asyncFunctionPrototype[Symbol.toStringTag], "%AsyncFunctionPrototype%'s [Symbol.toStringTag] property is 'AsyncFunction'");
  110. assert.isFalse(asyncFunctionPrototype.hasOwnProperty("prototype"), "%AsyncFunctionPrototype% does not have a 'prototype' property");
  111. }
  112. },
  113. {
  114. name: "%AsyncFunction% constructor is the value of the constructor property of %AsyncFunctionPrototype%.prototype and has the specified properties and prototype",
  115. body: function () {
  116. async function af() { }
  117. var asyncFunctionPrototype = Object.getPrototypeOf(af);
  118. var asyncFunctionConstructor = asyncFunctionPrototype.constructor;
  119. assert.areEqual(Function, Object.getPrototypeOf(asyncFunctionConstructor), "%AsyncFunction%'s prototype is Function");
  120. assert.isTrue(asyncFunctionConstructor.hasOwnProperty("name"), "%AsyncFunction% has 'name' property");
  121. assert.isTrue(asyncFunctionConstructor.hasOwnProperty("length"), "%AsyncFunction% has 'length' property");
  122. assert.isTrue(asyncFunctionConstructor.hasOwnProperty("prototype"), "%AsyncFunction% has 'prototype' property");
  123. checkAttributes("%AsyncFunction%", asyncFunctionConstructor, "name", { writable: false, enumerable: false, configurable: true });
  124. checkAttributes("%AsyncFunction%", asyncFunctionConstructor, "length", { writable: false, enumerable: false, configurable: true });
  125. checkAttributes("%AsyncFunction%", asyncFunctionConstructor, "prototype", { writable: false, enumerable: false, configurable: false });
  126. assert.areEqual("AsyncFunction", asyncFunctionConstructor.name, "%AsyncFunction%'s 'name' property is 'AsyncFunction'");
  127. assert.areEqual(asyncFunctionPrototype, asyncFunctionConstructor.prototype, "%AsyncFunction%'s 'prototype' property is %AsyncFunction%.prototype");
  128. assert.areEqual(1, asyncFunctionConstructor.length, "%AsyncFunction%'s 'length' property is 1");
  129. }
  130. },
  131. {
  132. name: "",
  133. body: function () {
  134. var asyncFunctionPrototype = Object.getPrototypeOf(async function () { });
  135. var AsyncFunction = asyncFunctionPrototype.constructor;
  136. var af = new AsyncFunction('return await 1;');
  137. assert.areEqual(asyncFunctionPrototype, Object.getPrototypeOf(af), "Async function created by %AsyncFunction% should have the same prototype as syntax declared async functions");
  138. assert.areEqual("anonymous", af.name, "AsyncFunction constructed async function's name is 'anonymous'");
  139. assert.areEqual("async function anonymous(\n) {return await 1;\n}", af.toString(), "toString of AsyncFunction constructed function is named 'anonymous'");
  140. af = new AsyncFunction('a', 'b', 'c', 'await a; await b; await c;');
  141. assert.areEqual("async function anonymous(a,b,c\n) {await a; await b; await c;\n}", af.toString(), "toString of AsyncFunction constructed function is named 'anonymous' with specified parameters");
  142. // Cannot verify behavior of async functions in conjunction with UnitTestFramework.js
  143. // due to callback nature of their execution. Instead, verification of behavior is
  144. // found in async-functionality.js test.
  145. }
  146. },
  147. ];
  148. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });