Skip to content

Commit 4ab82a8

Browse files
committed
make old test work
1 parent 116bbde commit 4ab82a8

File tree

3 files changed

+47
-31
lines changed

3 files changed

+47
-31
lines changed

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

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,10 +106,11 @@ function destroy_derived_children(derived) {
106106
let stack = [];
107107

108108
/**
109+
* @template T
109110
* @param {Derived} derived
110-
* @returns {void}
111+
* @returns {T}
111112
*/
112-
export function update_derived(derived) {
113+
export function execute_derived(derived) {
113114
var value;
114115
var prev_active_effect = active_effect;
115116

@@ -141,6 +142,15 @@ export function update_derived(derived) {
141142
}
142143
}
143144

145+
return value;
146+
}
147+
148+
/**
149+
* @param {Derived} derived
150+
* @returns {void}
151+
*/
152+
export function update_derived(derived) {
153+
var value = execute_derived(derived);
144154
var status =
145155
(skip_reaction || (derived.f & UNOWNED) !== 0) && derived.deps !== null ? MAYBE_DIRTY : CLEAN;
146156

@@ -162,11 +172,5 @@ export function destroy_derived(signal) {
162172
set_signal_status(signal, DESTROYED);
163173

164174
// TODO we need to ensure we remove the derived from any parent derives
165-
166-
signal.children =
167-
signal.deps =
168-
signal.reactions =
169-
// @ts-expect-error `signal.fn` cannot be `null` while the signal is alive
170-
signal.fn =
171-
null;
175+
signal.v = signal.children = signal.deps = signal.reactions = null;
172176
}

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

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
import { flush_tasks } from './dom/task.js';
2828
import { add_owner } from './dev/ownership.js';
2929
import { mutate, set, source } from './reactivity/sources.js';
30-
import { destroy_derived, update_derived } from './reactivity/deriveds.js';
30+
import { destroy_derived, execute_derived, update_derived } from './reactivity/deriveds.js';
3131
import * as e from './errors.js';
3232
import { lifecycle_outside_component } from '../shared/errors.js';
3333
import { FILENAME } from '../../constants.js';
@@ -300,40 +300,44 @@ export function update_reaction(reaction) {
300300
var previous_reaction = active_reaction;
301301
var previous_skip_reaction = skip_reaction;
302302
var prev_derived_sources = derived_sources;
303+
var flags = reaction.f;
303304

304305
new_deps = /** @type {null | Value[]} */ (null);
305306
skipped_deps = 0;
306307
untracked_writes = null;
307-
active_reaction = (reaction.f & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
308-
skip_reaction = !is_flushing_effect && (reaction.f & UNOWNED) !== 0;
308+
active_reaction = (flags & (BRANCH_EFFECT | ROOT_EFFECT)) === 0 ? reaction : null;
309+
skip_reaction = !is_flushing_effect && (flags & UNOWNED) !== 0;
309310
derived_sources = null;
310311

311312
try {
312313
var result = /** @type {Function} */ (0, reaction.fn)();
313314
var deps = reaction.deps;
314315

315-
if (new_deps !== null) {
316-
var i;
316+
// Avoid doing work on an effect/derived that might have become destroyed
317+
if ((flags & DESTROYED) === 0) {
318+
if (new_deps !== null) {
319+
var i;
317320

318-
remove_reactions(reaction, skipped_deps);
321+
remove_reactions(reaction, skipped_deps);
319322

320-
if (deps !== null && skipped_deps > 0) {
321-
deps.length = skipped_deps + new_deps.length;
322-
for (i = 0; i < new_deps.length; i++) {
323-
deps[skipped_deps + i] = new_deps[i];
323+
if (deps !== null && skipped_deps > 0) {
324+
deps.length = skipped_deps + new_deps.length;
325+
for (i = 0; i < new_deps.length; i++) {
326+
deps[skipped_deps + i] = new_deps[i];
327+
}
328+
} else {
329+
reaction.deps = deps = new_deps;
324330
}
325-
} else {
326-
reaction.deps = deps = new_deps;
327-
}
328331

329-
if (!skip_reaction) {
330-
for (i = skipped_deps; i < deps.length; i++) {
331-
(deps[i].reactions ??= []).push(reaction);
332+
if (!skip_reaction) {
333+
for (i = skipped_deps; i < deps.length; i++) {
334+
(deps[i].reactions ??= []).push(reaction);
335+
}
332336
}
337+
} else if (deps !== null && skipped_deps < deps.length) {
338+
remove_reactions(reaction, skipped_deps);
339+
deps.length = skipped_deps;
333340
}
334-
} else if (deps !== null && skipped_deps < deps.length) {
335-
remove_reactions(reaction, skipped_deps);
336-
deps.length = skipped_deps;
337341
}
338342

339343
return result;
@@ -739,9 +743,12 @@ export async function tick() {
739743
*/
740744
export function get(signal) {
741745
var flags = signal.f;
746+
var is_derived = (flags & DERIVED) !== 0;
742747

743-
if ((flags & DESTROYED) !== 0) {
744-
return signal.v;
748+
// If the derived is destroyed, just execute it again without retaining
749+
// it's memoisation properties – as the derived is stale
750+
if (is_derived && (flags & DESTROYED) !== 0) {
751+
return execute_derived(/** @type {Derived} */ (signal));
745752
}
746753

747754
if (is_signals_recorded) {
@@ -778,7 +785,7 @@ export function get(signal) {
778785
}
779786
}
780787

781-
if ((flags & DERIVED) !== 0) {
788+
if (is_derived) {
782789
var derived = /** @type {Derived} */ (signal);
783790

784791
if (check_dirtiness(derived)) {

packages/svelte/tests/runtime-runes/samples/derived-unowned-3/main.svelte

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
<script>
2+
import { untrack } from 'svelte';
3+
24
class Model {
35
data = $state();
46
@@ -26,6 +28,9 @@
2628
$effect(() => {
2729
if(needsSet) {
2830
setModel('effect');
31+
untrack(() => {
32+
needsSet = false;
33+
});
2934
}
3035
});
3136

0 commit comments

Comments
 (0)