Skip to content

Commit 8291cd9

Browse files
committed
fix: widen ownership when calling setContext
Instead of doing ownership addition at each `getContext` call site, we do it once as the `setContext` call site and make the state basically global. - avoids potential false positives in edge cases - makes the whole thing more performant, especially around things like calling `getContext` inside a list item component - false negatives are unlikely from this fixes #15072
1 parent 8e83127 commit 8291cd9

File tree

3 files changed

+24
-23
lines changed

3 files changed

+24
-23
lines changed

.changeset/unlucky-gorillas-hunt.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: widen ownership when calling setContext

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

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import {
88
active_effect,
99
active_reaction,
1010
set_active_effect,
11-
set_active_reaction
11+
set_active_reaction,
12+
untrack
1213
} from './runtime.js';
1314
import { effect } from './reactivity/effects.js';
1415
import { legacy_mode_flag } from '../flags/index.js';
@@ -49,14 +50,6 @@ export function set_dev_current_component_function(fn) {
4950
export function getContext(key) {
5051
const context_map = get_or_init_context_map('getContext');
5152
const result = /** @type {T} */ (context_map.get(key));
52-
53-
if (DEV) {
54-
const fn = /** @type {ComponentContext} */ (component_context).function;
55-
if (fn) {
56-
add_owner(result, fn, true);
57-
}
58-
}
59-
6053
return result;
6154
}
6255

@@ -74,6 +67,15 @@ export function getContext(key) {
7467
*/
7568
export function setContext(key, context) {
7669
const context_map = get_or_init_context_map('setContext');
70+
71+
if (DEV) {
72+
// When state is put into context, we treat as if it's global from now on.
73+
// We do for performance reasons (it's for example very expensive to call
74+
// getContext on a big object many times when part of a list component)
75+
// and danger of false positives.
76+
untrack(() => add_owner(context, null, true));
77+
}
78+
7779
context_map.set(key, context);
7880
return context;
7981
}
@@ -100,16 +102,6 @@ export function hasContext(key) {
100102
*/
101103
export function getAllContexts() {
102104
const context_map = get_or_init_context_map('getAllContexts');
103-
104-
if (DEV) {
105-
const fn = component_context?.function;
106-
if (fn) {
107-
for (const value of context_map.values()) {
108-
add_owner(value, fn, true);
109-
}
110-
}
111-
}
112-
113105
return /** @type {T} */ (context_map);
114106
}
115107

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ export function mark_module_end(component) {
109109

110110
/**
111111
* @param {any} object
112-
* @param {any} owner
112+
* @param {any | null} owner
113113
* @param {boolean} [global]
114114
* @param {boolean} [skip_warning]
115115
*/
@@ -120,7 +120,7 @@ export function add_owner(object, owner, global = false, skip_warning = false) {
120120
if (metadata && !has_owner(metadata, component)) {
121121
let original = get_owner(metadata);
122122

123-
if (owner[FILENAME] !== component[FILENAME] && !skip_warning) {
123+
if (owner && owner[FILENAME] !== component[FILENAME] && !skip_warning) {
124124
w.ownership_invalid_binding(component[FILENAME], owner[FILENAME], original[FILENAME]);
125125
}
126126
}
@@ -165,7 +165,7 @@ export function widen_ownership(from, to) {
165165

166166
/**
167167
* @param {any} object
168-
* @param {Function} owner
168+
* @param {Function | null} owner If `null`, then the object is globally owned and will not be checked
169169
* @param {Set<any>} seen
170170
*/
171171
function add_owner_to_object(object, owner, seen) {
@@ -174,7 +174,11 @@ function add_owner_to_object(object, owner, seen) {
174174
if (metadata) {
175175
// this is a state proxy, add owner directly, if not globally shared
176176
if ('owners' in metadata && metadata.owners != null) {
177-
metadata.owners.add(owner);
177+
if (owner) {
178+
metadata.owners.add(owner);
179+
} else {
180+
metadata.owners = null;
181+
}
178182
}
179183
} else if (object && typeof object === 'object') {
180184
if (seen.has(object)) return;

0 commit comments

Comments
 (0)