+ createProxyConstructor.name,
+ "createProxyConstructor",
+ );
+ });
+ });
+
+ describe("~", () => {
+ it("[[Call]] throws an error", () => {
+ assertThrows(() => {
+ createProxyConstructor({})();
+ });
+ });
+
+ it("[[Construct]] produces a proxy", () => {
+ const obj = {};
+ const proxyConstructor = createProxyConstructor({
+ get(O, P, Receiver) {
+ if (P === "etaoin") {
+ return Reflect.get(O, P, Receiver) ?? "success";
+ } else {
+ return Reflect.get(O, P, Receiver);
+ }
+ },
+ }, function () {
+ return obj;
+ });
+ const proxy = new proxyConstructor();
+ assertStrictEquals(proxy.etaoin, "success");
+ obj.etaoin = "shrdlu";
+ assertStrictEquals(proxy.etaoin, "shrdlu");
+ });
+
+ it("[[Construct]] receives the expected new.target", () => {
+ const constructor = function Constructor() {
+ return { name: new.target.name };
+ };
+ assertStrictEquals(
+ new (createProxyConstructor({}, constructor))().name,
+ "Constructor",
+ );
+ assertStrictEquals(
+ new (createProxyConstructor(
+ {},
+ constructor,
+ function NewTarget() {},
+ ))().name,
+ "NewTarget",
+ );
+ });
+ });
+
+ describe("~is[[.name]]", () => {
+ it("[[GetOwnProperty]] defines the appropriate method", () => {
+ assertNotStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}),
+ "isProxy",
+ ),
+ undefined,
+ );
+ assertNotStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}, function Base() {}),
+ "isBaseProxy",
+ ),
+ undefined,
+ );
+ assertNotStrictEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}, function Bad() {}, undefined, {
+ name: "⸺",
+ }),
+ "is⸺",
+ ),
+ undefined,
+ );
+ });
+
+ it("[[GetOwnProperty]] has the correct descriptor", () => {
+ const proxyConstructor = createProxyConstructor({});
+ assertEquals(
+ Object.getOwnPropertyDescriptor(
+ proxyConstructor,
+ "isProxy",
+ ),
+ {
+ configurable: true,
+ enumerable: false,
+ value: proxyConstructor.isProxy,
+ writable: true,
+ },
+ );
+ });
+
+ it("[[Call]] returns true for created proxies", () => {
+ const proxyConstructor = createProxyConstructor({});
+ const proxy = new proxyConstructor();
+ assertStrictEquals(
+ proxyConstructor.isProxy(proxy),
+ true,
+ );
+ });
+
+ it("[[Call]] returns false for nonproxies", () => {
+ const constructor = function Base() {};
+ const proxyConstructor = createProxyConstructor({}, constructor);
+ assertStrictEquals(
+ proxyConstructor.isBaseProxy(new constructor()),
+ false,
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ const proxyConstructor = createProxyConstructor({});
+ assertThrows(() => new proxyConstructor.isProxy({}));
+ });
+
+ describe(".length", () => {
+ it("[[Get]] returns the correct length", () => {
+ const proxyConstructor = createProxyConstructor({});
+ assertStrictEquals(proxyConstructor.isProxy.length, 1);
+ });
+ });
+
+ describe(".name", () => {
+ it("[[Get]] returns the correct name", () => {
+ const proxyConstructor = createProxyConstructor({});
+ assertStrictEquals(proxyConstructor.isProxy.name, "isProxy");
+ const otherProxyConstructor = createProxyConstructor(
+ {},
+ function Base() {},
+ );
+ assertStrictEquals(
+ otherProxyConstructor.isBaseProxy.name,
+ "isBaseProxy",
+ );
+ });
+ });
+ });
+
+ describe("~length", () => {
+ it("[[GetOwnProperty]] has the correct descriptor", () => {
+ assertEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}),
+ "length",
+ ),
+ {
+ configurable: true,
+ enumerable: false,
+ value: 1,
+ writable: false,
+ },
+ );
+ });
+ });
+
+ describe("~name", () => {
+ it("[[GetOwnProperty]] has the correct descriptor", () => {
+ assertEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}),
+ "name",
+ ),
+ {
+ configurable: true,
+ enumerable: false,
+ value: "Proxy",
+ writable: false,
+ },
+ );
+ });
+ });
+
+ describe("~prototype", () => {
+ it("[[GetOwnProperty]] has the correct descriptor", () => {
+ assertEquals(
+ Object.getOwnPropertyDescriptor(
+ createProxyConstructor({}),
+ "prototype",
+ ),
+ {
+ configurable: false,
+ enumerable: false,
+ value: undefined,
+ writable: false,
+ },
+ );
+ });
+ });
+
+ describe("~revocable", () => {
+ it("[[Call]] produces a revocable proxy", () => {
+ const obj = {};
+ const proxyConstructor = createProxyConstructor({
+ get(O, P, Receiver) {
+ if (P === "etaoin") {
+ return Reflect.get(O, P, Receiver) ?? "success";
+ } else {
+ return Reflect.get(O, P, Receiver);
+ }
+ },
+ }, function () {
+ return obj;
+ });
+ const { proxy, revoke } = proxyConstructor.revocable();
+ assertStrictEquals(proxy.etaoin, "success");
+ obj.etaoin = "shrdlu";
+ assertStrictEquals(proxy.etaoin, "shrdlu");
+ revoke();
+ assertThrows(() => proxy.etaoin);
+ });
+
+ it("[[Call]] receives the expected new.target", () => {
+ const constructor = function Constructor() {
+ return { name: new.target.name };
+ };
+ assertStrictEquals(
+ createProxyConstructor({}, constructor).revocable().proxy.name,
+ "Constructor",
+ );
+ assertStrictEquals(
+ createProxyConstructor(
+ {},
+ constructor,
+ function NewTarget() {},
+ ).revocable().proxy.name,
+ "NewTarget",
+ );
+ });
+
+ it("[[Construct]] throws an error", () => {
+ assertThrows(() => new (createProxyConstructor({})).revocable());
+ });
+
+ it("[[GetOwnProperty]] has the correct descriptor", () => {
+ const proxyConstructor = createProxyConstructor({});
+ assertEquals(
+ Object.getOwnPropertyDescriptor(proxyConstructor, "revocable"),
+ {
+ configurable: true,
+ enumerable: false,
+ value: proxyConstructor.revocable,
+ writable: true,
+ },