only dewaterfall when necessary

pull/16757/head
Rich Harris 1 week ago
parent 9a273c6af2
commit 231af6a14b

@ -131,9 +131,6 @@ const visitors = {
ignore_map.set(node, structuredClone(ignore_stack));
const scope = state.scopes.get(node);
if (node.type === 'Fragment') {
node.metadata.hoisted_promises.name = state.scope.generate('promises');
}
next(scope !== undefined && scope !== state.scope ? { ...state, scope } : state);
if (ignores.length > 0) {

@ -7,4 +7,18 @@
*/
export function Fragment(node, context) {
context.next({ ...context.state, fragment: node });
// TODO this indicates whether the fragment contains an `await` expression (not inside
// a child fragment), which is necessary for ensuring that a `SnippetBlock` creates an
// async function in SSR. It feels like this is probably duplicative, but it's late
// and it works, so for now I'm doing it like this
node.metadata.is_async = node.metadata.hoisted_promises.promises.length > 0;
if (node.metadata.hoisted_promises.promises.length > 1) {
node.metadata.hoisted_promises.name = context.state.scope.generate('promises');
} else {
// if there's only one promise in this fragment, we don't need to de-waterfall it
context.state.analysis.hoisted_promises.delete(node.metadata.hoisted_promises.promises[0]);
node.metadata.hoisted_promises.promises.length = 0;
}
}

@ -12,7 +12,8 @@ export function SnippetBlock(node, context) {
let fn = b.function_declaration(
node.expression,
[b.id('$$payload'), ...node.parameters],
/** @type {BlockStatement} */ (context.visit(node.body))
/** @type {BlockStatement} */ (context.visit(node.body)),
node.body.metadata.is_async
);
// @ts-expect-error - TODO remove this hack once $$render_inner for legacy bindings is gone

@ -2,32 +2,21 @@ import * as $ from 'svelte/internal/server';
export default function Async_each_fallback_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve([])];
const each_array = $.ensure_array_like(await promises[0]);
const each_array = $.ensure_array_like(await Promise.resolve([]));
$$payload.child(async ($$payload) => {
if (each_array.length !== 0) {
$$payload.push('<!--[-->');
if (each_array.length !== 0) {
$$payload.push('<!--[-->');
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
const promises_1 = [Promise.reject('This should never be reached')];
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_1[0])}`);
});
}
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.resolve(4)];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_2[0])}`);
});
$$payload.push(`<!---->${$.escape(await Promise.reject('This should never be reached'))}`);
}
} else {
$$payload.push('<!--[!-->');
$$payload.push(`<!---->${$.escape(await Promise.resolve(4))}`);
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -5,22 +5,16 @@ export default function Async_each_hoisting($$payload) {
const first = Promise.resolve(1);
const second = Promise.resolve(2);
const third = Promise.resolve(3);
const promises = [Promise.resolve([first, second, third])];
const each_array = $.ensure_array_like(await promises[0]);
const each_array = $.ensure_array_like(await Promise.resolve([first, second, third]));
$$payload.child(async ($$payload) => {
$$payload.push(`<!--[-->`);
$$payload.push(`<!--[-->`);
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
const promises_1 = [item];
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->${$.escape(await promises_1[0])}`);
});
}
$$payload.push(`<!---->${$.escape(await item)}`);
}
$$payload.push(`<!--]-->`);
});
$$payload.push(`<!--]-->`);
});
}

@ -2,28 +2,14 @@ import * as $ from 'svelte/internal/server';
export default function Async_if_alternate_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve(false)];
$$payload.child(async ($$payload) => {
if (await promises[0]) {
$$payload.push('<!--[-->');
const promises_1 = [Promise.reject('no no no')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_1[0])}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.resolve('yes yes yes')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_2[0])}`);
});
}
$$payload.push(`<!--]-->`);
});
if (await Promise.resolve(false)) {
$$payload.push('<!--[-->');
$$payload.push(`${$.escape(await Promise.reject('no no no'))}`);
} else {
$$payload.push('<!--[!-->');
$$payload.push(`${$.escape(await Promise.resolve('yes yes yes'))}`);
}
$$payload.push(`<!--]-->`);
});
}

@ -2,28 +2,14 @@ import * as $ from 'svelte/internal/server';
export default function Async_if_hoisting($$payload) {
$$payload.child(async ($$payload) => {
const promises = [Promise.resolve(true)];
$$payload.child(async ($$payload) => {
if (await promises[0]) {
$$payload.push('<!--[-->');
const promises_1 = [Promise.resolve('yes yes yes')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_1[0])}`);
});
} else {
$$payload.push('<!--[!-->');
const promises_2 = [Promise.reject('no no no')];
$$payload.child(async ($$payload) => {
$$payload.push(`${$.escape(await promises_2[0])}`);
});
}
$$payload.push(`<!--]-->`);
});
if (await Promise.resolve(true)) {
$$payload.push('<!--[-->');
$$payload.push(`${$.escape(await Promise.resolve('yes yes yes'))}`);
} else {
$$payload.push('<!--[!-->');
$$payload.push(`${$.escape(await Promise.reject('no no no'))}`);
}
$$payload.push(`<!--]-->`);
});
}
Loading…
Cancel
Save