Skip to content

Commit 0286e35

Browse files
committed
chore: improve old value implementation performance
1 parent c051a6e commit 0286e35

File tree

4 files changed

+81
-8
lines changed

4 files changed

+81
-8
lines changed

.changeset/early-ties-study.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
chore: improve old value implementation performance

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

Lines changed: 67 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { Derived, Effect, Source, Value } from '#client' */
1+
/** @import { Derived, Effect, Source, Value, ValueNode } from '#client' */
22
import { DEV } from 'esm-env';
33
import {
44
active_reaction,
@@ -37,7 +37,70 @@ import { proxy } from '../proxy.js';
3737
import { execute_derived } from './deriveds.js';
3838

3939
export let inspect_effects = new Set();
40-
export const old_values = new Map();
40+
/** @type { null | ValueNode } */
41+
export let old_value_node = null;
42+
/** @type { null | ValueNode } */
43+
export let last_old_value_node = null;
44+
45+
export function clear_old_value_node() {
46+
old_value_node = null;
47+
last_old_value_node = null;
48+
}
49+
50+
/**
51+
* @param {Source} signal
52+
*/
53+
export function get_old_value_node(signal) {
54+
let current = old_value_node;
55+
while (current !== null) {
56+
if (current.s === signal) {
57+
return current;
58+
}
59+
current = current.n;
60+
}
61+
return null;
62+
}
63+
64+
/**
65+
* @param {Source} signal
66+
* @param {any} value
67+
*/
68+
function create_value_node(signal, value) {
69+
return {
70+
s: signal,
71+
v: value,
72+
n: null
73+
};
74+
}
75+
76+
/**
77+
* @param {Source} signal
78+
* @param {any} value
79+
*/
80+
function set_old_value(signal, value) {
81+
const value_node = get_old_value_node(signal);
82+
if (value_node !== null) {
83+
value_node.v = value;
84+
return;
85+
}
86+
add_old_value(signal, value);
87+
}
88+
89+
/**
90+
* @param {Source} signal
91+
* @param {any} value
92+
*/
93+
function add_old_value(signal, value) {
94+
const value_node = create_value_node(signal, value);
95+
96+
if (last_old_value_node === null) {
97+
last_old_value_node = value_node;
98+
old_value_node = value_node;
99+
} else {
100+
last_old_value_node.n = value_node;
101+
last_old_value_node = value_node;
102+
}
103+
}
41104

42105
/**
43106
* @param {Set<any>} v
@@ -155,9 +218,9 @@ export function internal_set(source, value) {
155218
var old_value = source.v;
156219

157220
if (is_destroying_effect) {
158-
old_values.set(source, value);
221+
set_old_value(source, value);
159222
} else {
160-
old_values.set(source, old_value);
223+
add_old_value(source, old_value);
161224
}
162225

163226
source.v = value;

packages/svelte/src/internal/client/reactivity/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,5 @@ export interface Effect extends Reaction {
7474
export type Source<V = unknown> = Value<V>;
7575

7676
export type MaybeSource<T = unknown> = T | Source<T>;
77+
78+
export type ValueNode = { s: Source, n: null | ValueNode, v: any };

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

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
EFFECT_IS_UPDATING
2727
} from './constants.js';
2828
import { flush_tasks } from './dom/task.js';
29-
import { internal_set, old_values } from './reactivity/sources.js';
29+
import { clear_old_value_node, internal_set, get_old_value_node } from './reactivity/sources.js';
3030
import { destroy_derived_effects, update_derived } from './reactivity/deriveds.js';
3131
import * as e from './errors.js';
3232
import { FILENAME } from '../../constants.js';
@@ -676,7 +676,7 @@ function flush_queued_root_effects() {
676676
var collected_effects = process_effects(root_effects[i]);
677677
flush_queued_effects(collected_effects);
678678
}
679-
old_values.clear();
679+
clear_old_value_node();
680680
}
681681
} finally {
682682
is_flushing = false;
@@ -928,8 +928,11 @@ export function get(signal) {
928928
}
929929
}
930930

931-
if (is_destroying_effect && old_values.has(signal)) {
932-
return old_values.get(signal);
931+
if (is_destroying_effect) {
932+
const value_node = get_old_value_node(signal);
933+
if (value_node !== null) {
934+
return value_node.v;
935+
}
933936
}
934937

935938
return signal.v;

0 commit comments

Comments
 (0)