Rich Harris 8 months ago
parent 3b185b7ba9
commit 5bb5a8f767

@ -159,7 +159,9 @@ export function client_component(analysis, options) {
template_contains_script_tag: false
},
namespace: options.namespace,
bound_contenteditable: false
bound_contenteditable: false,
init_is_async: false,
update_is_async: false
},
events: new Set(),
preserve_whitespace: options.preserveWhitespace,

@ -75,6 +75,9 @@ export interface ComponentClientTransformState extends ClientTransformState {
*/
template_contains_script_tag: boolean;
};
// TODO it would be nice if these were colocated with the arrays they pertain to
init_is_async: boolean;
update_is_async: boolean;
};
readonly preserve_whitespace: boolean;

@ -74,7 +74,9 @@ export function Fragment(node, context) {
template_contains_script_tag: false
},
namespace,
bound_contenteditable: context.state.metadata.bound_contenteditable
bound_contenteditable: context.state.metadata.bound_contenteditable,
init_is_async: false,
update_is_async: false
}
};
@ -190,7 +192,7 @@ export function Fragment(node, context) {
}
if (state.update.length > 0) {
body.push(build_render_statement(state.update));
body.push(build_render_statement(state.update, state.metadata.update_is_async));
}
body.push(...state.after_update);

@ -409,7 +409,9 @@ export function RegularElement(node, context) {
b.block([
...child_state.init,
...element_state.init,
child_state.update.length > 0 ? build_render_statement(child_state.update) : b.empty,
child_state.update.length > 0
? build_render_statement(child_state.update, child_state.metadata.update_is_async)
: b.empty,
...child_state.after_update,
...element_state.after_update
])
@ -418,6 +420,9 @@ export function RegularElement(node, context) {
context.state.init.push(...child_state.init, ...element_state.init);
context.state.update.push(...child_state.update);
context.state.after_update.push(...child_state.after_update, ...element_state.after_update);
context.state.metadata.init_is_async ||= child_state.metadata.init_is_async;
context.state.metadata.update_is_async ||= child_state.metadata.update_is_async;
} else {
context.state.init.push(...element_state.init);
context.state.after_update.push(...element_state.after_update);
@ -627,9 +632,10 @@ function build_element_attribute_update_assignment(
if (attribute.metadata.expression.has_state) {
if (has_call) {
state.init.push(build_update(update));
state.init.push(build_update(update, attribute.metadata.expression.is_async));
} else {
state.update.push(update);
state.metadata.update_is_async ||= attribute.metadata.expression.is_async;
}
return true;
} else {
@ -662,12 +668,16 @@ function build_custom_element_attribute_update_assignment(node_id, attribute, co
if (attribute.metadata.expression.has_state) {
if (has_call) {
state.init.push(build_update(update));
state.init.push(build_update(update, attribute.metadata.expression.is_async));
} else {
state.update.push(update);
state.metadata.update_is_async ||= attribute.metadata.expression.is_async;
}
return true;
} else {
if (attribute.metadata.expression.is_async) {
throw new Error('TODO top-level await');
}
state.init.push(update);
return false;
}

@ -123,7 +123,12 @@ export function SvelteElement(node, context) {
/** @type {Statement[]} */
const inner = inner_context.state.init;
if (inner_context.state.update.length > 0) {
inner.push(build_render_statement(inner_context.state.update));
inner.push(
build_render_statement(
inner_context.state.update,
inner_context.state.metadata.update_is_async
)
);
}
inner.push(...inner_context.state.after_update);
inner.push(

@ -8,7 +8,7 @@ import { build_template_chunk } from './shared/utils.js';
* @param {ComponentContext} context
*/
export function TitleElement(node, context) {
const { has_state, value } = build_template_chunk(
const { has_state, is_async, value } = build_template_chunk(
/** @type {any} */ (node.fragment.nodes),
context.visit,
context.state
@ -18,7 +18,12 @@ export function TitleElement(node, context) {
if (has_state) {
context.state.update.push(statement);
context.state.metadata.update_is_async ||= is_async;
} else {
if (is_async) {
throw new Error('TODO top-level await');
}
context.state.init.push(statement);
}
}

@ -29,6 +29,7 @@ export function build_set_attributes(
state
) {
let has_state = false;
let is_async = false;
/** @type {ObjectExpression['properties']} */
const values = [];
@ -63,6 +64,8 @@ export function build_set_attributes(
}
values.push(b.spread(value));
}
is_async ||= attribute.metadata.expression.is_async;
}
const call = b.call(
@ -80,6 +83,7 @@ export function build_set_attributes(
context.state.init.push(b.let(attributes_id));
const update = b.stmt(b.assignment('=', attributes_id, call));
context.state.update.push(update);
context.state.metadata.update_is_async ||= is_async;
return true;
}
@ -104,7 +108,7 @@ export function build_style_directives(
const state = context.state;
for (const directive of style_directives) {
const { has_state, has_call } = directive.metadata.expression;
const { has_state, has_call, is_async } = directive.metadata.expression;
let value =
directive.value === true
@ -129,10 +133,14 @@ export function build_style_directives(
);
if (!is_attributes_reactive && has_call) {
state.init.push(build_update(update));
state.init.push(build_update(update, is_async));
} else if (is_attributes_reactive || has_state || has_call) {
state.update.push(update);
state.metadata.update_is_async ||= is_async;
} else {
if (is_async) {
throw new Error('TODO top-level await');
}
state.init.push(update);
}
}
@ -154,7 +162,7 @@ export function build_class_directives(
) {
const state = context.state;
for (const directive of class_directives) {
const { has_state, has_call } = directive.metadata.expression;
const { has_state, has_call, is_async } = directive.metadata.expression;
let value = /** @type {Expression} */ (context.visit(directive.expression));
if (has_call) {
@ -167,10 +175,14 @@ export function build_class_directives(
const update = b.stmt(b.call('$.toggle_class', element_id, b.literal(directive.name), value));
if (!is_attributes_reactive && has_call) {
state.init.push(build_update(update));
state.init.push(build_update(update, is_async));
} else if (is_attributes_reactive || has_state || has_call) {
state.update.push(update);
state.metadata.update_is_async ||= is_async;
} else {
if (is_async) {
throw new Error('TODO top-level await');
}
state.init.push(update);
}
}

@ -82,7 +82,11 @@ export function process_children(nodes, initial, is_element, { visit, state }) {
state.init.push(build_update(update, is_async));
} else if (has_state && !within_bound_contenteditable) {
state.update.push(update);
state.metadata.update_is_async ||= is_async;
} else {
if (is_async) {
throw new Error('TODO top-level await');
}
state.init.push(b.stmt(b.assignment('=', b.member(id, 'nodeValue'), value)));
}
}

@ -102,11 +102,12 @@ export function build_update(statement, is_async) {
/**
* @param {Statement[]} update
* @param {boolean} is_async
*/
export function build_render_statement(update) {
export function build_render_statement(update, is_async) {
return update.length === 1
? build_update(update[0])
: b.stmt(b.call('$.template_effect', b.thunk(b.block(update))));
? build_update(update[0], is_async)
: b.stmt(b.call('$.template_effect', b.thunk(b.block(update), is_async)));
}
/**

Loading…
Cancel
Save