object-basic.js 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. describe("correct behavior", () => {
  2. test("numeric indexing", () => {
  3. const o = { 1: 23 };
  4. expect(o[1]).toBe(23);
  5. expect(o[1n]).toBe(23);
  6. expect(o["1"]).toBe(23);
  7. o[10] = "123";
  8. expect(o[10]).toBe("123");
  9. expect(o["10"]).toBe("123");
  10. o[10n] = "1234";
  11. expect(o[10]).toBe("1234");
  12. expect(o["10"]).toBe("1234");
  13. });
  14. test("string indexing", () => {
  15. let foo = "bar";
  16. const o = {
  17. foo,
  18. bar: "baz",
  19. qux: true ? 10 : 20,
  20. hello: "friends",
  21. };
  22. expect(o.foo).toBe("bar");
  23. expect(o["foo"]).toBe("bar");
  24. expect(o.qux).toBe(10), expect(o.hello).toBe("friends");
  25. expect(o["hello"]).toBe("friends");
  26. });
  27. test("symbol keys", () => {
  28. let object = {};
  29. let symbol = Symbol("foo");
  30. object[symbol] = 2;
  31. expect(object[symbol]).toBe(2);
  32. });
  33. test("numeric keys", () => {
  34. const hex = { 0x10: "16" };
  35. const oct = { 0o10: "8" };
  36. const bin = { 0b10: "2" };
  37. const float = { 0.5: "0.5" };
  38. expect(hex["16"]).toBe("16");
  39. expect(oct["8"]).toBe("8");
  40. expect(bin["2"]).toBe("2");
  41. expect(float["0.5"]).toBe("0.5");
  42. });
  43. test("computed properties", () => {
  44. const foo = "bar";
  45. const computed = "computed";
  46. const o = {
  47. [1 + 2]: 42,
  48. [`I am a ${computed} key`]: foo,
  49. };
  50. expect(o[3]).toBe(42);
  51. expect(o["I am a computed key"]).toBe("bar");
  52. });
  53. test("duplicate keys", () => {
  54. const o = {
  55. duplicate: "hello",
  56. duplicate: "world",
  57. };
  58. expect(o.duplicate).toBe("world");
  59. });
  60. test("assigning after creation", () => {
  61. const o = {};
  62. o.baz = "test";
  63. expect(o.baz).toBe("test");
  64. expect(o["baz"]).toBe("test");
  65. expect(o[-1]).toBeUndefined();
  66. o[-1] = "hello friends";
  67. expect(o[-1]).toBe("hello friends");
  68. expect(o["-1"]).toBe("hello friends");
  69. });
  70. test("floating point keys", () => {
  71. const math = { 3.14: "pi" };
  72. expect(math["3.14"]).toBe("pi");
  73. expect(math[3.14]).toBe("pi");
  74. });
  75. test("keywords as property keys", () => {
  76. const o2 = {
  77. return: 1,
  78. yield: 1,
  79. for: 1,
  80. catch: 1,
  81. break: 1,
  82. };
  83. expect(o2.return).toBe(1);
  84. expect(o2.yield).toBe(1);
  85. expect(o2.for).toBe(1);
  86. expect(o2.catch).toBe(1);
  87. expect(o2.break).toBe(1);
  88. });
  89. test("prototypical inheritance", () => {
  90. var base = {
  91. getNumber() {
  92. return 10;
  93. },
  94. };
  95. var derived = {
  96. getNumber() {
  97. return 20 + super.getNumber();
  98. },
  99. };
  100. Object.setPrototypeOf(derived, base);
  101. expect(derived.getNumber()).toBe(30);
  102. });
  103. test("assigning object expression with destination referenced in object expression", () => {
  104. function go(i) {
  105. var i = { f: i };
  106. return i;
  107. }
  108. expect(go("foo")).toEqual({ f: "foo" });
  109. });
  110. });
  111. describe("side effects", () => {
  112. let a;
  113. const append = x => {
  114. a.push(x);
  115. };
  116. test("computed key side effects", () => {
  117. a = [];
  118. const o3 = { [append(1)]: 1, [append(2)]: 2, [append(3)]: 3 };
  119. expect(a).toHaveLength(3);
  120. expect(a[0]).toBe(1);
  121. expect(a[1]).toBe(2);
  122. expect(a[2]).toBe(3);
  123. expect(o3.undefined).toBe(3);
  124. });
  125. test("value side effects", () => {
  126. a = [];
  127. const o4 = { test: append(1), test: append(2), test: append(3) };
  128. expect(a).toHaveLength(3);
  129. expect(a[0]).toBe(1);
  130. expect(a[1]).toBe(2);
  131. expect(a[2]).toBe(3);
  132. expect(o4.test).toBeUndefined();
  133. });
  134. });
  135. describe("shorthanded properties with special names", () => {
  136. test("keywords cannot be used", () => {
  137. expect("({ function, })").not.toEval();
  138. expect("({ var, })").not.toEval();
  139. expect("({ const, })").not.toEval();
  140. expect("({ class, })").not.toEval();
  141. });
  142. test("reserved words are allowed in non-strict mode", () => {
  143. {
  144. var implements = 3;
  145. expect({ implements }).toEqual({ implements: 3 });
  146. }
  147. {
  148. var public = "a";
  149. expect({ public }).toEqual({ public: "a" });
  150. }
  151. {
  152. var let = 9;
  153. expect({ let }).toEqual({ let: 9 });
  154. }
  155. {
  156. var await = 8;
  157. expect({ await }).toEqual({ await: 8 });
  158. }
  159. {
  160. var async = 7;
  161. expect({ async }).toEqual({ async: 7 });
  162. }
  163. {
  164. var yield = 6;
  165. expect({ yield }).toEqual({ yield: 6 });
  166. }
  167. });
  168. test("reserved words are not allowed in strict mode", () => {
  169. expect('"use strict"; var implements = 3; ({ implements })').not.toEval();
  170. expect("\"use strict\"; var public = 'a'; ({ public })").not.toEval();
  171. expect('"use strict"; var let = 9; ({ let, })').not.toEval();
  172. expect('"use strict"; var yield = 6; ({ yield, })').not.toEval();
  173. });
  174. test("special non reserved words are allowed even in strict mode", () => {
  175. expect('"use strict"; var await = 8; ({ await, })').toEval();
  176. expect('"use strict"; var async = 7; ({ async, })').toEval();
  177. });
  178. });
  179. describe("errors", () => {
  180. test("syntax errors", () => {
  181. expect("({ foo: function() { super.bar; } })").not.toEval();
  182. expect("({ get ...foo })").not.toEval();
  183. expect("({ get... foo })").not.toEval();
  184. expect("({ get foo })").not.toEval();
  185. expect("({ get foo: bar })").not.toEval();
  186. expect("({ get [foo]: bar })").not.toEval();
  187. expect("({ get ...[foo] })").not.toEval();
  188. expect("({ get foo(bar) {} })").not.toEval();
  189. expect("({ set foo() {} })").not.toEval();
  190. expect("({ set foo(...bar) {} })").not.toEval();
  191. expect("({ set foo(bar, baz) {} })").not.toEval();
  192. expect("({ ...foo: bar })").not.toEval();
  193. });
  194. });
  195. describe("naming of anon functions", () => {
  196. test("method has name", () => {
  197. expect({ func() {} }.func.name).toBe("func");
  198. });
  199. test("getter has name", () => {
  200. expect(Object.getOwnPropertyDescriptor({ get func() {} }, "func").get.name).toBe(
  201. "get func"
  202. );
  203. });
  204. test("setter has name", () => {
  205. expect(Object.getOwnPropertyDescriptor({ set func(v) {} }, "func").set.name).toBe(
  206. "set func"
  207. );
  208. });
  209. test("anon function property", () => {
  210. expect({ func: function () {} }.func.name).toBe("func");
  211. });
  212. test("anon function from within parenthesis", () => {
  213. expect({ func: function () {} }.func.name).toBe("func");
  214. });
  215. test("anon function from indirect expression", () => {
  216. expect({ func: (0, function () {}) }.func.name).toBe("");
  217. });
  218. test("function from function call does not get named", () => {
  219. function f() {
  220. return function () {};
  221. }
  222. expect(f().name).toBe("");
  223. expect({ func: f() }.func.name).toBe("");
  224. });
  225. });