]> Lady’s Gitweb - Pisces/blobdiff - object.test.js
Refactor object.js not to depend on function.js
[Pisces] / object.test.js
index d5a60bb68ed60b00f3f31be1c0d1e11b935ab48d..3a0e1a73363a94d855ede03c3ed99ba7e67265f0 100644 (file)
@@ -19,6 +19,8 @@ import {
   spy,
 } from "./dev-deps.js";
 import {
+  defineOwnDataProperty,
+  defineOwnNonenumerableDataProperty,
   defineOwnProperties,
   defineOwnProperty,
   deleteOwnProperty,
@@ -34,17 +36,19 @@ import {
   getPrototype,
   hasOwnProperty,
   hasProperty,
+  isArraylikeObject,
+  isConcatSpreadableObject,
   isExtensibleObject,
   isUnfrozenObject,
   isUnsealedObject,
   LazyLoader,
+  lengthOfArraylike,
   namedEntries,
   namedKeys,
   namedValues,
   objectCreate,
   objectFromEntries,
   preventExtensions,
-  PropertyDescriptor,
   seal,
   setPropertyValue,
   setPropertyValues,
@@ -307,576 +311,105 @@ describe("LazyLoader", () => {
   });
 });
 
-describe("PropertyDescriptor", () => {
-  it("[[Call]] throws an error", () => {
-    assertThrows(() => PropertyDescriptor({}));
+describe("defineOwnDataProperty", () => {
+  it("[[Call]] defines the property", () => {
+    const obj = {};
+    defineOwnDataProperty(obj, "etaoin", "success");
+    assert(Object.hasOwn(obj, "etaoin"));
+    assertStrictEquals(obj.etaoin, "success");
+  });
+
+  it("[[Call]] defines a configurable, enumerable, writable property", () => {
+    const obj = {};
+    defineOwnDataProperty(obj, "etaoin", "success");
+    assertEquals(
+      Object.getOwnPropertyDescriptor(obj, "etaoin"),
+      {
+        configurable: true,
+        enumerable: true,
+        value: "success",
+        writable: true,
+      },
+    );
   });
 
-  it("[[Construct]] creates a new PropertyDescriptor", () => {
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
     assertStrictEquals(
-      Object.getPrototypeOf(new PropertyDescriptor({})),
-      PropertyDescriptor.prototype,
+      defineOwnDataProperty(obj, "etaoin", null),
+      obj,
     );
   });
 
-  it("[[Construct]] throws for primitives", () => {
-    assertThrows(() => new PropertyDescriptor("failure"));
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new defineOwnDataProperty(obj, "etaoin", null));
   });
 
   describe(".length", () => {
     it("[[Get]] returns the correct length", () => {
-      assertStrictEquals(PropertyDescriptor.length, 1);
+      assertStrictEquals(defineOwnDataProperty.length, 3);
     });
   });
 
   describe(".name", () => {
     it("[[Get]] returns the correct name", () => {
       assertStrictEquals(
-        PropertyDescriptor.name,
-        "PropertyDescriptor",
+        defineOwnDataProperty.name,
+        "defineOwnDataProperty",
       );
     });
   });
+});
 
-  describe("::complete", () => {
-    it("[[Call]] completes a generic descriptor", () => {
-      const desc = {};
-      PropertyDescriptor.prototype.complete.call(desc);
-      assertEquals(desc, {
-        configurable: false,
-        enumerable: false,
-        value: undefined,
-        writable: false,
-      });
-    });
-
-    it("[[Call]] completes a data descriptor", () => {
-      const desc = { value: undefined };
-      PropertyDescriptor.prototype.complete.call(desc);
-      assertEquals(desc, {
-        configurable: false,
-        enumerable: false,
-        value: undefined,
-        writable: false,
-      });
-    });
+describe("defineOwnNonenumerableDataProperty", () => {
+  it("[[Call]] defines the property", () => {
+    const obj = {};
+    defineOwnNonenumerableDataProperty(obj, "etaoin", "success");
+    assert(Object.hasOwn(obj, "etaoin"));
+    assertStrictEquals(obj.etaoin, "success");
+  });
 
-    it("[[Call]] completes an accessor descriptor", () => {
-      const desc = { get: undefined };
-      PropertyDescriptor.prototype.complete.call(desc);
-      assertEquals(desc, {
-        configurable: false,
+  it("[[Call]] defines a configurable, non·enumerable, writable property", () => {
+    const obj = {};
+    defineOwnNonenumerableDataProperty(obj, "etaoin", "success");
+    assertEquals(
+      Object.getOwnPropertyDescriptor(obj, "etaoin"),
+      {
+        configurable: true,
         enumerable: false,
-        get: undefined,
-        set: undefined,
-      });
-    });
-
-    describe(".length", () => {
-      it("[[Get]] returns the correct length", () => {
-        assertStrictEquals(
-          PropertyDescriptor.prototype.complete.length,
-          0,
-        );
-      });
-    });
-
-    describe(".name", () => {
-      it("[[Get]] returns the correct name", () => {
-        assertStrictEquals(
-          PropertyDescriptor.prototype.complete.name,
-          "complete",
-        );
-      });
-    });
+        value: "success",
+        writable: true,
+      },
+    );
   });
 
-  describe("::isAccessorDescriptor", () => {
-    it("[[Get]] returns false for a generic descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isAccessorDescriptor",
-          {},
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns false for a data descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isAccessorDescriptor",
-          { value: undefined },
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns true for an accessor descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isAccessorDescriptor",
-          { get: undefined },
-        ),
-        true,
-      );
-    });
-
-    describe("[[GetOwnProperty]].get.length", () => {
-      it("[[Get]] returns the correct length", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isAccessorDescriptor",
-          ).get.length,
-          0,
-        );
-      });
-    });
-
-    describe("[[GetOwnProperty]].get.name", () => {
-      it("[[Get]] returns the correct name", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isAccessorDescriptor",
-          ).get.name,
-          "get isAccessorDescriptor",
-        );
-      });
-    });
+  it("[[Call]] returns the provided object", () => {
+    const obj = {};
+    assertStrictEquals(
+      defineOwnNonenumerableDataProperty(obj, "etaoin", null),
+      obj,
+    );
   });
 
-  describe("::isDataDescriptor", () => {
-    it("[[Get]] returns false for a generic descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isDataDescriptor",
-          {},
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns true for a data descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isDataDescriptor",
-          { value: undefined },
-        ),
-        true,
-      );
-    });
-
-    it("[[Get]] returns false for an accessor descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isDataDescriptor",
-          { get: undefined },
-        ),
-        false,
-      );
-    });
-
-    describe("[[GetOwnProperty]].get.length", () => {
-      it("[[Get]] returns the correct length", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isDataDescriptor",
-          ).get.length,
-          0,
-        );
-      });
-    });
-
-    describe("[[GetOwnProperty]].get.name", () => {
-      it("[[Get]] returns the correct name", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isDataDescriptor",
-          ).get.name,
-          "get isDataDescriptor",
-        );
-      });
-    });
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() =>
+      new defineOwnNonenumerableDataProperty(obj, "etaoin", null)
+    );
   });
 
-  describe("::isFullyPopulated", () => {
-    it("[[Get]] returns false for a generic descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isFullyPopulated",
-          {},
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns false for a non‐fully‐populated data descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isFullyPopulated",
-          { value: undefined },
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns true for a fully‐populated data descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(PropertyDescriptor.prototype, "isFullyPopulated", {
-          configurable: true,
-          enumerable: true,
-          value: undefined,
-          writable: true,
-        }),
-        true,
-      );
-    });
-
-    it("[[Get]] returns false for a non‐fully‐populated accessor descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isFullyPopulated",
-          { get: undefined },
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns true for a fully‐populated accessor descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(PropertyDescriptor.prototype, "isFullyPopulated", {
-          configurable: true,
-          enumerable: true,
-          get: undefined,
-          set: undefined,
-        }),
-        true,
-      );
-    });
-
-    describe("[[GetOwnProperty]].get.length", () => {
-      it("[[Get]] returns the correct length", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isFullyPopulated",
-          ).get.length,
-          0,
-        );
-      });
-    });
-
-    describe("[[GetOwnProperty]].get.name", () => {
-      it("[[Get]] returns the correct name", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isFullyPopulated",
-          ).get.name,
-          "get isFullyPopulated",
-        );
-      });
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(defineOwnNonenumerableDataProperty.length, 3);
     });
   });
 
