fix: serialize input default values during SSR (#18733)

Alternative to #18452

---------

Co-authored-by: svelte-triage-bot <team@svelte.com>
pull/18754/head
Simon H 4 weeks ago committed by GitHub
parent b2c22ab66d
commit b580455c9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: serialize input default values during server rendering

@ -80,6 +80,14 @@ export function build_element_attributes(node, context, transform) {
) {
events_to_capture.add(attribute.name);
}
} else if (
node.type === 'RegularElement' &&
node.name === 'input' &&
(attribute.name === 'defaultValue' || attribute.name === 'defaultChecked')
) {
attributes.push(attribute);
// deopt to spread at runtime, where we can handle interaction of value/defaultValue etc
has_spread = true;
// the defaultValue/defaultChecked properties don't exist as attributes
} else if (attribute.name !== 'defaultValue' && attribute.name !== 'defaultChecked') {
if (attribute.name === 'class') {

@ -146,8 +146,10 @@ export function attributes(attrs, css_hash, classes, styles, flags = 0) {
const is_html = (flags & ELEMENT_IS_NAMESPACED) === 0;
const lowercase = (flags & ELEMENT_PRESERVE_ATTRIBUTE_CASE) === 0;
const is_input = (flags & ELEMENT_IS_INPUT) !== 0;
const names = Object.keys(attrs);
for (name of Object.keys(attrs)) {
outer: for (let i = 0; i < names.length; i++) {
name = names[i];
// omit functions, internal svelte properties and invalid attribute names
if (typeof attrs[name] === 'function') continue;
if (name[0] === '$' && name[1] === '$') continue; // faster than name.startsWith('$$')
@ -163,8 +165,13 @@ export function attributes(attrs, css_hash, classes, styles, flags = 0) {
if (is_input) {
if (name === 'defaultvalue' || name === 'defaultchecked') {
// value/checked takes precedence over defaultValue/defaultChecked
name = name === 'defaultvalue' ? 'value' : 'checked';
if (attrs[name]) continue;
if (name in attrs) continue;
// We're checking prior entries aswell because "name in attrs" is not enough as the attributes may have different casing
for (let j = 0; j < names.length; j++) {
if (names[j].toLowerCase() === name) continue outer;
}
}
}

@ -0,0 +1,3 @@
import { test } from '../../test';
export default test({});

@ -0,0 +1,6 @@
<input value="hello" />
<input type="checkbox" checked />
<input value="spread" checked />
<input value="" />
<input value="" />
<input value="" />

@ -0,0 +1,10 @@
<script>
const props = { defaultValue: 'spread', defaultChecked: true };
</script>
<input defaultValue="hello" />
<input type="checkbox" defaultChecked />
<input {...props} />
<input {...props} value="" checked={false} />
<input value="" checked={false} {...props} />
<input {...props} {...{ VALUE: '', CHECKED: false }} />
Loading…
Cancel
Save