Proxy.handler-getOwnPropertyDescriptor.js 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. describe("[Call][GetOwnProperty]] trap normal behavior", () => {
  2. test("forwarding when not defined in handler", () => {
  3. expect(
  4. Object.getOwnPropertyDescriptor(new Proxy({}, { getOwnPropertyDescriptor: null }), "a")
  5. ).toBeUndefined();
  6. expect(
  7. Object.getOwnPropertyDescriptor(
  8. new Proxy({}, { getOwnPropertyDescriptor: undefined }),
  9. "a"
  10. )
  11. ).toBeUndefined();
  12. expect(Object.getOwnPropertyDescriptor(new Proxy({}, {}), "a")).toBeUndefined();
  13. });
  14. test("correct arguments supplied to trap", () => {
  15. let o = {};
  16. let p = new Proxy(o, {
  17. getOwnPropertyDescriptor(target, property) {
  18. expect(target).toBe(o);
  19. expect(property).toBe("foo");
  20. },
  21. });
  22. Object.getOwnPropertyDescriptor(p, "foo");
  23. });
  24. test("conditional returned descriptor", () => {
  25. let o = { foo: "bar" };
  26. Object.defineProperty(o, "baz", {
  27. value: "qux",
  28. enumerable: false,
  29. configurable: true,
  30. writable: false,
  31. });
  32. let p = new Proxy(o, {
  33. getOwnPropertyDescriptor(target, property) {
  34. if (property === "baz") return Object.getOwnPropertyDescriptor(target, "baz");
  35. return {
  36. value: target[property],
  37. enumerable: false,
  38. configurable: true,
  39. writable: true,
  40. };
  41. },
  42. });
  43. expect(p).toHaveConfigurableProperty("baz");
  44. expect(p).not.toHaveEnumerableProperty("baz");
  45. expect(p).not.toHaveWritableProperty("baz");
  46. expect(p).toHaveValueProperty("baz", "qux");
  47. expect(p).not.toHaveGetterProperty("baz");
  48. expect(p).not.toHaveSetterProperty("baz");
  49. d = Object.getOwnPropertyDescriptor(p, "foo");
  50. expect(p).toHaveConfigurableProperty("foo");
  51. expect(p).not.toHaveEnumerableProperty("foo");
  52. expect(p).toHaveWritableProperty("foo");
  53. expect(p).toHaveValueProperty("foo", "bar");
  54. expect(p).not.toHaveGetterProperty("foo");
  55. expect(p).not.toHaveSetterProperty("foo");
  56. });
  57. });
  58. describe("[[GetOwnProperty]] invariants", () => {
  59. test("must return an object or undefined", () => {
  60. expect(() => {
  61. Object.getOwnPropertyDescriptor(
  62. new Proxy(
  63. {},
  64. {
  65. getOwnPropertyDescriptor() {
  66. return 1;
  67. },
  68. }
  69. )
  70. );
  71. }).toThrowWithMessage(
  72. TypeError,
  73. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: must return an object or undefined"
  74. );
  75. });
  76. test("cannot return undefined for a non-configurable property", () => {
  77. let o = {};
  78. Object.defineProperty(o, "foo", { value: 10, configurable: false });
  79. let p = new Proxy(o, {
  80. getOwnPropertyDescriptor() {
  81. return undefined;
  82. },
  83. });
  84. expect(Object.getOwnPropertyDescriptor(p, "bar")).toBeUndefined();
  85. expect(() => {
  86. Object.getOwnPropertyDescriptor(p, "foo");
  87. }).toThrowWithMessage(
  88. TypeError,
  89. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot return undefined for a property on the target which is a non-configurable property"
  90. );
  91. });
  92. test("cannot return undefined for an existing property if the target is non-extensible", () => {
  93. let o = {};
  94. Object.defineProperty(o, "baz", {
  95. value: 20,
  96. configurable: true,
  97. writable: true,
  98. enumerable: true,
  99. });
  100. Object.preventExtensions(o);
  101. let p = new Proxy(o, {
  102. getOwnPropertyDescriptor() {
  103. return undefined;
  104. },
  105. });
  106. expect(() => {
  107. Object.getOwnPropertyDescriptor(p, "baz");
  108. }).toThrowWithMessage(
  109. TypeError,
  110. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report a property as being undefined if it exists as an own property of the target and the target is non-extensible"
  111. );
  112. });
  113. test("invalid property descriptors", () => {
  114. let o = {};
  115. Object.defineProperty(o, "v1", { value: 10, configurable: false });
  116. Object.defineProperty(o, "v2", { value: 10, configurable: false, enumerable: true });
  117. Object.defineProperty(o, "v3", {
  118. configurable: false,
  119. get() {
  120. return 1;
  121. },
  122. });
  123. Object.defineProperty(o, "v4", {
  124. value: 10,
  125. configurable: false,
  126. writable: false,
  127. enumerable: true,
  128. });
  129. expect(() => {
  130. Object.getOwnPropertyDescriptor(
  131. new Proxy(o, {
  132. getOwnPropertyDescriptor() {
  133. return { configurable: true };
  134. },
  135. }),
  136. "v1"
  137. );
  138. }).toThrowWithMessage(
  139. TypeError,
  140. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target"
  141. );
  142. expect(() => {
  143. Object.getOwnPropertyDescriptor(
  144. new Proxy(o, {
  145. getOwnPropertyDescriptor() {
  146. return { enumerable: false };
  147. },
  148. }),
  149. "v2"
  150. );
  151. }).toThrowWithMessage(
  152. TypeError,
  153. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target"
  154. );
  155. expect(() => {
  156. Object.getOwnPropertyDescriptor(
  157. new Proxy(o, {
  158. getOwnPropertyDescriptor() {
  159. return { value: 10 };
  160. },
  161. }),
  162. "v3"
  163. );
  164. }).toThrowWithMessage(
  165. TypeError,
  166. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target"
  167. );
  168. expect(() => {
  169. Object.getOwnPropertyDescriptor(
  170. new Proxy(o, {
  171. getOwnPropertyDescriptor() {
  172. return { value: 10, writable: true };
  173. },
  174. }),
  175. "v4"
  176. );
  177. }).toThrowWithMessage(
  178. TypeError,
  179. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target"
  180. );
  181. });
  182. test("cannot report a property as non-configurable if it does not exist or is non-configurable", () => {
  183. let o = {};
  184. Object.defineProperty(o, "v", { configurable: true });
  185. expect(() => {
  186. Object.getOwnPropertyDescriptor(
  187. new Proxy(o, {
  188. getOwnPropertyDescriptor() {
  189. return { configurable: false };
  190. },
  191. }),
  192. "v"
  193. );
  194. }).toThrowWithMessage(
  195. TypeError,
  196. "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report target's property as non-configurable if the property does not exist, or if it is configurable"
  197. );
  198. });
  199. });