Skip to content

Commit f5db130

Browse files
chore: Switch payload.out to an array (#16428)
* chore: Switch `payload.out` to an array * Apply suggestions from code review * changeset
1 parent c2da1eb commit f5db130

File tree

23 files changed

+103
-73
lines changed

23 files changed

+103
-73
lines changed

.changeset/old-dots-sin.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+
chore: Switch `payload.out` to an array

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ export function EachBlock(node, context) {
4444
);
4545

4646
if (node.fallback) {
47-
const open = b.stmt(b.assignment('+=', b.id('$$payload.out'), block_open));
47+
const open = b.stmt(b.call(b.member(b.id('$$payload.out'), b.id('push')), block_open));
4848

4949
const fallback = /** @type {BlockStatement} */ (context.visit(node.fallback));
5050

5151
fallback.body.unshift(
52-
b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(BLOCK_OPEN_ELSE)))
52+
b.stmt(b.call(b.member(b.id('$$payload.out'), b.id('push')), b.literal(BLOCK_OPEN_ELSE)))
5353
);
5454

5555
state.template.push(

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ export function IfBlock(node, context) {
1717
? /** @type {BlockStatement} */ (context.visit(node.alternate))
1818
: b.block([]);
1919

20-
consequent.body.unshift(b.stmt(b.assignment('+=', b.id('$$payload.out'), block_open)));
20+
consequent.body.unshift(
21+
b.stmt(b.call(b.member(b.id('$$payload.out'), b.id('push')), block_open))
22+
);
2123

2224
alternate.body.unshift(
23-
b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(BLOCK_OPEN_ELSE)))
25+
b.stmt(b.call(b.member(b.id('$$payload.out'), b.id('push')), b.literal(BLOCK_OPEN_ELSE)))
2426
);
2527

