]> Lady’s Gitweb - Pisces/blobdiff - value.test.js
De‐classify property descriptors; move to value.js
[Pisces] / value.test.js
index 9121af479c46f3e2a190ec64742bf82ffd31ae34..0f95f22fda345a9841fc695a4c47b6dbaa8649a3 100644 (file)
@@ -8,6 +8,9 @@
 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
 
 import {
+  assert,
+  assertEquals,
+  assertNotStrictEquals,
   assertStrictEquals,
   assertThrows,
   describe,
@@ -15,8 +18,14 @@ import {
 } from "./dev-deps.js";
 import {
   ASYNC_ITERATOR,
+  completePropertyDescriptor,
   HAS_INSTANCE,
   IS_CONCAT_SPREADABLE,
+  isAccessorDescriptor,
+  isDataDescriptor,
+  isFullyPopulatedDescriptor,
+  isGenericDescriptor,
+  isPropertyDescriptorRecord,
   ITERATOR,
   LN10,
   LN2,
@@ -48,6 +57,7 @@ import {
   toIndex,
   toLength,
   toPrimitive,
+  toPropertyDescriptor,
   type,
   UNDEFINED,
   UNSCOPABLES,
@@ -239,21 +249,298 @@ describe("UNSCOPABLES", () => {
   });
 });
 
-describe("Ε", () => {
-  it("[[Get]] is ε", () => {
-    assertStrictEquals(Ε, Number.EPSILON);
+describe("completePropertyDescriptor", () => {
+  it("[[Call]] completes a generic descriptor", () => {
+    const desc = {};
+    completePropertyDescriptor(desc);
+    assertEquals(desc, {
+      configurable: false,
+      enumerable: false,
+      value: undefined,
+      writable: false,
+    });
+  });
+
+  it("[[Call]] completes a data descriptor", () => {
+    const desc = { value: undefined };
+    completePropertyDescriptor(desc);
+    assertEquals(desc, {
+      configurable: false,
+      enumerable: false,
+      value: undefined,
+      writable: false,
+    });
+  });
+
+  it("[[Call]] completes an accessor descriptor", () => {
+    const desc = { get: undefined };
+    completePropertyDescriptor(desc);
+    assertEquals(desc, {
+      configurable: false,
+      enumerable: false,
+      get: undefined,
+      set: undefined,
+    });
+  });
+
+  it("[[Call]] throws an error when the descriptor is undefined", () => {
+    assertThrows(() => new completePropertyDescriptor(undefined));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new completePropertyDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(completePropertyDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        completePropertyDescriptor.name,
+        "completePropertyDescriptor",
+      );
+    });
   });
 });
 
-describe("Π", () => {
-  it("[[Get]] is π", () => {
-    assertStrictEquals(Π, Math.PI);
+describe("isAccessorDescriptor", () => {
+  it("[[Call]] returns false for a generic descriptor", () => {
+    assertStrictEquals(isAccessorDescriptor({}), false);
+  });
+
+  it("[[Get]] returns false for a data descriptor", () => {
+    assertStrictEquals(
+      isAccessorDescriptor({ value: undefined }),
+      false,
+    );
+    assertStrictEquals(
+      isAccessorDescriptor({ writable: undefined }),
+      false,
+    );
+  });
+
+  it("[[Get]] returns true for an accessor descriptor", () => {
+    assertStrictEquals(isAccessorDescriptor({ get: undefined }), true);
+    assertStrictEquals(isAccessorDescriptor({ set: undefined }), true);
+  });
+
+  it("[[Get]] returns false for undefined", () => {
+    assertStrictEquals(isAccessorDescriptor(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isAccessorDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isAccessorDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isAccessorDescriptor.name,
+        "isAccessorDescriptor",
+      );
+    });
   });
 });
 
-describe("ℇ", () => {
-  it("[[Get]] is ℇ", () => {
-    assertStrictEquals(ℇ, Math.E);
+describe("isDataDescriptor", () => {
+  it("[[Call]] returns false for a generic descriptor", () => {
+    assertStrictEquals(isDataDescriptor({}), false);
+  });
+
+  it("[[Get]] returns true for a data descriptor", () => {
+    assertStrictEquals(isDataDescriptor({ value: undefined }), true);
+    assertStrictEquals(isDataDescriptor({ writable: true }), true);
+  });
+
+  it("[[Get]] returns false for an accessor descriptor", () => {
+    assertStrictEquals(isDataDescriptor({ get: undefined }), false);
+    assertStrictEquals(isDataDescriptor({ set: undefined }), false);
+  });
+
+  it("[[Get]] returns false for undefined", () => {
+    assertStrictEquals(isDataDescriptor(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isDataDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isDataDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(isDataDescriptor.name, "isDataDescriptor");
+    });
+  });
+});
+
+describe("isFullyPopulatedDescriptor", () => {
+  it("[[Call]] returns false for a generic descriptor", () => {
+    assertStrictEquals(isFullyPopulatedDescriptor({}), false);
+  });
+
+  it("[[Get]] returns false for a non‐fully‐populated data descriptor", () => {
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({ value: undefined }),
+      false,
+    );
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({ writable: true }),
+      false,
+    );
+  });
+
+  it("[[Get]] returns true for a fully‐populated data descriptor", () => {
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({
+        configurable: true,
+        enumerable: true,
+        value: undefined,
+        writable: true,
+      }),
+      true,
+    );
+  });
+
+  it("[[Get]] returns false for a non‐fully‐populated accessor descriptor", () => {
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({ get: undefined }),
+      false,
+    );
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({ set: undefined }),
+      false,
+    );
+  });
+
+  it("[[Get]] returns true for a fully‐populated accessor descriptor", () => {
+    assertStrictEquals(
+      isFullyPopulatedDescriptor({
+        configurable: true,
+        enumerable: true,
+        get: undefined,
+        set: undefined,
+      }),
+      true,
+    );
+  });
+
+  it("[[Get]] returns false for undefined", () => {
+    assertStrictEquals(isFullyPopulatedDescriptor(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isFullyPopulatedDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isFullyPopulatedDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isFullyPopulatedDescriptor.name,
+        "isFullyPopulatedDescriptor",
+      );
+    });
+  });
+});
+
+describe("isGenericDescriptor", () => {
+  it("[[Call]] returns true for a generic descriptor", () => {
+    assertStrictEquals(isGenericDescriptor({}), true);
+  });
+
+  it("[[Get]] returns false for a data descriptor", () => {
+    assertStrictEquals(
+      isGenericDescriptor({ value: undefined }),
+      false,
+    );
+    assertStrictEquals(isGenericDescriptor({ writable: true }), false);
+  });
+
+  it("[[Get]] returns false for an accessor descriptor", () => {
+    assertStrictEquals(isGenericDescriptor({ get: undefined }), false);
+    assertStrictEquals(isGenericDescriptor({ set: undefined }), false);
+  });
+
+  it("[[Get]] returns false for undefined", () => {
+    assertStrictEquals(isGenericDescriptor(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isGenericDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isGenericDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isGenericDescriptor.name,
+        "isGenericDescriptor",
+      );
+    });
+  });
+});
+
+describe("isPropertyDescriptorRecord", () => {
+  it("[[Call]] returns true for objects created by toPropertyDescriptor", () => {
+    assertStrictEquals(
+      isPropertyDescriptorRecord(toPropertyDescriptor({})),
+      true,
+    );
+  });
+
+  it("[[Get]] returns false for other objects", () => {
+    assertStrictEquals(
+      isPropertyDescriptorRecord(Object.create(null)),
+      false,
+    );
+  });
+
+  it("[[Get]] returns false for undefined", () => {
+    assertStrictEquals(isPropertyDescriptorRecord(undefined), false);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isPropertyDescriptorRecord({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isPropertyDescriptorRecord.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isPropertyDescriptorRecord.name,
+        "isPropertyDescriptorRecord",
+      );
+    });
   });
 });
 
@@ -747,6 +1034,278 @@ describe("toPrimitive", () => {
   });
 });
 
