onerror -> handleError

ssr-error-boundary
Rich Harris 2 days ago
parent 9d298fb54b
commit 2edee3188e

@ -340,9 +340,9 @@ export type MountOptions<Props extends Record<string, any> = Record<string, any>
intro?: boolean;
/**
* A function that transforms errors caught by error boundaries before they are passed to the `failed` snippet.
* This is used by SvelteKit to apply `handleError`. Defaults to the identity function on the client, and to throwing on the server.
* Defaults to the identity function.
*/
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
} & ({} extends Props
? {
/**

@ -59,11 +59,11 @@ var flags = EFFECT_TRANSPARENT | EFFECT_PRESERVED | BOUNDARY_EFFECT;
* @param {TemplateNode} node
* @param {BoundaryProps} props
* @param {((anchor: Node) => void)} children
* @param {((error: unknown) => unknown) | undefined} [onerror_transform]
* @param {((error: unknown) => unknown) | undefined} [transform_error]
* @returns {void}
*/
export function boundary(node, props, children, onerror_transform) {
new Boundary(node, props, children, onerror_transform);
export function boundary(node, props, children, transform_error) {
new Boundary(node, props, children, transform_error);
}
export class Boundary {
@ -73,11 +73,11 @@ export class Boundary {
is_pending = false;
/**
* API-level onerror transform function. Transforms errors before they reach the `failed` snippet.
* API-level handleError transform function. Transforms errors before they reach the `failed` snippet.
* Inherited from parent boundary, or defaults to identity.
* @type {(error: unknown) => unknown}
*/
onerror_transform;
transform_error;
/** @type {TemplateNode} */
#anchor;
@ -146,18 +146,18 @@ export class Boundary {
* @param {TemplateNode} node
* @param {BoundaryProps} props
* @param {((anchor: Node) => void)} children
* @param {((error: unknown) => unknown) | undefined} [onerror_transform]
* @param {((error: unknown) => unknown) | undefined} [transform_error]
*/
constructor(node, props, children, onerror_transform) {
constructor(node, props, children, transform_error) {
this.#anchor = node;
this.#props = props;
this.#children = children;
this.parent = /** @type {Effect} */ (active_effect).b;
// Inherit onerror_transform from parent boundary, or use the provided one, or default to identity
this.onerror_transform =
onerror_transform ?? (this.parent ? this.parent.onerror_transform : (e) => e);
// Inherit transform_error from parent boundary, or use the provided one, or default to identity
this.transform_error =
transform_error ?? (this.parent ? this.parent.transform_error : (e) => e);
this.is_pending = !!this.#props.pending;
@ -522,11 +522,11 @@ export class Boundary {
};
queue_micro_task(() => {
// Run the error through the API-level onerror transform (e.g. SvelteKit's handleError)
// Run the error through the API-level handleError transform (e.g. SvelteKit's handleError)
/** @type {unknown} */
var result;
try {
result = this.onerror_transform(error);
result = this.transform_error(error);
} catch (e) {
invoke_error_boundary(e, this.#effect && this.#effect.parent);
return;
@ -537,7 +537,7 @@ export class Boundary {
typeof result === 'object' &&
typeof (/** @type {any} */ (result).then) === 'function'
) {
// onerror returned a Promise — wait for it
// handleError returned a Promise — wait for it
/** @type {any} */ (result).then(
/** @param {unknown} transformed_error */
(transformed_error) => handle_error_result(transformed_error),

@ -81,7 +81,7 @@ export function mount(component, options) {
* context?: Map<any, any>;
* intro?: boolean;
* recover?: boolean;
* onerror?: (error: unknown) => unknown;
* handleError?: (error: unknown) => unknown;
* } : {
* target: Document | Element | ShadowRoot;
* props: Props;
@ -89,7 +89,7 @@ export function mount(component, options) {
* context?: Map<any, any>;
* intro?: boolean;
* recover?: boolean;
* onerror?: (error: unknown) => unknown;
* handleError?: (error: unknown) => unknown;
* }} options
* @returns {Exports}
*/
@ -160,7 +160,10 @@ const document_listeners = new Map();
* @param {MountOptions} options
* @returns {Exports}
*/
function _mount(Component, { target, anchor, props = {}, events, context, intro = true, onerror }) {
function _mount(
Component,
{ target, anchor, props = {}, events, context, intro = true, handleError }
) {
init_operations();
/** @type {Set<string>} */
@ -243,7 +246,7 @@ function _mount(Component, { target, anchor, props = {}, events, context, intro
pop();
},
onerror
handleError
);
return () => {

@ -56,7 +56,7 @@ export function element(renderer, tag, attributes_fn = noop, children_fn = noop)
* Takes a component and returns an object with `body` and `head` properties on it, which you can use to populate the HTML when server-rendering your app.
* @template {Record<string, any>} Props
* @param {Component<Props> | ComponentType<SvelteComponent<Props>>} component
* @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; csp?: Csp; onerror?: (error: unknown) => unknown }} [options]
* @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; csp?: Csp; handleError?: (error: unknown) => unknown }} [options]
* @returns {RenderOutput}
*/
export function render(component, options = {}) {

@ -52,7 +52,7 @@ export class Renderer {
/**
* If set, this renderer is an error boundary. When async collection
* of the children fails, the failed snippet is rendered instead.
* @type {{ failed: (renderer: Renderer, error: unknown, reset: () => void) => void; onerror: (error: unknown) => unknown } | null}
* @type {{ failed: (renderer: Renderer, error: unknown, reset: () => void) => void; handleError: (error: unknown) => unknown } | null}
*/
#boundary = null;
@ -224,7 +224,7 @@ export class Renderer {
/**
* Render children inside an error boundary. If the children throw and the API-level
* `onerror` transform handles the error (doesn't re-throw), the `failed` snippet is
* `handleError` transform handles the error (doesn't re-throw), the `failed` snippet is
* rendered instead. Otherwise the error propagates.
*
* @param {{ failed?: (renderer: Renderer, error: unknown, reset: () => void) => void }} props
@ -240,7 +240,7 @@ export class Renderer {
if (props.failed) {
child.#boundary = {
failed: props.failed,
onerror: this.global.onerror
handleError: this.global.handleError
};
}
@ -273,7 +273,7 @@ export class Renderer {
if (!failed_snippet) throw error;
const result = this.global.onerror(error);
const result = this.global.handleError(error);
if (result instanceof Promise) {
if (this.global.mode === 'sync') {
@ -684,9 +684,9 @@ export class Renderer {
content.head += boundary_content.head;
content.body += boundary_content.body;
} catch (error) {
const { failed, onerror } = item.#boundary;
const { failed, handleError } = item.#boundary;
let transformed = await onerror(error);
let transformed = await handleError(error);
// Render the failed snippet instead of the partial children content
const failed_renderer = new Renderer(item.global, item);
@ -728,7 +728,7 @@ export class Renderer {
* @template {Record<string, any>} Props
* @param {'sync' | 'async'} mode
* @param {import('svelte').Component<Props>} component
* @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; csp?: Csp; onerror?: (error: unknown) => unknown }} options
* @param {{ props?: Omit<Props, '$$slots' | '$$events'>; context?: Map<any, any>; idPrefix?: string; csp?: Csp; handleError?: (error: unknown) => unknown }} options
* @returns {Renderer}
*/
static #open_render(mode, component, options) {
@ -737,7 +737,7 @@ export class Renderer {
mode,
options.idPrefix ? options.idPrefix + '-' : '',
options.csp,
options.onerror
options.handleError
)
);
@ -851,11 +851,11 @@ export class SSRState {
css = new Set();
/**
* `onerror` transform passed to `render`. Called when an error boundary catches an error.
* `handleError` transform passed to `render`. Called when an error boundary catches an error.
* Throws by default if unset in `render`.
* @type {(error: unknown) => unknown}
*/
onerror;
handleError;
/** @type {{ path: number[], value: string }} */
#title = { path: [], value: '' };
@ -864,14 +864,14 @@ export class SSRState {
* @param {'sync' | 'async'} mode
* @param {string} id_prefix
* @param {Csp} csp
* @param {((error: unknown) => unknown) | undefined} [onerror]
* @param {((error: unknown) => unknown) | undefined} [handleError]
*/
constructor(mode, id_prefix = '', csp = { hash: false }, onerror) {
constructor(mode, id_prefix = '', csp = { hash: false }, handleError) {
this.mode = mode;
this.csp = { ...csp, script_hashes: [] };
this.onerror =
onerror ??
this.handleError =
handleError ??
((error) => {
throw error;
});

@ -17,7 +17,7 @@ export function render<
context?: Map<any, any>;
idPrefix?: string;
csp?: Csp;
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
}
]
: [
@ -27,7 +27,7 @@ export function render<
context?: Map<any, any>;
idPrefix?: string;
csp?: Csp;
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
}
]
): RenderOutput;

@ -101,7 +101,7 @@ export interface RuntimeTest<Props extends Record<string, any> = Record<string,
expect_unhandled_rejections?: boolean;
withoutNormalizeHtml?: boolean | 'only-strip-comments';
recover?: boolean;
onerror?: (error: unknown) => unknown;
handleError?: (error: unknown) => unknown;
}
declare global {
@ -365,7 +365,7 @@ async function run_test_variant(
const render_result = render(SsrSvelteComponent, {
props: config.server_props ?? config.props ?? {},
idPrefix: config.id_prefix,
onerror: config.onerror
handleError: config.handleError
});
const rendered =
variant === 'async-ssr' || (variant === 'hydrate' && compileOptions.experimental?.async)
@ -465,7 +465,7 @@ async function run_test_variant(
props,
intro: config.intro,
recover: config.recover ?? false,
onerror: config.onerror
handleError: config.handleError
});
}
} else {

@ -4,7 +4,7 @@ import { test } from '../../test';
export default test({
mode: ['hydrate', 'async-server', 'client'],
ssrHtml: '<p>caught: error</p>',
onerror: (error) => {
handleError: (error) => {
if (error !== 'catch me') throw 'wrong error object';
return 'error';
},

@ -4,7 +4,7 @@ import { test } from '../../test';
export default test({
mode: ['hydrate', 'async-server', 'client'],
ssrHtml: '<p>caught: error</p>',
onerror: (error) => {
handleError: (error) => {
if (error !== 'catch me') throw 'wrong error object';
return 'error';
},

@ -1,8 +1,8 @@
import { test } from '../../test';
export default test({
// onerror handles the error, but there's no failed snippet.
// handleError handles the error, but there's no failed snippet.
// The error should still propagate because there's nothing to render instead.
onerror: () => 'you will not see me',
handleError: () => 'you will not see me',
error: 'component error'
});

@ -1,6 +1,6 @@
import { test } from '../../test';
export default test({
// No onerror - by default the server throws, so the error should propagate.
// No handleError - by default the server throws, so the error should propagate.
error: 'component error'
});

@ -1,10 +1,10 @@
import { test } from '../../test';
export default test({
// boundary with failed snippet exists, so onerror should transform the error
onerror: (error) => {
// boundary with failed snippet exists, so handleError should transform the error
handleError: (error) => {
if (/** @type {Error} */ (error).message !== 'you are not supposed to see this message') {
return 'wrong object passed to onerror';
return 'wrong object passed to handleError';
}
return 'component error';
}

@ -24,7 +24,7 @@ interface SSRTest extends BaseTest {
error?: string;
csp?: { nonce: string } | { hash: true };
script_hashes?: string[];
onerror?: (error: unknown) => unknown;
handleError?: (error: unknown) => unknown;
}
// TODO remove this shim when we can
@ -86,7 +86,7 @@ const { test, run } = suite_with_variants<SSRTest, 'sync' | 'async', CompileOpti
props: config.props || {},
idPrefix: config.id_prefix,
csp: config.csp,
onerror: config.onerror
handleError: config.handleError
});
rendered = is_async ? await render_result : render_result;
// we need to access these inside the try-catch otherwise errors in the script tag are not caught

@ -339,9 +339,9 @@ declare module 'svelte' {
intro?: boolean;
/**
* A function that transforms errors caught by error boundaries before they are passed to the `failed` snippet.
* This is used by SvelteKit to apply `handleError`. Defaults to the identity function on the client, and to throwing on the server.
* Defaults to the identity function.
*/
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
} & ({} extends Props
? {
/**
@ -547,7 +547,7 @@ declare module 'svelte' {
context?: Map<any, any>;
intro?: boolean;
recover?: boolean;
onerror: (error: unknown) => unknown;
handleError?: (error: unknown) => unknown;
} : {
target: Document | Element | ShadowRoot;
props: Props;
@ -555,7 +555,7 @@ declare module 'svelte' {
context?: Map<any, any>;
intro?: boolean;
recover?: boolean;
onerror?: (error: unknown) => unknown;
handleError?: (error: unknown) => unknown;
}): Exports;
/**
* Unmounts a component that was previously mounted using `mount` or `hydrate`.
@ -2567,7 +2567,7 @@ declare module 'svelte/server' {
context?: Map<any, any>;
idPrefix?: string;
csp?: Csp;
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
}
]
: [
@ -2577,7 +2577,7 @@ declare module 'svelte/server' {
context?: Map<any, any>;
idPrefix?: string;
csp?: Csp;
onerror?: (error: unknown) => unknown | Promise<unknown>;
handleError?: (error: unknown) => unknown | Promise<unknown>;
}
]
): RenderOutput;

Loading…
Cancel
Save