async-hydration
Rich Harris 17 hours ago
parent 3744965ac4
commit f911483b9e

@ -28,23 +28,38 @@ export function RegularElement(node, context) {
...context.state,
namespace,
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 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);
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) {
context.state.template.push(
state.template.push(
b.literal(/** @type {AST.Text} */ (node.fragment.nodes[0]).data),
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;
}
@ -96,7 +111,7 @@ export function RegularElement(node, context) {
select_with_value = true;
select_with_value_async ||= spread.metadata.expression.has_await;
const { object, has_await } = build_spread_object(
const object = build_spread_object(
node,
node.attributes.filter(
(attribute) =>
@ -108,8 +123,6 @@ export function RegularElement(node, context) {
optimiser.transform
);
// TODO use has_await
state.template.push(
b.stmt(
b.assignment(
@ -236,4 +249,16 @@ export function RegularElement(node, context) {
if (dev) {
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') {
// TODO this is all wrong, it inlines the spread twice
const { object, has_await } = build_spread_object(
const object = build_spread_object(
node,
node.attributes.filter(
(attribute) =>
@ -231,8 +231,6 @@ export function build_element_attributes(node, context, transform) {
transform
);
// TODO use has_await?
context.state.template.push(
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
*/
export function build_spread_object(element, attributes, context, transform) {
let has_await = false;
const object = b.object(
attributes.map((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);
}
has_await ||= attribute.metadata.expression.has_await;
return b.spread(/** @type {Expression} */ (context.visit(attribute)));
return b.spread(
transform(
/** @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;
}
const spread = build_spread_object(element, attributes, context, transform);
const object = build_spread_object(element, attributes, context, transform);
const css_hash =
element.metadata.scoped && context.state.analysis.css.hash
? b.literal(context.state.analysis.css.hash)
: 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);
if (spread.has_await) {
call = b.call('$$renderer.push', b.thunk(call, true));
context.state.template.push(b.stmt(call));
} else {
context.state.template.push(call);
}
context.state.template.push(call);
}
/**

Loading…
Cancel
Save