abort synchronously in SSR

pull/16266/head
Rich Harris 3 months ago
parent c4a948def3
commit 93125942d7

@ -2,7 +2,6 @@
import { current_component } from './internal/server/context.js'; import { current_component } from './internal/server/context.js';
import { noop } from './internal/shared/utils.js'; import { noop } from './internal/shared/utils.js';
import * as e from './internal/server/errors.js'; import * as e from './internal/server/errors.js';
import { STALE_REACTION } from '#client/constants';
/** @param {() => void} fn */ /** @param {() => void} fn */
export function onDestroy(fn) { export function onDestroy(fn) {
@ -36,20 +35,7 @@ export function unmount() {
export async function tick() {} export async function tick() {}
/** @type {AbortController | null} */ export { getAbortSignal } from './internal/server/abort-signal.js';
let controller = null;
export function getAbortSignal() {
if (controller === null) {
const c = (controller = new AbortController());
queueMicrotask(() => {
c.abort(STALE_REACTION);
controller = null;
});
}
return controller.signal;
}
export { getAllContexts, getContext, hasContext, setContext } from './internal/server/context.js'; export { getAllContexts, getContext, hasContext, setContext } from './internal/server/context.js';

@ -0,0 +1,15 @@
import { STALE_REACTION } from '#client/constants';
/** @type {AbortController | null} */
export let controller = null;
export function abort() {
if (controller !== null) {
controller.abort(STALE_REACTION);
controller = null;
}
}
export function getAbortSignal() {
return (controller ??= new AbortController()).signal;
}

@ -18,6 +18,7 @@ import { validate_store } from '../shared/validate.js';
import { is_boolean_attribute, is_raw_text_element, is_void } from '../../utils.js'; import { is_boolean_attribute, is_raw_text_element, is_void } from '../../utils.js';
import { reset_elements } from './dev.js'; import { reset_elements } from './dev.js';
import { Payload } from './payload.js'; import { Payload } from './payload.js';
import { abort } from './abort-signal.js';
// https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
// https://infra.spec.whatwg.org/#noncharacter // https://infra.spec.whatwg.org/#noncharacter
@ -66,50 +67,54 @@ export let on_destroy = [];
* @returns {RenderOutput} * @returns {RenderOutput}
*/ */
export function render(component, options = {}) { export function render(component, options = {}) {
const payload = new Payload(options.idPrefix ? options.idPrefix + '-' : ''); try {
const payload = new Payload(options.idPrefix ? options.idPrefix + '-' : '');
const prev_on_destroy = on_destroy; const prev_on_destroy = on_destroy;
on_destroy = []; on_destroy = [];
payload.out += BLOCK_OPEN; payload.out += BLOCK_OPEN;
let reset_reset_element; let reset_reset_element;
if (DEV) { if (DEV) {
// prevent parent/child element state being corrupted by a bad render // prevent parent/child element state being corrupted by a bad render
reset_reset_element = reset_elements(); reset_reset_element = reset_elements();
} }
if (options.context) { if (options.context) {
push(); push();
/** @type {Component} */ (current_component).c = options.context; /** @type {Component} */ (current_component).c = options.context;
} }
// @ts-expect-error // @ts-expect-error
component(payload, options.props ?? {}, {}, {}); component(payload, options.props ?? {}, {}, {});
if (options.context) { if (options.context) {
pop(); pop();
} }
if (reset_reset_element) { if (reset_reset_element) {
reset_reset_element(); reset_reset_element();
} }
payload.out += BLOCK_CLOSE; payload.out += BLOCK_CLOSE;
for (const cleanup of on_destroy) cleanup(); for (const cleanup of on_destroy) cleanup();
on_destroy = prev_on_destroy; on_destroy = prev_on_destroy;
let head = payload.head.out + payload.head.title; let head = payload.head.out + payload.head.title;
for (const { hash, code } of payload.css) { for (const { hash, code } of payload.css) {
head += `<style id="${hash}">${code}</style>`; head += `<style id="${hash}">${code}</style>`;
} }
return { return {
head, head,
html: payload.out, html: payload.out,
body: payload.out body: payload.out
}; };
} finally {
abort();
}
} }
/** /**

Loading…
Cancel
Save