Repository: sveltejs/svelte (JavaScript)
Task type: Refactoring

Issue:
Proposal: `dev: true` only affects runtime warnings and errors
Right now, compiling with `dev: true` causes the compiler to emit a bunch of code to display additional runtime warnings and errors, to assist with debugging - and it also enables a compile-time warning for empty blocks. As far as I can tell, the empty blocks warning is the only compiler-time thing it affects.

This seems weird, and I think it would be nicer if `dev: true` _only_ affected runtime things. This would mean that the empty block compile-time warning would always be emitted - so this issues can go along with #2040, which makes it simpler to suppress specific warnings at compile time.


Discussion:

Solution patch:
diff --git a/src/Stats.ts b/src/Stats.ts
--- a/src/Stats.ts
+++ b/src/Stats.ts
@@ -26,8 +26,6 @@ function collapseTimings(timings) {
 }
 
 export default class Stats {
-	onwarn: (warning: Warning) => void;
-
 	startTime: number;
 	currentTiming: Timing;
 	currentChildren: Timing[];
@@ -35,15 +33,11 @@ export default class Stats {
 	stack: Timing[];
 	warnings: Warning[];
 
-	constructor({ onwarn }: {
-		onwarn: (warning: Warning) => void
-	}) {
+	constructor() {
 		this.startTime = now();
 		this.stack = [];
 		this.currentChildren = this.timings = [];
 
-		this.onwarn = onwarn;
-
 		this.warnings = [];
 	}
 
@@ -114,6 +108,5 @@ export default class Stats {
 
 	warn(warning) {
 		this.warnings.push(warning);
-		this.onwarn(warning);
 	}
 }
diff --git a/src/compile/index.ts b/src/compile/index.ts
--- a/src/compile/index.ts
+++ b/src/compile/index.ts
@@ -54,11 +54,7 @@ function get_name(filename) {
 export default function compile(source: string, options: CompileOptions = {}) {
 	options = assign({ generate: 'dom', dev: false }, options);
 
-	const stats = new Stats({
-		onwarn: options.onwarn
-			? (warning: Warning) => options.onwarn(warning, default_onwarn)
-			: default_onwarn
-	});
+	const stats = new Stats();
 
 	let ast: Ast;
 
diff --git a/src/compile/nodes/shared/Node.ts b/src/compile/nodes/shared/Node.ts
--- a/src/compile/nodes/shared/Node.ts
+++ b/src/compile/nodes/shared/Node.ts
@@ -49,7 +49,6 @@ export default class Node {
 	}
 
 	warnIfEmptyBlock() {
-		if (!this.component.compileOptions.dev) return;
 		if (!/Block$/.test(this.type) || !this.children) return;
 		if (this.children.length > 1) return;
 
diff --git a/src/interfaces.ts b/src/interfaces.ts
--- a/src/interfaces.ts
+++ b/src/interfaces.ts
@@ -60,8 +60,6 @@ export interface CompileOptions {
 	css?: boolean;
 
 	preserveComments?: boolean | false;
-
-	onwarn?: (warning: Warning, default_onwarn?: (warning: Warning) => void) => void;
 }
 
 export interface Visitor {


Test patch:
diff --git a/test/css/index.js b/test/css/index.js
--- a/test/css/index.js
+++ b/test/css/index.js
@@ -2,7 +2,7 @@ import * as assert from 'assert';
 import * as fs from 'fs';
 import { env, normalizeHtml, svelte } from '../helpers.js';
 
-function tryRequire(file) {
+function try_require(file) {
 	try {
 		const mod = require(file);
 		return mod.default || mod;
@@ -12,7 +12,7 @@ function tryRequire(file) {
 	}
 }
 
-function normalizeWarning(warning) {
+function normalize_warning(warning) {
 	warning.frame = warning.frame
 		.replace(/^\n/, '')
 		.replace(/^\t+/gm, '')
@@ -49,47 +49,30 @@ describe('css', () => {
 		}
 
 		(solo ? it.only : skip ? it.skip : it)(dir, () => {
-			const config = tryRequire(`./samples/${dir}/_config.js`) || {};
+			const config = try_require(`./samples/${dir}/_config.js`) || {};
 			const input = fs
 				.readFileSync(`test/css/samples/${dir}/input.svelte`, 'utf-8')
 				.replace(/\s+$/, '');
 
-			const expectedWarnings = (config.warnings || []).map(normalizeWarning);
-			const domWarnings = [];
-			const ssrWarnings = [];
+			const expected_warnings = (config.warnings || []).map(normalize_warning);
 
 			const dom = svelte.compile(
 				input,
-				Object.assign(config, {
-					format: 'cjs',
-					onwarn: warning => {
-						domWarnings.push(warning);
-					}
-				})
+				Object.assign(config, { format: 'cjs' })
 			);
 
-			assert.deepEqual(dom.stats.warnings, domWarnings);
-
 			const ssr = svelte.compile(
 				input,
-				Object.assign(config, {
-					format: 'cjs',
-					generate: 'ssr',
-					onwarn: warning => {
-						ssrWarnings.push(warning);
-					}
-				})
+				Object.assign(config, { format: 'cjs', generate: 'ssr' })
 			);
 
-			assert.deepEqual(dom.stats.warnings, domWarnings);
-
 			assert.equal(dom.css.code, ssr.css.code);
 
-			assert.deepEqual(
-				domWarnings.map(normalizeWarning),
-				ssrWarnings.map(normalizeWarning)
-			);
-			assert.deepEqual(domWarnings.map(normalizeWarning), expectedWarnings);
+			const dom_warnings = dom.stats.warnings.map(normalize_warning);
+			const ssr_warnings = ssr.stats.warnings.map(normalize_warning);
+
+			assert.deepEqual(dom_warnings, ssr_warnings);
+			assert.deepEqual(dom_warnings.map(normalize_warning), expected_warnings);
 
 			fs.writeFileSync(`test/css/samples/${dir}/_actual.css`, dom.css.code);
 			const expected = {
diff --git a/test/validator/index.js b/test/validator/index.js
--- a/test/validator/index.js
+++ b/test/validator/index.js
@@ -18,42 +18,32 @@ describe("validate", () => {
 			const config = loadConfig(`./validator/samples/${dir}/_config.js`);
 
 			const input = fs.readFileSync(`test/validator/samples/${dir}/input.svelte`, "utf-8").replace(/\s+$/, "");
-			const expectedWarnings = tryToLoadJson(`test/validator/samples/${dir}/warnings.json`) || [];
-			const expectedErrors = tryToLoadJson(`test/validator/samples/${dir}/errors.json`);
+			const expected_warnings = tryToLoadJson(`test/validator/samples/${dir}/warnings.json`) || [];
+			const expected_errors = tryToLoadJson(`test/validator/samples/${dir}/errors.json`);
 
 			let error;
 
 			try {
-				const warnings = [];
-
 				const { stats } = svelte.compile(input, {
-					onwarn(warning) {
-						const { code, message, pos, start, end } = warning;
-						warnings.push({ code, message, pos, start, end });
-					},
 					dev: config.dev,
 					legacy: config.legacy,
 					generate: false
 				});
 
-				assert.equal(stats.warnings.length, warnings.length);
-				stats.warnings.forEach((full, i) => {
-					const lite = warnings[i];
-					assert.deepEqual({
-						code: full.code,
-						message: full.message,
-						pos: full.pos,
-						start: full.start,
-						end: full.end
-					}, lite);
-				});
+				const warnings = stats.warnings.map(w => ({
+					code: w.code,
+					message: w.message,
+					pos: w.pos,
+					start: w.start,
+					end: w.end
+				}));
 
-				assert.deepEqual(warnings, expectedWarnings);
+				assert.deepEqual(warnings, expected_warnings);
 			} catch (e) {
 				error = e;
 			}
 
-			const expected = expectedErrors && expectedErrors[0];
+			const expected = expected_errors && expected_errors[0];
 
 			if (error || expected) {
 				if (error && !expected) {
diff --git a/test/validator/samples/empty-block-dev/_config.js b/test/validator/samples/empty-block-dev/_config.js
deleted file mode 100644
--- a/test/validator/samples/empty-block-dev/_config.js
+++ /dev/null
@@ -1,3 +0,0 @@
-export default {
-	dev: true
-};
\ No newline at end of file
diff --git a/test/validator/samples/empty-block-prod/input.svelte b/test/validator/samples/empty-block-prod/input.svelte
deleted file mode 100644
--- a/test/validator/samples/empty-block-prod/input.svelte
+++ /dev/null
@@ -1,5 +0,0 @@
-{#each things as thing}
-
-{/each}
-
-{#each things as thing}{/each}
\ No newline at end of file
diff --git a/test/validator/samples/empty-block-prod/warnings.json b/test/validator/samples/empty-block-prod/warnings.json
deleted file mode 100644
--- a/test/validator/samples/empty-block-prod/warnings.json
+++ /dev/null
@@ -1 +0,0 @@
-[]
\ No newline at end of file
diff --git a/test/validator/samples/empty-block-dev/input.svelte b/test/validator/samples/empty-block/input.svelte
similarity index 100%
rename from test/validator/samples/empty-block-dev/input.svelte
rename to test/validator/samples/empty-block/input.svelte
diff --git a/test/validator/samples/empty-block-dev/warnings.json b/test/validator/samples/empty-block/warnings.json
similarity index 100%
rename from test/validator/samples/empty-block-dev/warnings.json
rename to test/validator/samples/empty-block/warnings.json