Skip to content

Commit 7a8daed

Browse files
authored
fix!: improve BenchEvent, remove types BenchEventsMap and TaskEventsMap (#398)
1 parent 955544d commit 7a8daed

File tree

8 files changed

+210
-135
lines changed

8 files changed

+210
-135
lines changed

src/bench.ts

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ import pLimit from 'p-limit'
33
import type {
44
AddEventListenerOptionsArgument,
55
BenchEvents,
6-
BenchEventsMap,
76
BenchOptions,
7+
EventListener,
8+
EventListenerObject,
89
Fn,
910
FnOptions,
1011
RemoveEventListenerOptionsArgument,
@@ -19,7 +20,7 @@ import {
1920
defaultMinimumWarmupTime,
2021
emptyFunction,
2122
} from './constants'
22-
import { createBenchEvent } from './event'
23+
import { BenchEvent } from './event'
2324
import { Task } from './task'
2425
import {
2526
defaultConvertTaskResultForConsoleTable,
@@ -34,6 +35,12 @@ import {
3435
* The Bench class keeps track of the benchmark tasks and controls them.
3536
*/
3637
export class Bench extends EventTarget {
38+
declare addEventListener: <K extends BenchEvents>(
39+
type: K,
40+
listener: EventListener<K> | EventListenerObject<K> | null,
41+
options?: AddEventListenerOptionsArgument
42+
) => void
43+
3744
/**
3845
* Executes tasks concurrently based on the specified concurrency mode.
3946
*
@@ -53,6 +60,12 @@ export class Bench extends EventTarget {
5360
*/
5461
readonly opts: Readonly<ResolvedBenchOptions>
5562

63+
declare removeEventListener: <K extends BenchEvents>(
64+
type: K,
65+
listener: EventListener<K> | EventListenerObject<K> | null,
66+
options?: RemoveEventListenerOptionsArgument
67+
) => void
68+
5669
/**
5770
* The JavaScript runtime environment.
5871
*/
@@ -115,7 +128,7 @@ export class Bench extends EventTarget {
115128
this.opts.signal.addEventListener(
116129
'abort',
117130
() => {
118-
this.dispatchEvent(createBenchEvent('abort'))
131+
this.dispatchEvent(new BenchEvent('abort'))
119132
},
120133
{ once: true }
121134
)
@@ -134,21 +147,13 @@ export class Bench extends EventTarget {
134147
if (!this.#tasks.has(name)) {
135148
const task = new Task(this, name, fn, fnOpts)
136149
this.#tasks.set(name, task)
137-
this.dispatchEvent(createBenchEvent('add', task))
150+
this.dispatchEvent(new BenchEvent('add', task))
138151
} else {
139152
throw new Error(`Task "${name}" already exists`)
140153
}
141154
return this
142155
}
143156

144-
override addEventListener<K extends BenchEvents>(
145-
type: K,
146-
listener: BenchEventsMap[K],
147-
options?: AddEventListenerOptionsArgument
148-
): void {
149-
super.addEventListener(type, listener, options)
150-
}
151-
152157
/**
153158
* get a task based on the task name
154159
* @param name - the task name
@@ -166,25 +171,17 @@ export class Bench extends EventTarget {
166171
remove (name: string): this {
167172
const task = this.getTask(name)
168173
if (task) {
169-
this.dispatchEvent(createBenchEvent('remove', task))
174+
this.dispatchEvent(new BenchEvent('remove', task))
170175
this.#tasks.delete(name)
171176
}
172177
return this
173178
}
174179

175-
override removeEventListener<K extends BenchEvents>(
176-
type: K,
177-
listener: BenchEventsMap[K],
178-
options?: RemoveEventListenerOptionsArgument
179-
): void {
180-
super.removeEventListener(type, listener, options)
181-
}
182-
183180
/**
184181
* reset tasks and remove their result
185182
*/
186183
reset (): void {
187-
this.dispatchEvent(createBenchEvent('reset'))
184+
this.dispatchEvent(new BenchEvent('reset'))
188185
for (const task of this.#tasks.values()) {
189186
task.reset()
190187
}
@@ -199,15 +196,15 @@ export class Bench extends EventTarget {
199196
await this.#warmupTasks()
200197
}
201198
let values: Task[] = []
202-
this.dispatchEvent(createBenchEvent('start'))
199+
this.dispatchEvent(new BenchEvent('start'))
203200
if (this.concurrency === 'bench') {
204201
values = await this.#mapTasksConcurrently(task => task.run())
205202
} else {
206203
for (const task of this.#tasks.values()) {
207204
values.push(await task.run())
208205
}
209206
}
210-
this.dispatchEvent(createBenchEvent('complete'))
207+
this.dispatchEvent(new BenchEvent('complete'))
211208
return values
212209
}
213210

@@ -224,11 +221,11 @@ export class Bench extends EventTarget {
224221
this.#warmupTasksSync()
225222
}
226223
const values: Task[] = []
227-
this.dispatchEvent(createBenchEvent('start'))
224+
this.dispatchEvent(new BenchEvent('start'))
228225
for (const task of this.#tasks.values()) {
229226
values.push(task.runSync())
230227
}
231-
this.dispatchEvent(createBenchEvent('complete'))
228+
this.dispatchEvent(new BenchEvent('complete'))
232229
return values
233230
}
234231

@@ -249,6 +246,7 @@ export class Bench extends EventTarget {
249246
Stack: task.result.error.stack,
250247
}
251248
: convert(task)
249+
/* eslint-enable perfectionist/sort-objects */
252250
})
253251
}
254252

@@ -282,7 +280,7 @@ export class Bench extends EventTarget {
282280
* warmup the benchmark tasks.
283281
*/
284282
async #warmupTasks (): Promise<void> {
285-
this.dispatchEvent(createBenchEvent('warmup'))
283+
this.dispatchEvent(new BenchEvent('warmup'))
286284
if (this.concurrency === 'bench') {
287285
await this.#mapTasksConcurrently(task => task.warmup())
288286
} else {
@@ -296,7 +294,7 @@ export class Bench extends EventTarget {
296294
* warmup the benchmark tasks (sync version)
297295
*/
298296
#warmupTasksSync (): void {
299-
this.dispatchEvent(createBenchEvent('warmup'))
297+
this.dispatchEvent(new BenchEvent('warmup'))
300298
for (const task of this.#tasks.values()) {
301299
task.warmupSync()
302300
}

src/event.ts

Lines changed: 22 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,28 @@
11
import type { Task } from './task'
2-
import type { BenchEvents } from './types'
2+
import type { BenchEvents, BenchEventsOptionalTask, BenchEventsWithError, BenchEventsWithTask } from './types'
33

4-
const createBenchEvent = (eventType: BenchEvents, target?: Task) => {
5-
const event = new globalThis.Event(eventType)
6-
if (target) {
7-
Object.defineProperty(event, 'task', {
8-
configurable: false,
9-
enumerable: false,
10-
value: target,
11-
writable: false,
12-
})
4+
class BenchEvent<K extends BenchEvents=BenchEvents, M extends 'bench' | 'task' = 'bench'> extends globalThis.Event {
5+
declare type: K
6+
7+
get error (): K extends BenchEventsWithError ? Error : undefined {
8+
return this.#error as K extends BenchEventsWithError ? Error : undefined
139
}
14-
return event
15-
}
1610

17-
const createErrorEvent = (target: Task, error: Error) => {
18-
const event = new globalThis.Event('error')
19-
Object.defineProperty(event, 'task', {
20-
configurable: false,
21-
enumerable: false,
22-
value: target,
23-
writable: false,
24-
})
25-
Object.defineProperty(event, 'error', {
26-
configurable: false,
27-
enumerable: false,
28-
value: error,
29-
writable: false,
30-
})
31-
return event
11+
get task (): M extends 'task' ? Task : K extends BenchEventsWithTask ? Task : undefined {
12+
return this.#task as M extends 'task' ? Task : K extends BenchEventsWithTask ? Task : undefined
13+
}
14+
15+
#error?: Error
16+
#task?: Task
17+
18+
constructor (type: BenchEventsWithError, task: Task, error: Error)
19+
constructor (type: BenchEventsWithTask, task: Task)
20+
constructor (type: BenchEventsOptionalTask, task?: Task)
21+
constructor (type: BenchEvents, task?: Task, error?: Error) {
22+
super(type)
23+
this.#task = task
24+
this.#error = error
25+
}
3226
}
3327

34-
export { createBenchEvent, createErrorEvent }
28+
export { BenchEvent }

src/index.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ export { Task } from './task'
33
export type {
44
BenchEvent,
55
BenchEvents,
6-
BenchEventsMap,
76
BenchOptions,
87
EventListener,
98
Fn,
@@ -14,7 +13,6 @@ export type {
1413
ResolvedBenchOptions,
1514
Statistics,
1615
TaskEvents,
17-
TaskEventsMap,
1816
TaskResult,
1917
} from './types'
2018
export type { JSRuntime } from './utils'

src/task.ts

Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,17 @@ import pLimit from 'p-limit'
33
import type { Bench } from './bench'
44
import type {
55
AddEventListenerOptionsArgument,
6+
EventListener,
7+
EventListenerObject,
68
Fn,
79
FnOptions,
810
RemoveEventListenerOptionsArgument,
911
TaskEvents,
10-
TaskEventsMap,
1112
TaskResult,
1213
TaskResultRuntimeInfo,
1314
} from './types'
1415

15-
import { createBenchEvent, createErrorEvent } from './event'
16+
import { BenchEvent } from './event'
1617
import {
1718
getStatisticsSorted,
1819
invariant,
@@ -31,6 +32,18 @@ const hookNames = ['afterAll', 'beforeAll', 'beforeEach', 'afterEach'] as const
3132
* results, name, the task function, the number times the task function has been executed, ...
3233
*/
3334
export class Task extends EventTarget {
35+
declare addEventListener: <K extends TaskEvents>(
36+
type: K,
37+
listener: EventListener<K, 'task'> | EventListenerObject<K, 'task'> | null,
38+
options?: AddEventListenerOptionsArgument
39+
) => void
40+
41+
declare removeEventListener: <K extends TaskEvents>(
42+
type: K,
43+
listener: EventListener<K, 'task'> | EventListenerObject<K, 'task'> | null,
44+
options?: RemoveEventListenerOptionsArgument
45+
) => void
46+
3447
/**
3548
* The result object
3649
*/
@@ -109,8 +122,9 @@ export class Task extends EventTarget {
109122
this.#signal.addEventListener(
110123
'abort',
111124
() => {
112-
this.dispatchEvent(createBenchEvent('abort', this))
113-
this.#bench.dispatchEvent(createBenchEvent('abort', this))
125+
const ev = new BenchEvent('abort', this)
126+
this.dispatchEvent(ev)
127+
this.#bench.dispatchEvent(ev)
114128
},
115129
{ once: true }
116130
)
@@ -121,28 +135,12 @@ export class Task extends EventTarget {
121135
})
122136
}
123137

124-
override addEventListener<K extends TaskEvents>(
125-
type: K,
126-
listener: TaskEventsMap[K],
127-
options?: AddEventListenerOptionsArgument
128-
): void {
129-
super.addEventListener(type, listener, options)
130-
}
131-
132-
override removeEventListener<K extends TaskEvents>(
133-
type: K,
134-
listener: TaskEventsMap[K],
135-
options?: RemoveEventListenerOptionsArgument
136-
): void {
137-
super.removeEventListener(type, listener, options)
138-
}
139-
140138
/**
141139
* reset the task to make the `Task.runs` a zero-value and remove the `Task.result` object property
142140
* @internal
143141
*/
144142
reset (): void {
145-
this.dispatchEvent(createBenchEvent('reset', this))
143+
this.dispatchEvent(new BenchEvent('reset', this))
146144
this.runs = 0
147145

148146
this.#setTaskResult({
@@ -162,7 +160,7 @@ export class Task extends EventTarget {
162160
this.#setTaskResult({
163161
state: 'started',
164162
})
165-
this.dispatchEvent(createBenchEvent('start', this))
163+
this.dispatchEvent(new BenchEvent('start', this))
166164
await this.#bench.opts.setup(this, 'run')
167165
const { error, samples: latencySamples } = (await this.#benchmark(
168166
'run',
@@ -193,7 +191,7 @@ export class Task extends EventTarget {
193191
this.#setTaskResult({
194192
state: 'started',
195193
})
196-
this.dispatchEvent(createBenchEvent('start', this))
194+
this.dispatchEvent(new BenchEvent('start', this))
197195

198196
const setupResult = this.#bench.opts.setup(this, 'run')
199197
invariant(
@@ -226,7 +224,7 @@ export class Task extends EventTarget {
226224
if (this.result.state !== 'not-started') {
227225
return
228226
}
229-
this.dispatchEvent(createBenchEvent('warmup', this))
227+
this.dispatchEvent(new BenchEvent('warmup', this))
230228
await this.#bench.opts.setup(this, 'warmup')
231229
const { error } = (await this.#benchmark(
232230
'warmup',
@@ -247,7 +245,7 @@ export class Task extends EventTarget {
247245
return
248246
}
249247

250-
this.dispatchEvent(createBenchEvent('warmup', this))
248+
this.dispatchEvent(new BenchEvent('warmup', this))
251249

252250
const setupResult = this.#bench.opts.setup(this, 'warmup')
253251
invariant(
@@ -467,8 +465,9 @@ export class Task extends EventTarget {
467465
error,
468466
state: 'errored',
469467
})
470-
this.dispatchEvent(createErrorEvent(this, error))
471-
this.#bench.dispatchEvent(createErrorEvent(this, error))
468+
const ev = new BenchEvent('error', this, error)
469+
this.dispatchEvent(ev)
470+
this.#bench.dispatchEvent(ev)
472471
if (this.#bench.opts.throws) {
473472
throw error
474473
}
@@ -543,17 +542,19 @@ export class Task extends EventTarget {
543542
error,
544543
state: 'errored',
545544
})
546-
this.dispatchEvent(createErrorEvent(this, error))
547-
this.#bench.dispatchEvent(createErrorEvent(this, error))
545+
const ev = new BenchEvent('error', this, error)
546+
this.dispatchEvent(ev)
547+
this.#bench.dispatchEvent(ev)
548548
if (this.#bench.opts.throws) {
549549
throw error
550550
}
551551
}
552552

553-
this.dispatchEvent(createBenchEvent('cycle', this))
554-
this.#bench.dispatchEvent(createBenchEvent('cycle', this))
553+
const ev = new BenchEvent('cycle', this)
554+
this.dispatchEvent(ev)
555+
this.#bench.dispatchEvent(ev)
555556
// cycle and complete are equal in Task
556-
this.dispatchEvent(createBenchEvent('complete', this))
557+
this.dispatchEvent(new BenchEvent('complete', this))
557558
}
558559

559560
/**

0 commit comments

Comments
 (0)