Skip to content

Commit 73b3cf7

Browse files
authored
fix: treat undefined and null the same for the initial input value (#14562)
* fix: treat `undefined` and `null` the same for the initial input value Fixes #14558 * test * same for checked
1 parent 1ffce92 commit 73b3cf7

File tree

4 files changed

+161
-66
lines changed

4 files changed

+161
-66
lines changed

.changeset/cool-clocks-film.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: treat `undefined` and `null` the same for the initial input value

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

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,19 @@ export function remove_input_defaults(input) {
6060
export function set_value(element, value) {
6161
// @ts-expect-error
6262
var attributes = (element.__attributes ??= {});
63+
6364
if (
64-
attributes.value === (attributes.value = value) ||
65+
attributes.value ===
66+
(attributes.value =
67+
// treat null and undefined the same for the initial value
68+
value ?? undefined) ||
6569
// @ts-expect-error
6670
// `progress` elements always need their value set when its `0`
6771
(element.value === value && (value !== 0 || element.nodeName !== 'PROGRESS'))
68-
)
72+
) {
6973
return;
74+
}
75+
7076
// @ts-expect-error
7177
element.value = value;
7278
}
@@ -79,7 +85,15 @@ export function set_checked(element, checked) {
7985
// @ts-expect-error
8086
var attributes = (element.__attributes ??= {});
8187

82-
if (attributes.checked === (attributes.checked = checked)) return;
88+
if (
89+
attributes.checked ===
90+
(attributes.checked =
91+
// treat null and undefined the same for the initial value
92+
checked ?? undefined)
93+
) {
94+
return;
95+
}
96+
8397
// @ts-expect-error
8498
element.checked = checked;
8599
}

packages/svelte/tests/runtime-runes/samples/form-default-value/_config.js

Lines changed: 74 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@ export default test({
3737
const after_reset = [];
3838

3939
const reset = /** @type {HTMLInputElement} */ (target.querySelector('input[type=reset]'));
40-
const [test1, test2, test3, test4, test5, test12] = target.querySelectorAll('div');
41-
const [test6, test7, test8, test9] = target.querySelectorAll('select');
40+
const [test1, test2, test3, test4, test5, test6, test7, test14] =
41+
target.querySelectorAll('div');
42+
const [test8, test9, test10, test11] = target.querySelectorAll('select');
4243
const [
4344
test1_span,
4445
test2_span,
@@ -48,7 +49,9 @@ export default test({
4849
test6_span,
4950
test7_span,
5051
test8_span,
51-
test9_span
52+
test9_span,
53+
test10_span,
54+
test11_span
5255
] = target.querySelectorAll('span');
5356

5457
{
@@ -74,8 +77,8 @@ export default test({
7477
{
7578
/** @type {NodeListOf<HTMLInputElement | HTMLTextAreaElement>} */
7679
const inputs = test2.querySelectorAll('input, textarea');
77-
check_inputs(inputs, 'value', 'y');
78-
assert.htmlEqual(test2_span.innerHTML, 'y y y y');
80+
check_inputs(inputs, 'value', 'x');
81+
assert.htmlEqual(test2_span.innerHTML, 'x x x x');
7982

8083
for (const input of inputs) {
8184
set_input(input, 'value', 'foo');
@@ -85,125 +88,164 @@ export default test({
8588
assert.htmlEqual(test2_span.innerHTML, 'foo foo foo foo');
8689

8790
after_reset.push(() => {
91+
console.log('-------------');
8892
check_inputs(inputs, 'value', 'x');
8993
assert.htmlEqual(test2_span.innerHTML, 'x x x x');
9094
});
9195
}
9296

97+
{
98+
/** @type {NodeListOf<HTMLInputElement | HTMLTextAreaElement>} */
99+
const inputs = test3.querySelectorAll('input, textarea');
100+
check_inputs(inputs, 'value', 'y');
101+
assert.htmlEqual(test3_span.innerHTML, 'y y y y');
102+
103+
for (const input of inputs) {
104+
set_input(input, 'value', 'foo');
105+
}
106+
flushSync();
107+
check_inputs(inputs, 'value', 'foo');
108+
assert.htmlEqual(test3_span.innerHTML, 'foo foo foo foo');
109+
110+
after_reset.push(() => {
111+
check_inputs(inputs, 'value', 'x');
112+
assert.htmlEqual(test3_span.innerHTML, 'x x x x');
113+
});
114+
}
115+
93116
{
94117
/** @type {NodeListOf<HTMLInputElement>} */
95-
const inputs = test3.querySelectorAll('input');
118+
const inputs = test4.querySelectorAll('input');
96119
check_inputs(inputs, 'checked', true);
97-
assert.htmlEqual(test3_span.innerHTML, 'true true');
120+
assert.htmlEqual(test4_span.innerHTML, 'true true');
98121

99122
for (const input of inputs) {
100123
set_input(input, 'checked', false);
101124
}
102125
flushSync();
103126
check_inputs(inputs, 'checked', false);
104-
assert.htmlEqual(test3_span.innerHTML, 'false false');
127+
assert.htmlEqual(test4_span.innerHTML, 'false false');
105128

106129
after_reset.push(() => {
107130
check_inputs(inputs, 'checked', true);
108-
assert.htmlEqual(test3_span.innerHTML, 'true true');
131+
assert.htmlEqual(test4_span.innerHTML, 'true true');
109132
});
110133
}
111134

112135
{
113136
/** @type {NodeListOf<HTMLInputElement>} */
114-
const inputs = test4.querySelectorAll('input');
137+
const inputs = test5.querySelectorAll('input');
138+
check_inputs(inputs, 'checked', true);
139+
assert.htmlEqual(test5_span.innerHTML, 'true true');
140+
141+
for (const input of inputs) {
142+
set_input(input, 'checked', false);
143+
}
144+
flushSync();
115145
check_inputs(inputs, 'checked', false);
116-
assert.htmlEqual(test4_span.innerHTML, 'false false');
146+
assert.htmlEqual(test5_span.innerHTML, 'false false');
117147

118148
after_reset.push(() => {
119149
check_inputs(inputs, 'checked', true);
120-
assert.htmlEqual(test4_span.innerHTML, 'true true');
150+
assert.htmlEqual(test5_span.innerHTML, 'true true');
121151
});
122152
}
123153

124154
{
125155
/** @type {NodeListOf<HTMLInputElement>} */
126-
const inputs = test5.querySelectorAll('input');
156+
const inputs = test6.querySelectorAll('input');
157+
check_inputs(inputs, 'checked', false);
158+
assert.htmlEqual(test6_span.innerHTML, 'false false');
159+
160+
after_reset.push(() => {
161+
check_inputs(inputs, 'checked', true);
162+
assert.htmlEqual(test6_span.innerHTML, 'true true');
163+
});
164+
}
165+
166+
{
167+
/** @type {NodeListOf<HTMLInputElement>} */
168+
const inputs = test7.querySelectorAll('input');
127169
check_inputs(inputs, 'checked', true);
128-
assert.htmlEqual(test5_span.innerHTML, 'true');
170+
assert.htmlEqual(test7_span.innerHTML, 'true');
129171

130172
after_reset.push(() => {
131173
check_inputs(inputs, 'checked', false);
132-
assert.htmlEqual(test5_span.innerHTML, 'false');
174+
assert.htmlEqual(test7_span.innerHTML, 'false');
133175
});
134176
}
135177

136178
{
137179
/** @type {NodeListOf<HTMLOptionElement>} */
138-
const options = test6.querySelectorAll('option');
180+
const options = test8.querySelectorAll('option');
139181
check_inputs(options, 'selected', [false, true, false]);
140-
assert.htmlEqual(test6_span.innerHTML, 'b');
182+
assert.htmlEqual(test8_span.innerHTML, 'b');
141183

142184
select_option(options[2]);
143185
flushSync();
144186
check_inputs(options, 'selected', [false, false, true]);
145-
assert.htmlEqual(test6_span.innerHTML, 'c');
187+
assert.htmlEqual(test8_span.innerHTML, 'c');
146188

147189
after_reset.push(() => {
148190
check_inputs(options, 'selected', [false, true, false]);
149-
assert.htmlEqual(test6_span.innerHTML, 'b');
191+
assert.htmlEqual(test8_span.innerHTML, 'b');
150192
});
151193
}
152194

153195
{
154196
/** @type {NodeListOf<HTMLOptionElement>} */
155-
const options = test7.querySelectorAll('option');
197+
const options = test9.querySelectorAll('option');
156198
check_inputs(options, 'selected', [false, true, false]);
157-
assert.htmlEqual(test7_span.innerHTML, 'b');
199+
assert.htmlEqual(test9_span.innerHTML, 'b');
158200

159201
select_option(options[2]);
160202
flushSync();
161203
check_inputs(options, 'selected', [false, false, true]);
162-
assert.htmlEqual(test7_span.innerHTML, 'c');
204+
assert.htmlEqual(test9_span.innerHTML, 'c');
163205

164206
after_reset.push(() => {
165207
check_inputs(options, 'selected', [false, true, false]);
166-
assert.htmlEqual(test7_span.innerHTML, 'b');
208+
assert.htmlEqual(test9_span.innerHTML, 'b');
167209
});
168210
}
169211

170212
{
171213
/** @type {NodeListOf<HTMLOptionElement>} */
172-
const options = test8.querySelectorAll('option');
214+
const options = test10.querySelectorAll('option');
173215
check_inputs(options, 'selected', [false, false, true]);
174-
assert.htmlEqual(test8_span.innerHTML, 'c');
216+
assert.htmlEqual(test10_span.innerHTML, 'c');
175217

176218
select_option(options[0]);
177219
flushSync();
178220
check_inputs(options, 'selected', [true, false, false]);
179-
assert.htmlEqual(test8_span.innerHTML, 'a');
221+
assert.htmlEqual(test10_span.innerHTML, 'a');
180222

181223
after_reset.push(() => {
182224
check_inputs(options, 'selected', [false, true, false]);
183-
assert.htmlEqual(test8_span.innerHTML, 'b');
225+
assert.htmlEqual(test10_span.innerHTML, 'b');
184226
});
185227
}
186228

187229
{
188230
/** @type {NodeListOf<HTMLOptionElement>} */
189-
const options = test9.querySelectorAll('option');
231+
const options = test11.querySelectorAll('option');
190232
check_inputs(options, 'selected', [false, false, true]);
191-
assert.htmlEqual(test9_span.innerHTML, 'c');
233+
assert.htmlEqual(test11_span.innerHTML, 'c');
192234

193235
select_option(options[0]);
194236
flushSync();
195237
check_inputs(options, 'selected', [true, false, false]);
196-
assert.htmlEqual(test9_span.innerHTML, 'a');
238+
assert.htmlEqual(test11_span.innerHTML, 'a');
197239

198240
after_reset.push(() => {
199241
check_inputs(options, 'selected', [false, true, false]);
200-
assert.htmlEqual(test9_span.innerHTML, 'b');
242+
assert.htmlEqual(test11_span.innerHTML, 'b');
201243
});
202244
}
203245

204246
{
205247
/** @type {NodeListOf<HTMLInputElement | HTMLTextAreaElement>} */
206-
const inputs = test12.querySelectorAll('input, textarea');
248+
const inputs = test14.querySelectorAll('input, textarea');
207249
assert.equal(inputs[0].value, 'x');
208250
assert.equal(/** @type {HTMLInputElement} */ (inputs[1]).checked, true);
209251
assert.equal(inputs[2].value, 'x');

0 commit comments

Comments
 (0)