Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/nervous-stingrays-travel.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

Warn when an invalid `<select multiple>` value is given
13 changes: 13 additions & 0 deletions documentation/docs/98-reference/.generated/client-warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,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

```
Expand Down
11 changes: 11 additions & 0 deletions packages/svelte/messages/client-warnings/warnings.md
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
}

Expand Down Expand Up @@ -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));
}
}

Expand Down
11 changes: 11 additions & 0 deletions packages/svelte/src/internal/client/warnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,17 @@ export function ownership_invalid_mutation(component, owner) {
}
}

/**
* 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
Expand Down
Original file line number Diff line number Diff line change
@@ -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.'
]
});
Original file line number Diff line number Diff line change
@@ -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