Skip to content

Commit

Permalink
Merge branch 'next' into web-worker-integrity
Browse files Browse the repository at this point in the history
  • Loading branch information
Dan Skinner committed Oct 18, 2024
2 parents a801c57 + 1ee928f commit 6409517
Show file tree
Hide file tree
Showing 12 changed files with 110 additions and 22 deletions.
10 changes: 6 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# Changelog

## [Unreleased]

### Added

- Add new `reportUnhandledPromiseRejectionsAsHandled` config option [#2225](https://github.com/bugsnag/bugsnag-js/pull/2225)

## [8.0.0] - 2024-08-29

### Summary
Expand Down Expand Up @@ -31,10 +37,6 @@ As well as some bug fixes and **breaking changes** described in the [Upgrade Gui

## [7.25.1] - 2024-08-27

### Added

- (delivery-xml-http-request) Add Access-Control-Max-Age header to CORS preflight responses [#2160](https://github.com/bugsnag/bugsnag-js/pull/2160)

### Changed

- (react-native) Update bugsnag-cocoa from v6.29.0 to [v6.30.1](https://github.com/bugsnag/bugsnag-cocoa/blob/master/CHANGELOG.md#6301-2024-07-25)
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@
"@types/express-serve-static-core": "4.17.28",
"@types/prettier": "2.6.0",
"@types/yargs": "17.0.10",
"hermes-engine": "^0.7.2",
"hermes-engine": "^0.10.0",
"json-schema": "^0.4.0",
"shell-quote": "^1.7.3",
"thenify": "^3.3.1"
Expand Down
5 changes: 5 additions & 0 deletions packages/core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,10 @@ module.exports.schema = {
isArray(value) && value.length === filter(value, feature =>
feature && typeof feature === 'object' && typeof feature.name === 'string'
).length
},
reportUnhandledPromiseRejectionsAsHandled: {
defaultValue: () => false,
message: 'should be true|false',
validate: value => value === true || value === false
}
}
3 changes: 0 additions & 3 deletions packages/delivery-xml-http-request/delivery.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,6 @@ module.exports = (client, win = window) => ({
req.setRequestHeader('Bugsnag-Api-Key', event.apiKey || client._config.apiKey)
req.setRequestHeader('Bugsnag-Payload-Version', '4')
req.setRequestHeader('Bugsnag-Sent-At', (new Date()).toISOString())
if (url.substring(0, 5) === 'https') {
req.setRequestHeader('Access-Control-Max-Age', 86400)
}

if (client._config.sendPayloadChecksums && typeof Promise !== 'undefined' && Promise.toString().indexOf('[native code]') !== -1) {
getIntegrity(win, body).then((integrity) => {
Expand Down
5 changes: 2 additions & 3 deletions packages/delivery-xml-http-request/test/delivery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ describe('delivery:XMLHttpRequest', () => {
const payload = { sample: 'payload' } as unknown as EventDeliveryPayload
const config = {
apiKey: 'aaaaaaaa',
endpoints: { notify: 'https/echo/' },
endpoints: { notify: 'echo/' },
redactedKeys: [],
sendPayloadChecksums: true
}
Expand All @@ -62,12 +62,11 @@ describe('delivery:XMLHttpRequest', () => {
expect(err).toBe(null)
expect(requests.length).toBe(1)
expect(requests[0].method).toBe('POST')
expect(requests[0].url).toMatch('https/echo/')
expect(requests[0].url).toMatch('echo/')
expect(requests[0].headers['Content-Type']).toEqual('application/json')
expect(requests[0].headers['Bugsnag-Api-Key']).toEqual('aaaaaaaa')
expect(requests[0].headers['Bugsnag-Payload-Version']).toEqual('4')
expect(requests[0].headers['Bugsnag-Sent-At']).toMatch(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/)
expect(requests[0].headers['Access-Control-Max-Age']).toEqual(86400)
expect(requests[0].headers['Bugsnag-Integrity']).toEqual('sha1 14faf2461b0519f9d9d62cfb8d79483fcc8f825c')
expect(requests[0].data).toBe(JSON.stringify(payload))
done()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,34 @@ describe('plugin: node unhandled rejection handler', () => {
process.listeners('unhandledRejection')[0](new Error('never gonna catch me'), Promise.resolve())
})

it('should report unhandledRejection events as handled when reportUnhandledPromiseRejectionsAsHandled is true', (done) => {
const c = new Client({
apiKey: 'api_key',
reportUnhandledPromiseRejectionsAsHandled: true,
onUnhandledRejection: (err: Error, event: EventWithInternals) => {
expect(err.message).toBe('never gonna catch me')
expect(event._handledState.unhandled).toBe(false)
expect(event._handledState.severity).toBe('error')
expect(event._handledState.severityReason).toEqual({ type: 'unhandledPromiseRejection' })
plugin.destroy()
done()
},
plugins: [plugin]
}, {
...schema,
onUnhandledRejection: {
validate: (val: unknown) => typeof val === 'function',
message: 'should be a function',
defaultValue: () => {}
}
})
c._setDelivery(client => ({
sendEvent: (payload, cb) => cb(),
sendSession: (payload, cb) => cb()
}))
process.listeners('unhandledRejection')[0](new Error('never gonna catch me'), Promise.resolve())
})

it('should tolerate delivery errors', done => {
const c = new Client({
apiKey: 'api_key',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@ module.exports = {
const ctx = client._clientContext && client._clientContext.getStore()
const c = ctx || client

// Report unhandled promise rejections as handled if the user has configured it
const unhandled = !client._config.reportUnhandledPromiseRejectionsAsHandled

const event = c.Event.create(err, false, {
severity: 'error',
unhandled: true,
unhandled,
severityReason: { type: 'unhandledPromiseRejection' }
}, 'unhandledRejection handler', 1)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ module.exports = {
// Do not attach any listeners if autoDetectErrors is disabled or unhandledRejections are not an enabled error type
if (!client._config.autoDetectErrors || !client._config.enabledErrorTypes.unhandledRejections) return () => { }

// Report unhandled promise rejections as handled if the user has configured it
const unhandled = !client._config.reportUnhandledPromiseRejectionsAsHandled

// Check if Hermes is available and is being used for promises
// React Native v0.63 and v0.64 include global.HermesInternal but not 'hasPromise'
if (global?.HermesInternal?.hasPromise?.() && global.HermesInternal.enablePromiseRejectionTracker) {
Expand All @@ -19,7 +22,7 @@ module.exports = {
onUnhandled: (id, rejection = {}) => {
const event = client.Event.create(rejection, false, {
severity: 'error',
unhandled: true,
unhandled,
severityReason: { type: 'unhandledPromiseRejection' }
}, 'promise rejection tracking', 1)

Expand All @@ -39,7 +42,7 @@ module.exports = {
onUnhandled: (id, error) => {
const event = client.Event.create(error, false, {
severity: 'error',
unhandled: true,
unhandled,
severityReason: { type: 'unhandledPromiseRejection' }
}, 'promise rejection tracking', 1)
client._notify(event)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,30 @@ describe('plugin: react native rejection handler', () => {
stop()
})

it('should report unhandledRejection events as handled when reportUnhandledPromiseRejectionsAsHandled is true', (done) => {
expect.assertions(1)

const c = new Client({ apiKey: 'api_key', reportUnhandledPromiseRejectionsAsHandled: true })
c._setDelivery(client => ({
sendEvent: (payload) => {
const r = JSON.parse(JSON.stringify(payload))
expect(r.events[0].unhandled).toBe(false)
done()
},
sendSession: () => { }
}))
const stop = plugin.load(c)
// in the interests of keeping the tests quick, TypeErrors get rejected quicker
// see: https://github.com/then/promise/blob/d980ed01b7a383bfec416c96095e2f40fd18ab34/src/rejection-tracking.js#L48-L54
try {
// @ts-ignore
String.floop()
} catch (e) {
RnPromise.reject(e)
}
stop()
})

it('should hook in to the hermes promise rejection tracker', (done) => {
// @ts-ignore
global.HermesInternal = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,30 @@ describe('plugin: unhandled rejection', () => {
handler({ reason: new Error('BAD_PROMISE') })
})

it('should report unhandledRejection events as handled when reportUnhandledPromiseRejectionsAsHandled is true', (done) => {
const p = plugin(window)
const client = new Client({
apiKey: 'API_KEY_YEAH',
reportUnhandledPromiseRejectionsAsHandled: true,
plugins: [p]
})

client._setDelivery(client => ({
sendEvent: (payload) => {
const event = payload.events[0].toJSON()
expect(event.unhandled).toBe(false)
expect(event.severityReason).toEqual({ type: 'unhandledPromiseRejection' })
// @ts-ignore
p.destroy(window)
done()
},
sendSession: () => {}
}))

// simulate an UnhandledRejection event
getUnhandledRejectionHandler()({ reason: new Error('BAD_PROMISE') })
})

it('handles bad user input', done => {
expect.assertions(6)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,12 @@ module.exports = (win = window) => {
}
} catch (e) {}

// Report unhandled promise rejections as handled if the user has configured it
const unhandled = !client._config.reportUnhandledPromiseRejectionsAsHandled

const event = client.Event.create(error, false, {
severity: 'error',
unhandled: true,
unhandled,
severityReason: { type: 'unhandledPromiseRejection' }
}, 'unhandledrejection handler', 1, client._logger)

Expand Down

0 comments on commit 6409517

Please sign in to comment.