svelte 5.56.0 → 5.56.2
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 +3 -3
- package/src/compiler/phases/1-parse/acorn.js +16 -29
- package/src/compiler/phases/1-parse/state/tag.js +21 -8
- package/src/compiler/phases/1-parse/utils/bracket.js +14 -3
- package/src/compiler/phases/2-analyze/visitors/DeclarationTag.js +15 -2
- package/src/compiler/phases/2-analyze/visitors/SnippetBlock.js +15 -10
- package/src/compiler/phases/2-analyze/visitors/shared/element.js +1 -0
- package/src/compiler/phases/3-transform/client/visitors/DeclarationTag.js +3 -1
- package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +1 -1
- package/src/internal/client/dom/blocks/async.js +2 -0
- package/src/internal/client/dom/blocks/each.js +3 -1
- package/src/internal/client/dom/elements/attributes.js +9 -0
- package/src/internal/client/dom/elements/bindings/input.js +0 -1
- package/src/internal/client/reactivity/async.js +27 -14
- package/src/internal/client/reactivity/batch.js +16 -4
- package/src/internal/client/reactivity/effects.js +4 -2
- package/src/internal/client/runtime.js +6 -0
- package/src/reactivity/url-search-params.js +3 -2
- package/src/version.js +1 -1
- package/types/index.d.ts.map +1 -1
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "svelte",
|
|
3
3
|
"description": "Cybernetically enhanced web apps",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "5.56.
|
|
5
|
+
"version": "5.56.2",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"types": "./types/index.d.ts",
|
|
8
8
|
"engines": {
|
|
@@ -153,7 +153,7 @@
|
|
|
153
153
|
"source-map": "^0.7.4",
|
|
154
154
|
"tinyglobby": "^0.2.12",
|
|
155
155
|
"typescript": "^5.5.4",
|
|
156
|
-
"vitest": "^
|
|
156
|
+
"vitest": "^4.1.7",
|
|
157
157
|
"web-features": "^3.29.0"
|
|
158
158
|
},
|
|
159
159
|
"dependencies": {
|
|
@@ -168,7 +168,7 @@
|
|
|
168
168
|
"clsx": "^2.1.1",
|
|
169
169
|
"devalue": "^5.8.1",
|
|
170
170
|
"esm-env": "^1.2.1",
|
|
171
|
-
"esrap": "^2.2.
|
|
171
|
+
"esrap": "^2.2.11",
|
|
172
172
|
"is-reference": "^3.0.3",
|
|
173
173
|
"locate-character": "^3.0.0",
|
|
174
174
|
"magic-string": "^0.30.11",
|
|
@@ -5,7 +5,6 @@ import * as acorn from 'acorn';
|
|
|
5
5
|
import { walk } from 'zimmerframe';
|
|
6
6
|
import { tsPlugin } from '@sveltejs/acorn-typescript';
|
|
7
7
|
import * as e from '../../errors.js';
|
|
8
|
-
import { find_matching_bracket } from './utils/bracket.js';
|
|
9
8
|
|
|
10
9
|
const JSParser = acorn.Parser;
|
|
11
10
|
const TSParser = JSParser.extend(tsPlugin());
|
|
@@ -106,38 +105,26 @@ export function parse_expression_at(parser, source, index) {
|
|
|
106
105
|
* @returns {Statement}
|
|
107
106
|
*/
|
|
108
107
|
export function parse_statement_at(parser, source, index) {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
while (source[end - 1] === ';') {
|
|
114
|
-
end -= 1;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const padded_source = `${' '.repeat(index)}${source.slice(index, end)}`;
|
|
118
|
-
const { onComment, add_comments } = get_comment_handlers(
|
|
119
|
-
padded_source,
|
|
120
|
-
parser.root.comments,
|
|
121
|
-
index
|
|
122
|
-
);
|
|
108
|
+
// cast to `any`: acorn's Parser constructor and parseStatement/nextToken aren't in its public types
|
|
109
|
+
const acorn = /** @type {any} */ (parser.ts ? TSParser : JSParser);
|
|
110
|
+
const { onComment, add_comments } = get_comment_handlers(source, parser.root.comments, index);
|
|
123
111
|
|
|
124
112
|
try {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
sourceType: 'module',
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
add_comments(ast);
|
|
133
|
-
|
|
134
|
-
const statement = /** @type {Statement} */ (
|
|
135
|
-
/** @type {unknown} */ (/** @type {Program} */ (ast).body[0])
|
|
113
|
+
// This is like parseExpressionAt but for statements
|
|
114
|
+
const p = new acorn(
|
|
115
|
+
{ onComment, sourceType: 'module', ecmaVersion: 16, locations: true },
|
|
116
|
+
source,
|
|
117
|
+
index
|
|
136
118
|
);
|
|
137
|
-
|
|
119
|
+
p.nextToken();
|
|
120
|
+
const statement = /** @type {Statement} */ (p.parseStatement(null, true, Object.create(null)));
|
|
121
|
+
add_comments(/** @type {acorn.Node} */ (statement));
|
|
138
122
|
return statement;
|
|
139
|
-
} catch (
|
|
140
|
-
|
|
123
|
+
} catch (err) {
|
|
124
|
+
// A statement that runs to the end of the source (e.g. an unterminated declaration tag)
|
|
125
|
+
// is an EOF, not a stray token; preserve the friendlier `unexpected_eof` diagnostic.
|
|
126
|
+
if (/** @type {any} */ (err).pos === source.length) e.unexpected_eof(source.length);
|
|
127
|
+
handle_parse_error(err);
|
|
141
128
|
}
|
|
142
129
|
}
|
|
143
130
|
|
|
@@ -12,9 +12,9 @@ import { find_matching_bracket, match_bracket } from '../utils/bracket.js';
|
|
|
12
12
|
|
|
13
13
|
const regex_whitespace_with_closing_curly_brace = /\s*}/y;
|
|
14
14
|
const regex_supported_declaration = /(?:let|const)\b/y;
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
const
|
|
15
|
+
const regex_unsupported_declaration = /(?:var|interface|enum)\b/y;
|
|
16
|
+
// `type` is a contextual keyword; this is just a shape hint, confirmed by parsing.
|
|
17
|
+
const regex_maybe_type_declaration = /type\b/y;
|
|
18
18
|
|
|
19
19
|
const pointy_bois = { '<': '>' };
|
|
20
20
|
|
|
@@ -77,10 +77,17 @@ function read_declaration(parser) {
|
|
|
77
77
|
e.declaration_tag_invalid_type({ start, end: start + unsupported.length });
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
if (
|
|
80
|
+
if (
|
|
81
|
+
!parser.match_regex(regex_supported_declaration) &&
|
|
82
|
+
// `type` is special, since it is not a reserved keyword and can be used
|
|
83
|
+
// as part of a valid expression. We gotta parse first and then see what it is.
|
|
84
|
+
!parser.match_regex(regex_maybe_type_declaration)
|
|
85
|
+
) {
|
|
81
86
|
return null;
|
|
82
87
|
}
|
|
83
88
|
|
|
89
|
+
const initial_comment_count = parser.root.comments.length;
|
|
90
|
+
|
|
84
91
|
/** @type {import('estree').Statement | import('estree').VariableDeclaration} */
|
|
85
92
|
let declaration;
|
|
86
93
|
try {
|
|
@@ -117,10 +124,16 @@ function read_declaration(parser) {
|
|
|
117
124
|
}
|
|
118
125
|
|
|
119
126
|
if (declaration.type !== 'VariableDeclaration') {
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
127
|
+
if (declaration.type === 'ExpressionStatement') {
|
|
128
|
+
parser.root.comments.length = initial_comment_count; // Else they show up duplicated
|
|
129
|
+
return null;
|
|
130
|
+
} else {
|
|
131
|
+
// This is a TSTypeAliasDeclaration
|
|
132
|
+
e.declaration_tag_invalid_type({
|
|
133
|
+
start: declaration.start ?? start,
|
|
134
|
+
end: declaration.end ?? parser.index
|
|
135
|
+
});
|
|
136
|
+
}
|
|
124
137
|
}
|
|
125
138
|
|
|
126
139
|
// TODO support using
|
|
@@ -39,7 +39,9 @@ function find_string_end(string, search_start_index, string_start_char) {
|
|
|
39
39
|
* @returns {number} The index of the end of this regex expression, or `Infinity` if not found.
|
|
40
40
|
*/
|
|
41
41
|
function find_regex_end(string, search_start_index) {
|
|
42
|
-
|
|
42
|
+
const slash = find_unescaped_char(string, search_start_index, '/');
|
|
43
|
+
const eol = find_unescaped_char(string, search_start_index, '\n');
|
|
44
|
+
return slash < eol ? slash : Infinity;
|
|
43
45
|
}
|
|
44
46
|
|
|
45
47
|
/**
|
|
@@ -105,7 +107,11 @@ export function find_matching_bracket(template, index, open) {
|
|
|
105
107
|
continue;
|
|
106
108
|
case '/': {
|
|
107
109
|
const next_char = template[i + 1];
|
|
108
|
-
if (!next_char)
|
|
110
|
+
if (!next_char) {
|
|
111
|
+
// `/` is the last character; advance past it so we don't loop forever
|
|
112
|
+
i++;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
109
115
|
if (next_char === '/') {
|
|
110
116
|
i = infinity_if_negative(template.indexOf('\n', i + 1)) + '\n'.length;
|
|
111
117
|
continue;
|
|
@@ -114,7 +120,12 @@ export function find_matching_bracket(template, index, open) {
|
|
|
114
120
|
i = infinity_if_negative(template.indexOf('*/', i + 1)) + '*/'.length;
|
|
115
121
|
continue;
|
|
116
122
|
}
|
|
117
|
-
|
|
123
|
+
const end = find_regex_end(template, i + 1) + '/'.length;
|
|
124
|
+
if (end === Infinity) {
|
|
125
|
+
i++;
|
|
126
|
+
} else {
|
|
127
|
+
i = end;
|
|
128
|
+
}
|
|
118
129
|
continue;
|
|
119
130
|
}
|
|
120
131
|
default: {
|
|
@@ -2,21 +2,34 @@
|
|
|
2
2
|
/** @import { Context } from '../types' */
|
|
3
3
|
import * as b from '#compiler/builders';
|
|
4
4
|
import * as e from '../../../errors.js';
|
|
5
|
-
import {
|
|
5
|
+
import { extract_identifiers } from '../../../utils/ast.js';
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* @param {AST.DeclarationTag} node
|
|
9
9
|
* @param {Context} context
|
|
10
10
|
*/
|
|
11
11
|
export function DeclarationTag(node, context) {
|
|
12
|
-
validate_opening_tag(node, context.state, node.declaration.kind[0]);
|
|
13
12
|
if (!context.state.analysis.runes && !context.state.analysis.maybe_runes) {
|
|
14
13
|
e.declaration_tag_no_legacy_mode(node);
|
|
15
14
|
}
|
|
16
15
|
|
|
16
|
+
const is_top_level = context.path.length === 1 && context.path[0].type === 'Fragment';
|
|
17
|
+
if (is_top_level) {
|
|
18
|
+
const duplicate = node.declaration.declarations
|
|
19
|
+
.flatMap((declaration) => extract_identifiers(declaration.id))
|
|
20
|
+
.find((id) => context.state.analysis.instance.scope.declarations.has(id.name));
|
|
21
|
+
if (duplicate) {
|
|
22
|
+
e.declaration_duplicate(duplicate, duplicate.name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
context.visit(node.declaration, {
|
|
18
27
|
...context.state,
|
|
19
28
|
in_declaration_tag: true,
|
|
29
|
+
// the declaration lives in the fragment scope, which is one level deeper than the
|
|
30
|
+
// `function_depth` we're tracking here (`set_scope` doesn't update `function_depth`).
|
|
31
|
+
// align them so that `state_referenced_locally` warnings are calculated correctly
|
|
32
|
+
function_depth: context.state.scope.function_depth,
|
|
20
33
|
expression: node.metadata.expression
|
|
21
34
|
});
|
|
22
35
|
|
|
@@ -25,19 +25,24 @@ export function SnippetBlock(node, context) {
|
|
|
25
25
|
|
|
26
26
|
context.next({ ...context.state, parent_element: null });
|
|
27
27
|
|
|
28
|
-
const
|
|
29
|
-
context.path.length === 1 &&
|
|
30
|
-
context.path[0].type === 'Fragment' &&
|
|
31
|
-
can_hoist_snippet(context.state.scope, context.state.scopes);
|
|
28
|
+
const is_top_level = context.path.length === 1 && context.path[0].type === 'Fragment';
|
|
32
29
|
|
|
33
|
-
|
|
30
|
+
if (is_top_level) {
|
|
31
|
+
const name = node.expression.name;
|
|
34
32
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
if (context.state.analysis.instance.scope.declarations.has(name)) {
|
|
34
|
+
e.declaration_duplicate(node.expression, name);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
node.metadata.can_hoist =
|
|
38
|
+
is_top_level && can_hoist_snippet(context.state.scope, context.state.scopes);
|
|
39
39
|
|
|
40
|
-
|
|
40
|
+
if (node.metadata.can_hoist) {
|
|
41
|
+
const name = node.expression.name;
|
|
42
|
+
const binding = /** @type {Binding} */ (context.state.scope.get(name));
|
|
43
|
+
context.state.analysis.module.scope.declarations.set(name, binding);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
41
46
|
|
|
42
47
|
const { path } = context;
|
|
43
48
|
const parent = path.at(-2);
|
|
@@ -10,8 +10,10 @@ import { add_state_transformers } from './shared/declarations.js';
|
|
|
10
10
|
* @param {ComponentContext} context
|
|
11
11
|
*/
|
|
12
12
|
export function DeclarationTag(node, context) {
|
|
13
|
-
|
|
13
|
+
// register the transformers _before_ visiting the declaration, so that
|
|
14
|
+
// later declarators can reference earlier ones (e.g. `{let a = $state(0), b = $derived(a * 2)}`)
|
|
14
15
|
add_state_transformers(context);
|
|
16
|
+
const declaration = /** @type {Statement | undefined} */ (context.visit(node.declaration));
|
|
15
17
|
|
|
16
18
|
if (
|
|
17
19
|
node.metadata.promises_id &&
|
|
@@ -343,7 +343,7 @@ export class PromiseOptimiser {
|
|
|
343
343
|
* @param {ExpressionMetadata} metadata
|
|
344
344
|
*/
|
|
345
345
|
check_blockers(metadata) {
|
|
346
|
-
for (const binding of metadata.
|
|
346
|
+
for (const binding of metadata.references) {
|
|
347
347
|
if (binding.blocker) {
|
|
348
348
|
this.#blockers.add(binding.blocker);
|
|
349
349
|
}
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
set_hydrating,
|
|
10
10
|
skip_nodes
|
|
11
11
|
} from '../hydration.js';
|
|
12
|
+
import { assign_nodes } from '../template.js';
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* @param {TemplateNode} node
|
|
@@ -23,6 +24,7 @@ export function async(node, blockers = [], expressions = [], fn) {
|
|
|
23
24
|
if (was_hydrating) {
|
|
24
25
|
hydrate_next();
|
|
25
26
|
end = skip_nodes(false);
|
|
27
|
+
assign_nodes(node, end); // Necessary if this wraps the sole child of a block, else end marker can be wrong
|
|
26
28
|
}
|
|
27
29
|
|
|
28
30
|
if (expressions.length === 0 && blockers.every((b) => b.settled)) {
|
|
@@ -203,7 +203,9 @@ export function each(node, flags, get_collection, get_key, render_fn, fallback_f
|
|
|
203
203
|
var each_array = derived_safe_equal(() => {
|
|
204
204
|
var collection = get_collection();
|
|
205
205
|
|
|
206
|
-
return
|
|
206
|
+
return /** @type {V[]} */ (
|
|
207
|
+
is_array(collection) ? collection : collection == null ? [] : array_from(collection)
|
|
208
|
+
);
|
|
207
209
|
});
|
|
208
210
|
|
|
209
211
|
if (DEV) {
|
|
@@ -332,6 +332,15 @@ function set_attributes(
|
|
|
332
332
|
|
|
333
333
|
var setters = get_setters(element);
|
|
334
334
|
|
|
335
|
+
if (element.nodeName === INPUT_TAG && 'type' in next && ('value' in next || '__value' in next)) {
|
|
336
|
+
var type = next.type;
|
|
337
|
+
|
|
338
|
+
if (type !== current.type || (type === undefined && element.hasAttribute('type'))) {
|
|
339
|
+
current.type = type;
|
|
340
|
+
set_attribute(element, 'type', type, skip_warning);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
335
344
|
// since key is captured we use const
|
|
336
345
|
for (const key in next) {
|
|
337
346
|
// let instead of var because referenced in a closure
|
|
@@ -7,7 +7,6 @@ import { is } from '../../../proxy.js';
|
|
|
7
7
|
import { queue_micro_task } from '../../task.js';
|
|
8
8
|
import { hydrating } from '../../hydration.js';
|
|
9
9
|
import { tick, untrack } from '../../../runtime.js';
|
|
10
|
-
import { is_runes } from '../../../context.js';
|
|
11
10
|
import { current_batch, previous_batch } from '../../../reactivity/batch.js';
|
|
12
11
|
import { async_mode_flag } from '../../../../flags/index.js';
|
|
13
12
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Blocker, Effect, Value } from '#client' */
|
|
1
|
+
/** @import { Blocker, Effect, Source, Value } from '#client' */
|
|
2
2
|
import { DESTROYED, STALE_REACTION } from '#client/constants';
|
|
3
3
|
import { DEV } from 'esm-env';
|
|
4
4
|
import {
|
|
@@ -38,8 +38,22 @@ export function flatten(blockers, sync, async, fn) {
|
|
|
38
38
|
// Filter out already-settled blockers - no need to wait for them
|
|
39
39
|
var pending = blockers.filter((b) => !b.settled);
|
|
40
40
|
|
|
41
|
+
var deriveds = sync.map(d);
|
|
42
|
+
|
|
43
|
+
if (DEV) {
|
|
44
|
+
deriveds.forEach((d, i) => {
|
|
45
|
+
// TODO this is kinda useful for debugging but a lousy implementation —
|
|
46
|
+
// maybe the compiler could pass through the template string
|
|
47
|
+
d.label = sync[i]
|
|
48
|
+
.toString()
|
|
49
|
+
.replace('() => ', '')
|
|
50
|
+
.replaceAll('$.eager(() => ', '$state.eager(')
|
|
51
|
+
.replace(/\$\.get\((.+?)\)/g, (_, id) => id);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
41
55
|
if (async.length === 0 && pending.length === 0) {
|
|
42
|
-
fn(
|
|
56
|
+
fn(deriveds);
|
|
43
57
|
return;
|
|
44
58
|
}
|
|
45
59
|
|
|
@@ -53,8 +67,10 @@ export function flatten(blockers, sync, async, fn) {
|
|
|
53
67
|
? Promise.all(pending.map((b) => b.promise))
|
|
54
68
|
: null;
|
|
55
69
|
|
|
56
|
-
/**
|
|
57
|
-
|
|
70
|
+
/**
|
|
71
|
+
* @param {Source[]} async
|
|
72
|
+
*/
|
|
73
|
+
function finish(async) {
|
|
58
74
|
if ((parent.f & DESTROYED) !== 0) {
|
|
59
75
|
return;
|
|
60
76
|
}
|
|
@@ -62,7 +78,7 @@ export function flatten(blockers, sync, async, fn) {
|
|
|
62
78
|
restore();
|
|
63
79
|
|
|
64
80
|
try {
|
|
65
|
-
fn(
|
|
81
|
+
fn([...deriveds, ...async]);
|
|
66
82
|
} catch (error) {
|
|
67
83
|
invoke_error_boundary(error, parent);
|
|
68
84
|
}
|
|
@@ -74,17 +90,14 @@ export function flatten(blockers, sync, async, fn) {
|
|
|
74
90
|
|
|
75
91
|
// Fast path: blockers but no async expressions
|
|
76
92
|
if (async.length === 0) {
|
|
77
|
-
/** @type {Promise<any>} */ (blocker_promise)
|
|
78
|
-
.then(() => finish(sync.map(d)))
|
|
79
|
-
.finally(decrement_pending);
|
|
80
|
-
|
|
93
|
+
/** @type {Promise<any>} */ (blocker_promise).then(() => finish([])).finally(decrement_pending);
|
|
81
94
|
return;
|
|
82
95
|
}
|
|
83
96
|
|
|
84
97
|
// Full path: has async expressions
|
|
85
98
|
function run() {
|
|
86
99
|
Promise.all(async.map((expression) => async_derived(expression)))
|
|
87
|
-
.then(
|
|
100
|
+
.then(finish)
|
|
88
101
|
.catch((error) => invoke_error_boundary(error, parent))
|
|
89
102
|
.finally(decrement_pending);
|
|
90
103
|
}
|
|
@@ -168,10 +181,10 @@ export async function save(promise) {
|
|
|
168
181
|
* @returns {Promise<() => T>}
|
|
169
182
|
*/
|
|
170
183
|
export async function track_reactivity_loss(promise) {
|
|
171
|
-
var
|
|
184
|
+
var previous_reactivity_loss_tracker = reactivity_loss_tracker;
|
|
172
185
|
// Ensure that unrelated reads after an async operation is kicked off don't cause false positives
|
|
173
186
|
queueMicrotask(() => {
|
|
174
|
-
if (reactivity_loss_tracker ===
|
|
187
|
+
if (reactivity_loss_tracker === previous_reactivity_loss_tracker) {
|
|
175
188
|
set_reactivity_loss_tracker(null);
|
|
176
189
|
}
|
|
177
190
|
});
|
|
@@ -179,12 +192,12 @@ export async function track_reactivity_loss(promise) {
|
|
|
179
192
|
var value = await promise;
|
|
180
193
|
|
|
181
194
|
return () => {
|
|
182
|
-
set_reactivity_loss_tracker(
|
|
195
|
+
set_reactivity_loss_tracker(previous_reactivity_loss_tracker);
|
|
183
196
|
// While this can result in false negatives it also guards against the more important
|
|
184
197
|
// false positives that would occur if this is the last in a chain of async operations,
|
|
185
198
|
// and the reactivity_loss_tracker would then stay around until the next async operation happens.
|
|
186
199
|
queueMicrotask(() => {
|
|
187
|
-
if (reactivity_loss_tracker ===
|
|
200
|
+
if (reactivity_loss_tracker === previous_reactivity_loss_tracker) {
|
|
188
201
|
set_reactivity_loss_tracker(null);
|
|
189
202
|
}
|
|
190
203
|
});
|
|
@@ -41,6 +41,7 @@ import { set_signal_status } from './status.js';
|
|
|
41
41
|
import { legacy_is_updating_store } from './store.js';
|
|
42
42
|
import { invariant } from '../../shared/dev.js';
|
|
43
43
|
import { log_effect_tree } from '../dev/debug.js';
|
|
44
|
+
import { OBSOLETE } from './deriveds.js';
|
|
44
45
|
|
|
45
46
|
/** @type {Batch | null} */
|
|
46
47
|
let first_batch = null;
|
|
@@ -511,6 +512,10 @@ export class Batch {
|
|
|
511
512
|
if (d) deferred.promise.then(d.resolve).catch(d.reject);
|
|
512
513
|
}
|
|
513
514
|
|
|
515
|
+
// Clear them or else those that are still pending might get rejected on discard (after merged-into batch is done).
|
|
516
|
+
// This can happen when batch Y merged into X and Y has a pending boundary and therefore still-pending async deriveds inside.
|
|
517
|
+
batch.async_deriveds.clear();
|
|
518
|
+
|
|
514
519
|
// Mark is not guaranteed not touch these, so we transfer them
|
|
515
520
|
this.transfer_effects(batch.#dirty_effects, batch.#maybe_dirty_effects);
|
|
516
521
|
|
|
@@ -629,6 +634,10 @@ export class Batch {
|
|
|
629
634
|
for (const fn of this.#discard_callbacks) fn(this);
|
|
630
635
|
this.#discard_callbacks.clear();
|
|
631
636
|
|
|
637
|
+
for (const deferred of this.async_deriveds.values()) {
|
|
638
|
+
deferred.reject(OBSOLETE);
|
|
639
|
+
}
|
|
640
|
+
|
|
632
641
|
this.#unlink();
|
|
633
642
|
this.#deferred?.resolve();
|
|
634
643
|
}
|
|
@@ -677,12 +686,15 @@ export class Batch {
|
|
|
677
686
|
}
|
|
678
687
|
}
|
|
679
688
|
|
|
680
|
-
|
|
689
|
+
var current = [...batch.current.keys()].filter(
|
|
690
|
+
(source) => !(/** @type {[any, boolean]} */ (batch.current.get(source))[1])
|
|
691
|
+
);
|
|
692
|
+
|
|
693
|
+
// If not started yet or no sources to update (which is e.g. possible for the very first batch) then bail
|
|
694
|
+
if (!batch.#started || current.length === 0) continue;
|
|
681
695
|
|
|
682
696
|
// Re-run async/block effects that depend on distinct values changed in both batches (ignoring deriveds)
|
|
683
|
-
var others =
|
|
684
|
-
(s) => !(/** @type {[any, boolean]} */ (batch.current.get(s))[1]) && !this.current.has(s)
|
|
685
|
-
);
|
|
697
|
+
var others = current.filter((source) => !this.current.has(source));
|
|
686
698
|
|
|
687
699
|
if (others.length === 0) {
|
|
688
700
|
if (is_earlier) {
|
|
@@ -387,7 +387,9 @@ export function render_effect(fn, flags = 0) {
|
|
|
387
387
|
*/
|
|
388
388
|
export function template_effect(fn, sync = [], async = [], blockers = []) {
|
|
389
389
|
flatten(blockers, sync, async, (values) => {
|
|
390
|
-
create_effect(RENDER_EFFECT, () =>
|
|
390
|
+
create_effect(RENDER_EFFECT, () => {
|
|
391
|
+
fn(...values.map(get));
|
|
392
|
+
});
|
|
391
393
|
});
|
|
392
394
|
}
|
|
393
395
|
|
|
@@ -518,7 +520,7 @@ export function destroy_effect(effect, remove_dom = true) {
|
|
|
518
520
|
removed = true;
|
|
519
521
|
}
|
|
520
522
|
|
|
521
|
-
|
|
523
|
+
effect.f |= DESTROYING;
|
|
522
524
|
destroy_effect_children(effect, remove_dom && !removed);
|
|
523
525
|
remove_reactions(effect, 0);
|
|
524
526
|
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
batch_values,
|
|
52
52
|
current_batch,
|
|
53
53
|
flushSync,
|
|
54
|
+
previous_batch,
|
|
54
55
|
schedule_effect
|
|
55
56
|
} from './reactivity/batch.js';
|
|
56
57
|
import { handle_error } from './error-handling.js';
|
|
@@ -581,6 +582,11 @@ export function get(signal) {
|
|
|
581
582
|
if (
|
|
582
583
|
!untracking &&
|
|
583
584
|
reactivity_loss_tracker &&
|
|
585
|
+
// By checking that current/previous batch are null we filter out false positives.
|
|
586
|
+
// reactivity_loss_tracker is only reset after a microtask, so if a flush happens
|
|
587
|
+
// before that, we get warnings for things we shouldn't warn on.
|
|
588
|
+
current_batch === null &&
|
|
589
|
+
previous_batch === null &&
|
|
584
590
|
!reactivity_loss_tracker.warned &&
|
|
585
591
|
(reactivity_loss_tracker.effect.f & REACTION_IS_UPDATING) === 0 &&
|
|
586
592
|
!reactivity_loss_tracker.effect_deps.has(signal)
|
|
@@ -132,11 +132,12 @@ export class SvelteURLSearchParams extends URLSearchParams {
|
|
|
132
132
|
* @returns {void}
|
|
133
133
|
*/
|
|
134
134
|
set(name, value) {
|
|
135
|
-
var previous = super.getAll(name)
|
|
135
|
+
var previous = super.getAll(name);
|
|
136
136
|
super.set(name, value);
|
|
137
137
|
// can't use has(name, value), because for something like https://svelte.dev?foo=1&bar=2&foo=3
|
|
138
138
|
// if you set `foo` to 1, then foo=3 gets deleted whilst `has("foo", "1")` returns true
|
|
139
|
-
|
|
139
|
+
var current = super.getAll(name);
|
|
140
|
+
if (previous.length !== current.length || previous.some((value, i) => value !== current[i])) {
|
|
140
141
|
this.#update_url();
|
|
141
142
|
increment(this.#version);
|
|
142
143
|
}
|
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": "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",
|
|
277
277
|
"ignoreList": []
|
|
278
278
|
}
|