svelte 5.57.0 → 5.57.1
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 +8 -8
- package/src/compiler/phases/1-parse/acorn.js +36 -2
- package/src/compiler/phases/1-parse/index.js +23 -22
- package/src/compiler/phases/1-parse/read/context.js +3 -18
- package/src/compiler/phases/1-parse/read/expression.js +110 -2
- package/src/compiler/phases/1-parse/read/script.js +1 -1
- package/src/compiler/phases/1-parse/read/style.js +3 -5
- package/src/compiler/phases/1-parse/state/element.js +68 -40
- package/src/compiler/phases/1-parse/state/tag.js +6 -6
- package/src/compiler/phases/1-parse/utils/html.js +2 -0
- package/src/compiler/phases/1-parse/utils/whitespace.js +18 -0
- package/src/compiler/phases/2-analyze/css/css-prune.js +7 -6
- package/src/compiler/phases/2-analyze/index.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/BindDirective.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/ClassDeclaration.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/FunctionDeclaration.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/Identifier.js +1 -2
- package/src/compiler/phases/2-analyze/visitors/SvelteBody.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/SvelteDocument.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/SvelteWindow.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/VariableDeclarator.js +2 -2
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/constants.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +1 -1
- package/src/compiler/phases/2-analyze/visitors/shared/utils.js +0 -38
- package/src/compiler/phases/3-transform/client/utils.js +0 -38
- package/src/compiler/phases/3-transform/client/visitors/AssignmentExpression.js +2 -2
- package/src/compiler/phases/3-transform/client/visitors/CallExpression.js +1 -2
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +3 -8
- package/src/compiler/phases/3-transform/server/visitors/shared/element.js +8 -0
- package/src/compiler/phases/3-transform/utils.js +1 -1
- package/src/compiler/phases/nodes.js +30 -0
- package/src/compiler/phases/scope.js +77 -2
- package/src/compiler/state.js +9 -5
- package/src/compiler/utils/ast.js +2 -5
- package/src/compiler/utils/compile_diagnostic.js +1 -1
- package/src/compiler/utils/extract_svelte_ignore.js +1 -1
- package/src/compiler/utils/mapped_code.js +13 -1
- package/src/internal/client/constants.js +0 -9
- package/src/internal/client/dev/debug.js +0 -2
- package/src/internal/client/dom/elements/events.js +6 -1
- package/src/internal/client/errors.js +0 -16
- package/src/internal/client/proxy.js +12 -7
- package/src/internal/client/reactivity/batch.js +91 -71
- package/src/internal/client/reactivity/deriveds.js +0 -3
- package/src/internal/client/reactivity/sources.js +28 -16
- package/src/internal/client/reactivity/utils.js +2 -23
- package/src/internal/client/runtime.js +5 -9
- package/src/internal/server/context.js +9 -2
- package/src/internal/server/index.js +9 -2
- package/src/internal/server/renderer.js +101 -69
- package/src/internal/shared/errors.js +16 -0
- package/src/version.js +1 -1
- package/types/index.d.ts.map +1 -1
- package/src/compiler/phases/1-parse/utils/create.js +0 -16
- package/src/compiler/phases/2-analyze/visitors/shared/special-element.js +0 -16
- package/src/compiler/utils/push_array.js +0 -13
- /package/src/compiler/{phases/2-analyze/utils → utils}/check_graph_for_cycles.js +0 -0
- /package/src/compiler/{phases/1-parse/utils → utils}/fuzzymatch.js +0 -0
|
@@ -22,7 +22,6 @@ import {
|
|
|
22
22
|
import { async_mode_flag } from '../../flags/index.js';
|
|
23
23
|
import { deferred, define_property, includes } from '../../shared/utils.js';
|
|
24
24
|
import {
|
|
25
|
-
active_effect,
|
|
26
25
|
active_reaction,
|
|
27
26
|
get,
|
|
28
27
|
increment_write_version,
|
|
@@ -38,7 +37,6 @@ import { eager_effect, teardown, unlink_effect } from './effects.js';
|
|
|
38
37
|
import { defer_effect } from './utils.js';
|
|
39
38
|
import { UNINITIALIZED } from '../../../constants.js';
|
|
40
39
|
import { set_signal_status } from './status.js';
|
|
41
|
-
import { legacy_is_updating_store } from './store.js';
|
|
42
40
|
import { invariant } from '../../shared/dev.js';
|
|
43
41
|
import { log_effect_tree } from '../dev/debug.js';
|
|
44
42
|
import { OBSOLETE } from './deriveds.js';
|
|
@@ -160,10 +158,17 @@ export class Batch {
|
|
|
160
158
|
#deferred = null;
|
|
161
159
|
|
|
162
160
|
/**
|
|
163
|
-
*
|
|
161
|
+
* Effects that were scheduled in this batch but not yet 'resolved' into the
|
|
162
|
+
* root effects that need to be flushed. Resolving — the upwards traversal that
|
|
163
|
+
* marks the path to each effect on the shared effect tree (see #resolve) — is
|
|
164
|
+
* deferred until the batch is processed, so that the markers are created and
|
|
165
|
+
* consumed within a single traversal. Scheduling into other batches (which can
|
|
166
|
+
* happen concurrently, e.g. while a batch is committed) can therefore never
|
|
167
|
+
* observe (and be confused by) this batch's markers.
|
|
168
|
+
* May contain duplicates — deduplication happens during resolving
|
|
164
169
|
* @type {Effect[]}
|
|
165
170
|
*/
|
|
166
|
-
#
|
|
171
|
+
#scheduled = [];
|
|
167
172
|
|
|
168
173
|
/**
|
|
169
174
|
* Effects created while this batch was active.
|
|
@@ -273,14 +278,57 @@ export class Batch {
|
|
|
273
278
|
this.#unskipped_branches.add(effect);
|
|
274
279
|
}
|
|
275
280
|
|
|
276
|
-
|
|
277
|
-
|
|
281
|
+
/**
|
|
282
|
+
* Convert the effects that were scheduled in this batch into the root effects
|
|
283
|
+
* that need to be traversed, marking the path to each effect (by clearing the
|
|
284
|
+
* `CLEAN` flag on ancestor branches) so that the traversal can find them.
|
|
285
|
+
* This happens right before traversal rather than at scheduling time, so that
|
|
286
|
+
* the markers left on the (shared) effect tree are created and consumed within
|
|
287
|
+
* a single traversal — scheduling into other batches can never observe them
|
|
288
|
+
* @returns {Effect[]}
|
|
289
|
+
*/
|
|
290
|
+
#resolve() {
|
|
291
|
+
/** @type {Effect[]} */
|
|
292
|
+
var roots = [];
|
|
278
293
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
294
|
+
for (const effect of this.#scheduled) {
|
|
295
|
+
// skip effects that are destroyed, or that already ran (e.g. because
|
|
296
|
+
// they were reached by the traversal that preceded a drain iteration,
|
|
297
|
+
// or because they were scheduled twice)
|
|
298
|
+
if ((effect.f & DESTROYED) !== 0 || (effect.f & (DIRTY | MAYBE_DIRTY)) === 0) continue;
|
|
299
|
+
|
|
300
|
+
var e = effect;
|
|
301
|
+
var covered = false;
|
|
302
|
+
|
|
303
|
+
while (e.parent !== null) {
|
|
304
|
+
e = e.parent;
|
|
305
|
+
var flags = e.f;
|
|
306
|
+
|
|
307
|
+
if ((flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) {
|
|
308
|
+
if ((flags & CLEAN) === 0) {
|
|
309
|
+
// the path to the root was already marked, meaning the
|
|
310
|
+
// root was already collected — nothing left to do
|
|
311
|
+
covered = true;
|
|
312
|
+
break;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
e.f ^= CLEAN;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
if (!covered) {
|
|
320
|
+
roots.push(e);
|
|
321
|
+
}
|
|
282
322
|
}
|
|
283
323
|
|
|
324
|
+
this.#scheduled = [];
|
|
325
|
+
|
|
326
|
+
return roots;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
#process() {
|
|
330
|
+
this.#started = true;
|
|
331
|
+
|
|
284
332
|
if (DEV) {
|
|
285
333
|
// track all the values that were updated during this flush,
|
|
286
334
|
// so that they can be reset afterwards
|
|
@@ -304,9 +352,6 @@ export class Batch {
|
|
|
304
352
|
this.schedule(e);
|
|
305
353
|
}
|
|
306
354
|
|
|
307
|
-
const roots = this.#roots;
|
|
308
|
-
this.#roots = [];
|
|
309
|
-
|
|
310
355
|
this.apply();
|
|
311
356
|
|
|
312
357
|
/** @type {Effect[]} */
|
|
@@ -321,18 +366,28 @@ export class Batch {
|
|
|
321
366
|
*/
|
|
322
367
|
var updates = (legacy_updates = []);
|
|
323
368
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
//
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
369
|
+
// Effects can be scheduled during traversal (e.g. because a parent each/await/etc
|
|
370
|
+
// block updated an internal source, or because an effect invalidated itself)
|
|
371
|
+
// hence we loop until there are no more scheduled effects.
|
|
372
|
+
while (this.#scheduled.length > 0) {
|
|
373
|
+
if (flush_count++ > 1000) {
|
|
374
|
+
this.#unlink();
|
|
375
|
+
infinite_loop_guard(); // TODO try to reset_all() here?
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
for (const root of this.#resolve()) {
|
|
379
|
+
try {
|
|
380
|
+
this.#traverse(root, effects, render_effects);
|
|
381
|
+
} catch (e) {
|
|
382
|
+
reset_all(root);
|
|
383
|
+
// If there's no async work left, this branch is now dead and needs
|
|
384
|
+
// to be discarded to not become a zombie that is never cleaned up.
|
|
385
|
+
// See https://github.com/sveltejs/svelte/issues/18221#issuecomment-4497918414
|
|
386
|
+
// for a (non-minimal) reproduction that demonstrates a case where this is necessary
|
|
387
|
+
// to not get follow-up false-positives via "batch has scheduled roots" invariant errors.
|
|
388
|
+
if (!this.#is_deferred()) this.discard();
|
|
389
|
+
throw e;
|
|
390
|
+
}
|
|
336
391
|
}
|
|
337
392
|
}
|
|
338
393
|
|
|
@@ -393,7 +448,7 @@ export class Batch {
|
|
|
393
448
|
|
|
394
449
|
var next_batch = /** @type {Batch | null} */ (/** @type {unknown} */ (current_batch));
|
|
395
450
|
|
|
396
|
-
if (this.#pending === 0 && (this.#
|
|
451
|
+
if (this.#pending === 0 && (this.#scheduled.length === 0 || next_batch !== null)) {
|
|
397
452
|
this.#unlink();
|
|
398
453
|
|
|
399
454
|
// Order matters here - we need to commit and THEN continue flushing new batches, not the other way around,
|
|
@@ -408,12 +463,15 @@ export class Batch {
|
|
|
408
463
|
}
|
|
409
464
|
|
|
410
465
|
// Edge case: During traversal new branches might create effects that run immediately and set state,
|
|
411
|
-
// causing an effect
|
|
466
|
+
// causing an effect to be scheduled again. We need to traverse the current batch
|
|
412
467
|
// once more in that case - most of the time this will just clean up dirty branches.
|
|
413
|
-
if (this.#
|
|
468
|
+
if (this.#scheduled.length > 0) {
|
|
414
469
|
if (next_batch !== null) {
|
|
415
|
-
const
|
|
416
|
-
|
|
470
|
+
for (const e of this.#scheduled) {
|
|
471
|
+
next_batch.#scheduled.push(e);
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
this.#scheduled = [];
|
|
417
475
|
} else {
|
|
418
476
|
next_batch = this;
|
|
419
477
|
}
|
|
@@ -712,7 +770,7 @@ export class Batch {
|
|
|
712
770
|
// The microtask queue can contain the batch already scheduled to run right
|
|
713
771
|
// after this one is finished, so throwing the invariant would be wrong here.
|
|
714
772
|
if (DEV && !batch.#decrement_queued) {
|
|
715
|
-
invariant(batch.#
|
|
773
|
+
invariant(batch.#scheduled.length === 0, 'Batch has scheduled effects');
|
|
716
774
|
}
|
|
717
775
|
|
|
718
776
|
// A batch was unskipped in a later batch -> tell prior batches to unskip it, too
|
|
@@ -768,14 +826,12 @@ export class Batch {
|
|
|
768
826
|
|
|
769
827
|
// Only apply and traverse when we know we triggered async work with marking the effects
|
|
770
828
|
// and know this won't run anyway right afterwards
|
|
771
|
-
if (batch.#
|
|
829
|
+
if (batch.#scheduled.length > 0 && !batch.#decrement_queued) {
|
|
772
830
|
batch.apply();
|
|
773
831
|
|
|
774
|
-
for (var root of batch.#
|
|
832
|
+
for (var root of batch.#resolve()) {
|
|
775
833
|
batch.#traverse(root, [], []);
|
|
776
834
|
}
|
|
777
|
-
|
|
778
|
-
batch.#roots = [];
|
|
779
835
|
}
|
|
780
836
|
|
|
781
837
|
batch.deactivate();
|
|
@@ -939,43 +995,7 @@ export class Batch {
|
|
|
939
995
|
return;
|
|
940
996
|
}
|
|
941
997
|
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
while (e.parent !== null) {
|
|
945
|
-
e = e.parent;
|
|
946
|
-
var flags = e.f;
|
|
947
|
-
|
|
948
|
-
// if the effect is being scheduled because a parent (each/await/etc) block
|
|
949
|
-
// updated an internal source, or because a branch is being unskipped,
|
|
950
|
-
// bail out or we'll cause a second flush
|
|
951
|
-
if (collected_effects !== null && e === active_effect) {
|
|
952
|
-
if (async_mode_flag) return;
|
|
953
|
-
|
|
954
|
-
// in sync mode, render effects run during traversal. in an extreme edge case
|
|
955
|
-
// — namely that we're setting a value inside a derived read during traversal —
|
|
956
|
-
// they can be made dirty after they have already been visited, in which
|
|
957
|
-
// case we shouldn't bail out. we also shouldn't bail out if we're
|
|
958
|
-
// updating a store inside a `$:`, since this might invalidate
|
|
959
|
-
// effects that were already visited
|
|
960
|
-
if (
|
|
961
|
-
(active_reaction === null || (active_reaction.f & DERIVED) === 0) &&
|
|
962
|
-
!legacy_is_updating_store
|
|
963
|
-
) {
|
|
964
|
-
return;
|
|
965
|
-
}
|
|
966
|
-
}
|
|
967
|
-
|
|
968
|
-
if ((flags & (ROOT_EFFECT | BRANCH_EFFECT)) !== 0) {
|
|
969
|
-
if ((flags & CLEAN) === 0) {
|
|
970
|
-
// branch is already dirty, bail
|
|
971
|
-
return;
|
|
972
|
-
}
|
|
973
|
-
|
|
974
|
-
e.f ^= CLEAN;
|
|
975
|
-
}
|
|
976
|
-
}
|
|
977
|
-
|
|
978
|
-
this.#roots.push(e);
|
|
998
|
+
this.#scheduled.push(effect);
|
|
979
999
|
}
|
|
980
1000
|
|
|
981
1001
|
#unlink() {
|
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
EFFECT_PRESERVED,
|
|
10
10
|
STALE_REACTION,
|
|
11
11
|
ASYNC,
|
|
12
|
-
WAS_MARKED,
|
|
13
12
|
DESTROYED,
|
|
14
13
|
CLEAN,
|
|
15
14
|
REACTION_RAN,
|
|
@@ -365,7 +364,6 @@ export function execute_derived(derived) {
|
|
|
365
364
|
|
|
366
365
|
stack.push(derived);
|
|
367
366
|
|
|
368
|
-
derived.f &= ~WAS_MARKED;
|
|
369
367
|
destroy_derived_effects(derived);
|
|
370
368
|
value = update_reaction(derived);
|
|
371
369
|
} finally {
|
|
@@ -375,7 +373,6 @@ export function execute_derived(derived) {
|
|
|
375
373
|
}
|
|
376
374
|
} else {
|
|
377
375
|
try {
|
|
378
|
-
derived.f &= ~WAS_MARKED;
|
|
379
376
|
destroy_derived_effects(derived);
|
|
380
377
|
value = update_reaction(derived);
|
|
381
378
|
} finally {
|
|
@@ -25,10 +25,7 @@ import {
|
|
|
25
25
|
MAYBE_DIRTY,
|
|
26
26
|
BLOCK_EFFECT,
|
|
27
27
|
ROOT_EFFECT,
|
|
28
|
-
ASYNC
|
|
29
|
-
WAS_MARKED,
|
|
30
|
-
CONNECTED,
|
|
31
|
-
REACTION_IS_UPDATING
|
|
28
|
+
ASYNC
|
|
32
29
|
} from '#client/constants';
|
|
33
30
|
import * as e from '../errors.js';
|
|
34
31
|
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
|
|
@@ -171,6 +168,17 @@ export function set(source, value, should_proxy = false) {
|
|
|
171
168
|
return internal_set(source, new_value, legacy_updates);
|
|
172
169
|
}
|
|
173
170
|
|
|
171
|
+
/**
|
|
172
|
+
* A set of signals we have already seen while traversing in mark_reactions.
|
|
173
|
+
* Not always set to balance the common case of sources only having a couple
|
|
174
|
+
* of (transitive) dependencies (where always creating a Set would be bad for perf)
|
|
175
|
+
* with the edge case of extremely deep or wide dependency arrays with cycles.
|
|
176
|
+
* @type {Set<any> | null}
|
|
177
|
+
*/
|
|
178
|
+
var seen = null;
|
|
179
|
+
/** Number of transitive dependencies, see {@link seen} for more info */
|
|
180
|
+
var count_deps = 0;
|
|
181
|
+
|
|
174
182
|
/**
|
|
175
183
|
* @template V
|
|
176
184
|
* @param {Source<V>} source
|
|
@@ -240,7 +248,10 @@ export function internal_set(source, value, updated_during_traversal = null) {
|
|
|
240
248
|
|
|
241
249
|
// For debugging, in case you want to know which reactions are being scheduled:
|
|
242
250
|
// log_reactions(source);
|
|
251
|
+
seen = null;
|
|
252
|
+
count_deps = 0;
|
|
243
253
|
mark_reactions(source, DIRTY, updated_during_traversal);
|
|
254
|
+
seen = null;
|
|
244
255
|
|
|
245
256
|
// It's possible that the current reaction might not have up-to-date dependencies
|
|
246
257
|
// whilst it's actively running. So in the case of ensuring it registers the reaction
|
|
@@ -347,6 +358,18 @@ function mark_reactions(signal, status, updated_during_traversal) {
|
|
|
347
358
|
var runes = is_runes();
|
|
348
359
|
var length = reactions.length;
|
|
349
360
|
|
|
361
|
+
count_deps += length;
|
|
362
|
+
// Activate the `seen` Set if we think from the unusually high number of deps that
|
|
363
|
+
// there might be cycles in the graph, to avoid repeated lookups for reactions
|
|
364
|
+
// Example: https://github.com/sveltejs/svelte/issues/16658 has a graph with one source
|
|
365
|
+
// reaching ~10000 distinct deriveds/effects each, resulting in 65 million walks through repeated visits.
|
|
366
|
+
if (count_deps > 100000 && seen === null) seen = new Set();
|
|
367
|
+
|
|
368
|
+
if (seen !== null) {
|
|
369
|
+
if (seen.has(signal)) return;
|
|
370
|
+
seen.add(signal);
|
|
371
|
+
}
|
|
372
|
+
|
|
350
373
|
for (var i = 0; i < length; i++) {
|
|
351
374
|
var reaction = reactions[i];
|
|
352
375
|
var flags = reaction.f;
|
|
@@ -370,18 +393,7 @@ function mark_reactions(signal, status, updated_during_traversal) {
|
|
|
370
393
|
var derived = /** @type {Derived} */ (reaction);
|
|
371
394
|
|
|
372
395
|
batch_values?.delete(derived);
|
|
373
|
-
|
|
374
|
-
if ((flags & WAS_MARKED) === 0) {
|
|
375
|
-
// Only connected deriveds being executed outside the update cycle can be reliably unmarked right away
|
|
376
|
-
if (
|
|
377
|
-
flags & CONNECTED &&
|
|
378
|
-
(active_effect === null || (active_effect.f & REACTION_IS_UPDATING) === 0)
|
|
379
|
-
) {
|
|
380
|
-
reaction.f |= WAS_MARKED;
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
mark_reactions(derived, MAYBE_DIRTY, updated_during_traversal);
|
|
384
|
-
}
|
|
396
|
+
mark_reactions(derived, MAYBE_DIRTY, updated_during_traversal);
|
|
385
397
|
} else if (not_dirty) {
|
|
386
398
|
var effect = /** @type {Effect} */ (reaction);
|
|
387
399
|
|
|
@@ -1,24 +1,7 @@
|
|
|
1
|
-
/** @import {
|
|
2
|
-
import { CLEAN,
|
|
1
|
+
/** @import { Effect } from '#client' */
|
|
2
|
+
import { CLEAN, DIRTY, MAYBE_DIRTY } from '#client/constants';
|
|
3
3
|
import { set_signal_status } from './status.js';
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* @param {Value[] | null} deps
|
|
7
|
-
*/
|
|
8
|
-
function clear_marked(deps) {
|
|
9
|
-
if (deps === null) return;
|
|
10
|
-
|
|
11
|
-
for (const dep of deps) {
|
|
12
|
-
if ((dep.f & DERIVED) === 0 || (dep.f & WAS_MARKED) === 0) {
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
dep.f ^= WAS_MARKED;
|
|
17
|
-
|
|
18
|
-
clear_marked(/** @type {Derived} */ (dep).deps);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
|
|
22
5
|
/**
|
|
23
6
|
* @param {Effect} effect
|
|
24
7
|
* @param {Set<Effect>} dirty_effects
|
|
@@ -31,10 +14,6 @@ export function defer_effect(effect, dirty_effects, maybe_dirty_effects) {
|
|
|
31
14
|
maybe_dirty_effects.add(effect);
|
|
32
15
|
}
|
|
33
16
|
|
|
34
|
-
// Since we're not executing these effects now, we need to clear any WAS_MARKED flags
|
|
35
|
-
// so that other batches can correctly reach these effects during their own traversal
|
|
36
|
-
clear_marked(effect.deps);
|
|
37
|
-
|
|
38
17
|
// mark as clean so they get scheduled if they depend on pending async state
|
|
39
18
|
set_signal_status(effect, CLEAN);
|
|
40
19
|
}
|
|
@@ -21,7 +21,6 @@ import {
|
|
|
21
21
|
REACTION_IS_UPDATING,
|
|
22
22
|
STALE_REACTION,
|
|
23
23
|
ERROR_VALUE,
|
|
24
|
-
WAS_MARKED,
|
|
25
24
|
MANAGED_EFFECT,
|
|
26
25
|
REACTION_RAN
|
|
27
26
|
} from './constants.js';
|
|
@@ -100,7 +99,11 @@ export let current_sources = null;
|
|
|
100
99
|
|
|
101
100
|
/** @param {Value} value */
|
|
102
101
|
export function push_reaction_value(value) {
|
|
103
|
-
if (
|
|
102
|
+
if (
|
|
103
|
+
active_reaction !== null &&
|
|
104
|
+
((!async_mode_flag && (active_reaction.f & REACTION_IS_UPDATING) !== 0) ||
|
|
105
|
+
(active_reaction.f & DERIVED) !== 0)
|
|
106
|
+
) {
|
|
104
107
|
(current_sources ??= new Set()).add(value);
|
|
105
108
|
}
|
|
106
109
|
}
|
|
@@ -160,10 +163,6 @@ export function is_dirty(reaction) {
|
|
|
160
163
|
return true;
|
|
161
164
|
}
|
|
162
165
|
|
|
163
|
-
if (flags & DERIVED) {
|
|
164
|
-
reaction.f &= ~WAS_MARKED;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
166
|
if ((flags & MAYBE_DIRTY) !== 0) {
|
|
168
167
|
var dependencies = /** @type {Value[]} */ (reaction.deps);
|
|
169
168
|
var length = dependencies.length;
|
|
@@ -404,11 +403,8 @@ function remove_reaction(signal, dependency) {
|
|
|
404
403
|
) {
|
|
405
404
|
var derived = /** @type {Derived} */ (dependency);
|
|
406
405
|
|
|
407
|
-
// If we are working with a derived that is owned by an effect, then mark it as being
|
|
408
|
-
// disconnected and remove the mark flag, as it cannot be reliably removed otherwise
|
|
409
406
|
if ((derived.f & CONNECTED) !== 0) {
|
|
410
407
|
derived.f ^= CONNECTED;
|
|
411
|
-
derived.f &= ~WAS_MARKED;
|
|
412
408
|
}
|
|
413
409
|
|
|
414
410
|
// In a fork it's possible that a derived is executed and gets reactions, then commits, but is
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/** @import { SSRContext } from '#server' */
|
|
2
2
|
import { DEV } from 'esm-env';
|
|
3
3
|
import { create_context, get_or_init_context_map } from '../shared/context.js';
|
|
4
|
+
import * as e from './errors.js';
|
|
4
5
|
|
|
5
6
|
/** @type {SSRContext | null} */
|
|
6
7
|
export var ssr_context = null;
|
|
@@ -40,7 +41,13 @@ export function getContext(key) {
|
|
|
40
41
|
* @returns {T}
|
|
41
42
|
*/
|
|
42
43
|
export function setContext(key, context) {
|
|
43
|
-
get_or_init_context_map(ssr_context, 'setContext')
|
|
44
|
+
const context_map = get_or_init_context_map(ssr_context, 'setContext');
|
|
45
|
+
|
|
46
|
+
if (/** @type {SSRContext} */ (ssr_context).i) {
|
|
47
|
+
e.set_context_after_init();
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
context_map.set(key, context);
|
|
44
51
|
return context;
|
|
45
52
|
}
|
|
46
53
|
|
|
@@ -61,7 +68,7 @@ export function getAllContexts() {
|
|
|
61
68
|
* @param {Function} [fn]
|
|
62
69
|
*/
|
|
63
70
|
export function push(fn) {
|
|
64
|
-
ssr_context = { p: ssr_context, c: null, r: null };
|
|
71
|
+
ssr_context = { p: ssr_context, c: null, r: null, i: false };
|
|
65
72
|
|
|
66
73
|
if (DEV) {
|
|
67
74
|
ssr_context.function = fn;
|
|
@@ -146,8 +146,10 @@ export function attributes(attrs, css_hash, classes, styles, flags = 0) {
|
|
|
146
146
|
const is_html = (flags & ELEMENT_IS_NAMESPACED) === 0;
|
|
147
147
|
const lowercase = (flags & ELEMENT_PRESERVE_ATTRIBUTE_CASE) === 0;
|
|
148
148
|
const is_input = (flags & ELEMENT_IS_INPUT) !== 0;
|
|
149
|
+
const names = Object.keys(attrs);
|
|
149
150
|
|
|
150
|
-
for (
|
|
151
|
+
outer: for (let i = 0; i < names.length; i++) {
|
|
152
|
+
name = names[i];
|
|
151
153
|
// omit functions, internal svelte properties and invalid attribute names
|
|
152
154
|
if (typeof attrs[name] === 'function') continue;
|
|
153
155
|
if (name[0] === '$' && name[1] === '$') continue; // faster than name.startsWith('$$')
|
|
@@ -163,8 +165,13 @@ export function attributes(attrs, css_hash, classes, styles, flags = 0) {
|
|
|
163
165
|
|
|
164
166
|
if (is_input) {
|
|
165
167
|
if (name === 'defaultvalue' || name === 'defaultchecked') {
|
|
168
|
+
// value/checked takes precedence over defaultValue/defaultChecked
|
|
166
169
|
name = name === 'defaultvalue' ? 'value' : 'checked';
|
|
167
|
-
if (attrs
|
|
170
|
+
if (name in attrs) continue;
|
|
171
|
+
// We're checking prior entries aswell because "name in attrs" is not enough as the attributes may have different casing
|
|
172
|
+
for (let j = 0; j < names.length; j++) {
|
|
173
|
+
if (names[j].toLowerCase() === name) continue outer;
|
|
174
|
+
}
|
|
168
175
|
}
|
|
169
176
|
}
|
|
170
177
|
|