got the extra children to go away

pull/16762/head
S. Elliott Johnson 3 days ago
parent 0e5eeb7e45
commit 8773216e01

@ -41,9 +41,12 @@ export function AwaitBlock(node, context) {
mark_subtree_dynamic(context.path); mark_subtree_dynamic(context.path);
// this one doesn't get the new state because it still hoists to the existing scope
context.visit(node.expression, { ...context.state, expression: node.metadata.expression }); context.visit(node.expression, { ...context.state, expression: node.metadata.expression });
if (node.metadata.expression.has_await && context.state.fragment) {
context.state.fragment.metadata.is_async = true;
}
if (node.pending) context.visit(node.pending); if (node.pending) context.visit(node.pending);
if (node.then) context.visit(node.then); if (node.then) context.visit(node.then);
if (node.catch) context.visit(node.catch); if (node.catch) context.visit(node.catch);

@ -18,11 +18,11 @@ export function AwaitExpression(node, context) {
} }
if (context.state.fragment) { if (context.state.fragment) {
const len = context.state.fragment.metadata.hoisted_promises.promises.push(node.argument); // const len = context.state.fragment.metadata.hoisted_promises.promises.push(node.argument);
context.state.analysis.hoisted_promises.set( // context.state.analysis.hoisted_promises.set(
node.argument, // node.argument,
b.member(context.state.fragment.metadata.hoisted_promises.id, b.literal(len - 1), true) // b.member(context.state.fragment.metadata.hoisted_promises.id, b.literal(len - 1), true)
); // );
} }
suspend = true; suspend = true;

