Skip to content

Commit d86b052

Browse files
authored
fix: prevent false positive ownership warning (#11490)
fixes #11483 We need to keep track of the component function similar to how we keep track of the component context, so that effects etc have the correct one associated
1 parent 3e1f82b commit d86b052

File tree

10 files changed

+80
-12
lines changed

10 files changed

+80
-12
lines changed

.changeset/two-dogs-accept.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: prevent false positive ownership warning

packages/svelte/src/internal/client/dev/ownership.js

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import { STATE_SYMBOL } from '../constants.js';
44
import { render_effect, user_pre_effect } from '../reactivity/effects.js';
5-
import { dev_current_component_function, set_dev_current_component_function } from '../runtime.js';
5+
import { dev_current_component_function } from '../runtime.js';
66
import { get_prototype_of } from '../utils.js';
77
import * as w from '../warnings.js';
88

@@ -128,12 +128,8 @@ export function add_owner(object, owner, global = false) {
128128
* @param {any} Component
129129
*/
130130
export function add_owner_effect(get_object, Component) {
131-
var component = dev_current_component_function;
132131
user_pre_effect(() => {
133-
var prev = dev_current_component_function;
134-
set_dev_current_component_function(component);
135132
add_owner(get_object(), Component);
136-
set_dev_current_component_function(prev);
137133
});
138134
}
139135

packages/svelte/src/internal/client/dom/blocks/await.js

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import {
44
flush_sync,
55
set_current_component_context,
66
set_current_effect,
7-
set_current_reaction
7+
set_current_reaction,
8+
set_dev_current_component_function
89
} from '../../runtime.js';
910
import { block, branch, destroy_effect, pause_effect } from '../../reactivity/effects.js';
1011
import { INERT } from '../../constants.js';
12+
import { DEV } from 'esm-env';
1113

1214
/**
1315
* @template V
@@ -20,6 +22,11 @@ import { INERT } from '../../constants.js';
2022
*/
2123
export function await_block(anchor, get_input, pending_fn, then_fn, catch_fn) {
2224
const component_context = current_component_context;
25+
/** @type {any} */
26+
let component_function;
27+
if (DEV) {
28+
component_function = component_context?.function ?? null;
29+
}
2330

2431
/** @type {any} */
2532
let input;
@@ -41,7 +48,13 @@ export function await_block(anchor, get_input, pending_fn, then_fn, catch_fn) {
4148
set_current_effect(effect);
4249
set_current_reaction(effect); // TODO do we need both?
4350
set_current_component_context(component_context);
51+
if (DEV) {
52+
set_dev_current_component_function(component_function);
53+
}
4454
var e = branch(() => fn(anchor, value));
55+
if (DEV) {
56+
set_dev_current_component_function(null);
57+
}
4558
set_current_component_context(null);
4659
set_current_reaction(null);
4760
set_current_effect(null);

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
current_effect,
55
current_reaction,
66
destroy_effect_children,
7+
dev_current_component_function,
78
execute_effect,
89
get,
910
is_destroying_effect,
@@ -30,6 +31,7 @@ import {
3031
import { set } from './sources.js';
3132
import { remove } from '../dom/reconciler.js';
3233
import * as e from '../errors.js';
34+
import { DEV } from 'esm-env';
3335

3436
/**
3537
* @param {import('#client').Effect | null} effect
@@ -86,6 +88,10 @@ function create_effect(type, fn, sync) {
8688
transitions: null
8789
};
8890

91+
if (DEV) {
92+
effect.component_function = dev_current_component_function;
93+
}
94+
8995
if (current_reaction !== null && !is_root) {
9096
push_effect(effect, current_reaction);
9197
}

packages/svelte/src/internal/client/reactivity/types.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ export interface Effect extends Reaction {
4949
prev: null | Effect;
5050
/** Next sibling child effect created inside the parent signal */
5151
next: null | Effect;
52+
/** Dev only */
53+
component_function?: any;
5254
}
5355

5456
export interface ValueDebug<V = unknown> extends Value<V> {

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

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,6 @@ export let current_component_context = null;
113113
/** @param {import('#client').ComponentContext | null} context */
114114
export function set_current_component_context(context) {
115115
current_component_context = context;
116-
if (DEV) {
117-
dev_current_component_function = context?.function;
118-
}
119116
}
120117

121118
/**
@@ -420,7 +417,12 @@ export function execute_effect(effect) {
420417
var previous_component_context = current_component_context;
421418

422419
current_effect = effect;
423-
set_current_component_context(component_context);
420+
current_component_context = component_context;
421+
422+
if (DEV) {
423+
var previous_component_fn = dev_current_component_function;
424+
dev_current_component_function = effect.component_function;
425+
}
424426

425427
try {
426428
if ((flags & BLOCK_EFFECT) === 0) {
@@ -432,7 +434,11 @@ export function execute_effect(effect) {
432434
effect.teardown = typeof teardown === 'function' ? teardown : null;
433435
} finally {
434436
current_effect = previous_effect;
435-
set_current_component_context(previous_component_context);
437+
current_component_context = previous_component_context;
438+
439+
if (DEV) {
440+
dev_current_component_function = previous_component_fn;
441+
}
436442
}
437443
}
438444

@@ -1108,7 +1114,10 @@ export function pop(component) {
11081114
effect(effects[i]);
11091115
}
11101116
}
1111-
set_current_component_context(context_stack_item.p);
1117+
current_component_context = context_stack_item.p;
1118+
if (DEV) {
1119+
dev_current_component_function = context_stack_item.p?.function ?? null;
1120+
}
11121121
context_stack_item.m = true;
11131122
}
11141123
// Micro-optimization: Don't set .a above to the empty object
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<script>
2+
let { object = $bindable() } = $props();
3+
</script>
4+
5+
<button onclick={() => object.count += 1}>
6+
clicks: {object.count}
7+
</button>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<script>
2+
let { children } = $props();
3+
</script>
4+
5+
{@render children?.()}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
html: `<button>clicks: 0</button>`,
5+
6+
compileOptions: {
7+
dev: true
8+
},
9+
10+
warnings: []
11+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<script>
2+
import Outer from './Outer.svelte';
3+
import Inner from './Inner.svelte';
4+
5+
let object = $state({ count: 0 });
6+
let test = $state(true);
7+
</script>
8+
9+
<Outer>
10+
<!-- check that render effects inside slotted content doesn't mess with ownership validation -->
11+
{#if test}
12+
<Inner bind:object />
13+
{/if}
14+
</Outer>

0 commit comments

Comments
 (0)