snapshot of https://github.com/tldraw/tldraw.git (main, 2026-09-23; blobs > 131072B omitted)
Some checks failed
Deploy analytics worker / Deploy analytics worker to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
i18n upload strings / Upload latest strings (push) Failing after 1s
Deploy bemo / Deploy bemo to ${{ (github.ref == 'refs/heads/bemo-production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Failing after 1s
Deploy grafana resources / ${{ github.event_name == 'push' && 'Deploy grafana resources' || 'Validate grafana resources (dry run)' }} (push) Failing after 0s
End to end tests (dotcom) / Check for relevant changes (push) Failing after 0s
End to end tests (examples) / Check for relevant changes (push) Failing after 0s
End to end tests (mermaid readability) / Check for relevant changes (push) Failing after 1s
End to end tests (perf) / Check for relevant changes (push) Failing after 0s
Publish editor extensions / Publish editor extensions (push) Failing after 1s
Publish SDK packages / Remove the publish-packages label (push) Has been skipped
Checks / Tests & checks (push) Has been cancelled
Checks / Build all projects (push) Has been cancelled
Deploy templates / Deploy templates (push) Has been cancelled
End to end tests (dotcom) / End to end tests (dotcom) (push) Has been cancelled
End to end tests (mermaid readability) / End to end tests (mermaid readability) (push) Has been cancelled
End to end tests (perf) / End to end tests (perf) (push) Has been cancelled
Deploy .com / Deploy dotcom to ${{ (github.ref == 'refs/heads/production' && 'production') || (github.ref == 'refs/heads/main' && 'staging') || 'preview' }} (push) Has been cancelled
End to end tests (examples) / End to end tests (examples) (push) Has been cancelled
Publish SDK packages / Publish SDK packages (push) Has been cancelled
Publish SDK packages / Tell user released version (push) Has been cancelled
Publish SDK packages / Publishes code templates to separate repositories (push) Has been cancelled
Publish SDK packages / Deploys the template demos with the new SDK version (push) Has been cancelled

This commit is contained in:
upstream-mirror
2026-09-23 16:12:52 +05:00
commit a774ac673a
4541 changed files with 770499 additions and 0 deletions

View File

@@ -0,0 +1,254 @@
import { vi } from 'vitest'
import { MicrotaskNotifier } from './MicrotaskNotifier'
// Helper to flush all pending microtasks
async function flushMicrotasks() {
await Promise.resolve()
}
describe('MicrotaskNotifier', () => {
let consoleErrorSpy: ReturnType<typeof vi.spyOn>
beforeEach(() => {
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {})
})
afterEach(() => {
consoleErrorSpy.mockRestore()
})
describe('deferred delivery (MN1)', () => {
it('[MN1] does not call listeners synchronously', () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
notifier.register(listener)
notifier.notify('hello')
expect(listener).not.toHaveBeenCalled()
})
it('[MN1] delivers the notification arguments to every listener on a microtask', async () => {
const notifier = new MicrotaskNotifier<[string, number, boolean]>()
const listener1 = vi.fn()
const listener2 = vi.fn()
notifier.register(listener1)
notifier.register(listener2)
await flushMicrotasks()
notifier.notify('test', 123, true)
await flushMicrotasks()
expect(listener1).toHaveBeenCalledExactlyOnceWith('test', 123, true)
expect(listener2).toHaveBeenCalledExactlyOnceWith('test', 123, true)
})
it('[MN1] delivers multiple notifications in order', async () => {
const notifier = new MicrotaskNotifier<[number]>()
const calls: number[] = []
const listener = vi.fn((n: number) => calls.push(n))
notifier.register(listener)
await flushMicrotasks()
notifier.notify(1)
notifier.notify(2)
notifier.notify(3)
await flushMicrotasks()
expect(calls).toEqual([1, 2, 3])
})
it('[MN1] notify with no listeners does not throw', async () => {
const notifier = new MicrotaskNotifier<[string]>()
expect(() => notifier.notify('test')).not.toThrow()
await flushMicrotasks()
})
})
describe('deferred registration (MN2)', () => {
it('[MN2] a listener misses notifications issued before register was called', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
notifier.notify('before registration')
notifier.register(listener)
await flushMicrotasks()
expect(listener).not.toHaveBeenCalled()
})
it('[MN2] a listener receives notifications issued after register in the same synchronous block', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
// Both register and notify queue microtasks; microtasks run FIFO, so
// the add runs first and the notification is delivered
notifier.register(listener)
notifier.notify('same sync block')
await flushMicrotasks()
expect(listener).toHaveBeenCalledExactlyOnceWith('same sync block')
})
it('[MN2] registering during a notification defers the new listener to later notifications', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const lateListener = vi.fn()
const listener1 = vi.fn(() => {
notifier.register(lateListener)
})
notifier.register(listener1)
await flushMicrotasks()
notifier.notify('first')
await flushMicrotasks()
expect(lateListener).not.toHaveBeenCalled()
await flushMicrotasks() // late registration completes
notifier.notify('second')
await flushMicrotasks()
expect(lateListener).toHaveBeenCalledExactlyOnceWith('second')
})
})
describe('unsubscribing (MN3)', () => {
it('[MN3] unsubscribe is synchronous and stops future notifications', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
const other = vi.fn()
const unsubscribe = notifier.register(listener)
notifier.register(other)
await flushMicrotasks()
unsubscribe()
notifier.notify('should not receive')
await flushMicrotasks()
expect(listener).not.toHaveBeenCalled()
// other listeners are unaffected
expect(other).toHaveBeenCalledExactlyOnceWith('should not receive')
})
it('[MN3] unsubscribing before the add microtask runs prevents the registration entirely', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
const unsubscribe = notifier.register(listener)
unsubscribe() // before the add microtask runs
await flushMicrotasks()
notifier.notify('should not receive')
await flushMicrotasks()
expect(listener).not.toHaveBeenCalled()
})
it('[MN3] double unsubscribe is safe', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
const unsubscribe = notifier.register(listener)
await flushMicrotasks()
unsubscribe()
unsubscribe()
unsubscribe()
notifier.notify('test')
await flushMicrotasks()
expect(listener).not.toHaveBeenCalled()
})
it('[MN3] registering the same function twice', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const listener = vi.fn()
const unsub1 = notifier.register(listener)
const _unsub2 = notifier.register(listener)
await flushMicrotasks()
notifier.notify('test')
await flushMicrotasks()
// The listener set deduplicates the same function reference, so it is
// only called once per notification
expect(listener).toHaveBeenCalledTimes(1)
// Unsubscribing via the first registration removes the function for
// both registrations
unsub1()
notifier.notify('test2')
await flushMicrotasks()
expect(listener).toHaveBeenCalledTimes(1)
})
it('[MN3] unsubscribing during notification iteration takes effect for later notifications', async () => {
const notifier = new MicrotaskNotifier<[string]>()
let unsub2: (() => void) | undefined = undefined
const listener1 = vi.fn(() => {
// Unsubscribe listener2 while iteration is in progress
unsub2?.()
})
const listener2 = vi.fn()
const listener3 = vi.fn()
notifier.register(listener1)
unsub2 = notifier.register(listener2)
notifier.register(listener3)
await flushMicrotasks()
notifier.notify('test')
await flushMicrotasks()
expect(listener1).toHaveBeenCalled()
expect(listener3).toHaveBeenCalled()
listener1.mockClear()
listener2.mockClear()
listener3.mockClear()
notifier.notify('test2')
await flushMicrotasks()
expect(listener1).toHaveBeenCalled()
expect(listener2).not.toHaveBeenCalled()
expect(listener3).toHaveBeenCalled()
})
})
describe('listener errors (MN4)', () => {
it('[MN4] a listener that throws is caught and logged, and remaining listeners still run', async () => {
const notifier = new MicrotaskNotifier<[string]>()
const errorListener = vi.fn(() => {
throw new Error('listener error')
})
const normalListener = vi.fn()
notifier.register(errorListener)
notifier.register(normalListener)
await flushMicrotasks()
notifier.notify('test')
await flushMicrotasks()
expect(errorListener).toHaveBeenCalled()
expect(normalListener).toHaveBeenCalled()
expect(consoleErrorSpy).toHaveBeenCalledWith(
'Error in MicrotaskNotifier listener',
expect.any(Error)
)
})
})
})