@ -35,6 +35,11 @@ export function EachBlock(node, context) {
scope: /** @type {Scope} */ (context.state.scope.parent) scope: /** @type {Scope} */ (context.state.scope.parent)
}); });
// TODO it should be impossible to be in the template and not have a fragment...
if (node.metadata.expression.has_await && context.state.fragment) {
context.state.fragment.metadata.is_async = true;
}
context.visit(node.body); context.visit(node.body);
if (node.key) context.visit(node.key); if (node.key) context.visit(node.key);
if (node.fallback) { if (node.fallback) {

@ -12,7 +12,7 @@ export function Fragment(node, context) {
// a child fragment), which is necessary for ensuring that a `SnippetBlock` creates an // 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 // 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 // and it works, so for now I'm doing it like this
node.metadata.is_async = node.metadata.hoisted_promises.promises.length > 0; node.metadata.is_async ||= node.metadata.hoisted_promises.promises.length > 0;
if (node.metadata.hoisted_promises.promises.length === 1) { if (node.metadata.hoisted_promises.promises.length === 1) {
// if there's only one promise in this fragment, we don't need to de-waterfall it // if there's only one promise in this fragment, we don't need to de-waterfall it

@ -22,6 +22,10 @@ export function IfBlock(node, context) {
expression: node.metadata.expression expression: node.metadata.expression
}); });
if (node.metadata.expression.has_await && context.state.fragment) {
context.state.fragment.metadata.is_async = true;
}
context.visit(node.consequent); context.visit(node.consequent);
if (node.alternate) { if (node.alternate) {
context.visit(node.alternate); context.visit(node.alternate);

@ -32,7 +32,7 @@ export class Payload {
type; type;
/** @type {Payload | undefined} */ /** @type {Payload | undefined} */
parent; #parent;
/** /**
* Asynchronous work associated with this payload. `initial` is the promise from the function * Asynchronous work associated with this payload. `initial` is the promise from the function
@ -69,7 +69,7 @@ export class Payload {
constructor(global, local = { select_value: undefined }, parent, type) { constructor(global, local = { select_value: undefined }, parent, type) {
this.global = global; this.global = global;
this.local = { ...local }; this.local = { ...local };
this.parent = parent; this.#parent = parent;
this.type = type ?? parent?.type ?? 'body'; this.type = type ?? parent?.type ?? 'body';
} }
@ -108,6 +108,10 @@ export class Payload {
*/ */
push(content) { push(content) {
if (typeof content === 'function') { if (typeof content === 'function') {
if (this.global.mode === 'sync') {
// TODO more-proper error
throw new Error('Encountered an asynchronous component while rendering synchronously');
}
this.#out.push(content()); this.#out.push(content());
} else { } else {
this.#out.push(content); this.#out.push(content);
@ -148,7 +152,7 @@ export class Payload {
* @returns {number[]} * @returns {number[]}
*/ */
get_path() { get_path() {
return this.parent ? [...this.parent.get_path(), this.parent.#out.indexOf(this)] : []; return this.#parent ? [...this.#parent.get_path(), this.#parent.#out.indexOf(this)] : [];
} }
/** /**
@ -170,7 +174,7 @@ export class Payload {
} }
copy() { copy() {
const copy = new Payload(this.global, this.local, this.parent, this.type); const copy = new Payload(this.global, this.local, this.#parent, this.type);
copy.#out = this.#out.map((item) => (item instanceof Payload ? item.copy() : item)); copy.#out = this.#out.map((item) => (item instanceof Payload ? item.copy() : item));
copy.promises = this.promises; copy.promises = this.promises;
return copy; return copy;

@ -10,18 +10,13 @@ export default function Async_each_fallback_hoisting($$payload) {
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) { for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index]; let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->`); $$payload.push(`<!---->`);
$$payload.push(async () => $.escape(await Promise.reject('This should never be reached'))); $$payload.push(async () => $.escape(await Promise.reject('This should never be reached')));
});
} }
} else { } else {
$$payload.push('<!--[!-->'); $$payload.push('<!--[!-->');
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->`); $$payload.push(`<!---->`);
$$payload.push(async () => $.escape(await Promise.resolve(4))); $$payload.push(async () => $.escape(await Promise.resolve(4)));
});
} }
$$payload.push(`<!--]-->`); $$payload.push(`<!--]-->`);

@ -13,10 +13,8 @@ export default function Async_each_hoisting($$payload) {
for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) { for (let $$index = 0, $$length = each_array.length; $$index < $$length; $$index++) {
let item = each_array[$$index]; let item = each_array[$$index];
$$payload.child(async ($$payload) => {
$$payload.push(`<!---->`); $$payload.push(`<!---->`);
$$payload.push(async () => $.escape(await item)); $$payload.push(async () => $.escape(await item));
});
} }
$$payload.push(`<!--]-->`); $$payload.push(`<!--]-->`);

@ -4,16 +4,10 @@ export default function Async_if_alternate_hoisting($$payload) {
$$payload.child(async ($$payload) => { $$payload.child(async ($$payload) => {
if (await Promise.resolve(false)) { if (await Promise.resolve(false)) {
$$payload.push('<!--[-->'); $$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
$$payload.push(async () => $.escape(await Promise.reject('no no no'))); $$payload.push(async () => $.escape(await Promise.reject('no no no')));
});
} else { } else {
$$payload.push('<!--[!-->'); $$payload.push('<!--[!-->');
$$payload.child(async ($$payload) => {
$$payload.push(async () => $.escape(await Promise.resolve('yes yes yes'))); $$payload.push(async () => $.escape(await Promise.resolve('yes yes yes')));
});
} }
$$payload.push(`<!--]-->`); $$payload.push(`<!--]-->`);

@ -4,16 +4,10 @@ export default function Async_if_hoisting($$payload) {
$$payload.child(async ($$payload) => { $$payload.child(async ($$payload) => {
if (await Promise.resolve(true)) { if (await Promise.resolve(true)) {
$$payload.push('<!--[-->'); $$payload.push('<!--[-->');
$$payload.child(async ($$payload) => {
$$payload.push(async () => $.escape(await Promise.resolve('yes yes yes'))); $$payload.push(async () => $.escape(await Promise.resolve('yes yes yes')));
});
} else { } else {
$$payload.push('<!--[!-->'); $$payload.push('<!--[!-->');
$$payload.child(async ($$payload) => {
$$payload.push(async () => $.escape(await Promise.reject('no no no'))); $$payload.push(async () => $.escape(await Promise.reject('no no no')));
});
} }
$$payload.push(`<!--]-->`); $$payload.push(`<!--]-->`);

Loading…
Cancel
Save