+describe("toPropertyDescriptor", () => {
+  it("[[Call]] creates a new property descriptor record", () => {
+    const obj = {};
+    const desc = toPropertyDescriptor(obj);
+    assertEquals(obj, desc);
+    assertNotStrictEquals(obj, desc);
+  });
+
+  it("[[Call]] coerces the values", () => {
+    assertEquals(
+      toPropertyDescriptor({
+        configurable: undefined,
+        enumerable: undefined,
+        writable: undefined,
+      }),
+      { configurable: false, enumerable: false, writable: false },
+    );
+  });
+
+  it("[[Construct]] throws for primitives", () => {
+    assertThrows(() => toPropertyDescriptor(undefined));
+    assertThrows(() => toPropertyDescriptor("failure"));
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new toPropertyDescriptor({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(toPropertyDescriptor.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        toPropertyDescriptor.name,
+        "toPropertyDescriptor",
+      );
+    });
+  });
+
+  describe("~configurable", () => {
+    it("[[DefineOwnProperty]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "configurable", {});
+      assertStrictEquals(desc.configurable, false);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "configurable", { get: undefined })
+      );
+    });
+
+    it("[[Set]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      desc.configurable = undefined;
+      assertStrictEquals(desc.configurable, false);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ configurable: false });
+      delete desc.configurable;
+      assert(!("configurable" in desc));
+    });
+  });
+
+  describe("~enumerable", () => {
+    it("[[DefineOwnProperty]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "enumerable", {});
+      assertStrictEquals(desc.enumerable, false);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "enumerable", { get: undefined })
+      );
+    });
+
+    it("[[Set]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      desc.enumerable = undefined;
+      assertStrictEquals(desc.enumerable, false);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ enumerable: false });
+      delete desc.enumerable;
+      assert(!("enumerable" in desc));
+    });
+  });
+
+  describe("~get", () => {
+    it("[[DefineOwnProperty]] works", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "get", {});
+      assertStrictEquals(desc.get, undefined);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "get", { get: undefined })
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(
+        () => Object.defineProperty(desc, "get", { value: null }),
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if a data property is defined", () => {
+      const desc = toPropertyDescriptor({ value: undefined });
+      assertThrows(() => Object.defineProperty(desc, "get", {}));
+    });
+
+    it("[[Set]] works", () => {
+      const desc = toPropertyDescriptor({});
+      const fn = () => {};
+      desc.get = fn;
+      assertStrictEquals(desc.get, fn);
+    });
+
+    it("[[Set]] throws if not callable or undefined", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() => desc.get = null);
+    });
+
+    it("[[Set]] throws if a data property is defined", () => {
+      const desc = toPropertyDescriptor({ value: undefined });
+      assertThrows(() => desc.get = undefined);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ get: undefined });
+      delete desc.get;
+      assert(!("get" in desc));
+    });
+  });
+
+  describe("~set", () => {
+    it("[[DefineOwnProperty]] works", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "set", {});
+      assertStrictEquals(desc.set, undefined);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "set", { get: undefined })
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(
+        () => Object.defineProperty(desc, "set", { value: null }),
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if a data property is defined", () => {
+      const desc = toPropertyDescriptor({ value: undefined });
+      assertThrows(() => Object.defineProperty(desc, "set", {}));
+    });
+
+    it("[[Set]] works", () => {
+      const desc = toPropertyDescriptor({});
+      const fn = (_) => {};
+      desc.set = fn;
+      assertStrictEquals(desc.set, fn);
+    });
+
+    it("[[Set]] throws if not callable or undefined", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() => desc.set = null);
+    });
+
+    it("[[Set]] throws if a data property is defined", () => {
+      const desc = toPropertyDescriptor({ value: undefined });
+      assertThrows(() => desc.set = undefined);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ set: undefined });
+      delete desc.set;
+      assert(!("set" in desc));
+    });
+  });
+
+  describe("~value", () => {
+    it("[[DefineOwnProperty]] works", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "value", {});
+      assertStrictEquals(desc.value, undefined);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "value", { get: undefined })
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
+      const desc = toPropertyDescriptor({ get: undefined });
+      assertThrows(() => Object.defineProperty(desc, "value", {}));
+    });
+
+    it("[[Set]] works", () => {
+      const desc = toPropertyDescriptor({});
+      desc.value = "success";
+      assertStrictEquals(desc.value, "success");
+    });
+
+    it("[[Set]] throws if an accessor property is defined", () => {
+      const desc = toPropertyDescriptor({ get: undefined });
+      assertThrows(() => desc.value = null);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ value: undefined });
+      delete desc.value;
+      assert(!("value" in desc));
+    });
+  });
+
+  describe("~writable", () => {
+    it("[[DefineOwnProperty]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      Object.defineProperty(desc, "writable", {});
+      assertStrictEquals(desc.writable, false);
+    });
+
+    it("[[DefineOwnProperty]] throws for accessor properties", () => {
+      const desc = toPropertyDescriptor({});
+      assertThrows(() =>
+        Object.defineProperty(desc, "writable", { get: undefined })
+      );
+    });
+
+    it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
+      const desc = toPropertyDescriptor({ get: undefined });
+      assertThrows(() => Object.defineProperty(desc, "writable", {}));
+    });
+
+    it("[[Set]] coerces to a boolean", () => {
+      const desc = toPropertyDescriptor({});
+      desc.writable = undefined;
+      assertStrictEquals(desc.writable, false);
+    });
+
+    it("[[Set]] throws if an accessor property is defined", () => {
+      const desc = toPropertyDescriptor({ get: undefined });
+      assertThrows(() => desc.writable = false);
+    });
+
+    it("[[Delete]] works", () => {
+      const desc = toPropertyDescriptor({ writable: false });
+      delete desc.writable;
+      assert(!("writable" in desc));
+    });
+  });
+});
+
 describe("type", () => {
   it('[[Call]] returns "null" for null', () => {
     assertStrictEquals(type(null), "null");
@@ -784,3 +1343,21 @@ describe("type", () => {
     });
   });
 });
+
+describe("Ε", () => {
+  it("[[Get]] is ε", () => {
+    assertStrictEquals(Ε, Number.EPSILON);
+  });
+});
+
+describe("Π", () => {
+  it("[[Get]] is π", () => {
+    assertStrictEquals(Π, Math.PI);
+  });
+});
+
+describe("ℇ", () => {
+  it("[[Get]] is ℇ", () => {
+    assertStrictEquals(ℇ, Math.E);
+  });
+});
This page took 0.033097 seconds and 4 git commands to generate.