bitburner-official / bitburner-src

Bitburner source code.
Other
837 stars 273 forks source link

MISC: Add error cause to exceptionAlert and Recovery mode #1772

Closed catloversg closed 1 week ago

catloversg commented 1 week ago

Let's check this code:

function throw1() {
  throw new Error("throw1");
}

function throw2() {
  throw new Error("throw2");
}

function test() {
  try {
    if (Date.now() % 2 === 0) {
      throw1();
    } else {
      throw2();
    }
  } catch (e) {
    throw new Error("test", { cause: e });
  }
}

/** @param {NS} ns */
export async function main(ns) {
  console.clear();
  try {
    test();
  } catch (e) {
    console.log(String(e));
    console.log(String(e.stack));
    console.log(String(e.cause.stack));
  }
}

Example output:

Error: test
Error: test
    at test (a.js:17:11)
    at main (a.js:25:5)
    at startNetscript2Script (NetscriptWorker.ts:87:9)
Error: throw1
    at throw1 (a.js:2:9)
    at test (a.js:12:7)
    at main (a.js:25:5)
    at startNetscript2Script (NetscriptWorker.ts:87:9)
Error: test
Error: test
    at test (a.js:17:11)
    at main (a.js:25:5)
    at startNetscript2Script (NetscriptWorker.ts:87:9)
Error: throw2
    at throw2 (a.js:6:9)
    at test (a.js:14:7)
    at main (a.js:25:5)
    at startNetscript2Script (NetscriptWorker.ts:87:9)

Without e.cause, we cannot know the root cause (was the error thrown by throw1 or throw2?). This PR adds the error.cause to relevant error reporting UI.

Screenshots: Capture1 Capture2

d0sboots commented 1 week ago

Before you decide on this, test the result of error.toString(), which IIRC is different than String(error). You'll also want to look at the results on both Chrome and Firefox, since they have distinctly different error logging.

catloversg commented 1 week ago

Test code:

/** @param {NS} ns */
export async function main(ns) {
  ns.clearLog();
  const error1 = new Error("error1");
  const error2 = new Error("error2", { cause: error1 });
  const error3 = "error3";
  ns.print(`error1: String constructor: ${String(error1)}`);
  ns.print(`error2: String constructor: ${String(error2)}`);
  ns.print(`error3: String constructor: ${String(error3)}`);
  ns.print(`error1: toString(): ${error1.toString()}`);
  ns.print(`error2: toString(): ${error2.toString()}`);
  ns.print(`error3: toString(): ${error3.toString()}`);
}

Chrome:

error1: String constructor: Error: error1
error2: String constructor: Error: error2
error3: String constructor: error3
error1: toString(): Error: error1
error2: toString(): Error: error2
error3: toString(): error3

Firefox:

error1: String constructor: Error: error1
error2: String constructor: Error: error2
error3: String constructor: error3
error1: toString(): Error: error1
error2: toString(): Error: error2
error3: toString(): error3

The difference between Chrome and Firefox shows up when we use stack and other non-standard properties (e.g., columnNumber, fileName, lineNumber).

/** @param {NS} ns */
export async function main(ns) {
  ns.clearLog();
  const error1 = new Error("error1");
  const error2 = new Error("error2", { cause: error1 });
  ns.print(`error1.stack: ${error1.stack}`);
  ns.print(`error2.stack: ${error2.stack}`);
}

Chrome:

