Skip to content

Commit ee702d1

Browse files
committed
snapshot maps
1 parent 05987bc commit ee702d1

File tree

4 files changed

+34
-7
lines changed

4 files changed

+34
-7
lines changed

packages/svelte/src/internal/client/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,4 @@ export const EFFECT_RAN = 1 << 13;
1616
export const EFFECT_TRANSPARENT = 1 << 14;
1717

1818
export const STATE_SYMBOL = Symbol('$state');
19+
export const STATE_SNAPSHOT_SYMBOL = Symbol('$state.snapshot');

packages/svelte/src/internal/client/reactivity/snapshot.js

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { STATE_SYMBOL } from '../constants.js';
1+
import { STATE_SNAPSHOT_SYMBOL, STATE_SYMBOL } from '../constants.js';
22
import { array_prototype, get_prototype_of, is_array, object_prototype } from '../utils.js';
33

44
/**
@@ -13,17 +13,22 @@ export function snapshot(value, deep = false, values = new Map()) {
1313
return value;
1414
}
1515

16+
var unwrapped = /** @type {T} */ (values.get(value));
17+
if (unwrapped !== undefined) {
18+
return unwrapped;
19+
}
20+
21+
if (STATE_SNAPSHOT_SYMBOL in value) {
22+
// @ts-expect-error
23+
return value[STATE_SNAPSHOT_SYMBOL](deep);
24+
}
25+
1626
var proto = get_prototype_of(value);
1727

1828
if (
1929
(proto === object_prototype || proto === array_prototype) &&
2030
(deep || STATE_SYMBOL in value)
2131
) {
22-
var unwrapped = /** @type {T} */ (values.get(value));
23-
if (unwrapped !== undefined) {
24-
return unwrapped;
25-
}
26-
2732
if (is_array(value)) {
2833
var length = value.length;
2934
var array = Array(length);

packages/svelte/src/internal/client/runtime.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ import {
1515
BRANCH_EFFECT,
1616
STATE_SYMBOL,
1717
BLOCK_EFFECT,
18-
ROOT_EFFECT
18+
ROOT_EFFECT,
19+
STATE_SNAPSHOT_SYMBOL
1920
} from './constants.js';
2021
import { flush_tasks } from './dom/task.js';
2122
import { add_owner } from './dev/ownership.js';
@@ -1137,13 +1138,20 @@ export function deep_read(value, visited = new Set()) {
11371138
!visited.has(value)
11381139
) {
11391140
visited.add(value);
1141+
1142+
if (STATE_SNAPSHOT_SYMBOL in value) {
1143+
value[STATE_SNAPSHOT_SYMBOL](true);
1144+
return;
1145+
}
1146+
11401147
for (let key in value) {
11411148
try {
11421149
deep_read(value[key], visited);
11431150
} catch (e) {
11441151
// continue
11451152
}
11461153
}
1154+
11471155
const proto = get_prototype_of(value);
11481156
if (
11491157
proto !== Object.prototype &&

packages/svelte/src/reactivity/map.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { source, set } from '../internal/client/reactivity/sources.js';
33
import { get } from '../internal/client/runtime.js';
44
import { UNINITIALIZED } from '../constants.js';
55
import { map } from './utils.js';
6+
import { STATE_SNAPSHOT_SYMBOL } from '../internal/client/constants.js';
7+
import { snapshot } from '../internal/client/reactivity/snapshot.js';
68

79
/**
810
* @template K
@@ -155,4 +157,15 @@ export class ReactiveMap extends Map {
155157
get size() {
156158
return get(this.#size);
157159
}
160+
161+
/** @param {boolean} deep */
162+
[STATE_SNAPSHOT_SYMBOL](deep) {
163+
return new Map(
164+
map(
165+
this.#sources.entries(),
166+
([key, source]) => /** @type {[K, V]} */ ([key, snapshot(get(source), deep)]),
167+
'Map Iterator'
168+
)
169+
);
170+
}
158171
}

0 commit comments

Comments
 (0)