svelte 5.55.2 → 5.55.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/index.js +1 -1
- package/package.json +1 -1
- package/src/compiler/phases/2-analyze/visitors/ConstTag.js +25 -0
- package/src/compiler/phases/2-analyze/visitors/Fragment.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/ConstTag.js +18 -33
- package/src/compiler/phases/3-transform/server/visitors/ConstTag.js +13 -12
- package/src/internal/client/constants.js +2 -0
- package/src/internal/client/dev/hmr.js +6 -3
- package/src/internal/client/dom/blocks/boundary.js +21 -5
- package/src/internal/client/dom/blocks/branches.js +8 -0
- package/src/internal/client/reactivity/async.js +20 -1
- package/src/internal/client/reactivity/batch.js +21 -0
- package/src/internal/client/reactivity/deriveds.js +38 -34
- package/src/internal/client/runtime.js +4 -3
- package/src/internal/client/warnings.js +11 -0
- package/src/version.js +1 -1
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @import { AST } from '#compiler' */
|
|
2
2
|
/** @import { Context } from '../types' */
|
|
3
3
|
import * as e from '../../../errors.js';
|
|
4
|
+
import * as b from '#compiler/builders';
|
|
4
5
|
import { validate_opening_tag } from './shared/utils.js';
|
|
5
6
|
|
|
6
7
|
/**
|
|
@@ -42,4 +43,28 @@ export function ConstTag(node, context) {
|
|
|
42
43
|
function_depth: context.state.function_depth + 1,
|
|
43
44
|
derived_function_depth: context.state.function_depth + 1
|
|
44
45
|
});
|
|
46
|
+
|
|
47
|
+
const has_await = node.metadata.expression.has_await;
|
|
48
|
+
const blockers = [...node.metadata.expression.dependencies]
|
|
49
|
+
.map((dep) => dep.blocker)
|
|
50
|
+
.filter((b) => b !== null && b.object !== context.state.async_consts?.id);
|
|
51
|
+
|
|
52
|
+
if (has_await || context.state.async_consts || blockers.length > 0) {
|
|
53
|
+
const run = (context.state.async_consts ??= {
|
|
54
|
+
id: context.state.analysis.root.unique('promises'),
|
|
55
|
+
declaration_count: 0
|
|
56
|
+
});
|
|
57
|
+
node.metadata.promises_id = run.id;
|
|
58
|
+
|
|
59
|
+
const bindings = context.state.scope.get_bindings(declaration);
|
|
60
|
+
|
|
61
|
+
// keep the counter in sync with the number of thunks pushed in ConstTag in transform
|
|
62
|
+
// TODO 6.0 once non-async and non-runes mode is gone investigate making this more robust
|
|
63
|
+
// via something like the approach in https://github.com/sveltejs/svelte/pull/18032
|
|
64
|
+
const length = run.declaration_count++;
|
|
65
|
+
const blocker = b.member(run.id, b.literal(length), true);
|
|
66
|
+
for (const binding of bindings) {
|
|
67
|
+
binding.blocker = blocker;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
45
70
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
/** @import { Expression, Identifier, Pattern } from 'estree' */
|
|
1
|
+
/** @import { Expression, Identifier, Pattern, Statement } from 'estree' */
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
3
|
/** @import { ComponentContext } from '../types' */
|
|
4
|
-
/** @import { ExpressionMetadata } from '../../../nodes.js' */
|
|
5
4
|
import { dev } from '../../../../state.js';
|
|
6
5
|
import { extract_identifiers } from '../../../../utils/ast.js';
|
|
7
6
|
import * as b from '#compiler/builders';
|
|
@@ -27,13 +26,7 @@ export function ConstTag(node, context) {
|
|
|
27
26
|
|
|
28
27
|
context.state.transform[declaration.id.name] = { read: get_value };
|
|
29
28
|
|
|
30
|
-
add_const_declaration(
|
|
31
|
-
context.state,
|
|
32
|
-
declaration.id,
|
|
33
|
-
expression,
|
|
34
|
-
node.metadata.expression,
|
|
35
|
-
context.state.scope.get_bindings(declaration)
|
|
36
|
-
);
|
|
29
|
+
add_const_declaration(context.state, declaration.id, expression, node.metadata);
|
|
37
30
|
} else {
|
|
38
31
|
const identifiers = extract_identifiers(declaration.id);
|
|
39
32
|
const tmp = b.id(context.state.scope.generate('computed_const'));
|
|
@@ -70,13 +63,7 @@ export function ConstTag(node, context) {
|
|
|
70
63
|
expression = b.call('$.tag', expression, b.literal('[@const]'));
|
|
71
64
|
}
|
|
72
65
|
|
|
73
|
-
add_const_declaration(
|
|
74
|
-
context.state,
|
|
75
|
-
tmp,
|
|
76
|
-
expression,
|
|
77
|
-
node.metadata.expression,
|
|
78
|
-
context.state.scope.get_bindings(declaration)
|
|
79
|
-
);
|
|
66
|
+
add_const_declaration(context.state, tmp, expression, node.metadata);
|
|
80
67
|
|
|
81
68
|
for (const node of identifiers) {
|
|
82
69
|
context.state.transform[node.name] = {
|
|
@@ -90,42 +77,40 @@ export function ConstTag(node, context) {
|
|
|
90
77
|
* @param {ComponentContext['state']} state
|
|
91
78
|
* @param {Identifier} id
|
|
92
79
|
* @param {Expression} expression
|
|
93
|
-
* @param {
|
|
94
|
-
* @param {import('#compiler').Binding[]} bindings
|
|
80
|
+
* @param {AST.ConstTag['metadata']} metadata
|
|
95
81
|
*/
|
|
96
|
-
function add_const_declaration(state, id, expression, metadata
|
|
82
|
+
function add_const_declaration(state, id, expression, metadata) {
|
|
97
83
|
// we need to eagerly evaluate the expression in order to hit any
|
|
98
84
|
// 'Cannot access x before initialization' errors
|
|
99
85
|
const after = dev ? [b.stmt(b.call('$.get', id))] : [];
|
|
100
86
|
|
|
101
|
-
const
|
|
102
|
-
const blockers = [...metadata.dependencies]
|
|
87
|
+
const blockers = [...metadata.expression.dependencies]
|
|
103
88
|
.map((dep) => dep.blocker)
|
|
104
89
|
.filter((b) => b !== null && b.object !== state.async_consts?.id);
|
|
105
90
|
|
|
106
|
-
if (
|
|
91
|
+
if (metadata.promises_id) {
|
|
107
92
|
const run = (state.async_consts ??= {
|
|
108
|
-
id:
|
|
93
|
+
id: metadata.promises_id,
|
|
109
94
|
thunks: []
|
|
110
95
|
});
|
|
111
96
|
|
|
112
97
|
state.consts.push(b.let(id));
|
|
113
98
|
|
|
114
|
-
|
|
115
|
-
|
|
99
|
+
/** @type {Statement | undefined} */
|
|
100
|
+
let promise_stmt;
|
|
116
101
|
|
|
117
102
|
if (blockers.length === 1) {
|
|
118
|
-
|
|
103
|
+
promise_stmt = b.stmt(b.await(b.member(/** @type {Expression} */ (blockers[0]), 'promise')));
|
|
119
104
|
} else if (blockers.length > 0) {
|
|
120
|
-
|
|
105
|
+
promise_stmt = b.stmt(b.await(b.call('$.wait', b.array(blockers))));
|
|
121
106
|
}
|
|
122
107
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
108
|
+
// keep the number of thunks pushed in sync with ConstTag in analysis phase
|
|
109
|
+
const assignment = b.assignment('=', id, expression);
|
|
110
|
+
if (promise_stmt) {
|
|
111
|
+
run.thunks.push(b.thunk(b.block([promise_stmt, b.stmt(assignment)]), true));
|
|
112
|
+
} else {
|
|
113
|
+
run.thunks.push(b.thunk(assignment, metadata.expression.has_await));
|
|
129
114
|
}
|
|
130
115
|
} else {
|
|
131
116
|
state.consts.push(b.const(id, expression));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Expression, Pattern } from 'estree' */
|
|
1
|
+
/** @import { Expression, Pattern, Statement } from 'estree' */
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
3
|
/** @import { ComponentContext } from '../types.js' */
|
|
4
4
|
import * as b from '#compiler/builders';
|
|
@@ -12,36 +12,37 @@ export function ConstTag(node, context) {
|
|
|
12
12
|
const declaration = node.declaration.declarations[0];
|
|
13
13
|
const id = /** @type {Pattern} */ (context.visit(declaration.id));
|
|
14
14
|
const init = /** @type {Expression} */ (context.visit(declaration.init));
|
|
15
|
-
const has_await = node.metadata.expression.has_await;
|
|
16
15
|
const blockers = [...node.metadata.expression.dependencies]
|
|
17
16
|
.map((dep) => dep.blocker)
|
|
18
17
|
.filter((b) => b !== null && b.object !== context.state.async_consts?.id);
|
|
19
18
|
|
|
20
|
-
if (
|
|
19
|
+
if (node.metadata.promises_id) {
|
|
21
20
|
const run = (context.state.async_consts ??= {
|
|
22
|
-
id:
|
|
21
|
+
id: node.metadata.promises_id,
|
|
23
22
|
thunks: []
|
|
24
23
|
});
|
|
25
24
|
|
|
26
25
|
const identifiers = extract_identifiers(declaration.id);
|
|
27
|
-
const bindings = context.state.scope.get_bindings(declaration);
|
|
28
26
|
|
|
29
27
|
for (const identifier of identifiers) {
|
|
30
28
|
context.state.init.push(b.let(identifier.name));
|
|
31
29
|
}
|
|
32
30
|
|
|
31
|
+
/** @type {Statement | undefined} */
|
|
32
|
+
let promise_stmt;
|
|
33
|
+
|
|
33
34
|
if (blockers.length === 1) {
|
|
34
|
-
|
|
35
|
+
promise_stmt = b.stmt(b.await(/** @type {Expression} */ (blockers[0])));
|
|
35
36
|
} else if (blockers.length > 0) {
|
|
36
|
-
|
|
37
|
+
promise_stmt = b.stmt(b.await(b.call('Promise.all', b.array(blockers))));
|
|
37
38
|
}
|
|
38
39
|
|
|
40
|
+
// keep the number of thunks pushed in sync with ConstTag in analysis phase
|
|
39
41
|
const assignment = b.assignment('=', id, init);
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
binding.blocker = blocker;
|
|
42
|
+
if (promise_stmt) {
|
|
43
|
+
run.thunks.push(b.thunk(b.block([promise_stmt, b.stmt(assignment)]), true));
|
|
44
|
+
} else {
|
|
45
|
+
run.thunks.push(b.thunk(assignment, node.metadata.expression.has_await));
|
|
45
46
|
}
|
|
46
47
|
} else {
|
|
47
48
|
context.state.init.push(b.const(id, init));
|
|
@@ -62,6 +62,8 @@ export const STATE_SYMBOL = Symbol('$state');
|
|
|
62
62
|
export const LEGACY_PROPS = Symbol('legacy props');
|
|
63
63
|
export const LOADING_ATTR_SYMBOL = Symbol('');
|
|
64
64
|
export const PROXY_PATH_SYMBOL = Symbol('proxy path');
|
|
65
|
+
/** An anchor might change, via this symbol on the original anchor we can tell HMR about the updated anchor */
|
|
66
|
+
export const HMR_ANCHOR = Symbol('hmr anchor');
|
|
65
67
|
|
|
66
68
|
/** allow users to ignore aborted signal errors if `reason.name === 'StaleReactionError` */
|
|
67
69
|
export const STALE_REACTION = new (class StaleReactionError extends Error {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @import { Effect, TemplateNode } from '#client' */
|
|
2
2
|
import { FILENAME, HMR } from '../../../constants.js';
|
|
3
|
-
import { EFFECT_TRANSPARENT } from '#client/constants';
|
|
3
|
+
import { EFFECT_TRANSPARENT, HMR_ANCHOR } from '#client/constants';
|
|
4
4
|
import { hydrate_node, hydrating } from '../dom/hydration.js';
|
|
5
5
|
import { block, branch, destroy_effect } from '../reactivity/effects.js';
|
|
6
6
|
import { set, source } from '../reactivity/sources.js';
|
|
@@ -15,10 +15,10 @@ export function hmr(fn) {
|
|
|
15
15
|
const current = source(fn);
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @param {TemplateNode}
|
|
18
|
+
* @param {TemplateNode} initial_anchor
|
|
19
19
|
* @param {any} props
|
|
20
20
|
*/
|
|
21
|
-
function wrapper(
|
|
21
|
+
function wrapper(initial_anchor, props) {
|
|
22
22
|
let component = {};
|
|
23
23
|
let instance = {};
|
|
24
24
|
|
|
@@ -26,6 +26,7 @@ export function hmr(fn) {
|
|
|
26
26
|
let effect;
|
|
27
27
|
|
|
28
28
|
let ran = false;
|
|
29
|
+
let anchor = initial_anchor;
|
|
29
30
|
|
|
30
31
|
block(() => {
|
|
31
32
|
if (component === (component = get(current))) {
|
|
@@ -39,6 +40,8 @@ export function hmr(fn) {
|
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
effect = branch(() => {
|
|
43
|
+
anchor = /** @type {any} */ (anchor)[HMR_ANCHOR] ?? anchor;
|
|
44
|
+
|
|
42
45
|
// when the component is invalidated, replace it without transitions
|
|
43
46
|
if (ran) set_should_intro(false);
|
|
44
47
|
|
|
@@ -35,7 +35,7 @@ import { queue_micro_task } from '../task.js';
|
|
|
35
35
|
import * as e from '../../errors.js';
|
|
36
36
|
import * as w from '../../warnings.js';
|
|
37
37
|
import { DEV } from 'esm-env';
|
|
38
|
-
import { Batch, current_batch, schedule_effect } from '../../reactivity/batch.js';
|
|
38
|
+
import { Batch, current_batch, previous_batch, schedule_effect } from '../../reactivity/batch.js';
|
|
39
39
|
import { internal_set, source } from '../../reactivity/sources.js';
|
|
40
40
|
import { tag } from '../../dev/tracing.js';
|
|
41
41
|
import { createSubscriber } from '../../../../reactivity/create-subscriber.js';
|
|
@@ -386,15 +386,29 @@ export class Boundary {
|
|
|
386
386
|
|
|
387
387
|
/** @param {unknown} error */
|
|
388
388
|
error(error) {
|
|
389
|
-
var onerror = this.#props.onerror;
|
|
390
|
-
let failed = this.#props.failed;
|
|
391
|
-
|
|
392
389
|
// If we have nothing to capture the error, or if we hit an error while
|
|
393
390
|
// rendering the fallback, re-throw for another boundary to handle
|
|
394
|
-
if (!onerror && !failed) {
|
|
391
|
+
if (!this.#props.onerror && !this.#props.failed) {
|
|
395
392
|
throw error;
|
|
396
393
|
}
|
|
397
394
|
|
|
395
|
+
if (current_batch?.is_fork) {
|
|
396
|
+
if (this.#main_effect) current_batch.skip_effect(this.#main_effect);
|
|
397
|
+
if (this.#pending_effect) current_batch.skip_effect(this.#pending_effect);
|
|
398
|
+
if (this.#failed_effect) current_batch.skip_effect(this.#failed_effect);
|
|
399
|
+
|
|
400
|
+
current_batch.on_fork_commit(() => {
|
|
401
|
+
this.#handle_error(error);
|
|
402
|
+
});
|
|
403
|
+
} else {
|
|
404
|
+
this.#handle_error(error);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
/**
|
|
409
|
+
* @param {unknown} error
|
|
410
|
+
*/
|
|
411
|
+
#handle_error(error) {
|
|
398
412
|
if (this.#main_effect) {
|
|
399
413
|
destroy_effect(this.#main_effect);
|
|
400
414
|
this.#main_effect = null;
|
|
@@ -416,6 +430,8 @@ export class Boundary {
|
|
|
416
430
|
set_hydrate_node(skip_nodes());
|
|
417
431
|
}
|
|
418
432
|
|
|
433
|
+
var onerror = this.#props.onerror;
|
|
434
|
+
let failed = this.#props.failed;
|
|
419
435
|
var did_reset = false;
|
|
420
436
|
var calling_on_error = false;
|
|
421
437
|
|
|
@@ -7,8 +7,10 @@ import {
|
|
|
7
7
|
pause_effect,
|
|
8
8
|
resume_effect
|
|
9
9
|
} from '../../reactivity/effects.js';
|
|
10
|
+
import { HMR_ANCHOR } from '../../constants.js';
|
|
10
11
|
import { hydrate_node, hydrating } from '../hydration.js';
|
|
11
12
|
import { create_text, should_defer_append } from '../operations.js';
|
|
13
|
+
import { DEV } from 'esm-env';
|
|
12
14
|
|
|
13
15
|
/**
|
|
14
16
|
* @typedef {{ effect: Effect, fragment: DocumentFragment }} Branch
|
|
@@ -91,6 +93,12 @@ export class BranchManager {
|
|
|
91
93
|
this.#onscreen.set(key, offscreen.effect);
|
|
92
94
|
this.#offscreen.delete(key);
|
|
93
95
|
|
|
96
|
+
if (DEV) {
|
|
97
|
+
// Tell hmr.js about the anchor it should use for updates,
|
|
98
|
+
// since the initial one will be removed
|
|
99
|
+
/** @type {any} */ (offscreen.fragment.lastChild)[HMR_ANCHOR] = this.anchor;
|
|
100
|
+
}
|
|
101
|
+
|
|
94
102
|
// remove the anchor...
|
|
95
103
|
/** @type {TemplateNode} */ (offscreen.fragment.lastChild).remove();
|
|
96
104
|
|
|
@@ -164,10 +164,26 @@ export async function save(promise) {
|
|
|
164
164
|
*/
|
|
165
165
|
export async function track_reactivity_loss(promise) {
|
|
166
166
|
var previous_async_effect = reactivity_loss_tracker;
|
|
167
|
+
// Ensure that unrelated reads after an async operation is kicked off don't cause false positives
|
|
168
|
+
queueMicrotask(() => {
|
|
169
|
+
if (reactivity_loss_tracker === previous_async_effect) {
|
|
170
|
+
set_reactivity_loss_tracker(null);
|
|
171
|
+
}
|
|
172
|
+
});
|
|
173
|
+
|
|
167
174
|
var value = await promise;
|
|
168
175
|
|
|
169
176
|
return () => {
|
|
170
177
|
set_reactivity_loss_tracker(previous_async_effect);
|
|
178
|
+
// While this can result in false negatives it also guards against the more important
|
|
179
|
+
// false positives that would occur if this is the last in a chain of async operations,
|
|
180
|
+
// and the reactivity_loss_tracker would then stay around until the next async operation happens.
|
|
181
|
+
queueMicrotask(() => {
|
|
182
|
+
if (reactivity_loss_tracker === previous_async_effect) {
|
|
183
|
+
set_reactivity_loss_tracker(null);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
|
|
171
187
|
return value;
|
|
172
188
|
};
|
|
173
189
|
}
|
|
@@ -206,7 +222,9 @@ export async function* for_await_track_reactivity_loss(iterable) {
|
|
|
206
222
|
normal_completion = true;
|
|
207
223
|
break;
|
|
208
224
|
}
|
|
225
|
+
var prev = reactivity_loss_tracker;
|
|
209
226
|
yield value;
|
|
227
|
+
set_reactivity_loss_tracker(prev);
|
|
210
228
|
}
|
|
211
229
|
} finally {
|
|
212
230
|
// If the iterator had an abrupt completion and `return` is defined on the iterator, call it and return the value
|
|
@@ -265,6 +283,8 @@ export function run(thunks) {
|
|
|
265
283
|
for (const fn of thunks.slice(1)) {
|
|
266
284
|
promise = promise
|
|
267
285
|
.then(() => {
|
|
286
|
+
restore();
|
|
287
|
+
|
|
268
288
|
if (errored) {
|
|
269
289
|
throw errored.error;
|
|
270
290
|
}
|
|
@@ -273,7 +293,6 @@ export function run(thunks) {
|
|
|
273
293
|
throw STALE_REACTION;
|
|
274
294
|
}
|
|
275
295
|
|
|
276
|
-
restore();
|
|
277
296
|
return fn();
|
|
278
297
|
})
|
|
279
298
|
.catch(handle_error);
|
|
@@ -120,6 +120,12 @@ export class Batch {
|
|
|
120
120
|
*/
|
|
121
121
|
#discard_callbacks = new Set();
|
|
122
122
|
|
|
123
|
+
/**
|
|
124
|
+
* Callbacks that should run only when a fork is committed.
|
|
125
|
+
* @type {Set<(batch: Batch) => void>}
|
|
126
|
+
*/
|
|
127
|
+
#fork_commit_callbacks = new Set();
|
|
128
|
+
|
|
123
129
|
/**
|
|
124
130
|
* Async effects that are currently in flight
|
|
125
131
|
* @type {Map<Effect, number>}
|
|
@@ -489,6 +495,7 @@ export class Batch {
|
|
|
489
495
|
discard() {
|
|
490
496
|
for (const fn of this.#discard_callbacks) fn(this);
|
|
491
497
|
this.#discard_callbacks.clear();
|
|
498
|
+
this.#fork_commit_callbacks.clear();
|
|
492
499
|
|
|
493
500
|
batches.delete(this);
|
|
494
501
|
}
|
|
@@ -686,6 +693,16 @@ export class Batch {
|
|
|
686
693
|
this.#discard_callbacks.add(fn);
|
|
687
694
|
}
|
|
688
695
|
|
|
696
|
+
/** @param {(batch: Batch) => void} fn */
|
|
697
|
+
on_fork_commit(fn) {
|
|
698
|
+
this.#fork_commit_callbacks.add(fn);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
run_fork_commit_callbacks() {
|
|
702
|
+
for (const fn of this.#fork_commit_callbacks) fn(this);
|
|
703
|
+
this.#fork_commit_callbacks.clear();
|
|
704
|
+
}
|
|
705
|
+
|
|
689
706
|
settled() {
|
|
690
707
|
return (this.#deferred ??= deferred()).promise;
|
|
691
708
|
}
|
|
@@ -1212,6 +1229,10 @@ export function fork(fn) {
|
|
|
1212
1229
|
source.wv = increment_write_version();
|
|
1213
1230
|
}
|
|
1214
1231
|
|
|
1232
|
+
batch.activate();
|
|
1233
|
+
batch.run_fork_commit_callbacks();
|
|
1234
|
+
batch.deactivate();
|
|
1235
|
+
|
|
1215
1236
|
// trigger any `$state.eager(...)` expressions with the new state.
|
|
1216
1237
|
// eager effects don't get scheduled like other effects, so we
|
|
1217
1238
|
// can't just encounter them during traversal, we need to
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Derived, Effect, Source } from '#client' */
|
|
1
|
+
/** @import { Derived, Effect, Reaction, Source, Value } from '#client' */
|
|
2
2
|
/** @import { Batch } from './batch.js'; */
|
|
3
3
|
/** @import { Boundary } from '../dom/blocks/boundary.js'; */
|
|
4
4
|
import { DEV } from 'esm-env';
|
|
@@ -12,7 +12,8 @@ import {
|
|
|
12
12
|
WAS_MARKED,
|
|
13
13
|
DESTROYED,
|
|
14
14
|
CLEAN,
|
|
15
|
-
REACTION_RAN
|
|
15
|
+
REACTION_RAN,
|
|
16
|
+
INERT
|
|
16
17
|
} from '#client/constants';
|
|
17
18
|
import {
|
|
18
19
|
active_reaction,
|
|
@@ -23,7 +24,9 @@ import {
|
|
|
23
24
|
push_reaction_value,
|
|
24
25
|
is_destroying_effect,
|
|
25
26
|
update_effect,
|
|
26
|
-
remove_reactions
|
|
27
|
+
remove_reactions,
|
|
28
|
+
skipped_deps,
|
|
29
|
+
new_deps
|
|
27
30
|
} from '../runtime.js';
|
|
28
31
|
import { equals, safe_equals } from './equality.js';
|
|
29
32
|
import * as e from '../errors.js';
|
|
@@ -48,11 +51,11 @@ import { set_signal_status, update_derived_status } from './status.js';
|
|
|
48
51
|
/**
|
|
49
52
|
* This allows us to track 'reactivity loss' that occurs when signals
|
|
50
53
|
* are read after a non-context-restoring `await`. Dev-only
|
|
51
|
-
* @type {{ effect: Effect, warned: boolean } | null}
|
|
54
|
+
* @type {{ effect: Effect, effect_deps: Set<Value>, warned: boolean } | null}
|
|
52
55
|
*/
|
|
53
56
|
export let reactivity_loss_tracker = null;
|
|
54
57
|
|
|
55
|
-
/** @param {{ effect: Effect, warned: boolean } | null} v */
|
|
58
|
+
/** @param {{ effect: Effect, effect_deps: Set<Value>, warned: boolean } | null} v */
|
|
56
59
|
export function set_reactivity_loss_tracker(v) {
|
|
57
60
|
reactivity_loss_tracker = v;
|
|
58
61
|
}
|
|
@@ -67,10 +70,6 @@ export const recent_async_deriveds = new Set();
|
|
|
67
70
|
/*#__NO_SIDE_EFFECTS__*/
|
|
68
71
|
export function derived(fn) {
|
|
69
72
|
var flags = DERIVED | DIRTY;
|
|
70
|
-
var parent_derived =
|
|
71
|
-
active_reaction !== null && (active_reaction.f & DERIVED) !== 0
|
|
72
|
-
? /** @type {Derived} */ (active_reaction)
|
|
73
|
-
: null;
|
|
74
73
|
|
|
75
74
|
if (active_effect !== null) {
|
|
76
75
|
// Since deriveds are evaluated lazily, any effects created inside them are
|
|
@@ -90,7 +89,7 @@ export function derived(fn) {
|
|
|
90
89
|
rv: 0,
|
|
91
90
|
v: /** @type {V} */ (UNINITIALIZED),
|
|
92
91
|
wv: 0,
|
|
93
|
-
parent:
|
|
92
|
+
parent: active_effect,
|
|
94
93
|
ac: null
|
|
95
94
|
};
|
|
96
95
|
|
|
@@ -128,15 +127,12 @@ export function async_derived(fn, label, location) {
|
|
|
128
127
|
var deferreds = new Map();
|
|
129
128
|
|
|
130
129
|
async_effect(() => {
|
|
130
|
+
var effect = /** @type {Effect} */ (active_effect);
|
|
131
|
+
|
|
131
132
|
if (DEV) {
|
|
132
|
-
reactivity_loss_tracker = {
|
|
133
|
-
effect: /** @type {Effect} */ (active_effect),
|
|
134
|
-
warned: false
|
|
135
|
-
};
|
|
133
|
+
reactivity_loss_tracker = { effect, effect_deps: new Set(), warned: false };
|
|
136
134
|
}
|
|
137
135
|
|
|
138
|
-
var effect = /** @type {Effect} */ (active_effect);
|
|
139
|
-
|
|
140
136
|
/** @type {ReturnType<typeof deferred<V>>} */
|
|
141
137
|
var d = deferred();
|
|
142
138
|
promise = d.promise;
|
|
@@ -152,6 +148,24 @@ export function async_derived(fn, label, location) {
|
|
|
152
148
|
}
|
|
153
149
|
|
|
154
150
|
if (DEV) {
|
|
151
|
+
if (reactivity_loss_tracker) {
|
|
152
|
+
// Reused deps from previous run (indices 0 to skipped_deps-1)
|
|
153
|
+
// We deliberately only track direct dependencies of the async expression to encourage
|
|
154
|
+
// dependencies being directly visible at the point of the expression
|
|
155
|
+
if (effect.deps !== null) {
|
|
156
|
+
for (let i = 0; i < skipped_deps; i += 1) {
|
|
157
|
+
reactivity_loss_tracker.effect_deps.add(effect.deps[i]);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// New deps discovered this run
|
|
162
|
+
if (new_deps !== null) {
|
|
163
|
+
for (let i = 0; i < new_deps.length; i += 1) {
|
|
164
|
+
reactivity_loss_tracker.effect_deps.add(new_deps[i]);
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
155
169
|
reactivity_loss_tracker = null;
|
|
156
170
|
}
|
|
157
171
|
|
|
@@ -320,23 +334,6 @@ export function destroy_derived_effects(derived) {
|
|
|
320
334
|
*/
|
|
321
335
|
let stack = [];
|
|
322
336
|
|
|
323
|
-
/**
|
|
324
|
-
* @param {Derived} derived
|
|
325
|
-
* @returns {Effect | null}
|
|
326
|
-
*/
|
|
327
|
-
function get_derived_parent_effect(derived) {
|
|
328
|
-
var parent = derived.parent;
|
|
329
|
-
while (parent !== null) {
|
|
330
|
-
if ((parent.f & DERIVED) === 0) {
|
|
331
|
-
// The original parent effect might've been destroyed but the derived
|
|
332
|
-
// is used elsewhere now - do not return the destroyed effect in that case
|
|
333
|
-
return (parent.f & DESTROYED) === 0 ? /** @type {Effect} */ (parent) : null;
|
|
334
|
-
}
|
|
335
|
-
parent = parent.parent;
|
|
336
|
-
}
|
|
337
|
-
return null;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
337
|
/**
|
|
341
338
|
* @template T
|
|
342
339
|
* @param {Derived} derived
|
|
@@ -345,8 +342,15 @@ function get_derived_parent_effect(derived) {
|
|
|
345
342
|
export function execute_derived(derived) {
|
|
346
343
|
var value;
|
|
347
344
|
var prev_active_effect = active_effect;
|
|
345
|
+
var parent = derived.parent;
|
|
346
|
+
|
|
347
|
+
if (!is_destroying_effect && parent !== null && (parent.f & (DESTROYED | INERT)) !== 0) {
|
|
348
|
+
w.derived_inert();
|
|
349
|
+
|
|
350
|
+
return derived.v;
|
|
351
|
+
}
|
|
348
352
|
|
|
349
|
-
set_active_effect(
|
|
353
|
+
set_active_effect(parent);
|
|
350
354
|
|
|
351
355
|
if (DEV) {
|
|
352
356
|
let prev_eager_effects = eager_effects;
|
|
@@ -111,9 +111,9 @@ export function push_reaction_value(value) {
|
|
|
111
111
|
* and until a new dependency is accessed — we track this via `skipped_deps`
|
|
112
112
|
* @type {null | Value[]}
|
|
113
113
|
*/
|
|
114
|
-
let new_deps = null;
|
|
114
|
+
export let new_deps = null;
|
|
115
115
|
|
|
116
|
-
let skipped_deps = 0;
|
|
116
|
+
export let skipped_deps = 0;
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
119
|
* Tracks writes that the effect it's executed in doesn't listen to yet,
|
|
@@ -580,7 +580,8 @@ export function get(signal) {
|
|
|
580
580
|
!untracking &&
|
|
581
581
|
reactivity_loss_tracker &&
|
|
582
582
|
!reactivity_loss_tracker.warned &&
|
|
583
|
-
(reactivity_loss_tracker.effect.f & REACTION_IS_UPDATING) === 0
|
|
583
|
+
(reactivity_loss_tracker.effect.f & REACTION_IS_UPDATING) === 0 &&
|
|
584
|
+
!reactivity_loss_tracker.effect_deps.has(signal)
|
|
584
585
|
) {
|
|
585
586
|
reactivity_loss_tracker.warned = true;
|
|
586
587
|
|
|
@@ -74,6 +74,17 @@ export function console_log_state(method) {
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
/**
|
|
78
|
+
* Reading a derived belonging to a now-destroyed effect may result in stale values
|
|
79
|
+
*/
|
|
80
|
+
export function derived_inert() {
|
|
81
|
+
if (DEV) {
|
|
82
|
+
console.warn(`%c[svelte] derived_inert\n%cReading a derived belonging to a now-destroyed effect may result in stale values\nhttps://svelte.dev/e/derived_inert`, bold, normal);
|
|
83
|
+
} else {
|
|
84
|
+
console.warn(`https://svelte.dev/e/derived_inert`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
77
88
|
/**
|
|
78
89
|
* %handler% should be a function. Did you mean to %suggestion%?
|
|
79
90
|
* @param {string} handler
|
package/src/version.js
CHANGED
package/types/index.d.ts.map
CHANGED
|
@@ -273,6 +273,6 @@
|
|
|
273
273
|
null,
|
|
274
274
|
null
|
|
275
275
|
],
|
|
276
|
-
"mappings": ";;;;;;;;;kBAUiBA,2BAA2BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmC/BC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAwEhBC,kBAAkBA;;;;;;;;;;;;;;;;;;;;;;;;kBAwBbC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoCbC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;aAwBrBC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAiCfC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6BdC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;kBAuBRC,OAAOA;;;;;;;;;;;;;;;;kBAgBPC,eAAeA;;;;;;;;;;;;;;;;aAgBpBC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+CPC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzSLC,cAAcA;;;;;;;;;;;;iBAsBdC,OAAOA;;;;;;;;iBAwBPC,SAASA;;;;;;;;;;;;;;;;;;;;;;iBA0CTC,qBAAqBA;;;;;;;;;;iBA2CrBC,YAAYA;;;;;;;;;;iBAuBZC,WAAWA;iBClNXC,UAAUA;;;;iBC4DVC,gBAAgBA;;;;;MCvEpBC,WAAWA;;;;;
|
|
276
|
+
"mappings": ";;;;;;;;;kBAUiBA,2BAA2BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAmC/BC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAwEhBC,kBAAkBA;;;;;;;;;;;;;;;;;;;;;;;;kBAwBbC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAoCbC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;aAwBrBC,eAAeA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aAiCfC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aA6BdC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;kBAuBRC,OAAOA;;;;;;;;;;;;;;;;kBAgBPC,eAAeA;;;;;;;;;;;;;;;;aAgBpBC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA+CPC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCzSLC,cAAcA;;;;;;;;;;;;iBAsBdC,OAAOA;;;;;;;;iBAwBPC,SAASA;;;;;;;;;;;;;;;;;;;;;;iBA0CTC,qBAAqBA;;;;;;;;;;iBA2CrBC,YAAYA;;;;;;;;;;iBAuBZC,WAAWA;iBClNXC,UAAUA;;;;iBC4DVC,gBAAgBA;;;;;MCvEpBC,WAAWA;;;;;iBCy0BPC,SAASA;;;;;;;;;;;;;;;;;;iBA8VTC,IAAIA;;;;;;;;iBCxlCJC,aAAaA;;;;;;;;iBAyBbC,UAAUA;;;;;;;;;;;iBAoBVC,UAAUA;;;;;;iBA2BVC,UAAUA;;;;;;;iBAaVC,cAAcA;;;;;;iBCnGdC,KAAKA;;;;;iBA6BLC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8NPC,OAAOA;;;;;;iBCmLDC,IAAIA;;;;;;iBAwBVC,OAAOA;;;;;;;;;;;;;;iBA0OPC,OAAOA;MC7uBXC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBCqBFC,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA6BZC,MAAMA;;;;;;;;;;;;;;;;;;;;kBCtDNC,eAAeA;;;;;;;;kBAQfC,UAAUA;;;;;;;;;;iBCGXC,IAAIA;;;;;;;;;;;;;;;;kBCLHC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;iBCsBXC,mBAAmBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WJHlBN,YAAYA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA6BZC,MAAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBKjCPM,OAAOA;;;;;;iBA8CPC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8DbC,QAAQA;;;;iBA+DRC,IAAIA;;;;kBC9LHC,SAASA;;;;;;;;;;;;;;;;;;;;;;;aAuBdC,kBAAkBA;;;;;;;;;;;;;;aAclBC,YAAYA;;;;;;;;;;;;;;;;;;;;;;kBAsBPC,iBAAiBA;;;;;;;;kBCjDjBC,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAsCbC,OAAOA;;kBAEPC,YAAYA;;MAEjBC,aAAaA;;;;;;;kBAWRC,cAAcA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAuIdC,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MC9KzBC,SAASA;;kBAEJC,GAAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCoTUC,UAAUA;;;;;;;;;;;iBC9TxBC,KAAKA;;;;;;;cCbRC,OAAOA;;;;;;iBCqHJC,OAAOA;;;;;;;;;;;;;;;;WCzHNC,IAAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MCCTC,OAAOA;;;;;;;;;iBCMHC,MAAMA;;iBAQNC,SAASA;;iBAUTC,MAAMA;;iBASNC,OAAOA;;iBASPC,SAASA;;iBAqBTC,WAAWA;;iBAQXC,QAAQA;;iBAQRC,SAASA;;iBASTC,MAAMA;;iBAQNC,OAAOA;;iBAQPC,UAAUA;;iBAQVC,OAAOA;;iBAQPC,QAAQA;;iBASRC,YAAYA;;iBAaZC,SAASA;;iBAQTC,UAAUA;;iBAQVC,SAASA;;iBAYTC,MAAMA;;iBAQNC,OAAOA;;iBAQPC,SAASA;;iBAWTC,MAAMA;;iBAQNC,OAAOA;;iBAQPC,UAAUA;;iBAQVC,OAAOA;;iBAQPC,QAAQA;;iBAQRC,UAAUA;;iBASVC,OAAOA;;iBAQPC,QAAQA;;iBAQRC,SAASA;;iBAQTC,MAAMA;;iBAUNC,OAAOA;;;;;;;;;;;;;iBC5PPC,oBAAoBA;;;;;;;;;iBAkBpBC,gBAAgBA;;;;;;iBA4IhBC,GAAGA;;;;;iBAuBHC,QAAQA;;;;;iBAqCRC,aAAaA;;;;aAzLkKC,mBAAmBA;;;;;;;;iBCtDlMC,OAAOA;;;;;iBAgBPC,IAAIA;;;;;iBAiBJC,eAAeA;;;;;iBAefC,IAAIA;;;;;iBAkBJC,wBAAwBA;;;;;iBAexBC,cAAcA;;;;;iBAedC,OAAOA;;;;;iBAcPC,UAAUA;;;;;;;kBCtHTC,aAAaA;;;;;;kBAMbC,mBAAmBA;;;;;;;;;;;;;;;;;;;aAmBxBC,OAAOA;;kBAEFC,YAAYA;;;;;;;;;;;kBA0ChBC,MAAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAANA,MAAMA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBA4CFC,OAAOA;;;;;MClHZC,UAAUA;;;MAGVC,YAAYA;;;WAoBPC,QAAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCKZC,oBAAoBA;;;;;;iBCsCjBC,MAAMA;;;;;;iBCqBNC,OAAOA;;;;;;;;;;;;;;;;;cAyFVC,KAAKA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCxILC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCKVC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCMTC,SAASA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cCXTC,SAASA;;;;OCnCTC,OAAOA;;;;;;;;;;;;;;;;;;;;;;;;;;;cA4BPC,qBAAqBA;;;;;;;;;;;;;;;;;;;;;;;cCErBC,UAAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBCiBPC,gBAAgBA;OChDnBC,aAAaA;;;;;;;;;;;;;;;cCMbC,OAAOA;;;;;cASPC,OAAOA;;;;;cASPC,UAAUA;;;;;cASVC,WAAWA;;;;;cASXC,UAAUA;;;;;cASVC,WAAWA;;;;;cASXC,UAAUA;;;;;cAuBVC,SAASA;;;;;cAuBTC,MAAMA;;;;;;;cAmBNC,gBAAgBA;;;OD7HhBV,aAAaA;;;;;;;;;;;;;;;;iBEEVW,MAAMA;;;;;;;;;;;;;;;;;;;;;;;;;;MCUVC,GAAGA;;MAoBHC,YAAYA;;WAEPC,gBAAgBA;;;;;;;;;;;;MAYrBC,YAAYA;;;;;;;adlDZ9B,UAAUA;;;aAGVC,YAAYA;;;aAGZL,OAAOA;;;;;;;;;;;aAWPmC,iBAAiBA;;;;;;kBAMZ7B,QAAQA;;;;;;;;;;kBAUR8B,QAAQA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBefTC,QAAQA;;;;;;iBAcRC,QAAQA;;;;;;;;;;;;;;;;;;iBA4JRC,QAAQA;;;;;iBAcRC,GAAGA;;;;;;;;;;;;aC3MPC,cAAcA;;kBAETC,gBAAgBA;;;;;;;;kBAQhBC,UAAUA;;;;;;;;kBAQVC,UAAUA;;;;;;kBAMVC,SAASA;;;;;;;;;kBASTC,WAAWA;;;;;;;kBAOXC,WAAWA;;;;;;;;kBAQXC,UAAUA;;;;;;;kBAOVC,eAAeA;;;;;;;;;iBClBhBC,IAAIA;;;;;iBAwBJC,IAAIA;;;;;iBAiBJC,GAAGA;;;;;iBA6BHC,KAAKA;;;;;iBAmDLC,KAAKA;;;;;iBA2BLC,IAAIA;;;;;;;iBA+CJC,SAASA;;;;;;;;;;;;;;;;;;;iBCrLTC,EAAEA;;;;;;;;;;;iBAAFA,EAAEA;;;;;;;;;;;iBAAFA,EAAEA;;;;;;;;;;;iBAAFA,EAAEA;;;;;;;;;;;iBAAFA,EAAEA;;;;;;;;;;;;a/BzBNzH,kBAAkBA;;aAclBC,YAAYA;;aAsBPC,iBAAiBA;;aA3DjBH,SAASA;;aAuET2H,kBAAkBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aCRlBnH,cAAcA;;aAfdH,OAAOA;;;MAIZE,aAAaA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;WAkJRE,oBAAoBA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;MC9KzBC,SAASA",
|
|
277
277
|
"ignoreList": []
|
|
278
278
|
}
|