Proxy.handler-set.js 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. describe("[[Set]] trap normal behavior", () => {
  2. test("forwarding when not defined in handler", () => {
  3. expect((new Proxy({}, { set: undefined }).foo = 1)).toBe(1);
  4. expect((new Proxy({}, { set: null }).foo = 1)).toBe(1);
  5. expect((new Proxy({}, {}).foo = 1)).toBe(1);
  6. });
  7. test("correct arguments supplied to trap", () => {
  8. let o = {};
  9. let p = new Proxy(o, {
  10. set(target, prop, value, receiver) {
  11. expect(target).toBe(o);
  12. expect(prop).toBe("foo");
  13. expect(value).toBe(10);
  14. expect(receiver).toBe(p);
  15. return true;
  16. },
  17. });
  18. p.foo = 10;
  19. });
  20. test("correct arguments passed to trap even for number", () => {
  21. let o = {};
  22. let p = new Proxy(o, {
  23. set(target, prop, value, receiver) {
  24. expect(target).toBe(o);
  25. expect(prop).toBe("1");
  26. expect(value).toBe(10);
  27. expect(receiver).toBe(p);
  28. return true;
  29. },
  30. });
  31. p[1] = 10;
  32. });
  33. test("conditional return value", () => {
  34. let p = new Proxy(
  35. {},
  36. {
  37. set(target, prop, value) {
  38. if (target[prop] === value) {
  39. target[prop] *= 2;
  40. } else {
  41. target[prop] = value;
  42. }
  43. },
  44. }
  45. );
  46. p.foo = 10;
  47. expect(p.foo).toBe(10);
  48. p.foo = 10;
  49. expect(p.foo).toBe(20);
  50. p.foo = 10;
  51. expect(p.foo).toBe(10);
  52. p[Symbol.hasInstance] = "foo";
  53. expect(p[Symbol.hasInstance]).toBe("foo");
  54. });
  55. test("custom receiver value", () => {
  56. const o = {};
  57. const r = {};
  58. let p = new Proxy(o, {
  59. set(target, property, value, receiver) {
  60. receiver[property] = value;
  61. return true;
  62. },
  63. });
  64. expect(Reflect.set(p, "foo", 42, r)).toBe(true);
  65. expect(o.foo).toBeUndefined();
  66. expect(r.foo).toBe(42);
  67. });
  68. });
  69. describe("[[Set]] invariants", () => {
  70. test("cannot return true for a non-configurable, non-writable property", () => {
  71. let o = {};
  72. Object.defineProperty(o, "foo", { value: 10 });
  73. let p = new Proxy(o, {
  74. set() {
  75. return true;
  76. },
  77. });
  78. expect(() => {
  79. p.foo = 12;
  80. }).toThrowWithMessage(
  81. TypeError,
  82. "Proxy handler's set trap violates invariant: cannot return true for a property on the target which is a non-configurable, non-writable own data property"
  83. );
  84. });
  85. test("cannot return true for a non-configurable accessor property with no setter", () => {
  86. let o = {};
  87. Object.defineProperty(o, "foo", { get() {} });
  88. let p = new Proxy(o, {
  89. set() {
  90. return true;
  91. },
  92. });
  93. expect(() => {
  94. p.foo = 12;
  95. }).toThrowWithMessage(
  96. TypeError,
  97. "Proxy handler's set trap violates invariant: cannot return true for a property on the target which is a non-configurable own accessor property with an undefined set attribute"
  98. );
  99. });
  100. });