diff --git a/src/ast/nodes/Program.ts b/src/ast/nodes/Program.ts index e82cc2bf2b6..f5f260e06aa 100644 --- a/src/ast/nodes/Program.ts +++ b/src/ast/nodes/Program.ts @@ -3,7 +3,11 @@ import type MagicString from 'magic-string'; import getCodeFrame from '../../utils/getCodeFrame'; import { getOriginalLocation } from '../../utils/getOriginalLocation'; import relativeId from '../../utils/relativeId'; -import { type RenderOptions, renderStatementList } from '../../utils/renderHelpers'; +import { + findFirstLineBreakOutsideComment, + type RenderOptions, + renderStatementList +} from '../../utils/renderHelpers'; import type { HasEffectsContext, InclusionContext } from '../ExecutionContext'; import { createHasEffectsContext } from '../ExecutionContext'; import type * as NodeType from './NodeType'; @@ -79,6 +83,16 @@ export default class Program extends NodeBase { code.remove(0, start); } if (this.body.length > 0) { + // Keep all consecutive lines that start with a comment + while (code.original[start] === '/' && /[*/]/.test(code.original[start + 1])) { + const firstLineBreak = findFirstLineBreakOutsideComment( + code.original.slice(start, this.body[0].start) + ); + if (firstLineBreak[0] === -1) { + break; + } + start += firstLineBreak[1]; + } renderStatementList(this.body, code, start, this.end, options); } else { super.render(code, options); diff --git a/src/utils/renderHelpers.ts b/src/utils/renderHelpers.ts index c3e3b080841..89b486ee777 100644 --- a/src/utils/renderHelpers.ts +++ b/src/utils/renderHelpers.ts @@ -70,7 +70,7 @@ export function findNonWhiteSpace(code: string, index: number): number { // This assumes "code" only contains white-space and comments // Returns position of line-comment if applicable -function findFirstLineBreakOutsideComment(code: string): [number, number] { +export function findFirstLineBreakOutsideComment(code: string): [number, number] { let lineBreakPos, charCodeAfterSlash, start = 0; diff --git a/test/form/samples/leading-comments/_config.js b/test/form/samples/leading-comments/_config.js new file mode 100644 index 00000000000..0df87ffe825 --- /dev/null +++ b/test/form/samples/leading-comments/_config.js @@ -0,0 +1,6 @@ +module.exports = defineTest({ + description: 'keeps leading comments on consecutive lines', + options: { + external: ['external'] + } +}); diff --git a/test/form/samples/leading-comments/_expected.js b/test/form/samples/leading-comments/_expected.js new file mode 100644 index 00000000000..9975cfbc807 --- /dev/null +++ b/test/form/samples/leading-comments/_expected.js @@ -0,0 +1,13 @@ +import 'external'; + +// comment dep 1/3 +/* comment +*/ // comment dep 2/3 +// comment dep 3/3 + +console.log('dep'); + +// comment main 1/2 +// comment main 2/2 + +console.log('main'); diff --git a/test/form/samples/leading-comments/dep.js b/test/form/samples/leading-comments/dep.js new file mode 100644 index 00000000000..dffa1075a82 --- /dev/null +++ b/test/form/samples/leading-comments/dep.js @@ -0,0 +1,7 @@ +// comment dep 1/3 +/* comment +*/ // comment dep 2/3 +// comment dep 3/3 +/* import comment */ import 'external'; + +console.log('dep'); diff --git a/test/form/samples/leading-comments/main.js b/test/form/samples/leading-comments/main.js new file mode 100644 index 00000000000..f17e3915705 --- /dev/null +++ b/test/form/samples/leading-comments/main.js @@ -0,0 +1,6 @@ +#! /usr/bin/env node +// comment main 1/2 +// comment main 2/2 +import './dep.js'; + +console.log('main'); diff --git a/test/form/samples/pure-comment-scenarios-complex/_expected.js b/test/form/samples/pure-comment-scenarios-complex/_expected.js index 11dd422687e..bc4b8984dce 100644 --- a/test/form/samples/pure-comment-scenarios-complex/_expected.js +++ b/test/form/samples/pure-comment-scenarios-complex/_expected.js @@ -1,5 +1,6 @@ // pure top-level IIFE will be dropped + // pure top-level IIFE assigned to unreferenced var will not be dropped global.iife1 = /*@__PURE__*/(function() { console.log("iife1"); diff --git a/test/form/samples/remove-treeshaken-banners/_expected.js b/test/form/samples/remove-treeshaken-banners/_expected.js index 054d5981ded..41986884c32 100644 --- a/test/form/samples/remove-treeshaken-banners/_expected.js +++ b/test/form/samples/remove-treeshaken-banners/_expected.js @@ -1,4 +1,5 @@ // dep included banner: included + console.log('dep included'); // dep included footer: included diff --git a/test/form/samples/render-removed-statements/_expected.js b/test/form/samples/render-removed-statements/_expected.js index 6f8e622701a..707551fa6aa 100644 --- a/test/form/samples/render-removed-statements/_expected.js +++ b/test/form/samples/render-removed-statements/_expected.js @@ -1,4 +1,5 @@ /* header retained */ + /* lead retained */ console.log(2); // trail retained console.log(2); // trail retained