Skip to content

Commit

Permalink
fix: preserve trampoline stack trace using await
Browse files Browse the repository at this point in the history
  • Loading branch information
stagas committed Jan 26, 2022
1 parent 8ab77e2 commit a643a0e
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 6 deletions.
13 changes: 11 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,27 @@
export const debounce = (inner: (...args: any[]) => any) => {
let queued = false
let params: any[] = []
let resolve: () => void
let reject: (error: unknown) => void
function outer(this: any) {
try {
inner.apply(this, params)
resolve()
} catch (error) {
reject(error)
} finally {
queued = false
}
}
return function (...args: any[]) {
return async function (...args: any[]) {
params = args
if (queued) return
queued = true
queueMicrotask(outer)
await new Promise<void>((_resolve, _reject) => {
resolve = _resolve
reject = _reject
queueMicrotask(outer)
})
}
}

Expand Down
40 changes: 36 additions & 4 deletions src/test/index.spec.ts → test/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { debounce } from '../'
import { debounce } from '../src'

// https://github.com/facebook/jest/issues/5620
// eslint-disable-next-line @typescript-eslint/no-explicit-any
declare const process: any
beforeAll(() => process.actual().removeAllListeners('uncaughtException'))
beforeAll(() => process.actual().removeAllListeners('unhandledRejection'))

describe('debounce', () => {
it('simple', done => {
Expand Down Expand Up @@ -31,7 +31,7 @@ describe('debounce', () => {
})
})

it('when exception is thrown it resumes correctly', async () => {
it('on error it resumes correctly', async () => {
let x = 0

const fn = debounce((y: number) => {
Expand All @@ -46,9 +46,41 @@ describe('debounce', () => {
fn()

const error: Error = await new Promise(resolve =>
process.actual().once('uncaughtException', resolve)
process.actual().once('unhandledRejection', resolve)
)
expect(error.stack).toContain('debounce-micro/test/')
expect(error.message).toContain('some error')
expect(x).toEqual(0)

fn(2)
fn(4)
expect(x).toEqual(0)

await new Promise<void>(resolve => queueMicrotask(resolve))

expect(x).toEqual(4)
})

it('awaiting can catch error and preserves stack trace', async () => {
let x = 0

const fn = debounce((y: number) => {
if (!y) {
throw new Error('some error')
} else {
x += y
}
})

let error: Error

try {
await fn()
} catch (_error) {
error = _error
}

expect(error.stack).toContain('debounce-micro/test/')
expect(error.message).toContain('some error')
expect(x).toEqual(0)

Expand Down

0 comments on commit a643a0e

Please sign in to comment.