Forráskód Böngészése

LibJS: Convert Proxy tests

Matthew Olsson 5 éve
szülő
commit
449a1cf3a2

+ 32 - 34
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-apply.js

@@ -1,39 +1,37 @@
-load("test-common.js");
-
-try {
-    let p = new Proxy(() => 5, { apply: null });
-    assert(p() === 5);
-    let p = new Proxy(() => 5, { apply: undefined });
-    assert(p() === 5);
-    let p = new Proxy(() => 5, {});
-    assert(p() === 5);
+describe("[[Call]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        let p = new Proxy(() => 5, { apply: null });
+        expect(p()).toBe(5);
+        p = new Proxy(() => 5, { apply: undefined });
+        expect(p()).toBe(5);
+        p = new Proxy(() => 5, {});
+        expect(p()).toBe(5);
+    });
 
-    const f = (a, b) => a + b;
-    const handler = {
-        apply(target, this_, arguments) {
-            assert(target === f);
-            assert(this_ === handler);
-            if (arguments[2])
-                return arguments[0] * arguments[1];
-            return f(...arguments);
-        },
-    };
-    p = new Proxy(f, handler);
+    test("correct arguments supplied to trap", () => {
+        const f = (a, b) => a + b;
+        const handler = {
+            apply(target, this_, arguments) {
+                expect(target).toBe(f);
+                expect(this_).toBe(handler);
+                if (arguments[2])
+                    return arguments[0] * arguments[1];
+                return f(...arguments);
+            },
+        };
+        p = new Proxy(f, handler);
 
-    assert(p(2, 4) === 6);
-    assert(p(2, 4, true) === 8);
+        expect(p(2, 4)).toBe(6);
+        expect(p(2, 4, true)).toBe(8);
+    });
+});
 
-    // Invariants
-    [{}, [], new Proxy({}, {})].forEach(item => {
-        assertThrowsError(() => {
-            new Proxy(item, {})();
-        }, {
-            error: TypeError,
-            message: "[object ProxyObject] is not a function",
+describe("[[Call]] invariants", () => {
+    test("target must have a [[Call]] slot", () => {
+        [{}, [], new Proxy({}, {})].forEach(item => {
+            expect(() => {
+                new Proxy(item, {})();
+            }).toThrowWithMessage(TypeError, "[object ProxyObject] is not a function");
         });
     });
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 58 - 54
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-construct.js

@@ -1,58 +1,62 @@
-load("test-common.js");
-
-try {
-    let p = new Proxy(function() { this.x = 5; }, { construct: null });
-    assert((new p).x === 5);
-    let p = new Proxy(function() { this.x = 5; }, { construct: undefined });
-    assert((new p).x === 5);
-    let p = new Proxy(function() { this.x = 5; }, {});
-    assert((new p).x === 5);
-
-    function f(value) {
-        this.x = value;
-    }
-
-    let p;
-    const handler = {
-        construct(target, arguments, newTarget) {
-            assert(target === f);
-            assert(newTarget === p);
-            if (arguments[1])
-                return Reflect.construct(target, [arguments[0] * 2], newTarget);
-            return Reflect.construct(target, arguments, newTarget);
-        },
-    };
-    p = new Proxy(f, handler);
-
-    assert(new p(15).x === 15);
-    assert(new p(15, true).x === 30);
-
-    let p;
-    function theNewTarget() {};
-    const handler = {
-        construct(target, arguments, newTarget) {
-            assert(target === f);
-            assert(newTarget === theNewTarget);
-            if (arguments[1])
-                return Reflect.construct(target, [arguments[0] * 2], newTarget);
-            return Reflect.construct(target, arguments, newTarget);
-        },
-    };
-    p = new Proxy(f, handler);
+describe("[[Construct]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        let p = new Proxy(function() { this.x = 5; }, { construct: null });
+        expect((new p).x).toBe(5);
+        p = new Proxy(function() { this.x = 5; }, { construct: undefined });
+        expect((new p).x).toBe(5);
+        p = new Proxy(function() { this.x = 5; }, {});
+        expect((new p).x).toBe(5);
+    });
 
-    Reflect.construct(p, [15], theNewTarget);
+    test("trapping 'new'", () => {
+        function f(value) {
+            this.x = value;
+        }
+
+        let p;
+        const handler = {
+            construct(target, arguments, newTarget) {
+                expect(target).toBe(f);
+                expect(newTarget).toBe(p);
+                if (arguments[1])
+                    return Reflect.construct(target, [arguments[0] * 2], newTarget);
+                return Reflect.construct(target, arguments, newTarget);
+            },
+        };
+        p = new Proxy(f, handler);
+
+        expect(new p(15).x).toBe(15);
+        expect(new p(15, true).x).toBe(30);
+    });
 
-    // Invariants
-    [{}, [], new Proxy({}, {})].forEach(item => {
-        assertThrowsError(() => {
-            new (new Proxy(item, {}));
-        }, {
-            error: TypeError,
-            message: "[object ProxyObject] is not a constructor",
+    test("trapping Reflect.construct", () => {
+        function f(value) {
+            this.x = value;
+        }
+
+        let p;
+        function theNewTarget() {};
+        const handler = {
+            construct(target, arguments, newTarget) {
+                expect(target).toBe(f);
+                expect(newTarget).toBe(theNewTarget);
+                if (arguments[1])
+                    return Reflect.construct(target, [arguments[0] * 2], newTarget);
+                return Reflect.construct(target, arguments, newTarget);
+            },
+        };
+        p = new Proxy(f, handler);
+
+        Reflect.construct(p, [15], theNewTarget);
+    });
+});
+
+describe("[[Construct]] invariants", () => {
+    test("target must have a [[Construct]] slot", () => {
+        [{}, [], new Proxy({}, {})].forEach(item => {
+            expect(() => {
+                new (new Proxy(item, {}));
+            }).toThrowWithMessage(TypeError, "[object ProxyObject] is not a constructor");
         });
     });
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 94 - 89
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-defineProperty.js

@@ -1,107 +1,112 @@
-load("test-common.js");
-
-try {
-    let p = new Proxy({}, { defineProperty: null });
-    assert(Object.defineProperty(p, "foo", {}) === p);
-    p = new Proxy({}, { defineProperty: undefined });
-    assert(Object.defineProperty(p, "foo", {}) === p);
-    p = new Proxy({}, {});
-    assert(Object.defineProperty(p, "foo", {}) == p);
-
-    let o = {};
-    p = new Proxy(o, {
-        defineProperty(target, name, descriptor) {
-            assert(target === o);
-            assert(name === "foo");
-            assert(descriptor.configurable === true);
-            assert(descriptor.enumerable === undefined);
-            assert(descriptor.writable === true);
-            assert(descriptor.value === 10);
-            assert(descriptor.get === undefined);
-            assert(descriptor.set === undefined);
-            return true;
-        },
+describe("[[DefineProperty]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        let p = new Proxy({}, { defineProperty: null });
+        expect(Object.defineProperty(p, "foo", {})).toBe(p);
+        p = new Proxy({}, { defineProperty: undefined });
+        expect(Object.defineProperty(p, "foo", {})).toBe(p);
+        p = new Proxy({}, {});
+        expect(Object.defineProperty(p, "foo", {})).toBe(p);
     });
 
-    Object.defineProperty(p, "foo", { configurable: true, writable: true, value: 10 });
+    test("correct arguments passed to trap", () => {
+        let o = {};
+        p = new Proxy(o, {
+            defineProperty(target, name, descriptor) {
+                expect(target).toBe(o);
+                expect(name).toBe("foo");
+                expect(descriptor.configurable).toBe(true);
+                expect(descriptor.enumerable).toBeUndefined();
+                expect(descriptor.writable).toBe(true);
+                expect(descriptor.value).toBe(10);
+                expect(descriptor.get).toBeUndefined();
+                expect(descriptor.set).toBeUndefined();
+                return true;
+            },
+        });
 
-    p = new Proxy(o, {
-        defineProperty(target, name, descriptor) {
-            if (target[name] === undefined)
-                Object.defineProperty(target, name, descriptor);
-            return true;
-        },
+        Object.defineProperty(p, "foo", { configurable: true, writable: true, value: 10 });
     });
 
-    Object.defineProperty(p, "foo", { value: 10, enumerable: true, configurable: false, writable: true });
-    let d = Object.getOwnPropertyDescriptor(p, "foo");
-    assert(d.enumerable === true);
-    assert(d.configurable === false);
-    assert(d.writable === true);
-    assert(d.value === 10);
-    assert(d.get === undefined);
-    assert(d.set === undefined);
+    test("optionally ignoring the define call", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            defineProperty(target, name, descriptor) {
+                if (target[name] === undefined)
+                    Object.defineProperty(target, name, descriptor);
+                return true;
+            },
+        });
 
-    Object.defineProperty(p, "foo", { value: 20, enumerable: true, configurable: false, writable: true });
-    d = Object.getOwnPropertyDescriptor(p, "foo");
-    assert(d.enumerable === true);
-    assert(d.configurable === false);
-    assert(d.writable === true);
-    assert(d.value === 10);
-    assert(d.get === undefined);
-    assert(d.set === undefined);
+        Object.defineProperty(p, "foo", { value: 10, enumerable: true, configurable: false, writable: true });
+        let d = Object.getOwnPropertyDescriptor(p, "foo");
+        expect(d.enumerable).toBe(true);
+        expect(d.configurable).toBe(false);
+        expect(d.writable).toBe(true);
+        expect(d.value).toBe(10);
+        expect(d.get).toBeUndefined();
+        expect(d.set).toBeUndefined();
 
+        Object.defineProperty(p, "foo", { value: 20, enumerable: true, configurable: false, writable: true });
+        d = Object.getOwnPropertyDescriptor(p, "foo");
+        expect(d.enumerable).toBe(true);
+        expect(d.configurable).toBe(false);
+        expect(d.writable).toBe(true);
+        expect(d.value).toBe(10);
+        expect(d.get).toBeUndefined();
+        expect(d.set).toBeUndefined();
+    });
+});
 
-    // Invariants
+describe("[[DefineProperty]] invariants", () => {
+    test("trap can't return false", () => {
+        let p = new Proxy({}, {
+            defineProperty() { return false; }
+        });
 
-    p = new Proxy({}, {
-        defineProperty() { return false; }
+        expect(() => {
+            Object.defineProperty(p, "foo", {});
+        }).toThrowWithMessage(TypeError, "Object's [[DefineProperty]] method returned false");
     });
 
-    assertThrowsError(() => {
-        Object.defineProperty(p, "foo", {});
-    }, {
-        error: TypeError,
-        message: "Object's [[DefineProperty]] method returned false",
-    });
+    test("trap cannot return true for a non-extensible target if the property does not exist", () => {
+        let o = {};
+        Object.preventExtensions(o);
+        let p = new Proxy(o, {
+            defineProperty() {
+                return true;
+            }
+        });
 
-    o = {};
-    Object.preventExtensions(o);
-    p = new Proxy(o, {
-        defineProperty() {
-            return true;
-        }
-    });
-    assertThrowsError(() => {
-        Object.defineProperty(p, "foo", {});
-    }, {
-        error: TypeError,
-        message: "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",
+        expect(() => {
+            Object.defineProperty(p, "foo", {});
+        }).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");
     });
 
-    o = {};
-    Object.defineProperty(o, "foo", { value: 10, configurable: true });
-    p = new Proxy(o, {
-        defineProperty() {
-            return true;
-        },
-    });
+    test("trap cannot return true for a non-configurable property if it doesn't already exist on the target", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 10, configurable: true });
+        let p = new Proxy(o, {
+            defineProperty() {
+                return true;
+            },
+        });
 
-    assertThrowsError(() => {
-        Object.defineProperty(p, "bar", { value: 6, configurable: false });
-    }, {
-        error: TypeError,
-        message: "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",
+        expect(() => {
+            Object.defineProperty(p, "bar", { value: 6, configurable: false });
+        }).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");
     });
 
-    assertThrowsError(() => {
-        Object.defineProperty(p, "foo", { value: 6, configurable: false });
-    }, {
-        error: TypeError,
-        message: "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",
-    });
+    test("trap cannot return true for a non-configurable property if it already exists as a configurable property", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 10, configurable: true });
+        let p = new Proxy(o, {
+            defineProperty() {
+                return true;
+            },
+        });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+        expect(() => {
+            Object.defineProperty(p, "foo", { value: 6, configurable: false });
+        }).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");
+    })
+});

+ 45 - 45
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-deleteProperty.js

@@ -1,56 +1,56 @@
-load("test-common.js");
-
-try {
-    assert(delete (new Proxy({}, { deleteProperty: undefined })).foo === true);
-    assert(delete (new Proxy({}, { deleteProperty: null })).foo === true);
-    assert(delete (new Proxy({}, {})).foo === true);
-
-    let o = {};
-    let p = new Proxy(o, {
-        deleteProperty(target, property) {
-            assert(target === o);
-            assert(property === "foo");
-            return true;
-        }
+describe("[[Delete]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect(delete (new Proxy({}, { deleteProperty: undefined })).foo).toBe(true);
+        expect(delete (new Proxy({}, { deleteProperty: null })).foo).toBe(true);
+        expect(delete (new Proxy({}, {})).foo).toBe(true);
     });
 
-    delete p.foo;
-
-    o = { foo: 1, bar: 2 };
-    p = new Proxy(o, {
-        deleteProperty(target, property) {
-            if (property === "foo") {
-                delete target[property];
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            deleteProperty(target, property) {
+                expect(target).toBe(o);
+                expect(property).toBe("foo");
                 return true;
             }
-            return false;
-        }
-    });
+        });
 
-    assert(delete p.foo === true);
-    assert(delete p.bar === false);
+        delete p.foo;
+    });
 
-    assert(o.foo === undefined);
-    assert(o.bar === 2);
+    test("conditional deletion", () => {
+        o = { foo: 1, bar: 2 };
+        p = new Proxy(o, {
+            deleteProperty(target, property) {
+                if (property === "foo") {
+                    delete target[property];
+                    return true;
+                }
+                return false;
+            }
+        });
 
-    // Invariants
+        expect(delete p.foo).toBe(true);
+        expect(delete p.bar).toBe(false);
 
-    o = {};
-    Object.defineProperty(o, "foo", { configurable: false });
-    p = new Proxy(o, {
-        deleteProperty() {
-            return true;
-        },
+        expect(o.foo).toBe(undefined);
+        expect(o.bar).toBe(2);
     });
+});
 
-    assertThrowsError(() => {
-        delete p.foo;
-    }, {
-        error: TypeError,
-        message: "Proxy handler's deleteProperty trap violates invariant: cannot report a non-configurable own property of the target as deleted",
-    });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+describe("[[Delete]] invariants", () => {
+    test("cannot report a non-configurable own property as deleted", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { configurable: false });
+        let p = new Proxy(o, {
+            deleteProperty() {
+                return true;
+            },
+        });
+
+        expect(() => {
+            delete p.foo;
+        }).toThrowWithMessage(TypeError, "Proxy handler's deleteProperty trap violates invariant: cannot report a non-configurable own property of the target as deleted");
+    });
+});

+ 63 - 58
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-get.js

@@ -1,71 +1,76 @@
-load("test-common.js");
+describe("[[Get]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect((new Proxy({}, { get: undefined })).foo).toBeUndefined();
+        expect((new Proxy({}, { get: null })).foo).toBeUndefined();
+        expect((new Proxy({}, {})).foo).toBeUndefined();
+    });
 
-try {
-    assert((new Proxy({}, { get: undefined })).foo === undefined);
-    assert((new Proxy({}, { get: null })).foo === undefined);
-    assert((new Proxy({}, {})).foo === undefined);
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            get(target, property, receiver) {
+                expect(target).toBe(o);
+                expect(property).toBe("foo");
+                expect(receiver).toBe(p);
+            },
+        });
 
-    let o = {};
-    let p = new Proxy(o, {
-        get(target, property, receiver) {
-            assert(target === o);
-            assert(property === "foo");
-            assert(receiver === p);
-        },
+        p.foo;
     });
 
-    p.foo;
-
-    o = { foo: 1 };
-    p = new Proxy(o, {
-        get(target, property, receiver) {
-            if (property === "bar") {
-                return 2;
-            } else if (property === "baz") {
-                return receiver.qux;
-            } else if (property === "qux") {
-                return 3;
+    test("conditional return", () => {
+        let o = { foo: 1 };
+        let p = new Proxy(o, {
+            get(target, property, receiver) {
+                if (property === "bar") {
+                    return 2;
+                } else if (property === "baz") {
+                    return receiver.qux;
+                } else if (property === "qux") {
+                    return 3;
+                }
+                return target[property];
             }
-            return target[property];
-        }
-    });
+        });
 
-    assert(p.foo === 1);
-    assert(p.bar === 2);
-    assert(p.baz === 3);
-    assert(p.qux === 3);
-    assert(p.test === undefined);
+        expect(p.foo).toBe(1);
+        expect(p.bar).toBe(2);
+        expect(p.baz).toBe(3);
+        expect(p.qux).toBe(3);
+        expect(p.test).toBeUndefined();
+    });
+});
 
-    // Invariants
+describe("[[Get]] invariants", () => {
+    test("returned value must match the target property value if the property is non-configurable and non-writable", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 5, configurable: false, writable: true });
+        Object.defineProperty(o, "bar", { value: 10, configurable: false, writable: false });
 
-    o = {};
-    Object.defineProperty(o, "foo", { value: 5, configurable: false, writable: true });
-    Object.defineProperty(o, "bar", { value: 10, configurable: false, writable: false });
+        let p = new Proxy(o, {
+            get() {
+                return 8;
+            },
+        });
 
-    p = new Proxy(o, {
-        get() {
-            return 8;
-        },
+        expect(p.foo).toBe(8);
+        expect(() => {
+            p.bar;
+        }).toThrowWithMessage(TypeError, "Proxy handler's get trap violates invariant: the returned value must match the value on the target if the property exists on the target as a non-writable, non-configurable own data property");
     });
 
-    assert(p.foo === 8);
+    test("returned value must be undefined if the property is a non-configurable accessor with no getter", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { configurable: false, set(_) {} });
 
-    assertThrowsError(() => {
-        p.bar;
-    }, {
-        error: TypeError,
-        message: "Proxy handler's get trap violates invariant: the returned value must match the value on the target if the property exists on the target as a non-writable, non-configurable own data property",
-    });
-
-    Object.defineProperty(o, "baz", { configurable: false, set(_) {} });
-    assertThrowsError(() => {
-        p.baz;
-    }, {
-        error: TypeError,
-        message: "Proxy handler's get trap violates invariant: the returned value must be undefined if the property exists on the target as a non-configurable accessor property with an undefined get attribute",
-    });
+        let p = new Proxy(o, {
+            get() {
+                return 8;
+            },
+        });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+        expect(() => {
+            p.foo;
+        }).toThrowWithMessage(TypeError, "Proxy handler's get trap violates invariant: the returned value must be undefined if the property exists on the target as a non-configurable accessor property with an undefined get attribute");
+    })
+});

+ 123 - 137
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-getOwnPropertyDescriptor.js

@@ -1,159 +1,145 @@
-load("test-common.js");
-
-try {
-    assert(Object.getOwnPropertyDescriptor(new Proxy({}, { getOwnPropertyDescriptor: null }), "a") === undefined);
-    assert(Object.getOwnPropertyDescriptor(new Proxy({}, { getOwnPropertyDescriptor: undefined }), "a") === undefined);
-    assert(Object.getOwnPropertyDescriptor(new Proxy({}, {}), "a") === undefined);
-
-    let o = {};
-    let p = new Proxy(o, {
-        getOwnPropertyDescriptor(target, property) {
-            assert(target === o);
-            assert(property === "foo");
-        }
+describe("[Call][GetOwnProperty]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect(Object.getOwnPropertyDescriptor(new Proxy({}, { getOwnPropertyDescriptor: null }), "a")).toBeUndefined();
+        expect(Object.getOwnPropertyDescriptor(new Proxy({}, { getOwnPropertyDescriptor: undefined }), "a")).toBeUndefined();
+        expect(Object.getOwnPropertyDescriptor(new Proxy({}, {}), "a")).toBeUndefined();
     });
 
-    Object.getOwnPropertyDescriptor(p, "foo");
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            getOwnPropertyDescriptor(target, property) {
+                expect(target).toBe(o);
+                expect(property).toBe("foo");
+            }
+        });
 
-    o = { foo: "bar" };
-    Object.defineProperty(o, "baz", { value: "qux", enumerable: false, configurable: true, writable: false });
-    p = new Proxy(o, {
-        getOwnPropertyDescriptor(target, property) {
-            if (property === "baz")
-                return Object.getOwnPropertyDescriptor(target, "baz");
-             return { value: target[property], enumerable: false, configurable: true, writable: true };
-        }
-    });
-
-    let d = Object.getOwnPropertyDescriptor(p, "baz");
-    assert(d.configurable === true);
-    assert(d.enumerable === false);
-    assert(d.writable === false);
-    assert(d.value === "qux");
-    assert(d.get === undefined);
-    assert(d.set === undefined);
-
-    d = Object.getOwnPropertyDescriptor(p, "foo");
-    assert(d.configurable === true);
-    assert(d.enumerable === false);
-    assert(d.writable === true);
-    assert(d.value === "bar");
-    assert(d.get === undefined);
-    assert(d.set === undefined);
-
-    // Invariants
-
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy({}, {
-            getOwnPropertyDescriptor: 1
-        }));
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap wasn't undefined, null, or callable",
+        Object.getOwnPropertyDescriptor(p, "foo");
     });
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy({}, {
-            getOwnPropertyDescriptor() {
-                return 1;
-            },
-        }));
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: must return an object or undefined",
+    test("conditional returned descriptor", () => {
+        let o = { foo: "bar" };
+        Object.defineProperty(o, "baz", { value: "qux", enumerable: false, configurable: true, writable: false });
+
+        let p = new Proxy(o, {
+            getOwnPropertyDescriptor(target, property) {
+                if (property === "baz")
+                    return Object.getOwnPropertyDescriptor(target, "baz");
+                 return { value: target[property], enumerable: false, configurable: true, writable: true };
+            }
+        });
+
+        let d = Object.getOwnPropertyDescriptor(p, "baz");
+        expect(d.configurable).toBe(true);
+        expect(d.enumerable).toBe(false);
+        expect(d.writable).toBe(false);
+        expect(d.value).toBe("qux");
+        expect(d.get).toBeUndefined();
+        expect(d.set).toBeUndefined();
+
+        d = Object.getOwnPropertyDescriptor(p, "foo");
+        expect(d.configurable).toBe(true);
+        expect(d.enumerable).toBe(false);
+        expect(d.writable).toBe(true);
+        expect(d.value).toBe("bar");
+        expect(d.get).toBeUndefined();
+        expect(d.set).toBeUndefined();
     });
-
-    o = {};
-    Object.defineProperty(o, "foo", { value: 10, configurable: false });
-    p = new Proxy(o, {
-        getOwnPropertyDescriptor() {
-            return undefined;
-        },
+});
+
+describe("[[GetOwnProperty]] invariants", () => {
+    test("must return an object or undefined", () => {
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy({}, {
+                getOwnPropertyDescriptor() {
+                    return 1;
+                },
+            }));
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: must return an object or undefined");
     });
 
-    assert(Object.getOwnPropertyDescriptor(p, "bar") === undefined);
+    test("cannot return undefined for a non-configurable property", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 10, configurable: false });
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(p, "foo");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot return undefined for a property on the target which is a non-configurable property",
-    });
+        let p = new Proxy(o, {
+            getOwnPropertyDescriptor() {
+                return undefined;
+            },
+        });
 
-    Object.defineProperty(o, "baz", { value: 20, configurable: true, writable: true, enumerable: true });
-    Object.preventExtensions(o);
+        expect(Object.getOwnPropertyDescriptor(p, "bar")).toBeUndefined();
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(p, "baz");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report a property as being undefined if it exists as an own property of the target and the target is non-extensible",
+        expect(() => {
+            Object.getOwnPropertyDescriptor(p, "foo");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot return undefined for a property on the target which is a non-configurable property");
     });
 
-    o = {};
-    Object.defineProperty(o, "v1", { value: 10, configurable: false });
-    Object.defineProperty(o, "v2", { value: 10, configurable: false, enumerable: true });
-    Object.defineProperty(o, "v3", { configurable: false, get() { return 1; } });
-    Object.defineProperty(o, "v4", { value: 10, configurable: false, writable: false, enumerable: true });
-
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy(o, {
-            getOwnPropertyDescriptor() {
-                return { configurable: true };
-            },
-        }), "v1");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target",
-    });
+    test("cannot return undefined for an existing property if the target is non-extensible", () => {
+        let o = {};
+        Object.defineProperty(o, "baz", { value: 20, configurable: true, writable: true, enumerable: true });
+        Object.preventExtensions(o);
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy(o, {
+        let p = new Proxy(o, {
             getOwnPropertyDescriptor() {
-                return { enumerable: false };
+                return undefined;
             },
-        }), "v2");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target",
-    });
+        });
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy(o, {
-            getOwnPropertyDescriptor() {
-                return { value: 10 };
-            },
-        }), "v3");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target",
+        expect(() => {
+            Object.getOwnPropertyDescriptor(p, "baz");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report a property as being undefined if it exists as an own property of the target and the target is non-extensible");
     });
 
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy(o, {
-            getOwnPropertyDescriptor() {
-                return { value: 10, writable: true };
-            },
-        }), "v4");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target",
+    test("invalid property descriptors", () => {
+        let o = {};
+        Object.defineProperty(o, "v1", { value: 10, configurable: false });
+        Object.defineProperty(o, "v2", { value: 10, configurable: false, enumerable: true });
+        Object.defineProperty(o, "v3", { configurable: false, get() { return 1; } });
+        Object.defineProperty(o, "v4", { value: 10, configurable: false, writable: false, enumerable: true });
+
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy(o, {
+                getOwnPropertyDescriptor() {
+                    return { configurable: true };
+                },
+            }), "v1");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target");
+
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy(o, {
+                getOwnPropertyDescriptor() {
+                    return { enumerable: false };
+                },
+            }), "v2");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target");
+
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy(o, {
+                getOwnPropertyDescriptor() {
+                    return { value: 10 };
+                },
+            }), "v3");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target");
+
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy(o, {
+                getOwnPropertyDescriptor() {
+                    return { value: 10, writable: true };
+                },
+            }), "v4");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: invalid property descriptor for existing property on the target");
     });
 
-    o = {};
-    Object.defineProperty(o, "v", { configurable: true });
-    assertThrowsError(() => {
-        Object.getOwnPropertyDescriptor(new Proxy(o, {
-            getOwnPropertyDescriptor() {
-                return { configurable: false };
-            },
-        }), "v");
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report target's property as non-configurable if the property does not exist, or if it is configurable",
+    test("cannot report a property as non-configurable if it does not exist or is non-configurable", () => {
+        let o = {};
+        Object.defineProperty(o, "v", { configurable: true });
+        expect(() => {
+            Object.getOwnPropertyDescriptor(new Proxy(o, {
+                getOwnPropertyDescriptor() {
+                    return { configurable: false };
+                },
+            }), "v");
+        }).toThrowWithMessage(TypeError, "Proxy handler's getOwnPropertyDescriptor trap violates invariant: cannot report target's property as non-configurable if the property does not exist, or if it is configurable");
     });
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 67 - 73
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-getPrototypeOf.js

@@ -1,87 +1,81 @@
-load("test-common.js");
-
-try {
-    const child = {};
-    const childProto = { foo: "bar" };
-
-    Object.setPrototypeOf(child, childProto);
-    assert(child.foo === "bar");
-
-    Object.getPrototypeOf(new Proxy(child, { getPrototypeOf: null }));
-    Object.getPrototypeOf(new Proxy(child, { getPrototypeOf: undefined }));
-
-    let o = {};
-    let p = new Proxy(o, {
-        getPrototypeOf(target) {
-            assert(target === o);
-            return null;
-        }
-    });
-
-    Object.getPrototypeOf(p);
-
-    p = new Proxy(o, {
-        getPrototypeOf(target) {
-            if (target.foo)
-                return { bar: 1 };
-            return { bar: 2 };
-        },
+describe("[[GetPrototypeOf]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        let proto = {};
+        let o = {};
+        Object.setPrototypeOf(o, proto);
+
+        let p = new Proxy(o, { prototype: null });
+        expect(Object.getPrototypeOf(p)).toBe(proto);
+        p = new Proxy(o, { apply: undefined });
+        expect(Object.getPrototypeOf(p)).toBe(proto);
+        p = new Proxy(o, {});
+        expect(Object.getPrototypeOf(p)).toBe(proto);
     });
 
-    assert(Object.getPrototypeOf(p).bar === 2);
-    o.foo = 20
-    assert(Object.getPrototypeOf(p).bar === 1);
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            getPrototypeOf(target) {
+                expect(target).toBe(o);
+                return null;
+            }
+        });
 
-    // Invariants
-
-    assertThrowsError(() => {
-        Object.getPrototypeOf(new Proxy(child, { getPrototypeOf: 1 }));
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getPrototypeOf trap wasn't undefined, null, or callable",
+        Object.getPrototypeOf(p);
     });
 
-    assertThrowsError(() => {
-        Object.getPrototypeOf(new Proxy(child, { getPrototypeOf() { return 1; } }));
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getPrototypeOf trap violates invariant: must return an object or null",
+    test("conditional return", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            getPrototypeOf(target) {
+                if (target.foo)
+                    return { bar: 1 };
+                return { bar: 2 };
+            },
+        });
+
+        expect(Object.getPrototypeOf(p).bar).toBe(2);
+        o.foo = 20
+        expect(Object.getPrototypeOf(p).bar).toBe(1);
     });
 
-    p = new Proxy(child, {
-        getPrototypeOf(target) {
-            assert(target === child);
-            return { baz: "qux" };
-        },
-    });
+    test("non-extensible target", () => {
+        let o = {};
+        let proto = { foo: "bar" };
+        Object.setPrototypeOf(o, proto);
+        Object.preventExtensions(o);
 
-    assert(Object.getPrototypeOf(p).baz === "qux");
+        p = new Proxy(o, {
+            getPrototypeOf() {
+                return proto;
+            }
+        });
 
-    Object.preventExtensions(child);
-    p = new Proxy(child, {
-        getPrototypeOf(target) {
-            assert(target === child);
-            return childProto;
-        }
+        expect(Object.getPrototypeOf(p).foo).toBe("bar");
     });
+});
 
-    assert(Object.getPrototypeOf(p).foo === "bar");
-
-    p = new Proxy(child, {
-        getPrototypeOf(target) {
-            assert(target === child);
-            return { baz: "qux" };
-        }
+describe("[[GetPrototypeOf]] invariants", () => {
+    test("must return an object or null", () => {
+        expect(() => {
+            Object.getPrototypeOf(new Proxy({}, { getPrototypeOf() { return 1; } }));
+        }).toThrowWithMessage(TypeError, "Proxy handler's getPrototypeOf trap violates invariant: must return an object or null");
     });
 
-    assertThrowsError(() => {
-        Object.getPrototypeOf(p);
-    }, {
-        error: TypeError,
-        message: "Proxy handler's getPrototypeOf trap violates invariant: cannot return a different prototype object for a non-extensible target"
+    test("different return object for non-extensible target", () => {
+        let o = {};
+        let proto = {};
+        Object.setPrototypeOf(o, proto);
+        Object.preventExtensions(o);
+
+        let p = new Proxy(o, {
+            getPrototypeOf(target) {
+                return { baz: "qux" };
+            }
+        });
+
+        expect(() => {
+            Object.getPrototypeOf(p);
+        }).toThrowWithMessage(TypeError, "Proxy handler's getPrototypeOf trap violates invariant: cannot return a different prototype object for a non-extensible target");
     });
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 58 - 50
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-has.js

@@ -1,62 +1,70 @@
-load("test-common.js");
-
-try {
-    assert("foo" in new Proxy({}, { has: null }) === false);
-    assert("foo" in new Proxy({}, { has: undefined}) === false);
-    assert("foo" in new Proxy({}, {}) === false);
-
-    let o = {};
-    let p = new Proxy(o, {
-        has(target, prop) {
-            assert(target === o);
-            assert(prop === "foo");
-            return true;
-        }
+describe("[[Has]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect("foo" in new Proxy({}, { has: null })).toBe(false);
+        expect("foo" in new Proxy({}, { has: undefined})).toBe(false);
+        expect("foo" in new Proxy({}, {})).toBe(false);
     });
 
-    "foo" in p;
-
-    p = new Proxy(o, {
-        has(target, prop) {
-            if (target.checkedFoo)
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            has(target, prop) {
+                expect(target).toBe(o);
+                expect(prop).toBe("foo");
                 return true;
-            if (prop === "foo")
-                target.checkedFoo = true;
-            return false;
-        }
-    });
+            }
+        });
 
-    assert("foo" in p === false);
-    assert("foo" in p === true);
+        "foo" in p;
+    });
 
-    // Invariants
+    test("conditional return", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            has(target, prop) {
+                if (target.checkedFoo)
+                    return true;
+                if (prop === "foo")
+                    target.checkedFoo = true;
+                return false;
+            }
+        });
 
-    o = {};
-    Object.defineProperty(o, "foo", { configurable: false });
-    Object.defineProperty(o, "bar", { value: 10, configurable: true });
-    p = new Proxy(o, {
-        has() {
-            return false;
-        }
+        expect("foo" in p).toBe(false);
+        expect("foo" in p).toBe(true);
     });
+});
 
-    assertThrowsError(() => {
-        "foo" in p;
-    }, {
-        error: TypeError,
-        message: "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target as a non-configurable property",
-    });
+describe("[[Has]] invariants", () => {
+    test("cannot return false if the property exists and is non-configurable", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { configurable: false });
 
-    Object.preventExtensions(o);
+        p = new Proxy(o, {
+            has() {
+                return false;
+            }
+        });
 
-    assertThrowsError(() => {
-        "bar" in p;
-    }, {
-        error: TypeError,
-        message: "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target and the target is non-extensible",
+        expect(() => {
+            "foo" in p;
+        }).toThrowWithMessage(TypeError, "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target as a non-configurable property");
     });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+    test("cannot return false if the property exists and the target is non-extensible", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 10, configurable: true });
+
+        let p = new Proxy(o, {
+            has() {
+                return false;
+            }
+        });
+
+        Object.preventExtensions(o);
+
+        expect(() => {
+            "foo" in p;
+        }).toThrowWithMessage(TypeError, "Proxy handler's has trap violates invariant: a property cannot be reported as non-existent if it exists on the target and the target is non-extensible");
+    });
+});