-  describe("::isGenericDescriptor", () => {
-    it("[[Get]] returns true for a generic descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isGenericDescriptor",
-          {},
-        ),
-        true,
-      );
-    });
-
-    it("[[Get]] returns true for a data descriptor", () => {
-      assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isGenericDescriptor",
-          { value: undefined },
-        ),
-        false,
-      );
-    });
-
-    it("[[Get]] returns false for an accessor descriptor", () => {
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
       assertStrictEquals(
-        Reflect.get(
-          PropertyDescriptor.prototype,
-          "isGenericDescriptor",
-          { get: undefined },
-        ),
-        false,
-      );
-    });
-
-    describe("[[GetOwnProperty]].get.length", () => {
-      it("[[Get]] returns the correct length", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isGenericDescriptor",
-          ).get.length,
-          0,
-        );
-      });
-    });
-
-    describe("[[GetOwnProperty]].get.name", () => {
-      it("[[Get]] returns the correct name", () => {
-        assertStrictEquals(
-          Object.getOwnPropertyDescriptor(
-            PropertyDescriptor.prototype,
-            "isGenericDescriptor",
-          ).get.name,
-          "get isGenericDescriptor",
-        );
-      });
-    });
-  });
-
-  describe("~configurable", () => {
-    it("[[DefineOwnProperty]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "configurable", {});
-      assertStrictEquals(desc.configurable, false);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "configurable", { get: undefined })
-      );
-    });
-
-    it("[[Set]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      desc.configurable = undefined;
-      assertStrictEquals(desc.configurable, false);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ configurable: false });
-      delete desc.configurable;
-      assert(!("configurable" in desc));
-    });
-  });
-
-  describe("~enumerable", () => {
-    it("[[DefineOwnProperty]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "enumerable", {});
-      assertStrictEquals(desc.enumerable, false);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "enumerable", { get: undefined })
-      );
-    });
-
-    it("[[Set]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      desc.enumerable = undefined;
-      assertStrictEquals(desc.enumerable, false);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ enumerable: false });
-      delete desc.enumerable;
-      assert(!("enumerable" in desc));
-    });
-  });
-
-  describe("~get", () => {
-    it("[[DefineOwnProperty]] works", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "get", {});
-      assertStrictEquals(desc.get, undefined);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "get", { get: undefined })
-      );
-    });
-
-    it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(
-        () => Object.defineProperty(desc, "get", { value: null }),
-      );
-    });
-
-    it("[[DefineOwnProperty]] throws if a data property is defined", () => {
-      const desc = new PropertyDescriptor({ value: undefined });
-      assertThrows(() => Object.defineProperty(desc, "get", {}));
-    });
-
-    it("[[Set]] works", () => {
-      const desc = new PropertyDescriptor({});
-      const fn = () => {};
-      desc.get = fn;
-      assertStrictEquals(desc.get, fn);
-    });
-
-    it("[[Set]] throws if not callable or undefined", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() => desc.get = null);
-    });
-
-    it("[[Set]] throws if a data property is defined", () => {
-      const desc = new PropertyDescriptor({ value: undefined });
-      assertThrows(() => desc.get = undefined);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ get: undefined });
-      delete desc.get;
-      assert(!("get" in desc));
-    });
-  });
-
-  describe("~set", () => {
-    it("[[DefineOwnProperty]] works", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "set", {});
-      assertStrictEquals(desc.set, undefined);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "set", { get: undefined })
-      );
-    });
-
-    it("[[DefineOwnProperty]] throws if not callable or undefined", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(
-        () => Object.defineProperty(desc, "set", { value: null }),
-      );
-    });
-
-    it("[[DefineOwnProperty]] throws if a data property is defined", () => {
-      const desc = new PropertyDescriptor({ value: undefined });
-      assertThrows(() => Object.defineProperty(desc, "set", {}));
-    });
-
-    it("[[Set]] works", () => {
-      const desc = new PropertyDescriptor({});
-      const fn = (_) => {};
-      desc.set = fn;
-      assertStrictEquals(desc.set, fn);
-    });
-
-    it("[[Set]] throws if not callable or undefined", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() => desc.set = null);
-    });
-
-    it("[[Set]] throws if a data property is defined", () => {
-      const desc = new PropertyDescriptor({ value: undefined });
-      assertThrows(() => desc.set = undefined);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ set: undefined });
-      delete desc.set;
-      assert(!("set" in desc));
-    });
-  });
-
-  describe("~value", () => {
-    it("[[DefineOwnProperty]] works", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "value", {});
-      assertStrictEquals(desc.value, undefined);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "value", { get: undefined })
-      );
-    });
-
-    it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
-      const desc = new PropertyDescriptor({ get: undefined });
-      assertThrows(() => Object.defineProperty(desc, "value", {}));
-    });
-
-    it("[[Set]] works", () => {
-      const desc = new PropertyDescriptor({});
-      desc.value = "success";
-      assertStrictEquals(desc.value, "success");
-    });
-
-    it("[[Set]] throws if an accessor property is defined", () => {
-      const desc = new PropertyDescriptor({ get: undefined });
-      assertThrows(() => desc.value = null);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ value: undefined });
-      delete desc.value;
-      assert(!("value" in desc));
-    });
-  });
-
-  describe("~writable", () => {
-    it("[[DefineOwnProperty]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      Object.defineProperty(desc, "writable", {});
-      assertStrictEquals(desc.writable, false);
-    });
-
-    it("[[DefineOwnProperty]] throws for accessor properties", () => {
-      const desc = new PropertyDescriptor({});
-      assertThrows(() =>
-        Object.defineProperty(desc, "writable", { get: undefined })
+        defineOwnNonenumerableDataProperty.name,
+        "defineOwnNonenumerableDataProperty",
       );
     });
-
-    it("[[DefineOwnProperty]] throws if an accessor property is defined", () => {
-      const desc = new PropertyDescriptor({ get: undefined });
-      assertThrows(() => Object.defineProperty(desc, "writable", {}));
-    });
-
-    it("[[Set]] coerces to a boolean", () => {
-      const desc = new PropertyDescriptor({});
-      desc.writable = undefined;
-      assertStrictEquals(desc.writable, false);
-    });
-
-    it("[[Set]] throws if an accessor property is defined", () => {
-      const desc = new PropertyDescriptor({ get: undefined });
-      assertThrows(() => desc.writable = false);
-    });
-
-    it("[[Delete]] works", () => {
-      const desc = new PropertyDescriptor({ writable: false });
-      delete desc.writable;
-      assert(!("writable" in desc));
-    });
   });
 });
 
