Skip to content

Commit

Permalink
Faster SSR (#5701)
Browse files Browse the repository at this point in the history
Co-authored-by: Conduitry <git@chor.date>
Co-authored-by: Ben McCann <322311+benmccann@users.noreply.github.com>
  • Loading branch information
3 people committed May 13, 2022
1 parent 34eb6ef commit e7a2350
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
Expand Up @@ -9,7 +9,7 @@ export function get_class_attribute_value(attribute: Attribute): ESTreeExpressio
// handle special case — `class={possiblyUndefined}` with scoped CSS
if (attribute.chunks.length === 2 && (attribute.chunks[1] as Text).synthetic) {
const value = (attribute.chunks[0] as Expression).node;
return x`@escape(@null_to_empty(${value})) + "${(attribute.chunks[1] as Text).data}"`;
return x`@escape(@null_to_empty(${value}), true) + "${(attribute.chunks[1] as Text).data}"`;
}

return get_attribute_value(attribute);
Expand All @@ -22,7 +22,7 @@ export function get_attribute_value(attribute: Attribute): ESTreeExpression {
.map((chunk) => {
return chunk.type === 'Text'
? string_literal(chunk.data.replace(/"/g, '&quot;')) as ESTreeExpression
: x`@escape(${chunk.node})`;
: x`@escape(${chunk.node}, true)`;
})
.reduce((lhs, rhs) => x`${lhs} + ${rhs}`);
}
Expand Down
36 changes: 25 additions & 11 deletions src/runtime/internal/ssr.ts
Expand Up @@ -69,20 +69,34 @@ export function merge_ssr_styles(style_attribute, style_directive) {
return style_object;
}

export const escaped = {
'"': '&quot;',
"'": '&#39;',
'&': '&amp;',
'<': '&lt;',
'>': '&gt;'
};

export function escape(html) {
return String(html).replace(/["'&<>]/g, match => escaped[match]);
const ATTR_REGEX = /[&"]/g;
const CONTENT_REGEX = /[&<]/g;

/**
* Note: this method is performance sensitive and has been optimized
* https://github.com/sveltejs/svelte/pull/5701
*/
export function escape(value: unknown, is_attr = false) {
const str = String(value);

const pattern = is_attr ? ATTR_REGEX : CONTENT_REGEX;
pattern.lastIndex = 0;

let escaped = '';
let last = 0;

while (pattern.test(str)) {
const i = pattern.lastIndex - 1;
const ch = str[i];
escaped += str.substring(last, i) + (ch === '&' ? '&amp;' : (ch === '"' ? '&quot;' : '&lt;'));
last = i + 1;
}

return escaped + str.substring(last);
}

export function escape_attribute_value(value) {
return typeof value === 'string' ? escape(value) : value;
return typeof value === 'string' ? escape(value, true) : value;
}

export function escape_object(obj) {
Expand Down

0 comments on commit e7a2350

Please sign in to comment.