diff --git a/e2e/reporters/recorder.ts b/e2e/reporters/recorder.js similarity index 96% rename from e2e/reporters/recorder.ts rename to e2e/reporters/recorder.js index 8e454f4..a6501d5 100644 --- a/e2e/reporters/recorder.ts +++ b/e2e/reporters/recorder.js @@ -89,11 +89,6 @@ class E2eRecorderReporter extends JestMetadataReporter { await debugUtils.aggregateLogs(); } } - - static onTestEnvironmentCreate(env) { - console.log('I AM ALIVE'); - console.log(' ..--..'); - } } function sleep(ms) { diff --git a/environment-decorator.js b/environment-decorator.js index 3089cdc..721ceaf 100644 --- a/environment-decorator.js +++ b/environment-decorator.js @@ -1,2 +1,2 @@ /* Jest 27 fallback */ -module.exports = require('./dist/environment-listener'); +module.exports = require('./dist/environment-decorator'); diff --git a/environment-listener.js b/environment-listener.js new file mode 100644 index 0000000..3089cdc --- /dev/null +++ b/environment-listener.js @@ -0,0 +1,2 @@ +/* Jest 27 fallback */ +module.exports = require('./dist/environment-listener'); diff --git a/src/environment-listener.ts b/src/environment-listener.ts index 19c1b38..68585b2 100644 --- a/src/environment-listener.ts +++ b/src/environment-listener.ts @@ -4,9 +4,8 @@ import { JestMetadataError } from './errors'; import { detectDuplicateRealms, injectRealmIntoSandbox, realm } from './realms'; import { jestUtils, logger } from './utils'; -const log = logger.child({ cat: 'environment', tid: 'environment' }); - const listener: EnvironmentListenerFn = (context) => { + const log = logger.child({ cat: 'environment', tid: 'environment' }); const jestEnvironment = context.env; const jestEnvironmentConfig = context.config; const environmentContext = context.context; diff --git a/src/jest-reporter/__tests__/fallback-api.test.ts b/src/jest-reporter/__tests__/fallback-api.test.ts index 7b9215b..2bc2d03 100644 --- a/src/jest-reporter/__tests__/fallback-api.test.ts +++ b/src/jest-reporter/__tests__/fallback-api.test.ts @@ -8,7 +8,7 @@ import { MetadataFactoryImpl, WriteMetadataEventEmitter, } from '../../metadata'; -import { SerialSyncEmitter } from '../../utils'; +import { SerialEmitter } from '../../utils'; import { AssociateMetadata } from '../AssociateMetadata'; import { FallbackAPI } from '../FallbackAPI'; import { QueryMetadata } from '../QueryMetadata'; @@ -23,10 +23,10 @@ describe('Fallback API', () => { const IPCServer = jest.requireMock('../../ipc').IPCServer; const ipc: jest.Mocked = new IPCServer(); - const emitter = new SerialSyncEmitter('core').on('*', (event: MetadataEvent) => { + const emitter = new SerialEmitter('core').on('*', (event: MetadataEvent) => { metadataHandler.handle(event); }) as MetadataEventEmitter; - const setEmitter = new SerialSyncEmitter('set') as WriteMetadataEventEmitter; + const setEmitter = new SerialEmitter('set') as WriteMetadataEventEmitter; const metadataRegistry = new GlobalMetadataRegistry(); const metadataFactory = new MetadataFactoryImpl(metadataRegistry, setEmitter); const globalMetadata = metadataFactory.createGlobalMetadata(); diff --git a/src/metadata/__tests__/integration.test.ts b/src/metadata/__tests__/integration.test.ts index 6d98e1a..9810686 100644 --- a/src/metadata/__tests__/integration.test.ts +++ b/src/metadata/__tests__/integration.test.ts @@ -1,6 +1,6 @@ import fixtures from '../../../e2e'; -import { SerialSyncEmitter } from '../../utils'; +import { SerialEmitter } from '../../utils'; import { PlantSerializer } from '../__utils__'; import { GlobalMetadataRegistry, @@ -13,7 +13,7 @@ describe('metadata - integration test:', () => { test.each(Object.values(fixtures.metadata))( `e2e/__fixtures__/%s`, (_name: string, fixture: any[]) => { - const emitter: WriteMetadataEventEmitter = new SerialSyncEmitter('set'); + const emitter: WriteMetadataEventEmitter = new SerialEmitter('set'); const metadataRegistry = new GlobalMetadataRegistry(); const metadataFactory = new MetadataFactoryImpl(metadataRegistry, emitter); const globalMetadata = metadataFactory.createGlobalMetadata(); diff --git a/src/metadata/__tests__/run-traversal.test.ts b/src/metadata/__tests__/run-traversal.test.ts index 8471fb5..d9fdcd2 100644 --- a/src/metadata/__tests__/run-traversal.test.ts +++ b/src/metadata/__tests__/run-traversal.test.ts @@ -1,6 +1,6 @@ import fixtures from '../../../e2e'; -import { SerialSyncEmitter } from '../../utils'; +import { SerialEmitter } from '../../utils'; import { GlobalMetadataRegistry, Metadata, @@ -15,7 +15,7 @@ describe('file metadata traversal:', () => { }); test.each(lastFixtures)(`fixtures/%s`, (_name: string, fixture: any[]) => { - const emitter: WriteMetadataEventEmitter = new SerialSyncEmitter('set'); + const emitter: WriteMetadataEventEmitter = new SerialEmitter('set'); const metadataRegistry = new GlobalMetadataRegistry(); const metadataFactory = new MetadataFactoryImpl(metadataRegistry, emitter); const globalMetadata = metadataFactory.createGlobalMetadata(); diff --git a/src/realms/BaseRealm.ts b/src/realms/BaseRealm.ts index aad73a9..397b423 100644 --- a/src/realms/BaseRealm.ts +++ b/src/realms/BaseRealm.ts @@ -12,18 +12,16 @@ import { WriteMetadataEventEmitter, } from '../metadata'; -import { AggregatedEmitter, SerialSyncEmitter } from '../utils'; +import { AggregatedEmitter, SerialEmitter } from '../utils'; export abstract class BaseRealm { - readonly coreEmitter = new SerialSyncEmitter('core').on( + readonly coreEmitter = new SerialEmitter('core').on( '*', (event: MetadataEvent) => { this.metadataHandler.handle(event); }, ) as MetadataEventEmitter; - readonly setEmitter = new SerialSyncEmitter( - 'set', - ) as WriteMetadataEventEmitter; + readonly setEmitter = new SerialEmitter('set') as WriteMetadataEventEmitter; readonly events = new AggregatedEmitter('events').add(this.coreEmitter); readonly metadataRegistry = new GlobalMetadataRegistry(); diff --git a/src/utils/emitters/AggregatedEmitter.test.ts b/src/utils/emitters/AggregatedEmitter.test.ts index 25718ea..68d4afe 100644 --- a/src/utils/emitters/AggregatedEmitter.test.ts +++ b/src/utils/emitters/AggregatedEmitter.test.ts @@ -1,5 +1,5 @@ import { AggregatedEmitter } from './AggregatedEmitter'; -import { SerialSyncEmitter } from './SerialSyncEmitter'; +import { SerialEmitter } from './SerialEmitter'; describe('AggregatedEmitter', () => { let emitter: AggregatedEmitter<{ type: string }>; @@ -9,8 +9,8 @@ describe('AggregatedEmitter', () => { }); test('should re-emit events of added #emitters', () => { - const dummy1 = new SerialSyncEmitter('dummy1'); - const dummy2 = new SerialSyncEmitter('dummy2'); + const dummy1 = new SerialEmitter('dummy1'); + const dummy2 = new SerialEmitter('dummy2'); const listener = jest.fn(); const event1 = { type: 'test', id: 1 }; const event2 = { type: 'test', id: 2 }; @@ -26,8 +26,8 @@ describe('AggregatedEmitter', () => { }); test('should allow subscribing to events only once', () => { - const dummy1 = new SerialSyncEmitter('dummy1'); - const dummy2 = new SerialSyncEmitter('dummy2'); + const dummy1 = new SerialEmitter('dummy1'); + const dummy2 = new SerialEmitter('dummy2'); const listener = jest.fn(); const event1 = { type: 'test', id: 1 }; const event2 = { type: 'test', id: 2 }; @@ -42,7 +42,7 @@ describe('AggregatedEmitter', () => { }); test('should allow unsubscribing from events', () => { - const dummy = new SerialSyncEmitter('dummy1'); + const dummy = new SerialEmitter('dummy1'); const listener = jest.fn(); const event = { type: 'test', id: 1 }; diff --git a/src/utils/emitters/AggregatedEmitter.ts b/src/utils/emitters/AggregatedEmitter.ts index d5d7fd4..06a8e8c 100644 --- a/src/utils/emitters/AggregatedEmitter.ts +++ b/src/utils/emitters/AggregatedEmitter.ts @@ -1,12 +1,12 @@ import type { Emitter, ReadonlyEmitter } from '../../types'; -import { SerialSyncEmitter } from './SerialSyncEmitter'; +import { SerialEmitter } from './SerialEmitter'; export class AggregatedEmitter implements ReadonlyEmitter { readonly #emitters = new WeakSet>(); - readonly #rootEmitter: SerialSyncEmitter; + readonly #rootEmitter: SerialEmitter; constructor(name: string) { - this.#rootEmitter = new SerialSyncEmitter(name); + this.#rootEmitter = new SerialEmitter(name); } add(emitter: Emitter): this { diff --git a/src/utils/emitters/ReadonlyEmitterBase.ts b/src/utils/emitters/ReadonlyEmitterBase.ts deleted file mode 100644 index 5699424..0000000 --- a/src/utils/emitters/ReadonlyEmitterBase.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* eslint-disable @typescript-eslint/ban-types */ -import type { ReadonlyEmitter } from '../../types'; -import { iterateSorted } from '../iterateSorted'; -import { logger, nologger, optimizeTracing } from '../logger'; - -//#region Optimized event helpers - -const __CATEGORY_LISTENERS = ['listeners']; -const __LISTENERS = optimizeTracing((listener: unknown) => ({ - cat: __CATEGORY_LISTENERS, - fn: `${listener}`, -})); - -//#endregion - -const ONCE: unique symbol = Symbol('ONCE'); - -export abstract class ReadonlyEmitterBase - implements ReadonlyEmitter -{ - protected readonly _log: typeof logger; - protected readonly _listeners: Map = new Map(); - - #listenersCounter = 0; - - constructor(name?: string, shouldLog = true) { - this._log = (shouldLog ? logger : nologger).child({ cat: `emitter`, tid: `emitter-${name}` }); - this._listeners.set('*', []); - } - - on( - type: E['type'] | '*', - listener: Function & { [ONCE]?: true }, - order?: number, - ): this { - if (!listener[ONCE]) { - this._log.trace(__LISTENERS(listener), `on(${type})`); - } - - if (!this._listeners.has(type)) { - this._listeners.set(type, []); - } - - const listeners = this._listeners.get(type)!; - listeners.push([listener, order ?? this.#listenersCounter++]); - listeners.sort((a, b) => getOrder(a) - getOrder(b)); - - return this; - } - - once(type: E['type'] | '*', listener: Function, order?: number): this { - this._log.trace(__LISTENERS(listener), `once(${type})`); - return this.on(type, this.#createOnceListener(type, listener), order); - } - - off( - type: E['type'] | '*', - listener: Function & { [ONCE]?: true }, - _order?: number, - ): this { - if (!listener[ONCE]) { - this._log.trace(__LISTENERS(listener), `off(${type})`); - } - - const listeners = this._listeners.get(type) || []; - const index = listeners.findIndex(([l]) => l === listener); - if (index !== -1) { - listeners.splice(index, 1); - } - return this; - } - - protected *_getListeners(type: Event['type']): Iterable { - const wildcard: [Function, number][] = this._listeners.get('*') ?? []; - const named: [Function, number][] = this._listeners.get(type) ?? []; - for (const [listener] of iterateSorted<[Function, number]>(getOrder, wildcard, named)) { - yield listener; - } - } - - #createOnceListener(type: Event['type'], listener: Function) { - const onceListener = ((event: Event) => { - this.off(type, onceListener); - listener(event); - }) as Function & { [ONCE]?: true }; - - onceListener[ONCE] = true as const; - return onceListener; - } -} - -function getOrder([_a, b]: [T, number]): number { - return b; -} diff --git a/src/utils/emitters/SemiAsyncEmitter.ts b/src/utils/emitters/SemiAsyncEmitter.ts deleted file mode 100644 index 52825e5..0000000 --- a/src/utils/emitters/SemiAsyncEmitter.ts +++ /dev/null @@ -1,62 +0,0 @@ -import type { ReadonlyAsyncEmitter } from '../../types'; -import { SerialAsyncEmitter } from './SerialAsyncEmitter'; -import { SerialSyncEmitter } from './SerialSyncEmitter'; - -export class SemiAsyncEmitter - implements ReadonlyAsyncEmitter -{ - readonly #asyncEmitter: SerialAsyncEmitter; - readonly #syncEmitter: SerialSyncEmitter; - readonly #syncEvents: Set; - - constructor(name: string, syncEvents: Event['type'][]) { - this.#asyncEmitter = new SerialAsyncEmitter(name, false); - this.#syncEmitter = new SerialSyncEmitter(name, false); - this.#syncEvents = new Set(syncEvents); - } - - on( - type: E['type'] | '*', - listener: (event: E) => unknown, - order?: number, - ): this { - return this.#invoke('on', type, listener, order); - } - - once( - type: E['type'] | '*', - listener: (event: E) => unknown, - order?: number, - ): this { - return this.#invoke('once', type, listener, order); - } - - off(type: E['type'] | '*', listener: (event: E) => unknown): this { - return this.#invoke('off', type, listener); - } - - emit(event: Event): void | Promise { - return this.#syncEvents.has(event.type as Event['type']) - ? this.#syncEmitter.emit(event) - : this.#asyncEmitter.emit(event); - } - - #invoke( - methodName: 'on' | 'once' | 'off', - type: E['type'] | '*', - listener: (event: E) => unknown, - order?: number, - ): this { - const isSync = this.#syncEvents.has(type); - - if (type === '*' || isSync) { - this.#syncEmitter[methodName](type, listener, order); - } - - if (type === '*' || !isSync) { - this.#asyncEmitter[methodName](type, listener as (event: Event) => Promise, order); - } - - return this; - } -} diff --git a/src/utils/emitters/SerialAsyncEmitter.ts b/src/utils/emitters/SerialAsyncEmitter.ts deleted file mode 100644 index 1ccdda1..0000000 --- a/src/utils/emitters/SerialAsyncEmitter.ts +++ /dev/null @@ -1,32 +0,0 @@ -import type { AsyncEmitter } from '../../types'; -import { ReadonlyEmitterBase } from './ReadonlyEmitterBase'; -import { __EMIT, __INVOKE } from './syncEmitterCommons'; - -export class SerialAsyncEmitter - extends ReadonlyEmitterBase - implements AsyncEmitter -{ - #promise = Promise.resolve(); - - emit(event: Event): Promise { - return this.#enqueue(event); - } - - #enqueue(event: Event) { - return (this.#promise = this.#promise.then(() => this.#doEmit(event))); - } - - async #doEmit(event: Event) { - const eventType = event.type; - const listeners = [...this._getListeners(eventType)]; - - await this._log.trace.complete(__EMIT(event), event.type, async () => { - if (listeners) { - for (const listener of listeners) { - this._log.trace(__INVOKE(listener), 'invoke'); - await listener(event); - } - } - }); - } -} diff --git a/src/utils/emitters/SerialSyncEmitter.test.ts b/src/utils/emitters/SerialEmitter.test.ts similarity index 85% rename from src/utils/emitters/SerialSyncEmitter.test.ts rename to src/utils/emitters/SerialEmitter.test.ts index 0ef56da..944e5f8 100644 --- a/src/utils/emitters/SerialSyncEmitter.test.ts +++ b/src/utils/emitters/SerialEmitter.test.ts @@ -1,8 +1,8 @@ -import { SerialSyncEmitter } from './SerialSyncEmitter'; +import { SerialEmitter } from './SerialEmitter'; -describe('SerialSyncEmitter', () => { +describe('SerialEmitter', () => { it('should emit events', () => { - const emitter = new SerialSyncEmitter(); + const emitter = new SerialEmitter(); const listener = jest.fn(); emitter.on('test', listener); @@ -16,7 +16,7 @@ describe('SerialSyncEmitter', () => { }); it('should allow subscribing to events only once', () => { - const emitter = new SerialSyncEmitter(); + const emitter = new SerialEmitter(); const listener = jest.fn(); emitter.once('test', listener); emitter.emit({ type: 'test', payload: 42 }); @@ -26,7 +26,7 @@ describe('SerialSyncEmitter', () => { }); it('should allow subscribing to all events', () => { - const emitter = new SerialSyncEmitter(); + const emitter = new SerialEmitter(); const listener = jest.fn(); emitter.on('*', listener); emitter.emit({ type: 'test', payload: 42 }); @@ -38,7 +38,7 @@ describe('SerialSyncEmitter', () => { }); it('should allow unsubscribing from events', () => { - const emitter = new SerialSyncEmitter(); + const emitter = new SerialEmitter(); const listener = jest.fn(); emitter.on('test', listener); emitter.emit({ type: 'test', payload: 42 }); @@ -49,7 +49,7 @@ describe('SerialSyncEmitter', () => { }); it('should delay emits within emits', () => { - const emitter = new SerialSyncEmitter(); + const emitter = new SerialEmitter(); const listener1 = jest.fn(() => emitter.emit({ type: 'test', payload: 84 })); const listener2 = jest.fn(); emitter.once('test', listener1); diff --git a/src/utils/emitters/SerialEmitter.ts b/src/utils/emitters/SerialEmitter.ts new file mode 100644 index 0000000..3bda9e5 --- /dev/null +++ b/src/utils/emitters/SerialEmitter.ts @@ -0,0 +1,124 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import type { Emitter } from '../../types'; + +import { logger, nologger, optimizeTracing } from '../logger'; + +//#region Optimized event helpers + +const CATEGORIES = { + ENQUEUE: ['enqueue'], + EMIT: ['emit'], + INVOKE: ['invoke'], + LISTENERS: ['listeners'], +}; + +const __EMIT = optimizeTracing((event: unknown) => ({ cat: CATEGORIES.EMIT, event })); +const __ENQUEUE = optimizeTracing((event: unknown) => ({ + cat: CATEGORIES.ENQUEUE, + event, +})); +const __INVOKE = optimizeTracing((listener: unknown, type?: '*') => ({ + cat: CATEGORIES.INVOKE, + fn: `${listener}`, + type, +})); +const __LISTENERS = optimizeTracing((listener: unknown) => ({ + cat: CATEGORIES.LISTENERS, + fn: `${listener}`, +})); + +//#endregion + +const ONCE: unique symbol = Symbol('ONCE'); + +/** + * An event emitter that emits events in the order they are received. + * If an event is emitted while another event is being emitted, the new event + * will be queued and emitted after the current event is finished. + */ +export class SerialEmitter implements Emitter { + protected readonly _log: typeof logger; + protected readonly _listeners: Map = new Map(); + + #queue: Event[] = []; + + constructor(name?: string, shouldLog = true) { + this._log = (shouldLog ? logger : nologger).child({ cat: `emitter`, tid: `emitter-${name}` }); + this._listeners.set('*', []); + } + + on(type: E['type'] | '*', listener: Function & { [ONCE]?: true }): this { + if (!listener[ONCE]) { + this._log.trace(__LISTENERS(listener), `on(${type})`); + } + + if (!this._listeners.has(type)) { + this._listeners.set(type, []); + } + + const listeners = this._listeners.get(type)!; + listeners.push(listener); + + return this; + } + + once(type: E['type'] | '*', listener: Function): this { + this._log.trace(__LISTENERS(listener), `once(${type})`); + return this.on(type, this.#createOnceListener(type, listener)); + } + + off(type: E['type'] | '*', listener: Function & { [ONCE]?: true }): this { + if (!listener[ONCE]) { + this._log.trace(__LISTENERS(listener), `off(${type})`); + } + + const listeners = this._listeners.get(type) || []; + const index = listeners.indexOf(listener); + if (index !== -1) { + listeners.splice(index, 1); + } + return this; + } + + emit(nextEvent: Event): void { + this.#queue.push(Object.freeze(nextEvent)); + + if (this.#queue.length > 1) { + this._log.trace(__ENQUEUE(nextEvent), `enqueue(${nextEvent.type})`); + return; + } + + while (this.#queue.length > 0) { + const event = this.#queue[0]; + const eventType = event.type; + const listeners = this._getListeners(eventType); + + this._log.trace.complete(__EMIT(event), event.type, () => { + if (listeners) { + for (const listener of listeners) { + this._log.trace(__INVOKE(listener), 'invoke'); + listener(event); + } + } + }); + + this.#queue.shift(); + } + } + + protected _getListeners(type: Event['type']): Function[] { + const wildcard: Function[] = this._listeners.get('*') ?? []; + const named: Function[] = this._listeners.get(type) ?? []; + return [...wildcard, ...named]; + } + + #createOnceListener(type: Event['type'], listener: Function) { + const onceListener = ((event: Event) => { + this.off(type, onceListener); + listener(event); + }) as Function & { [ONCE]?: true }; + + onceListener[ONCE] = true as const; + return onceListener; + } +} diff --git a/src/utils/emitters/SerialSyncEmitter.ts b/src/utils/emitters/SerialSyncEmitter.ts deleted file mode 100644 index 1407377..0000000 --- a/src/utils/emitters/SerialSyncEmitter.ts +++ /dev/null @@ -1,41 +0,0 @@ -import type { Emitter } from '../../types'; -import { ReadonlyEmitterBase } from './ReadonlyEmitterBase'; -import { __EMIT, __ENQUEUE, __INVOKE } from './syncEmitterCommons'; - -/** - * An event emitter that emits events in the order they are received. - * If an event is emitted while another event is being emitted, the new event - * will be queued and emitted after the current event is finished. - */ -export class SerialSyncEmitter - extends ReadonlyEmitterBase - implements Emitter -{ - #queue: Event[] = []; - - emit(nextEvent: Event): void { - this.#queue.push(Object.freeze(nextEvent)); - - if (this.#queue.length > 1) { - this._log.trace(__ENQUEUE(nextEvent), `enqueue(${nextEvent.type})`); - return; - } - - while (this.#queue.length > 0) { - const event = this.#queue[0]; - const eventType = event.type; - const listeners = [...this._getListeners(eventType)]; - - this._log.trace.complete(__EMIT(event), event.type, () => { - if (listeners) { - for (const listener of listeners) { - this._log.trace(__INVOKE(listener), 'invoke'); - listener(event); - } - } - }); - - this.#queue.shift(); - } - } -} diff --git a/src/utils/emitters/index.ts b/src/utils/emitters/index.ts index 2011a5f..c2073a3 100644 --- a/src/utils/emitters/index.ts +++ b/src/utils/emitters/index.ts @@ -1,4 +1,2 @@ export * from './AggregatedEmitter'; -export * from './SerialAsyncEmitter'; -export * from './SerialSyncEmitter'; -export * from './SemiAsyncEmitter'; +export * from './SerialEmitter'; diff --git a/src/utils/emitters/syncEmitterCommons.ts b/src/utils/emitters/syncEmitterCommons.ts deleted file mode 100644 index e77d68e..0000000 --- a/src/utils/emitters/syncEmitterCommons.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { optimizeTracing } from '../logger'; - -const CATEGORIES = { - ENQUEUE: ['enqueue'], - EMIT: ['emit'], - INVOKE: ['invoke'], -}; - -export const __ENQUEUE = optimizeTracing((event: unknown) => ({ - cat: CATEGORIES.ENQUEUE, - event, -})); -export const __EMIT = optimizeTracing((event: unknown) => ({ cat: CATEGORIES.EMIT, event })); -export const __INVOKE = optimizeTracing((listener: unknown, type?: '*') => ({ - cat: CATEGORIES.INVOKE, - fn: `${listener}`, - type, -})); diff --git a/src/utils/iterateSorted.test.ts b/src/utils/iterateSorted.test.ts deleted file mode 100644 index 1e8e69c..0000000 --- a/src/utils/iterateSorted.test.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { iterateSorted } from './iterateSorted'; - -describe('iterateSorted', () => { - const ordered = ['a', 'quick', 'brown', 'fox', 'jumps', 'over', 'the', 'lazy', 'dog']; - const getIndex = (x: string) => ordered.indexOf(x); - - it('should iterate over two sorted arrays', () => { - const a = ['a', 'fox', 'jumps', 'over', 'the', 'dog']; - const b = ['quick', 'brown', 'lazy']; - const c = [...iterateSorted(getIndex, a, b)]; - const d = [...iterateSorted(getIndex, b, a)]; - - expect(c).toEqual(ordered); - expect(d).toEqual(ordered); - }); - - it('should iterate once if arrays are the same', () => { - const a = ['a', 'fox', 'jumps', 'over', 'the', 'dog']; - const b = a; - const c = [...iterateSorted(getIndex, a, b)]; - expect(c).toEqual(a); - }); -}); diff --git a/src/utils/iterateSorted.ts b/src/utils/iterateSorted.ts deleted file mode 100644 index 8b6a80a..0000000 --- a/src/utils/iterateSorted.ts +++ /dev/null @@ -1,42 +0,0 @@ -export function* iterateSorted( - getIndex: (x: T) => number, - a: Iterable, - b: Iterable, -): IterableIterator { - if (a === b) { - yield* a; - return; - } - - const ia = a[Symbol.iterator](); - const ib = b[Symbol.iterator](); - - let ea = ia.next(); - let eb = ib.next(); - - while (!ea.done && !eb.done) { - const va = ea.value; - const vb = eb.value; - - const na = getIndex(va); - const nb = getIndex(vb); - - if (na <= nb) { - yield va; - ea = ia.next(); - } else { - yield vb; - eb = ib.next(); - } - } - - while (!ea.done) { - yield ea.value; - ea = ia.next(); - } - - while (!eb.done) { - yield eb.value; - eb = ib.next(); - } -} diff --git a/src/utils/logger.ts b/src/utils/logger.ts index e5690f7..fbc73f6 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -8,16 +8,18 @@ import { noop } from './noop'; const logsDirectory = process.env.JEST_METADATA_DEBUG; bunyamin.logger = createBunyanImpl(isTraceEnabled()); -bunyamin.threadGroups.push( - { id: 'ipc-server', displayName: 'IPC Server (jest-metadata)' }, - { id: 'ipc-client', displayName: 'IPC Client (jest-metadata)' }, - { id: 'emitter-core', displayName: 'Core emitter (jest-metadata)' }, - { id: 'emitter-set', displayName: 'Set emitter (jest-metadata)' }, - { id: 'emitter-events', displayName: 'Events emitter (jest-metadata)' }, - { id: 'environment', displayName: 'Test Environment (jest-metadata)' }, - { id: 'metadata', displayName: 'Metadata (jest-metadata)' }, - { id: 'reporter', displayName: 'Reporter (jest-metadata)' }, -); +if (!bunyamin.threadGroups.some((x) => x.id === 'metadata')) { + bunyamin.threadGroups.push( + { id: 'ipc-server', displayName: 'IPC Server (jest-metadata)' }, + { id: 'ipc-client', displayName: 'IPC Client (jest-metadata)' }, + { id: 'emitter-core', displayName: 'Core emitter (jest-metadata)' }, + { id: 'emitter-set', displayName: 'Set emitter (jest-metadata)' }, + { id: 'emitter-events', displayName: 'Events emitter (jest-metadata)' }, + { id: 'environment', displayName: 'Test Environment (jest-metadata)' }, + { id: 'metadata', displayName: 'Metadata (jest-metadata)' }, + { id: 'reporter', displayName: 'Reporter (jest-metadata)' }, + ); +} // eslint-disable-next-line @typescript-eslint/no-explicit-any export const optimizeTracing: (f: F) => F = isTraceEnabled() ? (f) => f : ((() => noop) as any);