Skip to content

Commit 203c321

Browse files
committed
Merge branch 'main' into print
2 parents e47f579 + c4b32c2 commit 203c321

File tree

88 files changed

+844
-177
lines changed

Some content is hidden

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

88 files changed

+844
-177
lines changed

.changeset/beige-plants-laugh.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

.changeset/clever-dodos-jam.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: untrack `$inspect.with` and add check for unsafe mutation

documentation/docs/07-misc/02-testing.md

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -129,12 +129,12 @@ test('Effect', () => {
129129
// effects normally run after a microtask,
130130
// use flushSync to execute all pending effects synchronously
131131
flushSync();
132-
expect(log.value).toEqual([0]);
132+
expect(log).toEqual([0]);
133133

134134
count = 1;
135135
flushSync();
136136

137-
expect(log.value).toEqual([0, 1]);
137+
expect(log).toEqual([0, 1]);
138138
});
139139

140140
cleanup();
@@ -148,17 +148,13 @@ test('Effect', () => {
148148
*/
149149
export function logger(getValue) {
150150
/** @type {any[]} */
151-
let log = $state([]);
151+
let log = [];
152152

153153
$effect(() => {
154154
log.push(getValue());
155155
});
156156

157-
return {
158-
get value() {
159-
return log;
160-
}
161-
};
157+
return log;
162158
}
163159
```
164160

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ Cannot set prototype of `$state` object
125125
### state_unsafe_mutation
126126

127127
```
128-
Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
128+
Updating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
129129
```
130130

131131
This error occurs when state is updated while evaluating a `$derived`. You might encounter it while trying to 'derive' two pieces of state in one go:

packages/svelte/CHANGELOG.md

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

3+
## 5.34.7
4+
5+
### Patch Changes
6+
7+
- fix: address css class matching regression ([#16204](https://github.com/sveltejs/svelte/pull/16204))
8+
9+
## 5.34.6
10+
11+
### Patch Changes
12+
13+
- fix: match class and style directives against attribute selector ([#16179](https://github.com/sveltejs/svelte/pull/16179))
14+
15+
## 5.34.5
16+
17+
### Patch Changes
18+
19+
- fix: keep spread non-delegated event handlers up to date ([#16180](https://github.com/sveltejs/svelte/pull/16180))
20+
21+
- fix: remove undefined attributes on hydration ([#16178](https://github.com/sveltejs/svelte/pull/16178))
22+
23+
- fix: ensure sources within nested effects still register correctly ([#16193](https://github.com/sveltejs/svelte/pull/16193))
24+
25+
- fix: avoid shadowing a variable in dynamic components ([#16185](https://github.com/sveltejs/svelte/pull/16185))
26+
27+
## 5.34.4
28+
29+
### Patch Changes
30+
31+
- fix: don't set state withing `with_parent` in proxy ([#16176](https://github.com/sveltejs/svelte/pull/16176))
32+
33+
- fix: use compiler-driven reactivity in legacy mode template expressions ([#16100](https://github.com/sveltejs/svelte/pull/16100))
34+
335
## 5.34.3
436

537
### Patch Changes

packages/svelte/messages/client-errors/errors.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ See the [migration guide](/docs/svelte/v5-migration-guide#Components-are-no-long
8282
8383
## state_unsafe_mutation
8484

85-
> Updating state inside a derived or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
85+
> Updating state inside `$derived(...)`, `$inspect(...)` or a template expression is forbidden. If the value should not be reactive, declare it without `$state`
8686
8787
This error occurs when state is updated while evaluating a `$derived`. You might encounter it while trying to 'derive' two pieces of state in one go:
8888

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.34.3",
5+
"version": "5.34.7",
66
"type": "module",
77
"types": "./types/index.d.ts",
88
"engines": {

packages/svelte/src/compiler/phases/1-parse/state/tag.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,10 @@ function open(parser) {
6363
end: -1,
6464
test: read_expression(parser),
6565
consequent: create_fragment(),
66-
alternate: null
66+
alternate: null,
67+
metadata: {
68+
expression: create_expression_metadata()
69+
}
6770
});
6871

6972
parser.allow_whitespace();
@@ -244,7 +247,10 @@ function open(parser) {
244247
error: null,
245248
pending: null,
246249
then: null,
247-
catch: null
250+
catch: null,
251+
metadata: {
252+
expression: create_expression_metadata()
253+
}
248254
});
249255

250256
if (parser.eat('then')) {
@@ -326,7 +332,10 @@ function open(parser) {
326332
start,
327333
end: -1,
328334
expression,
329-
fragment: create_fragment()
335+
fragment: create_fragment(),
336+
metadata: {
337+
expression: create_expression_metadata()
338+
}
330339
});
331340

332341
parser.stack.push(block);
@@ -466,7 +475,10 @@ function next(parser) {
466475
elseif: true,
467476
test: expression,
468477
consequent: create_fragment(),
469-
alternate: null
478+
alternate: null,
479+
metadata: {
480+
expression: create_expression_metadata()
481+
}
470482
});
471483

472484
parser.stack.push(child);
@@ -629,7 +641,10 @@ function special(parser) {
629641
type: 'HtmlTag',
630642
start,
631643
end: parser.index,
632-
expression
644+
expression,
645+
metadata: {
646+
expression: create_expression_metadata()
647+
}
633648
});
634649

635650
return;
@@ -704,6 +719,9 @@ function special(parser) {
704719
declarations: [{ type: 'VariableDeclarator', id, init, start: id.start, end: init.end }],
705720
start: start + 2, // start at const, not at @const
706721
end: parser.index - 1
722+
},
723+
metadata: {
724+
expression: create_expression_metadata()
707725
}
708726
});
709727
}
@@ -730,6 +748,7 @@ function special(parser) {
730748
end: parser.index,
731749
expression: /** @type {AST.RenderTag['expression']} */ (expression),
732750
metadata: {
751+
expression: create_expression_metadata(),
733752
dynamic: false,
734753
arguments: [],
735754
path: [],

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

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -532,12 +532,7 @@ function relative_selector_might_apply_to_node(relative_selector, rule, element,
532532
}
533533

534534
case 'ClassSelector': {
535-
if (
536-
!attribute_matches(element, 'class', name, '~=', false) &&
537-
!element.attributes.some(
538-
(attribute) => attribute.type === 'ClassDirective' && attribute.name === name
539-
)
540-
) {
535+
if (!attribute_matches(element, 'class', name, '~=', false)) {
541536
return false;
542537
}
543538

@@ -633,14 +628,33 @@ function attribute_matches(node, name, expected_value, operator, case_insensitiv
633628
if (attribute.type === 'SpreadAttribute') return true;
634629
if (attribute.type === 'BindDirective' && attribute.name === name) return true;
635630

631+
const name_lower = name.toLowerCase();
632+
// match attributes against the corresponding directive but bail out on exact matching
633+
if (attribute.type === 'StyleDirective' && name_lower === 'style') return true;
634+
if (attribute.type === 'ClassDirective' && name_lower === 'class') {
635+
if (operator === '~=') {
636+
if (attribute.name === expected_value) return true;
637+
} else {
638+
return true;
639+
}
640+
}
641+
636642
if (attribute.type !== 'Attribute') continue;
637-
if (attribute.name.toLowerCase() !== name.toLowerCase()) continue;
643+
if (attribute.name.toLowerCase() !== name_lower) continue;
638644

639645
if (attribute.value === true) return operator === null;
640646
if (expected_value === null) return true;
641647

642648
if (is_text_attribute(attribute)) {
643-
return test_attribute(operator, expected_value, case_insensitive, attribute.value[0].data);
649+
const matches = test_attribute(
650+
operator,
651+
expected_value,
652+
case_insensitive,
653+
attribute.value[0].data
654+
);
655+
// continue if we still may match against a class/style directive
656+
if (!matches && (name_lower === 'class' || name_lower === 'style')) continue;
657+
return matches;
644658
}
645659

646660
const chunks = get_attribute_chunks(attribute.value);
@@ -649,7 +663,7 @@ function attribute_matches(node, name, expected_value, operator, case_insensitiv
649663
/** @type {string[]} */
650664
let prev_values = [];
651665
for (const chunk of chunks) {
652-
const current_possible_values = get_possible_values(chunk, name === 'class');
666+
const current_possible_values = get_possible_values(chunk, name_lower === 'class');
653667

654668
// impossible to find out all combinations
655669
if (!current_possible_values) return true;

packages/svelte/src/compiler/phases/2-analyze/visitors/AssignmentExpression.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,9 @@ export function AssignmentExpression(node, context) {
2323
}
2424
}
2525

26+
if (context.state.expression) {
27+
context.state.expression.has_assignment = true;
28+
}
29+
2630
context.next();
2731
}

0 commit comments

Comments
 (0)