Don't duplicate the base class when using constantSuper (#13303)

This commit is contained in:
Nicolò Ribaudo 2021-05-15 00:02:46 +02:00 committed by GitHub
parent 3195883923
commit 989aac2a4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 77 additions and 33 deletions

View File

@ -672,7 +672,7 @@ const thisContextVisitor = traverse.visitors.merge([
function replaceThisContext( function replaceThisContext(
path, path,
ref, ref,
superRef, getSuperRef,
file, file,
isStaticBlock, isStaticBlock,
constantSuper, constantSuper,
@ -682,9 +682,9 @@ function replaceThisContext(
const replacer = new ReplaceSupers({ const replacer = new ReplaceSupers({
methodPath: path, methodPath: path,
constantSuper, constantSuper,
superRef,
file, file,
refToPreserve: ref, refToPreserve: ref,
getSuperRef,
getObjectRef() { getObjectRef() {
state.needsClassRef = true; state.needsClassRef = true;
return isStaticBlock || path.node.static return isStaticBlock || path.node.static
@ -710,11 +710,20 @@ export function buildFieldsInitNodes(
constantSuper, constantSuper,
) { ) {
let needsClassRef = false; let needsClassRef = false;
let injectSuperRef;
const staticNodes = []; const staticNodes = [];
const instanceNodes = []; const instanceNodes = [];
// These nodes are pure and can be moved to the closest statement position // These nodes are pure and can be moved to the closest statement position
const pureStaticNodes = []; const pureStaticNodes = [];
const getSuperRef = t.isIdentifier(superRef)
? () => superRef
: () => {
injectSuperRef ??=
props[0].scope.generateUidIdentifierBasedOnNode(superRef);
return injectSuperRef;
};
for (const prop of props) { for (const prop of props) {
ts.assertFieldTransformed(prop); ts.assertFieldTransformed(prop);
@ -730,7 +739,7 @@ export function buildFieldsInitNodes(
const replaced = replaceThisContext( const replaced = replaceThisContext(
prop, prop,
ref, ref,
superRef, getSuperRef,
state, state,
isStaticBlock, isStaticBlock,
constantSuper, constantSuper,
@ -865,6 +874,14 @@ export function buildFieldsInitNodes(
prop.remove(); prop.remove();
} }
if (injectSuperRef) {
path.scope.push({ id: t.cloneNode(injectSuperRef) });
path.set(
"superClass",
t.assignmentExpression("=", injectSuperRef, path.node.superClass),
);
}
if (!needsClassRef) return path; if (!needsClassRef) return path;
if (path.isClassExpression()) { if (path.isClassExpression()) {

View File

@ -206,22 +206,20 @@ const looseHandlers = {
}, },
get(superMember) { get(superMember) {
const { isStatic, superRef } = this; const { isStatic, getSuperRef } = this;
const { computed } = superMember.node; const { computed } = superMember.node;
const prop = this.prop(superMember); const prop = this.prop(superMember);
let object; let object;
if (isStatic) { if (isStatic) {
object = superRef object =
? t.cloneNode(superRef) getSuperRef() ??
: t.memberExpression( t.memberExpression(t.identifier("Function"), t.identifier("prototype"));
t.identifier("Function"),
t.identifier("prototype"),
);
} else { } else {
object = superRef object = t.memberExpression(
? t.memberExpression(t.cloneNode(superRef), t.identifier("prototype")) getSuperRef() ?? t.identifier("Object"),
: t.memberExpression(t.identifier("Object"), t.identifier("prototype")); t.identifier("prototype"),
);
} }
return t.memberExpression(object, prop, computed); return t.memberExpression(object, prop, computed);
@ -264,15 +262,15 @@ type ReplaceSupersOptionsBase = {
refToPreserve?: t.Identifier; refToPreserve?: t.Identifier;
}; };
type ReplaceSupersOptions = type ReplaceSupersOptions = ReplaceSupersOptionsBase &
| ({ (
objectRef?: undefined; | { objectRef?: undefined; getObjectRef: () => t.Node }
getObjectRef: () => t.Node; | { objectRef: t.Node; getObjectRef?: undefined }
} & ReplaceSupersOptionsBase) ) &
| ({ (
objectRef: t.Node; | { superRef?: undefined; getSuperRef: () => t.Node }
getObjectRef?: () => t.Node; | { superRef: t.Node; getSuperRef?: undefined }
} & ReplaceSupersOptionsBase); );
export default class ReplaceSupers { export default class ReplaceSupers {
constructor(opts: ReplaceSupersOptions) { constructor(opts: ReplaceSupersOptions) {
@ -286,7 +284,6 @@ export default class ReplaceSupers {
this.isPrivateMethod = path.isPrivate() && path.isMethod(); this.isPrivateMethod = path.isPrivate() && path.isMethod();
this.file = opts.file; this.file = opts.file;
this.superRef = opts.superRef;
this.constantSuper = process.env.BABEL_8_BREAKING this.constantSuper = process.env.BABEL_8_BREAKING
? opts.constantSuper ? opts.constantSuper
: // Fallback to isLoose for backward compatibility : // Fallback to isLoose for backward compatibility
@ -301,12 +298,16 @@ export default class ReplaceSupers {
declare isStatic: boolean; declare isStatic: boolean;
declare methodPath: NodePath; declare methodPath: NodePath;
declare opts: ReplaceSupersOptions; declare opts: ReplaceSupersOptions;
declare superRef: any;
getObjectRef() { getObjectRef() {
return t.cloneNode(this.opts.objectRef || this.opts.getObjectRef()); return t.cloneNode(this.opts.objectRef || this.opts.getObjectRef());
} }
getSuperRef() {
if (this.opts.superRef) return t.cloneNode(this.opts.superRef);
if (this.opts.getSuperRef) return t.cloneNode(this.opts.getSuperRef());
}
replace() { replace() {
// https://github.com/babel/babel/issues/11994 // https://github.com/babel/babel/issues/11994
if (this.opts.refToPreserve) { if (this.opts.refToPreserve) {
@ -324,7 +325,7 @@ export default class ReplaceSupers {
isStatic: this.isStatic, isStatic: this.isStatic,
isPrivateMethod: this.isPrivateMethod, isPrivateMethod: this.isPrivateMethod,
getObjectRef: this.getObjectRef.bind(this), getObjectRef: this.getObjectRef.bind(this),
superRef: this.superRef, getSuperRef: this.getSuperRef.bind(this),
...handler, ...handler,
}); });
} }

View File

@ -0,0 +1,3 @@
class A extends class B {} {
static x = super.x;
}

View File

@ -0,0 +1,5 @@
var _B;
class A extends (_B = class B {}) {}
babelHelpers.defineProperty(A, "x", _B.x);

View File

@ -0,0 +1,3 @@
class A extends B {
foo = super.bar;
}

View File

@ -0,0 +1,7 @@
class A extends B {
constructor(...args) {
super(...args);
babelHelpers.defineProperty(this, "foo", super.bar);
}
}

View File

@ -0,0 +1,6 @@
{
"assumptions": {
"constantSuper": true
},
"plugins": ["proposal-class-properties"]
}

View File

@ -0,0 +1,3 @@
class A extends B {
static foo = super.bar;
}

View File

@ -0,0 +1,3 @@
class A extends B {}
babelHelpers.defineProperty(A, "foo", B.bar);

View File

@ -1,17 +1,13 @@
var _class, _temp; var _ref, _class, _temp;
class Foo extends (_temp = _class = class {}, (() => { class Foo extends (_ref = (_temp = _class = class _ref {}, (() => {
_class.bar = 42; _class.bar = 42;
})(), _temp) {} })(), _temp)) {}
Foo.bar = 21; Foo.bar = 21;
(() => { (() => {
var _class2, _temp2; Foo.foo = _ref.bar;
Foo.foo = (_temp2 = _class2 = class {}, (() => {
_class2.bar = 42;
})(), _temp2).bar;
})(); })();
expect(Foo.foo).toBe(42); expect(Foo.foo).toBe(42);