Motivation
Currently Bench.add() internally constructs a Task instance from (name, fn, fnOpts), leaving no room to use a Task subclass.
This change extracts that logic into a new addTask(task: Task) method that accepts an already-built Task instance. This allows creating custom Task subclasses that encapsulate specific logic (before, after, or during a benchmark run) without having to modify Bench's internal flow, improving the organization, reusability, and testability of the code that consumes the library.
This enables use cases such as validation or integrity checks before running a benchmark, custom logging or metrics, specific setup/teardown logic, or conditionally skipping a task, among others.
Changes
add() now delegates to the new addTask() method. add()'s behavior and signature remain unchanged — this is a non-breaking change.
- Adds
addTask(task: Task): this, which registers the given Task and throws an Error if one with the same name already exists.
/**
* Adds a benchmark task to the task map.
* @param name - the task name
* @param fn - the task function
* @param fnOpts - the task function options
* @returns the Bench instance
* @throws {Error} when a task with the same name already exists
*/
add (name: string, fn: Fn, fnOpts: FnOptions = {}): this {
return this.addTask(new Task(this, name, fn, fnOpts))
}
/**
* Adds a benchmark task to the task map.
* @param task - the task to be added
* @returns the Bench instance
* @throws {Error} when a task with the same name already exists
*/
addTask (task: Task): this {
if (!this.#tasks.has(task.name)) {
this.#tasks.set(task.name, task)
this.dispatchEvent(new BenchEvent('add', task))
} else {
throw new Error(`Task "${task.name}" already exists`)
}
return this
}
Example usage
import { Bench, Task } from 'tinybench';
class MyCustomTask extends Task {
// ...
}
const bench = new Bench(/* ... */)
bench.addTask(new MyCustomTask(/* ... */))
Compatibility
Does not break the existing public API. add() keeps its current behavior.
TODO
Motivation
Currently
Bench.add()internally constructs aTaskinstance from(name, fn, fnOpts), leaving no room to use aTasksubclass.This change extracts that logic into a new
addTask(task: Task)method that accepts an already-builtTaskinstance. This allows creating customTasksubclasses that encapsulate specific logic (before, after, or during a benchmark run) without having to modifyBench's internal flow, improving the organization, reusability, and testability of the code that consumes the library.This enables use cases such as validation or integrity checks before running a benchmark, custom logging or metrics, specific setup/teardown logic, or conditionally skipping a task, among others.
Changes
add()now delegates to the newaddTask()method.add()'s behavior and signature remain unchanged — this is a non-breaking change.addTask(task: Task): this, which registers the givenTaskand throws anErrorif one with the same name already exists.Example usage
Compatibility
Does not break the existing public API.
add()keeps its current behavior.TODO
addTask(duplicate name,'add'event dispatch)