pull/16797/head
Rich Harris 1 day ago
parent 3744965ac4
commit f911483b9e

@ -28,23 +28,38 @@ export function RegularElement(node, context) {
...context.state, ...context.state,
namespace, namespace,
preserve_whitespace: preserve_whitespace:
context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea' context.state.preserve_whitespace || node.name === 'pre' || node.name === 'textarea',
init: [],
template: []
}; };
const node_is_void = is_void(node.name); const node_is_void = is_void(node.name);
const optimiser = new PromiseOptimiser(); const optimiser = new PromiseOptimiser();
context.state.template.push(b.literal(`<${node.name}`)); state.template.push(b.literal(`<${node.name}`));
const body = build_element_attributes(node, { ...context, state }, optimiser.transform); const body = build_element_attributes(node, { ...context, state }, optimiser.transform);
context.state.template.push(b.literal(node_is_void ? '/>' : '>')); // add `/>` for XHTML compliance state.template.push(b.literal(node_is_void ? '/>' : '>')); // add `/>` for XHTML compliance
if ((node.name === 'script' || node.name === 'style') && node.fragment.nodes.length === 1) { if ((node.name === 'script' || node.name === 'style') && node.fragment.nodes.length === 1) {
context.state.template.push( state.template.push(
b.literal(/** @type {AST.Text} */ (node.fragment.nodes[0]).data), b.literal(/** @type {AST.Text} */ (node.fragment.nodes[0]).data),
b.literal(`</${node.name}>`) b.literal(`</${node.name}>`)
); );
// TODO this is a real edge case, would be good to DRY this out
if (optimiser.expressions.length > 0) {
context.state.template.push(
call_child_renderer(
b.block([optimiser.apply(), ...state.init, ...build_template(state.template)]),
true
)
);
} else {
context.state.init.push(...state.init);
context.state.template.push(...state.template);
}
return; return;
} }
@ -96,7 +111,7 @@ export function RegularElement(node, context) {
select_with_value = true; select_with_value = true;
select_with_value_async ||= spread.metadata.expression.has_await; select_with_value_async ||= spread.metadata.expression.has_await;
const { object, has_await } = build_spread_object( const object = build_spread_object(
node, node,
node.attributes.filter( node.attributes.filter(
(attribute) => (attribute) =>
@ -108,8 +123,6 @@ export function RegularElement(node, context) {
optimiser.transform optimiser.transform
); );
// TODO use has_await
state.template.push( state.template.push(
b.stmt( b.stmt(
b.assignment( b.assignment(
@ -236,4 +249,16 @@ export function RegularElement(node, context) {
if (dev) { if (dev) {
state.template.push(b.stmt(b.call('$.pop_element'))); state.template.push(b.stmt(b.call('$.pop_element')));
} }
if (optimiser.expressions.length > 0) {
context.state.template.push(
call_child_renderer(
b.block([optimiser.apply(), ...state.init, ...build_template(state.template)]),
true
)
);
} else {
context.state.init.push(...state.init);
context.state.template.push(...state.template);
}
} }

@ -219,7 +219,7 @@ export function build_element_attributes(node, context, transform) {
if (node.name === 'option') { if (node.name === 'option') {
// TODO this is all wrong, it inlines the spread twice // TODO this is all wrong, it inlines the spread twice
const { object, has_await } = build_spread_object( const object = build_spread_object(
node, node,
node.attributes.filter( node.attributes.filter(
(attribute) => (attribute) =>
@ -231,8 +231,6 @@ export function build_element_attributes(node, context, transform) {
transform transform
); );
// TODO use has_await?
context.state.template.push( context.state.template.push(
b.call('$.maybe_selected', b.id('$$renderer'), b.member(object, 'value', false, true)) b.call('$.maybe_selected', b.id('$$renderer'), b.member(object, 'value', false, true))
); );
@ -348,8 +346,6 @@ function get_attribute_name(element, attribute) {
* @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform * @param {(expression: Expression, metadata: ExpressionMetadata) => Expression} transform
*/ */
export function build_spread_object(element, attributes, context, transform) { export function build_spread_object(element, attributes, context, transform) {
let has_await = false;
const object = b.object( const object = b.object(
attributes.map((attribute) => { attributes.map((attribute) => {
if (attribute.type === 'Attribute') { if (attribute.type === 'Attribute') {
@ -375,13 +371,16 @@ export function build_spread_object(element, attributes, context, transform) {
return b.prop('init', b.key(name), value); return b.prop('init', b.key(name), value);
} }
has_await ||= attribute.metadata.expression.has_await; return b.spread(
transform(
return b.spread(/** @type {Expression} */ (context.visit(attribute))); /** @type {Expression} */ (context.visit(attribute)),
attribute.metadata.expression
)
);
}) })
); );
return { object, has_await }; return object;
} }
/** /**
@ -445,23 +444,18 @@ function build_element_spread_attributes(
flags |= ELEMENT_IS_INPUT; flags |= ELEMENT_IS_INPUT;
} }
const spread = build_spread_object(element, attributes, context, transform); const object = build_spread_object(element, attributes, context, transform);
const css_hash = const css_hash =
element.metadata.scoped && context.state.analysis.css.hash element.metadata.scoped && context.state.analysis.css.hash
? b.literal(context.state.analysis.css.hash) ? b.literal(context.state.analysis.css.hash)
: undefined; : undefined;
const args = [spread.object, css_hash, classes, styles, flags ? b.literal(flags) : undefined]; const args = [object, css_hash, classes, styles, flags ? b.literal(flags) : undefined];
let call = b.call('$.attributes', ...args); let call = b.call('$.attributes', ...args);
if (spread.has_await) { context.state.template.push(call);
call = b.call('$$renderer.push', b.thunk(call, true));
context.state.template.push(b.stmt(call));
} else {
context.state.template.push(call);
}
} }
/** /**

Loading…
Cancel
Save