error1.stack: Error: error1
    at main (home/a.js:4:18)
    at startNetscript2Script (webpack://bitburner/./src/NetscriptWorker.ts?:87:9)
error2.stack: Error: error2
    at main (home/a.js:5:18)
    at startNetscript2Script (webpack://bitburner/./src/NetscriptWorker.ts?:87:9)

Firefox:

error1.stack: main@home/a.js:4:18
startNetscript2Script@webpack://bitburner/./src/NetscriptWorker.ts?:87:9
async*createAndAddWorkerScript@webpack://bitburner/./src/NetscriptWorker.ts?:343:142
startWorkerScript@webpack://bitburner/./src/NetscriptWorker.ts?:297:31
run@webpack://bitburner/./src/ui/React/LogBoxManager.tsx?:225:74
callCallback@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3945:14
invokeGuardedCallbackDev@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3994:16
invokeGuardedCallback@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:4056:31
invokeGuardedCallbackAndCatchFirstError@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:4070:25
executeDispatch@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8243:42
processDispatchQueueItemsInOrder@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8275:22
processDispatchQueue@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8288:37
dispatchEventsForPlugins@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8299:23
dispatchEventForPluginEventSystem/<@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8508:12
batchedEventUpdates$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:22391:12
batchedEventUpdates@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3745:12
dispatchEventForPluginEventSystem@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8507:22
attemptToDispatchEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:6005:36
dispatchEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:5924:41
unstable_runWithPriority@webpack://bitburner/./node_modules/scheduler/cjs/scheduler.development.js?:468:12
runWithPriority$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:11276:10
discreteUpdates$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:22408:14
discreteUpdates@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3756:12
dispatchDiscreteEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:5889:18
EventListener.handleEvent*addEventBubbleListener@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:6011:10
addTrappedEventListener@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8411:29
listenToNativeEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8374:28
listenToAllSupportedEvents/<@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8326:28
listenToAllSupportedEvents@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8324:21
createRootImpl@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25882:31
ReactDOMBlockingRoot@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25830:24
createLegacyRoot@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25895:10
legacyCreateRootFromDOMContainer@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25976:10
legacyRenderSubtreeIntoContainer@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:26002:44
render@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:26098:10
@webpack://bitburner/./src/index.tsx?:18:40
./src/index.tsx@https://bitburner.local/legacy/dist/main.bundle.js:7167:1
__webpack_require__@https://bitburner.local/legacy/dist/main.bundle.js:9442:42
__webpack_exports__<@https://bitburner.local/legacy/dist/main.bundle.js:9789:108
__webpack_require__.O@https://bitburner.local/legacy/dist/main.bundle.js:9484:23
@https://bitburner.local/legacy/dist/main.bundle.js:9790:53
@https://bitburner.local/legacy/dist/main.bundle.js:9792:12
error2.stack: main@home/a.js:5:18
startNetscript2Script@webpack://bitburner/./src/NetscriptWorker.ts?:87:9
async*createAndAddWorkerScript@webpack://bitburner/./src/NetscriptWorker.ts?:343:142
startWorkerScript@webpack://bitburner/./src/NetscriptWorker.ts?:297:31
run@webpack://bitburner/./src/ui/React/LogBoxManager.tsx?:225:74
callCallback@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3945:14
invokeGuardedCallbackDev@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3994:16
invokeGuardedCallback@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:4056:31
invokeGuardedCallbackAndCatchFirstError@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:4070:25
executeDispatch@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8243:42
processDispatchQueueItemsInOrder@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8275:22
processDispatchQueue@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8288:37
dispatchEventsForPlugins@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8299:23
dispatchEventForPluginEventSystem/<@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8508:12
batchedEventUpdates$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:22391:12
batchedEventUpdates@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3745:12
dispatchEventForPluginEventSystem@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8507:22
attemptToDispatchEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:6005:36
dispatchEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:5924:41
unstable_runWithPriority@webpack://bitburner/./node_modules/scheduler/cjs/scheduler.development.js?:468:12
runWithPriority$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:11276:10
discreteUpdates$1@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:22408:14
discreteUpdates@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:3756:12
dispatchDiscreteEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:5889:18
EventListener.handleEvent*addEventBubbleListener@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:6011:10
addTrappedEventListener@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8411:29
listenToNativeEvent@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8374:28
listenToAllSupportedEvents/<@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8326:28
listenToAllSupportedEvents@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:8324:21
createRootImpl@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25882:31
ReactDOMBlockingRoot@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25830:24
createLegacyRoot@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25895:10
legacyCreateRootFromDOMContainer@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:25976:10
legacyRenderSubtreeIntoContainer@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:26002:44
render@webpack://bitburner/./node_modules/react-dom/cjs/react-dom.development.js?:26098:10
@webpack://bitburner/./src/index.tsx?:18:40
./src/index.tsx@https://bitburner.local/legacy/dist/main.bundle.js:7167:1
__webpack_require__@https://bitburner.local/legacy/dist/main.bundle.js:9442:42
__webpack_exports__<@https://bitburner.local/legacy/dist/main.bundle.js:9789:108
__webpack_require__.O@https://bitburner.local/legacy/dist/main.bundle.js:9484:23
@https://bitburner.local/legacy/dist/main.bundle.js:9790:53
@https://bitburner.local/legacy/dist/main.bundle.js:9792:12

Some non-standard properties are implemented by only Firefox (e.g., columnNumber, fileName, lineNumber).

d0sboots commented 1 week ago

You get a nicely formatted error with both the message, stack, and cause, if you directly console. log an error, but I guess there's no simple and portable way to recreate that as a string. Pity.

d0sboots commented 1 week ago

I guess that other function turned out not to be relevant?

catloversg commented 1 week ago

I checked that code (errorMessage in src\Netscript\ErrorMessages.ts), but I don't think we should merge the new function parseUnknownError and related code with it. Those parts are used for different purposes: