Skip to content

Commit 9dc3205

Browse files
committed
i was doing this all wrong
1 parent 8d2a7d0 commit 9dc3205

File tree

4 files changed

+45
-53
lines changed

4 files changed

+45
-53
lines changed

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

Lines changed: 17 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/** @typedef {{ file: string, line: number, column: number }} Location */
22

3+
import { STATE_SYMBOL } from '../proxy.js';
34
import { current_component_context, current_owners, deep_read, untrack } from '../runtime.js';
45

56
/** @type {Record<string, Array<{ start: Location, end: Location, component: Function }>>} */
@@ -82,59 +83,45 @@ export function mark_module_end() {
8283
/** @type {Function | null} */
8384
let new_owner = null;
8485

85-
/**
86-
* @param {import('../types.js').SignalDebug} signal
87-
*/
88-
export function set_owners(signal) {
89-
if (current_owners && signal.owners) {
90-
for (const owner of current_owners) {
91-
signal.owners.add(owner);
92-
}
93-
}
94-
}
95-
9686
/**
9787
*
9888
* @param {any} object
9989
* @param {any} owner
10090
*/
10191
export function add_owner(object, owner) {
10292
untrack(() => {
103-
new_owner = owner;
104-
deep_read(object);
105-
new_owner = null;
93+
add_owner_to_object(object, owner);
10694
});
10795
}
10896

10997
/**
110-
* @param {import('../types.js').SignalDebug} signal
98+
* @param {any} object
99+
* @param {Function} owner
111100
*/
112-
export function add_owner_to_signal(signal) {
113-
if (
114-
new_owner &&
115-
// @ts-expect-error
116-
signal.owners?.has(current_component_context.function)
117-
) {
118-
signal.owners.add(new_owner);
101+
function add_owner_to_object(object, owner) {
102+
if (object?.[STATE_SYMBOL]?.owners && !object[STATE_SYMBOL].owners.has(owner)) {
103+
object[STATE_SYMBOL].owners.add(owner);
104+
105+
for (const key in object) {
106+
add_owner_to_object(object[key], owner);
107+
}
119108
}
120109
}
121110

122111
/**
123-
* @param {import('../types.js').SignalDebug} signal
112+
* @param {Set<Function>} owners
124113
*/
125-
export function check_ownership(signal) {
126-
if (!signal.owners) return;
127-
114+
export function check_ownership(owners) {
128115
const component = get_component();
129116

130-
if (component && signal.owners.size > 0 && !signal.owners.has(component)) {
131-
let owner = [...signal.owners][0];
117+
if (component && !owners.has(component)) {
118+
let original = [...owners][0];
132119

133120
let message =
134121
// @ts-expect-error
135-
owner.filename !== component.filename
122+
original.filename !== component.filename
136123
? // @ts-expect-error
137-
`${component.filename} mutated a value owned by ${owner.filename}. This is strongly discouraged`
124+
`${component.filename} mutated a value owned by ${original.filename}. This is strongly discouraged`
138125
: 'Mutating a value outside the component that created it is strongly discouraged';
139126

140127
// eslint-disable-next-line no-console

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

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import {
1010
mutable_source,
1111
batch_inspect,
1212
set_current_owners,
13-
current_owners
13+
current_owners,
14+
current_component_context
1415
} from './runtime.js';
1516
import {
1617
array_prototype,
@@ -22,16 +23,18 @@ import {
2223
is_frozen,
2324
object_prototype
2425
} from './utils.js';
26+
import { check_ownership } from './dev/ownership.js';
2527

2628
export const STATE_SYMBOL = Symbol('$state');
2729

2830
/**
2931
* @template T
3032
* @param {T} value
3133
* @param {boolean} [immutable]
34+
* @param {Function[]} [owners]
3235
* @returns {import('./types.js').ProxyStateObject<T> | T}
3336
*/
34-
export function proxy(value, immutable = true) {
37+
export function proxy(value, immutable = true, owners) {
3538
if (typeof value === 'object' && value != null && !is_frozen(value)) {
3639
// If we have an existing proxy, return it...
3740
if (STATE_SYMBOL in value) {
@@ -62,7 +65,13 @@ export function proxy(value, immutable = true) {
6265

6366
if (DEV) {
6467
// @ts-expect-error
65-
value[STATE_SYMBOL].owner = new Set(current_owners);
68+
value[STATE_SYMBOL].owners =
69+
owners === undefined
70+
? current_component_context
71+
? // @ts-expect-error
72+
new Set([current_component_context.function])
73+
: null
74+
: new Set(owners);
6675
}
6776

6877
return proxy;
@@ -136,7 +145,7 @@ const state_proxy_handler = {
136145
const metadata = target[STATE_SYMBOL];
137146

138147
const s = metadata.s.get(prop);
139-
if (s !== undefined) set(s, proxy(descriptor.value, metadata.i));
148+
if (s !== undefined) set(s, proxy(descriptor.value, metadata.i, metadata.owners));
140149
}
141150

142151
return Reflect.defineProperty(target, prop, descriptor);
@@ -185,7 +194,7 @@ const state_proxy_handler = {
185194
) {
186195
const previous_owners = current_owners;
187196
if (DEV) set_current_owners(metadata.owner);
188-
s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i));
197+
s = (metadata.i ? source : mutable_source)(proxy(target[prop], metadata.i, metadata.owners));
189198
if (DEV) set_current_owners(previous_owners);
190199
metadata.s.set(prop, s);
191200
}
@@ -228,7 +237,7 @@ const state_proxy_handler = {
228237
if (s !== undefined || (effect_active() && (!has || get_descriptor(target, prop)?.writable))) {
229238
if (s === undefined) {
230239
s = (metadata.i ? source : mutable_source)(
231-
has ? proxy(target[prop], metadata.i) : UNINITIALIZED
240+
has ? proxy(target[prop], metadata.i, metadata.owners) : UNINITIALIZED
232241
);
233242
metadata.s.set(prop, s);
234243
}
@@ -243,10 +252,18 @@ const state_proxy_handler = {
243252
set(target, prop, value) {
244253
const metadata = target[STATE_SYMBOL];
245254
const s = metadata.s.get(prop);
246-
if (s !== undefined) set(s, proxy(value, metadata.i));
255+
if (s !== undefined) {
256+
set(s, proxy(value, metadata.i, metadata.owners));
257+
} else if (DEV) {
258+
// TODO transfer ownership, in case it differs
259+
}
247260
const is_array = metadata.a;
248261
const not_has = !(prop in target);
249262

263+
if (DEV && metadata.owners) {
264+
check_ownership(metadata.owners);
265+
}
266+
250267
// variable.length = value -> clear all signals with index >= value
251268
if (is_array && prop === 'length') {
252269
for (let i = value; i < target.length; i += 1) {

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

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import {
1919
} from '../../constants.js';
2020
import { STATE_SYMBOL, unstate } from './proxy.js';
2121
import { EACH_BLOCK, IF_BLOCK } from './block.js';
22-
import { add_owner_to_signal, check_ownership, set_owners } from './dev/ownership.js';
2322

2423
export const SOURCE = 1;
2524
export const DERIVED = 1 << 1;
@@ -183,8 +182,7 @@ function create_source_signal(flags, value) {
183182
// value
184183
v: value,
185184
// this is for DEV only
186-
inspect: new Set(),
187-
owners: new Set()
185+
inspect: new Set()
188186
};
189187
}
190188
return {
@@ -953,8 +951,6 @@ export function get(signal) {
953951
if (DEV) {
954952
const debuggable = /** @type {import('./types.js').SignalDebug} */ (signal);
955953

956-
add_owner_to_signal(debuggable);
957-
958954
// @ts-expect-error
959955
if (signal.inspect && inspect_fn) {
960956
debuggable.inspect.add(inspect_fn);
@@ -1026,10 +1022,6 @@ export function get(signal) {
10261022
* @returns {V}
10271023
*/
10281024
export function set(signal, value) {
1029-
if (DEV) {
1030-
check_ownership(/** @type {import('./types.js').SignalDebug} */ (signal));
1031-
}
1032-
10331025
set_signal_value(signal, value);
10341026
return value;
10351027
}
@@ -1345,10 +1337,6 @@ export function source(initial_value) {
13451337
* @param {import('./types.js').Signal} signal
13461338
*/
13471339
function bind_signal_to_component_context(signal) {
1348-
if (DEV) {
1349-
set_owners(/** @type {import('./types.js').SignalDebug} */ (signal));
1350-
}
1351-
13521340
if (current_component_context === null || !current_component_context.r) return;
13531341

13541342
const signals = current_component_context.d;

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export type SourceSignalDebug = {
8383
/** This is DEV only */
8484
inspect: Set<Function>;
8585
/** This is DEV only */
86-
owners: Set<Function>;
86+
proxy?: ProxyStateObject;
8787
};
8888

8989
export type ComputationSignal<V = unknown> = {
@@ -408,8 +408,8 @@ export interface ProxyMetadata<T = Record<string | symbol, any>> {
408408
p: ProxyStateObject<T>;
409409
/** The original target this proxy was created for */
410410
t: T;
411-
/** The component that 'owns' this state, if any */
412-
o: string;
411+
/** Dev-only — the components that 'own' this state, if any */
412+
owners: null | Set<Function>;
413413
}
414414

415415
export type ProxyStateObject<T = Record<string | symbol, any>> = T & {

0 commit comments

Comments
 (0)