Skip to content

Commit 76f5ecf

Browse files
authored
fix: never deduplicate expressions in templates (#15451)
1 parent 0abd7f2 commit 76f5ecf

File tree

5 files changed

+22
-49
lines changed

5 files changed

+22
-49
lines changed

.changeset/five-wolves-swim.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'svelte': patch
3+
---
4+
5+
fix: never deduplicate expressions in templates

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

-46
Original file line numberDiff line numberDiff line change
@@ -26,55 +26,9 @@ export function memoize_expression(state, value) {
2626
* @param {Expression} value
2727
*/
2828
export function get_expression_id(state, value) {
29-
for (let i = 0; i < state.expressions.length; i += 1) {
30-
if (compare_expressions(state.expressions[i], value)) {
31-
return b.id(`$${i}`);
32-
}
33-
}
34-
3529
return b.id(`$${state.expressions.push(value) - 1}`);
3630
}
3731

38-
/**
39-
* Returns true of two expressions have an identical AST shape
40-
* @param {Expression} a
41-
* @param {Expression} b
42-
*/
43-
function compare_expressions(a, b) {
44-
if (a.type !== b.type) {
45-
return false;
46-
}
47-
48-
for (const key in a) {
49-
if (key === 'type' || key === 'metadata' || key === 'loc' || key === 'start' || key === 'end') {
50-
continue;
51-
}
52-
53-
const va = /** @type {any} */ (a)[key];
54-
const vb = /** @type {any} */ (b)[key];
55-
56-
if ((typeof va === 'object') !== (typeof vb === 'object')) {
57-
return false;
58-
}
59-
60-
if (typeof va !== 'object' || va === null || vb === null) {
61-
if (va !== vb) return false;
62-
} else if (Array.isArray(va)) {
63-
if (va.length !== vb.length) {
64-
return false;
65-
}
66-
67-
if (va.some((v, i) => !compare_expressions(v, vb[i]))) {
68-
return false;
69-
}
70-
} else if (!compare_expressions(va, vb)) {
71-
return false;
72-
}
73-
}
74-
75-
return true;
76-
}
77-
7832
/**
7933
* @param {Array<AST.Text | AST.ExpressionTag>} values
8034
* @param {(node: AST.SvelteNode, state: any) => any} visit
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { test } from '../../test';
2+
3+
export default test({
4+
test({ assert, target }) {
5+
const [p1, p2] = target.querySelectorAll('p');
6+
assert.notEqual(p1.textContent, p2.textContent);
7+
}
8+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<script>
2+
let { m = 1 } = $props();
3+
</script>
4+
5+
<p>{(Math.random() * m).toFixed(10)}</p>
6+
<p>{(Math.random() * m).toFixed(10)}</p>

packages/svelte/tests/snapshot/samples/dynamic-attributes-casing/_expected/client/main.svelte.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ export default function Main($$anchor) {
2121
$.template_effect(() => $.set_custom_element_data(custom_element_1, 'fooBar', y()));
2222

2323
$.template_effect(
24-
($0) => {
24+
($0, $1) => {
2525
$.set_attribute(div, 'foobar', x);
2626
$.set_attribute(svg, 'viewBox', x);
2727
$.set_attribute(div_1, 'foobar', $0);
28-
$.set_attribute(svg_1, 'viewBox', $0);
28+
$.set_attribute(svg_1, 'viewBox', $1);
2929
},
30-
[y]
30+
[y, y]
3131
);
3232

3333
$.append($$anchor, fragment);

0 commit comments

Comments
 (0)