Proxy.handler-defineProperty.js 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. describe("[[DefineProperty]] trap normal behavior", () => {
  2. test("forwarding when not defined in handler", () => {
  3. let p = new Proxy({}, { defineProperty: null });
  4. expect(Object.defineProperty(p, "foo", {})).toBe(p);
  5. p = new Proxy({}, { defineProperty: undefined });
  6. expect(Object.defineProperty(p, "foo", {})).toBe(p);
  7. p = new Proxy({}, {});
  8. expect(Object.defineProperty(p, "foo", {})).toBe(p);
  9. });
  10. test("correct arguments passed to trap", () => {
  11. let o = {};
  12. p = new Proxy(o, {
  13. defineProperty(target, name, descriptor) {
  14. expect(target).toBe(o);
  15. expect(name).toBe("foo");
  16. expect(descriptor.configurable).toBe(true);
  17. expect(descriptor.enumerable).toBeUndefined();
  18. expect(descriptor.writable).toBe(true);
  19. expect(descriptor.value).toBe(10);
  20. expect(descriptor.get).toBeUndefined();
  21. expect(descriptor.set).toBeUndefined();
  22. return true;
  23. },
  24. });
  25. Object.defineProperty(p, "foo", { configurable: true, writable: true, value: 10 });
  26. });
  27. test("optionally ignoring the define call", () => {
  28. let o = {};
  29. let p = new Proxy(o, {
  30. defineProperty(target, name, descriptor) {
  31. if (target[name] === undefined)
  32. Object.defineProperty(target, name, descriptor);
  33. return true;
  34. },
  35. });
  36. Object.defineProperty(p, "foo", { value: 10, enumerable: true, configurable: false, writable: true });
  37. let d = Object.getOwnPropertyDescriptor(p, "foo");
  38. expect(d.enumerable).toBe(true);
  39. expect(d.configurable).toBe(false);
  40. expect(d.writable).toBe(true);
  41. expect(d.value).toBe(10);
  42. expect(d.get).toBeUndefined();
  43. expect(d.set).toBeUndefined();
  44. Object.defineProperty(p, "foo", { value: 20, enumerable: true, configurable: false, writable: true });
  45. d = Object.getOwnPropertyDescriptor(p, "foo");
  46. expect(d.enumerable).toBe(true);
  47. expect(d.configurable).toBe(false);
  48. expect(d.writable).toBe(true);
  49. expect(d.value).toBe(10);
  50. expect(d.get).toBeUndefined();
  51. expect(d.set).toBeUndefined();
  52. });
  53. });
  54. describe("[[DefineProperty]] invariants", () => {
  55. test("trap can't return false", () => {
  56. let p = new Proxy({}, {
  57. defineProperty() { return false; }
  58. });
  59. expect(() => {
  60. Object.defineProperty(p, "foo", {});
  61. }).toThrowWithMessage(TypeError, "Object's [[DefineProperty]] method returned false");
  62. });
  63. test("trap cannot return true for a non-extensible target if the property does not exist", () => {
  64. let o = {};
  65. Object.preventExtensions(o);
  66. let p = new Proxy(o, {
  67. defineProperty() {
  68. return true;
  69. }
  70. });
  71. expect(() => {
  72. Object.defineProperty(p, "foo", {});
  73. }).toThrowWithMessage(TypeError, "Proxy handler's defineProperty trap violates invariant: a property cannot be reported as being defined if the property does not exist on the target and the target is non-extensible");
  74. });
  75. test("trap cannot return true for a non-configurable property if it doesn't already exist on the target", () => {
  76. let o = {};
  77. Object.defineProperty(o, "foo", { value: 10, configurable: true });
  78. let p = new Proxy(o, {
  79. defineProperty() {
  80. return true;
  81. },
  82. });
  83. expect(() => {
  84. Object.defineProperty(p, "bar", { value: 6, configurable: false });
  85. }).toThrowWithMessage(TypeError, "Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it does not already exist on the target object");
  86. });
  87. test("trap cannot return true for a non-configurable property if it already exists as a configurable property", () => {
  88. let o = {};
  89. Object.defineProperty(o, "foo", { value: 10, configurable: true });
  90. let p = new Proxy(o, {
  91. defineProperty() {
  92. return true;
  93. },
  94. });
  95. expect(() => {
  96. Object.defineProperty(p, "foo", { value: 6, configurable: false });
  97. }).toThrowWithMessage(TypeError, "Proxy handler's defineProperty trap violates invariant: a property cannot be defined as non-configurable if it already exists on the target object as a configurable property");
  98. })
  99. });