Skip to content

Commit

Permalink
Preserve rendered class names (#4674)
Browse files Browse the repository at this point in the history
* Preserve class declaration names

* Preserve class expression names

* Slightly improve code
  • Loading branch information
lukastaegert committed Oct 16, 2022
1 parent 11d425b commit 46e1eaa
Show file tree
Hide file tree
Showing 30 changed files with 147 additions and 37 deletions.
17 changes: 14 additions & 3 deletions src/ast/nodes/ClassDeclaration.ts
Expand Up @@ -33,10 +33,21 @@ export default class ClassDeclaration extends ClassNode {
const {
exportNamesByVariable,
format,
snippets: { _ }
snippets: { _, getPropertyAccess }
} = options;
if (format === 'system' && this.id && exportNamesByVariable.has(this.id.variable)) {
code.appendLeft(this.end, `${_}${getSystemExportStatement([this.id.variable], options)};`);
if (this.id) {
const { variable, name } = this.id;
if (format === 'system' && exportNamesByVariable.has(variable)) {
code.appendLeft(this.end, `${_}${getSystemExportStatement([variable], options)};`);
}
const renderedVariable = variable.getName(getPropertyAccess);
if (renderedVariable !== name) {
this.superClass?.render(code, options);
this.body.render(code, options);
code.prependRight(this.start, `let ${renderedVariable}${_}=${_}`);
code.prependLeft(this.end, ';');
return;
}
}
super.render(code, options);
}
Expand Down
28 changes: 18 additions & 10 deletions src/ast/nodes/VariableDeclarator.ts
Expand Up @@ -9,6 +9,7 @@ import {
import type { HasEffectsContext, InclusionContext } from '../ExecutionContext';
import type { ObjectPath } from '../utils/PathTracker';
import { UNDEFINED_EXPRESSION } from '../values';
import ClassExpression from './ClassExpression';
import Identifier from './Identifier';
import * as NodeType from './NodeType';
import { type ExpressionNode, type IncludeChildren, NodeBase } from './shared/Node';
Expand Down Expand Up @@ -45,26 +46,33 @@ export default class VariableDeclarator extends NodeBase {
render(code: MagicString, options: RenderOptions): void {
const {
exportNamesByVariable,
snippets: { _ }
snippets: { _, getPropertyAccess }
} = options;
const renderId = this.id.included;
const { end, id, init, start } = this;
const renderId = id.included;
if (renderId) {
this.id.render(code, options);
id.render(code, options);
} else {
const operatorPos = findFirstOccurrenceOutsideComment(code.original, '=', this.id.end);
code.remove(this.start, findNonWhiteSpace(code.original, operatorPos + 1));
const operatorPos = findFirstOccurrenceOutsideComment(code.original, '=', id.end);
code.remove(start, findNonWhiteSpace(code.original, operatorPos + 1));
}
if (this.init) {
this.init.render(
if (init) {
if (id instanceof Identifier && init instanceof ClassExpression && !init.id) {
const renderedVariable = id.variable!.getName(getPropertyAccess);
if (renderedVariable !== id.name) {
code.appendLeft(init.start + 5, ` ${id.name}`);
}
}
init.render(
code,
options,
renderId ? BLANK : { renderedSurroundingElement: NodeType.ExpressionStatement }
);
} else if (
this.id instanceof Identifier &&
isReassignedExportsMember(this.id.variable!, exportNamesByVariable)
id instanceof Identifier &&
isReassignedExportsMember(id.variable!, exportNamesByVariable)
) {
code.appendLeft(this.end, `${_}=${_}void 0`);
code.appendLeft(end, `${_}=${_}void 0`);
}
}

Expand Down
@@ -1,10 +1,10 @@
define(['exports'], (function (exports) { 'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,10 +1,10 @@
'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,8 +1,8 @@
class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
Expand Up @@ -3,11 +3,11 @@ System.register([], (function (exports) {
return {
execute: (function () {

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = exports('p', 43);

Expand Down
@@ -1,10 +1,10 @@
define(['exports'], (function (exports) { 'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,10 +1,10 @@
'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,8 +1,8 @@
class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
Expand Up @@ -3,11 +3,11 @@ System.register([], (function (exports) {
return {
execute: (function () {

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = exports('p', 43);

Expand Down
@@ -1,10 +1,10 @@
define(['exports'], (function (exports) { 'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,10 +1,10 @@
'use strict';

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
@@ -1,8 +1,8 @@
class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
}
};

var p$1 = 43;

Expand Down
Expand Up @@ -3,11 +3,11 @@ System.register([], (function (exports) {
return {
execute: (function () {

class C$1 {
let C$1 = class C {
fn (num) {
console.log(num - p);
}
} exports('C', C$1);
}; exports('C', C$1);

var p$1 = exports('p', 43);

Expand Down
@@ -0,0 +1,4 @@
module.exports = {
description: 'handles exporting class declarations with name conflicts in SystemJS',
options: { output: { name: 'bundle' } }
};
@@ -0,0 +1,10 @@
define(['exports'], (function (exports) { 'use strict';

let Foo$1 = class Foo {};

class Foo {}

exports.First = Foo$1;
exports.Second = Foo;

}));
@@ -0,0 +1,8 @@
'use strict';

let Foo$1 = class Foo {};

class Foo {}

exports.First = Foo$1;
exports.Second = Foo;
@@ -0,0 +1,5 @@
let Foo$1 = class Foo {};

class Foo {}

export { Foo$1 as First, Foo as Second };
@@ -0,0 +1,13 @@
var bundle = (function (exports) {
'use strict';

let Foo$1 = class Foo {};

class Foo {}

exports.First = Foo$1;
exports.Second = Foo;

return exports;

})({});
@@ -0,0 +1,12 @@
System.register('bundle', [], (function (exports) {
'use strict';
return {
execute: (function () {

let Foo$1 = class Foo {}; exports('First', Foo$1);

class Foo {} exports('Second', Foo);

})
};
}));
@@ -0,0 +1,14 @@
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
typeof define === 'function' && define.amd ? define(['exports'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.bundle = {}));
})(this, (function (exports) { 'use strict';

let Foo$1 = class Foo {};

class Foo {}

exports.First = Foo$1;
exports.Second = Foo;

}));
@@ -0,0 +1,2 @@
class Foo {}
export { Foo };
2 changes: 2 additions & 0 deletions test/form/samples/exported-class-declaration-conflict/main.js
@@ -0,0 +1,2 @@
export { Foo as First } from './first';
export { Foo as Second } from './second';
@@ -0,0 +1,2 @@
class Foo {}
export { Foo };
3 changes: 3 additions & 0 deletions test/function/samples/class-name-conflict/_config.js
@@ -0,0 +1,3 @@
module.exports = {
description: 'preserves class names even if the class is renamed'
};
3 changes: 3 additions & 0 deletions test/function/samples/class-name-conflict/declaration1.js
@@ -0,0 +1,3 @@
class foo {}

assert.strictEqual(foo.name, 'foo');
3 changes: 3 additions & 0 deletions test/function/samples/class-name-conflict/declaration2.js
@@ -0,0 +1,3 @@
class foo {}

assert.strictEqual(foo.name, 'foo');
3 changes: 3 additions & 0 deletions test/function/samples/class-name-conflict/expression1.js
@@ -0,0 +1,3 @@
let foo = class {};

assert.strictEqual(foo.name, 'foo');
3 changes: 3 additions & 0 deletions test/function/samples/class-name-conflict/expression2.js
@@ -0,0 +1,3 @@
let foo = class {};

assert.strictEqual(foo.name, 'foo');
4 changes: 4 additions & 0 deletions test/function/samples/class-name-conflict/main.js
@@ -0,0 +1,4 @@
import './expression1';
import './declaration1';
import './expression2';
import './declaration2';

0 comments on commit 46e1eaa

Please sign in to comment.