Repository: sveltejs/svelte (JavaScript)
Date: 2018-03-09 03:03:17+00:00
Task type: Bug Fix

Issue:
Another 1.56 context bug
Via [StackOverflow](https://stackoverflow.com/questions/49119171/event-computed-property-issue/49120647#49120647):

```html
<p><input bind:value=search></p>

{{#each categories.filter(predicate) as category}}
  <!-- the click event should work, right? -->
    <button on:click='console.log(category)'>{{category}}</button>
{{/each}}

<script>
    export default {
        data() {
            return {
                search: '',
                categories: [
                    'animal',
                    'vegetable',
                    'mineral'
                ]
            }
        },
      computed: {
            predicate: search => {
                search = search.toLowerCase();
                return word => word.startsWith(search);
            }
        }
    };
</script>
```

[REPL](https://svelte.technology/repl?version=1.56.1&gist=798be31e79dfbf363a9f7e497557acfb).


Issue discussion:
Poked around in the REPL, dunno if this is helpful but here goes nothing.

https://gist.github.com/tivac/7c74c2b8f8927612b4f057ad16d5e782#file-output-js-L33-L36

`create_main_fragment` is calling `create_each_block` and passing it a `category` and a `category_index` in the `state` object.

https://gist.github.com/tivac/7c74c2b8f8927612b4f057ad16d5e782#file-output-js-L132-L154

`create_each_value` is then setting `button._svelte` to have a `each_value` and `category_index`, even though `state.each_value` doesn't exist. This happens in both the `p` and `h`.

https://gist.github.com/tivac/7c74c2b8f8927612b4f057ad16d5e782#file-output-js-L167-L170

Then when the event handler fires `this._svelte.each_value` is undefined and everything goes real bad.


Solution patch:
diff --git a/src/generators/nodes/EachBlock.ts b/src/generators/nodes/EachBlock.ts
--- a/src/generators/nodes/EachBlock.ts
+++ b/src/generators/nodes/EachBlock.ts
@@ -75,6 +75,7 @@ export default class EachBlock extends Node {
 		}
 
 		this.contextProps = [
+			`${this.block.listName}: ${this.block.listName}`,
 			`${this.context}: ${this.block.listName}[#i]`,
 			`${this.block.indexName}: #i`
 		];


Test patch:
diff --git a/test/js/samples/each-block-changed-check/expected-bundle.js b/test/js/samples/each-block-changed-check/expected-bundle.js
--- a/test/js/samples/each-block-changed-check/expected-bundle.js
+++ b/test/js/samples/each-block-changed-check/expected-bundle.js
@@ -212,6 +212,7 @@ function create_main_fragment(component, state) {
 
 	for (var i = 0; i < comments.length; i += 1) {
 		each_blocks[i] = create_each_block(component, assign({}, state, {
+			comments: comments,
 			comment: comments[i],
 			i: i
 		}));
@@ -244,6 +245,7 @@ function create_main_fragment(component, state) {
 			if (changed.comments || changed.elapsed || changed.time) {
 				for (var i = 0; i < comments.length; i += 1) {
 					var each_context = assign({}, state, {
+						comments: comments,
 						comment: comments[i],
 						i: i
 					});
diff --git a/test/js/samples/each-block-changed-check/expected.js b/test/js/samples/each-block-changed-check/expected.js
--- a/test/js/samples/each-block-changed-check/expected.js
+++ b/test/js/samples/each-block-changed-check/expected.js
@@ -10,6 +10,7 @@ function create_main_fragment(component, state) {
 
 	for (var i = 0; i < comments.length; i += 1) {
 		each_blocks[i] = create_each_block(component, assign({}, state, {
+			comments: comments,
 			comment: comments[i],
 			i: i
 		}));
@@ -42,6 +43,7 @@ function create_main_fragment(component, state) {
 			if (changed.comments || changed.elapsed || changed.time) {
 				for (var i = 0; i < comments.length; i += 1) {
 					var each_context = assign({}, state, {
+						comments: comments,
 						comment: comments[i],
 						i: i
 					});
diff --git a/test/runtime/samples/each-block-array-literal/_config.js b/test/runtime/samples/each-block-array-literal/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/each-block-array-literal/_config.js
@@ -0,0 +1,19 @@
+export default {
+	html: `
+		<button>racoon</button>
+		<button>eagle</button>
+	`,
+
+	test(assert, component, target) {
+		assert.htmlEqual(target.innerHTML,`
+			<button>racoon</button>
+			<button>eagle</button>
+		`);
+
+		const button = target.querySelector('button');
+		const event = new window.MouseEvent('click');
+
+		button.dispatchEvent(event);
+		assert.equal(component.get('clicked'), 'racoon');
+	},
+};
diff --git a/test/runtime/samples/each-block-array-literal/main.html b/test/runtime/samples/each-block-array-literal/main.html
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/each-block-array-literal/main.html
@@ -0,0 +1,11 @@
+{{#each ['racoon', 'eagle'] as animal}}
+	<button on:click="set({clicked: animal})">{{animal}}</button>
+{{/each}}
+
+<script>
+	export default {
+		data: () => ({
+			clicked: null,
+		}),
+	};
+</script>