summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/extensions/newer-type-functions-caller-arguments.js
blob: 8f2d47a11d38ec1c266919e944921cdba610126b (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
// Tests that newer-type functions (i.e. anything not defined by regular function declarations and
// expressions) throw when accessing their 'arguments' and 'caller' properties.

// 9.2.7 (AddRestrictedFunctionProperties) defines accessors on Function.prototype which throw on
// every 'get' and 'set' of 'caller' and 'arguments'.
// Additionally, 16.2 (Forbidden Extensions) forbids adding properties to all non-"legacy" function
// declarations and expressions. This creates the effect that all newer-style functions act like
// strict-mode functions when accessing their 'caller' and 'arguments' properties.

const container = {
    async asyncMethod() {},
    *genMethod() {},
    method() {},
    get getterMethod() {},
    set setterMethod(x) {},
};

function* genDecl(){}
async function asyncDecl(){}
class classDecl {}
class extClassDecl extends Object {}
class classDeclExplicitCtor { constructor(){} }
class extClassDeclExplicitCtor extends Object { constructor(){} }

const functions = [
    // Declarations
    genDecl,
    asyncDecl,
    classDecl,
    extClassDecl,
    classDeclExplicitCtor,
    extClassDeclExplicitCtor,

    // Expressions
    async function(){},
    function*(){},
    () => {},
    async () => {},
    class {},
    class extends Object {},
    class { constructor(){} },
    class extends Object { constructor(){} },

    // Methods
    container.asyncMethod,
    container.genMethod,
    container.method,
    Object.getOwnPropertyDescriptor(container, "getterMethod").get,
    Object.getOwnPropertyDescriptor(container, "setterMethod").set,

    // Bound functions
    function(){}.bind(),

    // Built-ins (native and self-hosted)
    Function,
    Function.prototype.bind,
];

const supportsAsyncGenerator = (function() {
    try {
        eval("async function* f(){}");
        return true;
    } catch (e) {
        return false;
    }
})();

if (supportsAsyncGenerator) {
eval(`
    async function* asyncGenDecl(){}

    functions.push(asyncGenDecl);
    functions.push(async function*(){});
    functions.push({async* asyncGenerator(){}}.asyncGenerator);
`);
}

functions.forEach(f => {
    checkArgumentsAccess(f);
    checkCallerAccess(f);
});

function checkArgumentsAccess(f) {
    assertThrowsInstanceOf(() => f.arguments, TypeError,
                           `Expected 'arguments' property access to throw on ${f}`);
}

function checkCallerAccess(f) {
    assertThrowsInstanceOf(() => f.caller, TypeError,
                           `Expected 'caller' property access to throw on ${f}`);
}

if (typeof reportCompare === "function")
    reportCompare(true, true);