async-svelte-set-alternative
Rich Harris 2 days ago
parent 40f05ab9d3
commit 2c2bc766e9

@ -2,7 +2,8 @@
import { DEV } from 'esm-env';
import { source, set, state, increment } from '../internal/client/reactivity/sources.js';
import { label, tag } from '../internal/client/dev/tracing.js';
import { get, update_version } from '../internal/client/runtime.js';
import { active_effect, get, untrack, update_version } from '../internal/client/runtime.js';
import { async_mode_flag } from '../internal/flags/index.js';
var read_methods = ['forEach', 'isDisjointFrom', 'isSubsetOf', 'isSupersetOf'];
var set_like_methods = ['difference', 'intersection', 'symmetricDifference', 'union'];
@ -47,8 +48,8 @@ var inited = false;
export class SvelteSet extends Set {
/** @type {Map<T, Source<boolean>>} */
#sources = new Map();
#version = state(0);
#size = state(0);
/** @type {Source<Set<T>>} */
#items = state(new Set());
#update_version = update_version || -1;
/**
@ -57,19 +58,10 @@ export class SvelteSet extends Set {
constructor(value) {
super();
if (DEV) {
// If the value is invalid then the native exception will fire here
value = new Set(value);
tag(this.#version, 'SvelteSet version');
tag(this.#size, 'SvelteSet.size');
}
this.#items = state(new Set(value))
if (value) {
for (var element of value) {
super.add(element);
}
this.#size.v = super.size;
if (DEV) {
tag(this.#items, 'SvelteSet items');
}
if (!inited) this.#init();
@ -98,7 +90,7 @@ export class SvelteSet extends Set {
for (const method of read_methods) {
// @ts-ignore
proto[method] = function (...v) {
get(this.#version);
get(this.#items);
// @ts-ignore
return set_proto[method].apply(this, v);
};
@ -107,7 +99,7 @@ export class SvelteSet extends Set {
for (const method of set_like_methods) {
// @ts-ignore
proto[method] = function (...v) {
get(this.#version);
get(this.#items);
// @ts-ignore
var set = /** @type {Set<T>} */ (set_proto[method].apply(this, v));
return new SvelteSet(set);
@ -117,19 +109,18 @@ export class SvelteSet extends Set {
/** @param {T} value */
has(value) {
var has = super.has(value);
var sources = this.#sources;
var s = sources.get(value);
if (s === undefined) {
if (!has) {
if (active_effect === null && (!async_mode_flag || !untrack(() => get(this.#items)).has(value))) {
// If the value doesn't exist, track the version in case it's added later
// but don't create sources willy-nilly to track all possible values
get(this.#version);
get(this.#items);
return false;
}
s = this.#source(true);
s = this.#source((get(this.#items)).has(value));
if (DEV) {
tag(s, `SvelteSet has(${label(value)})`);
@ -138,16 +129,22 @@ export class SvelteSet extends Set {
sources.set(value, s);
}
get(s);
return has;
return get(s);
}
/** @param {T} value */
add(value) {
if (!super.has(value)) {
super.add(value);
set(this.#size, super.size);
increment(this.#version);
if (!get(this.#items).has(value)) {
const clone = new Set(get(this.#items));
clone.add(value);
set(this.#items, clone);
}
var s = this.#sources.get(value);
if (s !== undefined) {
set(s, true);
}
return this;
@ -155,7 +152,7 @@ export class SvelteSet extends Set {
/** @param {T} value */
delete(value) {
var deleted = super.delete(value);
var has = get(this.#items).has(value);
var sources = this.#sources;
var s = sources.get(value);
@ -164,20 +161,24 @@ export class SvelteSet extends Set {
set(s, false);
}
if (deleted) {
set(this.#size, super.size);
increment(this.#version);
if (has) {
const clone = new Set(get(this.#items));
clone.delete(value);
set(this.#items, clone);
}
return deleted;
return has;
}
clear() {
if (super.size === 0) {
if (get(this.#items).size === 0) {
return;
}
// Clear first, so we get nice console.log outputs with $inspect
super.clear();
set(this.#items, new Set());
var sources = this.#sources;
for (var s of sources.values()) {
@ -185,8 +186,6 @@ export class SvelteSet extends Set {
}
sources.clear();
set(this.#size, 0);
increment(this.#version);
}
keys() {
@ -194,20 +193,18 @@ export class SvelteSet extends Set {
}
values() {
get(this.#version);
return super.values();
return get(this.#items).values();
}
entries() {
get(this.#version);
return super.entries();
return get(this.#items).entries();
}
[Symbol.iterator]() {
return this.keys();
return this.values();
}
get size() {
return get(this.#size);
return get(this.#items).size;
}
}

Loading…
Cancel
Save