mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-23 01:32:55 +02:00
91 lines
3.6 KiB
TypeScript
91 lines
3.6 KiB
TypeScript
import { ScriptDeath } from "../Netscript/ScriptDeath";
|
|
import type { WorkerScript } from "../Netscript/WorkerScript";
|
|
import { dialogBoxCreate } from "../ui/React/DialogBox";
|
|
import { getErrorMessageWithStackAndCause } from "./ErrorHelper";
|
|
|
|
import { DisplayError } from "../ErrorHandling/DisplayError";
|
|
|
|
/** Generate an error dialog when workerscript is known */
|
|
export function handleUnknownError(e: unknown, ws: WorkerScript | null = null, initialText = "") {
|
|
if (e instanceof ScriptDeath) {
|
|
// No dialog for ScriptDeath
|
|
return;
|
|
}
|
|
if (ws && typeof e === "string") {
|
|
/**
|
|
* - Attempt to strip out the error type, if present.
|
|
* - Extract error text by skipping:
|
|
* - Error type
|
|
* - Script name and PID
|
|
*
|
|
* Error example:
|
|
* "RUNTIME ERROR\ntest.js@home (PID - 1)\n\ngetServer: Invalid hostname: 'invalid'\n\nStack:\ntest.js:L5@main"
|
|
*
|
|
* - errorType: "RUNTIME"
|
|
* - errorText: "getServer: Invalid hostname: 'invalid'\n\nStack:\ntest.js:L5@main"
|
|
*/
|
|
const errorType = e.match(/^(\w+) ERROR/)?.[1];
|
|
if (errorType) {
|
|
const errorText = e.split(/\n/).slice(3).join("\n");
|
|
DisplayError(initialText + errorText, errorType, ws);
|
|
return;
|
|
}
|
|
DisplayError(initialText + e, "RUNTIME", ws);
|
|
} else if (e instanceof SyntaxError) {
|
|
DisplayError(initialText + getErrorMessageWithStackAndCause(e), "SYNTAX", ws);
|
|
} else if (e instanceof Error) {
|
|
// Ignore any cancellation errors from Monaco that get here
|
|
if (e.name === "Canceled" && e.message === "Canceled") {
|
|
return;
|
|
}
|
|
if (ws) {
|
|
console.error(`An error was thrown in your script. Hostname: ${ws.hostname}, script name: ${ws.name}.`);
|
|
}
|
|
/**
|
|
* If e is an instance of Error, we print it to the console. This is especially useful when debugging a TypeScript
|
|
* script. The stack trace in the error popup contains only the trace of the transpiled code. Even with a source
|
|
* map, parsing it to get the relevant info from the original TypeScript file is complicated. The built-in developer
|
|
* tool of browsers will do that for us if we print the error to the console.
|
|
*/
|
|
console.error(e);
|
|
DisplayError(initialText + getErrorMessageWithStackAndCause(e), getErrorType(e.stack) ?? "RUNTIME", ws);
|
|
} else if (typeof e !== "string") {
|
|
console.error("Unexpected error:", e);
|
|
const msg = `Unexpected type of error thrown. This error was likely thrown manually within a script.
|
|
Error has been logged to the console.\n\nType of error: ${typeof e}\nValue of error: ${e}`;
|
|
DisplayError(msg, "UNKNOWN", ws);
|
|
}
|
|
}
|
|
|
|
/** Use this handler to handle the error when we call getSaveData function or getSaveInfo function */
|
|
export function handleGetSaveDataInfoError(error: unknown, fromGetSaveInfo = false) {
|
|
console.error(error);
|
|
let errorMessage = `Cannot get save ${fromGetSaveInfo ? "info" : "data"}. Error: ${error}.`;
|
|
if (error instanceof RangeError) {
|
|
errorMessage += " This may be because the save data is too large.";
|
|
}
|
|
if (error instanceof Error && error.stack) {
|
|
errorMessage += `\nStack:\n${error.stack}`;
|
|
}
|
|
dialogBoxCreate(errorMessage);
|
|
}
|
|
|
|
function getErrorType(e = ""): string | undefined {
|
|
if (e.toLowerCase().includes("typeerror")) {
|
|
return "TYPE";
|
|
}
|
|
if (e.toLowerCase().includes("syntaxerror")) {
|
|
return "SYNTAX";
|
|
}
|
|
if (e.toLowerCase().includes("referenceerror")) {
|
|
return "REFERENCE";
|
|
}
|
|
if (e.toLowerCase().includes("rangeerror")) {
|
|
return "RANGE";
|
|
}
|
|
|
|
// Check if the first line contains an error type
|
|
const match = e.match(/^\s*([A-Z]+)\s+ERROR/);
|
|
return match?.[1];
|
|
}
|