valuesAndEntries.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. WScript.LoadScriptFile("..\\UnitTestFramework\\UnitTestFramework.js");
  6. var tests = [
  7. {
  8. name: "Object.values/entries should exist and constructed properly",
  9. body: function () {
  10. assert.isTrue(Object.hasOwnProperty('values'), "Object should have a values method");
  11. assert.isTrue(Object.hasOwnProperty('entries'), "Object should have a entries method");
  12. assert.areEqual(1, Object.values.length, "values method takes one argument");
  13. assert.areEqual(1, Object.entries.length, "entries method takes one argument");
  14. assert.areEqual("values", Object.values.name, "values.name is 'values'");
  15. assert.areEqual("entries", Object.entries.name, "entries.name is 'entries'");
  16. var descriptor = Object.getOwnPropertyDescriptor(Object, 'values');
  17. assert.isTrue(descriptor.writable, "writable(values) must be true");
  18. assert.isFalse(descriptor.enumerable, "enumerable(values) must be false");
  19. assert.isTrue(descriptor.configurable, "configurable(values) must be true");
  20. descriptor = Object.getOwnPropertyDescriptor(Object, 'entries');
  21. assert.isTrue(descriptor.writable, "writable(entries) must be true");
  22. assert.isFalse(descriptor.enumerable, "enumerable(entries) must be false");
  23. assert.isTrue(descriptor.configurable, "configurable(entries) must be true");
  24. }
  25. },
  26. {
  27. name: "Object.values/entries basic syntax",
  28. body: function () {
  29. assert.throws(function () { eval("Object.values();"); }, TypeError, "Calling values method without any arguments throws an error", "Object expected");
  30. assert.throws(function () { eval("Object.values(undefined);"); }, TypeError, "Calling values method on undefined throws an error", "Object expected");
  31. assert.throws(function () { eval("Object.values(null);"); }, TypeError, "Calling values method on null throws an error", "Object expected");
  32. assert.isTrue(Array.isArray(Object.values({})), "calling values method on an object returns an array");
  33. assert.areEqual(0, Object.values({}).length, "calling values method on an empty object returns an empty array");
  34. assert.throws(function () { eval("Object.entries();"); }, TypeError, "Calling entries method without any arguments throws an error", "Object expected");
  35. assert.throws(function () { eval("Object.entries(undefined);"); }, TypeError, "Calling entries method on undefined throws an error", "Object expected");
  36. assert.throws(function () { eval("Object.entries(null);"); }, TypeError, "Calling entries method on null throws an error", "Object expected");
  37. assert.isTrue(Array.isArray(Object.entries({})), "calling entries method on an object returns an array");
  38. assert.areEqual(0, Object.entries({}).length, "calling entries method on an empty object returns an empty array");
  39. }
  40. },
  41. {
  42. name: "Object.values/entries functionality",
  43. body: function () {
  44. var a1 = {prop1:10, prop2:20};
  45. var values = Object.values(a1);
  46. assert.areEqual(2, values.length, "calling values on an object with two properties will returned an array of 2 elements");
  47. assert.areEqual(10, values[0], "First element of the returned values array should be 10");
  48. assert.areEqual(20, values[1], "Second element of the returned values array should be 20");
  49. var entries = Object.entries(a1);
  50. assert.areEqual(2, entries.length, "calling entries on an object with two properties will returned an array of 2 elements");
  51. assert.isTrue(Array.isArray(entries[0]) && Array.isArray(entries[1]), "each element itself an array of key, value pair");
  52. assert.areEqual(["prop1", 10], entries[0], "First element of the returned entry array should be ['prop1', 10]");
  53. assert.areEqual(["prop2", 20], entries[1], "Second element of the returned entry array should be ['prop2', 20]");
  54. var a2 = {prop3 : 30};
  55. a2[2] = 40;
  56. a2["prop4"] = 50;
  57. Object.defineProperty(a2, "prop5", { value: 60, enumerable: true});
  58. Object.defineProperty(a2, "prop6", { value: 70, enumerable: false});
  59. Object.defineProperty(a2, 'prop7', { enumerable: true, get: function () { return 80;}});
  60. var sym = Symbol('prop8');
  61. a2[sym] = 90;
  62. values = Object.values(a2);
  63. assert.areEqual(5, values.length, "values method returns an array of 5 elements, symbol and non-enumerable should be excluded");
  64. assert.areEqual([40,30,50,60,80], values, "values method returns an array and matches correctly");
  65. entries = Object.entries(a2);
  66. assert.areEqual(5, entries.length, "entries method returns an array of 5 elements, symbol and non-enumerable should be excluded");
  67. assert.areEqual("2,40,prop3,30,prop4,50,prop5,60,prop7,80", entries.toString(), "entries method returns an array and matches correctly");
  68. }
  69. },
  70. {
  71. name: "Object.values/entries with proxy",
  72. body: function () {
  73. var obj1 = {prop1:10};
  74. var proxy1 = new Proxy(obj1, { });
  75. var values = Object.values(proxy1);
  76. assert.areEqual(1, values.length, "values - Proxy object on an object with one property returns an array of 1 element");
  77. assert.areEqual(10, values[0], "values - Proxy object on an object with one property returns correct element");
  78. var entries = Object.entries(proxy1);
  79. assert.areEqual(1, entries.length, "entries - Proxy object on an object with one property returns an array of 1 element");
  80. assert.areEqual(["prop1", 10], entries[0], "entries - Proxy object on an object with one property returns correct element");
  81. var obj2 = {};
  82. Object.defineProperty(obj2, "prop2", { value: 20, enumerable: true });
  83. Object.defineProperty(obj2, "prop3", { get: function () { return 30; }, enumerable: true });
  84. var proxy2 = new Proxy(obj2, {
  85. getOwnPropertyDescriptor: function (target, property) {
  86. return Reflect.getOwnPropertyDescriptor(target, property);
  87. }
  88. });
  89. values = Object.values(proxy2);
  90. assert.areEqual(2, values.length, "values - exhibiting a Proxy trapping getOwnPropertyDescriptor returns an aray to 2 elements");
  91. assert.areEqual(20, values[0], "values - a Proxy trapping getOwnPropertyDescriptor matching the first element");
  92. assert.areEqual(30, values[1], "values - a Proxy trapping getOwnPropertyDescriptor matching the second element");
  93. entries = Object.entries(proxy2);
  94. assert.areEqual(2, entries.length, "values - exhibiting a Proxy trapping getOwnPropertyDescriptor returns an aray to 2 elements");
  95. assert.areEqual(["prop2", 20], entries[0], "entries - a Proxy trapping getOwnPropertyDescriptor matching the first element");
  96. assert.areEqual(["prop3", 30], entries[1], "entries - a Proxy trapping getOwnPropertyDescriptor matching the second element");
  97. var obj3 = {};
  98. var count = 0;
  99. var proxy3 = new Proxy(obj3, {
  100. get: function (target, property, receiver) {
  101. return count++ * 5;
  102. },
  103. getOwnPropertyDescriptor: function (target, property) {
  104. return {configurable: true, enumerable: true};
  105. },
  106. ownKeys: function (target) {
  107. return ["prop0", "prop1", Symbol("prop2"), Symbol("prop5")];
  108. }
  109. });
  110. values = Object.values(proxy3);
  111. assert.areEqual(2, values.length, "values - exhibiting a Proxy with get and ownKeys traps - returns 2 elements");
  112. assert.areEqual(0, values[0], "values - exhibiting a Proxy with get and ownKeys traps - matching first element");
  113. assert.areEqual(5, values[1], "values - exhibiting a Proxy with get and ownKeys traps - matching second element");
  114. entries = Object.entries(proxy3);
  115. assert.areEqual(2, entries.length, "entries - exhibiting a Proxy with get and ownKeys trap - returns 2 elements");
  116. assert.areEqual(["prop0", 10], entries[0], "entries - exhibiting a Proxy with get and ownKeys trap - matching first element");
  117. assert.areEqual(["prop1", 15], entries[1], "entries - exhibiting a Proxy with get and ownKeys trap - matching second element");
  118. }
  119. },
  120. {
  121. name: "Object.values - deleting or making non-enumerable during enumeration",
  122. body: function () {
  123. var aDeletesB = {
  124. get a() {
  125. delete this.b;
  126. return 1;
  127. },
  128. b: 2
  129. };
  130. var values = Object.values(aDeletesB);
  131. assert.areEqual(1, values.length, "deleting next key during enumeration is excluded in the result");
  132. assert.areEqual(1, values[0], "deleting next key - first element is 1");
  133. var aRemovesB = {
  134. get a() {
  135. Object.defineProperty(this, 'b', {
  136. enumerable: false
  137. });
  138. return 1;
  139. },
  140. b: 2
  141. };
  142. values = Object.values(aRemovesB);
  143. assert.areEqual(1, values.length, "making the next key non-enumerable is excluded in the result");
  144. assert.areEqual(1, values[0], "making next nonenumerable - first element is 1");
  145. }
  146. },
  147. {
  148. name: "Object.entries - deleting or making non-enumerable during enumeration",
  149. body: function () {
  150. var aDeletesB = {
  151. get a() {
  152. delete this.b;
  153. return 1;
  154. },
  155. b: 2
  156. };
  157. var entries = Object.entries(aDeletesB);
  158. assert.areEqual(1, entries.length, "deleting next key during enumeration is excluded in the result");
  159. assert.areEqual(['a', 1], entries[0], "deleting next key - first element is 1");
  160. var aRemovesB = {
  161. get a() {
  162. Object.defineProperty(this, 'b', {
  163. enumerable: false
  164. });
  165. return 1;
  166. },
  167. b: 2
  168. };
  169. entries = Object.entries(aRemovesB);
  170. assert.areEqual(1, entries.length, "making the next key non-enumerable is excluded in the result");
  171. assert.areEqual(['a', 1], entries[0], "making next nonenumerable - first element is 1");
  172. }
  173. },
  174. {
  175. name: "Object.values - making non-enumerable to enumerable during enumeration",
  176. body: function () {
  177. var aAddsB = {};
  178. Object.defineProperty(aAddsB, "a", { get: function () { Object.defineProperty(this, 'b', { enumerable: true }); return 1; }, enumerable: true });
  179. Object.defineProperty(aAddsB, "b", { value: 2, configurable:true, enumerable: false});
  180. var values = Object.values(aAddsB);
  181. assert.areEqual(2, values.length, "making the second non-enumerable key to enumerable is included in the result");
  182. assert.areEqual(1, values[0], "non-enumerable to enumerable - first element is 1");
  183. assert.areEqual(2, values[1], "non-enumerable to enumerable - second element is 2");
  184. }
  185. },
  186. {
  187. name: "Object.entries - making non-enumerable to enumerable during enumeration",
  188. body: function () {
  189. var aAddsB = {};
  190. Object.defineProperty(aAddsB, "a", { get: function () { Object.defineProperty(this, 'b', { enumerable:true }); return 1; }, enumerable: true });
  191. Object.defineProperty(aAddsB, "b", { value: 2, configurable:true, enumerable: false});
  192. var entries = Object.entries(aAddsB);
  193. assert.areEqual(2, entries.length, "making the second non-enumerable key to enumerable is included in the result");
  194. assert.areEqual(['a', 1], entries[0], "non-enumerable to enumerable - first element is 1");
  195. assert.areEqual(['b', 2], entries[1], "non-enumerable to enumerable - second element is 2");
  196. }
  197. }
  198. ];
  199. testRunner.runTests(tests, { verbose: WScript.Arguments[0] != "summary" });