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.
146 lines
3.8 KiB
JavaScript
146 lines
3.8 KiB
JavaScript
// `super.foo` not in a class or object method
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
() => () => {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
};
|
|
|
|
// `super.foo` in a function
|
|
function f(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
}
|
|
f = function(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
};
|
|
|
|
// `super.foo` in function inside class constructor
|
|
class A extends Super {
|
|
constructor() {
|
|
function inner(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
}
|
|
f = () => function(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
};
|
|
}
|
|
}
|
|
|
|
// `super.foo` in function inside class method
|
|
class B extends Super {
|
|
method() {
|
|
function inner(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
}
|
|
f = () => function(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
};
|
|
}
|
|
}
|
|
|
|
// `super.foo` in function inside class property
|
|
class C extends Super {
|
|
prop = () => {
|
|
function inner(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
}
|
|
f = () => function(arg = super.foo) {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
};
|
|
};
|
|
}
|
|
|
|
// `super.foo` in class computed keys
|
|
class D {
|
|
[super.foo] = 1;
|
|
static [() => super.foo] = 2;
|
|
accessor [123 + super.foo] = 3;
|
|
static accessor [() => () => 123 + super.foo] = 4;
|
|
[super.foo]() {};
|
|
static [() => super.foo]() {};
|
|
get [super.foo]() {};
|
|
static get [() => super.foo]() {};
|
|
set [super.foo](v) {};
|
|
static set [() => () => 123 + super.foo](v) {};
|
|
}
|
|
|
|
// `super.foo` in class extends
|
|
class E extends super.foo {}
|
|
class F extends (() => (arg = super.foo) => 123 + super.foo) {}
|
|
|
|
// `super.foo` in class decorators
|
|
@super.foo
|
|
class G extends Super {
|
|
@super.foo prop = 1;
|
|
@super.foo static prop = 2;
|
|
@super.foo accessor access = 3;
|
|
@super.foo static accessor access = 4;
|
|
@super.foo method() {}
|
|
}
|
|
|
|
// `super.foo` in computed keys in class inside function
|
|
function g() {
|
|
class Inner {
|
|
[super.foo] = 1;
|
|
static [(arg = super.foo) => super.foo] = 2;
|
|
accessor [123 + super.foo] = 3;
|
|
static accessor [() => (arg = super.foo) => 123 + super.foo] = 4;
|
|
[super.foo]() {};
|
|
static [() => super.foo]() {};
|
|
get [super.foo]() {};
|
|
static get [() => super.foo]() {};
|
|
set [super.foo](v) {};
|
|
static set [() => () => 123 + super.foo](v) {};
|
|
}
|
|
}
|
|
|
|
// `super.foo` in extends clause of class inside function
|
|
function h() {
|
|
class E extends super.foo {}
|
|
class F extends (() => (arg = super.foo) => 123 + super.foo) {}
|
|
}
|
|
|
|
// `super.foo` in decorators in class inside function
|
|
function i() {
|
|
@super.foo
|
|
class Inner {
|
|
@super.foo prop = 1;
|
|
@super.foo static prop = 2;
|
|
@super.foo accessor access = 3;
|
|
@super.foo static accessor access = 4;
|
|
@super.foo method() {}
|
|
}
|
|
}
|
|
|
|
// `super.foo` in object properties
|
|
obj = {
|
|
prop: (arg = super.foo) => {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
},
|
|
['x']: (arg = super.foo) => {
|
|
super.foo;
|
|
() => (arg = super.foo) => 123 + super.foo;
|
|
if (true) { while (false) { { super.foo; } } }
|
|
},
|
|
};
|