Skip to content

Commit 45ef2af

Browse files
Merge branch 'integration/typescript' into PLAT-13698-metadata-delegate
2 parents fd6b092 + b3d5c1d commit 45ef2af

7 files changed

Lines changed: 45 additions & 37 deletions

File tree

packages/core/package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
"./lib/es-utils/keys": "./src/lib/es-utils/keys.js",
1717
"./lib/derecursify": "./src/lib/derecursify.js",
1818
"./lib/callback-runner": "./src/lib/callback-runner.js",
19-
"./lib/node-fallback-stack": "./src/lib/node-fallback-stack.js",
2019
"./lib/path-normalizer": "./src/lib/path-normalizer.js",
2120
"./lib/validators/string-with-length": "./src/lib/validators/string-with-length.js",
2221
"./lib/validators/list-of-functions": "./src/lib/validators/list-of-functions.js",

packages/core/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ export { default as jsonPayload } from './lib/json-payload'
88
export { default as intRange } from './lib/validators/int-range'
99
export { default as isError } from './lib/iserror'
1010
export { default as metadataDelegate } from './lib/metadata-delegate'
11+
export { default as nodeFallbackStack } from './lib/node-fallback-stack'
1112
export { default as runSyncCallbacks } from './lib/sync-callback-runner'
1213

1314
export * from './common'

packages/core/src/lib/node-fallback-stack.js

Lines changed: 0 additions & 28 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// The utilities in this file are used to save the stackframes from a known execution context
2+
// to use when a subsequent error has no stack frames. This happens with a lot of
3+
// node's builtin async callbacks when they return from the native layer with no context
4+
// for example:
5+
//
6+
// fs.readFile('does not exist', (err) => {
7+
// /* node 8 */
8+
// err.stack = "ENOENT: no such file or directory, open 'nope'"
9+
// /* node 4,6 */
10+
// err.stack = "Error: ENOENT: no such file or directory, open 'nope'\n at Error (native)"
11+
// })
12+
13+
interface NodeFallbackStack {
14+
getStack: () => string | undefined
15+
maybeUseFallbackStack: (err: Error, fallbackStack: string) => Error
16+
}
17+
18+
const nodeFallbackStack: NodeFallbackStack = {
19+
// Gets the stack string for the current execution context
20+
getStack: () => {
21+
// slice(3) removes the first line + this function's frame + the caller's frame,
22+
// so the stack begins with the caller of this function
23+
return (new Error()).stack?.split('\n').slice(3).join('\n')
24+
},
25+
26+
// Given an Error and a fallbackStack from getStack(), use the fallbackStack
27+
// if error.stack has no genuine stackframes (according to the example above)
28+
maybeUseFallbackStack: (err, fallbackStack) => {
29+
const lines = err.stack?.split('\n')
30+
if (lines?.length === 1 || (lines?.length === 2 && /at Error \(native\)/.test(lines[1]))) {
31+
err.stack = `${lines[0]}\n${fallbackStack}`
32+
}
33+
return err
34+
}
35+
}
36+
37+
export default nodeFallbackStack

packages/plugin-contextualize/contextualize.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
1-
const { getStack } = require('@bugsnag/core/lib/node-fallback-stack')
2-
const { cloneClient } = require('@bugsnag/core')
1+
const { cloneClient, nodeFallbackStack } = require('@bugsnag/core')
32

43
module.exports = {
54
name: 'contextualize',
65
load: client => {
76
const contextualize = (fn, onError) => {
87
// capture a stacktrace in case a resulting error has nothing
9-
const fallbackStack = getStack()
8+
const fallbackStack = nodeFallbackStack.getStack()
109

1110
const clonedClient = cloneClient(client)
1211

packages/plugin-intercept/intercept.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { getStack, maybeUseFallbackStack } = require('@bugsnag/core/lib/node-fallback-stack')
1+
const { nodeFallbackStack } = require('@bugsnag/core')
22

33
module.exports = {
44
name: 'intercept',
@@ -10,12 +10,12 @@ module.exports = {
1010
}
1111

1212
// capture a stacktrace in case a resulting error has nothing
13-
const fallbackStack = getStack()
13+
const fallbackStack = nodeFallbackStack.getStack()
1414

1515
return (err, ...data) => {
1616
if (err) {
1717
// check if the stacktrace has no context, if so, if so append the frames we created earlier
18-
if (err.stack) maybeUseFallbackStack(err, fallbackStack)
18+
if (err.stack) nodeFallbackStack.maybeUseFallbackStack(err, fallbackStack)
1919
const event = client.Event.create(err, true, {
2020
severity: 'warning',
2121
unhandled: false,

packages/plugin-node-uncaught-exception/uncaught-exception.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const { maybeUseFallbackStack } = require('@bugsnag/core/lib/node-fallback-stack')
1+
const { nodeFallbackStack } = require('@bugsnag/core')
22

33
let _handler
44
module.exports = {
@@ -12,7 +12,7 @@ module.exports = {
1212

1313
// check if the stacktrace has no context, if so append the frames we created earlier
1414
// see plugin-contextualize for where this is created
15-
if (err.stack && c.fallbackStack) maybeUseFallbackStack(err, c.fallbackStack)
15+
if (err.stack && c.fallbackStack) nodeFallbackStack.maybeUseFallbackStack(err, c.fallbackStack)
1616

1717
const event = c.Event.create(err, false, {
1818
severity: 'error',

0 commit comments

Comments
 (0)