summaryrefslogtreecommitdiff
path: root/Libraries/LibJS/Tests/builtins/Proxy/Proxy.handler-get.js
blob: 7919b196fe4ef996026c60b9d3943b1a95ba68c0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
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();
    });

    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);
            },
        });

        p.foo;
    });

    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];
            },
        });

        expect(p.foo).toBe(1);
        expect(p.bar).toBe(2);
        expect(p.baz).toBe(3);
        expect(p.qux).toBe(3);
        expect(p.test).toBeUndefined();
        expect(p[Symbol.hasInstance]).toBeUndefined();
    });

    test("custom receiver value", () => {
        let p = new Proxy(
            {},
            {
                get(target, property, receiver) {
                    return receiver;
                },
            }
        );

        expect(Reflect.get(p, "foo", 42)).toBe(42);
    });
});

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 });

        let 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"
        );
    });

    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(_) {} });

        let p = new Proxy(o, {
            get() {
                return 8;
            },
        });

        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"
        );
    });
});