diff --git a/packages/svelte/src/index-server.js b/packages/svelte/src/index-server.js index ab2258ac5f..e5039cf150 100644 --- a/packages/svelte/src/index-server.js +++ b/packages/svelte/src/index-server.js @@ -2,7 +2,6 @@ import { current_component } from './internal/server/context.js'; import { noop } from './internal/shared/utils.js'; import * as e from './internal/server/errors.js'; -import { STALE_REACTION } from '#client/constants'; /** @param {() => void} fn */ export function onDestroy(fn) { @@ -36,20 +35,7 @@ export function unmount() { export async function tick() {} -/** @type {AbortController | null} */ -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 { getAbortSignal } from './internal/server/abort-signal.js'; export { getAllContexts, getContext, hasContext, setContext } from './internal/server/context.js'; diff --git a/packages/svelte/src/internal/server/abort-signal.js b/packages/svelte/src/internal/server/abort-signal.js new file mode 100644 index 0000000000..4e44254c5d --- /dev/null +++ b/packages/svelte/src/internal/server/abort-signal.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; +} diff --git a/packages/svelte/src/internal/server/index.js b/packages/svelte/src/internal/server/index.js index 2ca85fff44..ceb516ebb0 100644 --- a/packages/svelte/src/internal/server/index.js +++ b/packages/svelte/src/internal/server/index.js @@ -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 { reset_elements } from './dev.js'; import { Payload } from './payload.js'; +import { abort } from './abort-signal.js'; // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2 // https://infra.spec.whatwg.org/#noncharacter @@ -66,50 +67,54 @@ export let on_destroy = []; * @returns {RenderOutput} */ 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; - on_destroy = []; - payload.out += BLOCK_OPEN; + const prev_on_destroy = on_destroy; + on_destroy = []; + payload.out += BLOCK_OPEN; - let reset_reset_element; + let reset_reset_element; - if (DEV) { - // prevent parent/child element state being corrupted by a bad render - reset_reset_element = reset_elements(); - } + if (DEV) { + // prevent parent/child element state being corrupted by a bad render + reset_reset_element = reset_elements(); + } - if (options.context) { - push(); - /** @type {Component} */ (current_component).c = options.context; - } + if (options.context) { + push(); + /** @type {Component} */ (current_component).c = options.context; + } - // @ts-expect-error - component(payload, options.props ?? {}, {}, {}); + // @ts-expect-error + component(payload, options.props ?? {}, {}, {}); - if (options.context) { - pop(); - } + if (options.context) { + pop(); + } - if (reset_reset_element) { - reset_reset_element(); - } + if (reset_reset_element) { + reset_reset_element(); + } - payload.out += BLOCK_CLOSE; - for (const cleanup of on_destroy) cleanup(); - on_destroy = prev_on_destroy; + payload.out += BLOCK_CLOSE; + for (const cleanup of on_destroy) cleanup(); + 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) { - head += ``; - } + for (const { hash, code } of payload.css) { + head += ``; + } - return { - head, - html: payload.out, - body: payload.out - }; + return { + head, + html: payload.out, + body: payload.out + }; + } finally { + abort(); + } } /**