fix: never deduplicate expressions in templates (#15451)

pull/15452/head
Rich Harris 7 months ago committed by GitHub
parent 0abd7f2a7f
commit 76f5ecfdab
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: never deduplicate expressions in templates

@ -26,55 +26,9 @@ export function memoize_expression(state, value) {
* @param {Expression} value
*/
export function get_expression_id(state, value) {
for (let i = 0; i < state.expressions.length; i += 1) {
if (compare_expressions(state.expressions[i], value)) {
return b.id(`$${i}`);
}
}
return b.id(`$${state.expressions.push(value) - 1}`);
}
/**
* Returns true of two expressions have an identical AST shape
* @param {Expression} a
* @param {Expression} b
*/
function compare_expressions(a, b) {
if (a.type !== b.type) {
return false;
}
for (const key in a) {
if (key === 'type' || key === 'metadata' || key === 'loc' || key === 'start' || key === 'end') {
continue;
}
const va = /** @type {any} */ (a)[key];
const vb = /** @type {any} */ (b)[key];
if ((typeof va === 'object') !== (typeof vb === 'object')) {
return false;
}
if (typeof va !== 'object' || va === null || vb === null) {
if (va !== vb) return false;
} else if (Array.isArray(va)) {
if (va.length !== vb.length) {
return false;
}
if (va.some((v, i) => !compare_expressions(v, vb[i]))) {
return false;
}
} else if (!compare_expressions(va, vb)) {
return false;
}
}
return true;
}
/**
* @param {Array<AST.Text | AST.ExpressionTag>} values
* @param {(node: AST.SvelteNode, state: any) => any} visit

@ -0,0 +1,8 @@
import { test } from '../../test';
export default test({
test({ assert, target }) {
const [p1, p2] = target.querySelectorAll('p');
assert.notEqual(p1.textContent, p2.textContent);
}
});

@ -0,0 +1,6 @@
<script>
let { m = 1 } = $props();
</script>
<p>{(Math.random() * m).toFixed(10)}</p>
<p>{(Math.random() * m).toFixed(10)}</p>

@ -21,13 +21,13 @@ export default function Main($$anchor) {
$.template_effect(() => $.set_custom_element_data(custom_element_1, 'fooBar', y()));
$.template_effect(
($0) => {
($0, $1) => {
$.set_attribute(div, 'foobar', x);
$.set_attribute(svg, 'viewBox', x);
$.set_attribute(div_1, 'foobar', $0);
$.set_attribute(svg_1, 'viewBox', $0);
$.set_attribute(svg_1, 'viewBox', $1);
},
[y]
[y, y]
);
$.append($$anchor, fragment);

Loading…
Cancel
Save