Repository: sveltejs/svelte (JavaScript)
Date: 2017-12-10 02:06:00+00:00
Task type: Bug Fix

Issue:
<:Component> Inside other tag mount to null
Hi, thank for such wonderful project

just stumble upon Dynamic component bugs.
provided [REPL](https://svelte.technology/repl?version=1.46.0&gist=90b93d44b6713125767cd4941378325f) of bug

when <:Component> inside other 
```html
<div>
<:Component {view}></:Component>
</div>
```

switching to other type causing null error as compiled code mount to `null.parentNode`

```js
m: function mount(target, anchor) {
    insertNode(h1, target, anchor);
    insertNode(text_1, target, anchor);
    insertNode(div, target, anchor);
    if (switch_instance) switch_instance._mount(div, null);
},

p: function update(changed, state) {
    if (switch_value !== (switch_value = state.view)) {
        if (switch_instance) switch_instance.destroy();

        if (switch_value) {
            switch_instance = new switch_value(switch_props(state));
            switch_instance._fragment.c();
            switch_instance._mount(null.parentNode, null);
        }
    }
},
```


Issue discussion:

Solution patch:
diff --git a/src/generators/nodes/Component.ts b/src/generators/nodes/Component.ts
--- a/src/generators/nodes/Component.ts
+++ b/src/generators/nodes/Component.ts
@@ -289,6 +289,8 @@ export default class Component extends Node {
 				`if (${name}) ${name}._mount(${parentNode || '#target'}, ${parentNode ? 'null' : 'anchor'});`
 			);
 
+			const updateMountNode = this.getUpdateMountNode(anchor);
+
 			block.builders.update.addBlock(deindent`
 				if (${switch_vars.value} !== (${switch_vars.value} = ${snippet})) {
 					if (${name}) ${name}.destroy();
@@ -298,7 +300,7 @@ export default class Component extends Node {
 						${name}._fragment.c();
 
 						${this.children.map(child => remount(generator, child, name))}
-						${name}._mount(${anchor}.parentNode, ${anchor});
+						${name}._mount(${updateMountNode}, ${anchor});
 
 						${eventHandlers.map(handler => deindent`
 							${name}.on("${handler.name}", ${handler.var});


Test patch:
diff --git a/test/runtime/samples/dynamic-component-inside-element/Bar.html b/test/runtime/samples/dynamic-component-inside-element/Bar.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-inside-element/Bar.html
@@ -0,0 +1 @@
+<p>{{x}}, therefore Bar</p>
\ No newline at end of file
diff --git a/test/runtime/samples/dynamic-component-inside-element/Foo.html b/test/runtime/samples/dynamic-component-inside-element/Foo.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-inside-element/Foo.html
@@ -0,0 +1 @@
+<p>{{x}}, therefore Foo</p>
\ No newline at end of file
diff --git a/test/runtime/samples/dynamic-component-inside-element/_config.js b/test/runtime/samples/dynamic-component-inside-element/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-inside-element/_config.js
@@ -0,0 +1,19 @@
+export default {
+	data: {
+		x: true
+	},
+
+	html: `
+		<div><p>true, therefore Foo</p></div>
+	`,
+
+	test(assert, component, target) {
+		component.set({
+			x: false
+		});
+
+		assert.htmlEqual(target.innerHTML, `
+			<div><p>false, therefore Bar</p></div>
+		`);
+	}
+};
\ No newline at end of file
diff --git a/test/runtime/samples/dynamic-component-inside-element/main.html b/test/runtime/samples/dynamic-component-inside-element/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/dynamic-component-inside-element/main.html
@@ -0,0 +1,14 @@
+<div>
+	<:Component { x ? Foo : Bar } x='{{x}}'/>
+</div>
+
+<script>
+	import Foo from './Foo.html';
+	import Bar from './Bar.html';
+
+	export default {
+		data() {
+			return { Foo, Bar };
+		}
+	};
+</script>
\ No newline at end of file