pull/13611/head
Dominic Gannaway 2 years ago
parent de30becc9c
commit e3cff9b9c4

@ -1,4 +1,4 @@
/** @import { Derived, Source } from './types.js' */
/** @import { Source } from './types.js' */
import { DEV } from 'esm-env';
import {
PROPS_IS_BINDABLE,
@ -22,6 +22,7 @@ import { safe_equals } from './equality.js';
import * as e from '../errors.js';
import { BRANCH_EFFECT, DESTROYED, LEGACY_DERIVED_PROP, ROOT_EFFECT } from '../constants.js';
import { proxy } from '../proxy.js';
import { teardown } from './effects.js';
/**
* @param {((value?: number) => number)} fn
@ -292,8 +293,6 @@ export function prop(props, key, flags, fallback) {
/** @type {() => V} */
var getter;
/** @type {Derived} */
var derived_getter;
if (runes) {
getter = () => {
var value = /** @type {V} */ (props[key]);
@ -305,7 +304,7 @@ export function prop(props, key, flags, fallback) {
} else {
// Svelte 4 did not trigger updates when a primitive value was updated to the same value.
// Replicate that behavior through using a derived
derived_getter = with_parent_branch(() =>
var derived_getter = with_parent_branch(() =>
(immutable ? derived : derived_safe_equal)(() => /** @type {V} */ (props[key]))
);
derived_getter.f |= LEGACY_DERIVED_PROP;
@ -350,12 +349,22 @@ 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);
teardown(() => {
// 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 (getter() === undefined) {
from_child = true;
}
});
var current_value = with_parent_branch(() =>
derived(() => {
var parent_value = getter();
var child_value = get(inner_current_value);
if (from_child || (derived_getter !== undefined && (derived_getter.f & DESTROYED) !== 0)) {
if (from_child) {
from_child = false;
was_from_child = true;
return child_value;

@ -0,0 +1,15 @@
<script>
let { x } = $props();
$effect(() => {
console.log('init')
x = () => {
console.log('teardown')
}
return () => {
x();
}
})
</script>

@ -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']);
}
});

@ -0,0 +1,12 @@
<script>
import Component from "./Component.svelte";
let toggle = $state(true);
</script>
<button onclick={() => toggle = !toggle}>toggle</button>
{#if toggle}
<Component />
{/if}
Loading…
Cancel
Save