mirror of https://github.com/sveltejs/svelte
Fix: SvelteSet's forEach, isDisjointFrom, isSubsetOf, isSupersetOf, difference, intersection, symmetricDifference, and union methods operate on an empty parent Set instead of the actual values stored in the #sources Map.
This commit fixes the issue reported at packages/svelte/src/reactivity/set.js:96
## Bug Explanation
The `SvelteSet` class was refactored to store values only in the `#sources` Map (where `Source<boolean>` values indicate presence/absence) instead of calling `super.add()` to store values in the parent `Set`. The constructor was changed from:
```javascript
super(value); // Old: values stored in parent Set
```
To:
```javascript
super(); // New: parent Set is empty
if (value) {
for (var element of value) {
sources.set(element, this.#source(true)); // Values stored only in #sources
}
}
```
However, the `#init()` method was not updated to reflect this change. It still uses `set_proto[method].apply(this, v)` which calls Set prototype methods on `this` (the SvelteSet instance). Since the parent Set is now always empty, these methods operate on an empty set and return incorrect results:
- `forEach` iterates over nothing
- `isDisjointFrom` always returns true (empty set is disjoint from everything)
- `isSubsetOf` always returns true (empty set is subset of everything)
- `isSupersetOf` always returns false for non-empty sets
- `difference`, `intersection`, `symmetricDifference`, `union` all produce incorrect results
## Fix Explanation
The fix materializes the current values into a temporary native `Set` before calling the prototype methods. Since `this.values()` is already implemented to correctly iterate over the `#sources` Map and yield values where the source is truthy, we use it to create the temporary Set:
```javascript
var set = new Set(this.values());
return set_proto[method].apply(set, v); // Now operates on the materialized Set
```
This ensures that:
1. All current values from `#sources` are collected into a proper native Set
2. The Set prototype methods operate on actual data, not an empty Set
3. Reactivity is preserved since `get(this.#version)` is still called before materializing
4. The `values()` method already calls `get(source)` for each source, tracking dependencies properly
Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
Co-authored-by: Rich-Harris <hello@rich-harris.dev>
async-svelte-set-alternative
parent
7176069843
commit
88293b6d5b
Loading…
Reference in new issue