|
|
|
|
@ -3,6 +3,9 @@ import { DEV } from 'esm-env';
|
|
|
|
|
import { set, source, 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 { async_mode_flag } from '../internal/flags/index.js';
|
|
|
|
|
|
|
|
|
|
const MISSING = Symbol('missing');
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* A reactive version of the built-in [`Map`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) object.
|
|
|
|
|
@ -51,10 +54,10 @@ import { get, update_version } from '../internal/client/runtime.js';
|
|
|
|
|
* @extends {Map<K, V>}
|
|
|
|
|
*/
|
|
|
|
|
export class SvelteMap extends Map {
|
|
|
|
|
/** @type {Map<K, Source<number>>} */
|
|
|
|
|
/** @type {Map<K, Source<V>>} */
|
|
|
|
|
#sources = new Map();
|
|
|
|
|
#version = state(0);
|
|
|
|
|
#size = state(0);
|
|
|
|
|
/** @type {Source<Map<K, V>>} */
|
|
|
|
|
#items;
|
|
|
|
|
#update_version = update_version || -1;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -63,19 +66,16 @@ export class SvelteMap extends Map {
|
|
|
|
|
constructor(value) {
|
|
|
|
|
super();
|
|
|
|
|
|
|
|
|
|
if (DEV) {
|
|
|
|
|
// If the value is invalid then the native exception will fire here
|
|
|
|
|
value = new Map(value);
|
|
|
|
|
this.#items = state(new Map(value));
|
|
|
|
|
|
|
|
|
|
tag(this.#version, 'SvelteMap version');
|
|
|
|
|
tag(this.#size, 'SvelteMap.size');
|
|
|
|
|
var sources = this.#sources;
|
|
|
|
|
|
|
|
|
|
for (const [key, value] of this.#items.v) {
|
|
|
|
|
sources.set(key, this.#source(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value) {
|
|
|
|
|
for (var [key, v] of value) {
|
|
|
|
|
super.set(key, v);
|
|
|
|
|
}
|
|
|
|
|
this.#size.v = super.size;
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(this.#items, 'SvelteMap items');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@ -98,24 +98,27 @@ export class SvelteMap extends Map {
|
|
|
|
|
var s = sources.get(key);
|
|
|
|
|
|
|
|
|
|
if (s === undefined) {
|
|
|
|
|
if (super.has(key)) {
|
|
|
|
|
s = this.#source(0);
|
|
|
|
|
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(s, `SvelteMap get(${label(key)})`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sources.set(key, s);
|
|
|
|
|
} else {
|
|
|
|
|
// We should always track the version in case
|
|
|
|
|
// the Set ever gets this value in the future.
|
|
|
|
|
get(this.#version);
|
|
|
|
|
if (!async_mode_flag) {
|
|
|
|
|
// 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.#items);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var items = get(this.#items);
|
|
|
|
|
var value = /** @type {V} */ (items.has(key) ? items.get(key) : (MISSING));
|
|
|
|
|
|
|
|
|
|
s = this.#source(value);
|
|
|
|
|
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(s, `SvelteSet has(${label(value)})`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sources.set(key, s);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get(s);
|
|
|
|
|
return true;
|
|
|
|
|
var value = get(s);
|
|
|
|
|
return value !== MISSING;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -123,8 +126,9 @@ export class SvelteMap extends Map {
|
|
|
|
|
* @param {any} [this_arg]
|
|
|
|
|
*/
|
|
|
|
|
forEach(callbackfn, this_arg) {
|
|
|
|
|
this.#read_all();
|
|
|
|
|
super.forEach(callbackfn, this_arg);
|
|
|
|
|
for (const [key, value] of this.entries()) {
|
|
|
|
|
callbackfn(value, key, this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {K} key */
|
|
|
|
|
@ -133,24 +137,15 @@ export class SvelteMap extends Map {
|
|
|
|
|
var s = sources.get(key);
|
|
|
|
|
|
|
|
|
|
if (s === undefined) {
|
|
|
|
|
if (super.has(key)) {
|
|
|
|
|
s = this.#source(0);
|
|
|
|
|
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(s, `SvelteMap get(${label(key)})`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sources.set(key, s);
|
|
|
|
|
} else {
|
|
|
|
|
// We should always track the version in case
|
|
|
|
|
// the Set ever gets this value in the future.
|
|
|
|
|
get(this.#version);
|
|
|
|
|
return undefined;
|
|
|
|
|
}
|
|
|
|
|
// We should always track the version in case
|
|
|
|
|
// the Set ever gets this value in the future.
|
|
|
|
|
var items = get(this.#items);
|
|
|
|
|
return items.get(key);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get(s);
|
|
|
|
|
return super.get(key);
|
|
|
|
|
var value = get(s);
|
|
|
|
|
|
|
|
|
|
return value === MISSING ? undefined : value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
@ -160,107 +155,86 @@ export class SvelteMap extends Map {
|
|
|
|
|
set(key, value) {
|
|
|
|
|
var sources = this.#sources;
|
|
|
|
|
var s = sources.get(key);
|
|
|
|
|
var prev_res = super.get(key);
|
|
|
|
|
var res = super.set(key, value);
|
|
|
|
|
var version = this.#version;
|
|
|
|
|
|
|
|
|
|
if (s === undefined) {
|
|
|
|
|
s = this.#source(0);
|
|
|
|
|
if (s !== undefined) {
|
|
|
|
|
set(s, value);
|
|
|
|
|
} else {
|
|
|
|
|
sources.set(key, this.#source(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(s, `SvelteMap get(${label(key)})`);
|
|
|
|
|
}
|
|
|
|
|
var items = get(this.#items);
|
|
|
|
|
|
|
|
|
|
sources.set(key, s);
|
|
|
|
|
set(this.#size, super.size);
|
|
|
|
|
increment(version);
|
|
|
|
|
} else if (prev_res !== value) {
|
|
|
|
|
increment(s);
|
|
|
|
|
|
|
|
|
|
// if not every reaction of s is a reaction of version we need to also include version
|
|
|
|
|
var v_reactions = version.reactions === null ? null : new Set(version.reactions);
|
|
|
|
|
var needs_version_increase =
|
|
|
|
|
v_reactions === null ||
|
|
|
|
|
!s.reactions?.every((r) =>
|
|
|
|
|
/** @type {NonNullable<typeof v_reactions>} */ (v_reactions).has(r)
|
|
|
|
|
);
|
|
|
|
|
if (needs_version_increase) {
|
|
|
|
|
increment(version);
|
|
|
|
|
}
|
|
|
|
|
if (!items.has(key)) {
|
|
|
|
|
const clone = new Map(items);
|
|
|
|
|
clone.set(key, value);
|
|
|
|
|
|
|
|
|
|
set(this.#items, clone);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** @param {K} key */
|
|
|
|
|
delete(key) {
|
|
|
|
|
var items = get(this.#items);
|
|
|
|
|
var has = items.has(key);
|
|
|
|
|
var sources = this.#sources;
|
|
|
|
|
var s = sources.get(key);
|
|
|
|
|
var res = super.delete(key);
|
|
|
|
|
|
|
|
|
|
if (s !== undefined) {
|
|
|
|
|
sources.delete(key);
|
|
|
|
|
set(s, -1);
|
|
|
|
|
set(s, /** @type {V} */ (MISSING));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (res) {
|
|
|
|
|
set(this.#size, super.size);
|
|
|
|
|
increment(this.#version);
|
|
|
|
|
if (has) {
|
|
|
|
|
const clone = new Map(items);
|
|
|
|
|
clone.delete(key);
|
|
|
|
|
|
|
|
|
|
set(this.#items, clone);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
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 Map());
|
|
|
|
|
|
|
|
|
|
var sources = this.#sources;
|
|
|
|
|
set(this.#size, 0);
|
|
|
|
|
|
|
|
|
|
for (var s of sources.values()) {
|
|
|
|
|
set(s, -1);
|
|
|
|
|
set(s, /** @type {V} */ (MISSING));
|
|
|
|
|
}
|
|
|
|
|
increment(this.#version);
|
|
|
|
|
|
|
|
|
|
sources.clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#read_all() {
|
|
|
|
|
get(this.#version);
|
|
|
|
|
keys() {
|
|
|
|
|
return get(this.#items).keys();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var sources = this.#sources;
|
|
|
|
|
if (this.#size.v !== sources.size) {
|
|
|
|
|
for (var key of super.keys()) {
|
|
|
|
|
if (!sources.has(key)) {
|
|
|
|
|
var s = this.#source(0);
|
|
|
|
|
if (DEV) {
|
|
|
|
|
tag(s, `SvelteMap get(${label(key)})`);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sources.set(key, s);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
*values() {
|
|
|
|
|
for (const key of get(this.#items).keys()) {
|
|
|
|
|
const s = this.#sources.get(key);
|
|
|
|
|
if (s === undefined) continue;
|
|
|
|
|
|
|
|
|
|
for ([, s] of this.#sources) {
|
|
|
|
|
get(s);
|
|
|
|
|
const value = get(s);
|
|
|
|
|
if (value !== MISSING) yield value;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
keys() {
|
|
|
|
|
get(this.#version);
|
|
|
|
|
return super.keys();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
values() {
|
|
|
|
|
this.#read_all();
|
|
|
|
|
return super.values();
|
|
|
|
|
}
|
|
|
|
|
*entries() {
|
|
|
|
|
for (const key of get(this.#items).keys()) {
|
|
|
|
|
const s = this.#sources.get(key);
|
|
|
|
|
if (s === undefined) continue;
|
|
|
|
|
|
|
|
|
|
entries() {
|
|
|
|
|
this.#read_all();
|
|
|
|
|
return super.entries();
|
|
|
|
|
const value = get(s);
|
|
|
|
|
if (value !== MISSING) yield [key, value];
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Symbol.iterator]() {
|
|
|
|
|
@ -268,7 +242,6 @@ export class SvelteMap extends Map {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
get size() {
|
|
|
|
|
get(this.#size);
|
|
|
|
|
return super.size;
|
|
|
|
|
return get(this.#items).size;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|