Skip to content

Commit 2f8eda9

Browse files
Rich-Harristrueadmpaoloricciuti
authored
fix: ensure SvelteDate cached methods have correct reactive context (#14525)
* fix: ensure SvelteDate cached methods have no reactive context * fix: ensure SvelteDate cached methods have no reactive context * fix * lint * use active reaction at time of instance creation * tweak changeset * Update packages/svelte/src/internal/client/dom/elements/bindings/shared.js Co-authored-by: Paolo Ricciuti <[email protected]> --------- Co-authored-by: Dominic Gannaway <[email protected]> Co-authored-by: Paolo Ricciuti <[email protected]>
1 parent 3927568 commit 2f8eda9

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

.changeset/wicked-zebras-exist.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+
fix: use correct reaction when lazily creating deriveds inside `SvelteDate`

packages/svelte/src/reactivity/date.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
/** @import { Source } from '#client' */
2-
import { DESTROYED } from '../internal/client/constants.js';
32
import { derived } from '../internal/client/index.js';
43
import { source, set } from '../internal/client/reactivity/sources.js';
5-
import { get } from '../internal/client/runtime.js';
4+
import { active_reaction, get, set_active_reaction } from '../internal/client/runtime.js';
65

76
var inited = false;
87

@@ -12,6 +11,8 @@ export class SvelteDate extends Date {
1211
/** @type {Map<keyof Date, Source<unknown>>} */
1312
#deriveds = new Map();
1413

14+
#reaction = active_reaction;
15+
1516
/** @param {any[]} params */
1617
constructor(...params) {
1718
// @ts-ignore
@@ -43,14 +44,21 @@ export class SvelteDate extends Date {
4344

4445
var d = this.#deriveds.get(method);
4546

46-
if (d === undefined || (d.f & DESTROYED) !== 0) {
47+
if (d === undefined) {
48+
// lazily create the derived, but as though it were being
49+
// created at the same time as the class instance
50+
const reaction = active_reaction;
51+
set_active_reaction(this.#reaction);
52+
4753
d = derived(() => {
4854
get(this.#time);
4955
// @ts-ignore
5056
return date_proto[method].apply(this, args);
5157
});
5258

5359
this.#deriveds.set(method, d);
60+
61+
set_active_reaction(reaction);
5462
}
5563

5664
return get(d);

packages/svelte/src/reactivity/date.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,3 +642,33 @@ test('Date methods invoked for the first time in a derived', () => {
642642

643643
cleanup();
644644
});
645+
646+
test('Date methods shared between deriveds', () => {
647+
const date = new SvelteDate(initial_date);
648+
const log: any = [];
649+
650+
const cleanup = effect_root(() => {
651+
const year = derived(() => {
652+
return date.getFullYear();
653+
});
654+
const year2 = derived(() => {
655+
return date.getTime(), date.getFullYear();
656+
});
657+
658+
render_effect(() => {
659+
log.push(get(year) + '/' + get(year2).toString());
660+
});
661+
662+
flushSync(() => {
663+
date.setFullYear(date.getFullYear() + 1);
664+
});
665+
666+
flushSync(() => {
667+
date.setFullYear(date.getFullYear() + 1);
668+
});
669+
});
670+
671+
assert.deepEqual(log, ['2023/2023', '2024/2024', '2025/2025']);
672+
673+
cleanup();
674+
});

0 commit comments

Comments
 (0)