From cb2799d1efa91e35c54188fc875cf82a3e8bd68d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 7 Feb 2019 11:54:40 -0500 Subject: [PATCH] only escape attribute values when rendering HTML --- src/compile/render-dom/wrappers/Slot.ts | 2 +- src/compile/render-ssr/handlers/Element.ts | 10 +++++----- src/compile/render-ssr/handlers/Slot.ts | 2 +- src/utils/get_slot_data.ts | 4 ++-- src/utils/stringify_attribute.ts | 6 ++++-- 5 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/compile/render-dom/wrappers/Slot.ts b/src/compile/render-dom/wrappers/Slot.ts index 746f9a2066..440590239d 100644 --- a/src/compile/render-dom/wrappers/Slot.ts +++ b/src/compile/render-dom/wrappers/Slot.ts @@ -63,7 +63,7 @@ export default class SlotWrapper extends Wrapper { get_slot_changes = renderer.component.getUniqueName(`get_${slot_name}_slot_changes`); get_slot_context = renderer.component.getUniqueName(`get_${slot_name}_slot_context`); - const context_props = get_slot_data(attributes); + const context_props = get_slot_data(attributes, false); const changes_props = []; const dependencies = new Set(); diff --git a/src/compile/render-ssr/handlers/Element.ts b/src/compile/render-ssr/handlers/Element.ts index ba5bd998ab..622b0d3eec 100644 --- a/src/compile/render-ssr/handlers/Element.ts +++ b/src/compile/render-ssr/handlers/Element.ts @@ -78,7 +78,7 @@ export default function(node, renderer, options) { args.push(snip(attribute.expression)); } else { if (attribute.name === 'value' && node.name === 'textarea') { - textareaContents = stringify_attribute(attribute); + textareaContents = stringify_attribute(attribute, true); } else if (attribute.isTrue) { args.push(`{ ${quoteNameIfNecessary(attribute.name)}: true }`); } else if ( @@ -89,7 +89,7 @@ export default function(node, renderer, options) { // a boolean attribute with one non-Text chunk args.push(`{ ${quoteNameIfNecessary(attribute.name)}: ${snip(attribute.chunks[0])} }`); } else { - args.push(`{ ${quoteNameIfNecessary(attribute.name)}: \`${stringify_attribute(attribute)}\` }`); + args.push(`{ ${quoteNameIfNecessary(attribute.name)}: \`${stringify_attribute(attribute, true)}\` }`); } } }); @@ -100,7 +100,7 @@ export default function(node, renderer, options) { if (attribute.type !== 'Attribute') return; if (attribute.name === 'value' && node.name === 'textarea') { - textareaContents = stringify_attribute(attribute); + textareaContents = stringify_attribute(attribute, true); } else if (attribute.isTrue) { openingTag += ` ${attribute.name}`; } else if ( @@ -112,14 +112,14 @@ export default function(node, renderer, options) { openingTag += '${' + snip(attribute.chunks[0]) + ' ? " ' + attribute.name + '" : "" }'; } else if (attribute.name === 'class' && classExpr) { addClassAttribute = false; - openingTag += ` class="\${[\`${stringify_attribute(attribute)}\`, ${classExpr}].join(' ').trim() }"`; + openingTag += ` class="\${[\`${stringify_attribute(attribute, true)}\`, ${classExpr}].join(' ').trim() }"`; } else if (attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text') { const { name } = attribute; const snippet = snip(attribute.chunks[0]); openingTag += '${(v => v == null ? "" : ` ' + name + '="${@escape(' + snippet + ')}"`)(' + snippet + ')}'; } else { - openingTag += ` ${attribute.name}="${stringify_attribute(attribute)}"`; + openingTag += ` ${attribute.name}="${stringify_attribute(attribute, true)}"`; } }); } diff --git a/src/compile/render-ssr/handlers/Slot.ts b/src/compile/render-ssr/handlers/Slot.ts index 6bf2a22cad..341ae6df2d 100644 --- a/src/compile/render-ssr/handlers/Slot.ts +++ b/src/compile/render-ssr/handlers/Slot.ts @@ -7,7 +7,7 @@ export default function(node, renderer, options) { const slot_name = name && name.chunks[0].data || 'default'; const prop = quotePropIfNecessary(slot_name); - const slot_data = get_slot_data(node.attributes); + const slot_data = get_slot_data(node.attributes, true); const arg = slot_data.length > 0 ? `{ ${slot_data.join(', ')} }` : ''; diff --git a/src/utils/get_slot_data.ts b/src/utils/get_slot_data.ts index 3b817c8329..b7b08db341 100644 --- a/src/utils/get_slot_data.ts +++ b/src/utils/get_slot_data.ts @@ -1,7 +1,7 @@ import { snip } from './snip'; import { stringify_attribute } from './stringify_attribute'; -export default function(attributes) { +export default function get_slot_data(attributes, is_ssr: boolean) { return attributes .filter(attribute => attribute.name !== 'name') .map(attribute => { @@ -11,7 +11,7 @@ export default function(attributes) { ? '""' : attribute.chunks.length === 1 && attribute.chunks[0].type !== 'Text' ? snip(attribute.chunks[0]) - : '`' + stringify_attribute(attribute) + '`'; + : '`' + stringify_attribute(attribute, is_ssr) + '`'; return `${attribute.name}: ${value}`; }); diff --git a/src/utils/stringify_attribute.ts b/src/utils/stringify_attribute.ts index 933a84ed03..8cd7e2101c 100644 --- a/src/utils/stringify_attribute.ts +++ b/src/utils/stringify_attribute.ts @@ -3,14 +3,16 @@ import Node from '../compile/nodes/shared/Node'; import { escapeTemplate, escape } from './stringify'; import { snip } from './snip'; -export function stringify_attribute(attribute: Attribute) { +export function stringify_attribute(attribute: Attribute, is_ssr: boolean) { return attribute.chunks .map((chunk: Node) => { if (chunk.type === 'Text') { return escapeTemplate(escape(chunk.data).replace(/"/g, '"')); } - return '${@escape(' + snip(chunk) + ')}'; + return is_ssr + ? '${@escape(' + snip(chunk) + ')}' + : '${' + snip(chunk) + '}'; }) .join(''); } \ No newline at end of file