fix(bonjour): keep ciao failure handling extension-owned

This commit is contained in:
Peter Steinberger
2026-04-26 23:29:40 +01:00
parent 0472b6197a
commit c9c0ab3a44
4 changed files with 81 additions and 81 deletions

View File

@@ -48,6 +48,34 @@ describe("bonjour-ciao", () => {
expect(ignoreCiaoUnhandledRejection(new Error("CIAO PROBING CANCELLED"))).toBe(true);
});
it("suppresses wrapped ciao cancellation rejections", () => {
expect(
classifyCiaoUnhandledRejection({
reason: new Error("CIAO ANNOUNCEMENT CANCELLED"),
}),
).toEqual({
kind: "cancellation",
formatted: "CIAO ANNOUNCEMENT CANCELLED",
});
});
it("suppresses aggregate ciao assertion rejections", () => {
expect(
classifyCiaoUnhandledRejection(
new AggregateError([
Object.assign(
new Error("Reached illegal state! IPV4 address change from defined to undefined!"),
{ name: "AssertionError" },
),
]),
),
).toEqual({
kind: "interface-assertion",
formatted:
"AssertionError: Reached illegal state! IPV4 address change from defined to undefined!",
});
});
it("suppresses lower-case string cancellation reasons too", () => {
expect(ignoreCiaoUnhandledRejection("ciao announcement cancelled during cleanup")).toBe(true);
});

View File

@@ -11,17 +11,59 @@ export type CiaoProcessErrorClassification =
| { kind: "interface-assertion"; formatted: string }
| { kind: "netmask-assertion"; formatted: string };
function collectCiaoProcessErrorCandidates(reason: unknown): unknown[] {
const queue: unknown[] = [reason];
const seen = new Set<unknown>();
const candidates: unknown[] = [];
while (queue.length > 0) {
const current = queue.shift();
if (current == null || seen.has(current)) {
continue;
}
seen.add(current);
candidates.push(current);
if (!current || typeof current !== "object") {
continue;
}
const record = current as Record<string, unknown>;
for (const nested of [
record.cause,
record.reason,
record.original,
record.error,
record.data,
]) {
if (nested != null && !seen.has(nested)) {
queue.push(nested);
}
}
if (Array.isArray(record.errors)) {
for (const nested of record.errors) {
if (nested != null && !seen.has(nested)) {
queue.push(nested);
}
}
}
}
return candidates;
}
export function classifyCiaoProcessError(reason: unknown): CiaoProcessErrorClassification | null {
const formatted = formatBonjourError(reason);
const message = formatted.toUpperCase();
if (CIAO_CANCELLATION_MESSAGE_RE.test(message)) {
return { kind: "cancellation", formatted };
}
if (CIAO_INTERFACE_ASSERTION_MESSAGE_RE.test(message)) {
return { kind: "interface-assertion", formatted };
}
if (CIAO_NETMASK_ASSERTION_MESSAGE_RE.test(message)) {
return { kind: "netmask-assertion", formatted };
for (const candidate of collectCiaoProcessErrorCandidates(reason)) {
const formatted = formatBonjourError(candidate);
const message = formatted.toUpperCase();
if (CIAO_CANCELLATION_MESSAGE_RE.test(message)) {
return { kind: "cancellation", formatted };
}
if (CIAO_INTERFACE_ASSERTION_MESSAGE_RE.test(message)) {
return { kind: "interface-assertion", formatted };
}
if (CIAO_NETMASK_ASSERTION_MESSAGE_RE.test(message)) {
return { kind: "netmask-assertion", formatted };
}
}
return null;
}