Skip to content

Commit de80949

Browse files
authored
fix(14815): warn when an invalid <select multiple> value is given (#14816)
* fix(14815): warn when an invalid <select multiple> value is given * Create nervous-stingrays-travel.md
1 parent 21d5448 commit de80949

File tree

7 files changed

+71
-4
lines changed

7 files changed

+71
-4
lines changed
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+
Warn when an invalid `<select multiple>` value is given

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,19 @@ Consider the following code:
200200
201201
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
202202
203+
### select_multiple_invalid_value
204+
205+
```
206+
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.
207+
```
208+
209+
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.
210+
211+
To silence the warning, ensure that `value`:
212+
213+
- is an array for an explicit selection
214+
- is `null` or `undefined` to keep the selection as is
215+
203216
### state_proxy_equality_mismatch
204217
205218
```

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,17 @@ Consider the following code:
168168
169169
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
170170
171+
## select_multiple_invalid_value
172+
173+
> 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.
174+
175+
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.
176+
177+
To silence the warning, ensure that `value`:
178+
179+
- is an array for an explicit selection
180+
- is `null` or `undefined` to keep the selection as is
181+
171182
## state_proxy_equality_mismatch
172183
173184
> 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
@@ -158,6 +158,17 @@ export function ownership_invalid_mutation(name, location, prop, parent) {
158158
}
159159
}
160160

161+
/**
162+
* 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.
163+
*/
164+
export function select_multiple_invalid_value() {
165+
if (DEV) {
166+
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);
167+
} else {
168+
console.warn(`https://svelte.dev/e/select_multiple_invalid_value`);
169+
}
170+
}
171+
161172
/**
162173
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
163174
* @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)