summaryrefslogtreecommitdiffstats
path: root/js/src/tests/non262/class/classHeritage.js
blob: 478c23fc219a75acf8dc5ba9b24f91a43d3fae80 (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
97
// It's an error to have a non-constructor as your heritage
assertThrowsInstanceOf(() => eval(`class a extends Math.sin {
                                        constructor() { }
                                    }`), TypeError);
assertThrowsInstanceOf(() => eval(`(class a extends Math.sin {
                                        constructor() { }
                                    })`), TypeError);

// Unless it's null, in which case it works like a normal class, except that
// the prototype object does not inherit from Object.prototype.
class basic {
    constructor() { }
}
class nullExtends extends null {
    constructor() { }
}
var nullExtendsExpr = class extends null { constructor() { } };

assertEq(Object.getPrototypeOf(basic), Function.prototype);
assertEq(Object.getPrototypeOf(basic.prototype), Object.prototype);

for (let extension of [nullExtends, nullExtendsExpr]) {
    assertEq(Object.getPrototypeOf(extension), Function.prototype);
    assertEq(Object.getPrototypeOf(extension.prototype), null);
}

var baseMethodCalled;
var staticMethodCalled;
var overrideCalled;
class base {
    constructor() { };
    method() { baseMethodCalled = true; }
    static staticMethod() { staticMethodCalled = true; }
    override() { overrideCalled = "base" }
}
class derived extends base {
    constructor() { super(); };
    override() { overrideCalled = "derived"; }
}
var derivedExpr = class extends base {
    constructor() { super(); };
    override() { overrideCalled = "derived"; }
};

// Make sure we get the right object layouts.
for (let extension of [derived, derivedExpr]) {
    baseMethodCalled = false;
    staticMethodCalled = false;
    overrideCalled = "";
    // Make sure we get the right object layouts.
    assertEq(Object.getPrototypeOf(extension), base);
    assertEq(Object.getPrototypeOf(extension.prototype), base.prototype);

    // We do inherit the methods, right?
    (new extension()).method();
    assertEq(baseMethodCalled, true);

    // But we can still override them?
    (new extension()).override();
    assertEq(overrideCalled, "derived");

    // What about the statics?
    extension.staticMethod();
    assertEq(staticMethodCalled, true);
}

// Gotta extend an object, or null.
function nope() {
    class Foo extends "Bar" {
        constructor() { }
    }
}
function nopeExpr() {
    (class extends "Bar" {
        constructor() { }
     });
}
assertThrowsInstanceOf(nope, TypeError);
assertThrowsInstanceOf(nopeExpr, TypeError);

// The .prototype of the extension must be an object, or null.
nope.prototype = "not really, no";
function stillNo() {
    class Foo extends nope {
        constructor() { }
    }
}
function stillNoExpr() {
    (class extends nope {
        constructor() { }
     });
}
assertThrowsInstanceOf(stillNo, TypeError);
assertThrowsInstanceOf(stillNoExpr, TypeError);

if (typeof reportCompare === "function")
    reportCompare(0, 0, "OK");