Skip to content

Commit 1b4cb30

Browse files
committed
fix(14815): warn when an invalid <select multiple> value is given
1 parent 1d773ef commit 1b4cb30

File tree

6 files changed

+66
-4
lines changed

6 files changed

+66
-4
lines changed

documentation/docs/98-reference/.generated/client-warnings.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,19 @@ Consider the following code:
204204
205205
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
206206
207+
### select_multiple_invalid_value
208+
209+
```
210+
The `value` property of a `<select multiple>` element should be an array, but it received a non-array value. The selection will be kept as is.
211+
```
212+
213+
When using `<select multiple value={...}>`, Svelte will mark all selected `<option>` elements as selected by iterating over the array passed to `value`. If `value` is not an array, Svelte will emit this warning and keep the selected options as they are.
214+
215+
To silence the warning, ensure that `value`:
216+
217+
- is an array for an explicit selection
218+
- is `null` or `undefined` to keep the selection as is
219+
207220
### state_proxy_equality_mismatch
208221
209222
```

packages/svelte/messages/client-warnings/warnings.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,17 @@ Consider the following code:
170170
171171
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
172172
173+
## select_multiple_invalid_value
174+
175+
> The `value` property of a `<select multiple>` element should be an array, but it received a non-array value. The selection will be kept as is.
176+
177+
When using `<select multiple value={...}>`, Svelte will mark all selected `<option>` elements as selected by iterating over the array passed to `value`. If `value` is not an array, Svelte will emit this warning and keep the selected options as they are.
178+
179+
To silence the warning, ensure that `value`:
180+
181+
- is an array for an explicit selection
182+
- is `null` or `undefined` to keep the selection as is
183+
173184
## state_proxy_equality_mismatch
174185
175186
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results

packages/svelte/src/internal/client/dom/elements/bindings/select.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ import { effect } from '../../../reactivity/effects.js';
22
import { listen_to_event_and_reset_event } from './shared.js';
33
import { untrack } from '../../../runtime.js';
44
import { is } from '../../../proxy.js';
5+
import { is_array } from '../../../../shared/utils.js';
6+
import * as w from '../../../warnings.js';
57

68
/**
79
* Selects the correct option(s) (depending on whether this is a multiple select)
@@ -12,6 +14,17 @@ import { is } from '../../../proxy.js';
1214
*/
1315
export function select_option(select, value, mounting) {
1416
if (select.multiple) {
17+
// If value is null or undefined, keep the selection as is
18+
if (value == undefined) {
19+
return;
20+
}
21+
22+
// If not an array, warn and keep the selection as is
23+
if (!is_array(value)) {
24+
return w.select_multiple_invalid_value();
25+
}
26+
27+
// Otherwise, update the selection
1528
return select_options(select, value);
1629
}
1730

@@ -124,14 +137,12 @@ export function bind_select_value(select, get, set = get) {
124137
}
125138

126139
/**
127-
* @template V
128140
* @param {HTMLSelectElement} select
129-
* @param {V} value
141+
* @param {unknown[]} value
130142
*/
131143
function select_options(select, value) {
132144
for (var option of select.options) {
133-
// @ts-ignore
134-
option.selected = ~value.indexOf(get_option_value(option));
145+
option.selected = value.includes(get_option_value(option));
135146
}
136147
}
137148

packages/svelte/src/internal/client/warnings.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,17 @@ export function ownership_invalid_mutation(component, owner) {
155155
}
156156
}
157157

158+
/**
159+
* The `value` property of a `<select multiple>` element should be an array, but it received a non-array value. The selection will be kept as is.
160+
*/
161+
export function select_multiple_invalid_value() {
162+
if (DEV) {
163+
console.warn(`%c[svelte] select_multiple_invalid_value\n%cThe \`value\` property of a \`<select multiple>\` element should be an array, but it received a non-array value. The selection will be kept as is.\nhttps://svelte.dev/e/select_multiple_invalid_value`, bold, normal);
164+
} else {
165+
console.warn(`https://svelte.dev/e/select_multiple_invalid_value`);
166+
}
167+
}
168+
158169
/**
159170
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
160171
* @param {string} operator
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
warnings: [
5+
'The `value` property of a `<select multiple>` element should be an array, but it received a non-array value. The selection will be kept as is.'
6+
]
7+
});
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<select multiple value={null}>
2+
<option>option</option>
3+
</select>
4+
<select multiple value={undefined}>
5+
<option>option</option>
6+
</select>
7+
<select multiple value={123}>
8+
<option>option</option>
9+
</select>

0 commit comments

Comments
 (0)