Repository: sveltejs/svelte (JavaScript)
Task type: Bug Fix

Issue:
++count.value produce undefined
**Describe the bug**
Seems if we try to increase some object property with increment operator before the operand Svelte produces undefined value in ctx. Interesting that this would work fine if we use increment operator as postfix or if the value is not an object.

**To Reproduce**
[REPL](https://svelte.dev/repl/4a36e029739649a88848359693076b26?version=3.18.1)


Discussion:

Solution patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,6 +9,7 @@
 * Permit reserved keywords as destructuring keys in `{#each}` ([#4372](https://github.com/sveltejs/svelte/issues/4372))
 * Disallow reserved keywords in `{expressions}` ([#4372](https://github.com/sveltejs/svelte/issues/4372))
 * Fix code generation error with precedence of arrow functions ([#4384](https://github.com/sveltejs/svelte/issues/4384))
+* Fix invalidation in expressions like `++foo.bar` ([#4393](https://github.com/sveltejs/svelte/issues/4393))
 
 ## 3.18.1
 
diff --git a/src/compiler/compile/render_dom/invalidate.ts b/src/compiler/compile/render_dom/invalidate.ts
--- a/src/compiler/compile/render_dom/invalidate.ts
+++ b/src/compiler/compile/render_dom/invalidate.ts
@@ -49,7 +49,7 @@ export function invalidate(renderer: Renderer, scope: Scope, node: Node, names:
 			const pass_value = (
 				extra_args.length > 0 ||
 				(node.type === 'AssignmentExpression' && node.left.type !== 'Identifier') ||
-				(node.type === 'UpdateExpression' && !node.prefix)
+				(node.type === 'UpdateExpression' && (!node.prefix || node.argument.type !== 'Identifier'))
 			);
 
 			if (pass_value) {


Test patch:
diff --git a/test/runtime/samples/instrumentation-update-expression/_config.js b/test/runtime/samples/instrumentation-update-expression/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/instrumentation-update-expression/_config.js
@@ -0,0 +1,31 @@
+export default {
+	html: `
+		<p>0</p>
+		<button>foo++</button>
+		<button>++foo</button>
+		<p>0</p>
+		<button>bar.bar++</button>
+		<button>++bar.bar</button>
+	`,
+	async test({ assert, target, window }) {
+		const [foo, bar] = target.querySelectorAll('p');
+		const [button1, button2, button3, button4] = target.querySelectorAll('button');
+		const event = new window.MouseEvent('click');
+
+		await button1.dispatchEvent(event);
+		assert.equal(foo.innerHTML, '1');
+		assert.equal(bar.innerHTML, '0');
+
+		await button2.dispatchEvent(event);
+		assert.equal(foo.innerHTML, '2');
+		assert.equal(bar.innerHTML, '0');
+
+		await button3.dispatchEvent(event);
+		assert.equal(foo.innerHTML, '2');
+		assert.equal(bar.innerHTML, '1');
+
+		await button4.dispatchEvent(event);
+		assert.equal(foo.innerHTML, '2');
+		assert.equal(bar.innerHTML, '2');
+	}
+};
diff --git a/test/runtime/samples/instrumentation-update-expression/main.svelte b/test/runtime/samples/instrumentation-update-expression/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/instrumentation-update-expression/main.svelte
@@ -0,0 +1,14 @@
+<script>
+	let foo = 0;
+	let bar = { bar: 0 };
+</script>
+
+<p>{foo}</p>
+
+<button on:click={() => foo++}>foo++</button>
+<button on:click={() => ++foo}>++foo</button>
+
+<p>{bar.bar}</p>
+
+<button on:click={() => bar.bar++}>bar.bar++</button>
+<button on:click={() => ++bar.bar}>++bar.bar</button>