Repository: sveltejs/svelte (JavaScript)
Date: 2019-12-10 22:59:05+00:00
Task type: Bug Fix

Issue:
Slot with props doesn't propergate changes
**Describe the bug**
If a slot that passes a value back contains another slot then any changes to the value will not propagate through.

**To Reproduce**
[Here's a repl](https://svelte.dev/repl/14a72260fda84ddcab25aea7c3f4c993?version=3.16.0). *Outer.svelte* renders a slot and passes `text='first'` then updates it to `'second'`. *Inner.svelte* simply renders a slot. It should render `first first` then after a second change to `second second` but it instead changes to `second first` showing that the inner slot is never notified of the change. 

**Severity**
At work I'm re-writting a very large application in svelte. I'm running into this bug frequently do to how we handle state. This very much needs to be fixed before we can push to production.



Issue discussion:

Solution patch:
diff --git a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
--- a/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
+++ b/src/compiler/compile/render_dom/wrappers/InlineComponent/index.ts
@@ -182,11 +182,9 @@ export default class InlineComponentWrapper extends Wrapper {
 			});
 		});
 
-		const non_let_dependencies = Array.from(fragment_dependencies).filter(name => !this.node.scope.is_let(name));
-
 		const dynamic_attributes = this.node.attributes.filter(a => a.get_dependencies().length > 0);
 
-		if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || non_let_dependencies.length > 0)) {
+		if (!uses_spread && (dynamic_attributes.length > 0 || this.node.bindings.length > 0 || fragment_dependencies.size > 0)) {
 			updates.push(b`const ${name_changes} = {};`);
 		}
 
@@ -266,9 +264,9 @@ export default class InlineComponentWrapper extends Wrapper {
 			}
 		}
 
-		if (non_let_dependencies.length > 0) {
+		if (fragment_dependencies.size > 0) {
 			updates.push(b`
-				if (${renderer.dirty(non_let_dependencies)}) {
+				if (${renderer.dirty(Array.from(fragment_dependencies))}) {
 					${name_changes}.$$scope = { dirty: #dirty, ctx: #ctx };
 				}`);
 		}


Test patch:
diff --git a/test/runtime/samples/component-slot-let-in-slot/Inner.svelte b/test/runtime/samples/component-slot-let-in-slot/Inner.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/component-slot-let-in-slot/Inner.svelte
@@ -0,0 +1 @@
+<slot/>
diff --git a/test/runtime/samples/component-slot-let-in-slot/Outer.svelte b/test/runtime/samples/component-slot-let-in-slot/Outer.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/component-slot-let-in-slot/Outer.svelte
@@ -0,0 +1,5 @@
+<script>
+	export let prop
+</script>
+
+<slot value={prop} />
diff --git a/test/runtime/samples/component-slot-let-in-slot/_config.js b/test/runtime/samples/component-slot-let-in-slot/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/component-slot-let-in-slot/_config.js
@@ -0,0 +1,12 @@
+export default {
+	props: {
+		prop: 'a',
+	},
+
+	html: 'a',
+
+	test({ assert, component, target }) {
+		component.prop = 'b';
+		assert.htmlEqual( target.innerHTML, 'b' );
+	}
+};
diff --git a/test/runtime/samples/component-slot-let-in-slot/main.svelte b/test/runtime/samples/component-slot-let-in-slot/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/component-slot-let-in-slot/main.svelte
@@ -0,0 +1,10 @@
+<script>
+	import Outer from './Outer.svelte'
+	import Inner from './Inner.svelte'
+
+	export let prop
+</script>
+
+<Outer {prop} let:value>
+	<Inner>{value}</Inner>
+</Outer>