out-of-order-rendering
Rich Harris 2 days ago
parent 20cc1c694d
commit f4b94e57a3

@ -312,9 +312,10 @@ export function EachBlock(node, context) {
declarations.push(b.let(node.index, index));
}
const { has_await } = node.metadata.expression;
const get_collection = b.thunk(collection, has_await);
const thunk = has_await ? b.thunk(b.call('$.get', b.id('$$collection'))) : get_collection;
const is_async = node.metadata.expression.is_async();
const get_collection = b.thunk(collection, node.metadata.expression.has_await);
const thunk = is_async ? b.thunk(b.call('$.get', b.id('$$collection'))) : get_collection;
const render_args = [b.id('$$anchor'), item];
if (uses_index || collection_id) render_args.push(index);
@ -341,12 +342,13 @@ export function EachBlock(node, context) {
statements.unshift(b.stmt(b.call('$.validate_each_keys', thunk, key_function)));
}
if (has_await) {
if (is_async) {
context.state.init.push(
b.stmt(
b.call(
'$.async',
context.state.node,
node.metadata.expression.blockers(),
b.array([get_collection]),
b.arrow([context.state.node, b.id('$$collection')], b.block(statements))
)

@ -37,7 +37,8 @@ export function HtmlTag(node, context) {
b.call(
'$.async',
context.state.node,
b.array([b.thunk(expression, true)]),
node.metadata.expression.blockers(),
b.array([b.thunk(expression, node.metadata.expression.has_await)]),
b.arrow([context.state.node, b.id('$$html')], b.block([statement]))
)
)

@ -11,10 +11,10 @@ import { build_expression, add_svelte_meta } from './shared/utils.js';
export function KeyBlock(node, context) {
context.state.template.push_comment();
const { has_await } = node.metadata.expression;
const is_async = node.metadata.expression.is_async();
const expression = build_expression(context, node.expression, node.metadata.expression);
const key = b.thunk(has_await ? b.call('$.get', b.id('$$key')) : expression);
const key = b.thunk(is_async ? b.call('$.get', b.id('$$key')) : expression);
const body = /** @type {Expression} */ (context.visit(node.fragment));
let statement = add_svelte_meta(
@ -23,12 +23,13 @@ export function KeyBlock(node, context) {
'key'
);
if (has_await) {
if (is_async) {
statement = b.stmt(
b.call(
'$.async',
context.state.node,
b.array([b.thunk(expression, true)]),
node.metadata.expression.blockers(),
b.array([b.thunk(expression, node.metadata.expression.has_await)]),
b.arrow([context.state.node, b.id('$$key')], b.block([statement]))
)
);

@ -272,12 +272,25 @@ function transform_body(program, context) {
context.visit(b.var(s.node.id, s.node.init))
);
if (visited.declarations.length === 1) {
return b.thunk(
b.assignment('=', s.node.id, visited.declarations[0].init ?? b.void0),
s.has_await
);
}
// if we have multiple declarations, it indicates destructuring
return b.thunk(
b.block([
b.var(visited.declarations[0].id, visited.declarations[0].init),
...visited.declarations
.slice(1)
.map((d) => b.stmt(b.assignment('=', d.id, d.init ?? b.void0)))
]),
s.has_await
);
}
if (s.node.type === 'ClassDeclaration') {
return b.thunk(
b.assignment(

@ -93,10 +93,10 @@ export function SvelteElement(node, context) {
);
}
const { has_await } = node.metadata.expression;
const is_async = node.metadata.expression.is_async();
const expression = /** @type {Expression} */ (context.visit(node.tag));
const get_tag = b.thunk(has_await ? b.call('$.get', b.id('$$tag')) : expression);
const get_tag = b.thunk(is_async ? b.call('$.get', b.id('$$tag')) : expression);
/** @type {Statement[]} */
const inner = inner_context.state.init;
@ -139,13 +139,14 @@ export function SvelteElement(node, context) {
)
);
if (has_await) {
if (is_async) {
context.state.init.push(
b.stmt(
b.call(
'$.async',
context.state.node,
b.array([b.thunk(expression, true)]),
node.metadata.expression.blockers(),
b.array([b.thunk(expression, node.metadata.expression.has_await)]),
b.arrow([context.state.node, b.id('$$tag')], b.block(statements))
)
)

@ -56,10 +56,8 @@ export function flatten(blockers, sync, async, fn) {
var was_hydrating = hydrating;
Promise.all(blockers).then(() => {
restore();
const result = Promise.all(async.map((expression) => async_derived(expression)))
function run() {
Promise.all(async.map((expression) => async_derived(expression)))
.then((result) => {
restore();
@ -82,11 +80,22 @@ export function flatten(blockers, sync, async, fn) {
.catch((error) => {
invoke_error_boundary(error, parent);
});
}
unset_context();
if (blockers.length > 0) {
Promise.all(blockers).then(() => {
restore();
return result;
try {
return run();
} finally {
batch?.deactivate();
unset_context();
}
});
} else {
run();
}
}
/**
@ -274,7 +283,8 @@ export async function async_body(anchor, fn) {
export function run(thunks) {
const restore = capture();
let promise = Promise.resolve();
// let promise = Promise.resolve();
let promise = new Promise((f) => Batch.enqueue(() => f(undefined)));
var boundary = get_boundary();
var batch = /** @type {Batch} */ (current_batch);

@ -34,7 +34,7 @@ import * as e from '../errors.js';
import { legacy_mode_flag, tracing_mode_flag } from '../../flags/index.js';
import { get_stack, tag_proxy } from '../dev/tracing.js';
import { component_context, is_runes } from '../context.js';
import { Batch, eager_block_effects, schedule_effect } from './batch.js';
import { Batch, current_batch, eager_block_effects, schedule_effect } from './batch.js';
import { proxy } from '../proxy.js';
import { execute_derived } from './deriveds.js';

Loading…
Cancel
Save