+ 31 - 44
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-isExtensible.js

@@ -1,49 +1,36 @@
-load("test-common.js");
-
-try {
-    assert(Object.isExtensible(new Proxy({}, { isExtensible: null })) === true);
-    assert(Object.isExtensible(new Proxy({}, { isExtensible: undefined })) === true);
-    assert(Object.isExtensible(new Proxy({}, {})) === true);
-
-    let o = {};
-    let p = new Proxy(o, {
-        isExtensible(target) {
-            assert(target === o);
-            return true;
-        }
-    });
-
-    Object.isExtensible(p);
-
-    // Invariants
-
-    o = {};
-    p = new Proxy(o, {
-        isExtensible(proxyTarget) {
-            assert(proxyTarget === o);
-            return true;
-        },
+describe("[[IsExtensible]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect(Object.isExtensible(new Proxy({}, { isExtensible: null }))).toBe(true);
+        expect(Object.isExtensible(new Proxy({}, { isExtensible: undefined }))).toBe(true);
+        expect(Object.isExtensible(new Proxy({}, {}))).toBe(true);
     });
 
-    assert(Object.isExtensible(p) === true);
-    Object.preventExtensions(o);
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            isExtensible(target) {
+                expect(target).toBe(o);
+                return true;
+            }
+        });
 
-    assertThrowsError(() => {
-        Object.isExtensible(p);
-    }, {
-        error: TypeError,
-        message: "Proxy handler's isExtensible trap violates invariant: return value must match the target's extensibility",
+        expect(Object.isExtensible(p)).toBe(true);
     });
-
-    p = new Proxy(o, {
-        isExtensible(proxyTarget) {
-            assert(proxyTarget === o);
-            return false;
-        },
+});
+
+describe("[[Call]] invariants", () => {
+    test("return value must match the target's extensibility", () => {
+        let o = {};
+        Object.preventExtensions(o);
+
+        let p = new Proxy(o, {
+            isExtensible() {
+                return true;
+            },
+        });
+
+        expect(() => {
+            Object.isExtensible(p);
+        }).toThrowWithMessage(TypeError, "Proxy handler's isExtensible trap violates invariant: return value must match the target's extensibility");
     });
-    assert(Object.isExtensible(p) === false);
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 45 - 47
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-preventExtensions.js

@@ -1,55 +1,53 @@
-load("test-common.js");
-
-try {
-    let p = new Proxy({}, { preventExtensions: null });
-    assert(Object.preventExtensions(p) === p);
-    p = new Proxy({}, { preventExtensions: undefined });
-    assert(Object.preventExtensions(p) === p);
-    p = new Proxy({}, {});
-    assert(Object.preventExtensions(p) == p);
-
-    let o = {};
-    p = new Proxy(o, {
-        preventExtensions(target) {
-            assert(target === o);
-            return true;
-        }
+describe("[[PreventExtension]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        let p = new Proxy({}, { preventExtensions: null });
+        expect(Object.preventExtensions(p)).toBe(p);
+        p = new Proxy({}, { preventExtensions: undefined });
+        expect(Object.preventExtensions(p)).toBe(p);
+        p = new Proxy({}, {});
+        expect(Object.preventExtensions(p)).toBe(p);
     });
 
-    Object.preventExtensions(o);
-    Object.preventExtensions(p);
-
-    // Invariants
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        p = new Proxy(o, {
+            preventExtensions(target) {
+                expect(target).toBe(o);
+                return true;
+            }
+        });
 
-    p = new Proxy({}, {
-        preventExtensions() {
-            return false;
-        },
-    });
-    assertThrowsError(() => {
+        Object.preventExtensions(o);
         Object.preventExtensions(p);
-    }, {
-        error: TypeError,
-        message: "Object's [[PreventExtensions]] method returned false",
     });
-
-    o = {};
-    p = new Proxy(o, {
-        preventExtensions() {
-            return true;
-        },
-    });
-    assertThrowsError(() => {
-        Object.preventExtensions(p);
-    }, {
-        error: TypeError,
-        message: "Proxy handler's preventExtensions trap violates invariant: cannot return true if the target object is extensible"
+});
+
+describe("[[PreventExtensions]] invariants", () => {
+    test("cannot return false", () => {
+        let p = new Proxy({}, {
+            preventExtensions() {
+                return false;
+            },
+        });
+
+        expect(() => {
+            Object.preventExtensions(p);
+        }).toThrowWithMessage(TypeError, "Object's [[PreventExtensions]] method returned false");
     });
 
-    Object.preventExtensions(o);
-    assert(Object.preventExtensions(p) === p);
+    test("cannot return true if the target is extensible", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            preventExtensions() {
+                return true;
+            },
+        });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+        expect(() => {
+            Object.preventExtensions(p);
+        }).toThrowWithMessage(TypeError, "Proxy handler's preventExtensions trap violates invariant: cannot return true if the target object is extensible");
+
+        Object.preventExtensions(o);
+        expect(Object.preventExtensions(p)).toBe(p);
+    });
+});

+ 60 - 53
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-set.js

@@ -1,66 +1,73 @@
-load("test-common.js");
+describe("[[Set]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        expect((new Proxy({}, { set: undefined }).foo = 1)).toBe(1);
+        expect((new Proxy({}, { set: null }).foo = 1)).toBe(1);
+        expect((new Proxy({}, {}).foo = 1)).toBe(1);
+    });
 
