mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
9fa551a6ce
Fixes #13284. Fix semantic's checking of `super()` and `super.prop`. This fixes various TS test cases, notably correctly identifying that these are all illegal: ```js class C { prop = function() { super.foo }; [super.foo]() {} @super.foo method() {} }; ``` It also fixes various edge cases related to classes nested within other classes that aren't covered by existing conformance tests. It's pretty much a complete re-write. I've combined the 2 paths for in a class and not in a class into one, to avoid repeated code. This PR includes pass + fail test fixtures which include `super` in every conceivable position I could think of. There are so many errors in the fail test fixtures, that I had to write a script to check the snapshot includes them all! Hopefully this solves this issue for once and for all! Note: The large pass fixture seems to be revealing bugs somewhere in transformer - there's a mismatch, as well as lots of wrong scopes. But that's incidental to this PR, and can be addressed separately.
306 lines
7.3 KiB
JavaScript
306 lines
7.3 KiB
JavaScript
// `super()` not in a class or object method
|
|
super();
|
|
() => () => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
() => (arg = super()) => {
|
|
super();
|
|
() => () => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
};
|
|
|
|
// `super()` in a function
|
|
function f(arg = super()) {
|
|
super();
|
|
() => () => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
f = function(arg = super()) {
|
|
super();
|
|
() => () => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
};
|
|
|
|
// `super()` in class constructor of class without super class
|
|
class A {
|
|
constructor(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
}
|
|
|
|
// `super()` in class properties
|
|
class B extends Super {
|
|
prop = super();
|
|
static prop = () => (arg = super()) => 123 + super();
|
|
|
|
accessor access = super();
|
|
static accessor access = () => () => 123 + super();
|
|
}
|
|
|
|
// `super()` in class methods / getters / setters
|
|
class C extends Super {
|
|
method(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
static method(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
['x'](arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
static ['x'](arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
get y() {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
set y(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
static get y() {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
|
|
static set y(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
}
|
|
|
|
// `super()` in class static block
|
|
class D extends Super {
|
|
static {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
}
|
|
|
|
// `super()` in function or object method inside class constructor
|
|
class E extends Super {
|
|
constructor() {
|
|
function inner(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
}
|
|
f = () => function(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
};
|
|
obj = {
|
|
method(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
set x(arg = super()) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
};
|
|
}
|
|
}
|
|
|
|
// `super()` in class computed keys
|
|
class F extends Super {
|
|
[super()] = 1;
|
|
static [(arg = super()) => super()] = 2;
|
|
accessor [123 + super()] = 3;
|
|
static accessor [() => (arg = super()) => 123 + super()] = 4;
|
|
[super()]() {};
|
|
static [() => super()]() {};
|
|
get [super()]() {};
|
|
static get [() => super()]() {};
|
|
set [super()](v) {};
|
|
static set [() => () => 123 + super()](v) {};
|
|
}
|
|
|
|
// `super()` in class extends
|
|
class G extends super() {}
|
|
class H extends (() => () => 123 + super()) {}
|
|
|
|
// `super()` in class decorators
|
|
@super()
|
|
class I extends Super {
|
|
@super() prop = 1;
|
|
@super() static prop = 2;
|
|
@super() accessor access = 3;
|
|
@super() static accessor access = 4;
|
|
@super() method() {}
|
|
}
|
|
|
|
// `super()` in properties / methods of class inside class constructor
|
|
class J extends Super {
|
|
constructor() {
|
|
class Inner {
|
|
prop = super();
|
|
static prop = (arg = super()) => 123 + super();
|
|
accessor access = super();
|
|
static accessor access = (arg = super()) => 123 + super();
|
|
method() { super(); }
|
|
static method() { (arg = super()) => 123 + super(); }
|
|
get x() { super(); }
|
|
static get y() { (arg = super()) => 123 + super(); }
|
|
set x(v) { super(); }
|
|
static set y(v) { (arg = super()) => 123 + super(); }
|
|
static { super(); }
|
|
}
|
|
}
|
|
}
|
|
|
|
// `super()` in computed keys of class inside class property
|
|
class K extends Super {
|
|
prop = class Inner {
|
|
[super()] = 1;
|
|
static [(arg = super()) => super()] = 2;
|
|
accessor [123 + super()] = 3;
|
|
static accessor [() => (arg = super()) => 123 + super()] = 4;
|
|
[super()]() {};
|
|
static [() => super()]() {};
|
|
get [super()]() {};
|
|
static get [() => super()]() {};
|
|
set [super()](v) {};
|
|
static set [() => () => 123 + super()](v) {};
|
|
};
|
|
}
|
|
|
|
// `super()` in computed keys of class inside class method
|
|
class L extends Super {
|
|
method() {
|
|
class Inner {
|
|
[super()] = 1;
|
|
static [(arg = super()) => super()] = 2;
|
|
accessor [123 + super()] = 3;
|
|
static accessor [() => (arg = super()) => 123 + super()] = 4;
|
|
[super()]() {};
|
|
static [() => super()]() {};
|
|
get [super()]() {};
|
|
static get [() => super()]() {};
|
|
set [super()](v) {};
|
|
static set [() => () => 123 + super()](v) {};
|
|
}
|
|
}
|
|
}
|
|
|
|
// `super()` in extends clause of class inside class property
|
|
class M extends Super {
|
|
prop1 = class Inner extends super() {};
|
|
prop2 = class Inner extends (() => (arg = super()) => 123 + super()) {};
|
|
}
|
|
|
|
// `super()` in extends clause of class inside class method
|
|
class N extends Super {
|
|
method() {
|
|
class Inner1 extends super() {};
|
|
class Inner2 extends (() => (arg = super()) => 123 + super()) {};
|
|
}
|
|
}
|
|
|
|
// `super()` in decorators of class inside class property
|
|
class O extends Super {
|
|
prop = @super() class Inner extends Super {
|
|
@super() prop = 1;
|
|
@super() static prop = 2;
|
|
@super() accessor access = 3;
|
|
@super() static accessor access = 4;
|
|
@super() method() {}
|
|
};
|
|
}
|
|
|
|
// `super()` in decorators of class inside class method
|
|
class P extends Super {
|
|
method() {
|
|
@super()
|
|
class Inner extends Super {
|
|
@super() prop = 1;
|
|
@super() static prop = 2;
|
|
@super() accessor access = 3;
|
|
@super() static accessor access = 4;
|
|
@super() method() {}
|
|
}
|
|
}
|
|
}
|
|
|
|
// `super()` in deeply nested classes inside class method
|
|
class Q extends Super {
|
|
method() {
|
|
class A {
|
|
[
|
|
class B {
|
|
[
|
|
class C {
|
|
[super()]() {}
|
|
}
|
|
]() {}
|
|
}
|
|
]() {}
|
|
}
|
|
|
|
class D extends class E extends class F extends super() {} {} {}
|
|
|
|
class G {
|
|
@(
|
|
class H {
|
|
@(
|
|
class I {
|
|
@super()
|
|
method() {}
|
|
}
|
|
)
|
|
method() {}
|
|
}
|
|
)
|
|
method() {}
|
|
}
|
|
}
|
|
}
|
|
|
|
// `super()` in object methods
|
|
obj = {
|
|
method() {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
['x']() {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
get x() {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
set x(v) {
|
|
super();
|
|
() => (arg = super()) => 123 + super();
|
|
if (true) { while (false) { { super(); } } }
|
|
},
|
|
};
|