2021-11-08 10:30:36 +01:00
|
|
|
import type { ComponentNode } from "./component_node";
|
2021-11-18 10:44:49 +01:00
|
|
|
import type { Fiber } from "./fibers";
|
2021-11-08 10:30:36 +01:00
|
|
|
|
2021-11-18 10:44:49 +01:00
|
|
|
// Maps fibers to thrown errors
|
|
|
|
|
export const fibersInError: WeakMap<Fiber, any> = new WeakMap();
|
|
|
|
|
export const nodeErrorHandlers: WeakMap<ComponentNode, ((error: any) => void)[]> = new WeakMap();
|
2021-11-08 10:30:36 +01:00
|
|
|
|
2021-11-18 10:44:49 +01:00
|
|
|
function _handleError(node: ComponentNode | null, error: any, isFirstRound = false): boolean {
|
2021-11-08 10:30:36 +01:00
|
|
|
if (!node) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const fiber = node.fiber;
|
|
|
|
|
if (fiber) {
|
|
|
|
|
fibersInError.set(fiber, error);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const errorHandlers = nodeErrorHandlers.get(node);
|
|
|
|
|
if (errorHandlers) {
|
2021-11-16 16:26:39 +01:00
|
|
|
if (isFirstRound && fiber) {
|
2021-11-08 10:30:36 +01:00
|
|
|
fiber.root.counter--;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let propagate = true;
|
|
|
|
|
for (const h of errorHandlers) {
|
|
|
|
|
try {
|
|
|
|
|
h(error);
|
|
|
|
|
propagate = false;
|
|
|
|
|
} catch (e) {
|
|
|
|
|
error = e as Error;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (propagate) {
|
|
|
|
|
return _handleError(node.parent, error);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
} else {
|
|
|
|
|
return _handleError(node.parent, error);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-18 10:44:49 +01:00
|
|
|
type ErrorParams = { error: any } & ({ node: ComponentNode } | { fiber: Fiber });
|
|
|
|
|
export function handleError(params: ErrorParams) {
|
|
|
|
|
const error = params.error;
|
|
|
|
|
const node = "node" in params ? params.node : params.fiber.node;
|
|
|
|
|
const fiber = "fiber" in params ? params.fiber : node.fiber!;
|
|
|
|
|
|
2021-11-08 10:30:36 +01:00
|
|
|
fibersInError.set(fiber.root, error);
|
|
|
|
|
|
2021-11-17 11:06:24 +01:00
|
|
|
const handled = _handleError(node, error, true);
|
|
|
|
|
if (!handled) {
|
2021-11-08 10:30:36 +01:00
|
|
|
try {
|
|
|
|
|
node.app.destroy();
|
|
|
|
|
} catch (e) {}
|
|
|
|
|
}
|
2021-11-17 11:06:24 +01:00
|
|
|
return handled;
|
2021-11-08 10:30:36 +01:00
|
|
|
}
|