Skip to content

Commit

Permalink
fix: ensure SvelteDate cached methods have correct reactive context (#…
Browse files Browse the repository at this point in the history
…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]>
  • Loading branch information
3 people authored Dec 3, 2024
1 parent 3927568 commit 2f8eda9
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 3 deletions.
5 changes: 5 additions & 0 deletions .changeset/wicked-zebras-exist.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'svelte': patch
---

fix: use correct reaction when lazily creating deriveds inside `SvelteDate`
14 changes: 11 additions & 3 deletions packages/svelte/src/reactivity/date.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/** @import { Source } from '#client' */
import { DESTROYED } from '../internal/client/constants.js';
import { derived } from '../internal/client/index.js';
import { source, set } from '../internal/client/reactivity/sources.js';
import { get } from '../internal/client/runtime.js';
import { active_reaction, get, set_active_reaction } from '../internal/client/runtime.js';

var inited = false;

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

#reaction = active_reaction;

/** @param {any[]} params */
constructor(...params) {
// @ts-ignore
Expand Down Expand Up @@ -43,14 +44,21 @@ export class SvelteDate extends Date {

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

if (d === undefined || (d.f & DESTROYED) !== 0) {
if (d === undefined) {
// lazily create the derived, but as though it were being
// created at the same time as the class instance
const reaction = active_reaction;
set_active_reaction(this.#reaction);

d = derived(() => {
get(this.#time);
// @ts-ignore
return date_proto[method].apply(this, args);
});

this.#deriveds.set(method, d);

set_active_reaction(reaction);
}

return get(d);
Expand Down
30 changes: 30 additions & 0 deletions packages/svelte/src/reactivity/date.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -642,3 +642,33 @@ test('Date methods invoked for the first time in a derived', () => {

cleanup();
});

test('Date methods shared between deriveds', () => {
const date = new SvelteDate(initial_date);
const log: any = [];

const cleanup = effect_root(() => {
const year = derived(() => {
return date.getFullYear();
});
const year2 = derived(() => {
return date.getTime(), date.getFullYear();
});

render_effect(() => {
log.push(get(year) + '/' + get(year2).toString());
});

flushSync(() => {
date.setFullYear(date.getFullYear() + 1);
});

flushSync(() => {
date.setFullYear(date.getFullYear() + 1);
});
});

assert.deepEqual(log, ['2023/2023', '2024/2024', '2025/2025']);

cleanup();
});

0 comments on commit 2f8eda9

Please sign in to comment.