mirror of https://github.com/sveltejs/svelte
fix: SvelteMap incorrectly handles keys with `undefined` values (#17826)
## Summary
`SvelteMap` had two bugs related to how it checked for key existence
internally:
### 1. `has()` and `get()` returned wrong results for keys with
`undefined` values
Both methods used `super.get(key) !== undefined` to determine if a key
existed before creating a per-key reactive source. This fails for keys
whose value is legitimately `undefined`, causing:
- `has(key)` to return `false` for existing keys with `undefined` values
- `get(key)` to skip creating a per-key source and fall back to tracking
`version`, resulting in over-notification
**Fix:** Replace `super.get(key) !== undefined` with `super.has(key)` in
both `has()` and `get()`, matching the pattern already used in
`SvelteSet`.
### 2. `delete()` skipped reactive updates when a key had no per-key
source
The `size` and `version` reactive updates were inside the `if (s !==
undefined)` block, meaning they only fired when a per-key source existed
(i.e., someone had previously called `has()` or `get()` on that specific
key). If a key was added via the constructor or `set()` but never
individually read, deleting it would not trigger reactive updates for
effects depending on `size` or iterators.
**Fix:** Move `set(this.#size, super.size)` and
`increment(this.#version)` to a separate `if (res)` block so they fire
whenever a key is actually deleted, regardless of whether a per-key
source existed.
### Before fix
```js
const map = new SvelteMap([['foo', undefined]]);
map.has('foo'); // false (should be true)
map.get('foo'); // undefined but tracks version instead of per-key source
```
### After fix
```js
const map = new SvelteMap([['foo', undefined]]);
map.has('foo'); // true
map.get('foo'); // undefined with correct per-key tracking
```
## Test plan
Tests are in `packages/svelte/src/reactivity/map.test.ts`:
- `map.has()` returns `true` for constructor-initialized keys with
`undefined` values
- `map.get()` returns `undefined` with proper per-key reactive tracking
- `map.delete()` triggers `has()`/`get()` reactivity for
undefined-valued keys
- `map.set(key, undefined)` followed by `has()`/`get()` works correctly
- `map.delete()` triggers `size` reactivity for keys that were never
individually read (no per-key source)
- All existing tests pass unchanged
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
pull/17812/head
parent
3fc4bc6774
commit
18db0cab86
@ -0,0 +1,5 @@
|
||||
---
|
||||
'svelte': patch
|
||||
---
|
||||
|
||||
fix: `SvelteMap` incorrectly handles keys with `undefined` values
|
||||
Loading…
Reference in new issue