diff --git a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
index ca35ea84db49..e219f86aa1c0 100644
--- a/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
+++ b/src/compiler/compile/render_dom/wrappers/Element/Attribute.ts
@@ -171,7 +171,7 @@ export default class AttributeWrapper extends BaseAttributeWrapper {
}
if (is_indirectly_bound_value) {
- const update_value = b`${element.var}.value = ${element.var}.__value;`;
+ const update_value = b`@set_input_value(${element.var}, ${element.var}.__value);`;
block.chunks.hydrate.push(update_value);
updater = b`
diff --git a/test/js/samples/select-dynamic-value/expected.js b/test/js/samples/select-dynamic-value/expected.js
index cd1ab1d81242..1d0896d6e822 100644
--- a/test/js/samples/select-dynamic-value/expected.js
+++ b/test/js/samples/select-dynamic-value/expected.js
@@ -8,7 +8,8 @@ import {
insert,
noop,
safe_not_equal,
- select_option
+ select_option,
+ set_input_value
} from "svelte/internal";
function create_fragment(ctx) {
@@ -24,9 +25,9 @@ function create_fragment(ctx) {
option1 = element("option");
option1.textContent = "2";
option0.__value = "1";
- option0.value = option0.__value;
+ set_input_value(option0, option0.__value);
option1.__value = "2";
- option1.value = option1.__value;
+ set_input_value(option1, option1.__value);
},
m(target, anchor) {
insert(target, select, anchor);
diff --git a/test/runtime/samples/binding-select-null-placeholder/_config.js b/test/runtime/samples/binding-select-null-placeholder/_config.js
new file mode 100644
index 000000000000..b453e6869a95
--- /dev/null
+++ b/test/runtime/samples/binding-select-null-placeholder/_config.js
@@ -0,0 +1,28 @@
+const items = [ { id: 'a' }, { id: 'b' } ];
+
+export default {
+ props: {
+ foo: null,
+ items
+ },
+
+ test({ assert, component, target }) {
+ const select = target.querySelector( 'select' );
+ const options = target.querySelectorAll( 'option' );
+
+ assert.equal( options[0].selected, true );
+ assert.equal( options[0].disabled, true );
+ assert.equal( options[1].selected, false );
+ assert.equal( options[1].disabled, false );
+
+ // placeholder option value must be blank string for native required field validation
+ assert.equal( options[0].value, '' );
+ assert.equal( select.checkValidity(), false );
+
+ component.foo = items[0];
+
+ assert.equal( options[0].selected, false );
+ assert.equal( options[1].selected, true );
+ assert.equal( select.checkValidity(), true );
+ }
+};
diff --git a/test/runtime/samples/binding-select-null-placeholder/main.svelte b/test/runtime/samples/binding-select-null-placeholder/main.svelte
new file mode 100644
index 000000000000..65cab994957c
--- /dev/null
+++ b/test/runtime/samples/binding-select-null-placeholder/main.svelte
@@ -0,0 +1,11 @@
+
+
+