|
|
@ -27,6 +27,9 @@ import { regex_starts_with_newline, regex_whitespaces_strict } from '../../patte
|
|
|
|
import { DOMBooleanAttributes } from '../../../../constants.js';
|
|
|
|
import { DOMBooleanAttributes } from '../../../../constants.js';
|
|
|
|
import { sanitize_template_string } from '../../../utils/sanitize_template_string.js';
|
|
|
|
import { sanitize_template_string } from '../../../utils/sanitize_template_string.js';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const block_open = t_string('<![>');
|
|
|
|
|
|
|
|
const block_close = t_string('<!]>');
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @param {string} value
|
|
|
|
* @param {string} value
|
|
|
|
* @returns {import('./types').TemplateString}
|
|
|
|
* @returns {import('./types').TemplateString}
|
|
|
@ -52,15 +55,6 @@ function t_statement(value) {
|
|
|
|
return { type: 'statement', value };
|
|
|
|
return { type: 'statement', value };
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* @param {import('./types').ServerTransformState} state
|
|
|
|
|
|
|
|
* @returns {[import('estree').VariableDeclaration, import('estree').Identifier]}
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
function serialize_anchor(state) {
|
|
|
|
|
|
|
|
const id = state.scope.root.unique('anchor');
|
|
|
|
|
|
|
|
return [b.const(id, b.call('$.create_anchor', b.id('$$payload'))), id];
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* @param {import('./types').Template[]} template
|
|
|
|
* @param {import('./types').Template[]} template
|
|
|
|
* @param {import('estree').Identifier} out
|
|
|
|
* @param {import('estree').Identifier} out
|
|
|
@ -1237,12 +1231,10 @@ const template_visitors = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
HtmlTag(node, context) {
|
|
|
|
HtmlTag(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
const raw = /** @type {import('estree').Expression} */ (context.visit(node.expression));
|
|
|
|
const raw = /** @type {import('estree').Expression} */ (context.visit(node.expression));
|
|
|
|
context.state.template.push(t_expression(raw));
|
|
|
|
context.state.template.push(t_expression(raw));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ConstTag(node, { state, visit }) {
|
|
|
|
ConstTag(node, { state, visit }) {
|
|
|
|
const declaration = node.declaration.declarations[0];
|
|
|
|
const declaration = node.declaration.declarations[0];
|
|
|
@ -1273,10 +1265,8 @@ const template_visitors = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
RenderTag(node, context) {
|
|
|
|
RenderTag(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [anchor, anchor_id] = serialize_anchor(state);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.init.push(anchor);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.template.push(t_expression(anchor_id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const callee = unwrap_optional(node.expression).callee;
|
|
|
|
const callee = unwrap_optional(node.expression).callee;
|
|
|
|
const raw_args = unwrap_optional(node.expression).arguments;
|
|
|
|
const raw_args = unwrap_optional(node.expression).arguments;
|
|
|
@ -1302,7 +1292,7 @@ const template_visitors = {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
state.template.push(t_expression(anchor_id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
ClassDirective(node) {
|
|
|
|
ClassDirective(node) {
|
|
|
|
error(node, 'INTERNAL', 'Node should have been handled elsewhere');
|
|
|
|
error(node, 'INTERNAL', 'Node should have been handled elsewhere');
|
|
|
@ -1427,9 +1417,7 @@ const template_visitors = {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
const [el_anchor, anchor_id] = serialize_anchor(context.state);
|
|
|
|
context.state.template.push(block_open);
|
|
|
|
context.state.init.push(el_anchor);
|
|
|
|
|
|
|
|
context.state.template.push(t_expression(anchor_id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const main = create_block(node, node.fragment.nodes, {
|
|
|
|
const main = create_block(node, node.fragment.nodes, {
|
|
|
|
...context,
|
|
|
|
...context,
|
|
|
@ -1465,7 +1453,7 @@ const template_visitors = {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
),
|
|
|
|
),
|
|
|
|
t_expression(anchor_id)
|
|
|
|
block_close
|
|
|
|
);
|
|
|
|
);
|
|
|
|
if (context.state.options.dev) {
|
|
|
|
if (context.state.options.dev) {
|
|
|
|
context.state.template.push(t_statement(b.stmt(b.call('$.pop_element'))));
|
|
|
|
context.state.template.push(t_statement(b.stmt(b.call('$.pop_element'))));
|
|
|
@ -1473,9 +1461,7 @@ const template_visitors = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
EachBlock(node, context) {
|
|
|
|
EachBlock(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const each_node_meta = node.metadata;
|
|
|
|
const each_node_meta = node.metadata;
|
|
|
|
const collection = /** @type {import('estree').Expression} */ (context.visit(node.expression));
|
|
|
|
const collection = /** @type {import('estree').Expression} */ (context.visit(node.expression));
|
|
|
@ -1486,14 +1472,6 @@ const template_visitors = {
|
|
|
|
: b.id(node.index);
|
|
|
|
: b.id(node.index);
|
|
|
|
const children = node.body.nodes;
|
|
|
|
const children = node.body.nodes;
|
|
|
|
|
|
|
|
|
|
|
|
const [each_dec, each_id] = serialize_anchor(state);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {import('./types').Anchor} */
|
|
|
|
|
|
|
|
const anchor = {
|
|
|
|
|
|
|
|
type: 'Anchor',
|
|
|
|
|
|
|
|
id: each_id
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const array_id = state.scope.root.unique('each_array');
|
|
|
|
const array_id = state.scope.root.unique('each_array');
|
|
|
|
state.init.push(b.const(array_id, b.call('$.ensure_array_like', collection)));
|
|
|
|
state.init.push(b.const(array_id, b.call('$.ensure_array_like', collection)));
|
|
|
|
|
|
|
|
|
|
|
@ -1507,11 +1485,14 @@ const template_visitors = {
|
|
|
|
each.push(b.let(node.index, index));
|
|
|
|
each.push(b.let(node.index, index));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
each.push(b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(block_open.value))));
|
|
|
|
|
|
|
|
|
|
|
|
each.push(
|
|
|
|
each.push(
|
|
|
|
each_dec,
|
|
|
|
.../** @type {import('estree').Statement[]} */ (create_block(node, children, context))
|
|
|
|
.../** @type {import('estree').Statement[]} */ (create_block(node, children, context, anchor))
|
|
|
|
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
each.push(b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(block_close.value))));
|
|
|
|
|
|
|
|
|
|
|
|
const for_loop = b.for(
|
|
|
|
const for_loop = b.for(
|
|
|
|
b.let(index, b.literal(0)),
|
|
|
|
b.let(index, b.literal(0)),
|
|
|
|
b.binary('<', index, b.member(array_id, b.id('length'))),
|
|
|
|
b.binary('<', index, b.member(array_id, b.id('length'))),
|
|
|
@ -1535,13 +1516,11 @@ const template_visitors = {
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
state.template.push(t_statement(for_loop));
|
|
|
|
state.template.push(t_statement(for_loop));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
IfBlock(node, context) {
|
|
|
|
IfBlock(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Insert ssr:if:true/false anchors in addition to the other anchors so that
|
|
|
|
// Insert ssr:if:true/false anchors in addition to the other anchors so that
|
|
|
|
// the if block can catch hydration mismatches (false on the server, true on the client and vice versa)
|
|
|
|
// the if block can catch hydration mismatches (false on the server, true on the client and vice versa)
|
|
|
@ -1568,13 +1547,11 @@ const template_visitors = {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
AwaitBlock(node, context) {
|
|
|
|
AwaitBlock(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.template.push(
|
|
|
|
state.template.push(
|
|
|
|
t_statement(
|
|
|
|
t_statement(
|
|
|
@ -1608,16 +1585,14 @@ const template_visitors = {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
);
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
KeyBlock(node, context) {
|
|
|
|
KeyBlock(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
const body = create_block(node, node.fragment.nodes, context);
|
|
|
|
const body = create_block(node, node.fragment.nodes, context);
|
|
|
|
state.template.push(t_statement(b.block(body)));
|
|
|
|
state.template.push(t_statement(b.block(body)));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SnippetBlock(node, context) {
|
|
|
|
SnippetBlock(node, context) {
|
|
|
|
// TODO hoist where possible
|
|
|
|
// TODO hoist where possible
|
|
|
@ -1635,34 +1610,28 @@ const template_visitors = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Component(node, context) {
|
|
|
|
Component(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
const call = serialize_inline_component(node, node.name, context);
|
|
|
|
const call = serialize_inline_component(node, node.name, context);
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SvelteSelf(node, context) {
|
|
|
|
SvelteSelf(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
const call = serialize_inline_component(node, context.state.analysis.name, context);
|
|
|
|
const call = serialize_inline_component(node, context.state.analysis.name, context);
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SvelteComponent(node, context) {
|
|
|
|
SvelteComponent(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
const call = serialize_inline_component(
|
|
|
|
const call = serialize_inline_component(
|
|
|
|
node,
|
|
|
|
node,
|
|
|
|
/** @type {import('estree').Expression} */ (context.visit(node.expression)),
|
|
|
|
/** @type {import('estree').Expression} */ (context.visit(node.expression)),
|
|
|
|
context
|
|
|
|
context
|
|
|
|
);
|
|
|
|
);
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_statement(call));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
LetDirective(node, { state }) {
|
|
|
|
LetDirective(node, { state }) {
|
|
|
|
if (node.expression && node.expression.type !== 'Identifier') {
|
|
|
|
if (node.expression && node.expression.type !== 'Identifier') {
|
|
|
@ -1745,9 +1714,7 @@ const template_visitors = {
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SlotElement(node, context) {
|
|
|
|
SlotElement(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|
const [dec, id] = serialize_anchor(state);
|
|
|
|
state.template.push(block_open);
|
|
|
|
state.init.push(dec);
|
|
|
|
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @type {import('estree').Property[]} */
|
|
|
|
/** @type {import('estree').Property[]} */
|
|
|
|
const props = [];
|
|
|
|
const props = [];
|
|
|
@ -1794,7 +1761,7 @@ const template_visitors = {
|
|
|
|
const slot = b.call('$.slot', b.id('$$payload'), expression, props_expression, fallback);
|
|
|
|
const slot = b.call('$.slot', b.id('$$payload'), expression, props_expression, fallback);
|
|
|
|
|
|
|
|
|
|
|
|
state.template.push(t_statement(b.stmt(slot)));
|
|
|
|
state.template.push(t_statement(b.stmt(slot)));
|
|
|
|
state.template.push(t_expression(id));
|
|
|
|
state.template.push(block_close);
|
|
|
|
},
|
|
|
|
},
|
|
|
|
SvelteHead(node, context) {
|
|
|
|
SvelteHead(node, context) {
|
|
|
|
const state = context.state;
|
|
|
|
const state = context.state;
|
|
|
|