Skip to content

Commit

Permalink
fix: birpc using safe timers (#1379)
Browse files Browse the repository at this point in the history
  • Loading branch information
sheremet-va committed May 27, 2022
1 parent d2137dd commit 89353ae
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 6 deletions.
12 changes: 10 additions & 2 deletions packages/vitest/src/runtime/rpc.ts
@@ -1,5 +1,13 @@
import { getWorkerState } from '../utils'
import { getWorkerState, withSafeTimers } from '../utils'

export const rpc = () => {
return getWorkerState().rpc
const { rpc } = getWorkerState()
return new Proxy(rpc, {
get(target, p, handler) {
const sendCall = Reflect.get(target, p, handler)
const safeSendCall = (...args: any[]) => withSafeTimers(() => sendCall(...args))
safeSendCall.asEvent = sendCall.asEvent
return safeSendCall
},
})
}
41 changes: 37 additions & 4 deletions packages/vitest/src/utils/timers.ts
@@ -1,4 +1,37 @@
export const setTimeout = globalThis.setTimeout
export const setInterval = globalThis.setInterval
export const clearInterval = globalThis.clearInterval
export const clearTimeout = globalThis.clearTimeout
const {
setTimeout: safeSetTimeout,
setInterval: safeSetInterval,
clearInterval: safeClearInterval,
clearTimeout: safeClearTimeout,
} = globalThis

export {
safeSetTimeout as setTimeout,
safeSetInterval as setInterval,
safeClearInterval as clearInterval,
safeClearTimeout as clearTimeout,
}

// can only work with sync code to not potentially mess with other code
export function withSafeTimers(fn: () => void) {
const currentSetTimeout = globalThis.setTimeout
const currentSetInterval = globalThis.setInterval
const currentClearInterval = globalThis.clearInterval
const currentClearTimeout = globalThis.clearTimeout

try {
globalThis.setTimeout = safeSetTimeout
globalThis.setInterval = safeSetInterval
globalThis.clearInterval = safeClearInterval
globalThis.clearTimeout = safeClearTimeout

const result = fn()
return result
}
finally {
globalThis.setTimeout = currentSetTimeout
globalThis.setInterval = currentSetInterval
globalThis.clearInterval = currentClearInterval
globalThis.clearTimeout = currentClearTimeout
}
}
35 changes: 35 additions & 0 deletions test/core/test/rpc.spec.ts
@@ -0,0 +1,35 @@
import { afterAll, beforeAll, describe, test, vi } from 'vitest'

const { setTimeout } = globalThis

function delay(timeout: number) {
return new Promise((resolve) => {
setTimeout(resolve, timeout)
})
}

function checkExtraTimers(location: string) {
const count = vi.getTimerCount()
if (count > 0)
throw new Error(`got extra timers (${location}): ${count}`)
}

beforeAll(() => {
vi.useFakeTimers()
})

afterAll(() => {
vi.useRealTimers()
})

describe.each([1, 2])('group %d', (group) => {
test('test', async () => {
checkExtraTimers(`group ${group}a`)
vi.advanceTimersByTime(60000 + 1)

await delay(10)

checkExtraTimers(`group ${group}b`)
vi.advanceTimersByTime(60000 + 1)
})
})

0 comments on commit 89353ae

Please sign in to comment.