@dxos/async 0.12.0-next-73daef452f1464b62efdbca75fb0067c1066f264 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/chunk-events.mjs.map +1 -1
- package/dist/lib/index.mjs +66 -14
- package/dist/lib/index.mjs.map +1 -1
- package/dist/lib/testing.mjs +27 -13
- package/dist/lib/testing.mjs.map +1 -1
- package/dist/types/src/errors.d.ts +1 -1
- package/dist/types/src/errors.d.ts.map +1 -1
- package/dist/types/src/events.d.ts +1 -1
- package/dist/types/src/events.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +22 -21
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/observable-value.d.ts +1 -1
- package/dist/types/src/observable-value.d.ts.map +1 -1
- package/dist/types/src/observable.d.ts +1 -1
- package/dist/types/src/observable.d.ts.map +1 -1
- package/dist/types/src/stream.d.ts.map +1 -1
- package/dist/types/src/test-stream.d.ts +9 -9
- package/dist/types/src/test-stream.d.ts.map +1 -1
- package/dist/types/src/timer.d.ts +1 -1
- package/dist/types/src/timer.d.ts.map +1 -1
- package/dist/types/src/update-scheduler.d.ts.map +1 -1
- package/dist/types/src/yield.d.ts +19 -0
- package/dist/types/src/yield.d.ts.map +1 -0
- package/dist/types/src/yield.test.d.ts +2 -0
- package/dist/types/src/yield.test.d.ts.map +1 -0
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +9 -8
- package/src/debounce.test.ts +1 -1
- package/src/errors.ts +1 -1
- package/src/event-emitter.test.ts +3 -3
- package/src/event-emitter.ts +1 -1
- package/src/events.test.ts +2 -2
- package/src/events.ts +1 -1
- package/src/index.ts +22 -21
- package/src/mutex.test.ts +2 -2
- package/src/observable-value.test.ts +3 -3
- package/src/observable-value.ts +1 -1
- package/src/observable.test.ts +3 -3
- package/src/observable.ts +2 -2
- package/src/persistent-lifecycle.test.ts +3 -3
- package/src/persistent-lifecycle.ts +3 -3
- package/src/push-iterable.ts +1 -1
- package/src/stream.test.ts +1 -1
- package/src/stream.ts +12 -9
- package/src/task-scheduling.test.ts +2 -2
- package/src/task-scheduling.ts +2 -2
- package/src/test-stream.test.ts +3 -2
- package/src/test-stream.ts +39 -18
- package/src/testing.test.ts +2 -2
- package/src/testing.ts +2 -2
- package/src/timeout.test.ts +1 -1
- package/src/timeout.ts +1 -1
- package/src/timer.ts +1 -1
- package/src/trigger.test.ts +2 -2
- package/src/trigger.ts +2 -2
- package/src/update-scheduler.test.ts +2 -2
- package/src/update-scheduler.ts +5 -3
- package/src/yield.test.ts +63 -0
- package/src/yield.ts +75 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chunk-events.mjs","names":[],"sources":["../../src/errors.ts","../../src/timeout.ts","../../src/events.ts"],"sourcesContent":["//\n// Copyright 2020 DXOS.org\n//\n\nimport { type ObservableProvider } from './observable-value';\n\n// TODO(burdon): Move to debug.\n// Use: https://nodejs.org/api/errors.html\nexport const toError = (err: any) => (err === undefined || typeof err === 'string' ? new Error(err) : err);\n\nexport class TimeoutError extends Error {\n constructor(timeout?: number, label?: string) {\n super(timeout ? `Timeout [${timeout.toLocaleString()}ms]${label === undefined ? '' : `: ${label}`}` : 'Timeout');\n }\n}\n\nexport interface AsyncEvents<T = any> {\n onSuccess?(result: T): void;\n onTimeout?(err: TimeoutError): void;\n onError(err: any): void;\n}\n\nexport const observableError = (observable: ObservableProvider<AsyncEvents>, err: any) => {\n if (err instanceof TimeoutError) {\n observable.callback.onTimeout?.(err);\n } else {\n observable.callback.onError(toError(err));\n }\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { type Context, ContextDisposedError } from '@dxos/context';\n\nimport { TimeoutError } from './errors';\n\n/**\n * Times out after delay.\n */\nexport const sleep = (ms: number) => {\n return new Promise<void>((resolve) => {\n const finish = Date.now() + ms;\n\n // `setTimeout` does not guarantee execution at >= the scheduled time and may execute slightly early.\n const sleeper = () => {\n const delta = finish - Date.now();\n if (delta > 0) {\n setTimeout(sleeper, delta);\n } else {\n resolve();\n }\n };\n\n sleeper();\n });\n};\n\n// TODO(burdon): Reconcile with sleep.\nexport const sleepWithContext = (ctx: Context, ms: number) => {\n const error = new ContextDisposedError();\n return new Promise<void>((resolve, reject) => {\n if (ctx.disposed) {\n reject(error);\n return;\n }\n\n const timeout = setTimeout(() => {\n clearDispose();\n resolve();\n }, ms);\n\n const clearDispose = ctx.onDispose(() => {\n clearTimeout(timeout);\n reject(error);\n });\n });\n};\n\n/**\n * Can be used in long-running tasks to let other callbacks be invoked.\n */\nexport const asyncReturn = () => sleep(0);\n\n/**\n * Wait for promise or throw error.\n */\nexport const asyncTimeout = async <T>(promise: Promise<T>, timeout: number, err?: Error | string): Promise<T> => {\n if (typeof promise === 'function') {\n throw new Error('First argument must be a promise.');\n }\n\n let timeoutId: NodeJS.Timeout;\n const throwable = err === undefined || typeof err === 'string' ? new TimeoutError(timeout, err) : err;\n const timeoutPromise = new Promise<T>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n reject(throwable);\n }, timeout);\n\n unrefTimeout(timeoutId);\n });\n\n return await Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timeoutId);\n });\n};\n\n/**\n * In Node.JS, `unref` prevents the timeout from blocking the process from exiting. Not available in browsers.\n * https://nodejs.org/api/timers.html#timeoutunref\n */\nexport const unrefTimeout = (timeoutId: NodeJS.Timeout) => {\n if (typeof timeoutId === 'object' && 'unref' in timeoutId) {\n timeoutId.unref();\n }\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { Context } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { type CleanupFn } from './cleanup';\n\nexport type Effect = () => CleanupFn | undefined;\n\n/**\n * Effect that's been added to a specific Event.\n */\ninterface MaterializedEffect {\n effect: Effect;\n cleanup: CleanupFn | undefined;\n}\n\ninterface EventEmitterLike {\n on(event: string, cb: (data?: any) => void): void;\n off(event: string, cb: (data?: any) => void): void;\n}\n\nexport type ListenerOptions = {\n weak?: boolean;\n once?: boolean;\n};\n\ntype EventCallback<T> = (data: T) => MaybePromise<void>;\n\n// TODO(dmaretskyi): Remove this once the code is cleaned up.\nconst DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;\n\n/**\n * An EventEmitter variant that does not do event multiplexing and represents a single event.\n *\n * ## Typical usage:\n * ```javascript\n * class Model {\n * public readonly update = new Event<UpdateData>();\n * private readonly privateEvent = new Event<void>();\n *\n * onUpdate(data: UpdateData) {\n * ...\n * this.update.emit(data);\n * }\n * }\n *\n * model.update.on(data => {\n * ...\n * });\n * ```\n *\n * ## Advantages over traditional EventEmitter:\n * 1. User describes explicitly what events a class has as they are defined as class fields.\n * 2. User can explicitly define event visibility (public, protected, private).\n * 3. Having events as class fields allows the compiler to check for correct event usage.\n * 4. User can type the data that event will be emitting.\n * 5. Uses composition instead of inheritance.\n * 6. Removes the cases where event names intersect when used in cases with inheritance.\n * 7. Remove the need to namespace events when developing a class with events that will be used as a base-class.\n */\n// TODO(burdon): Rename EventSink? (Event is a built-in type).\nexport class Event<T = void> implements ReadOnlyEvent<T> {\n /**\n * Wrap objects that have on/off style event emitters.\n */\n static wrap<T>(emitter: EventEmitterLike, eventName: string): Event<T> {\n const event = new Event<T>();\n\n event.addEffect(() => {\n const onEvent = (data: any) => event.emit(data);\n emitter.on(eventName, onEvent);\n return () => emitter.off(eventName, onEvent);\n });\n\n return event;\n }\n\n private readonly _listeners = new Set<EventListener<T>>();\n private readonly _effects = new Set<MaterializedEffect>();\n\n /**\n * Emit an event.\n * In most cases should only be called by the class or entity containing the event.\n * All listeners are called in order of subscription with persistent ones first.\n * Listeners are called synchronously in the same stack.\n * A thrown exception in the listener will stop the event from being emitted to the rest of the listeners.\n *\n * @param data param that will be passed to all listeners.\n */\n emit(data: T): void {\n for (const listener of this._listeners) {\n listener.trigger(data);\n\n if (listener.once) {\n this._listeners.delete(listener);\n }\n }\n }\n\n /**\n * Emit an event and wait for async listeners to complete.\n * In most cases should only be called by the class or entity containing the event.\n * All listeners are called in order of subscription with persistent ones first.\n * Listeners are called sequentially.\n *\n * @param data param that will be passed to all listeners.\n */\n async emitAsync(data: T): Promise<void> {\n for (const listener of this._listeners) {\n await listener.triggerAsync(data);\n\n if (listener.once) {\n this._listeners.delete(listener);\n }\n }\n }\n\n /**\n * Register an event listener.\n * If provided callback was already registered as once-listener, it is made permanent.\n *\n * @param callback\n * @param options.weak If true, the callback will be weakly referenced and will be garbage collected if no other references to it exist.\n * @returns function that unsubscribes this event listener\n */\n on(callback: EventCallback<T>): CleanupFn;\n on(ctx: Context, callback: EventCallback<T>, options?: ListenerOptions): CleanupFn;\n on(_ctx: any, _callback?: EventCallback<T>, options?: ListenerOptions): CleanupFn {\n const [ctx, callback] = _ctx instanceof Context ? [_ctx, _callback] : [new Context(), _ctx];\n const weak = !!options?.weak;\n const once = !!options?.once;\n\n const listener = new EventListener(this, callback, ctx, once, weak);\n\n this._addListener(listener);\n\n return () => {\n this._removeListener(listener);\n };\n }\n\n /**\n * Unsubscribe this callback from new events. Includes persistent and once-listeners.\n * NOTE: It is recommended to use `Event.on`'s return value instead.\n * If the callback is not subscribed this is no-op.\n *\n * @param callback\n */\n off(callback: (data: T) => void): void {\n for (const listener of this._listeners) {\n if (listener.derefCallback() === callback) {\n this._removeListener(listener);\n }\n }\n }\n\n /**\n * Register a callback to be called only once when the next event is emitted.\n * If this callback is already registered as permanent listener, this is no-op.\n *\n * @param callback\n */\n once(callback: (data: T) => void): CleanupFn;\n once(ctx: Context, callback: (data: T) => void): CleanupFn;\n once(_ctx: any, _callback?: (data: T) => void): CleanupFn {\n const [ctx, callback] = _ctx instanceof Context ? [_ctx, _callback] : [new Context(), _ctx];\n\n const listener = new EventListener(this, callback, ctx, true, false);\n\n this._addListener(listener);\n\n return () => {\n this._removeListener(listener);\n };\n }\n\n /**\n * An async iterator that iterates over events.\n * This iterator runs indefinitely.\n */\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n yield await new Promise((resolve) => {\n this.once(resolve);\n });\n }\n }\n\n /**\n * Returns a promise that resolves with the first event emitted that matches the provided predicate.\n *\n * @param predicate\n */\n waitFor(predicate: (data: T) => boolean): Promise<T> {\n return new Promise((resolve) => {\n const unsubscribe = this.on((data) => {\n if (predicate(data)) {\n unsubscribe();\n resolve(data);\n }\n });\n });\n }\n\n /**\n * Returns a promise that resolves once a specific number of events was emitted since this method was called.\n *\n * @param expectedCount\n */\n waitForCount(expectedCount: number): Promise<T> {\n let count = 0;\n return this.waitFor(() => ++count === expectedCount);\n }\n\n /**\n * Similar to waitFor, but the promise resolves immediately if the condition is already true.\n */\n // TODO(burdon): Should pass event property to predicate.\n async waitForCondition(predicate: () => boolean): Promise<void> {\n if (!predicate()) {\n await this.waitFor(predicate);\n }\n }\n\n /**\n * Returns the number of persistent listeners.\n */\n listenerCount(): number {\n return this._listeners.size;\n }\n\n /**\n * Add a side effect that will be activated once the event has at least one subscriber.\n * The provided callback can return a function that will be used to clean up after the last subscriber unsubscribes from the event.\n * The API is similar to `useEffect` from React.\n *\n * ## Example:\n * ```typescript\n * event.addEffect(() => {\n * // do stuff\n * return () => {\n * // clean-up\n * };\n * });\n * ```\n *\n * @returns Callback that will remove this effect once called.\n */\n addEffect(effect: Effect): CleanupFn {\n const handle: MaterializedEffect = { effect, cleanup: undefined };\n\n if (this.listenerCount() > 0) {\n handle.cleanup = handle.effect();\n }\n\n this._effects.add(handle);\n return () => {\n // eslint-disable-next-line no-unused-expressions\n handle.cleanup?.();\n this._effects.delete(handle);\n };\n }\n\n /**\n * Triggers an event with at least `timeout` milliseconds between each event.\n * If the event is triggered more often, the event is delayed until the timeout is reached.\n * If event is emitted for the first time or event wasn't fired for `timeout` milliseconds,\n * the event is emitted after `timeout / 8` ms.\n */\n // TODO(burdon): Factor out generic function.\n debounce(timeout = 0): Event<void> {\n let firing: NodeJS.Timeout | undefined;\n let lastFired: number | undefined;\n\n const debouncedEvent = new Event<void>();\n debouncedEvent.addEffect(() => {\n const unsubscribe = this.on(() => {\n if (!firing) {\n const fireIn = !lastFired || Date.now() - lastFired > timeout ? timeout / 8 : timeout;\n firing = setTimeout(() => {\n lastFired = Date.now();\n firing = undefined;\n debouncedEvent.emit();\n }, fireIn);\n }\n });\n\n return () => {\n unsubscribe();\n clearTimeout(firing);\n };\n });\n\n return debouncedEvent;\n }\n\n /**\n * Turn any variant of `Event<T>` into an `Event<void>` discarding the callback parameter.\n */\n discardParameter(): Event<void> {\n return this as any;\n }\n\n /**\n * Pipe the events into another event.\n * @param event\n */\n pipeInto(event: Event<T>): CleanupFn {\n return this.on((data) => event.emit(data));\n }\n\n /**\n * Overridden to not return implementation details.\n */\n toJSON(): { listenerCount: number } {\n return {\n listenerCount: this.listenerCount(),\n };\n }\n\n private _addListener(listener: EventListener<T>): void {\n this._listeners.add(listener);\n\n if (this.listenerCount() === 1) {\n this._runEffects();\n }\n }\n\n /**\n * @internal\n */\n _removeListener(listener: EventListener<T>): void {\n this._listeners.delete(listener);\n listener.remove();\n\n if (this.listenerCount() === 0) {\n this._cleanupEffects();\n }\n }\n\n private _runEffects(): void {\n for (const handle of this._effects) {\n handle.cleanup = handle.effect();\n }\n }\n\n private _cleanupEffects(): void {\n for (const handle of this._effects) {\n // eslint-disable-next-line no-unused-expressions\n handle.cleanup?.();\n handle.cleanup = undefined;\n }\n }\n}\n\n/**\n * A version of Event class which only has subscribe methods.\n * Useful in cases where you want to explicitly prohibit calling `emit` method.\n */\nexport interface ReadOnlyEvent<T = void> {\n /**\n * Register an event listener.\n * If provided callback was already registered as once-listener, it is made permanent.\n *\n * @param callback\n * @param options.weak If true, the callback will be weakly referenced and will be garbage collected if no other references to it exist.\n * @returns function that unsubscribes this event listener\n */\n on(callback: (data: T) => void): CleanupFn;\n on(ctx: Context, callback: (data: T) => void, options?: ListenerOptions): CleanupFn;\n\n /**\n * Unsubscribes this callback from new events. Includes persistent and once-listeners.\n * NOTE: It is recommended to us `Event.on`'s return value.\n * If the callback is not subscribed this is no-op.\n *\n * @param callback\n */\n off(callback: (data: T) => void): void;\n\n /**\n * Register a callback to be called only once when the next event is emitted.\n * If this callback is already registered as permanent listener, this is no-op.\n *\n * @param callback\n */\n once(callback: (data: T) => void): CleanupFn;\n\n /**\n * An async iterator that iterates over events.\n * This iterator runs indefinitely.\n */\n [Symbol.asyncIterator](): AsyncIterator<T>;\n\n /**\n * Returns a promise that resolves with the first event emitted that matches the provided predicate.\n *\n * @param predicate\n */\n waitFor(predicate: (data: T) => boolean): Promise<T>;\n\n /**\n * Returns a promise that resolves once a specific number of events was emitted since this method was called.\n *\n * @param expectedCount\n */\n waitForCount(expectedCount: number): Promise<T>;\n\n /**\n * Turn any variant of `Event<T>` into an `Event<void>` discarding the callback parameter.\n */\n discardParameter(): Event<void>;\n\n /**\n * Triggers an event with at least `timeout` milliseconds between each event.\n * If the event is triggered more often, the event is delayed until the timeout is reached.\n * If event is emitted for the first time or event wasn't fired for `timeout` milliseconds,\n * the event is emitted after `timeout / 8` ms.\n */\n debounce(timeout?: number): Event<void>;\n}\n\nclass EventListener<T> {\n public readonly callback: EventCallback<T> | WeakRef<EventCallback<T>>;\n\n private readonly _clearDispose?: () => void = undefined;\n\n constructor(\n event: Event<T>,\n listener: EventCallback<T>,\n public readonly ctx: Context,\n public readonly once: boolean,\n public readonly weak: boolean,\n ) {\n this._clearDispose = ctx.onDispose(() => {\n event._removeListener(this);\n });\n\n if (weak) {\n this.callback = new WeakRef(listener);\n weakListeners().registry?.register(\n listener,\n {\n event: new WeakRef(event),\n listener: this,\n },\n this,\n );\n } else {\n this.callback = listener;\n }\n }\n\n derefCallback(): EventCallback<T> | undefined {\n return this.weak ? (this.callback as WeakRef<EventCallback<T>>).deref() : (this.callback as EventCallback<T>);\n }\n\n trigger(data: T): void {\n let result!: MaybePromise<void>;\n try {\n const callback = this.derefCallback();\n result = callback?.(data);\n } catch (err: any) {\n this.ctx.raise(err);\n }\n\n if (!DO_NOT_ERROR_ON_ASYNC_CALLBACK) {\n if (result instanceof Promise) {\n throw new TypeError('Event has async callbacks, use emitAsync instead');\n }\n }\n }\n\n async triggerAsync(data: T): Promise<void> {\n try {\n const callback = this.derefCallback();\n await callback?.(data);\n } catch (err: any) {\n this.ctx.raise(err);\n }\n }\n\n remove(): void {\n this._clearDispose?.();\n weakListeners().registry?.unregister(this);\n }\n}\n\ntype HeldValue = {\n event: WeakRef<Event<any>>;\n listener: EventListener<any>;\n};\n\nlet weakListenersState: FinalizationRegistry<HeldValue> | null = null;\n\ntype WeakListeners = {\n registry: FinalizationRegistry<HeldValue> | undefined;\n};\n\nconst FINALIZATION_REGISTRY_SUPPORTED = !!globalThis.FinalizationRegistry;\n\nconst weakListeners = (): WeakListeners => {\n if (!FINALIZATION_REGISTRY_SUPPORTED) {\n return { registry: undefined };\n }\n weakListenersState ??= new FinalizationRegistry(({ event, listener }) => {\n event.deref()?._removeListener(listener);\n });\n return { registry: weakListenersState };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"chunk-events.mjs","names":[],"sources":["../../src/errors.ts","../../src/timeout.ts","../../src/events.ts"],"sourcesContent":["//\n// Copyright 2020 DXOS.org\n//\n\nimport { type ObservableProvider } from './observable-value.ts';\n\n// TODO(burdon): Move to debug.\n// Use: https://nodejs.org/api/errors.html\nexport const toError = (err: any) => (err === undefined || typeof err === 'string' ? new Error(err) : err);\n\nexport class TimeoutError extends Error {\n constructor(timeout?: number, label?: string) {\n super(timeout ? `Timeout [${timeout.toLocaleString()}ms]${label === undefined ? '' : `: ${label}`}` : 'Timeout');\n }\n}\n\nexport interface AsyncEvents<T = any> {\n onSuccess?(result: T): void;\n onTimeout?(err: TimeoutError): void;\n onError(err: any): void;\n}\n\nexport const observableError = (observable: ObservableProvider<AsyncEvents>, err: any) => {\n if (err instanceof TimeoutError) {\n observable.callback.onTimeout?.(err);\n } else {\n observable.callback.onError(toError(err));\n }\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { type Context, ContextDisposedError } from '@dxos/context';\n\nimport { TimeoutError } from './errors.ts';\n\n/**\n * Times out after delay.\n */\nexport const sleep = (ms: number) => {\n return new Promise<void>((resolve) => {\n const finish = Date.now() + ms;\n\n // `setTimeout` does not guarantee execution at >= the scheduled time and may execute slightly early.\n const sleeper = () => {\n const delta = finish - Date.now();\n if (delta > 0) {\n setTimeout(sleeper, delta);\n } else {\n resolve();\n }\n };\n\n sleeper();\n });\n};\n\n// TODO(burdon): Reconcile with sleep.\nexport const sleepWithContext = (ctx: Context, ms: number) => {\n const error = new ContextDisposedError();\n return new Promise<void>((resolve, reject) => {\n if (ctx.disposed) {\n reject(error);\n return;\n }\n\n const timeout = setTimeout(() => {\n clearDispose();\n resolve();\n }, ms);\n\n const clearDispose = ctx.onDispose(() => {\n clearTimeout(timeout);\n reject(error);\n });\n });\n};\n\n/**\n * Can be used in long-running tasks to let other callbacks be invoked.\n */\nexport const asyncReturn = () => sleep(0);\n\n/**\n * Wait for promise or throw error.\n */\nexport const asyncTimeout = async <T>(promise: Promise<T>, timeout: number, err?: Error | string): Promise<T> => {\n if (typeof promise === 'function') {\n throw new Error('First argument must be a promise.');\n }\n\n let timeoutId: NodeJS.Timeout;\n const throwable = err === undefined || typeof err === 'string' ? new TimeoutError(timeout, err) : err;\n const timeoutPromise = new Promise<T>((resolve, reject) => {\n timeoutId = setTimeout(() => {\n reject(throwable);\n }, timeout);\n\n unrefTimeout(timeoutId);\n });\n\n return await Promise.race([promise, timeoutPromise]).finally(() => {\n clearTimeout(timeoutId);\n });\n};\n\n/**\n * In Node.JS, `unref` prevents the timeout from blocking the process from exiting. Not available in browsers.\n * https://nodejs.org/api/timers.html#timeoutunref\n */\nexport const unrefTimeout = (timeoutId: NodeJS.Timeout) => {\n if (typeof timeoutId === 'object' && 'unref' in timeoutId) {\n timeoutId.unref();\n }\n};\n","//\n// Copyright 2020 DXOS.org\n//\n\nimport { Context } from '@dxos/context';\nimport { type MaybePromise } from '@dxos/util';\n\nimport { type CleanupFn } from './cleanup.ts';\n\nexport type Effect = () => CleanupFn | undefined;\n\n/**\n * Effect that's been added to a specific Event.\n */\ninterface MaterializedEffect {\n effect: Effect;\n cleanup: CleanupFn | undefined;\n}\n\ninterface EventEmitterLike {\n on(event: string, cb: (data?: any) => void): void;\n off(event: string, cb: (data?: any) => void): void;\n}\n\nexport type ListenerOptions = {\n weak?: boolean;\n once?: boolean;\n};\n\ntype EventCallback<T> = (data: T) => MaybePromise<void>;\n\n// TODO(dmaretskyi): Remove this once the code is cleaned up.\nconst DO_NOT_ERROR_ON_ASYNC_CALLBACK = true;\n\n/**\n * An EventEmitter variant that does not do event multiplexing and represents a single event.\n *\n * ## Typical usage:\n * ```javascript\n * class Model {\n * public readonly update = new Event<UpdateData>();\n * private readonly privateEvent = new Event<void>();\n *\n * onUpdate(data: UpdateData) {\n * ...\n * this.update.emit(data);\n * }\n * }\n *\n * model.update.on(data => {\n * ...\n * });\n * ```\n *\n * ## Advantages over traditional EventEmitter:\n * 1. User describes explicitly what events a class has as they are defined as class fields.\n * 2. User can explicitly define event visibility (public, protected, private).\n * 3. Having events as class fields allows the compiler to check for correct event usage.\n * 4. User can type the data that event will be emitting.\n * 5. Uses composition instead of inheritance.\n * 6. Removes the cases where event names intersect when used in cases with inheritance.\n * 7. Remove the need to namespace events when developing a class with events that will be used as a base-class.\n */\n// TODO(burdon): Rename EventSink? (Event is a built-in type).\nexport class Event<T = void> implements ReadOnlyEvent<T> {\n /**\n * Wrap objects that have on/off style event emitters.\n */\n static wrap<T>(emitter: EventEmitterLike, eventName: string): Event<T> {\n const event = new Event<T>();\n\n event.addEffect(() => {\n const onEvent = (data: any) => event.emit(data);\n emitter.on(eventName, onEvent);\n return () => emitter.off(eventName, onEvent);\n });\n\n return event;\n }\n\n private readonly _listeners = new Set<EventListener<T>>();\n private readonly _effects = new Set<MaterializedEffect>();\n\n /**\n * Emit an event.\n * In most cases should only be called by the class or entity containing the event.\n * All listeners are called in order of subscription with persistent ones first.\n * Listeners are called synchronously in the same stack.\n * A thrown exception in the listener will stop the event from being emitted to the rest of the listeners.\n *\n * @param data param that will be passed to all listeners.\n */\n emit(data: T): void {\n for (const listener of this._listeners) {\n listener.trigger(data);\n\n if (listener.once) {\n this._listeners.delete(listener);\n }\n }\n }\n\n /**\n * Emit an event and wait for async listeners to complete.\n * In most cases should only be called by the class or entity containing the event.\n * All listeners are called in order of subscription with persistent ones first.\n * Listeners are called sequentially.\n *\n * @param data param that will be passed to all listeners.\n */\n async emitAsync(data: T): Promise<void> {\n for (const listener of this._listeners) {\n await listener.triggerAsync(data);\n\n if (listener.once) {\n this._listeners.delete(listener);\n }\n }\n }\n\n /**\n * Register an event listener.\n * If provided callback was already registered as once-listener, it is made permanent.\n *\n * @param callback\n * @param options.weak If true, the callback will be weakly referenced and will be garbage collected if no other references to it exist.\n * @returns function that unsubscribes this event listener\n */\n on(callback: EventCallback<T>): CleanupFn;\n on(ctx: Context, callback: EventCallback<T>, options?: ListenerOptions): CleanupFn;\n on(_ctx: any, _callback?: EventCallback<T>, options?: ListenerOptions): CleanupFn {\n const [ctx, callback] = _ctx instanceof Context ? [_ctx, _callback] : [new Context(), _ctx];\n const weak = !!options?.weak;\n const once = !!options?.once;\n\n const listener = new EventListener(this, callback, ctx, once, weak);\n\n this._addListener(listener);\n\n return () => {\n this._removeListener(listener);\n };\n }\n\n /**\n * Unsubscribe this callback from new events. Includes persistent and once-listeners.\n * NOTE: It is recommended to use `Event.on`'s return value instead.\n * If the callback is not subscribed this is no-op.\n *\n * @param callback\n */\n off(callback: (data: T) => void): void {\n for (const listener of this._listeners) {\n if (listener.derefCallback() === callback) {\n this._removeListener(listener);\n }\n }\n }\n\n /**\n * Register a callback to be called only once when the next event is emitted.\n * If this callback is already registered as permanent listener, this is no-op.\n *\n * @param callback\n */\n once(callback: (data: T) => void): CleanupFn;\n once(ctx: Context, callback: (data: T) => void): CleanupFn;\n once(_ctx: any, _callback?: (data: T) => void): CleanupFn {\n const [ctx, callback] = _ctx instanceof Context ? [_ctx, _callback] : [new Context(), _ctx];\n\n const listener = new EventListener(this, callback, ctx, true, false);\n\n this._addListener(listener);\n\n return () => {\n this._removeListener(listener);\n };\n }\n\n /**\n * An async iterator that iterates over events.\n * This iterator runs indefinitely.\n */\n async *[Symbol.asyncIterator](): AsyncIterator<T> {\n while (true) {\n yield await new Promise((resolve) => {\n this.once(resolve);\n });\n }\n }\n\n /**\n * Returns a promise that resolves with the first event emitted that matches the provided predicate.\n *\n * @param predicate\n */\n waitFor(predicate: (data: T) => boolean): Promise<T> {\n return new Promise((resolve) => {\n const unsubscribe = this.on((data) => {\n if (predicate(data)) {\n unsubscribe();\n resolve(data);\n }\n });\n });\n }\n\n /**\n * Returns a promise that resolves once a specific number of events was emitted since this method was called.\n *\n * @param expectedCount\n */\n waitForCount(expectedCount: number): Promise<T> {\n let count = 0;\n return this.waitFor(() => ++count === expectedCount);\n }\n\n /**\n * Similar to waitFor, but the promise resolves immediately if the condition is already true.\n */\n // TODO(burdon): Should pass event property to predicate.\n async waitForCondition(predicate: () => boolean): Promise<void> {\n if (!predicate()) {\n await this.waitFor(predicate);\n }\n }\n\n /**\n * Returns the number of persistent listeners.\n */\n listenerCount(): number {\n return this._listeners.size;\n }\n\n /**\n * Add a side effect that will be activated once the event has at least one subscriber.\n * The provided callback can return a function that will be used to clean up after the last subscriber unsubscribes from the event.\n * The API is similar to `useEffect` from React.\n *\n * ## Example:\n * ```typescript\n * event.addEffect(() => {\n * // do stuff\n * return () => {\n * // clean-up\n * };\n * });\n * ```\n *\n * @returns Callback that will remove this effect once called.\n */\n addEffect(effect: Effect): CleanupFn {\n const handle: MaterializedEffect = { effect, cleanup: undefined };\n\n if (this.listenerCount() > 0) {\n handle.cleanup = handle.effect();\n }\n\n this._effects.add(handle);\n return () => {\n // eslint-disable-next-line no-unused-expressions\n handle.cleanup?.();\n this._effects.delete(handle);\n };\n }\n\n /**\n * Triggers an event with at least `timeout` milliseconds between each event.\n * If the event is triggered more often, the event is delayed until the timeout is reached.\n * If event is emitted for the first time or event wasn't fired for `timeout` milliseconds,\n * the event is emitted after `timeout / 8` ms.\n */\n // TODO(burdon): Factor out generic function.\n debounce(timeout = 0): Event<void> {\n let firing: NodeJS.Timeout | undefined;\n let lastFired: number | undefined;\n\n const debouncedEvent = new Event<void>();\n debouncedEvent.addEffect(() => {\n const unsubscribe = this.on(() => {\n if (!firing) {\n const fireIn = !lastFired || Date.now() - lastFired > timeout ? timeout / 8 : timeout;\n firing = setTimeout(() => {\n lastFired = Date.now();\n firing = undefined;\n debouncedEvent.emit();\n }, fireIn);\n }\n });\n\n return () => {\n unsubscribe();\n clearTimeout(firing);\n };\n });\n\n return debouncedEvent;\n }\n\n /**\n * Turn any variant of `Event<T>` into an `Event<void>` discarding the callback parameter.\n */\n discardParameter(): Event<void> {\n return this as any;\n }\n\n /**\n * Pipe the events into another event.\n * @param event\n */\n pipeInto(event: Event<T>): CleanupFn {\n return this.on((data) => event.emit(data));\n }\n\n /**\n * Overridden to not return implementation details.\n */\n toJSON(): { listenerCount: number } {\n return {\n listenerCount: this.listenerCount(),\n };\n }\n\n private _addListener(listener: EventListener<T>): void {\n this._listeners.add(listener);\n\n if (this.listenerCount() === 1) {\n this._runEffects();\n }\n }\n\n /**\n * @internal\n */\n _removeListener(listener: EventListener<T>): void {\n this._listeners.delete(listener);\n listener.remove();\n\n if (this.listenerCount() === 0) {\n this._cleanupEffects();\n }\n }\n\n private _runEffects(): void {\n for (const handle of this._effects) {\n handle.cleanup = handle.effect();\n }\n }\n\n private _cleanupEffects(): void {\n for (const handle of this._effects) {\n // eslint-disable-next-line no-unused-expressions\n handle.cleanup?.();\n handle.cleanup = undefined;\n }\n }\n}\n\n/**\n * A version of Event class which only has subscribe methods.\n * Useful in cases where you want to explicitly prohibit calling `emit` method.\n */\nexport interface ReadOnlyEvent<T = void> {\n /**\n * Register an event listener.\n * If provided callback was already registered as once-listener, it is made permanent.\n *\n * @param callback\n * @param options.weak If true, the callback will be weakly referenced and will be garbage collected if no other references to it exist.\n * @returns function that unsubscribes this event listener\n */\n on(callback: (data: T) => void): CleanupFn;\n on(ctx: Context, callback: (data: T) => void, options?: ListenerOptions): CleanupFn;\n\n /**\n * Unsubscribes this callback from new events. Includes persistent and once-listeners.\n * NOTE: It is recommended to us `Event.on`'s return value.\n * If the callback is not subscribed this is no-op.\n *\n * @param callback\n */\n off(callback: (data: T) => void): void;\n\n /**\n * Register a callback to be called only once when the next event is emitted.\n * If this callback is already registered as permanent listener, this is no-op.\n *\n * @param callback\n */\n once(callback: (data: T) => void): CleanupFn;\n\n /**\n * An async iterator that iterates over events.\n * This iterator runs indefinitely.\n */\n [Symbol.asyncIterator](): AsyncIterator<T>;\n\n /**\n * Returns a promise that resolves with the first event emitted that matches the provided predicate.\n *\n * @param predicate\n */\n waitFor(predicate: (data: T) => boolean): Promise<T>;\n\n /**\n * Returns a promise that resolves once a specific number of events was emitted since this method was called.\n *\n * @param expectedCount\n */\n waitForCount(expectedCount: number): Promise<T>;\n\n /**\n * Turn any variant of `Event<T>` into an `Event<void>` discarding the callback parameter.\n */\n discardParameter(): Event<void>;\n\n /**\n * Triggers an event with at least `timeout` milliseconds between each event.\n * If the event is triggered more often, the event is delayed until the timeout is reached.\n * If event is emitted for the first time or event wasn't fired for `timeout` milliseconds,\n * the event is emitted after `timeout / 8` ms.\n */\n debounce(timeout?: number): Event<void>;\n}\n\nclass EventListener<T> {\n public readonly callback: EventCallback<T> | WeakRef<EventCallback<T>>;\n\n private readonly _clearDispose?: () => void = undefined;\n\n constructor(\n event: Event<T>,\n listener: EventCallback<T>,\n public readonly ctx: Context,\n public readonly once: boolean,\n public readonly weak: boolean,\n ) {\n this._clearDispose = ctx.onDispose(() => {\n event._removeListener(this);\n });\n\n if (weak) {\n this.callback = new WeakRef(listener);\n weakListeners().registry?.register(\n listener,\n {\n event: new WeakRef(event),\n listener: this,\n },\n this,\n );\n } else {\n this.callback = listener;\n }\n }\n\n derefCallback(): EventCallback<T> | undefined {\n return this.weak ? (this.callback as WeakRef<EventCallback<T>>).deref() : (this.callback as EventCallback<T>);\n }\n\n trigger(data: T): void {\n let result!: MaybePromise<void>;\n try {\n const callback = this.derefCallback();\n result = callback?.(data);\n } catch (err: any) {\n this.ctx.raise(err);\n }\n\n if (!DO_NOT_ERROR_ON_ASYNC_CALLBACK) {\n if (result instanceof Promise) {\n throw new TypeError('Event has async callbacks, use emitAsync instead');\n }\n }\n }\n\n async triggerAsync(data: T): Promise<void> {\n try {\n const callback = this.derefCallback();\n await callback?.(data);\n } catch (err: any) {\n this.ctx.raise(err);\n }\n }\n\n remove(): void {\n this._clearDispose?.();\n weakListeners().registry?.unregister(this);\n }\n}\n\ntype HeldValue = {\n event: WeakRef<Event<any>>;\n listener: EventListener<any>;\n};\n\nlet weakListenersState: FinalizationRegistry<HeldValue> | null = null;\n\ntype WeakListeners = {\n registry: FinalizationRegistry<HeldValue> | undefined;\n};\n\nconst FINALIZATION_REGISTRY_SUPPORTED = !!globalThis.FinalizationRegistry;\n\nconst weakListeners = (): WeakListeners => {\n if (!FINALIZATION_REGISTRY_SUPPORTED) {\n return { registry: undefined };\n }\n weakListenersState ??= new FinalizationRegistry(({ event, listener }) => {\n event.deref()?._removeListener(listener);\n });\n return { registry: weakListenersState };\n};\n"],"mappings":"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"}
|
package/dist/lib/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { a as sleepWithContext, c as observableError, i as sleep, l as toError, n as asyncReturn, o as unrefTimeout, r as asyncTimeout, s as TimeoutError, t as Event } from "./chunk-events.mjs";
|
|
2
|
-
import { ComplexMap, createSetDispatch, throwUnhandledError } from "@dxos/util";
|
|
2
|
+
import { ComplexMap, createSetDispatch, isNode, throwUnhandledError } from "@dxos/util";
|
|
3
3
|
import { Context, ContextDisposedError, LifecycleState, Resource, cancelWithContext } from "@dxos/context";
|
|
4
4
|
import { StackTrace, warnAfterTimeout } from "@dxos/debug";
|
|
5
5
|
import Observable from "zen-observable";
|
|
@@ -1025,6 +1025,8 @@ var makePushIterable = () => {
|
|
|
1025
1025
|
//#endregion
|
|
1026
1026
|
//#region src/stream.ts
|
|
1027
1027
|
var __dxlog_file = "/__w/dxos/dxos/packages/common/async/src/stream.ts";
|
|
1028
|
+
/** Narrows a caught `unknown` to `Error` — a thrown value is not guaranteed to be one. */
|
|
1029
|
+
var toCaughtError = (err) => err instanceof Error ? err : new Error(String(err));
|
|
1028
1030
|
/**
|
|
1029
1031
|
* Represents a typed stream of data.
|
|
1030
1032
|
* In concept it's a Promise that can resolve multiple times.
|
|
@@ -1143,7 +1145,7 @@ var Stream = class Stream {
|
|
|
1143
1145
|
}, {
|
|
1144
1146
|
"~LogMeta": "~LogMeta",
|
|
1145
1147
|
F: __dxlog_file,
|
|
1146
|
-
L:
|
|
1148
|
+
L: 201
|
|
1147
1149
|
});
|
|
1148
1150
|
this._ctx.onDispose(() => this.close());
|
|
1149
1151
|
try {
|
|
@@ -1157,7 +1159,7 @@ var Stream = class Stream {
|
|
|
1157
1159
|
log("Stream is closed, dropping message.", void 0, {
|
|
1158
1160
|
"~LogMeta": "~LogMeta",
|
|
1159
1161
|
F: __dxlog_file,
|
|
1160
|
-
L:
|
|
1162
|
+
L: 227,
|
|
1161
1163
|
S: this
|
|
1162
1164
|
});
|
|
1163
1165
|
return;
|
|
@@ -1166,13 +1168,13 @@ var Stream = class Stream {
|
|
|
1166
1168
|
if (this._messageHandler) try {
|
|
1167
1169
|
this._messageHandler(msg);
|
|
1168
1170
|
} catch (err) {
|
|
1169
|
-
throwUnhandledError(err);
|
|
1171
|
+
throwUnhandledError(toCaughtError(err));
|
|
1170
1172
|
}
|
|
1171
1173
|
else {
|
|
1172
1174
|
invariant(this._buffer, void 0, {
|
|
1173
1175
|
"~LogMeta": "~LogMeta",
|
|
1174
1176
|
F: __dxlog_file,
|
|
1175
|
-
L:
|
|
1177
|
+
L: 241,
|
|
1176
1178
|
S: this,
|
|
1177
1179
|
A: ["this._buffer", ""]
|
|
1178
1180
|
});
|
|
@@ -1187,14 +1189,14 @@ var Stream = class Stream {
|
|
|
1187
1189
|
try {
|
|
1188
1190
|
this._closeHandler?.(err);
|
|
1189
1191
|
} catch (err) {
|
|
1190
|
-
throwUnhandledError(err);
|
|
1192
|
+
throwUnhandledError(toCaughtError(err));
|
|
1191
1193
|
}
|
|
1192
1194
|
this._ctx.dispose();
|
|
1193
1195
|
}
|
|
1194
1196
|
});
|
|
1195
1197
|
if (producerCleanup) this._producerCleanup = producerCleanup;
|
|
1196
1198
|
} catch (err) {
|
|
1197
|
-
this._ctx.raise(err);
|
|
1199
|
+
this._ctx.raise(toCaughtError(err));
|
|
1198
1200
|
}
|
|
1199
1201
|
}
|
|
1200
1202
|
_markAsReady() {
|
|
@@ -1208,28 +1210,28 @@ var Stream = class Stream {
|
|
|
1208
1210
|
invariant(!this._messageHandler, "Stream is already subscribed to.", {
|
|
1209
1211
|
"~LogMeta": "~LogMeta",
|
|
1210
1212
|
F: __dxlog_file,
|
|
1211
|
-
L:
|
|
1213
|
+
L: 282,
|
|
1212
1214
|
S: this,
|
|
1213
1215
|
A: ["!this._messageHandler", "'Stream is already subscribed to.'"]
|
|
1214
1216
|
});
|
|
1215
1217
|
invariant(!this._closeHandler, "Stream is already subscribed to.", {
|
|
1216
1218
|
"~LogMeta": "~LogMeta",
|
|
1217
1219
|
F: __dxlog_file,
|
|
1218
|
-
L:
|
|
1220
|
+
L: 283,
|
|
1219
1221
|
S: this,
|
|
1220
1222
|
A: ["!this._closeHandler", "'Stream is already subscribed to.'"]
|
|
1221
1223
|
});
|
|
1222
1224
|
invariant(this._buffer, void 0, {
|
|
1223
1225
|
"~LogMeta": "~LogMeta",
|
|
1224
1226
|
F: __dxlog_file,
|
|
1225
|
-
L:
|
|
1227
|
+
L: 284,
|
|
1226
1228
|
S: this,
|
|
1227
1229
|
A: ["this._buffer", ""]
|
|
1228
1230
|
});
|
|
1229
1231
|
for (const message of this._buffer) try {
|
|
1230
1232
|
onMessage(message);
|
|
1231
1233
|
} catch (err) {
|
|
1232
|
-
throwUnhandledError(err);
|
|
1234
|
+
throwUnhandledError(toCaughtError(err));
|
|
1233
1235
|
}
|
|
1234
1236
|
this._buffer = null;
|
|
1235
1237
|
if (this._isClosed) {
|
|
@@ -1252,7 +1254,7 @@ var Stream = class Stream {
|
|
|
1252
1254
|
invariant(!this._readyHandler, "Stream already has a handler for the ready event.", {
|
|
1253
1255
|
"~LogMeta": "~LogMeta",
|
|
1254
1256
|
F: __dxlog_file,
|
|
1255
|
-
L:
|
|
1257
|
+
L: 319,
|
|
1256
1258
|
S: this,
|
|
1257
1259
|
A: ["!this._readyHandler", "'Stream already has a handler for the ready event.'"]
|
|
1258
1260
|
});
|
|
@@ -1516,7 +1518,7 @@ var UpdateScheduler = class {
|
|
|
1516
1518
|
if (this._params.maxFrequency) {
|
|
1517
1519
|
const now = performance.now();
|
|
1518
1520
|
const delay = this._lastUpdateTime + TIME_PERIOD / this._params.maxFrequency - now;
|
|
1519
|
-
if (delay > 0) {
|
|
1521
|
+
if (delay > 0 && this._skipDelay.state !== TriggerState.RESOLVED) {
|
|
1520
1522
|
const skipDelay = this._skipDelay;
|
|
1521
1523
|
await new Promise((resolve) => {
|
|
1522
1524
|
const timeoutId = setTimeout(() => {
|
|
@@ -1589,6 +1591,56 @@ var UpdateScheduler = class {
|
|
|
1589
1591
|
}
|
|
1590
1592
|
};
|
|
1591
1593
|
//#endregion
|
|
1592
|
-
|
|
1594
|
+
//#region src/yield.ts
|
|
1595
|
+
/** One channel for every yield: a port per call would leave an open handle behind each one. */
|
|
1596
|
+
var channel;
|
|
1597
|
+
var waiting = [];
|
|
1598
|
+
var yieldViaMessageChannel = () => new Promise((resolve) => {
|
|
1599
|
+
if (!channel) {
|
|
1600
|
+
channel = new MessageChannel();
|
|
1601
|
+
channel.port1.onmessage = () => waiting.shift()?.();
|
|
1602
|
+
}
|
|
1603
|
+
waiting.push(resolve);
|
|
1604
|
+
channel.port2.postMessage(void 0);
|
|
1605
|
+
});
|
|
1606
|
+
/**
|
|
1607
|
+
* Resolves in a later task so queued input and rendering get a turn between slices of a long job.
|
|
1608
|
+
*
|
|
1609
|
+
* `scheduler.yield` keeps the continuation ahead of other same-priority work where the host has it.
|
|
1610
|
+
* A message task is the browser fallback because timers are clamped in a hidden tab, which would
|
|
1611
|
+
* stall a background sync; Node drains message ports without visiting its timers, so it gets the
|
|
1612
|
+
* timer instead.
|
|
1613
|
+
*/
|
|
1614
|
+
var yieldToEventLoop = () => {
|
|
1615
|
+
const scheduler = globalThis.scheduler;
|
|
1616
|
+
if (scheduler?.yield) return scheduler.yield();
|
|
1617
|
+
if (!isNode() && typeof MessageChannel !== "undefined") return yieldViaMessageChannel();
|
|
1618
|
+
return new Promise((resolve) => setTimeout(resolve, 0));
|
|
1619
|
+
};
|
|
1620
|
+
var SLICE_BUDGET_MS = {
|
|
1621
|
+
interactive: 83,
|
|
1622
|
+
smooth: 13,
|
|
1623
|
+
idle: 5
|
|
1624
|
+
};
|
|
1625
|
+
var sliceUntilNextTurn;
|
|
1626
|
+
var openSliceUntilNextTurn = () => {
|
|
1627
|
+
if (!sliceUntilNextTurn) {
|
|
1628
|
+
const started = { start: performance.now() };
|
|
1629
|
+
sliceUntilNextTurn = started;
|
|
1630
|
+
yieldToEventLoop().then(() => {
|
|
1631
|
+
if (sliceUntilNextTurn === started) sliceUntilNextTurn = void 0;
|
|
1632
|
+
});
|
|
1633
|
+
}
|
|
1634
|
+
return sliceUntilNextTurn;
|
|
1635
|
+
};
|
|
1636
|
+
/** Whether the current slice has used its strategy's budget, for callers that yield by other means. */
|
|
1637
|
+
var shouldYield = (strategy) => performance.now() - openSliceUntilNextTurn().start >= SLICE_BUDGET_MS[strategy];
|
|
1638
|
+
/** Yields to the event loop once the current slice has used its strategy's budget, and resolves at once otherwise. */
|
|
1639
|
+
var yieldOrContinue = async (strategy) => {
|
|
1640
|
+
if (!shouldYield(strategy)) return;
|
|
1641
|
+
await yieldToEventLoop();
|
|
1642
|
+
};
|
|
1643
|
+
//#endregion
|
|
1644
|
+
export { AsyncTask, CancellableObservableProvider, DeferredTask, Event, MulticastObservable, Mutex, MutexGuard, Observable, ObservableProvider, PersistentLifecycle, PushStream, Stream, SubscriptionList, SubscriptionSet, TimeoutError, Timer, Trigger, TriggerState, UpdateScheduler, addEventListener, addListener, asyncReturn, asyncTimeout, chain, combine, debounce, debounceAndThrottle, delay, dumpLeaks, getFirstStreamValue, interval, latch, makePushIterable, observableError, onEvent, promiseFromCallback, runInContext, runInContextAsync, scheduleExponentialBackoffTaskInterval, scheduleMicroTask, scheduleTask, scheduleTaskInterval, shouldYield, sleep, sleepWithContext, streamToArray, synchronized, throttle, timeout, toError, trackLeaks, trackResource, trigger, unrefTimeout, until, untilError, untilPromise, waitForCondition, waitForEvent, yieldOrContinue, yieldToEventLoop };
|
|
1593
1645
|
|
|
1594
1646
|
//# sourceMappingURL=index.mjs.map
|