Repository: sveltejs/svelte (JavaScript)
Date: 2019-09-30 21:43:22+00:00
Task type: Bug Fix

Issue:
Compound operators don't work in reactive statements
**Describe the bug**
Compound operators don't work in reactive statements, I suspect this has to do with the fact that there are no variables the assignment depends on. So it is not run when the value of the left hand side of the operator changes.

**To Reproduce**

[REPL](https://svelte.dev/repl/80525ce4fe0c4b07adb498ed2040c806?version=3.12.1)

**Expected behavior**
In the REPL example when clicking the button the first time count should be 2 and after pressing the button a second time the count should be 6.

**Severity**

Slightly annoying but easily worked around by not using compound operators.



Issue discussion:
I haven't checked this, but I believe what needs to be done for there is to make the identifier in `UpdateExpression`s [here](https://github.com/sveltejs/svelte/blob/5d8ca9f07db206556c6634746384c7778e12e8cb/src/compiler/compile/Component.ts#L1272) also be added as a dependency.

Solution patch:
diff --git a/src/compiler/compile/Component.ts b/src/compiler/compile/Component.ts
--- a/src/compiler/compile/Component.ts
+++ b/src/compiler/compile/Component.ts
@@ -1265,10 +1265,16 @@ export default class Component {
 						}
 
 						if (node.type === 'AssignmentExpression') {
-							extract_identifiers(get_object(node.left)).forEach(node => {
+							const left = get_object(node.left);
+
+							extract_identifiers(left).forEach(node => {
 								assignee_nodes.add(node);
 								assignees.add(node.name);
 							});
+
+							if (node.operator !== '=') {
+								dependencies.add(left.name);
+							}
 						} else if (node.type === 'UpdateExpression') {
 							const identifier = get_object(node.argument);
 							assignees.add(identifier.name);


Test patch:
diff --git a/test/runtime/samples/reactive-compound-operator/_config.js b/test/runtime/samples/reactive-compound-operator/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/reactive-compound-operator/_config.js
@@ -0,0 +1,27 @@
+export default {
+	html: `
+		<button>+1</button>
+		<p>count: 0</p>
+	`,
+
+	async test({ assert, component, target, window }) {
+		const click = new window.MouseEvent('click');
+		const button = target.querySelector('button');
+
+		await button.dispatchEvent(click);
+
+		assert.equal(component.x, 2);
+		assert.htmlEqual(target.innerHTML, `
+			<button>+1</button>
+			<p>count: 2</p>
+		`);
+
+		await button.dispatchEvent(click);
+
+		assert.equal(component.x, 6);
+		assert.htmlEqual(target.innerHTML, `
+			<button>+1</button>
+			<p>count: 6</p>
+		`);
+	}
+};
diff --git a/test/runtime/samples/reactive-compound-operator/main.svelte b/test/runtime/samples/reactive-compound-operator/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/reactive-compound-operator/main.svelte
@@ -0,0 +1,8 @@
+<script>
+	export let x = 0;
+
+	$: x *= 2;
+</script>
+
+<button on:click='{() => x += 1}'>+1</button>
+<p>count: {x}</p>
diff --git a/test/runtime/samples/reactive-update-expression/_config.js b/test/runtime/samples/reactive-update-expression/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/reactive-update-expression/_config.js
@@ -0,0 +1,29 @@
+export default {
+	html: `
+	<button>+1</button>
+	<p>count: 1</p>
+	`,
+
+	async test({ assert, component, target, window }) {
+		const click = new window.MouseEvent('click');
+		const button = target.querySelector('button');
+
+		assert.equal(component.x, 1);
+
+		await button.dispatchEvent(click);
+
+		assert.equal(component.x, 3);
+		assert.htmlEqual(target.innerHTML, `
+			<button>+1</button>
+			<p>count: 3</p>
+		`);
+
+		await button.dispatchEvent(click);
+
+		assert.equal(component.x, 5);
+		assert.htmlEqual(target.innerHTML, `
+			<button>+1</button>
+			<p>count: 5</p>
+		`);
+	}
+};
diff --git a/test/runtime/samples/reactive-update-expression/main.svelte b/test/runtime/samples/reactive-update-expression/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/reactive-update-expression/main.svelte
@@ -0,0 +1,12 @@
+<script>
+	export let x = 0;
+
+  $: x++;
+
+  function onClick() {
+    x += 1;
+  }
+</script>
+
+<button on:click='{() => x += 1}'>+1</button>
+<p>count: {x}</p>