@@ -884,7 +417,7 @@ describe("defineOwnProperty", () => {
   it("[[Call]] defines the property", () => {
     const obj = {};
     defineOwnProperty(obj, "etaoin", {});
-    assert("etaoin" in obj);
+    assert(Object.hasOwn(obj, "etaoin"));
   });
 
   it("[[Call]] returns the provided object", () => {
@@ -1096,17 +629,45 @@ describe("frozenCopy", () => {
     );
   });
 
+  it("[[Call]] preserves data properties", () => {
+    const properties = {
+      implied: {
+        configurable: false,
+        enumerable: true,
+      },
+      writable: {
+        configurable: false,
+        enumerable: true,
+        value: "etaoin",
+        writable: true,
+      },
+      nonwritable: {
+        configurable: false,
+        enumerable: true,
+        value: "shrdlu",
+        writable: false,
+      },
+    };
+    assertEquals(
+      Object.getOwnPropertyDescriptors(
+        frozenCopy(Object.create(null, properties)),
+      ),
+      {
+        implied: {
+          ...properties.implied,
+          value: undefined,
+          writable: false,
+        },
+        writable: { ...properties.writable, writable: false },
+        nonwritable: properties.nonwritable,
+      },
+    );
+  });
+
   it("[[Call]] does not copy properties on the prototype", () => {
     assert(
       !("failure" in
-        frozenCopy(Object.create({ failure: undefined }), {
-          data: {
-            configurable: true,
-            value: undefined,
-            writable: true,
-          },
-          accessor: { configurable: true, get: undefined },
-        })),
+        frozenCopy(Object.create({ failure: undefined }))),
     );
   });
 
@@ -1534,6 +1095,114 @@ describe("hasOwnProperty", () => {
   });
 });
 
