diff --git a/.changeset/fast-toes-act.md b/.changeset/fast-toes-act.md new file mode 100644 index 0000000000..121d5d4a71 --- /dev/null +++ b/.changeset/fast-toes-act.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: properly assign trailing comments diff --git a/packages/svelte/src/compiler/phases/1-parse/acorn.js b/packages/svelte/src/compiler/phases/1-parse/acorn.js index 071e39421f..32be464013 100644 --- a/packages/svelte/src/compiler/phases/1-parse/acorn.js +++ b/packages/svelte/src/compiler/phases/1-parse/acorn.js @@ -104,18 +104,42 @@ function get_comment_handlers(source) { next(); if (comments[0]) { - const parent = path.at(-1); + const parent = /** @type {any} */ (path.at(-1)); + if (parent === undefined || node.end !== parent.end) { const slice = source.slice(node.end, comments[0].start); - - if (/^[,) \t]*$/.test(slice)) { + const is_last_in_body = + ((parent?.type === 'BlockStatement' || parent?.type === 'Program') && + parent.body.indexOf(node) === parent.body.length - 1) || + (parent?.type === 'ArrayExpression' && + parent.elements.indexOf(node) === parent.elements.length - 1) || + (parent?.type === 'ObjectExpression' && + parent.properties.indexOf(node) === parent.properties.length - 1); + + if (is_last_in_body) { + // Special case: There can be multiple trailing comments after the last node in a block, + // and they can be separated by newlines + let end = node.end; + + while (comments.length) { + const comment = comments[0]; + if (parent && comment.start >= parent.end) break; + + (node.trailingComments ||= []).push(comment); + comments.shift(); + end = comment.end; + } + } else if (node.end <= comments[0].start && /^[,) \t]*$/.test(slice)) { node.trailingComments = [/** @type {CommentWithLocation} */ (comments.shift())]; } } } } }); - if (comments.length > 0) { + + // Special case: Trailing comments after the root node (which can only happen for expression tags or for Program nodes). + // Adding them ensures that we can later detect the end of the expression tag correctly. + if (comments.length > 0 && (comments[0].start >= ast.end || ast.type === 'Program')) { (ast.trailingComments ||= []).push(...comments.splice(0)); } } diff --git a/packages/svelte/tests/parser-legacy/samples/javascript-comments/input.svelte b/packages/svelte/tests/parser-legacy/samples/javascript-comments/input.svelte index 5300667984..35a9125cb9 100644 --- a/packages/svelte/tests/parser-legacy/samples/javascript-comments/input.svelte +++ b/packages/svelte/tests/parser-legacy/samples/javascript-comments/input.svelte @@ -5,15 +5,37 @@ /** a comment */ function asd() { - + foo; // trailing + /* leading comment 1 */ + /* leading comment 2 */ + /* leading comment 3 */ + bar; + /* trailing comment 1 */ + /* trailing comment 2 */ + /* trailing comment 3 */ } + + const array = [ + // leading comment 1 + // leading comment 2 + 1, // trailing comment 1 + /* trailing comment 2 */ + ]; + + const object = { + // leading comment 1 + // leading comment 2 + a: 1, // trailing comment 1 + /* trailing comment 2 */ + };