Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error.prepareStackTrace isn't called #49681

Closed
danilobatistaqueiroz opened this issue Sep 17, 2023 · 3 comments
Closed

Error.prepareStackTrace isn't called #49681

danilobatistaqueiroz opened this issue Sep 17, 2023 · 3 comments
Labels
invalid Issues and PRs that are invalid.

Comments

@danilobatistaqueiroz
Copy link

danilobatistaqueiroz commented Sep 17, 2023

Version

20.1.0

Platform

Linux 6.2.0-32-generic #32~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 18 10:40:13 UTC 2 x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

When defining a stacktrace using Error.prepareStackTrace = function(_,stack) {...}
As of node version 20.1.0 the function isn't called anymore.

try {
    var sourceMapSupport = require('source-map-support' + '');
} catch (_) {
    sourceMapSupport = null;
}
function getCaller3Info() {
  if (this === undefined) {
      // Cannot access caller info in 'strict' mode.
      return;
  }
  var obj = {};
  var saveLimit = Error.stackTraceLimit;
  var savePrepare = Error.prepareStackTrace;
  Error.stackTraceLimit = 3;
  Error.prepareStackTrace = function (_, stack) {
      var caller = stack[2];
      if (sourceMapSupport) {
          caller = sourceMapSupport.wrapCallSite(caller);
      }
      obj.file = caller.getFileName();
      obj.line = caller.getLineNumber();
      var func = caller.getFunctionName();
      if (func)
          obj.func = func;
  };
  Error.captureStackTrace(this, arguments.callee);
  this.stack;
  Error.stackTraceLimit = saveLimit;
  Error.prepareStackTrace = savePrepare;
  return obj;
}
console.log(getCaller3Info());

How often does it reproduce? Is there a required condition?

Any Node version after 20.0.0

What is the expected behavior? Why is that the expected behavior?

Function defined in Error.prepareStackTrace would be called.

What do you see instead?

The function isn't called.

Additional information

No response

@bnoordhuis
Copy link
Member

Go to https://v8.dev/docs/stack-trace-api and read the section on Error.prepareStackTrace. Yours is buggy because you don't return anything.

@bnoordhuis bnoordhuis closed this as not planned Won't fix, can't repro, duplicate, stale Sep 17, 2023
@bnoordhuis bnoordhuis added the invalid Issues and PRs that are invalid. label Sep 17, 2023
@trentm
Copy link
Contributor

trentm commented Nov 18, 2023

Go to https://v8.dev/docs/stack-trace-api and read the section on Error.prepareStackTrace. Yours is buggy because you don't return anything.

@bnoordhuis No, that isn't it. In general, returning undefined from Error.prepareStackTrace() is fine.
Also you didn't answer the question. Perhaps you could re-open this issue.

Here is another example script:

console.log(process.version);

var obj = {};
// Starting with node v20.1.0, if the `obj` given to `Error.captureStackTrace`
// is `globalThis`, then a custom `Error.prepareStackTrace` is not called.
var obj = globalThis; // Comment out this line and prepareStackTrace is called.
console.log('obj:', obj);

Error.prepareStackTrace = function (err, stack) {
  console.log('the custom prepareStackTrace was called');
  return 'the stack value';
};
Error.captureStackTrace(obj);

console.log('obj "stack" descriptor:', Object.getOwnPropertyDescriptor(obj, 'stack'));
console.log('obj.stack:', obj.stack);

Running this with Node.js v20.0.0 and the custom Error.prepareStackTrace is called:

% node err-prep-called.js
v20.0.0
obj: <ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Getter/Setter],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Getter/Setter],
  btoa: [Getter/Setter],
  performance: [Getter/Setter],
  fetch: [AsyncFunction: fetch],
  crypto: [Getter]
}
the custom prepareStackTrace was called
obj "stack" descriptor: {
  value: 'the stack value',
  writable: true,
  enumerable: false,
  configurable: true
}
obj.stack: the stack value

However, calling it with v20.1.0 and it is not:

% node err-prep-called.js
v20.1.0
obj: <ref *1> Object [global] {
  global: [Circular *1],
  queueMicrotask: [Function: queueMicrotask],
  clearImmediate: [Function: clearImmediate],
  setImmediate: [Function: setImmediate] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  structuredClone: [Getter/Setter],
  clearInterval: [Function: clearInterval],
  clearTimeout: [Function: clearTimeout],
  setInterval: [Function: setInterval],
  setTimeout: [Function: setTimeout] {
    [Symbol(nodejs.util.promisify.custom)]: [Getter]
  },
  atob: [Getter/Setter],
  btoa: [Getter/Setter],
  performance: [Getter/Setter],
  fetch: [AsyncFunction: fetch],
  crypto: [Getter]
}
obj "stack" descriptor: undefined
obj.stack: undefined

I don't see anything in https://nodejs.org/en/blog/release/v20.1.0 that sticks out that would have changed this behaviour, but I gather this would have been a change in the guts of v8, so perhaps:

I haven't looked at the v8 diff -- I don't know v8 well at all.

If the obj passed in is not globalThis, then it works with both versions:

% node err-prep-called.js
v20.1.0
obj: {}
the custom prepareStackTrace was called
obj "stack" descriptor: {
  value: 'the stack value',
  writable: true,
  enumerable: false,
  configurable: true
}
obj.stack: the stack value

@trentm
Copy link
Contributor

trentm commented Nov 18, 2023

I haven't looked at the v8 diff

Ah, that v8 diff includes: v8/v8@4d08e2d
"[runtime] Make Error.captureStackTrace() a no-op for global object "

So, obviously, that'll be it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
invalid Issues and PRs that are invalid.
Projects
None yet
Development

No branches or pull requests

3 participants