Skip to content

Commit 2fa0644

Browse files
authored
fix: improve template text node serialization (#9722)
fix: improve template text node serialization
1 parent 7eba35b commit 2fa0644

File tree

6 files changed

+50
-5
lines changed

6 files changed

+50
-5
lines changed

.changeset/swift-ravens-hunt.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 template text node serialization

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1382,13 +1382,17 @@ function process_children(nodes, parent, { visit, state }) {
13821382

13831383
/**
13841384
* @param {Sequence} sequence
1385+
* @param {boolean} in_fragment
13851386
*/
1386-
function flush_sequence(sequence) {
1387+
function flush_sequence(sequence, in_fragment) {
13871388
if (sequence.length === 1) {
13881389
const node = sequence[0];
13891390

1390-
if (node.type === 'Text') {
1391+
if ((in_fragment && node.type === 'ExpressionTag') || node.type === 'Text') {
13911392
expression = b.call('$.sibling', expression);
1393+
}
1394+
1395+
if (node.type === 'Text') {
13921396
state.template.push(node.raw);
13931397
return;
13941398
}
@@ -1475,7 +1479,7 @@ function process_children(nodes, parent, { visit, state }) {
14751479
sequence.push(node);
14761480
} else {
14771481
if (sequence.length > 0) {
1478-
flush_sequence(sequence);
1482+
flush_sequence(sequence, true);
14791483
sequence = [];
14801484
}
14811485

@@ -1519,7 +1523,7 @@ function process_children(nodes, parent, { visit, state }) {
15191523
}
15201524

15211525
if (sequence.length > 0) {
1522-
flush_sequence(sequence);
1526+
flush_sequence(sequence, false);
15231527
}
15241528
}
15251529

packages/svelte/src/compiler/phases/3-transform/server/transform-server.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ function process_children(nodes, parent, { visit, state }) {
173173
}
174174

175175
const expression = b.call(
176-
'$.escape',
176+
'$.escape_text',
177177
/** @type {import('estree').Expression} */ (visit(node.expression))
178178
);
179179
state.template.push(t_expression(expression));

packages/svelte/src/internal/server/index.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,17 @@ export function escape(value, is_attr = false) {
150150
return escaped + str.substring(last);
151151
}
152152

153+
/**
154+
* @template V
155+
* @param {V} value
156+
* @returns {string}
157+
*/
158+
export function escape_text(value) {
159+
const escaped = escape(value);
160+
// If the value is empty, then ensure we put a space so that it creates a text node on the client
161+
return escaped === '' ? ' ' : escaped;
162+
}
163+
153164
/**
154165
* @param {Payload} payload
155166
* @param {(head_payload: Payload['head']) => void} fn
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import { flushSync } from 'svelte';
2+
import { test } from '../../test';
3+
4+
export default test({
5+
async test({ assert, target, component }) {
6+
const [b1] = target.querySelectorAll('button');
7+
8+
flushSync(() => {
9+
b1?.click();
10+
});
11+
12+
await Promise.resolve();
13+
assert.deepEqual(component.log, ['onclick']);
14+
}
15+
});
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<script>
2+
const {log = []} = $props();
3+
4+
function send() {
5+
log.push("onclick")
6+
}
7+
</script>
8+
9+
{undefined}<hr/>
10+
<button onclick={send}>Send Event</button>

0 commit comments

Comments
 (0)