+describe("isArraylikeObject", () => {
+  it("[[Call]] returns false for primitives", () => {
+    assertStrictEquals(isArraylikeObject("failure"), false);
+  });
+
+  it("[[Call]] returns false if length throws", () => {
+    assertStrictEquals(
+      isArraylikeObject({
+        get length() {
+          throw void {};
+        },
+      }),
+      false,
+    );
+  });
+
+  it("[[Call]] returns false if length is not a number and cannot be converted to one", () => {
+    assertStrictEquals(isArraylikeObject({ length: 1n }), false);
+  });
+
+  it("[[Call]] returns true if length is convertable to a number", () => {
+    assertStrictEquals(isArraylikeObject({ length: -0 }), true);
+    assertStrictEquals(isArraylikeObject({ length: 1 }), true);
+    assertStrictEquals(isArraylikeObject({ length: -1.25 }), true);
+    assertStrictEquals(
+      isArraylikeObject({ length: 9007199254740992 }),
+      true,
+    );
+    assertStrictEquals(isArraylikeObject({ length: Infinity }), true);
+    assertStrictEquals(isArraylikeObject({ length: "success" }), true);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isArraylikeObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isArraylikeObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isArraylikeObject.name,
+        "isArraylikeObject",
+      );
+    });
+  });
+});
+
+describe("isConcatSpreadableObject", () => {
+  it("[[Call]] returns false for primitives", () => {
+    assertStrictEquals(isConcatSpreadableObject("failure"), false);
+  });
+
+  it("[[Call]] returns false if [Symbol.isConcatSpreadable] is null or false", () => {
+    assertStrictEquals(
+      isConcatSpreadableObject(
+        Object.assign([], { [Symbol.isConcatSpreadable]: null }),
+      ),
+      false,
+    );
+    assertStrictEquals(
+      isConcatSpreadableObject(
+        Object.assign([], { [Symbol.isConcatSpreadable]: false }),
+      ),
+      false,
+    );
+  });
+
+  it("[[Call]] returns true if [Symbol.isConcatSpreadable] is undefined and the object is an array", () => {
+    assertStrictEquals(
+      isConcatSpreadableObject(
+        Object.assign([], { [Symbol.isConcatSpreadable]: undefined }),
+      ),
+      true,
+    );
+  });
+
+  it("[[Call]] returns true if [Symbol.isConcatSpreadable] is true", () => {
+    assertStrictEquals(
+      isConcatSpreadableObject({ [Symbol.isConcatSpreadable]: true }),
+      true,
+    );
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new isConcatSpreadableObject({}));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(isConcatSpreadableObject.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(
+        isConcatSpreadableObject.name,
+        "isConcatSpreadableObject",
+      );
+    });
+  });
+});
+
 describe("isExtensibleObject", () => {
   it("[[Call]] returns true for extensible objects", () => {
     assertStrictEquals(isExtensibleObject({}), true);
@@ -1648,6 +1317,63 @@ describe("isUnsealedObject", () => {
   });
 });
 
+describe("lengthOfArraylike", () => {
+  it("[[Call]] returns the length", () => {
+    assertStrictEquals(
+      lengthOfArraylike({ length: 9007199254740991 }),
+      9007199254740991,
+    );
+  });
+
+  it("[[Call]] returns a non·nan result", () => {
+    assertStrictEquals(lengthOfArraylike({ length: NaN }), 0);
+    assertStrictEquals(lengthOfArraylike({ length: "failure" }), 0);
+  });
+
+  it("[[Call]] returns an integral result", () => {
+    assertStrictEquals(lengthOfArraylike({ length: 0.25 }), 0);
+    assertStrictEquals(lengthOfArraylike({ length: 1.1 }), 1);
+  });
+
+  it("[[Call]] returns a result greater than or equal to zero", () => {
+    assertStrictEquals(lengthOfArraylike({ length: -0 }), 0);
+    assertStrictEquals(lengthOfArraylike({ length: -1 }), 0);
+    assertStrictEquals(lengthOfArraylike({ length: -Infinity }), 0);
+  });
+
+  it("[[Call]] returns a result less than 2 ** 53", () => {
+    assertStrictEquals(
+      lengthOfArraylike({ length: 9007199254740992 }),
+      9007199254740991,
+    );
+    assertStrictEquals(
+      lengthOfArraylike({ length: Infinity }),
+      9007199254740991,
+    );
+  });
+
+  it("[[Call]] does not require an object argument", () => {
+    assertStrictEquals(lengthOfArraylike("string"), 6);
+    assertStrictEquals(lengthOfArraylike(Symbol()), 0);
+  });
+
+  it("[[Construct]] throws an error", () => {
+    assertThrows(() => new lengthOfArraylike(""));
+  });
+
+  describe(".length", () => {
+    it("[[Get]] returns the correct length", () => {
+      assertStrictEquals(lengthOfArraylike.length, 1);
+    });
+  });
+
+  describe(".name", () => {
+    it("[[Get]] returns the correct name", () => {
+      assertStrictEquals(lengthOfArraylike.name, "lengthOfArraylike");
+    });
+  });
+});
+
 describe("namedEntries", () => {
   it("[[Call]] gets named entries", () => {
     assertEquals(namedEntries({ success: true }), [["success", true]]);
This page took 0.04535 seconds and 4 git commands to generate.