Skip to content

Commit 1edea72

Browse files
authored
fix: preserve fetch stack traces (#4778)
1 parent 4b36fef commit 1edea72

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

index-fetch.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,33 @@ const { getGlobalDispatcher, setGlobalDispatcher } = require('./lib/global')
44
const EnvHttpProxyAgent = require('./lib/dispatcher/env-http-proxy-agent')
55
const fetchImpl = require('./lib/web/fetch').fetch
66

7+
function appendFetchStackTrace (err, filename) {
8+
if (!err || typeof err !== 'object') {
9+
return
10+
}
11+
12+
const stack = typeof err.stack === 'string' ? err.stack : ''
13+
const normalizedFilename = filename.replace(/\\/g, '/')
14+
15+
if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) {
16+
return
17+
}
18+
19+
const capture = {}
20+
Error.captureStackTrace(capture, appendFetchStackTrace)
21+
22+
if (!capture.stack) {
23+
return
24+
}
25+
26+
const captureLines = capture.stack.split('\n').slice(1).join('\n')
27+
28+
err.stack = stack ? `${stack}\n${captureLines}` : capture.stack
29+
}
30+
731
module.exports.fetch = function fetch (init, options = undefined) {
832
return fetchImpl(init, options).catch(err => {
9-
if (err && typeof err === 'object') {
10-
Error.captureStackTrace(err)
11-
}
33+
appendFetchStackTrace(err, __filename)
1234
throw err
1335
})
1436
}

index.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,33 @@ module.exports.getGlobalDispatcher = getGlobalDispatcher
121121

122122
const fetchImpl = require('./lib/web/fetch').fetch
123123

124+
function appendFetchStackTrace (err, filename) {
125+
if (!err || typeof err !== 'object') {
126+
return
127+
}
128+
129+
const stack = typeof err.stack === 'string' ? err.stack : ''
130+
const normalizedFilename = filename.replace(/\\/g, '/')
131+
132+
if (stack && (stack.includes(filename) || stack.includes(normalizedFilename))) {
133+
return
134+
}
135+
136+
const capture = {}
137+
Error.captureStackTrace(capture, appendFetchStackTrace)
138+
139+
if (!capture.stack) {
140+
return
141+
}
142+
143+
const captureLines = capture.stack.split('\n').slice(1).join('\n')
144+
145+
err.stack = stack ? `${stack}\n${captureLines}` : capture.stack
146+
}
147+
124148
module.exports.fetch = function fetch (init, options = undefined) {
125149
return fetchImpl(init, options).catch(err => {
126-
if (err && typeof err === 'object') {
127-
Error.captureStackTrace(err)
128-
}
150+
appendFetchStackTrace(err, __filename)
129151
throw err
130152
})
131153
}

test/fetch/client-error-stack-trace.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ test('FETCH: request errors and prints trimmed stack trace', async (t) => {
1818
} catch (error) {
1919
const stackLines = error.stack.split('\n')
2020
t.assert.ok(stackLines[0].includes('TypeError: fetch failed'))
21-
t.assert.ok(stackLines[1].includes(`${projectFolder}${sep}index.js`))
22-
t.assert.ok(stackLines[2].includes('at process.processTicksAndRejections'))
23-
t.assert.ok(stackLines[3].includes(`at async TestContext.<anonymous> (${__filename}`))
21+
t.assert.ok(stackLines.some(line => line.includes(`lib${sep}web${sep}fetch${sep}index.js`)))
22+
t.assert.ok(stackLines.some(line => line.includes(`${projectFolder}${sep}index.js`)))
23+
t.assert.ok(stackLines.some(line => line.includes(__filename)))
2424
}
2525
})
2626

@@ -30,8 +30,8 @@ test('FETCH-index: request errors and prints trimmed stack trace', async (t) =>
3030
} catch (error) {
3131
const stackLines = error.stack.split('\n')
3232
t.assert.ok(stackLines[0].includes('TypeError: fetch failed'))
33-
t.assert.ok(stackLines[1].includes(`${projectFolder}${sep}index-fetch.js`))
34-
t.assert.ok(stackLines[2].includes('at process.processTicksAndRejections'))
35-
t.assert.ok(stackLines[3].includes(`at async TestContext.<anonymous> (${__filename}`))
33+
t.assert.ok(stackLines.some(line => line.includes(`lib${sep}web${sep}fetch${sep}index.js`)))
34+
t.assert.ok(stackLines.some(line => line.includes(`${projectFolder}${sep}index-fetch.js`)))
35+
t.assert.ok(stackLines.some(line => line.includes(__filename)))
3636
}
3737
})

0 commit comments

Comments
 (0)