2628
context.state.template.push(b.if(test, consequent, alternate), block_close);

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

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -96,10 +96,10 @@ function is_statement(node) {
9696
/**
9797
* @param {Array<Statement | Expression>} template
9898
* @param {Identifier} out
99-
* @param {AssignmentOperator} operator
99+
* @param {AssignmentOperator | 'push'} operator
100100
* @returns {Statement[]}
101101
*/
102-
export function build_template(template, out = b.id('$$payload.out'), operator = '+=') {
102+
export function build_template(template, out = b.id('$$payload.out'), operator = 'push') {
103103
/** @type {string[]} */
104104
let strings = [];
105105

@@ -110,18 +110,32 @@ export function build_template(template, out = b.id('$$payload.out'), operator =
110110
const statements = [];
111111

112112
const flush = () => {
113-
statements.push(
114-
b.stmt(
115-
b.assignment(
116-
operator,
117-
out,
118-
b.template(
119-
strings.map((cooked, i) => b.quasi(cooked, i === strings.length - 1)),
120-
expressions
113+
if (operator === 'push') {
114+
statements.push(
115+
b.stmt(
116+
b.call(
117+
b.member(out, b.id('push')),
118+
b.template(
119+
strings.map((cooked, i) => b.quasi(cooked, i === strings.length - 1)),
120+
expressions
121+
)
121122
)
122123
)
123-
)
124-
);
124+
);
125+
} else {
126+
statements.push(
127+
b.stmt(
128+
b.assignment(
129+
operator,
130+
out,
131+
b.template(
132+
strings.map((cooked, i) => b.quasi(cooked, i === strings.length - 1)),
133+
expressions
134+
)
135+
)
136+
)
137+
);
138+
}
125139
strings = [];
126140
expressions = [];
127141
};

packages/svelte/src/internal/server/blocks/snippet.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ export function createRawSnippet(fn) {
1515
// @ts-expect-error the types are a lie
1616
return (/** @type {Payload} */ payload, /** @type {Params} */ ...args) => {
1717
var getters = /** @type {Getters<Params>} */ (args.map((value) => () => value));
18-
payload.out += fn(...getters)
19-
.render()
20-
.trim();
18+
payload.out.push(
19+
fn(...getters)
20+
.render()
21+
.trim()
22+
);
2123
};
2224
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ function print_error(payload, message) {
4040

4141
// eslint-disable-next-line no-console
4242
console.error(message);
43-
payload.head.out += `<script>console.error(${JSON.stringify(message)})</script>`;
43+
payload.head.out.push(`<script>console.error(${JSON.stringify(message)})</script>`);
4444
}
4545

4646
export function reset_elements() {

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

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,23 +33,23 @@ const INVALID_ATTR_NAME_CHAR_REGEX =
3333
* @returns {void}
3434
*/
3535
export function element(payload, tag, attributes_fn = noop, children_fn = noop) {
36-
payload.out += '<!---->';
36+
payload.out.push('<!---->');
3737

3838
if (tag) {
39-
payload.out += `<${tag}`;
39+
payload.out.push(`<${tag}`);
4040
attributes_fn();
41-
payload.out += `>`;
41+
payload.out.push(`>`);
4242

4343
if (!is_void(tag)) {
4444
children_fn();
4545
if (!is_raw_text_element(tag)) {
46-
payload.out += EMPTY_COMMENT;
46+
payload.out.push(EMPTY_COMMENT);
4747
}
48-
payload.out += `</${tag}>`;
48+
payload.out.push(`</${tag}>`);
4949
}
5050
}
5151

52-
payload.out += '<!---->';
52+
payload.out.push('<!---->');
5353
}
5454

5555
/**
@@ -72,7 +72,7 @@ export function render(component, options = {}) {
7272

7373
const prev_on_destroy = on_destroy;
7474
on_destroy = [];
75-
payload.out += BLOCK_OPEN;
75+
payload.out.push(BLOCK_OPEN);
7676

7777
let reset_reset_element;
7878

@@ -97,20 +97,22 @@ export function render(component, options = {}) {
9797
reset_reset_element();
9898
}
9999

100-
payload.out += BLOCK_CLOSE;
100+
payload.out.push(BLOCK_CLOSE);
101101
for (const cleanup of on_destroy) cleanup();
102102
on_destroy = prev_on_destroy;
103103

104-
let head = payload.head.out + payload.head.title;
104+
let head = payload.head.out.join('') + payload.head.title;
105105

106106
for (const { hash, code } of payload.css) {
107107
head += `<style id="${hash}">${code}</style>`;
108108
}
109109

110+
const body = payload.out.join('');
111+
110112
return {
111113
head,
112-
html: payload.out,
113-
body: payload.out
114+
html: body,
115+
body: body
114116
};
115117
} finally {
116118
abort();
@@ -124,9 +126,9 @@ export function render(component, options = {}) {
124126
*/
125127
export function head(payload, fn) {
126128
const head_payload = payload.head;
127-
head_payload.out += BLOCK_OPEN;
129+
head_payload.out.push(BLOCK_OPEN);
128130
fn(head_payload);
129-
head_payload.out += BLOCK_CLOSE;
131+
head_payload.out.push(BLOCK_CLOSE);
130132
}
131133

132134
/**
@@ -141,21 +143,21 @@ export function css_props(payload, is_html, props, component, dynamic = false) {
141143
const styles = style_object_to_string(props);
142144

143145
if (is_html) {
144-
payload.out += `<svelte-css-wrapper style="display: contents; ${styles}">`;
146+
payload.out.push(`<svelte-css-wrapper style="display: contents; ${styles}">`);
145147
} else {
146-
payload.out += `<g style="${styles}">`;
148+
payload.out.push(`<g style="${styles}">`);
147149
}
148150

149151
if (dynamic) {
150-
payload.out += '<!---->';
152+
payload.out.push('<!---->');
151153
}
152154

153155
component();
154156

155157
if (is_html) {
156-
payload.out += `<!----></svelte-css-wrapper>`;
158+
payload.out.push(`<!----></svelte-css-wrapper>`);
157159
} else {
158-
payload.out += `<!----></g>`;
160+
payload.out.push(`<!----></g>`);
159161
}
160162
}
161163

@@ -440,13 +442,13 @@ export function bind_props(props_parent, props_now) {
440442
*/
441443
function await_block(payload, promise, pending_fn, then_fn) {
442444
if (is_promise(promise)) {
443-
payload.out += BLOCK_OPEN;
445+
payload.out.push(BLOCK_OPEN);
444446
promise.then(null, noop);
445447
if (pending_fn !== null) {
446448
pending_fn();
447449
}
448450
} else if (then_fn !== null) {
449-
payload.out += BLOCK_OPEN_ELSE;
451+
payload.out.push(BLOCK_OPEN_ELSE);
450452
then_fn(promise);
451453
}
452454
}
@@ -493,7 +495,7 @@ export function once(get_value) {
493495
*/
494496
export function props_id(payload) {
495497
const uid = payload.uid();
496-
payload.out += '<!--#' + uid + '-->';
498+
payload.out.push('<!--#' + uid + '-->');
497499
return uid;
498500
}
499501

@@ -562,10 +564,13 @@ export function valueless_option(payload, children) {
562564

563565
children();
564566

565-
var body = payload.out.slice(i);
567+
var body = payload.out.slice(i).join('');
566568

567569
if (body.replace(/<!---->/g, '') === payload.select_value) {
568570
// replace '>' with ' selected>' (closing tag will be added later)
569-
payload.out = payload.out.slice(0, i - 1) + ' selected>' + body;
571+
var last_item = payload.out[i - 1];
572+
payload.out[i - 1] = last_item.slice(0, -1) + ' selected>';
573+
// Remove the old items after position i and add the body as a single item
574+
payload.out.splice(i, payload.out.length - i, body);
570575
}
571576
}

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
export class HeadPayload {
22
/** @type {Set<{ hash: string; code: string }>} */
33
css = new Set();
4-
out = '';
4+
/** @type {string[]} */
5+
out = [];
56
uid = () => '';
67
title = '';
78

8-
constructor(css = new Set(), out = '', title = '', uid = () => '') {
9+
constructor(css = new Set(), /** @type {string[]} */ out = [], title = '', uid = () => '') {
910
this.css = css;
1011
this.out = out;
1112
this.title = title;
@@ -16,7 +17,8 @@ export class HeadPayload {
1617
export class Payload {
1718
/** @type {Set<{ hash: string; code: string }>} */
1819
css = new Set();
19-
out = '';
20+
/** @type {string[]} */
21+
out = [];
2022
uid = () => '';
2123
select_value = undefined;
2224

@@ -36,12 +38,12 @@ export class Payload {
3638
export function copy_payload({ out, css, head, uid }) {
3739
const payload = new Payload();
3840

39-
payload.out = out;
41+
payload.out = [...out];
4042
payload.css = new Set(css);
4143
payload.uid = uid;
4244

4345
payload.head = new HeadPayload();
44-
payload.head.out = head.out;
46+
payload.head.out = [...head.out];
4547
payload.head.css = new Set(head.css);
4648
payload.head.title = head.title;
4749
payload.head.uid = head.uid;
@@ -56,7 +58,7 @@ export function copy_payload({ out, css, head, uid }) {
5658
* @returns {void}
5759
*/
5860
export function assign_payload(p1, p2) {
59-
p1.out = p2.out;
61+
p1.out = [...p2.out];
6062
p1.css = p2.css;
6163
p1.head = p2.head;
6264
p1.uid = p2.uid;

packages/svelte/tests/snapshot/samples/await-block-scope/_expected/server/index.svelte.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default function Await_block_scope($$payload) {
88
counter.count += 1;
99
}
1010

11-
$$payload.out += `<button>clicks: ${$.escape(counter.count)}</button> `;
11+
$$payload.out.push(`<button>clicks: ${$.escape(counter.count)}</button> `);
1212
$.await($$payload, promise, () => {}, (counter) => {});
13-
$$payload.out += `<!--]--> ${$.escape(counter.count)}`;
13+
$$payload.out.push(`<!--]--> ${$.escape(counter.count)}`);
1414
}

packages/svelte/tests/snapshot/samples/bind-component-snippet/_expected/server/index.svelte.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import * as $ from 'svelte/internal/server';
22
import TextInput from './Child.svelte';
33

44
function snippet($$payload) {
5-
$$payload.out += `<!---->Something`;
5+
$$payload.out.push(`<!---->Something`);
66
}
77

88
export default function Bind_component_snippet($$payload) {
@@ -23,7 +23,7 @@ export default function Bind_component_snippet($$payload) {
2323
}
2424
});
2525

26-
$$payload.out += `<!----> value: ${$.escape(value)}`;
26+
$$payload.out.push(`<!----> value: ${$.escape(value)}`);
2727
}
2828

2929
do {

0 commit comments

Comments
 (0)