Repository: sveltejs/svelte (JavaScript) — Bug Fix

Issue:
preserveComments doesn't work
**Describe the bug**
The compiler option `preserveComments: true` does nothing.

**To Reproduce**
See [this repo](https://github.com/bwbroersma/preserve-comments-in-ssr/). With [minimal changes](https://github.com/bwbroersma/preserve-comments-in-ssr/commit/0e873e990e9407984fb4fdf3e021912121b890b6) from the svelte/template. This is [my output with missing comment](https://github.com/bwbroersma/preserve-comments-in-ssr/blob/master/public/build/bundle.js#L76-L79).

**Expected behavior**
Keep the comment in the SSR.

Probably this is because of this todo:
https://github.com/sveltejs/svelte/blob/aabb23cc3427e3c26a497fb23e2880f5a0c11e68/src/compiler/compile/render_ssr/handlers/Comment.ts#L5-L9

**Information about your Svelte project:**
svelte-3.21.0 & rollup.




Discussion:

Resolving patch:
diff --git a/src/compiler/compile/render_ssr/handlers/Comment.ts b/src/compiler/compile/render_ssr/handlers/Comment.ts
--- a/src/compiler/compile/render_ssr/handlers/Comment.ts
+++ b/src/compiler/compile/render_ssr/handlers/Comment.ts
@@ -1,10 +1,8 @@
 import Renderer, { RenderOptions } from '../Renderer';
 import Comment from '../../nodes/Comment';
 
-export default function(_node: Comment, _renderer: Renderer, _options: RenderOptions) {
-	// TODO preserve comments
-
-	// if (options.preserveComments) {
-	// 	renderer.append(`<!--${node.data}-->`);
-	// }
+export default function(node: Comment, renderer: Renderer, options: RenderOptions) {
+	if (options.preserveComments) {
+		renderer.add_string(`<!--${node.data}-->`);
+	}
 }


Test patch:
diff --git a/test/helpers.ts b/test/helpers.ts
--- a/test/helpers.ts
+++ b/test/helpers.ts
@@ -4,7 +4,7 @@ import glob from 'tiny-glob/sync';
 import * as path from 'path';
 import * as fs from 'fs';
 import * as colors from 'kleur';
-export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual, expected, message?) => void };
+export const assert = (assert$1 as unknown) as typeof assert$1 & { htmlEqual: (actual, expected, message?) => void, htmlEqualWithComments: (actual, expected, message?) => void };
 
 // for coverage purposes, we need to test source files,
 // but for sanity purposes, we need to test dist files
@@ -118,6 +118,9 @@ function cleanChildren(node) {
 				node.removeChild(child);
 				child = previous;
 			}
+		} else if (child.nodeType === 8) {
+			// comment
+			// do nothing
 		} else {
 			cleanChildren(child);
 		}
@@ -137,11 +140,11 @@ function cleanChildren(node) {
 	}
 }
 
-export function normalizeHtml(window, html) {
+export function normalizeHtml(window, html, preserveComments = false) {
 	try {
 		const node = window.document.createElement('div');
 		node.innerHTML = html
-			.replace(/<!--.*?-->/g, '')
+			.replace(/(<!--.*?-->)/g, preserveComments ? '$1' : '')
 			.replace(/>[\s\r\n]+</g, '><')
 			.trim();
 		cleanChildren(node);
@@ -162,6 +165,14 @@ export function setupHtmlEqual() {
 			message
 		);
 	};
+	// eslint-disable-next-line no-import-assign
+	assert.htmlEqualWithComments = (actual, expected, message) => {
+		assert.deepEqual(
+			normalizeHtml(window, actual, true),
+			normalizeHtml(window, expected, true),
+			message
+		);
+	};
 }
 
 export function loadConfig(file) {
diff --git a/test/js/samples/ssr-preserve-comments/expected.js b/test/js/samples/ssr-preserve-comments/expected.js
--- a/test/js/samples/ssr-preserve-comments/expected.js
+++ b/test/js/samples/ssr-preserve-comments/expected.js
@@ -3,8 +3,8 @@ import { create_ssr_component } from "svelte/internal";
 
 const Component = create_ssr_component(($$result, $$props, $$bindings, slots) => {
 	return `<div>content</div>
-
+<!-- comment -->
 <div>more content</div>`;
 });
 
-export default Component;
\ No newline at end of file
+export default Component;
diff --git a/test/server-side-rendering/index.ts b/test/server-side-rendering/index.ts
--- a/test/server-side-rendering/index.ts
+++ b/test/server-side-rendering/index.ts
@@ -81,7 +81,9 @@ describe('ssr', () => {
 				if (css.code) fs.writeFileSync(`${dir}/_actual.css`, css.code);
 
 				try {
-					assert.htmlEqual(html, expectedHtml);
+					(compileOptions.preserveComments
+						? assert.htmlEqualWithComments
+						: assert.htmlEqual)(html, expectedHtml);
 				} catch (error) {
 					if (shouldUpdateExpected()) {
 						fs.writeFileSync(`${dir}/_expected.html`, html);
diff --git a/test/server-side-rendering/samples/comment-preserve/_config.js b/test/server-side-rendering/samples/comment-preserve/_config.js
new file mode 100644
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/_config.js
@@ -0,0 +1,5 @@
+export default {
+	compileOptions: {
+		preserveComments: true
+	}
+};
diff --git a/test/server-side-rendering/samples/comment-preserve/_expected.html b/test/server-side-rendering/samples/comment-preserve/_expected.html
new file mode 100644
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/_expected.html
@@ -0,0 +1,3 @@
+<p>before</p>
+<!-- a comment -->
+<p>after</p>
diff --git a/test/server-side-rendering/samples/comment-preserve/main.svelte b/test/server-side-rendering/samples/comment-preserve/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/server-side-rendering/samples/comment-preserve/main.svelte
@@ -0,0 +1,3 @@
+<p>before</p>
+<!-- a comment -->
+<p>after</p>