diff --git a/src/Chunk.ts b/src/Chunk.ts index 4a9c675605d..21f65ec3eb1 100644 --- a/src/Chunk.ts +++ b/src/Chunk.ts @@ -1168,7 +1168,8 @@ export default class Chunk { indent, namespaceToStringTag, pluginDriver, - snippets + snippets, + useOriginalName: null }; let usesTopLevelAwait = false; diff --git a/src/ast/nodes/ClassDeclaration.ts b/src/ast/nodes/ClassDeclaration.ts index 093f91d2f6d..b2f1186041c 100644 --- a/src/ast/nodes/ClassDeclaration.ts +++ b/src/ast/nodes/ClassDeclaration.ts @@ -2,6 +2,7 @@ import type MagicString from 'magic-string'; import type { RenderOptions } from '../../utils/renderHelpers'; import { getSystemExportStatement } from '../../utils/systemJsRendering'; import type ChildScope from '../scopes/ChildScope'; +import type Variable from '../variables/Variable'; import Identifier, { type IdentifierWithVariable } from './Identifier'; import type * as NodeType from './NodeType'; import ClassNode from './shared/ClassNode'; @@ -43,7 +44,10 @@ export default class ClassDeclaration extends ClassNode { const renderedVariable = variable.getName(getPropertyAccess); if (renderedVariable !== name) { this.superClass?.render(code, options); - this.body.render(code, options); + this.body.render(code, { + ...options, + useOriginalName: (_variable: Variable) => _variable === variable + }); code.prependRight(this.start, `let ${renderedVariable}${_}=${_}`); code.prependLeft(this.end, ';'); return; diff --git a/src/ast/nodes/Identifier.ts b/src/ast/nodes/Identifier.ts index 2fd56ba5c97..b587e4bbf75 100644 --- a/src/ast/nodes/Identifier.ts +++ b/src/ast/nodes/Identifier.ts @@ -244,11 +244,11 @@ export default class Identifier extends NodeBase implements PatternNode { render( code: MagicString, - { snippets: { getPropertyAccess } }: RenderOptions, + { snippets: { getPropertyAccess }, useOriginalName }: RenderOptions, { renderedParentType, isCalleeOfRenderedParent, isShorthandProperty }: NodeRenderOptions = BLANK ): void { if (this.variable) { - const name = this.variable.getName(getPropertyAccess); + const name = this.variable.getName(getPropertyAccess, useOriginalName); if (name !== this.name) { code.overwrite(this.start, this.end, name, { diff --git a/src/ast/variables/Variable.ts b/src/ast/variables/Variable.ts index 28f18a6e84a..37a9ca93270 100644 --- a/src/ast/variables/Variable.ts +++ b/src/ast/variables/Variable.ts @@ -1,5 +1,6 @@ import type ExternalModule from '../../ExternalModule'; import type Module from '../../Module'; +import type { RenderOptions } from '../../utils/renderHelpers'; import type { HasEffectsContext } from '../ExecutionContext'; import type { NodeInteraction } from '../NodeInteractions'; import { INTERACTION_ACCESSED } from '../NodeInteractions'; @@ -42,8 +43,11 @@ export default class Variable extends ExpressionEntity { return this.renderBaseName || this.renderName || this.name; } - getName(getPropertyAccess: (name: string) => string): string { - const name = this.renderName || this.name; + getName( + getPropertyAccess: (name: string) => string, + useOriginalName?: RenderOptions['useOriginalName'] + ): string { + const name = useOriginalName?.(this) ? this.name : this.renderName || this.name; return this.renderBaseName ? `${this.renderBaseName}${getPropertyAccess(name)}` : name; } diff --git a/src/utils/renderHelpers.ts b/src/utils/renderHelpers.ts index 48c8a441aed..c3e3b080841 100644 --- a/src/utils/renderHelpers.ts +++ b/src/utils/renderHelpers.ts @@ -15,6 +15,7 @@ export interface RenderOptions { namespaceToStringTag: boolean; pluginDriver: PluginDriver; snippets: GenerateCodeSnippets; + useOriginalName: ((variable: Variable) => boolean) | null; } export interface NodeRenderOptions { diff --git a/test/form/samples/use-class-name-in-static-block/_config.js b/test/form/samples/use-class-name-in-static-block/_config.js new file mode 100644 index 00000000000..1ca77cc9bb4 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_config.js @@ -0,0 +1,3 @@ +module.exports = { + description: 'use the original class name instead of renderName in class body' +}; diff --git a/test/form/samples/use-class-name-in-static-block/_expected/amd.js b/test/form/samples/use-class-name-in-static-block/_expected/amd.js new file mode 100644 index 00000000000..b42174f3455 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/amd.js @@ -0,0 +1,36 @@ +define((function () { 'use strict'; + + let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } + }; + + class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } + } + + assert.ok(Test$1.test); + assert.ok(Test.test); + +})); diff --git a/test/form/samples/use-class-name-in-static-block/_expected/cjs.js b/test/form/samples/use-class-name-in-static-block/_expected/cjs.js new file mode 100644 index 00000000000..764d68ec68a --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/cjs.js @@ -0,0 +1,34 @@ +'use strict'; + +let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } +}; + +class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } +} + +assert.ok(Test$1.test); +assert.ok(Test.test); diff --git a/test/form/samples/use-class-name-in-static-block/_expected/es.js b/test/form/samples/use-class-name-in-static-block/_expected/es.js new file mode 100644 index 00000000000..eddebce6e34 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/es.js @@ -0,0 +1,32 @@ +let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } +}; + +class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } +} + +assert.ok(Test$1.test); +assert.ok(Test.test); diff --git a/test/form/samples/use-class-name-in-static-block/_expected/iife.js b/test/form/samples/use-class-name-in-static-block/_expected/iife.js new file mode 100644 index 00000000000..0b0a9b0c0aa --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/iife.js @@ -0,0 +1,37 @@ +(function () { + 'use strict'; + + let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } + }; + + class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } + } + + assert.ok(Test$1.test); + assert.ok(Test.test); + +})(); diff --git a/test/form/samples/use-class-name-in-static-block/_expected/system.js b/test/form/samples/use-class-name-in-static-block/_expected/system.js new file mode 100644 index 00000000000..a1bc68606c8 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/system.js @@ -0,0 +1,41 @@ +System.register([], (function () { + 'use strict'; + return { + execute: (function () { + + let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } + }; + + class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } + } + + assert.ok(Test$1.test); + assert.ok(Test.test); + + }) + }; +})); diff --git a/test/form/samples/use-class-name-in-static-block/_expected/umd.js b/test/form/samples/use-class-name-in-static-block/_expected/umd.js new file mode 100644 index 00000000000..d2b0377bf59 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/_expected/umd.js @@ -0,0 +1,39 @@ +(function (factory) { + typeof define === 'function' && define.amd ? define(factory) : + factory(); +})((function () { 'use strict'; + + let Test$1 = class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } + }; + + class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } + } + + assert.ok(Test$1.test); + assert.ok(Test.test); + +})); diff --git a/test/form/samples/use-class-name-in-static-block/main.js b/test/form/samples/use-class-name-in-static-block/main.js new file mode 100644 index 00000000000..27ceb8b9400 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/main.js @@ -0,0 +1,5 @@ +import { Test } from './test1.js'; +import { Test as Test2 } from './test2.js'; + +assert.ok(Test.test); +assert.ok(Test2.test); diff --git a/test/form/samples/use-class-name-in-static-block/test1.js b/test/form/samples/use-class-name-in-static-block/test1.js new file mode 100644 index 00000000000..e6d964bb0e0 --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/test1.js @@ -0,0 +1,14 @@ +export class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } +} diff --git a/test/form/samples/use-class-name-in-static-block/test2.js b/test/form/samples/use-class-name-in-static-block/test2.js new file mode 100644 index 00000000000..0ac76f89d2c --- /dev/null +++ b/test/form/samples/use-class-name-in-static-block/test2.js @@ -0,0 +1,14 @@ +export class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } +} diff --git a/test/function/samples/use-class-name-in-static-block/_config.js b/test/function/samples/use-class-name-in-static-block/_config.js new file mode 100644 index 00000000000..53bc76e249c --- /dev/null +++ b/test/function/samples/use-class-name-in-static-block/_config.js @@ -0,0 +1,4 @@ +module.exports = { + description: 'use the original class name instead of renderName in class body', + minNodeVersion: 16 +}; diff --git a/test/function/samples/use-class-name-in-static-block/main.js b/test/function/samples/use-class-name-in-static-block/main.js new file mode 100644 index 00000000000..27ceb8b9400 --- /dev/null +++ b/test/function/samples/use-class-name-in-static-block/main.js @@ -0,0 +1,5 @@ +import { Test } from './test1.js'; +import { Test as Test2 } from './test2.js'; + +assert.ok(Test.test); +assert.ok(Test2.test); diff --git a/test/function/samples/use-class-name-in-static-block/test1.js b/test/function/samples/use-class-name-in-static-block/test1.js new file mode 100644 index 00000000000..e6d964bb0e0 --- /dev/null +++ b/test/function/samples/use-class-name-in-static-block/test1.js @@ -0,0 +1,14 @@ +export class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test1'; + static { + assert.ok(Test.test); + new Test(); + } +} diff --git a/test/function/samples/use-class-name-in-static-block/test2.js b/test/function/samples/use-class-name-in-static-block/test2.js new file mode 100644 index 00000000000..0ac76f89d2c --- /dev/null +++ b/test/function/samples/use-class-name-in-static-block/test2.js @@ -0,0 +1,14 @@ +export class Test { + constructor() { + assert.ok(Test.test); + assert.ok(this.getText()); + } + getText() { + return Test.test; + } + static test = 'Test2'; + static { + assert.ok(Test.test); + new Test(); + } +}