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

feat(napi): keep stack traces in a deferred context #1637

Merged
merged 6 commits into from
Jul 15, 2023

Conversation

MarkusJx
Copy link
Contributor

@MarkusJx MarkusJx commented Jul 1, 2023

Currently, stack traces from the calling javascript context are not preserved, when an error is thrown inside a deferred context (e.g. an async fn). Thus, errors thrown inside async functions always look like this:

[Error: Test] { code: 'GenericFailure' }

Which is not very useful when debugging an application.

Current solution

The npm package trace can be used to add the stack traces to the errors thrown in another thread.

Proposal

This comment shows how stack traces can be added to errors thrown inside a deferred context: nodejs/node-addon-api#595 (comment)

Basically, for the stack trace to be preserved, an error needs to be created in the main thread, so the v8 can keep a reference to the calling function. As the error doesn't contain the error message of an error thrown inside the deferred context, the message and status code must be replaced in the error before returning the error back to the javascript process.

This PR adds this functionality as an optional feature, as creating a new error every time a promise is returned to the javascript process seems wasteful. I did some simple performance tests and the performance impact didn't seem to bad (the compute times seemed to be pretty much unchanged, but I think keeping this as an optional feature would be better).

With this feature enabled, stack traces from errors returned by a promise look like this:

Error: Test
    at test (test.js:28:20)
    at Object.<anonymous> (test.js:58:1)
    at Module._compile (node:internal/modules/cjs/loader:1226:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
    at Module.load (node:internal/modules/cjs/loader:1089:32)
    at Module._load (node:internal/modules/cjs/loader:930:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47 {
  code: 'GenericFailure'
}




This feature was originally requested here: MarkusJx/node-java-bridge#77

MarkusJx and others added 3 commits July 1, 2023 11:52
Signed-off-by: Markus <28785953+MarkusJx@users.noreply.github.com>
Signed-off-by: Markus <28785953+MarkusJx@users.noreply.github.com>
@MarkusJx MarkusJx changed the title feat(napi): add feature to keep stack traces in a deferred context feat(napi): keep stack traces in a deferred context Jul 2, 2023
@Brooooooklyn Brooooooklyn self-requested a review July 4, 2023 06:50
@Brooooooklyn Brooooooklyn added the enhancement New feature or request label Jul 4, 2023
@Brooooooklyn
Copy link
Sponsor Member

@MarkusJx could you add a test for it 🤔

@MarkusJx
Copy link
Contributor Author

Sure, but where should I put the tests?

MarkusJx and others added 3 commits July 14, 2023 21:21
Signed-off-by: Markus <28785953+MarkusJx@users.noreply.github.com>
Signed-off-by: Markus <28785953+MarkusJx@users.noreply.github.com>
@MarkusJx
Copy link
Contributor Author

I've added a test for the stack traces from deferred contexts inside examples/napi/__tests__/values.spec.ts.
I've also adapted the code to return errors, which were created inside the JavaScript process, as those errors already contain a stack trace, instead of the replacement error.

Also, I've noticed that cloning an error which contains raw values (errors from the javascript process) causes the process to crash, as the clone will be freed and the original will also be freed, causing the raw values to be freed twice. I think. Don't know if this is a known issue, but I thought I should mention it.

@Brooooooklyn Brooooooklyn merged commit 73a704a into napi-rs:main Jul 15, 2023
45 of 47 checks passed
@MarkusJx MarkusJx deleted the feat/deferred-trace branch July 15, 2023 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants