Skip to content

Commit

Permalink
fix: SSR template escaping (#12007)
Browse files Browse the repository at this point in the history
We need to escape at the point of serialization to catch all cases, not just the ones we wrapped with the escape method previously
fixes #12005
  • Loading branch information
gtm-nayan authored Jun 12, 2024
1 parent 84ad208 commit 2a86323
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 19 deletions.
5 changes: 5 additions & 0 deletions .changeset/late-zebras-argue.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"svelte": patch
---

fix: SSR template escaping
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,9 @@ import {
} from '../../../../internal/server/hydration.js';
import { filename, locator } from '../../../state.js';

export const block_open = string(BLOCK_OPEN);
export const block_close = string(BLOCK_CLOSE);
export const block_anchor = string(BLOCK_ANCHOR);

/** @param {string} value */
function string(value) {
return b.literal(sanitize_template_string(value));
}
export const block_open = b.literal(BLOCK_OPEN);
export const block_close = b.literal(BLOCK_CLOSE);
export const block_anchor = b.literal(BLOCK_ANCHOR);

/**
* @param {import('estree').Node} node
Expand Down Expand Up @@ -93,7 +88,8 @@ function serialize_template(template, out = b.id('$$payload.out'), operator = '+
if (!last) quasis.push((last = b.quasi('', false)));

if (node.type === 'Literal') {
last.value.raw += node.value;
last.value.raw +=
typeof node.value === 'string' ? sanitize_template_string(node.value) : node.value;
} else if (node.type === 'TemplateLiteral') {
last.value.raw += node.quasis[0].value.raw;
quasis.push(...node.quasis.slice(1));
Expand Down Expand Up @@ -1203,14 +1199,14 @@ const template_visitors = {
throw new Error('Node should have been handled elsewhere');
},
RegularElement(node, context) {
context.state.template.push(string(`<${node.name}`));
context.state.template.push(b.literal(`<${node.name}`));
const body = serialize_element_attributes(node, context);
context.state.template.push(string('>'));
context.state.template.push(b.literal('>'));

if ((node.name === 'script' || node.name === 'style') && node.fragment.nodes.length === 1) {
context.state.template.push(
string(/** @type {import('#compiler').Text} */ (node.fragment.nodes[0]).data),
string(`</${node.name}>`)
b.literal(/** @type {import('#compiler').Text} */ (node.fragment.nodes[0]).data),
b.literal(`</${node.name}>`)
);

return;
Expand Down Expand Up @@ -1285,7 +1281,7 @@ const template_visitors = {
}

if (!VoidElements.includes(node.name) && namespace !== 'foreign') {
state.template.push(string(`</${node.name}>`));
state.template.push(b.literal(`</${node.name}>`));
}

if (state.options.dev) {
Expand Down Expand Up @@ -1524,9 +1520,9 @@ const template_visitors = {
},
TitleElement(node, context) {
// title is guaranteed to contain only text/expression tag children
const template = [string('<title>')];
const template = [b.literal('<title>')];
process_children(node.fragment.nodes, { ...context, state: { ...context.state, template } });
template.push(string('</title>'));
template.push(b.literal('</title>'));

context.state.init.push(...serialize_template(template, b.id('$$payload.title'), '='));
},
Expand Down Expand Up @@ -1802,7 +1798,7 @@ function serialize_element_attributes(node, context) {
).value;
if (name !== 'class' || literal_value) {
context.state.template.push(
string(
b.literal(
` ${attribute.name}${
DOMBooleanAttributes.includes(name) && literal_value === true
? ''
Expand Down Expand Up @@ -1830,7 +1826,7 @@ function serialize_element_attributes(node, context) {

if (events_to_capture.size !== 0) {
for (const event of events_to_capture) {
context.state.template.push(string(` ${event}="this.__e=event"`));
context.state.template.push(b.literal(` ${event}="this.__e=event"`));
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { test } from '../../test';

export default test({
html: '<code>`${foo}\\n`</code>\n<div title="`${foo}\\n`">foo</div>\n<div>`${foo}\\n`</div>'
html: '<code>`${foo}\\n`</code>\n`\n<div title="`${foo}\\n`">foo</div>\n<div>`${foo}\\n`</div>'
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
</script>

<code>`$&#123;foo}\n`</code>
{@html "`"}
<div title="`$&#123;foo}\n`">foo</div>
<Widget value="`$&#123;foo}\n`"/>

0 comments on commit 2a86323

Please sign in to comment.