Skip to content

Commit d590cd8

Browse files
authored
fix: ignore value attribute on select during SSR (#11724)
The value attribute on select elements does nothing - it does not influence the initial value (in SSR that's the job of the `selected` attribute on an option element), updating it does not influence the current value either. Instead of rendering it out and then removing it on hydration (which is costly because the mutation causes work) we just don't render it in SSR. No test/changeset because no change in behavior.
1 parent 6d2f1a4 commit d590cd8

File tree

4 files changed

+22
-18
lines changed

4 files changed

+22
-18
lines changed

packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1990,7 +1990,7 @@ export const template_visitors = {
19901990
child_metadata.bound_contenteditable = true;
19911991
}
19921992

1993-
if (needs_input_reset && (node.name === 'input' || node.name === 'select')) {
1993+
if (needs_input_reset && node.name === 'input') {
19941994
context.state.init.push(b.stmt(b.call('$.remove_input_attr_defaults', context.state.node)));
19951995
}
19961996

packages/svelte/src/compiler/phases/3-transform/server/transform-server.js

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,18 +1851,27 @@ function serialize_element_attributes(node, context) {
18511851

18521852
for (const attribute of node.attributes) {
18531853
if (attribute.type === 'Attribute') {
1854-
if (attribute.name === 'value' && node.name === 'textarea') {
1855-
if (
1856-
attribute.value !== true &&
1857-
attribute.value[0].type === 'Text' &&
1858-
regex_starts_with_newline.test(attribute.value[0].data)
1859-
) {
1860-
// Two or more leading newlines are required to restore the leading newline immediately after `<textarea>`.
1861-
// see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions
1862-
// also see related code in analysis phase
1863-
attribute.value[0].data = '\n' + attribute.value[0].data;
1854+
if (attribute.name === 'value') {
1855+
if (node.name === 'textarea') {
1856+
if (
1857+
attribute.value !== true &&
1858+
attribute.value[0].type === 'Text' &&
1859+
regex_starts_with_newline.test(attribute.value[0].data)
1860+
) {
1861+
// Two or more leading newlines are required to restore the leading newline immediately after `<textarea>`.
1862+
// see https://html.spec.whatwg.org/multipage/syntax.html#element-restrictions
1863+
// also see related code in analysis phase
1864+
attribute.value[0].data = '\n' + attribute.value[0].data;
1865+
}
1866+
content = {
1867+
escape: true,
1868+
expression: serialize_attribute_value(attribute.value, context)
1869+
};
1870+
} else if (node.name !== 'select') {
1871+
// omit value attribute for select elements, it's irrelevant for the initially selected value and has no
1872+
// effect on the selected value after the user interacts with the select element (the value _property_ does, but not the attribute)
1873+
attributes.push(attribute);
18641874
}
1865-
content = { escape: true, expression: serialize_attribute_value(attribute.value, context) };
18661875

18671876
// omit event handlers except for special cases
18681877
} else if (is_event_attribute(attribute)) {

packages/svelte/src/internal/client/dom/elements/attributes.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { LOADING_ATTR_SYMBOL } from '../../constants.js';
1111
/**
1212
* The value/checked attribute in the template actually corresponds to the defaultValue property, so we need
1313
* to remove it upon hydration to avoid a bug when someone resets the form value.
14-
* @param {HTMLInputElement | HTMLSelectElement} dom
14+
* @param {HTMLInputElement} dom
1515
* @returns {void}
1616
*/
1717
export function remove_input_attr_defaults(dom) {

packages/svelte/tests/runtime-legacy/samples/binding-select-late-3/_config.js

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,6 @@ export default test({
1414
<p>selected: two</p>
1515
`,
1616

17-
ssrHtml: `
18-
<select value="two"></select>
19-
<p>selected: two</p>
20-
`,
21-
2217
async test({ assert, component, target }) {
2318
component.items = ['one', 'two', 'three'];
2419

0 commit comments

Comments
 (0)