From d32379dd3219ac31584a13f1429b76629c2467c0 Mon Sep 17 00:00:00 2001 From: Javi Velasco Date: Tue, 27 Sep 2022 19:03:01 +0200 Subject: [PATCH] Fix `unhandledrejection` event shape and add more tests --- .changeset/serious-papayas-dance.md | 5 +++ packages/runtime/src/edge-runtime.ts | 4 +- packages/runtime/tests/edge-runtime.test.ts | 7 ++-- .../runtime/tests/unhandled-rejection.test.ts | 14 +++++++ packages/runtime/tests/unhandled-rejection.ts | 37 +++++++++++++++++++ 5 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 .changeset/serious-papayas-dance.md create mode 100644 packages/runtime/tests/unhandled-rejection.test.ts create mode 100644 packages/runtime/tests/unhandled-rejection.ts diff --git a/.changeset/serious-papayas-dance.md b/.changeset/serious-papayas-dance.md new file mode 100644 index 00000000..35e55033 --- /dev/null +++ b/.changeset/serious-papayas-dance.md @@ -0,0 +1,5 @@ +--- +'edge-runtime': patch +--- + +Fix `unhandledrejection` handler parameters diff --git a/packages/runtime/src/edge-runtime.ts b/packages/runtime/src/edge-runtime.ts index ea7631fc..46ccde79 100644 --- a/packages/runtime/src/edge-runtime.ts +++ b/packages/runtime/src/edge-runtime.ts @@ -68,7 +68,9 @@ export class EdgeRuntime< process.on( 'unhandledRejection', function invokeRejectionHandlers(reason, promise) { - unhandledRejectionHandlers?.forEach((handler) => handler(reason, promise)) + unhandledRejectionHandlers?.forEach((handler) => + handler({ reason, promise }) + ) } ) process.on('uncaughtException', function invokeErrorHandlers(error) { diff --git a/packages/runtime/tests/edge-runtime.test.ts b/packages/runtime/tests/edge-runtime.test.ts index 1c665fdc..f1e96ac8 100644 --- a/packages/runtime/tests/edge-runtime.test.ts +++ b/packages/runtime/tests/edge-runtime.test.ts @@ -9,6 +9,7 @@ beforeAll(async () => { .spyOn(process, 'on') .mockImplementation((event: string, handler: Function) => { handlerByEvent.set(event, handler) + return process }) ;({ EdgeRuntime } = await import('../src/edge-runtime')) }) @@ -60,13 +61,13 @@ test('invokes context rejection handler', async () => { const runtime = new EdgeRuntime() const handleRejection = jest.fn() - const error = new Error('Boom!!!') + const reason = new Error('Boom!!!') const promise = Promise.resolve() runtime.context.addEventListener('unhandledrejection', handleRejection) expect(handlerByEvent.get('unhandledRejection')).toBeDefined() - handlerByEvent.get('unhandledRejection')!(error, promise) - expect(handleRejection).toHaveBeenCalledWith(error, promise) + handlerByEvent.get('unhandledRejection')!(reason, promise) + expect(handleRejection).toHaveBeenCalledWith({ reason, promise }) expect(handleRejection).toHaveBeenCalledTimes(1) }) diff --git a/packages/runtime/tests/unhandled-rejection.test.ts b/packages/runtime/tests/unhandled-rejection.test.ts new file mode 100644 index 00000000..cfd403a0 --- /dev/null +++ b/packages/runtime/tests/unhandled-rejection.test.ts @@ -0,0 +1,14 @@ +import { exec } from 'child_process' +import { promisify } from 'util' +import { resolve } from 'path' + +jest.setTimeout(20000) + +it('handles correctly unhandled rejections', async () => { + const execAsync = promisify(exec) + const result = await execAsync( + `ts-node --transpile-only ${resolve(__dirname, 'unhandled-rejection.ts')}`, + { encoding: 'utf8' } + ) + expect(result.stdout).toContain('TEST PASSED!') +}) diff --git a/packages/runtime/tests/unhandled-rejection.ts b/packages/runtime/tests/unhandled-rejection.ts new file mode 100644 index 00000000..6e10a0b2 --- /dev/null +++ b/packages/runtime/tests/unhandled-rejection.ts @@ -0,0 +1,37 @@ +import { EdgeRuntime } from '../src' +import assert from 'assert' + +async function main() { + const runtime = new EdgeRuntime() + const deferred = new Promise((resolve) => { + runtime.context.handleRejection = (event: PromiseRejectionEvent) => { + resolve(event) + } + }) + + runtime.evaluate(` + addEventListener('fetch', (event) => { + new Promise((resolve, reject) => reject(new TypeError('This is not controlled'))) + event.respondWith(new Response('hello')); + }) + + addEventListener('unhandledrejection', (event) => { + globalThis.handleRejection(event) + }) + `) + + const response = await runtime.dispatchFetch('https://example.com') + const event = await deferred + + assert.strictEqual(response.status, 200) + assert.strictEqual(event.reason.message, 'This is not controlled') + return 'TEST PASSED!' +} + +main() + .then(console.log) + .catch((error) => { + console.log('TEST FAILED!') + console.log(error) + process.exit(1) + })