Repository: sveltejs/svelte (JavaScript)
Date: 2018-12-23 19:29:52+00:00
Task type: Bug Fix

Issue:
Erroneous missing data warnings
Missing data warnings shouldn't be emitted if a prop was provided, even if it equals `null` or `undefined`: [REPL](https://v3.svelte.technology/repl?version=3.0.0-alpha8&gist=1a7796ea08f2c20115c4e0b2b1e87254)


Issue discussion:

Solution patch:
diff --git a/src/compile/render-dom/index.ts b/src/compile/render-dom/index.ts
--- a/src/compile/render-dom/index.ts
+++ b/src/compile/render-dom/index.ts
@@ -131,10 +131,10 @@ export default function dom(
 		if (expected.length) {
 			dev_props_check = deindent`
 				const { ctx } = this.$$;
+				const props = ${options.customElement ? `this.attributes` : `options.props || {}`};
 				${expected.map(name => deindent`
-
-				if (ctx.${name} === undefined${options.customElement && ` && !('${name}' in this.attributes)`}) {
-					console.warn("<${component.tag}> was created without expected data property '${name}'");
+				if (ctx.${name} === undefined && !('${name}' in props)) {
+					console.warn("<${component.tag}> was created without expected prop '${name}'");
 				}`)}
 			`;
 		}


Test patch:
diff --git a/test/custom-elements/samples/no-missing-prop-warnings/test.js b/test/custom-elements/samples/no-missing-prop-warnings/test.js
--- a/test/custom-elements/samples/no-missing-prop-warnings/test.js
+++ b/test/custom-elements/samples/no-missing-prop-warnings/test.js
@@ -12,7 +12,7 @@ export default function (target) {
 	target.innerHTML = '<my-app foo=yes />';
 
 	assert.equal(warnings.length, 1);
-	assert.equal(warnings[0], `<my-app> was created without expected data property 'bar'`);
+	assert.equal(warnings[0], `<my-app> was created without expected prop 'bar'`);
 
 	console.warn = warn;
 }
\ No newline at end of file
diff --git a/test/js/samples/debug-empty/expected.js b/test/js/samples/debug-empty/expected.js
--- a/test/js/samples/debug-empty/expected.js
+++ b/test/js/samples/debug-empty/expected.js
@@ -70,8 +70,9 @@ class SvelteComponent extends SvelteComponentDev {
 		init(this, options, instance, create_fragment, safe_not_equal);
 
 		const { ctx } = this.$$;
-		if (ctx.name === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'name'");
+		const props = options.props || {};
+		if (ctx.name === undefined && !('name' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'name'");
 		}
 	}
 
diff --git a/test/js/samples/debug-foo-bar-baz-things/expected.js b/test/js/samples/debug-foo-bar-baz-things/expected.js
--- a/test/js/samples/debug-foo-bar-baz-things/expected.js
+++ b/test/js/samples/debug-foo-bar-baz-things/expected.js
@@ -158,17 +158,18 @@ class SvelteComponent extends SvelteComponentDev {
 		init(this, options, instance, create_fragment, safe_not_equal);
 
 		const { ctx } = this.$$;
-		if (ctx.things === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'things'");
+		const props = options.props || {};
+		if (ctx.things === undefined && !('things' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'things'");
 		}
-		if (ctx.foo === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'foo'");
+		if (ctx.foo === undefined && !('foo' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'foo'");
 		}
-		if (ctx.bar === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'bar'");
+		if (ctx.bar === undefined && !('bar' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'bar'");
 		}
-		if (ctx.baz === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'baz'");
+		if (ctx.baz === undefined && !('baz' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'baz'");
 		}
 	}
 
diff --git a/test/js/samples/debug-foo/expected.js b/test/js/samples/debug-foo/expected.js
--- a/test/js/samples/debug-foo/expected.js
+++ b/test/js/samples/debug-foo/expected.js
@@ -156,11 +156,12 @@ class SvelteComponent extends SvelteComponentDev {
 		init(this, options, instance, create_fragment, safe_not_equal);
 
 		const { ctx } = this.$$;
-		if (ctx.things === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'things'");
+		const props = options.props || {};
+		if (ctx.things === undefined && !('things' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'things'");
 		}
-		if (ctx.foo === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'foo'");
+		if (ctx.foo === undefined && !('foo' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'foo'");
 		}
 	}
 
diff --git a/test/js/samples/dev-warning-missing-data-computed/expected.js b/test/js/samples/dev-warning-missing-data-computed/expected.js
--- a/test/js/samples/dev-warning-missing-data-computed/expected.js
+++ b/test/js/samples/dev-warning-missing-data-computed/expected.js
@@ -76,8 +76,9 @@ class SvelteComponent extends SvelteComponentDev {
 		init(this, options, instance, create_fragment, safe_not_equal);
 
 		const { ctx } = this.$$;
-		if (ctx.foo === undefined) {
-			console.warn("<SvelteComponent> was created without expected data property 'foo'");
+		const props = options.props || {};
+		if (ctx.foo === undefined && !('foo' in props)) {
+			console.warn("<SvelteComponent> was created without expected prop 'foo'");
 		}
 	}
 
diff --git a/test/runtime/samples/dev-warning-missing-data-binding/_config.js b/test/runtime/samples/dev-warning-missing-data-binding/_config.js
--- a/test/runtime/samples/dev-warning-missing-data-binding/_config.js
+++ b/test/runtime/samples/dev-warning-missing-data-binding/_config.js
@@ -4,6 +4,6 @@ export default {
 	},
 
 	warnings: [
-		`<Main$> was created without expected data property 'value'`
+		`<Main$> was created without expected prop 'value'`
 	]
 };
diff --git a/test/runtime/samples/dev-warning-missing-data-component/Foo.html b/test/runtime/samples/dev-warning-missing-data-component/Foo.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/Foo.html
@@ -0,0 +1 @@
+<div>{x} {y}</div>
\ No newline at end of file
diff --git a/test/runtime/samples/dev-warning-missing-data-component/_config.js b/test/runtime/samples/dev-warning-missing-data-component/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/_config.js
@@ -0,0 +1,9 @@
+export default {
+	compileOptions: {
+		dev: true
+	},
+
+	warnings: [
+		`<Foo$> was created without expected prop 'y'`
+	]
+};
diff --git a/test/runtime/samples/dev-warning-missing-data-component/main.html b/test/runtime/samples/dev-warning-missing-data-component/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dev-warning-missing-data-component/main.html
@@ -0,0 +1,5 @@
+<script>
+	import Foo from './Foo.html';
+</script>
+
+<Foo x={undefined}/>
\ No newline at end of file
diff --git a/test/runtime/samples/dev-warning-missing-data/_config.js b/test/runtime/samples/dev-warning-missing-data/_config.js
--- a/test/runtime/samples/dev-warning-missing-data/_config.js
+++ b/test/runtime/samples/dev-warning-missing-data/_config.js
@@ -4,7 +4,7 @@ export default {
 	},
 
 	warnings: [
-		`<Main$> was created without expected data property 'foo'`,
-		`<Main$> was created without expected data property 'bar'`
+		`<Main$> was created without expected prop 'foo'`,
+		`<Main$> was created without expected prop 'bar'`
 	]
 };