reduce some indirection

pull/11977/head
Rich Harris 2 years ago
parent 7b7f4bbd3c
commit 877c127899

@ -47,30 +47,28 @@ export const block_anchor = t_string(`<!--${HYDRATION_ANCHOR}-->`);
/** /**
* @param {string} value * @param {string} value
* @returns {import('./types').TemplateExpression}
*/ */
function t_string(value) { function t_string(value) {
return { type: 'expression', value: b.literal(sanitize_template_string(value)) }; return t_expression(b.literal(sanitize_template_string(value)));
} }
/** /**
* @param {import('estree').Expression} value * @param {import('estree').Expression} value
* @returns {import('./types').TemplateExpression}
*/ */
function t_expression(value) { function t_expression(value) {
return { type: 'expression', value }; return value;
} }
/** /**
* @param {import('estree').Statement} value * @param {import('estree').Node} node
* @returns {import('./types').TemplateStatement} * @returns {node is import('estree').Statement}
*/ */
function t_statement(value) { function is_statement(node) {
return { type: 'statement', value }; return node.type.endsWith('Statement') || node.type.endsWith('Declaration');
} }
/** /**
* @param {import('./types').Template[]} template * @param {Array<import('estree').Statement | import('estree').Expression>} template
* @param {import('estree').Identifier} out * @param {import('estree').Identifier} out
* @returns {import('estree').Statement[]} * @returns {import('estree').Statement[]}
*/ */
@ -94,19 +92,20 @@ function serialize_template(template, out = b.id('out')) {
for (let i = 0; i < template.length; i++) { for (let i = 0; i < template.length; i++) {
const template_item = template[i]; const template_item = template[i];
if (template_item.type === 'statement') {
if (is_statement(template_item)) {
if (quasis.length !== 0) { if (quasis.length !== 0) {
flush_payload(); flush_payload();
} }
statements.push(template_item.value); statements.push(template_item);
} else { } else {
let last = quasis.at(-1); let last = quasis.at(-1);
if (!last) quasis.push((last = b.quasi('', false))); if (!last) quasis.push((last = b.quasi('', false)));
if (template_item.value.type === 'Literal') { if (template_item.type === 'Literal') {
last.value.raw += template_item.value.value; last.value.raw += template_item.value;
} else if (template_item.type === 'expression') { } else {
const value = template_item.value; const value = template_item;
if (value.type === 'TemplateLiteral') { if (value.type === 'TemplateLiteral') {
last.value.raw += value.quasis[0].value.raw; last.value.raw += value.quasis[0].value.raw;
quasis.push(...value.quasis.slice(1)); quasis.push(...value.quasis.slice(1));
@ -114,7 +113,7 @@ function serialize_template(template, out = b.id('out')) {
continue; continue;
} }
expressions.push(value); expressions.push(value);
quasis.push(b.quasi('', i + 1 === template.length || template[i + 1].type === 'statement')); quasis.push(b.quasi('', i + 1 === template.length || is_statement(template[i + 1])));
} }
} }
} }
@ -1125,10 +1124,10 @@ function serialize_inline_component(node, component_name, context) {
) )
); );
context.state.template.push(t_statement(statement)); context.state.template.push(statement);
} else { } else {
context.state.template.push(block_open); context.state.template.push(block_open);
context.state.template.push(t_statement(statement)); context.state.template.push(statement);
context.state.template.push(block_close); context.state.template.push(block_close);
} }
} }
@ -1302,23 +1301,21 @@ const template_visitors = {
}, },
DebugTag(node, { state, visit }) { DebugTag(node, { state, visit }) {
state.template.push( state.template.push(
t_statement( b.stmt(
b.stmt( b.call(
b.call( 'console.log',
'console.log', b.object(
b.object( node.identifiers.map((identifier) =>
node.identifiers.map((identifier) => b.prop(
b.prop( 'init',
'init', identifier,
identifier, /** @type {import('estree').Expression} */ (visit(identifier))
/** @type {import('estree').Expression} */ (visit(identifier))
)
) )
) )
) )
) )
), ),
t_statement(b.debugger) b.debugger
); );
}, },
RenderTag(node, context) { RenderTag(node, context) {
@ -1339,13 +1336,11 @@ const template_visitors = {
}); });
state.template.push( state.template.push(
t_statement( b.stmt(
b.stmt( (node.expression.type === 'CallExpression' ? b.call : b.maybe_call)(
(node.expression.type === 'CallExpression' ? b.call : b.maybe_call)( snippet_function,
snippet_function, b.id('$$payload'),
b.id('$$payload'), ...snippet_args
...snippet_args
)
) )
) )
); );
@ -1394,15 +1389,13 @@ const template_visitors = {
if (state.options.dev) { if (state.options.dev) {
const location = /** @type {import('locate-character').Location} */ (locator(node.start)); const location = /** @type {import('locate-character').Location} */ (locator(node.start));
state.template.push( state.template.push(
t_statement( b.stmt(
b.stmt( b.call(
b.call( '$.push_element',
'$.push_element', b.id('$$payload'),
b.id('$$payload'), b.literal(node.name),
b.literal(node.name), b.literal(location.line),
b.literal(location.line), b.literal(location.column)
b.literal(location.column)
)
) )
) )
); );
@ -1415,7 +1408,7 @@ const template_visitors = {
if (body.type !== 'Identifier') { if (body.type !== 'Identifier') {
id = b.id(state.scope.generate('$$body')); id = b.id(state.scope.generate('$$body'));
state.template.push(t_statement(b.const(id, body))); state.template.push(b.const(id, body));
} }
// if this is a `<textarea>` value or a contenteditable binding, we only add // if this is a `<textarea>` value or a contenteditable binding, we only add
@ -1425,12 +1418,10 @@ const template_visitors = {
// Use the body expression as the body if it's truthy, otherwise use the inner template // Use the body expression as the body if it's truthy, otherwise use the inner template
state.template.push( state.template.push(
t_statement( b.if(
b.if( id,
id, b.block(serialize_template([t_expression(id)])),
b.block(serialize_template([t_expression(id)])), b.block([...inner_state.init, ...serialize_template(inner_state.template)])
b.block([...inner_state.init, ...serialize_template(inner_state.template)])
)
) )
); );
} }
@ -1440,7 +1431,7 @@ const template_visitors = {
} }
if (state.options.dev) { if (state.options.dev) {
state.template.push(t_statement(b.stmt(b.call('$.pop_element')))); state.template.push(b.stmt(b.call('$.pop_element')));
} }
}, },
SvelteElement(node, context) { SvelteElement(node, context) {
@ -1471,9 +1462,7 @@ const template_visitors = {
serialize_element_attributes(node, { ...context, state }); serialize_element_attributes(node, { ...context, state });
if (context.state.options.dev) { if (context.state.options.dev) {
context.state.template.push( context.state.template.push(b.stmt(b.call('$.push_element', tag, b.id('$$payload'))));
t_statement(b.stmt(b.call('$.push_element', tag, b.id('$$payload'))))
);
} }
const attributes = b.block([...state.init, ...serialize_template(state.template)]); const attributes = b.block([...state.init, ...serialize_template(state.template)]);
@ -1485,10 +1474,10 @@ const template_visitors = {
b.call('$.element', b.id('$$payload'), tag, b.thunk(attributes), b.thunk(children)) b.call('$.element', b.id('$$payload'), tag, b.thunk(attributes), b.thunk(children))
); );
context.state.template.push(t_statement(b.if(tag, body)), block_anchor); context.state.template.push(b.if(tag, body), block_anchor);
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(b.stmt(b.call('$.pop_element')));
} }
}, },
EachBlock(node, context) { EachBlock(node, context) {
@ -1542,22 +1531,17 @@ const template_visitors = {
); );
state.template.push( state.template.push(
t_statement( b.if(
b.if( b.binary('!==', b.member(array_id, b.id('length')), b.literal(0)),
b.binary('!==', b.member(array_id, b.id('length')), b.literal(0)), b.block([for_loop, close]),
b.block([for_loop, close]), fallback
fallback
)
) )
); );
} else { } else {
state.template.push(t_statement(for_loop), t_statement(close)); state.template.push(for_loop, close);
} }
}, },
IfBlock(node, context) { IfBlock(node, context) {
const state = context.state;
state.template.push(block_open);
const test = /** @type {import('estree').Expression} */ (context.visit(node.test)); const test = /** @type {import('estree').Expression} */ (context.visit(node.test));
const consequent = /** @type {import('estree').BlockStatement} */ ( const consequent = /** @type {import('estree').BlockStatement} */ (
@ -1573,52 +1557,43 @@ const template_visitors = {
b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(BLOCK_CLOSE_ELSE))) b.stmt(b.assignment('+=', b.id('$$payload.out'), b.literal(BLOCK_CLOSE_ELSE)))
); );
state.template.push(t_statement(b.if(test, consequent, alternate))); context.state.template.push(block_open, b.if(test, consequent, alternate));
}, },
AwaitBlock(node, context) { AwaitBlock(node, context) {
const state = context.state; context.state.template.push(
state.template.push(block_open); block_open,
b.stmt(
state.template.push( b.call(
t_statement( '$.await',
b.stmt( /** @type {import('estree').Expression} */ (context.visit(node.expression)),
b.call( b.thunk(
'$.await', node.pending
/** @type {import('estree').Expression} */ (context.visit(node.expression)), ? /** @type {import('estree').BlockStatement} */ (context.visit(node.pending))
b.thunk( : b.block([])
node.pending ),
? /** @type {import('estree').BlockStatement} */ (context.visit(node.pending)) b.arrow(
: b.block([]) node.value ? [/** @type {import('estree').Pattern} */ (context.visit(node.value))] : [],
), node.then
b.arrow( ? /** @type {import('estree').BlockStatement} */ (context.visit(node.then))
node.value : b.block([])
? [/** @type {import('estree').Pattern} */ (context.visit(node.value))] ),
: [], b.arrow(
node.then node.error ? [/** @type {import('estree').Pattern} */ (context.visit(node.error))] : [],
? /** @type {import('estree').BlockStatement} */ (context.visit(node.then)) node.catch
: b.block([]) ? /** @type {import('estree').BlockStatement} */ (context.visit(node.catch))
), : b.block([])
b.arrow(
node.error
? [/** @type {import('estree').Pattern} */ (context.visit(node.error))]
: [],
node.catch
? /** @type {import('estree').BlockStatement} */ (context.visit(node.catch))
: b.block([])
)
) )
) )
) ),
block_close
); );
state.template.push(block_close);
}, },
KeyBlock(node, context) { KeyBlock(node, context) {
const state = context.state; context.state.template.push(
state.template.push(block_open); block_open,
const block = /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment)); /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment)),
state.template.push(t_statement(block)); block_close
state.template.push(block_close); );
}, },
SnippetBlock(node, context) { SnippetBlock(node, context) {
const fn = b.function_declaration( const fn = b.function_declaration(
@ -1687,16 +1662,14 @@ const template_visitors = {
for (const attribute of node.attributes) { for (const attribute of node.attributes) {
if (attribute.type === 'LetDirective') { if (attribute.type === 'LetDirective') {
context.state.template.push( context.state.template.push(
t_statement( /** @type {import('estree').ExpressionStatement} */ (context.visit(attribute))
/** @type {import('estree').ExpressionStatement} */ (context.visit(attribute))
)
); );
} }
} }
const block = /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment)); const block = /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment));
context.state.template.push(t_statement(block)); context.state.template.push(block);
}, },
TitleElement(node, context) { TitleElement(node, context) {
const state = context.state; const state = context.state;
@ -1720,9 +1693,6 @@ const template_visitors = {
state.init.push(...serialize_template(inner_state.template, b.id('title'))); state.init.push(...serialize_template(inner_state.template, b.id('title')));
}, },
SlotElement(node, context) { SlotElement(node, context) {
const state = context.state;
state.template.push(block_open);
/** @type {import('estree').Property[]} */ /** @type {import('estree').Property[]} */
const props = []; const props = [];
@ -1767,15 +1737,13 @@ const template_visitors = {
: b.thunk(/** @type {import('estree').BlockStatement} */ (context.visit(node.fragment))); : b.thunk(/** @type {import('estree').BlockStatement} */ (context.visit(node.fragment)));
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))); context.state.template.push(block_open, b.stmt(slot), block_close);
state.template.push(block_close);
}, },
SvelteHead(node, context) { SvelteHead(node, context) {
const state = context.state;
const block = /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment)); const block = /** @type {import('estree').BlockStatement} */ (context.visit(node.fragment));
state.template.push( context.state.template.push(
t_statement(b.stmt(b.call('$.head', b.id('$$payload'), b.arrow([b.id('$$payload')], block)))) b.stmt(b.call('$.head', b.id('$$payload'), b.arrow([b.id('$$payload')], block)))
); );
}, },
// @ts-ignore: need to extract this out somehow // @ts-ignore: need to extract this out somehow

@ -42,7 +42,7 @@ export interface ComponentServerTransformState extends ServerTransformState {
readonly hoisted: Array<Statement | ModuleDeclaration>; readonly hoisted: Array<Statement | ModuleDeclaration>;
/** The SSR template */ /** The SSR template */
readonly template: Template[]; readonly template: Array<Statement | Expression>;
readonly metadata: { readonly metadata: {
namespace: Namespace; namespace: Namespace;
}; };

Loading…
Cancel
Save