svelte 5.45.1 → 5.45.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/errors.js +9 -0
- package/src/compiler/phases/1-parse/index.js +32 -16
- package/src/compiler/phases/1-parse/read/context.js +3 -12
- package/src/compiler/phases/1-parse/state/element.js +79 -55
- package/src/compiler/phases/1-parse/state/tag.js +8 -16
- package/src/compiler/phases/2-analyze/index.js +2 -2
- package/src/compiler/phases/2-analyze/visitors/Identifier.js +2 -1
- package/src/compiler/phases/2-analyze/visitors/RegularElement.js +3 -2
- package/src/compiler/phases/3-transform/client/transform-template/index.js +1 -2
- package/src/compiler/phases/3-transform/client/visitors/BindDirective.js +27 -11
- package/src/compiler/phases/3-transform/client/visitors/CallExpression.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/Component.js +1 -2
- package/src/compiler/phases/3-transform/client/visitors/Fragment.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/RegularElement.js +1 -0
- package/src/compiler/phases/3-transform/client/visitors/SvelteComponent.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/SvelteHead.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/SvelteSelf.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/TitleElement.js +1 -1
- package/src/compiler/phases/3-transform/client/visitors/VariableDeclaration.js +2 -1
- package/src/compiler/phases/3-transform/client/visitors/shared/component.js +27 -25
- package/src/compiler/phases/3-transform/client/visitors/shared/events.js +8 -2
- package/src/compiler/phases/3-transform/client/visitors/shared/fragment.js +10 -4
- package/src/compiler/phases/3-transform/client/visitors/shared/utils.js +2 -2
- package/src/compiler/phases/3-transform/server/visitors/RegularElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/SvelteElement.js +1 -1
- package/src/compiler/phases/3-transform/server/visitors/shared/element.js +2 -2
- package/src/compiler/phases/3-transform/shared/transform-async.js +4 -1
- package/src/compiler/phases/nodes.js +4 -2
- package/src/compiler/state.js +12 -4
- package/src/compiler/utils/builders.js +6 -2
- package/src/internal/client/dev/debug.js +361 -3
- package/src/internal/client/reactivity/batch.js +3 -0
- package/src/internal/client/reactivity/sources.js +2 -0
- package/src/internal/server/hydratable.js +11 -1
- package/src/version.js +1 -1
- package/types/index.d.ts +16 -11
- package/types/index.d.ts.map +1 -1
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
/** @import { AST } from '#compiler' */
|
|
2
2
|
/** @import { ComponentContext } from '../types' */
|
|
3
3
|
import { build_component } from './shared/component.js';
|
|
4
|
+
import * as b from '#compiler/builders';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* @param {AST.SvelteComponent} node
|
|
7
8
|
* @param {ComponentContext} context
|
|
8
9
|
*/
|
|
9
10
|
export function SvelteComponent(node, context) {
|
|
10
|
-
const component = build_component(node, '$$component', context);
|
|
11
|
+
const component = build_component(node, '$$component', null, context);
|
|
11
12
|
context.state.init.push(component);
|
|
12
13
|
}
|
|
@@ -14,7 +14,7 @@ export function SvelteHead(node, context) {
|
|
|
14
14
|
context.state.init.push(
|
|
15
15
|
b.stmt(
|
|
16
16
|
b.call(
|
|
17
|
-
'$.head',
|
|
17
|
+
b.id('$.head', node.name_loc),
|
|
18
18
|
b.literal(hash(filename)),
|
|
19
19
|
b.arrow([b.id('$$anchor')], /** @type {BlockStatement} */ (context.visit(node.fragment)))
|
|
20
20
|
)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/** @import { AST } from '#compiler' */
|
|
2
2
|
/** @import { ComponentContext } from '../types' */
|
|
3
|
+
import { component_name } from '../../../../state.js';
|
|
3
4
|
import { build_component } from './shared/component.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
@@ -7,6 +8,6 @@ import { build_component } from './shared/component.js';
|
|
|
7
8
|
* @param {ComponentContext} context
|
|
8
9
|
*/
|
|
9
10
|
export function SvelteSelf(node, context) {
|
|
10
|
-
const component = build_component(node,
|
|
11
|
+
const component = build_component(node, component_name, node.name_loc, context);
|
|
11
12
|
context.state.init.push(component);
|
|
12
13
|
}
|
|
@@ -20,7 +20,7 @@ export function TitleElement(node, context) {
|
|
|
20
20
|
const statement = b.stmt(
|
|
21
21
|
b.assignment(
|
|
22
22
|
'=',
|
|
23
|
-
b.id('$.document.title'),
|
|
23
|
+
b.member(b.id('$.document'), b.id('title', node.name_loc)),
|
|
24
24
|
evaluated.is_known
|
|
25
25
|
? b.literal(evaluated.value)
|
|
26
26
|
: evaluated.is_defined
|
|
@@ -136,7 +136,8 @@ export function VariableDeclaration(node, context) {
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
if (is_state) {
|
|
139
|
-
|
|
139
|
+
const callee = b.id('$.state', /** @type {CallExpression} */ (init).callee.loc);
|
|
140
|
+
value = b.call(callee, value);
|
|
140
141
|
|
|
141
142
|
if (dev) {
|
|
142
143
|
value = b.call('$.tag', value, b.literal(id.name));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, Statement } from 'estree' */
|
|
1
|
+
/** @import { BlockStatement, Expression, ExpressionStatement, Identifier, MemberExpression, Pattern, Property, SequenceExpression, SourceLocation, Statement } from 'estree' */
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
3
|
/** @import { ComponentContext } from '../../types.js' */
|
|
4
4
|
import { dev, is_ignored } from '../../../../../state.js';
|
|
@@ -12,10 +12,11 @@ import { determine_slot } from '../../../../../utils/slot.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* @param {AST.Component | AST.SvelteComponent | AST.SvelteSelf} node
|
|
14
14
|
* @param {string} component_name
|
|
15
|
+
* @param {SourceLocation | null} loc
|
|
15
16
|
* @param {ComponentContext} context
|
|
16
17
|
* @returns {Statement}
|
|
17
18
|
*/
|
|
18
|
-
export function build_component(node, component_name, context) {
|
|
19
|
+
export function build_component(node, component_name, loc, context) {
|
|
19
20
|
/** @type {Expression} */
|
|
20
21
|
const anchor = context.state.node;
|
|
21
22
|
|
|
@@ -259,15 +260,9 @@ export function build_component(node, component_name, context) {
|
|
|
259
260
|
attribute.expression.type === 'Identifier' &&
|
|
260
261
|
context.state.scope.get(attribute.expression.name)?.kind === 'store_sub';
|
|
261
262
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)]),
|
|
266
|
-
true
|
|
267
|
-
);
|
|
268
|
-
} else {
|
|
269
|
-
push_prop(b.get(attribute.name, [b.return(expression)]), true);
|
|
270
|
-
}
|
|
263
|
+
const get = is_store_sub
|
|
264
|
+
? b.get(attribute.name, [b.stmt(b.call('$.mark_store_binding')), b.return(expression)])
|
|
265
|
+
: b.get(attribute.name, [b.return(expression)]);
|
|
271
266
|
|
|
272
267
|
const assignment = b.assignment(
|
|
273
268
|
'=',
|
|
@@ -275,10 +270,16 @@ export function build_component(node, component_name, context) {
|
|
|
275
270
|
b.id('$$value')
|
|
276
271
|
);
|
|
277
272
|
|
|
278
|
-
|
|
279
|
-
b.
|
|
280
|
-
|
|
281
|
-
|
|
273
|
+
const set = b.set(attribute.name, [
|
|
274
|
+
b.stmt(/** @type {Expression} */ (context.visit(assignment)))
|
|
275
|
+
]);
|
|
276
|
+
|
|
277
|
+
get.key.loc = attribute.name_loc;
|
|
278
|
+
set.key.loc = attribute.name_loc;
|
|
279
|
+
|
|
280
|
+
// Delay prop pushes so bindings come at the end, to avoid spreads overwriting them
|
|
281
|
+
push_prop(get, true);
|
|
282
|
+
push_prop(set, true);
|
|
282
283
|
}
|
|
283
284
|
}
|
|
284
285
|
} else if (attribute.type === 'AttachTag') {
|
|
@@ -434,16 +435,17 @@ export function build_component(node, component_name, context) {
|
|
|
434
435
|
|
|
435
436
|
/** @param {Expression} node_id */
|
|
436
437
|
let fn = (node_id) => {
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
438
|
+
// TODO We can remove this ternary once we remove legacy mode, since in runes mode dynamic components
|
|
439
|
+
// will be handled separately through the `$.component` function, and then the component name will
|
|
440
|
+
// always be referenced through just the identifier here.
|
|
441
|
+
const callee = is_component_dynamic
|
|
442
|
+
? b.id(intermediate_name)
|
|
443
|
+
: /** @type {Expression} */ (context.visit(b.member_id(component_name)));
|
|
444
|
+
|
|
445
|
+
// line up the `Foo` in `Foo(...)` and `<Foo>` for usable stack traces
|
|
446
|
+
callee.loc = loc;
|
|
447
|
+
|
|
448
|
+
return b.call(callee, node_id, props_expression);
|
|
447
449
|
};
|
|
448
450
|
|
|
449
451
|
if (bind_this !== null) {
|
|
@@ -32,7 +32,13 @@ export function visit_event_attribute(node, context) {
|
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
context.state.init.push(
|
|
35
|
-
b.stmt(
|
|
35
|
+
b.stmt(
|
|
36
|
+
b.assignment(
|
|
37
|
+
'=',
|
|
38
|
+
b.member(context.state.node, b.id('__' + event_name, node.name_loc)),
|
|
39
|
+
handler
|
|
40
|
+
)
|
|
41
|
+
)
|
|
36
42
|
);
|
|
37
43
|
} else {
|
|
38
44
|
const statement = b.stmt(
|
|
@@ -140,7 +146,7 @@ export function build_event_handler(node, metadata, context) {
|
|
|
140
146
|
b.this,
|
|
141
147
|
b.id('$$args'),
|
|
142
148
|
b.id(context.state.analysis.name),
|
|
143
|
-
|
|
149
|
+
b.array([b.literal(loc.line), b.literal(loc.column)]),
|
|
144
150
|
has_side_effects(node) && b.true,
|
|
145
151
|
remove_parens && b.true
|
|
146
152
|
);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Expression } from 'estree' */
|
|
1
|
+
/** @import { Expression, Identifier, SourceLocation } from 'estree' */
|
|
2
2
|
/** @import { AST } from '#compiler' */
|
|
3
3
|
/** @import { ComponentContext } from '../../types' */
|
|
4
4
|
import { cannot_be_set_statically } from '../../../../../../utils.js';
|
|
@@ -42,13 +42,14 @@ export function process_children(nodes, initial, is_element, context) {
|
|
|
42
42
|
/**
|
|
43
43
|
* @param {boolean} is_text
|
|
44
44
|
* @param {string} name
|
|
45
|
+
* @param {SourceLocation | null} [loc]
|
|
45
46
|
*/
|
|
46
|
-
function flush_node(is_text, name) {
|
|
47
|
+
function flush_node(is_text, name, loc) {
|
|
47
48
|
const expression = get_node(is_text);
|
|
48
49
|
let id = expression;
|
|
49
50
|
|
|
50
51
|
if (id.type !== 'Identifier') {
|
|
51
|
-
id = b.id(context.state.scope.generate(name));
|
|
52
|
+
id = b.id(context.state.scope.generate(name), loc);
|
|
52
53
|
context.state.init.push(b.var(id, expression));
|
|
53
54
|
}
|
|
54
55
|
|
|
@@ -109,7 +110,12 @@ export function process_children(nodes, initial, is_element, context) {
|
|
|
109
110
|
) {
|
|
110
111
|
node.metadata.is_controlled = true;
|
|
111
112
|
} else {
|
|
112
|
-
const id = flush_node(
|
|
113
|
+
const id = flush_node(
|
|
114
|
+
false,
|
|
115
|
+
node.type === 'RegularElement' ? node.name : 'node',
|
|
116
|
+
node.type === 'RegularElement' ? node.name_loc : null
|
|
117
|
+
);
|
|
118
|
+
|
|
113
119
|
child_state = { ...context.state, node: id };
|
|
114
120
|
}
|
|
115
121
|
|
|
@@ -366,8 +366,8 @@ export function validate_binding(state, binding, expression) {
|
|
|
366
366
|
: b.literal(/** @type {Identifier} */ (expression.property).name)
|
|
367
367
|
)
|
|
368
368
|
),
|
|
369
|
-
|
|
370
|
-
|
|
369
|
+
b.literal(loc.line),
|
|
370
|
+
b.literal(loc.column)
|
|
371
371
|
)
|
|
372
372
|
)
|
|
373
373
|
);
|
|
@@ -50,7 +50,7 @@ export function SvelteElement(node, context) {
|
|
|
50
50
|
build_element_attributes(node, { ...context, state }, optimiser.transform);
|
|
51
51
|
|
|
52
52
|
if (dev) {
|
|
53
|
-
const location =
|
|
53
|
+
const location = locator(node.start);
|
|
54
54
|
statements.push(
|
|
55
55
|
b.stmt(
|
|
56
56
|
b.call(
|
|
@@ -142,7 +142,7 @@ export function build_element_attributes(node, context, transform) {
|
|
|
142
142
|
);
|
|
143
143
|
|
|
144
144
|
attributes.push(
|
|
145
|
-
create_attribute('checked', -1, -1, [
|
|
145
|
+
create_attribute('checked', null, -1, -1, [
|
|
146
146
|
{
|
|
147
147
|
type: 'ExpressionTag',
|
|
148
148
|
start: -1,
|
|
@@ -165,7 +165,7 @@ export function build_element_attributes(node, context, transform) {
|
|
|
165
165
|
);
|
|
166
166
|
} else {
|
|
167
167
|
attributes.push(
|
|
168
|
-
create_attribute(attribute.name, -1, -1, [
|
|
168
|
+
create_attribute(attribute.name, null, -1, -1, [
|
|
169
169
|
{
|
|
170
170
|
type: 'ExpressionTag',
|
|
171
171
|
start: -1,
|
|
@@ -54,7 +54,10 @@ export function transform_body(instance_body, runner, transform) {
|
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
const statements = visited.declarations.map((node) => {
|
|
57
|
-
if (
|
|
57
|
+
if (
|
|
58
|
+
node.id.type === 'Identifier' &&
|
|
59
|
+
(node.id.name.startsWith('$$d') || node.id.name.startsWith('$$array'))
|
|
60
|
+
) {
|
|
58
61
|
// this is an intermediate declaration created in VariableDeclaration.js;
|
|
59
62
|
// subsequent statements depend on it
|
|
60
63
|
return b.var(node.id, node.init);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/** @import { Expression, PrivateIdentifier } from 'estree' */
|
|
1
|
+
/** @import { Expression, PrivateIdentifier, SourceLocation } from 'estree' */
|
|
2
2
|
/** @import { AST, Binding } from '#compiler' */
|
|
3
3
|
import * as b from '#compiler/builders';
|
|
4
4
|
|
|
@@ -47,17 +47,19 @@ export function is_custom_element_node(node) {
|
|
|
47
47
|
|
|
48
48
|
/**
|
|
49
49
|
* @param {string} name
|
|
50
|
+
* @param {SourceLocation | null} name_loc
|
|
50
51
|
* @param {number} start
|
|
51
52
|
* @param {number} end
|
|
52
53
|
* @param {AST.Attribute['value']} value
|
|
53
54
|
* @returns {AST.Attribute}
|
|
54
55
|
*/
|
|
55
|
-
export function create_attribute(name, start, end, value) {
|
|
56
|
+
export function create_attribute(name, name_loc, start, end, value) {
|
|
56
57
|
return {
|
|
57
58
|
type: 'Attribute',
|
|
58
59
|
start,
|
|
59
60
|
end,
|
|
60
61
|
name,
|
|
62
|
+
name_loc,
|
|
61
63
|
value,
|
|
62
64
|
metadata: {
|
|
63
65
|
delegated: false,
|
package/src/compiler/state.js
CHANGED
|
@@ -40,19 +40,28 @@ export let dev;
|
|
|
40
40
|
|
|
41
41
|
export let runes = false;
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
/** @type {(index: number) => Location} */
|
|
44
|
+
export let locator;
|
|
44
45
|
|
|
45
46
|
/** @param {string} value */
|
|
46
47
|
export function set_source(value) {
|
|
47
48
|
source = value;
|
|
48
|
-
|
|
49
|
+
|
|
50
|
+
const l = getLocator(source, { offsetLine: 1 });
|
|
51
|
+
|
|
52
|
+
locator = (i) => {
|
|
53
|
+
const loc = l(i);
|
|
54
|
+
if (!loc) throw new Error('An impossible situation occurred');
|
|
55
|
+
|
|
56
|
+
return loc;
|
|
57
|
+
};
|
|
49
58
|
}
|
|
50
59
|
|
|
51
60
|
/**
|
|
52
61
|
* @param {AST.SvelteNode & { start?: number | undefined }} node
|
|
53
62
|
*/
|
|
54
63
|
export function locate_node(node) {
|
|
55
|
-
const loc =
|
|
64
|
+
const loc = locator(/** @type {number} */ (node.start));
|
|
56
65
|
return `${sanitize_location(filename)}:${loc?.line}:${loc.column}`;
|
|
57
66
|
}
|
|
58
67
|
|
|
@@ -103,7 +112,6 @@ export function reset(state) {
|
|
|
103
112
|
runes = false;
|
|
104
113
|
component_name = UNKNOWN_FILENAME;
|
|
105
114
|
source = '';
|
|
106
|
-
locator = () => undefined;
|
|
107
115
|
filename = (state.filename ?? UNKNOWN_FILENAME).replace(/\\/g, '/');
|
|
108
116
|
warning_filter = state.warning ?? (() => true);
|
|
109
117
|
warnings = [];
|
|
@@ -262,10 +262,14 @@ export function get(name, body) {
|
|
|
262
262
|
|
|
263
263
|
/**
|
|
264
264
|
* @param {string} name
|
|
265
|
+
* @param {ESTree.SourceLocation | null} [loc]
|
|
265
266
|
* @returns {ESTree.Identifier}
|
|
266
267
|
*/
|
|
267
|
-
export function id(name) {
|
|
268
|
-
|
|
268
|
+
export function id(name, loc) {
|
|
269
|
+
const node = /** @type {ESTree.Identifier} */ ({ type: 'Identifier', name });
|
|
270
|
+
if (loc) node.loc = loc;
|
|
271
|
+
|
|
272
|
+
return node;
|
|
269
273
|
}
|
|
270
274
|
|
|
271
275
|
/**
|