Repository: sveltejs/svelte (JavaScript)
Date: 2019-01-26 05:07:35+00:00
Task type: Bug Fix

Issue:
await block with nested components does not remove child blocks
When the pending/fulfilled (and maybe catch) blocks of an `await` contains a nested component, the block doesn't get removed when the promise fulfills or is set to a new pending promise.

[REPL](https://v3.svelte.technology/repl?version=3.0.0-alpha18&gist=253f3273c4e581bfc3bebfa89f5757ae)

Alpha 16 works correctly ([repl](https://v3.svelte.technology/repl?version=3.0.0-alpha16&gist=253f3273c4e581bfc3bebfa89f5757ae))


Issue discussion:

Solution patch:
diff --git a/src/internal/await-block.js b/src/internal/await-block.js
--- a/src/internal/await-block.js
+++ b/src/internal/await-block.js
@@ -1,5 +1,5 @@
 import { assign, isPromise } from './utils.js';
-import { group_outros } from './transitions.js';
+import { check_outros, group_outros, on_outro } from './transitions.js';
 import { flush } from '../internal/scheduler.js';
 
 export function handlePromise(promise, info) {
@@ -18,10 +18,12 @@ export function handlePromise(promise, info) {
 				info.blocks.forEach((block, i) => {
 					if (i !== index && block) {
 						group_outros();
-						block.o(() => {
+						on_outro(() => {
 							block.d(1);
 							info.blocks[i] = null;
 						});
+						block.o();
+						check_outros();
 					}
 				});
 			} else {


Test patch:
diff --git a/test/runtime/samples/await-with-components/Widget.html b/test/runtime/samples/await-with-components/Widget.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/await-with-components/Widget.html
@@ -0,0 +1,5 @@
+{value}
+
+<script>
+  export let value = 'Loading...';
+</script>
\ No newline at end of file
diff --git a/test/runtime/samples/await-with-components/_config.js b/test/runtime/samples/await-with-components/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/await-with-components/_config.js
@@ -0,0 +1,29 @@
+export default {
+	async test({ assert, component, target }) {
+		let resolve, reject;
+		let promise = new Promise(ok => resolve = ok);
+
+		component.promise = promise;
+		assert.htmlEqual(target.innerHTML, 'Loading...');
+
+		resolve(42);
+		await promise;
+		assert.htmlEqual(target.innerHTML, '42');
+
+		promise = new Promise((ok, fail) => reject = fail);
+		component.promise = promise;
+		assert.htmlEqual(target.innerHTML, 'Loading...');
+
+		reject(99);
+		await promise.then(null, () => {});
+		assert.htmlEqual(target.innerHTML, '99');
+
+		promise = new Promise(ok => resolve = ok);
+		component.promise = promise;
+		assert.htmlEqual(target.innerHTML, 'Loading...');
+
+		resolve(1);
+		await promise;
+		assert.htmlEqual(target.innerHTML, '1');
+	}
+};
diff --git a/test/runtime/samples/await-with-components/main.html b/test/runtime/samples/await-with-components/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/await-with-components/main.html
@@ -0,0 +1,12 @@
+{#await promise}
+	<Widget />
+{:then result}
+	<Widget value="{result}" />
+{:catch err}
+	<Widget value="{err}" />
+{/await}
+
+<script>
+	import Widget from './Widget.html';
+	export let promise = Promise.resolve();
+</script>
\ No newline at end of file