svelte 5.55.8 → 5.55.10
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 +4 -4
- package/src/compiler/phases/2-analyze/visitors/AwaitExpression.js +1 -2
- package/src/compiler/phases/2-analyze/visitors/shared/a11y/index.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/AwaitBlock.js +2 -2
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +2 -2
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +13 -16
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/AwaitBlock.js +8 -1
- package/src/compiler/phases/3-transform/server/visitors/shared/utils.js +21 -12
- package/src/compiler/phases/nodes.js +2 -2
- package/src/compiler/warnings.js +6 -5
- package/src/internal/client/dom/blocks/await.js +16 -12
- package/src/internal/client/dom/blocks/branches.js +2 -0
- package/src/internal/client/dom/blocks/svelte-element.js +5 -3
- package/src/internal/client/dom/elements/events.js +5 -10
- package/src/internal/client/reactivity/async.js +4 -4
- package/src/internal/client/reactivity/batch.js +75 -59
- package/src/internal/client/reactivity/deriveds.js +7 -4
- package/src/internal/client/reactivity/effects.js +5 -2
- package/src/internal/client/runtime.js +9 -3
- 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.55.
|
|
5
|
+
"version": "5.55.10",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"types": "./types/index.d.ts",
|
|
8
8
|
"engines": {
|
|
@@ -157,7 +157,7 @@
|
|
|
157
157
|
"dependencies": {
|
|
158
158
|
"@jridgewell/remapping": "^2.3.4",
|
|
159
159
|
"@jridgewell/sourcemap-codec": "^1.5.0",
|
|
160
|
-
"@sveltejs/acorn-typescript": "^1.0.
|
|
160
|
+
"@sveltejs/acorn-typescript": "^1.0.10",
|
|
161
161
|
"@types/estree": "^1.0.5",
|
|
162
162
|
"@types/trusted-types": "^2.0.7",
|
|
163
163
|
"acorn": "^8.12.1",
|
|
@@ -166,14 +166,14 @@
|
|
|
166
166
|
"clsx": "^2.1.1",
|
|
167
167
|
"devalue": "^5.8.1",
|
|
168
168
|
"esm-env": "^1.2.1",
|
|
169
|
-
"esrap": "^2.2.
|
|
169
|
+
"esrap": "^2.2.9",
|
|
170
170
|
"is-reference": "^3.0.3",
|
|
171
171
|
"locate-character": "^3.0.0",
|
|
172
172
|
"magic-string": "^0.30.11",
|
|
173
173
|
"zimmerframe": "^1.1.2"
|
|
174
174
|
},
|
|
175
175
|
"scripts": {
|
|
176
|
-
"build": "rollup -c && pnpm generate",
|
|
176
|
+
"build": "rollup -c && pnpm generate && node scripts/check-treeshakeability.js",
|
|
177
177
|
"dev": "node scripts/process-messages -w & rollup -cw",
|
|
178
178
|
"check": "tsc --project tsconfig.runtime.json && tsc && cd ./tests/types && tsc",
|
|
179
179
|
"check:tsgo": "tsgo --project tsconfig.runtime.json --skipLibCheck && tsgo --skipLibCheck",
|
|
@@ -115,8 +115,7 @@ function is_last_evaluated_expression(path, node) {
|
|
|
115
115
|
break;
|
|
116
116
|
|
|
117
117
|
case 'MemberExpression':
|
|
118
|
-
|
|
119
|
-
break;
|
|
118
|
+
return false;
|
|
120
119
|
|
|
121
120
|
case 'ObjectExpression':
|
|
122
121
|
if (node !== parent.properties.at(-1)) return false;
|
|
@@ -302,7 +302,7 @@ export function check_element(node, context) {
|
|
|
302
302
|
const has_key_event =
|
|
303
303
|
handlers.has('keydown') || handlers.has('keyup') || handlers.has('keypress');
|
|
304
304
|
if (!has_key_event) {
|
|
305
|
-
w.a11y_click_events_have_key_events(node);
|
|
305
|
+
w.a11y_click_events_have_key_events(node, node.name);
|
|
306
306
|
}
|
|
307
307
|
}
|
|
308
308
|
}
|
|
@@ -71,14 +71,14 @@ export function AwaitBlock(node, context) {
|
|
|
71
71
|
'await'
|
|
72
72
|
);
|
|
73
73
|
|
|
74
|
-
if (node.metadata.expression.has_blockers()) {
|
|
74
|
+
if (node.metadata.expression.has_blockers() || node.metadata.expression.has_await) {
|
|
75
75
|
context.state.init.push(
|
|
76
76
|
b.stmt(
|
|
77
77
|
b.call(
|
|
78
78
|
'$.async',
|
|
79
79
|
context.state.node,
|
|
80
80
|
node.metadata.expression.blockers(),
|
|
81
|
-
b.array([]),
|
|
81
|
+
b.array([]), // {#await await ...} is special insofar that the await should not be waited on
|
|
82
82
|
b.arrow([context.state.node], b.block([stmt]))
|
|
83
83
|
)
|
|
84
84
|
)
|
|
@@ -201,8 +201,8 @@ export function RegularElement(node, context) {
|
|
|
201
201
|
}
|
|
202
202
|
}
|
|
203
203
|
|
|
204
|
-
// Let bindings first, they can be used on attributes
|
|
205
|
-
context.state.
|
|
204
|
+
// Let bindings first, they can be used on attributes and `{@const}` declarations
|
|
205
|
+
context.state.let_directives.push(...lets);
|
|
206
206
|
|
|
207
207
|
const node_id = context.state.node;
|
|
208
208
|
|
|
@@ -194,11 +194,6 @@ export function VariableDeclaration(node, context) {
|
|
|
194
194
|
/** @type {CallExpression} */ (init)
|
|
195
195
|
);
|
|
196
196
|
|
|
197
|
-
// for now, only wrap async derived in $.save if it's not
|
|
198
|
-
// a top-level instance derived. TODO in future maybe we
|
|
199
|
-
// can dewaterfall all of them?
|
|
200
|
-
const should_save = context.state.is_instance && context.state.scope.function_depth > 1;
|
|
201
|
-
|
|
202
197
|
if (declarator.id.type === 'Identifier') {
|
|
203
198
|
let expression = /** @type {Expression} */ (context.visit(value));
|
|
204
199
|
|
|
@@ -213,9 +208,7 @@ export function VariableDeclaration(node, context) {
|
|
|
213
208
|
location ? b.literal(location) : undefined
|
|
214
209
|
);
|
|
215
210
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
declarations.push(b.declarator(declarator.id, call));
|
|
211
|
+
declarations.push(b.declarator(declarator.id, b.await(call)));
|
|
219
212
|
} else {
|
|
220
213
|
if (rune === '$derived') expression = b.thunk(expression);
|
|
221
214
|
|
|
@@ -251,7 +244,7 @@ export function VariableDeclaration(node, context) {
|
|
|
251
244
|
location ? b.literal(location) : undefined
|
|
252
245
|
);
|
|
253
246
|
|
|
254
|
-
call =
|
|
247
|
+
call = b.await(call);
|
|
255
248
|
}
|
|
256
249
|
|
|
257
250
|
declarations.push(b.declarator(id, call));
|
|
@@ -386,13 +379,17 @@ export function VariableDeclaration(node, context) {
|
|
|
386
379
|
* @param {Expression} value
|
|
387
380
|
*/
|
|
388
381
|
function create_state_declarators(declarator, context, value) {
|
|
382
|
+
/**
|
|
383
|
+
* @param {Expression} value
|
|
384
|
+
* @param {string} name
|
|
385
|
+
*/
|
|
386
|
+
const mutable_source = (value, name) => {
|
|
387
|
+
const call = b.call('$.mutable_source', value, context.state.analysis.immutable && b.true);
|
|
388
|
+
return dev ? b.call('$.tag', call, b.literal(name)) : call;
|
|
389
|
+
};
|
|
390
|
+
|
|
389
391
|
if (declarator.id.type === 'Identifier') {
|
|
390
|
-
return [
|
|
391
|
-
b.declarator(
|
|
392
|
-
declarator.id,
|
|
393
|
-
b.call('$.mutable_source', value, context.state.analysis.immutable ? b.true : undefined)
|
|
394
|
-
)
|
|
395
|
-
];
|
|
392
|
+
return [b.declarator(declarator.id, mutable_source(value, declarator.id.name))];
|
|
396
393
|
}
|
|
397
394
|
|
|
398
395
|
const tmp = b.id(context.state.scope.generate('tmp'));
|
|
@@ -414,7 +411,7 @@ function create_state_declarators(declarator, context, value) {
|
|
|
414
411
|
return b.declarator(
|
|
415
412
|
path.node,
|
|
416
413
|
binding?.kind === 'state'
|
|
417
|
-
?
|
|
414
|
+
? mutable_source(value, /** @type {Identifier} */ (path.node).name)
|
|
418
415
|
: value
|
|
419
416
|
);
|
|
420
417
|
})
|
|
@@ -52,7 +52,7 @@ export class Memoizer {
|
|
|
52
52
|
* @param {ExpressionMetadata} metadata
|
|
53
53
|
*/
|
|
54
54
|
check_blockers(metadata) {
|
|
55
|
-
for (const binding of metadata.
|
|
55
|
+
for (const binding of metadata.references) {
|
|
56
56
|
if (binding.blocker) {
|
|
57
57
|
this.#blockers.add(binding.blocker);
|
|
58
58
|
}
|
|
@@ -9,12 +9,19 @@ import { block_close, create_child_block } from './shared/utils.js';
|
|
|
9
9
|
* @param {ComponentContext} context
|
|
10
10
|
*/
|
|
11
11
|
export function AwaitBlock(node, context) {
|
|
12
|
+
let expression = /** @type {Expression} */ (context.visit(node.expression));
|
|
13
|
+
if (node.metadata.expression.has_await) {
|
|
14
|
+
// If this is an await expression, turn it into a IIFE so that the result is a promise.
|
|
15
|
+
// {#await await ...} is special insofar that the await should not be waited on.
|
|
16
|
+
expression = b.call(b.arrow([], expression, true));
|
|
17
|
+
}
|
|
18
|
+
|
|
12
19
|
/** @type {Statement} */
|
|
13
20
|
let statement = b.stmt(
|
|
14
21
|
b.call(
|
|
15
22
|
'$.await',
|
|
16
23
|
b.id('$$renderer'),
|
|
17
|
-
|
|
24
|
+
expression,
|
|
18
25
|
b.thunk(
|
|
19
26
|
node.pending ? /** @type {BlockStatement} */ (context.visit(node.pending)) : b.block([])
|
|
20
27
|
),
|
|
@@ -229,18 +229,25 @@ export function build_attribute_value(
|
|
|
229
229
|
? node.data.replace(regex_whitespaces_strict, ' ')
|
|
230
230
|
: node.data;
|
|
231
231
|
} else {
|
|
232
|
-
|
|
233
|
-
b.call(
|
|
234
|
-
'$.stringify',
|
|
235
|
-
transform(
|
|
236
|
-
/** @type {Expression} */ (context.visit(node.expression)),
|
|
237
|
-
node.metadata.expression
|
|
238
|
-
)
|
|
239
|
-
)
|
|
240
|
-
);
|
|
232
|
+
const evaluated = context.state.scope.evaluate(node.expression);
|
|
241
233
|
|
|
242
|
-
|
|
243
|
-
|
|
234
|
+
if (evaluated.is_known) {
|
|
235
|
+
quasi.value.cooked += (evaluated.value ?? '') + '';
|
|
236
|
+
} else {
|
|
237
|
+
const expression = transform(
|
|
238
|
+
/** @type {Expression} */ (context.visit(node.expression)),
|
|
239
|
+
node.metadata.expression
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
expressions.push(
|
|
243
|
+
evaluated.is_string && evaluated.is_defined
|
|
244
|
+
? expression
|
|
245
|
+
: b.call('$.stringify', expression)
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
quasi = b.quasi('', i + 1 === value.length);
|
|
249
|
+
quasis.push(quasi);
|
|
250
|
+
}
|
|
244
251
|
}
|
|
245
252
|
}
|
|
246
253
|
|
|
@@ -248,7 +255,9 @@ export function build_attribute_value(
|
|
|
248
255
|
quasi.value.raw = sanitize_template_string(/** @type {string} */ (quasi.value.cooked));
|
|
249
256
|
}
|
|
250
257
|
|
|
251
|
-
return
|
|
258
|
+
return expressions.length > 0
|
|
259
|
+
? b.template(quasis, expressions)
|
|
260
|
+
: b.literal(/** @type {string} */ (quasi.value.cooked));
|
|
252
261
|
}
|
|
253
262
|
|
|
254
263
|
/**
|
|
@@ -102,8 +102,8 @@ export class ExpressionMetadata {
|
|
|
102
102
|
if (!this.#blockers) {
|
|
103
103
|
this.#blockers = new Set();
|
|
104
104
|
|
|
105
|
-
for (const
|
|
106
|
-
if (
|
|
105
|
+
for (const r of this.references) {
|
|
106
|
+
if (r.blocker) this.#blockers.add(r.blocker);
|
|
107
107
|
}
|
|
108
108
|
}
|
|
109
109
|
|
package/src/compiler/warnings.js
CHANGED
|
@@ -166,11 +166,12 @@ export function a11y_autofocus(node) {
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
|
-
* Visible, non-interactive
|
|
169
|
+
* Visible, non-interactive element `<%element%>` with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as `<button type="button">` or `<a>` might be more appropriate
|
|
170
170
|
* @param {null | NodeLike} node
|
|
171
|
+
* @param {string} element
|
|
171
172
|
*/
|
|
172
|
-
export function a11y_click_events_have_key_events(node) {
|
|
173
|
-
w(node, 'a11y_click_events_have_key_events', `Visible, non-interactive
|
|
173
|
+
export function a11y_click_events_have_key_events(node, element) {
|
|
174
|
+
w(node, 'a11y_click_events_have_key_events', `Visible, non-interactive element \`<${element}>\` with a click event must be accompanied by a keyboard event handler. Consider whether an interactive element such as \`<button type="button">\` or \`<a>\` might be more appropriate\nhttps://svelte.dev/e/a11y_click_events_have_key_events`);
|
|
174
175
|
}
|
|
175
176
|
|
|
176
177
|
/**
|
|
@@ -803,11 +804,11 @@ export function script_context_deprecated(node) {
|
|
|
803
804
|
}
|
|
804
805
|
|
|
805
806
|
/**
|
|
806
|
-
*
|
|
807
|
+
* Unrecognised attribute — should be one of `generics`, `lang` or `module`. If this exists for a preprocessor, ensure that the preprocessor removes it
|
|
807
808
|
* @param {null | NodeLike} node
|
|
808
809
|
*/
|
|
809
810
|
export function script_unknown_attribute(node) {
|
|
810
|
-
w(node, 'script_unknown_attribute', `
|
|
811
|
+
w(node, 'script_unknown_attribute', `Unrecognised attribute — should be one of \`generics\`, \`lang\` or \`module\`. If this exists for a preprocessor, ensure that the preprocessor removes it\nhttps://svelte.dev/e/script_unknown_attribute`);
|
|
811
812
|
}
|
|
812
813
|
|
|
813
814
|
/**
|
|
@@ -7,7 +7,8 @@ import {
|
|
|
7
7
|
hydrating,
|
|
8
8
|
skip_nodes,
|
|
9
9
|
set_hydrate_node,
|
|
10
|
-
set_hydrating
|
|
10
|
+
set_hydrating,
|
|
11
|
+
hydrate_node
|
|
11
12
|
} from '../hydration.js';
|
|
12
13
|
import { queue_micro_task } from '../task.js';
|
|
13
14
|
import { HYDRATION_START_ELSE, UNINITIALIZED } from '../../../../constants.js';
|
|
@@ -15,6 +16,7 @@ import { is_runes } from '../../context.js';
|
|
|
15
16
|
import { Batch, current_batch, flushSync, is_flushing_sync } from '../../reactivity/batch.js';
|
|
16
17
|
import { BranchManager } from './branches.js';
|
|
17
18
|
import { capture, unset_context } from '../../reactivity/async.js';
|
|
19
|
+
import { DEV } from 'esm-env';
|
|
18
20
|
|
|
19
21
|
const PENDING = 0;
|
|
20
22
|
const THEN = 1;
|
|
@@ -42,16 +44,16 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
|
|
|
42
44
|
var value = runes ? source(v) : mutable_source(v, false, false);
|
|
43
45
|
var error = runes ? source(v) : mutable_source(v, false, false);
|
|
44
46
|
|
|
47
|
+
if (DEV) {
|
|
48
|
+
value.label = '{#await ...} value';
|
|
49
|
+
error.label = '{#await ...} error';
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
var branches = new BranchManager(node);
|
|
46
53
|
|
|
47
54
|
block(() => {
|
|
48
55
|
var batch = /** @type {Batch} */ (current_batch);
|
|
49
|
-
|
|
50
|
-
// we null out `current_batch` because otherwise `save(...)` will incorrectly restore it —
|
|
51
|
-
// the batch will already have been committed by the time it resolves
|
|
52
|
-
batch.deactivate();
|
|
53
56
|
var input = get_input();
|
|
54
|
-
batch.activate();
|
|
55
57
|
|
|
56
58
|
var destroyed = false;
|
|
57
59
|
|
|
@@ -79,15 +81,17 @@ export function await_block(node, get_input, pending_fn, then_fn, catch_fn) {
|
|
|
79
81
|
// We don't want to restore the previous batch here; {#await} blocks don't follow the async logic
|
|
80
82
|
// we have elsewhere, instead pending/resolve/fail states are each their own batch so to speak.
|
|
81
83
|
restore(false);
|
|
84
|
+
// ...but it might still be set here. That means a `save(...)` has restored it — but that batch will
|
|
85
|
+
// likely already have been committed by the time it resolves, and this resolve should be processed
|
|
86
|
+
// in a separate batch. We're not using batch.deactivate()/activate() above because get_input()
|
|
87
|
+
// could write to sources, which would then incorrectly create a new batch or could mess with
|
|
88
|
+
// async_derived expecting a current_batch to exist.
|
|
89
|
+
if (current_batch === batch) {
|
|
90
|
+
batch.deactivate();
|
|
91
|
+
}
|
|
82
92
|
// Make sure we have a batch, since the branch manager expects one to exist
|
|
83
93
|
Batch.ensure();
|
|
84
94
|
|
|
85
|
-
if (hydrating) {
|
|
86
|
-
// `restore()` could set `hydrating` to `true`, which we very much
|
|
87
|
-
// don't want — we want to restore everything _except_ this
|
|
88
|
-
set_hydrating(false);
|
|
89
|
-
}
|
|
90
|
-
|
|
91
95
|
try {
|
|
92
96
|
fn();
|
|
93
97
|
} finally {
|
|
@@ -90,6 +90,8 @@ export class BranchManager {
|
|
|
90
90
|
var offscreen = this.#offscreen.get(key);
|
|
91
91
|
|
|
92
92
|
if (offscreen) {
|
|
93
|
+
// effect could have been outro'ed before through a prior batch — resume if necessary
|
|
94
|
+
resume_effect(offscreen.effect);
|
|
93
95
|
this.#onscreen.set(key, offscreen.effect);
|
|
94
96
|
this.#offscreen.delete(key);
|
|
95
97
|
|
|
@@ -88,9 +88,11 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
|
|
|
88
88
|
assign_nodes(element, element);
|
|
89
89
|
|
|
90
90
|
if (render_fn) {
|
|
91
|
+
var tmp_comment = null;
|
|
92
|
+
|
|
91
93
|
if (hydrating && is_raw_text_element(next_tag)) {
|
|
92
|
-
// prevent hydration glitches
|
|
93
|
-
element.append(document.createComment(''));
|
|
94
|
+
// prevent hydration glitches (code just below expects an anchor)
|
|
95
|
+
element.append((tmp_comment = document.createComment('')));
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
// If hydrating, use the existing ssr comment as the anchor so that the
|
|
@@ -114,7 +116,7 @@ export function element(node, get_tag, is_svg, render_fn, get_namespace, locatio
|
|
|
114
116
|
// contains children, it's a user error (which is warned on elsewhere)
|
|
115
117
|
// and the DOM will be silently discarded
|
|
116
118
|
render_fn(element, child_anchor);
|
|
117
|
-
|
|
119
|
+
tmp_comment?.remove();
|
|
118
120
|
set_animation_effect_override(null);
|
|
119
121
|
}
|
|
120
122
|
|
|
@@ -257,12 +257,7 @@ export function handle_event_propagation(event) {
|
|
|
257
257
|
var other_errors = [];
|
|
258
258
|
|
|
259
259
|
while (current_target !== null) {
|
|
260
|
-
|
|
261
|
-
var parent_element =
|
|
262
|
-
current_target.assignedSlot ||
|
|
263
|
-
current_target.parentNode ||
|
|
264
|
-
/** @type {any} */ (current_target).host ||
|
|
265
|
-
null;
|
|
260
|
+
if (current_target === handler_element) break;
|
|
266
261
|
|
|
267
262
|
try {
|
|
268
263
|
// @ts-expect-error
|
|
@@ -284,10 +279,10 @@ export function handle_event_propagation(event) {
|
|
|
284
279
|
throw_error = error;
|
|
285
280
|
}
|
|
286
281
|
}
|
|
287
|
-
if (event.cancelBubble
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
current_target =
|
|
282
|
+
if (event.cancelBubble) break;
|
|
283
|
+
|
|
284
|
+
path_idx++;
|
|
285
|
+
current_target = path_idx < path.length ? /** @type {Element} */ (path[path_idx]) : null;
|
|
291
286
|
}
|
|
292
287
|
|
|
293
288
|
if (throw_error) {
|
|
@@ -352,15 +352,15 @@ export function wait(blockers) {
|
|
|
352
352
|
*/
|
|
353
353
|
export function increment_pending() {
|
|
354
354
|
var effect = /** @type {Effect} */ (active_effect);
|
|
355
|
-
var boundary =
|
|
355
|
+
var boundary = effect.b; // undefined if called outside the render tree, e.g. a standalone $effect.root
|
|
356
356
|
var batch = /** @type {Batch} */ (current_batch);
|
|
357
|
-
var blocking = boundary
|
|
357
|
+
var blocking = !!boundary?.is_rendered();
|
|
358
358
|
|
|
359
|
-
boundary
|
|
359
|
+
boundary?.update_pending_count(1, batch);
|
|
360
360
|
batch.increment(blocking, effect);
|
|
361
361
|
|
|
362
362
|
return () => {
|
|
363
|
-
boundary
|
|
363
|
+
boundary?.update_pending_count(-1, batch);
|
|
364
364
|
batch.decrement(blocking, effect);
|
|
365
365
|
};
|
|
366
366
|
}
|