svelte 5.46.0 → 5.46.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/1-parse/read/script.js +8 -1
- package/src/compiler/phases/2-analyze/index.js +2 -1
- package/src/compiler/phases/2-analyze/visitors/EachBlock.js +3 -1
- package/src/compiler/phases/3-transform/client/transform-client.js +2 -8
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +3 -1
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +5 -6
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +1 -1
- package/src/compiler/phases/3-transform/shared/transform-async.js +8 -1
- package/src/internal/client/dev/hmr.js +25 -14
- package/src/internal/client/dom/blocks/async.js +1 -1
- package/src/internal/client/dom/blocks/boundary.js +52 -17
- package/src/internal/client/index.js +0 -1
- package/src/internal/client/reactivity/async.js +4 -54
- package/src/internal/client/reactivity/batch.js +55 -87
- package/src/internal/client/reactivity/deriveds.js +18 -12
- package/src/internal/client/reactivity/effects.js +2 -2
- package/src/internal/client/reactivity/sources.js +5 -3
- package/src/internal/client/reactivity/status.js +25 -0
- package/src/internal/client/reactivity/utils.js +40 -0
- package/src/internal/client/runtime.js +45 -45
- package/src/legacy/legacy-client.js +2 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +4 -4
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -6,6 +6,7 @@ import { regex_not_newline_characters } from '../../patterns.js';
|
|
|
6
6
|
import * as e from '../../../errors.js';
|
|
7
7
|
import * as w from '../../../warnings.js';
|
|
8
8
|
import { is_text_attribute } from '../../../utils/ast.js';
|
|
9
|
+
import { locator } from '../../../state.js';
|
|
9
10
|
|
|
10
11
|
const regex_closing_script_tag = /<\/script\s*>/;
|
|
11
12
|
const regex_starts_with_closing_script_tag = /^<\/script\s*>/;
|
|
@@ -39,9 +40,15 @@ export function read_script(parser, start, attributes) {
|
|
|
39
40
|
parser.acorn_error(err);
|
|
40
41
|
}
|
|
41
42
|
|
|
42
|
-
// TODO is this necessary?
|
|
43
43
|
ast.start = script_start;
|
|
44
44
|
|
|
45
|
+
if (ast.loc) {
|
|
46
|
+
// Acorn always uses `0` as the start of a `Program`, but for sourcemap purposes
|
|
47
|
+
// we need it to be the start of the `<script>` contents
|
|
48
|
+
({ line: ast.loc.start.line, column: ast.loc.start.column } = locator(start));
|
|
49
|
+
({ line: ast.loc.end.line, column: ast.loc.end.column } = locator(parser.index));
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
/** @type {'default' | 'module'} */
|
|
46
53
|
let context = 'default';
|
|
47
54
|
|
|
@@ -657,7 +657,8 @@ export function analyze_component(root, source, options) {
|
|
|
657
657
|
if (
|
|
658
658
|
binding &&
|
|
659
659
|
binding.kind === 'normal' &&
|
|
660
|
-
binding.declaration_kind !== 'import'
|
|
660
|
+
binding.declaration_kind !== 'import' &&
|
|
661
|
+
binding.declaration_kind !== 'function'
|
|
661
662
|
) {
|
|
662
663
|
binding.kind = 'state';
|
|
663
664
|
binding.mutated = true;
|
|
@@ -54,7 +54,9 @@ export function EachBlock(node, context) {
|
|
|
54
54
|
|
|
55
55
|
// collect transitive dependencies...
|
|
56
56
|
for (const binding of node.metadata.expression.dependencies) {
|
|
57
|
-
|
|
57
|
+
if (binding.declaration_kind !== 'function') {
|
|
58
|
+
collect_transitive_dependencies(binding, node.metadata.transitive_deps);
|
|
59
|
+
}
|
|
58
60
|
}
|
|
59
61
|
|
|
60
62
|
// ...and ensure they are marked as state, so they can be turned
|
|
@@ -519,14 +519,9 @@ export function client_component(analysis, options) {
|
|
|
519
519
|
|
|
520
520
|
if (options.hmr) {
|
|
521
521
|
const id = b.id(analysis.name);
|
|
522
|
-
const HMR = b.id('$.HMR');
|
|
523
|
-
|
|
524
|
-
const existing = b.member(id, HMR, true);
|
|
525
|
-
const incoming = b.member(b.id('module.default'), HMR, true);
|
|
526
522
|
|
|
527
523
|
const accept_fn_body = [
|
|
528
|
-
b.stmt(b.
|
|
529
|
-
b.stmt(b.call('$.set', b.member(existing, 'source'), b.member(incoming, 'original')))
|
|
524
|
+
b.stmt(b.call(b.member(b.member(id, b.id('$.HMR'), true), 'update'), b.id('module.default')))
|
|
530
525
|
];
|
|
531
526
|
|
|
532
527
|
if (analysis.css.hash) {
|
|
@@ -535,8 +530,7 @@ export function client_component(analysis, options) {
|
|
|
535
530
|
}
|
|
536
531
|
|
|
537
532
|
const hmr = b.block([
|
|
538
|
-
b.stmt(b.assignment('=', id, b.call('$.hmr', id
|
|
539
|
-
|
|
533
|
+
b.stmt(b.assignment('=', id, b.call('$.hmr', id))),
|
|
540
534
|
b.stmt(b.call('import.meta.hot.accept', b.arrow([b.id('module')], b.block(accept_fn_body))))
|
|
541
535
|
]);
|
|
542
536
|
|
|
@@ -336,7 +336,9 @@ export function RegularElement(node, context) {
|
|
|
336
336
|
trimmed.every(
|
|
337
337
|
(node) =>
|
|
338
338
|
node.type === 'Text' ||
|
|
339
|
-
(!node.metadata.expression.has_state &&
|
|
339
|
+
(!node.metadata.expression.has_state &&
|
|
340
|
+
!node.metadata.expression.has_await &&
|
|
341
|
+
!node.metadata.expression.has_blockers())
|
|
340
342
|
) &&
|
|
341
343
|
trimmed.some((node) => node.type === 'ExpressionTag');
|
|
342
344
|
|
|
@@ -209,11 +209,11 @@ export function VariableDeclaration(node, context) {
|
|
|
209
209
|
let call = b.call(
|
|
210
210
|
'$.async_derived',
|
|
211
211
|
b.thunk(expression, true),
|
|
212
|
+
dev && b.literal(declarator.id.name),
|
|
212
213
|
location ? b.literal(location) : undefined
|
|
213
214
|
);
|
|
214
215
|
|
|
215
216
|
call = should_save ? save(call) : b.await(call);
|
|
216
|
-
if (dev) call = b.call('$.tag', call, b.literal(declarator.id.name));
|
|
217
217
|
|
|
218
218
|
declarations.push(b.declarator(declarator.id, call));
|
|
219
219
|
} else {
|
|
@@ -244,17 +244,16 @@ export function VariableDeclaration(node, context) {
|
|
|
244
244
|
call = b.call(
|
|
245
245
|
'$.async_derived',
|
|
246
246
|
b.thunk(expression, true),
|
|
247
|
+
dev &&
|
|
248
|
+
b.literal(
|
|
249
|
+
`[$derived ${declarator.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`
|
|
250
|
+
),
|
|
247
251
|
location ? b.literal(location) : undefined
|
|
248
252
|
);
|
|
249
253
|
|
|
250
254
|
call = should_save ? save(call) : b.await(call);
|
|
251
255
|
}
|
|
252
256
|
|
|
253
|
-
if (dev) {
|
|
254
|
-
const label = `[$derived ${declarator.id.type === 'ArrayPattern' ? 'iterable' : 'object'}]`;
|
|
255
|
-
call = b.call('$.tag', call, b.literal(label));
|
|
256
|
-
}
|
|
257
|
-
|
|
258
257
|
declarations.push(b.declarator(id, call));
|
|
259
258
|
}
|
|
260
259
|
|
|
@@ -134,7 +134,7 @@ export function build_template_chunk(
|
|
|
134
134
|
|
|
135
135
|
const evaluated = state.scope.evaluate(value);
|
|
136
136
|
|
|
137
|
-
has_await ||= node.metadata.expression.has_await;
|
|
137
|
+
has_await ||= node.metadata.expression.has_await || node.metadata.expression.has_blockers();
|
|
138
138
|
has_state ||= has_await || (node.metadata.expression.has_state && !evaluated.is_known);
|
|
139
139
|
|
|
140
140
|
if (values.length === 1) {
|
|
@@ -86,7 +86,14 @@ export function transform_body(instance_body, runner, transform) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
if (s.node.type === 'ExpressionStatement') {
|
|
89
|
-
|
|
89
|
+
// the expression may be a $inspect call, which will be transformed into an empty statement
|
|
90
|
+
const expression = /** @type {ESTree.Expression | ESTree.EmptyStatement} */ (
|
|
91
|
+
transform(s.node.expression)
|
|
92
|
+
);
|
|
93
|
+
|
|
94
|
+
if (expression.type === 'EmptyStatement') {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
90
97
|
|
|
91
98
|
return expression.type === 'AwaitExpression'
|
|
92
99
|
? b.thunk(expression, true)
|
|
@@ -1,23 +1,25 @@
|
|
|
1
|
-
/** @import {
|
|
1
|
+
/** @import { Effect, TemplateNode } from '#client' */
|
|
2
2
|
import { FILENAME, HMR } from '../../../constants.js';
|
|
3
3
|
import { EFFECT_TRANSPARENT } 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
|
-
import { source } from '../reactivity/sources.js';
|
|
6
|
+
import { set, source } from '../reactivity/sources.js';
|
|
7
7
|
import { set_should_intro } from '../render.js';
|
|
8
8
|
import { get } from '../runtime.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* @template {(anchor: Comment, props: any) => any} Component
|
|
12
|
-
* @param {Component}
|
|
13
|
-
* @param {() => Source<Component>} get_source
|
|
12
|
+
* @param {Component} fn
|
|
14
13
|
*/
|
|
15
|
-
export function hmr(
|
|
14
|
+
export function hmr(fn) {
|
|
15
|
+
const current = source(fn);
|
|
16
|
+
|
|
16
17
|
/**
|
|
17
18
|
* @param {TemplateNode} anchor
|
|
18
19
|
* @param {any} props
|
|
19
20
|
*/
|
|
20
21
|
function wrapper(anchor, props) {
|
|
22
|
+
let component = {};
|
|
21
23
|
let instance = {};
|
|
22
24
|
|
|
23
25
|
/** @type {Effect} */
|
|
@@ -26,8 +28,9 @@ export function hmr(original, get_source) {
|
|
|
26
28
|
let ran = false;
|
|
27
29
|
|
|
28
30
|
block(() => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
+
if (component === (component = get(current))) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
31
34
|
|
|
32
35
|
if (effect) {
|
|
33
36
|
// @ts-ignore
|
|
@@ -62,16 +65,24 @@ export function hmr(original, get_source) {
|
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
// @ts-expect-error
|
|
65
|
-
wrapper[FILENAME] =
|
|
68
|
+
wrapper[FILENAME] = fn[FILENAME];
|
|
66
69
|
|
|
67
70
|
// @ts-ignore
|
|
68
71
|
wrapper[HMR] = {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
72
|
+
fn,
|
|
73
|
+
current,
|
|
74
|
+
update: (/** @type {any} */ incoming) => {
|
|
75
|
+
// This logic ensures that the first version of the component is the one
|
|
76
|
+
// whose update function and therefore block effect is preserved across updates.
|
|
77
|
+
// If we don't do this dance and instead just use `incoming` as the new component
|
|
78
|
+
// and then update, we'll create an ever-growing stack of block effects.
|
|
79
|
+
|
|
80
|
+
// Trigger the original block effect
|
|
81
|
+
set(wrapper[HMR].current, incoming[HMR].fn);
|
|
82
|
+
|
|
83
|
+
// Replace the incoming source with the original one
|
|
84
|
+
incoming[HMR].current = wrapper[HMR].current;
|
|
85
|
+
}
|
|
75
86
|
};
|
|
76
87
|
|
|
77
88
|
return wrapper;
|
|
@@ -21,7 +21,7 @@ import { get_boundary } from './boundary.js';
|
|
|
21
21
|
export function async(node, blockers = [], expressions = [], fn) {
|
|
22
22
|
var boundary = get_boundary();
|
|
23
23
|
var batch = /** @type {Batch} */ (current_batch);
|
|
24
|
-
var blocking =
|
|
24
|
+
var blocking = boundary.is_rendered();
|
|
25
25
|
|
|
26
26
|
boundary.update_pending_count(1);
|
|
27
27
|
batch.increment(blocking);
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
BOUNDARY_EFFECT,
|
|
4
4
|
COMMENT_NODE,
|
|
5
|
+
DIRTY,
|
|
5
6
|
EFFECT_PRESERVED,
|
|
6
|
-
EFFECT_TRANSPARENT
|
|
7
|
+
EFFECT_TRANSPARENT,
|
|
8
|
+
MAYBE_DIRTY
|
|
7
9
|
} from '#client/constants';
|
|
8
10
|
import { HYDRATION_START_ELSE } from '../../../../constants.js';
|
|
9
11
|
import { component_context, set_component_context } from '../../context.js';
|
|
@@ -34,11 +36,13 @@ import { queue_micro_task } from '../task.js';
|
|
|
34
36
|
import * as e from '../../errors.js';
|
|
35
37
|
import * as w from '../../warnings.js';
|
|
36
38
|
import { DEV } from 'esm-env';
|
|
37
|
-
import { Batch } from '../../reactivity/batch.js';
|
|
39
|
+
import { Batch, schedule_effect } from '../../reactivity/batch.js';
|
|
38
40
|
import { internal_set, source } from '../../reactivity/sources.js';
|
|
39
41
|
import { tag } from '../../dev/tracing.js';
|
|
40
42
|
import { createSubscriber } from '../../../../reactivity/create-subscriber.js';
|
|
41
43
|
import { create_text } from '../operations.js';
|
|
44
|
+
import { defer_effect } from '../../reactivity/utils.js';
|
|
45
|
+
import { set_signal_status } from '../../reactivity/status.js';
|
|
42
46
|
|
|
43
47
|
/**
|
|
44
48
|
* @typedef {{
|
|
@@ -64,7 +68,7 @@ export class Boundary {
|
|
|
64
68
|
/** @type {Boundary | null} */
|
|
65
69
|
parent;
|
|
66
70
|
|
|
67
|
-
|
|
71
|
+
is_pending = false;
|
|
68
72
|
|
|
69
73
|
/** @type {TemplateNode} */
|
|
70
74
|
#anchor;
|
|
@@ -101,6 +105,12 @@ export class Boundary {
|
|
|
101
105
|
|
|
102
106
|
#is_creating_fallback = false;
|
|
103
107
|
|
|
108
|
+
/** @type {Set<Effect>} */
|
|
109
|
+
#dirty_effects = new Set();
|
|
110
|
+
|
|
111
|
+
/** @type {Set<Effect>} */
|
|
112
|
+
#maybe_dirty_effects = new Set();
|
|
113
|
+
|
|
104
114
|
/**
|
|
105
115
|
* A source containing the number of pending async deriveds/expressions.
|
|
106
116
|
* Only created if `$effect.pending()` is used inside the boundary,
|
|
@@ -134,7 +144,7 @@ export class Boundary {
|
|
|
134
144
|
|
|
135
145
|
this.parent = /** @type {Effect} */ (active_effect).b;
|
|
136
146
|
|
|
137
|
-
this
|
|
147
|
+
this.is_pending = !!this.#props.pending;
|
|
138
148
|
|
|
139
149
|
this.#effect = block(() => {
|
|
140
150
|
/** @type {Effect} */ (active_effect).b = this;
|
|
@@ -151,6 +161,10 @@ export class Boundary {
|
|
|
151
161
|
this.#hydrate_pending_content();
|
|
152
162
|
} else {
|
|
153
163
|
this.#hydrate_resolved_content();
|
|
164
|
+
|
|
165
|
+
if (this.#pending_count === 0) {
|
|
166
|
+
this.is_pending = false;
|
|
167
|
+
}
|
|
154
168
|
}
|
|
155
169
|
} else {
|
|
156
170
|
var anchor = this.#get_anchor();
|
|
@@ -164,7 +178,7 @@ export class Boundary {
|
|
|
164
178
|
if (this.#pending_count > 0) {
|
|
165
179
|
this.#show_pending_snippet();
|
|
166
180
|
} else {
|
|
167
|
-
this
|
|
181
|
+
this.is_pending = false;
|
|
168
182
|
}
|
|
169
183
|
}
|
|
170
184
|
|
|
@@ -184,10 +198,6 @@ export class Boundary {
|
|
|
184
198
|
} catch (error) {
|
|
185
199
|
this.error(error);
|
|
186
200
|
}
|
|
187
|
-
|
|
188
|
-
// Since server rendered resolved content, we never show pending state
|
|
189
|
-
// Even if client-side async operations are still running, the content is already displayed
|
|
190
|
-
this.#pending = false;
|
|
191
201
|
}
|
|
192
202
|
|
|
193
203
|
#hydrate_pending_content() {
|
|
@@ -212,7 +222,7 @@ export class Boundary {
|
|
|
212
222
|
this.#pending_effect = null;
|
|
213
223
|
});
|
|
214
224
|
|
|
215
|
-
this
|
|
225
|
+
this.is_pending = false;
|
|
216
226
|
}
|
|
217
227
|
});
|
|
218
228
|
}
|
|
@@ -220,7 +230,7 @@ export class Boundary {
|
|
|
220
230
|
#get_anchor() {
|
|
221
231
|
var anchor = this.#anchor;
|
|
222
232
|
|
|
223
|
-
if (this
|
|
233
|
+
if (this.is_pending) {
|
|
224
234
|
this.#pending_anchor = create_text();
|
|
225
235
|
this.#anchor.before(this.#pending_anchor);
|
|
226
236
|
|
|
@@ -231,11 +241,19 @@ export class Boundary {
|
|
|
231
241
|
}
|
|
232
242
|
|
|
233
243
|
/**
|
|
234
|
-
*
|
|
244
|
+
* Defer an effect inside a pending boundary until the boundary resolves
|
|
245
|
+
* @param {Effect} effect
|
|
246
|
+
*/
|
|
247
|
+
defer_effect(effect) {
|
|
248
|
+
defer_effect(effect, this.#dirty_effects, this.#maybe_dirty_effects);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Returns `false` if the effect exists inside a boundary whose pending snippet is shown
|
|
235
253
|
* @returns {boolean}
|
|
236
254
|
*/
|
|
237
|
-
|
|
238
|
-
return this
|
|
255
|
+
is_rendered() {
|
|
256
|
+
return !this.is_pending && (!this.parent || this.parent.is_rendered());
|
|
239
257
|
}
|
|
240
258
|
|
|
241
259
|
has_pending_snippet() {
|
|
@@ -298,7 +316,24 @@ export class Boundary {
|
|
|
298
316
|
this.#pending_count += d;
|
|
299
317
|
|
|
300
318
|
if (this.#pending_count === 0) {
|
|
301
|
-
this
|
|
319
|
+
this.is_pending = false;
|
|
320
|
+
|
|
321
|
+
// any effects that were encountered and deferred during traversal
|
|
322
|
+
// should be rescheduled — after the next traversal (which will happen
|
|
323
|
+
// immediately, due to the same update that brought us here)
|
|
324
|
+
// the effects will be flushed
|
|
325
|
+
for (const e of this.#dirty_effects) {
|
|
326
|
+
set_signal_status(e, DIRTY);
|
|
327
|
+
schedule_effect(e);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
for (const e of this.#maybe_dirty_effects) {
|
|
331
|
+
set_signal_status(e, MAYBE_DIRTY);
|
|
332
|
+
schedule_effect(e);
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
this.#dirty_effects.clear();
|
|
336
|
+
this.#maybe_dirty_effects.clear();
|
|
302
337
|
|
|
303
338
|
if (this.#pending_effect) {
|
|
304
339
|
pause_effect(this.#pending_effect, () => {
|
|
@@ -394,7 +429,7 @@ export class Boundary {
|
|
|
394
429
|
|
|
395
430
|
// we intentionally do not try to find the nearest pending boundary. If this boundary has one, we'll render it on reset
|
|
396
431
|
// but it would be really weird to show the parent's boundary on a child reset.
|
|
397
|
-
this
|
|
432
|
+
this.is_pending = this.has_pending_snippet();
|
|
398
433
|
|
|
399
434
|
this.#main_effect = this.#run(() => {
|
|
400
435
|
this.#is_creating_fallback = false;
|
|
@@ -404,7 +439,7 @@ export class Boundary {
|
|
|
404
439
|
if (this.#pending_count > 0) {
|
|
405
440
|
this.#show_pending_snippet();
|
|
406
441
|
} else {
|
|
407
|
-
this
|
|
442
|
+
this.is_pending = false;
|
|
408
443
|
}
|
|
409
444
|
};
|
|
410
445
|
|
|
@@ -25,7 +25,6 @@ import {
|
|
|
25
25
|
set_from_async_derived
|
|
26
26
|
} from './deriveds.js';
|
|
27
27
|
import { aborted } from './effects.js';
|
|
28
|
-
import { hydrate_next, hydrating, set_hydrate_node, skip_nodes } from '../dom/hydration.js';
|
|
29
28
|
|
|
30
29
|
/**
|
|
31
30
|
* @param {Array<Promise<void>>} blockers
|
|
@@ -211,51 +210,6 @@ export function unset_context() {
|
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
|
|
214
|
-
/**
|
|
215
|
-
* @param {TemplateNode} anchor
|
|
216
|
-
* @param {(target: TemplateNode) => Promise<void>} fn
|
|
217
|
-
*/
|
|
218
|
-
export async function async_body(anchor, fn) {
|
|
219
|
-
var boundary = get_boundary();
|
|
220
|
-
var batch = /** @type {Batch} */ (current_batch);
|
|
221
|
-
var blocking = !boundary.is_pending();
|
|
222
|
-
|
|
223
|
-
boundary.update_pending_count(1);
|
|
224
|
-
batch.increment(blocking);
|
|
225
|
-
|
|
226
|
-
var active = /** @type {Effect} */ (active_effect);
|
|
227
|
-
|
|
228
|
-
var was_hydrating = hydrating;
|
|
229
|
-
var next_hydrate_node = undefined;
|
|
230
|
-
|
|
231
|
-
if (was_hydrating) {
|
|
232
|
-
hydrate_next();
|
|
233
|
-
next_hydrate_node = skip_nodes(false);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
try {
|
|
237
|
-
var promise = fn(anchor);
|
|
238
|
-
} finally {
|
|
239
|
-
if (next_hydrate_node) {
|
|
240
|
-
set_hydrate_node(next_hydrate_node);
|
|
241
|
-
hydrate_next();
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
try {
|
|
246
|
-
await promise;
|
|
247
|
-
} catch (error) {
|
|
248
|
-
if (!aborted(active)) {
|
|
249
|
-
invoke_error_boundary(error, active);
|
|
250
|
-
}
|
|
251
|
-
} finally {
|
|
252
|
-
boundary.update_pending_count(-1);
|
|
253
|
-
batch.decrement(blocking);
|
|
254
|
-
|
|
255
|
-
unset_context();
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
213
|
/**
|
|
260
214
|
* @param {Array<() => void | Promise<void>>} thunks
|
|
261
215
|
*/
|
|
@@ -264,7 +218,7 @@ export function run(thunks) {
|
|
|
264
218
|
|
|
265
219
|
var boundary = get_boundary();
|
|
266
220
|
var batch = /** @type {Batch} */ (current_batch);
|
|
267
|
-
var blocking =
|
|
221
|
+
var blocking = boundary.is_rendered();
|
|
268
222
|
|
|
269
223
|
boundary.update_pending_count(1);
|
|
270
224
|
batch.increment(blocking);
|
|
@@ -298,17 +252,13 @@ export function run(thunks) {
|
|
|
298
252
|
throw STALE_REACTION;
|
|
299
253
|
}
|
|
300
254
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
return fn();
|
|
304
|
-
} finally {
|
|
305
|
-
// TODO do we need it here as well as below?
|
|
306
|
-
unset_context();
|
|
307
|
-
}
|
|
255
|
+
restore();
|
|
256
|
+
return fn();
|
|
308
257
|
})
|
|
309
258
|
.catch(handle_error)
|
|
310
259
|
.finally(() => {
|
|
311
260
|
unset_context();
|
|
261
|
+
current_batch?.deactivate();
|
|
312
262
|
});
|
|
313
263
|
|
|
314
264
|
promises.push(promise);
|