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
pull/15967/head
Gautier Ben Aïm 4 months ago committed by GitHub
parent 21d5448ab7
commit de8094910d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
"svelte": patch
---
Warn when an invalid `<select multiple>` value is given

@ -200,6 +200,19 @@ Consider the following code:
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
### select_multiple_invalid_value
```
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.
```
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.
To silence the warning, ensure that `value`:
- is an array for an explicit selection
- is `null` or `undefined` to keep the selection as is
### state_proxy_equality_mismatch
```

@ -168,6 +168,17 @@ Consider the following code:
To fix it, either create callback props to communicate changes, or mark `person` as [`$bindable`]($bindable).
## select_multiple_invalid_value
> 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.
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.
To silence the warning, ensure that `value`:
- is an array for an explicit selection
- is `null` or `undefined` to keep the selection as is
## state_proxy_equality_mismatch
> Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results

@ -2,6 +2,8 @@ import { effect } from '../../../reactivity/effects.js';
import { listen_to_event_and_reset_event } from './shared.js';
import { untrack } from '../../../runtime.js';
import { is } from '../../../proxy.js';
import { is_array } from '../../../../shared/utils.js';
import * as w from '../../../warnings.js';
/**
* Selects the correct option(s) (depending on whether this is a multiple select)
@ -12,6 +14,17 @@ import { is } from '../../../proxy.js';
*/
export function select_option(select, value, mounting) {
if (select.multiple) {
// If value is null or undefined, keep the selection as is
if (value == undefined) {
return;
}
// If not an array, warn and keep the selection as is
if (!is_array(value)) {
return w.select_multiple_invalid_value();
}
// Otherwise, update the selection
return select_options(select, value);
}
@ -124,14 +137,12 @@ export function bind_select_value(select, get, set = get) {
}
/**
* @template V
* @param {HTMLSelectElement} select
* @param {V} value
* @param {unknown[]} value
*/
function select_options(select, value) {
for (var option of select.options) {
// @ts-ignore
option.selected = ~value.indexOf(get_option_value(option));
option.selected = value.includes(get_option_value(option));
}
}

@ -158,6 +158,17 @@ export function ownership_invalid_mutation(name, location, prop, parent) {
}
}
/**
* 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.
*/
export function select_multiple_invalid_value() {
if (DEV) {
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);
} else {
console.warn(`https://svelte.dev/e/select_multiple_invalid_value`);
}
}
/**
* Reactive `$state(...)` proxies and the values they proxy have different identities. Because of this, comparisons with `%operator%` will produce unexpected results
* @param {string} operator

@ -0,0 +1,7 @@
import { test } from '../../test';
export default test({
warnings: [
'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.'
]
});

@ -0,0 +1,9 @@
<select multiple value={null}>
<option>option</option>
</select>
<select multiple value={undefined}>
<option>option</option>
</select>
<select multiple value={123}>
<option>option</option>
</select>
Loading…
Cancel
Save