Repository: sveltejs/svelte (JavaScript)
Date: 2021-08-27 14:41:37+00:00
Task type: Bug Fix

Issue:
Selected <select> value disappears in svelte 3.42.2
### Describe the bug

`<select>` elements that should have a selected option appear blank after the update to 3.42.2

This only happens (to me at least) if the select is inside a component that has store props passed to it.

I am aware of the change proposed in #6126 and implemented by #6170 but it seems that this is not the root cause of this issue but rather brings to light a underlying problem.

I have tried adding `console.log(value)` to `select_option` function in [svelte/src/runtime/internal/dom.ts#L536](https://github.com/sveltejs/svelte/blob/edf8844ae67662d677997df8e43ef2376fa2abbd/src/runtime/internal/dom.ts#L536)
and It logged `undefined` with the code shown in the REPL.  


### Reproduction

https://svelte.dev/repl/6ab9575cda57439a83652811ecfd7d8c?version=3.42.2

### Logs

_No response_

### System Info

```shell
Brave Version 1.26.74 Chromium: 91.0.4472.124 (Official Build) (64-bit) on Arch Linux
```


### Severity

blocking an upgrade


Issue discussion:
I just randomly stumbled across this. The disappearing stops once you remove `{...$restProps}`. Maybe this helps in some way
Sorry for the wrong mention.
Please ignore the mentioned.

Solution patch:
diff --git a/src/compiler/compile/render_dom/wrappers/Element/index.ts b/src/compiler/compile/render_dom/wrappers/Element/index.ts
--- a/src/compiler/compile/render_dom/wrappers/Element/index.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/index.ts
@@ -674,7 +674,7 @@ export default class ElementWrapper extends Wrapper {
 				(${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value);
 			`);
 			block.chunks.update.push(b`
-				if (${block.renderer.dirty(Array.from(dependencies))}) (${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value);;
+				if (${block.renderer.dirty(Array.from(dependencies))} && 'value' in ${data}) (${data}.multiple ? @select_options : @select_option)(${this.var}, ${data}.value);;
 			`);
 		} else if (this.node.name === 'input' && this.attributes.find(attr => attr.node.name === 'value')) {
 			const type = this.node.get_static_attribute_value('type');


Test patch:
diff --git a/test/runtime/samples/spread-element-select-value-undefined/Select.svelte b/test/runtime/samples/spread-element-select-value-undefined/Select.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/Select.svelte
@@ -0,0 +1,12 @@
+<script>
+	export let options = [];
+	export let value = "";
+	export let label = "";
+</script>
+
+<select bind:value {...$$restProps}>
+	{#each options as option}
+		<option>{option}</option>
+	{/each}
+</select>
+<p>{label}</p>
diff --git a/test/runtime/samples/spread-element-select-value-undefined/_config.js b/test/runtime/samples/spread-element-select-value-undefined/_config.js
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/_config.js
@@ -0,0 +1,11 @@
+export default {
+	async test({ assert, component, target, window }) {
+		const select = target.querySelector('select');
+
+		assert.equal(select.value, '1');
+
+		component.label = 'hoge';
+
+		assert.equal(select.value, '1');
+	}
+};
diff --git a/test/runtime/samples/spread-element-select-value-undefined/main.svelte b/test/runtime/samples/spread-element-select-value-undefined/main.svelte
new file mode 100644
--- /dev/null
+++ b/test/runtime/samples/spread-element-select-value-undefined/main.svelte
@@ -0,0 +1,11 @@
+<script>
+	import Select from "./Select.svelte";
+	let value = {
+		a: "1",
+		b: "1",
+	};
+	const options = ["1", "2", "3"];
+	export let label = "test";
+</script>
+
+<Select bind:value={value.a} {options} label={label} />