From 68a226341597fc2baef1dc33f63dd96497e25565 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Tue, 15 Oct 2024 16:39:37 +0100 Subject: [PATCH] fix: ensure local prop value is read during teardown (#13611) * fix: ensure local prop value is read during teardown * add test * cleanup * less overhead --- .changeset/clean-sloths-nail.md | 5 +++++ .../src/internal/client/reactivity/props.js | 12 +++++++++--- .../props-local-teardown/Component.svelte | 15 +++++++++++++++ .../samples/props-local-teardown/_config.js | 19 +++++++++++++++++++ .../samples/props-local-teardown/main.svelte | 12 ++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 .changeset/clean-sloths-nail.md create mode 100644 packages/svelte/tests/runtime-runes/samples/props-local-teardown/Component.svelte create mode 100644 packages/svelte/tests/runtime-runes/samples/props-local-teardown/_config.js create mode 100644 packages/svelte/tests/runtime-runes/samples/props-local-teardown/main.svelte diff --git a/.changeset/clean-sloths-nail.md b/.changeset/clean-sloths-nail.md new file mode 100644 index 0000000000..9e93a3fda6 --- /dev/null +++ b/.changeset/clean-sloths-nail.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +fix: ensure local prop value is read during teardown diff --git a/packages/svelte/src/internal/client/reactivity/props.js b/packages/svelte/src/internal/client/reactivity/props.js index b817ace3f0..32969139bf 100644 --- a/packages/svelte/src/internal/client/reactivity/props.js +++ b/packages/svelte/src/internal/client/reactivity/props.js @@ -1,4 +1,4 @@ -/** @import { Source } from './types.js' */ +/** @import { Derived, Source } from './types.js' */ import { DEV } from 'esm-env'; import { PROPS_IS_BINDABLE, @@ -12,6 +12,7 @@ import { mutable_source, set, source } from './sources.js'; import { derived, derived_safe_equal } from './deriveds.js'; import { active_effect, + active_reaction, get, is_signals_recorded, set_active_effect, @@ -20,7 +21,7 @@ import { } from '../runtime.js'; import { safe_equals } from './equality.js'; import * as e from '../errors.js'; -import { BRANCH_EFFECT, LEGACY_DERIVED_PROP, ROOT_EFFECT } from '../constants.js'; +import { BRANCH_EFFECT, DESTROYED, LEGACY_DERIVED_PROP, ROOT_EFFECT } from '../constants.js'; import { proxy } from '../proxy.js'; /** @@ -348,12 +349,17 @@ export function prop(props, key, flags, fallback) { // The derived returns the current value. The underlying mutable // source is written to from various places to persist this value. var inner_current_value = mutable_source(prop_value); + var current_value = with_parent_branch(() => derived(() => { var parent_value = getter(); var child_value = get(inner_current_value); + var current_derived = /** @type {Derived} */ (active_reaction); - if (from_child) { + // If the getter from the parent returns undefined, switch + // to using the local value from inner_current_value instead, + // as the parent value might have been torn down + if (from_child || (parent_value === undefined && (current_derived.f & DESTROYED) !== 0)) { from_child = false; was_from_child = true; return child_value; diff --git a/packages/svelte/tests/runtime-runes/samples/props-local-teardown/Component.svelte b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/Component.svelte new file mode 100644 index 0000000000..c324940402 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/Component.svelte @@ -0,0 +1,15 @@ + diff --git a/packages/svelte/tests/runtime-runes/samples/props-local-teardown/_config.js b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/_config.js new file mode 100644 index 0000000000..f79098edbf --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/_config.js @@ -0,0 +1,19 @@ +import { flushSync } from 'svelte'; +import { test } from '../../test'; + +export default test({ + async test({ assert, logs, target }) { + const [btn1] = target.querySelectorAll('button'); + + btn1?.click(); + flushSync(); + + btn1?.click(); + flushSync(); + + btn1?.click(); + flushSync(); + + assert.deepEqual(logs, ['init', 'teardown', 'init', 'teardown']); + } +}); diff --git a/packages/svelte/tests/runtime-runes/samples/props-local-teardown/main.svelte b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/main.svelte new file mode 100644 index 0000000000..9aceaabb77 --- /dev/null +++ b/packages/svelte/tests/runtime-runes/samples/props-local-teardown/main.svelte @@ -0,0 +1,12 @@ + + + + +{#if toggle} + +{/if} +