fix: special case literals with `"` in it and fix standalone case

pull/14269/head
paoloricciuti 2 years ago
parent dec07f00c1
commit 72244cd14e

@ -2,8 +2,6 @@
/** @import { Context } from '../types' */
import { is_tag_valid_with_parent } from '../../../../html-tree-validation.js';
import * as e from '../../../errors.js';
import { is_inlinable_expression } from '../../utils.js';
import { mark_subtree_dynamic } from './shared/fragment.js';
/**
* @param {AST.ExpressionTag} node

@ -6,6 +6,7 @@ import { TEMPLATE_FRAGMENT, TEMPLATE_USE_IMPORT_NODE } from '../../../../../cons
import { dev } from '../../../../state.js';
import * as b from '../../../../utils/builders.js';
import { sanitize_template_string } from '../../../../utils/sanitize_template_string.js';
import { is_inlinable_expression } from '../../../utils.js';
import { clean_nodes, infer_namespace } from '../../utils.js';
import { process_children } from './shared/fragment.js';
import { build_render_statement } from './shared/utils.js';
@ -142,7 +143,8 @@ export function Fragment(node, context) {
const use_space_template =
trimmed.some((node) => node.type === 'ExpressionTag') &&
trimmed.every((node) => node.type === 'Text' || node.type === 'ExpressionTag');
trimmed.every((node) => node.type === 'Text' || node.type === 'ExpressionTag') &&
!is_inlinable_expression(trimmed, context.state.scope);
if (use_space_template) {
// special case — we can use `$.text` instead of creating a unique template

@ -364,10 +364,7 @@ export function RegularElement(node, context) {
let { value } = build_template_literal(trimmed, context.visit, child_state);
// if the expression is inlinable we just push it to the template
if (is_inlinable_expression(trimmed, context.state.scope)) {
// escaping every quasi if it's a template literal
if (value.type === 'TemplateLiteral') {
escape_template_quasis(value);
}
escape_template_quasis(value);
state.template.push(value);
} else {
// else we programmatically set the value
@ -601,6 +598,7 @@ function build_element_attribute_update_assignment(element, node_id, attribute,
return true;
} else {
if (inlinable_expression) {
escape_template_quasis(value, true);
context.state.template.push(` ${name}="`, value, '"');
} else {
state.init.push(update);

@ -84,11 +84,8 @@ export function process_children(nodes, initial, is_element, { visit, state }) {
state.update.push(update);
} else {
// if the expression is inlinable we just push it to the template
if (is_inlinable_expression(sequence, state.scope)) {
// escaping every quasi if it's a template literal
if (value.type === 'TemplateLiteral') {
escape_template_quasis(value);
}
if (is_inlinable_expression(sequence, state.scope) && !is_text) {
escape_template_quasis(value);
state.template.push(value);
} else {
// else we programmatically set the value

@ -1,4 +1,4 @@
/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement, Super, TemplateLiteral } from 'estree' */
/** @import { Expression, ExpressionStatement, Identifier, MemberExpression, Statement, Super, TemplateLiteral, Literal } from 'estree' */
/** @import { AST, SvelteNode } from '#compiler' */
/** @import { ComponentClientTransformState } from '../../types' */
import { walk } from 'zimmerframe';
@ -34,12 +34,30 @@ export function get_states_and_calls(values) {
}
/**
* Escape the html in every quesi in the template literal
* @param {TemplateLiteral} template
* @param {SvelteNode} template
* @param {boolean} [is_attr]
*/
export function escape_template_quasis(template) {
for (let quasi of template.quasis) {
quasi.value.raw = escape_html(quasi.value.raw);
}
export function escape_template_quasis(template, is_attr) {
walk(
template,
{},
{
TemplateLiteral(node, { next }) {
for (let quasi of node.quasis) {
quasi.value.raw = escape_html(quasi.value.raw, is_attr);
}
next();
},
Literal(node, { next }) {
if (node.raw != null) {
node.raw = escape_html(node.raw, is_attr);
} else {
node.value = escape_html(node.value, is_attr);
}
next();
}
}
);
}
/**

@ -66,7 +66,11 @@ export function is_inlinable_expression(value, scope) {
// we need to special case null and boolean values because
// we want to set them programmatically
value.expression.type === 'Literal' &&
(value.expression.value === null || typeof value.expression.value === 'boolean')
(value.expression.value === null ||
typeof value.expression.value === 'boolean' ||
// we also want to special case the case of a literal with quotes
// because it could mess with the template
(typeof value.expression.value === 'string' && value.expression.value.includes('"')))
) {
return false;
}

Loading…
Cancel
Save