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
|
describe("non-syntax errors", () => {
test("super reference inside nested-but-same |this| scope with no base class", () => {
expect(`
class A {
foo() {
() => { super.bar; }
}
}`).toEval();
});
test("super reference property lookup with no base class", () => {
expect(`
class A {
constructor() {
super.foo;
}
}`).toEval();
});
});
describe("reference errors", () => {
test("derived class doesn't call super in constructor before using this", () => {
class Parent {}
class Child extends Parent {
constructor() {
this;
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| has not been initialized");
});
test("derived class calls super twice in constructor", () => {
class Parent {}
class Child extends Parent {
constructor() {
super();
super();
}
}
expect(() => {
new Child();
}).toThrowWithMessage(ReferenceError, "|this| is already initialized");
});
});
describe("syntax errors", () => {
test("getter with argument", () => {
expect(`
class A {
get foo(v) {
return 0;
}
}`).not.toEval();
});
test("setter with no arguments", () => {
expect(`
class A {
set foo() {
}
}`).not.toEval();
});
test("setter with more than one argument", () => {
expect(`
class A {
set foo(bar, baz) {
}
}`).not.toEval();
});
test("super reference inside different |this| scope", () => {
expect(`
class Parent {}
class Child extends Parent {
foo() {
function f() { super.foo; }
}
}`).not.toEval();
});
test("super reference call with no base class", () => {
expect(`
class A {
constructor() {
super();
}
}`).not.toEval();
});
});
|