|
1 |
| -/** @import { ProxyMetadata } from '#client' */ |
2 | 1 | /** @typedef {{ file: string, line: number, column: number }} Location */
|
3 | 2 |
|
4 |
| -import { STATE_SYMBOL_METADATA } from '../constants.js'; |
5 |
| -import { render_effect, user_pre_effect } from '../reactivity/effects.js'; |
6 |
| -import { dev_current_component_function } from '../context.js'; |
7 |
| -import { get_prototype_of } from '../../shared/utils.js'; |
8 |
| -import * as w from '../warnings.js'; |
9 |
| -import { FILENAME, UNINITIALIZED } from '../../../constants.js'; |
10 |
| - |
11 | 3 | /** @type {Record<string, Array<{ start: Location, end: Location, component: Function }>>} */
|
12 | 4 | const boundaries = {};
|
13 | 5 |
|
@@ -71,8 +63,6 @@ export function get_component() {
|
71 | 63 | return null;
|
72 | 64 | }
|
73 | 65 |
|
74 |
| -export const ADD_OWNER = Symbol('ADD_OWNER'); |
75 |
| - |
76 | 66 | /**
|
77 | 67 | * Together with `mark_module_end`, this function establishes the boundaries of a `.svelte` file,
|
78 | 68 | * such that subsequent calls to `get_component` can tell us which component is responsible
|
@@ -106,199 +96,3 @@ export function mark_module_end(component) {
|
106 | 96 | boundary.component = component;
|
107 | 97 | }
|
108 | 98 | }
|
109 |
| - |
110 |
| -/** |
111 |
| - * @param {any} object |
112 |
| - * @param {any | null} owner |
113 |
| - * @param {boolean} [global] |
114 |
| - * @param {boolean} [skip_warning] |
115 |
| - */ |
116 |
| -export function add_owner(object, owner, global = false, skip_warning = false) { |
117 |
| - if (object && !global) { |
118 |
| - const component = dev_current_component_function; |
119 |
| - const metadata = object[STATE_SYMBOL_METADATA]; |
120 |
| - if (metadata && !has_owner(metadata, component)) { |
121 |
| - let original = get_owner(metadata); |
122 |
| - |
123 |
| - if (owner && owner[FILENAME] !== component[FILENAME] && !skip_warning) { |
124 |
| - w.ownership_invalid_binding(component[FILENAME], owner[FILENAME], original[FILENAME]); |
125 |
| - } |
126 |
| - } |
127 |
| - } |
128 |
| - |
129 |
| - add_owner_to_object(object, owner, new Set()); |
130 |
| -} |
131 |
| - |
132 |
| -/** |
133 |
| - * @param {() => unknown} get_object |
134 |
| - * @param {any} Component |
135 |
| - * @param {boolean} [skip_warning] |
136 |
| - */ |
137 |
| -export function add_owner_effect(get_object, Component, skip_warning = false) { |
138 |
| - user_pre_effect(() => { |
139 |
| - add_owner(get_object(), Component, false, skip_warning); |
140 |
| - }); |
141 |
| -} |
142 |
| - |
143 |
| -/** |
144 |
| - * @param {any} _this |
145 |
| - * @param {Function} owner |
146 |
| - * @param {Array<() => any>} getters |
147 |
| - * @param {boolean} skip_warning |
148 |
| - */ |
149 |
| -export function add_owner_to_class(_this, owner, getters, skip_warning) { |
150 |
| - _this[ADD_OWNER].current ||= getters.map(() => UNINITIALIZED); |
151 |
| - |
152 |
| - for (let i = 0; i < getters.length; i += 1) { |
153 |
| - const current = getters[i](); |
154 |
| - // For performance reasons we only re-add the owner if the state has changed |
155 |
| - if (current !== _this[ADD_OWNER][i]) { |
156 |
| - _this[ADD_OWNER].current[i] = current; |
157 |
| - add_owner(current, owner, false, skip_warning); |
158 |
| - } |
159 |
| - } |
160 |
| -} |
161 |
| - |
162 |
| -/** |
163 |
| - * @param {ProxyMetadata | null} from |
164 |
| - * @param {ProxyMetadata} to |
165 |
| - */ |
166 |
| -export function widen_ownership(from, to) { |
167 |
| - if (to.owners === null) { |
168 |
| - return; |
169 |
| - } |
170 |
| - |
171 |
| - while (from) { |
172 |
| - if (from.owners === null) { |
173 |
| - to.owners = null; |
174 |
| - break; |
175 |
| - } |
176 |
| - |
177 |
| - for (const owner of from.owners) { |
178 |
| - to.owners.add(owner); |
179 |
| - } |
180 |
| - |
181 |
| - from = from.parent; |
182 |
| - } |
183 |
| -} |
184 |
| - |
185 |
| -/** |
186 |
| - * @param {any} object |
187 |
| - * @param {Function | null} owner If `null`, then the object is globally owned and will not be checked |
188 |
| - * @param {Set<any>} seen |
189 |
| - */ |
190 |
| -function add_owner_to_object(object, owner, seen) { |
191 |
| - const metadata = /** @type {ProxyMetadata} */ (object?.[STATE_SYMBOL_METADATA]); |
192 |
| - |
193 |
| - if (metadata) { |
194 |
| - // this is a state proxy, add owner directly, if not globally shared |
195 |
| - if ('owners' in metadata && metadata.owners != null) { |
196 |
| - if (owner) { |
197 |
| - metadata.owners.add(owner); |
198 |
| - } else { |
199 |
| - metadata.owners = null; |
200 |
| - } |
201 |
| - } |
202 |
| - } else if (object && typeof object === 'object') { |
203 |
| - if (seen.has(object)) return; |
204 |
| - seen.add(object); |
205 |
| - if (ADD_OWNER in object && object[ADD_OWNER]) { |
206 |
| - // this is a class with state fields. we put this in a render effect |
207 |
| - // so that if state is replaced (e.g. `instance.name = { first, last }`) |
208 |
| - // the new state is also co-owned by the caller of `getContext` |
209 |
| - render_effect(() => { |
210 |
| - object[ADD_OWNER](owner); |
211 |
| - }); |
212 |
| - } else { |
213 |
| - var proto = get_prototype_of(object); |
214 |
| - |
215 |
| - if (proto === Object.prototype) { |
216 |
| - // recurse until we find a state proxy |
217 |
| - for (const key in object) { |
218 |
| - if (Object.getOwnPropertyDescriptor(object, key)?.get) { |
219 |
| - // Similar to the class case; the getter could update with a new state |
220 |
| - let current = UNINITIALIZED; |
221 |
| - render_effect(() => { |
222 |
| - const next = object[key]; |
223 |
| - if (current !== next) { |
224 |
| - current = next; |
225 |
| - add_owner_to_object(next, owner, seen); |
226 |
| - } |
227 |
| - }); |
228 |
| - } else { |
229 |
| - add_owner_to_object(object[key], owner, seen); |
230 |
| - } |
231 |
| - } |
232 |
| - } else if (proto === Array.prototype) { |
233 |
| - // recurse until we find a state proxy |
234 |
| - for (let i = 0; i < object.length; i += 1) { |
235 |
| - add_owner_to_object(object[i], owner, seen); |
236 |
| - } |
237 |
| - } |
238 |
| - } |
239 |
| - } |
240 |
| -} |
241 |
| - |
242 |
| -/** |
243 |
| - * @param {ProxyMetadata} metadata |
244 |
| - * @param {Function} component |
245 |
| - * @returns {boolean} |
246 |
| - */ |
247 |
| -function has_owner(metadata, component) { |
248 |
| - if (metadata.owners === null) { |
249 |
| - return true; |
250 |
| - } |
251 |
| - |
252 |
| - return ( |
253 |
| - metadata.owners.has(component) || |
254 |
| - // This helps avoid false positives when using HMR, where the component function is replaced |
255 |
| - (FILENAME in component && |
256 |
| - [...metadata.owners].some( |
257 |
| - (owner) => /** @type {any} */ (owner)[FILENAME] === component[FILENAME] |
258 |
| - )) || |
259 |
| - (metadata.parent !== null && has_owner(metadata.parent, component)) |
260 |
| - ); |
261 |
| -} |
262 |
| - |
263 |
| -/** |
264 |
| - * @param {ProxyMetadata} metadata |
265 |
| - * @returns {any} |
266 |
| - */ |
267 |
| -function get_owner(metadata) { |
268 |
| - return ( |
269 |
| - metadata?.owners?.values().next().value ?? |
270 |
| - get_owner(/** @type {ProxyMetadata} */ (metadata.parent)) |
271 |
| - ); |
272 |
| -} |
273 |
| - |
274 |
| -let skip = false; |
275 |
| - |
276 |
| -/** |
277 |
| - * @param {() => any} fn |
278 |
| - */ |
279 |
| -export function skip_ownership_validation(fn) { |
280 |
| - skip = true; |
281 |
| - fn(); |
282 |
| - skip = false; |
283 |
| -} |
284 |
| - |
285 |
| -/** |
286 |
| - * @param {ProxyMetadata} metadata |
287 |
| - */ |
288 |
| -export function check_ownership(metadata) { |
289 |
| - if (skip) return; |
290 |
| - |
291 |
| - const component = get_component(); |
292 |
| - |
293 |
| - if (component && !has_owner(metadata, component)) { |
294 |
| - let original = get_owner(metadata); |
295 |
| - |
296 |
| - // @ts-expect-error |
297 |
| - if (original[FILENAME] !== component[FILENAME]) { |
298 |
| - // @ts-expect-error |
299 |
| - w.ownership_invalid_mutation(component[FILENAME], original[FILENAME]); |
300 |
| - } else { |
301 |
| - w.ownership_invalid_mutation(); |
302 |
| - } |
303 |
| - } |
304 |
| -} |
0 commit comments