Skip to content

intent to implement - rework of stack trace decorationΒ #21958

@devsnek

Description

@devsnek

This is an attempt to finally fix the inconsistent stack decoration in node core... hopefully future-facing enough for everyone.

the final code might not be js but the logic will look something like this:

  // Called for every stack trace in the isolate.
  // more consistency as a platform and no more
  // calling decorateErrorStack which
  // is super slow and inconsistent.
  // Using the V8 callback also means we don't need
  // to store the state of whether an exception has
  // been decorated, V8 does it for us.
  setPrepareStackTraceCallback(
    (global, shouldNotDecorate, safeToString, error, frames, message) => {

      // V8 engine prepareStackTrace polyfill
      // To be buffer-constructor-style-deprecated
      // if/when ECMA262 error stacks API is finalized.
      // Being able to explicitly bail here means we don't
      // run into double-decoration issues, like with my last
      // attempt to fix stack decoration.
      if (global.Error !== undefined &&
          typeof global.Error.prepareStackTrace === 'function') {
        return global.Error.prepareStackTrace(error, frames);
      }

      const errorString = safeToString(error);

      // checks for Symbol.for('node.error.decorate') === false
      // or an internal weakset for core things (iirc there were one
      // or two places where we disable the arrow so i threw this in)
      if (shouldNotDecorate(error)) {
        return `${errorString}\n    at ${frames.join('\n    at ')}`;
      }

      const [
        sourceLine,
        resourceName,
        lineNumber,
        startColumn,
        endColumn,
      ] = message;

      // same output we have now
      return `${resourceName}:${lineNumber}
${sourceLine}
${' '.repeat(startColumn)}${'^'.repeat(endColumn - startColumn)}
${errorString}
    at ${frames.join('\n    at ')}`;
});

i have a patch here (https://chromium-review.googlesource.com/c/v8/v8/+/1119768) to implement the API callback in V8 (and after that lands I have another patch lined up to make v8::StackTrace movable to js-land) but before any of that happens V8 wants to know we will actually use this.

The only thing not handled here is when node has an uncaught non-error exception:

node/src/node.cc

Lines 976 to 985 in 811598b

if (!can_set_arrow || (mode == FATAL_ERROR && !err_obj->IsNativeError())) {
if (env->printed_error())
return;
Mutex::ScopedLock lock(process_mutex);
env->set_printed_error(true);
uv_tty_reset_mode();
PrintErrorString("\n%s", arrow);
return;
}
but i think we can still make that work if we really want to (i would argue that we shouldn't)

/cc @hashseed @schuay @addaleax @Trott

Metadata

Metadata

Assignees

No one assigned

    Labels

    errorsIssues and PRs related to JavaScript errors originated in Node.js core.v8 engineIssues and PRs related to the V8 dependency.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions