Skip to content

Commit 2f8baac

Browse files
committed
Merge remote-tracking branch 'origin/main' into thunkify-deriveds-on-server
2 parents 961c36b + 0ace76d commit 2f8baac

File tree

52 files changed

+533
-161
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+533
-161
lines changed

.changeset/strong-coins-peel.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: improve error message for migration errors when slot would be renamed

.changeset/wild-bulldogs-move.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: allow characters in the supplementary special-purpose plane

documentation/docs/02-runes/07-$inspect.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ This rune, added in 5.14, causes the surrounding function to be _traced_ in deve
5252
import { doSomeWork } from './elsewhere';
5353
5454
$effect(() => {
55+
+++// $inspect.trace must be the first statement of a function body+++
5556
+++$inspect.trace();+++
5657
doSomeWork();
5758
});

documentation/docs/98-reference/.generated/compile-errors.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,12 @@ A `:global` selector cannot modify an existing selector
274274
A `:global` selector can only be modified if it is a descendant of other selectors
275275
```
276276

277+
### css_global_block_invalid_placement
278+
279+
```
280+
A `:global` selector cannot be inside a pseudoclass
281+
```
282+
277283
### css_global_invalid_placement
278284

279285
```

packages/svelte/CHANGELOG.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,33 @@
11
# svelte
22

3+
## 5.28.2
4+
5+
### Patch Changes
6+
7+
- fix: don't mark selector lists inside `:global` with multiple items as unused ([#15817](https://github.com/sveltejs/svelte/pull/15817))
8+
9+
## 5.28.1
10+
11+
### Patch Changes
12+
13+
- fix: ensure `<svelte:boundary>` properly removes error content in production mode ([#15793](https://github.com/sveltejs/svelte/pull/15793))
14+
15+
- fix: `update_version` after `delete` if `source` is `undefined` and `prop` in `target` ([#15796](https://github.com/sveltejs/svelte/pull/15796))
16+
17+
- fix: emit error on wrong placement of the `:global` block selector ([#15794](https://github.com/sveltejs/svelte/pull/15794))
18+
19+
## 5.28.0
20+
21+
### Minor Changes
22+
23+
- feat: partially evaluate more expressions ([#15781](https://github.com/sveltejs/svelte/pull/15781))
24+
25+
## 5.27.3
26+
27+
### Patch Changes
28+
29+
- fix: use function declaration for snippets in server output to avoid TDZ violation ([#15789](https://github.com/sveltejs/svelte/pull/15789))
30+
331
## 5.27.2
432

533
### Patch Changes

packages/svelte/messages/compile-errors/style.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ x y {
5050

5151
> A `:global` selector can only be modified if it is a descendant of other selectors
5252
53+
## css_global_block_invalid_placement
54+
55+
> A `:global` selector cannot be inside a pseudoclass
56+
5357
## css_global_invalid_placement
5458

5559
> `:global(...)` can be at the start or end of a selector sequence, but not in the middle

packages/svelte/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"name": "svelte",
33
"description": "Cybernetically enhanced web apps",
44
"license": "MIT",
5-
"version": "5.27.2",
5+
"version": "5.28.2",
66
"type": "module",
77
"types": "./types/index.d.ts",
88
"engines": {

packages/svelte/src/compiler/errors.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,15 @@ export function css_global_block_invalid_modifier_start(node) {
581581
e(node, 'css_global_block_invalid_modifier_start', `A \`:global\` selector can only be modified if it is a descendant of other selectors\nhttps://svelte.dev/e/css_global_block_invalid_modifier_start`);
582582
}
583583

584+
/**
585+
* A `:global` selector cannot be inside a pseudoclass
586+
* @param {null | number | NodeLike} node
587+
* @returns {never}
588+
*/
589+
export function css_global_block_invalid_placement(node) {
590+
e(node, 'css_global_block_invalid_placement', `A \`:global\` selector cannot be inside a pseudoclass\nhttps://svelte.dev/e/css_global_block_invalid_placement`);
591+
}
592+
584593
/**
585594
* `:global(...)` can be at the start or end of a selector sequence, but not in the middle
586595
* @param {null | number | NodeLike} node

packages/svelte/src/compiler/migrate/index.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,7 +1307,7 @@ const template = {
13071307
name = state.scope.generate(slot_name);
13081308
if (name !== slot_name) {
13091309
throw new MigrationError(
1310-
'This migration would change the name of a slot making the component unusable'
1310+
`This migration would change the name of a slot (${slot_name} to ${name}) making the component unusable`
13111311
);
13121312
}
13131313
}
@@ -1880,7 +1880,7 @@ function handle_identifier(node, state, path) {
18801880
let new_name = state.scope.generate(name);
18811881
if (new_name !== name) {
18821882
throw new MigrationError(
1883-
'This migration would change the name of a slot making the component unusable'
1883+
`This migration would change the name of a slot (${name} to ${new_name}) making the component unusable`
18841884
);
18851885
}
18861886
}

packages/svelte/src/compiler/phases/1-parse/utils/html.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ const NUL = 0;
7272
// to replace them ourselves
7373
//
7474
// Source: http://en.wikipedia.org/wiki/Character_encodings_in_HTML#Illegal_characters
75+
// Also see: https://en.wikipedia.org/wiki/Plane_(Unicode)
76+
// Also see: https://html.spec.whatwg.org/multipage/parsing.html#preprocessing-the-input-stream
7577

7678
/** @param {number} code */
7779
function validate_code(code) {
@@ -116,5 +118,10 @@ function validate_code(code) {
116118
return code;
117119
}
118120

121+
// supplementary special-purpose plane 0xe0000 - 0xe07f and 0xe0100 - 0xe01ef
122+
if ((code >= 917504 && code <= 917631) || (code >= 917760 && code <= 917999)) {
123+
return code;
124+
}
125+
119126
return NUL;
120127
}

packages/svelte/src/compiler/phases/2-analyze/css/css-analyze.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,12 @@ const css_visitors = {
6868
const global = node.children.find(is_global);
6969

7070
if (global) {
71-
const idx = node.children.indexOf(global);
71+
const is_nested = context.path.at(-2)?.type === 'PseudoClassSelector';
72+
if (is_nested && !global.selectors[0].args) {
73+
e.css_global_block_invalid_placement(global.selectors[0]);
74+
}
7275

76+
const idx = node.children.indexOf(global);
7377
if (global.selectors[0].args !== null && idx !== 0 && idx !== node.children.length - 1) {
7478
// ensure `:global(...)` is not used in the middle of a selector (but multiple `global(...)` in sequence are ok)
7579
for (let i = idx + 1; i < node.children.length; i++) {

packages/svelte/src/compiler/phases/3-transform/client/visitors/shared/utils.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,17 @@ export function build_template_chunk(
6969
node.metadata.expression
7070
);
7171

72-
has_state ||= node.metadata.expression.has_state;
72+
const evaluated = state.scope.evaluate(value);
73+
74+
has_state ||= node.metadata.expression.has_state && !evaluated.is_known;
7375

7476
if (values.length === 1) {
7577
// If we have a single expression, then pass that in directly to possibly avoid doing
7678
// extra work in the template_effect (instead we do the work in set_text).
79+
if (evaluated.is_known) {
80+
value = b.literal(evaluated.value);
81+
}
82+
7783
return { value, has_state };
7884
}
7985

@@ -89,8 +95,6 @@ export function build_template_chunk(
8995
}
9096
}
9197

92-
const evaluated = state.scope.evaluate(value);
93-
9498
if (evaluated.is_known) {
9599
quasi.value.cooked += evaluated.value + '';
96100
} else {

packages/svelte/src/compiler/phases/3-transform/css/index.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,12 @@ const visitors = {
196196
next();
197197
},
198198
SelectorList(node, { state, next, path }) {
199+
const parent = path.at(-1);
200+
199201
// Only add comments if we're not inside a complex selector that itself is unused or a global block
200202
if (
201-
(!is_in_global_block(path) || node.children.length > 1) &&
203+
(!is_in_global_block(path) ||
204+
(node.children.length > 1 && parent?.type === 'Rule' && parent.metadata.is_global_block)) &&
202205
!path.find((n) => n.type === 'ComplexSelector' && !n.metadata.used)
203206
) {
204207
const children = node.children;
@@ -260,7 +263,6 @@ const visitors = {
260263

261264
// if this selector list belongs to a rule, require a specificity bump for the
262265
// first scoped selector but only if we're at the top level
263-
let parent = path.at(-1);
264266
if (parent?.type === 'Rule') {
265267
specificity = { bumped: false };
266268

@@ -376,7 +378,6 @@ const visitors = {
376378
};
377379

378380
/**
379-
*
380381
* @param {Array<AST.CSS.Node>} path
381382
*/
382383
function is_in_global_block(path) {
Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/** @import { ArrowFunctionExpression, BlockStatement, CallExpression } from 'estree' */
1+
/** @import { BlockStatement } from 'estree' */
22
/** @import { AST } from '#compiler' */
33
/** @import { ComponentContext } from '../types.js' */
44
import { dev } from '../../../../state.js';
@@ -9,27 +9,21 @@ import * as b from '#compiler/builders';
99
* @param {ComponentContext} context
1010
*/
1111
export function SnippetBlock(node, context) {
12-
const body = /** @type {BlockStatement} */ (context.visit(node.body));
12+
let fn = b.function_declaration(
13+
node.expression,
14+
[b.id('$$payload'), ...node.parameters],
15+
/** @type {BlockStatement} */ (context.visit(node.body))
16+
);
1317

14-
if (dev) {
15-
body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload'))));
16-
}
18+
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone
19+
fn.___snippet = true;
1720

18-
/** @type {ArrowFunctionExpression | CallExpression} */
19-
let fn = b.arrow([b.id('$$payload'), ...node.parameters], body);
21+
const statements = node.metadata.can_hoist ? context.state.hoisted : context.state.init;
2022

2123
if (dev) {
22-
fn = b.call('$.prevent_snippet_stringification', fn);
24+
fn.body.body.unshift(b.stmt(b.call('$.validate_snippet_args', b.id('$$payload'))));
25+
statements.push(b.stmt(b.call('$.prevent_snippet_stringification', fn.id)));
2326
}
2427

25-
const declaration = b.declaration('const', [b.declarator(node.expression, fn)]);
26-
27-
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone
28-
fn.___snippet = true;
29-
30-
if (node.metadata.can_hoist) {
31-
context.state.hoisted.push(declaration);
32-
} else {
33-
context.state.init.push(declaration);
34-
}
28+
statements.push(fn);
3529
}

0 commit comments

Comments
 (0)