-try {
-    assert((new Proxy({}, { set: undefined }).foo = 1) === 1);
-    assert((new Proxy({}, { set: null }).foo = 1) === 1);
-    assert((new Proxy({}, {}).foo = 1) === 1);
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let p = new Proxy(o, {
+            set(target, prop, value, receiver) {
+                expect(target).toBe(o);
+                expect(prop).toBe("foo");
+                expect(value).toBe(10);
+                expect(receiver).toBe(p);
+                return true;
+            },
+        });
 
-    let o = {};
-    let p = new Proxy(o, {
-        set(target, prop, value, receiver) {
-            assert(target === o);
-            assert(prop === "foo");
-            assert(value === 10);
-            assert(receiver === p);
-            return true;
-        },
+        p.foo = 10;
     });
 
-    p.foo = 10;
+    test("conditional return value", () => {
+        let p = new Proxy({}, {
+            set(target, prop, value) {
+                if (target[prop] === value) {
+                    target[prop] *= 2;
+                } else {
+                    target[prop] = value;
+                }
+            },
+        });
 
-    p = new Proxy(o, {
-        set(target, prop, value, receiver) {
-            if (target[prop] === value) {
-                target[prop] *= 2;
-            } else {
-                target[prop] = value;
-            }
-        },
+        p.foo = 10;
+        expect(p.foo).toBe(10);
+        p.foo = 10;
+        expect(p.foo).toBe(20);
+        p.foo = 10;
+        expect(p.foo).toBe(10);
     });
+});
 
-    p.foo = 10;
-    assert(p.foo === 10);
-    p.foo = 10;
-    assert(p.foo === 20);
-    p.foo = 10;
-    assert(p.foo === 10);
+describe("[[Set]] invariants", () => {
+    test("cannot return true for a non-configurable, non-writable property", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { value: 10 });
 
-    // Invariants
+        let p = new Proxy(o, {
+            set() {
+                return true;
+            },
+        });
 
-    o = {};
-    Object.defineProperty(o, "foo", { value: 10 });
-    p = new Proxy(o, {
-        set() {
-            return true;
-        },
+        expect(() => {
+            p.foo = 12;
+        }).toThrowWithMessage(TypeError, "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");
     });
 
-    assertThrowsError(() => {
-        p.foo = 12;
-    }, {
-        error: TypeError,
-        message: "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",
-    });
+    test("cannot return true for a non-configurable accessor property with no setter", () => {
+        let o = {};
+        Object.defineProperty(o, "foo", { get() {} });
 
-    Object.defineProperty(o, "bar", { get() {} });
-    assertThrowsError(() => {
-        p.bar = 12;
-    }, {
-        error: TypeError,
-        message: "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",
-    });
+        let p = new Proxy(o, {
+            set() {
+                return true;
+            },
+        });
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+        expect(() => {
+            p.foo = 12;
+        }).toThrowWithMessage(TypeError, "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");
+    });
+});

+ 79 - 80
Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-setPrototypeOf.js

@@ -1,95 +1,94 @@
-load("test-common.js");
-
-try {
-    const child = {};
-    const childProto = { foo: "bar" };
+describe("[[SetPrototypeOf]] trap normal behavior", () => {
+    test("forwarding when not defined in handler", () => {
+        const o = {};
+        const proto = { foo: "bar" };
+        Object.setPrototypeOf(o, proto);
+
+        let p = new Proxy(o, { setPrototypeOf: null });
+        expect(Object.setPrototypeOf(p, proto)).toBe(p);
+        let p = new Proxy(o, { setPrototypeOf: undefined });
+        expect(Object.setPrototypeOf(p, proto)).toBe(p);
+        let p = new Proxy(o, {});
+        expect(Object.setPrototypeOf(p, proto)).toBe(p);
+    });
 
-    Object.setPrototypeOf(child, childProto);
-    assert(child.foo === "bar");
+    test("correct arguments supplied to trap", () => {
+        let o = {};
+        let theNewProto = { foo: "bar" };
 
-    Object.setPrototypeOf(new Proxy(child, { setPrototypeOf: null }), childProto);
-    Object.setPrototypeOf(new Proxy(child, { setPrototypeOf: undefined }), childProto);
+        let p = new Proxy(o, {
+            setPrototypeOf(target, newProto) {
+                expect(target).toBe(o);
+                expect(newProto).toBe(theNewProto);
+                return true;
+            }
+        });
 
-    let o = {};
-    let theNewProto = { foo: "bar" };
-    let p = new Proxy(o, {
-        setPrototypeOf(target, newProto) {
-            assert(target === o);
-            assert(newProto === theNewProto);
-            return true;
-        }
+        Object.setPrototypeOf(p, theNewProto);
     });
 
-    Object.setPrototypeOf(p, theNewProto);
-
-    p = new Proxy(o, {
-        setPrototypeOf(target, newProto) {
-            if (target.shouldSet)
-                Object.setPrototypeOf(target, newProto);
-            return true;
-        },
+    test("conditional setting", () => {
+        let o = {};
+
+        let p = new Proxy(o, {
+            setPrototypeOf(target, newProto) {
+                if (target.shouldSet)
+                    Object.setPrototypeOf(target, newProto);
+                return true;
+            },
+        });
+
+        Object.setPrototypeOf(p, { foo: 1 });
+        expect(Object.getPrototypeOf(p).foo).toBeUndefined();
+        p.shouldSet = true;
+        expect(o.shouldSet).toBe(true);
+        Object.setPrototypeOf(p, { foo: 1 });
+        expect(Object.getPrototypeOf(p).foo).toBe(1);
     });
 
-    Object.setPrototypeOf(p, { foo: 1 });
-    assert(Object.getPrototypeOf(p).foo === undefined);
-    p.shouldSet = true;
-    assert(o.shouldSet === true);
-    Object.setPrototypeOf(p, { foo: 1 });
-    assert(Object.getPrototypeOf(p).foo === 1);
+    test("non-extensible targets", () => {
+        let o = {};
+        let proto = {};
+        Object.setPrototypeOf(o, proto);
+        Object.preventExtensions(o);
 
-    // Invariants
+        p = new Proxy(o, {
+            setPrototypeOf() {
+                return true;
+            },
+        });
 
-    assertThrowsError(() => {
-        Object.setPrototypeOf(new Proxy(child, { setPrototypeOf: 1 }), {});
-    }, {
-        error: TypeError,
-        message: "Proxy handler's setPrototypeOf trap wasn't undefined, null, or callable",
+        expect(Object.setPrototypeOf(p, proto)).toBe(p);
+        expect(Object.getPrototypeOf(p)).toBe(proto);
     });
-
-    p = new Proxy(child, {
-        setPrototypeOf(target, newProto) {
-            assert(target === child);
-            return false;
-        },
+});
+
+describe("[[SetPrototypeOf]] invariants", () => {
+    test("cannot return false", () => {
+        let o = {};
+        p = new Proxy(o, {
+            setPrototypeOf() {
+                return false;
+            },
+        });
+
+        expect(() => {
+            Object.setPrototypeOf(p, {});
+        }).toThrowWithMessage(TypeError, "Object's [[SetPrototypeOf]] method returned false");
     });
 
-    assertThrowsError(() => {
-        Object.setPrototypeOf(p, {});
-    }, {
-        error: TypeError,
-        message: "Object's [[SetPrototypeOf]] method returned false",
-    });
-    assert(Object.getPrototypeOf(p) === childProto);
+    test("the argument must match the target's prototype if the target is non-extensible", () => {
+        let o = {};
+        Object.preventExtensions(o);
 
-    p = new Proxy(child, {
-        setPrototypeOf(target, newProto) {
-            assert(target === child);
-            return true;
-        },
-    });
+        let p = new Proxy(o, {
+            setPrototypeOf() {
+                return true;
+            }
+        });
 
-    assert(Object.setPrototypeOf(p, {}) === p);
-    assert(Object.getPrototypeOf(p) === childProto);
-
-    Object.preventExtensions(child);
-    p = new Proxy(child, {
-        setPrototypeOf(target, newProto) {
-            assert(target === child);
-            return true;
-        },
+        expect(() => {
+            Object.setPrototypeOf(p, {});
+        }).toThrowWithMessage(TypeError, "Proxy handler's setPrototypeOf trap violates invariant: the argument must match the prototype of the target if the target is non-extensible");
     });
-
-    assert(Object.setPrototypeOf(p, childProto) === p);
-    assert(Object.getPrototypeOf(p) === childProto);
-
-    assertThrowsError(() => {
-        Object.setPrototypeOf(p, {});
-    }, {
-        error: TypeError,
-        message: "Proxy handler's setPrototypeOf trap violates invariant: the argument must match the prototype of the target if the target is non-extensible",
-    });
-
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+});

+ 25 - 24
Libraries/LibJS/Tests/builtins/Proxy/Proxy.js

@@ -1,30 +1,31 @@
-load("test-common.js");
+test("constructs properly", () => {
+    expect(() => {
+        new Proxy({}, {});
+    }).not.toThrow();
+});
 
-try {
-    new Proxy({}, {});
-
-    assertThrowsError(() => {
+test("constructor argument count", () => {
+    expect(() => {
         new Proxy();
-    }, {
-        error: TypeError,
-        message: "Proxy constructor requires at least two arguments",
-    });
+    }).toThrowWithMessage(TypeError, "Proxy constructor requires at least two arguments");
 
-    assertThrowsError(() => {
-        Proxy();
-    }, {
-        error: TypeError,
-        message: "Proxy must be called with the 'new' operator",
-    });
+    expect(() => {
+        new Proxy({});
+    }).toThrowWithMessage(TypeError, "Proxy constructor requires at least two arguments");
+});
 
-    assertThrowsError(() => {
+test("constructor requires objects", () => {
+    expect(() => {
         new Proxy(1, {});
-    }, {
-        error: TypeError,
-        message: "Expected target argument of Proxy constructor to be object, got 1",
-    });
+    }).toThrowWithMessage(TypeError, "Expected target argument of Proxy constructor to be object, got 1");
+
+    expect(() => {
+        new Proxy({}, 1);
+    }).toThrowWithMessage(TypeError, "Expected handler argument of Proxy constructor to be object, got 1");
+});
 
-    console.log("PASS");
-} catch (e) {
-    console.log("FAIL: " + e);
-}
+test("constructor must be invoked with 'new'", () => {
+    expect(() => {
+        Proxy({}, {});
+    }).toThrowWithMessage(TypeError, "Proxy must be called with the 'new' operator");
+});

+ 13 - 0
Userland/test-js.cpp

@@ -42,6 +42,19 @@
 
 // FIXME: Will eventually not be necessary when all tests are converted
 Vector<String> tests_to_run = {
+    "builtins/Proxy/Proxy.js",
+    "builtins/Proxy/Proxy.handler-apply.js",
+    "builtins/Proxy/Proxy.handler-construct.js",
+    "builtins/Proxy/Proxy.handler-defineProperty.js",
+    "builtins/Proxy/Proxy.handler-deleteProperty.js",
+    "builtins/Proxy/Proxy.handler-get.js",
+    "builtins/Proxy/Proxy.handler-getOwnPropertyDescriptor.js",
+    "builtins/Proxy/Proxy.handler-getPrototypeOf.js",
+    "builtins/Proxy/Proxy.handler-has.js",
+    "builtins/Proxy/Proxy.handler-isExtensible.js",
+    "builtins/Proxy/Proxy.handler-preventExtensions.js",
+    "builtins/Proxy/Proxy.handler-set.js",
+    "builtins/Proxy/Proxy.handler-setPrototypeOf.js",
     "add-values-to-primitive.js",
     "automatic-semicolon-insertion.js",
     "comments-basic.js",