Repository: sveltejs/svelte (JavaScript)
Date: 2018-03-02 21:08:00+00:00
Task type: Bug Fix

Issue:
bug with select_block_type function
We have code wich work perfect in 1.54.1 version. But in 1.56 this code not working. 

Exampes:

- [54.1](https://svelte.technology/repl?version=1.54.1&gist=c5fefd4ac9568c773a668237108ad8c1)
- [56](https://svelte.technology/repl?version=1.56.0&gist=c5fefd4ac9568c773a668237108ad8c1)

function select_block_type in new version not get `header` argument
```javascript
function select_block_type(state) {
	if (!header.icon) return create_if_block_2;
	return create_if_block_3;
}
```
bug with select_block_type function
We have code wich work perfect in 1.54.1 version. But in 1.56 this code not working. 

Exampes:

- [54.1](https://svelte.technology/repl?version=1.54.1&gist=c5fefd4ac9568c773a668237108ad8c1)
- [56](https://svelte.technology/repl?version=1.56.0&gist=c5fefd4ac9568c773a668237108ad8c1)

function select_block_type in new version not get `header` argument
```javascript
function select_block_type(state) {
	if (!header.icon) return create_if_block_2;
	return create_if_block_3;
}
```


Issue discussion:
Was just preparing a [REPL](https://svelte.technology/repl?version=1.56.0&gist=9bf16064d22bb098855ee5b1244902a4) about the same problem:

Throws "item is not defined" - seems to happen when using `{{else}}` inside `{{#each}}`. If the `{{else}}` is removed, no error is thrown.

Works fine with 0.55.
It _looks_ like the issue is [right here](https://github.com/sveltejs/svelte/blob/8aaf92aca282a81475964a6460de3f1ed46159f6/src/generators/nodes/IfBlock.ts#L318) (and also [right here](https://github.com/sveltejs/svelte/blob/8aaf92aca282a81475964a6460de3f1ed46159f6/src/generators/nodes/IfBlock.ts#L409)). The code is attempting to use values from `state` without actually retrieving them from the `state` object. I'm taking a peek at this, but all of this code was heavily refactored for 1.56.0 and so I'm not very familiar with it yet.
It looks like you identified the issue, but in case it's helpful I was running into the same problem with `{{else}}` inside `{{#await}}`:  [1.55.1](https://svelte.technology/repl?version=1.55.1&gist=193bc11dba0141344cb5b37f9de50144) vs [1.56.0](https://svelte.technology/repl?version=1.56.0&gist=193bc11dba0141344cb5b37f9de50144). I'm assuming this goes back to the same thing.
Here is the most minimal test case with just a single `{{#each}}` and `{{#if}}`-`{{else}}` I could build: [1.55.1](https://svelte.technology/repl?version=1.55.1&gist=56c3cca04ac1b7b891477e331e0e0234) vs [1.56.0](https://svelte.technology/repl?version=1.56.0&gist=56c3cca04ac1b7b891477e331e0e0234).
Was just preparing a [REPL](https://svelte.technology/repl?version=1.56.0&gist=9bf16064d22bb098855ee5b1244902a4) about the same problem:

Throws "item is not defined" - seems to happen when using `{{else}}` inside `{{#each}}`. If the `{{else}}` is removed, no error is thrown.

Works fine with 0.55.
It _looks_ like the issue is [right here](https://github.com/sveltejs/svelte/blob/8aaf92aca282a81475964a6460de3f1ed46159f6/src/generators/nodes/IfBlock.ts#L318) (and also [right here](https://github.com/sveltejs/svelte/blob/8aaf92aca282a81475964a6460de3f1ed46159f6/src/generators/nodes/IfBlock.ts#L409)). The code is attempting to use values from `state` without actually retrieving them from the `state` object. I'm taking a peek at this, but all of this code was heavily refactored for 1.56.0 and so I'm not very familiar with it yet.
It looks like you identified the issue, but in case it's helpful I was running into the same problem with `{{else}}` inside `{{#await}}`:  [1.55.1](https://svelte.technology/repl?version=1.55.1&gist=193bc11dba0141344cb5b37f9de50144) vs [1.56.0](https://svelte.technology/repl?version=1.56.0&gist=193bc11dba0141344cb5b37f9de50144). I'm assuming this goes back to the same thing.
Here is the most minimal test case with just a single `{{#each}}` and `{{#if}}`-`{{else}}` I could build: [1.55.1](https://svelte.technology/repl?version=1.55.1&gist=56c3cca04ac1b7b891477e331e0e0234) vs [1.56.0](https://svelte.technology/repl?version=1.56.0&gist=56c3cca04ac1b7b891477e331e0e0234).

Solution patch:
diff --git a/src/generators/nodes/IfBlock.ts b/src/generators/nodes/IfBlock.ts
--- a/src/generators/nodes/IfBlock.ts
+++ b/src/generators/nodes/IfBlock.ts
@@ -313,15 +313,12 @@ function compound(
 	const current_block_type = block.getUniqueName(`current_block_type`);
 	const current_block_type_and = hasElse ? '' : `${current_block_type} && `;
 
-	generator.blocks.push(deindent`
+	block.builders.init.addBlock(deindent`
 		function ${select_block_type}(state) {
 			${branches
 				.map(({ condition, block }) => `${condition ? `if (${condition}) ` : ''}return ${block};`)
 				.join('\n')}
 		}
-	`);
-
-	block.builders.init.addBlock(deindent`
 		var ${current_block_type} = ${select_block_type}(state);
 		var ${name} = ${current_block_type_and}${current_block_type}(#component, state);
 	`);


Test patch:
diff --git a/test/js/samples/if-block-no-update/expected-bundle.js b/test/js/samples/if-block-no-update/expected-bundle.js
--- a/test/js/samples/if-block-no-update/expected-bundle.js
+++ b/test/js/samples/if-block-no-update/expected-bundle.js
@@ -189,6 +189,10 @@ var proto = {
 function create_main_fragment(component, state) {
 	var if_block_anchor;
 
+	function select_block_type(state) {
+		if (state.foo) return create_if_block;
+		return create_if_block_1;
+	}
 	var current_block_type = select_block_type(state);
 	var if_block = current_block_type(component, state);
 
@@ -268,11 +272,6 @@ function create_if_block_1(component, state) {
 	};
 }
 
-function select_block_type(state) {
-	if (state.foo) return create_if_block;
-	return create_if_block_1;
-}
-
 function SvelteComponent(options) {
 	init(this, options);
 	this._state = assign({}, options.data);
diff --git a/test/js/samples/if-block-no-update/expected.js b/test/js/samples/if-block-no-update/expected.js
--- a/test/js/samples/if-block-no-update/expected.js
+++ b/test/js/samples/if-block-no-update/expected.js
@@ -4,6 +4,10 @@ import { assign, createComment, createElement, detachNode, init, insertNode, noo
 function create_main_fragment(component, state) {
 	var if_block_anchor;
 
+	function select_block_type(state) {
+		if (state.foo) return create_if_block;
+		return create_if_block_1;
+	}
 	var current_block_type = select_block_type(state);
 	var if_block = current_block_type(component, state);
 
@@ -83,11 +87,6 @@ function create_if_block_1(component, state) {
 	};
 }
 
-function select_block_type(state) {
-	if (state.foo) return create_if_block;
-	return create_if_block_1;
-}
-
 function SvelteComponent(options) {
 	init(this, options);
 	this._state = assign({}, options.data);
diff --git a/test/runtime/samples/if-block-else-in-each/_config.js b/test/runtime/samples/if-block-else-in-each/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/if-block-else-in-each/_config.js
@@ -0,0 +1,9 @@
+export default {
+	data: {
+		array: [true, false],
+	},
+	html: `
+		<div>foo</div>
+		<div>bar</div>
+	`,
+};
diff --git a/test/runtime/samples/if-block-else-in-each/main.html b/test/runtime/samples/if-block-else-in-each/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/if-block-else-in-each/main.html
@@ -0,0 +1,7 @@
+{{#each array as item}}
+	{{#if item}}
+		<div>foo</div>
+	{{else}}
+		<div>bar</div>
+	{{/if}}
+{{/each}}