fix: improve template text node serialization (#9722)

fix: improve template text node serialization
pull/9707/head
Dominic Gannaway 1 year ago committed by GitHub
parent 7eba35b9d1
commit 2fa06447cf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: improve template text node serialization

@ -1382,13 +1382,17 @@ function process_children(nodes, parent, { visit, state }) {
/** /**
* @param {Sequence} sequence * @param {Sequence} sequence
* @param {boolean} in_fragment
*/ */
function flush_sequence(sequence) { function flush_sequence(sequence, in_fragment) {
if (sequence.length === 1) { if (sequence.length === 1) {
const node = sequence[0]; const node = sequence[0];
if (node.type === 'Text') { if ((in_fragment && node.type === 'ExpressionTag') || node.type === 'Text') {
expression = b.call('$.sibling', expression); expression = b.call('$.sibling', expression);
}
if (node.type === 'Text') {
state.template.push(node.raw); state.template.push(node.raw);
return; return;
} }
@ -1475,7 +1479,7 @@ function process_children(nodes, parent, { visit, state }) {
sequence.push(node); sequence.push(node);
} else { } else {
if (sequence.length > 0) { if (sequence.length > 0) {
flush_sequence(sequence); flush_sequence(sequence, true);
sequence = []; sequence = [];
} }
@ -1519,7 +1523,7 @@ function process_children(nodes, parent, { visit, state }) {
} }
if (sequence.length > 0) { if (sequence.length > 0) {
flush_sequence(sequence); flush_sequence(sequence, false);
} }
} }

@ -173,7 +173,7 @@ function process_children(nodes, parent, { visit, state }) {
} }
const expression = b.call( const expression = b.call(
'$.escape', '$.escape_text',
/** @type {import('estree').Expression} */ (visit(node.expression)) /** @type {import('estree').Expression} */ (visit(node.expression))
); );
state.template.push(t_expression(expression)); state.template.push(t_expression(expression));

@ -150,6 +150,17 @@ export function escape(value, is_attr = false) {
return escaped + str.substring(last); return escaped + str.substring(last);
} }
/**
* @template V
* @param {V} value
* @returns {string}
*/
export function escape_text(value) {
const escaped = escape(value);
// If the value is empty, then ensure we put a space so that it creates a text node on the client
return escaped === '' ? ' ' : escaped;
}
/** /**
* @param {Payload} payload * @param {Payload} payload
* @param {(head_payload: Payload['head']) => void} fn * @param {(head_payload: Payload['head']) => void} fn

@ -0,0 +1,15 @@
import { flushSync } from 'svelte';
import { test } from '../../test';
export default test({
async test({ assert, target, component }) {
const [b1] = target.querySelectorAll('button');
flushSync(() => {
b1?.click();
});
await Promise.resolve();
assert.deepEqual(component.log, ['onclick']);
}
});

@ -0,0 +1,10 @@
<script>
const {log = []} = $props();
function send() {
log.push("onclick")
}
</script>
{undefined}<hr/>
<button onclick={send}>Send Event</button>
Loading…
Cancel
Save