overtake 1.3.0 → 1.3.2

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/README.md CHANGED
@@ -112,10 +112,12 @@ benchmark('local', () => 1)
112
112
 
113
113
  // Programmatic usage – provide baseUrl
114
114
  const suite = new Benchmark('local');
115
- suite.target('helper', async () => {
116
- const { helper } = await import('./helpers.js');
117
- return { helper };
118
- });
115
+ suite
116
+ .target('helper', async () => {
117
+ const { helper } = await import('./helpers.js');
118
+ return { helper };
119
+ })
120
+ .measure('use helper', ({ helper }) => helper());
119
121
  await suite.execute({ baseUrl: import.meta.url });
120
122
  ```
121
123
 
@@ -127,16 +129,15 @@ When using `npx overtake`, a global `benchmark` function is provided:
127
129
 
128
130
  ```typescript
129
131
  // benchmark.ts - No imports needed!
130
- benchmark('small', () => generateSmallData())
131
- .feed('large', () => generateLargeData())
132
- .target('algorithm A')
133
- .measure('process', (_, input) => {
134
- processA(input);
135
- })
136
- .target('algorithm B')
137
- .measure('process', (_, input) => {
138
- processB(input);
139
- });
132
+ const suite = benchmark('small', () => generateSmallData()).feed('large', () => generateLargeData());
133
+
134
+ suite.target('algorithm A').measure('process', (_, input) => {
135
+ processA(input);
136
+ });
137
+
138
+ suite.target('algorithm B').measure('process', (_, input) => {
139
+ processB(input);
140
+ });
140
141
  ```
141
142
 
142
143
  ```bash
@@ -171,21 +172,32 @@ printTableReports(reports);
171
172
 
172
173
  ```typescript
173
174
  // Create with initial feed
174
- benchmark('initial data', () => data)
175
- .feed('more data', () => moreData) // Add more datasets
175
+ const suite = benchmark('initial data', () => data).feed('more data', () => moreData); // Add more datasets
176
176
 
177
- // Define what to compare
178
- .target('implementation A')
179
- .measure('operation', (ctx, input) => {
180
- /* ... */
181
- })
177
+ // Define what to compare
178
+ suite.target('implementation A').measure('operation', (ctx, input) => {
179
+ /* ... */
180
+ });
182
181
 
183
- .target('implementation B')
184
- .measure('operation', (ctx, input) => {
185
- /* ... */
186
- });
182
+ suite.target('implementation B').measure('operation', (ctx, input) => {
183
+ /* ... */
184
+ });
187
185
  ```
188
186
 
187
+ ### Method Chaining Reference
188
+
189
+ ```
190
+ benchmark(name, feedFn) -> Benchmark
191
+ .feed(name, feedFn) -> Benchmark
192
+ .target(name, setup?) -> Target
193
+ .teardown(fn) -> Target
194
+ .measure(name, fn) -> Measure
195
+ .pre(fn) -> Measure
196
+ .post(fn) -> Measure
197
+ ```
198
+
199
+ Note: `.measure()` returns `Measure`, not `Benchmark`. To add multiple targets, call `suite.target()` separately for each.
200
+
189
201
  ### Targets with Setup
190
202
 
191
203
  ```typescript
@@ -243,12 +255,18 @@ sumBenchmark.target('reduce').measure('sum', (_, numbers) => {
243
255
 
244
256
  ```typescript
245
257
  // examples/imports.ts - Correct way to import local files
246
- .target('local files', async () => {
247
- const { join } = await import('node:path');
248
- const modulePath = join(process.cwd(), './build/myModule.js');
249
- const { myFunction } = await import(modulePath);
250
- return { myFunction };
251
- })
258
+ const suite = benchmark('local modules', () => testData);
259
+
260
+ suite
261
+ .target('local files', async () => {
262
+ const { join } = await import('node:path');
263
+ const modulePath = join(process.cwd(), './build/myModule.js');
264
+ const { myFunction } = await import(modulePath);
265
+ return { myFunction };
266
+ })
267
+ .measure('call function', ({ myFunction }, input) => {
268
+ myFunction(input);
269
+ });
252
270
  ```
253
271
 
254
272
  **[📁 See all examples](./examples/):**
package/build/cli.cjs CHANGED
@@ -95,13 +95,14 @@ commander.name(name).description(description).version(version).argument('<paths.
95
95
  instance = _indexcjs.Benchmark.create(...args);
96
96
  return instance;
97
97
  };
98
+ const globals = Object.create(null);
99
+ for (const k of Object.getOwnPropertyNames(globalThis)){
100
+ globals[k] = globalThis[k];
101
+ }
102
+ globals.benchmark = benchmark;
98
103
  const script = new _nodevm.SourceTextModule(code, {
99
104
  identifier,
100
- context: (0, _nodevm.createContext)({
101
- benchmark,
102
- Buffer,
103
- console
104
- }),
105
+ context: (0, _nodevm.createContext)(globals),
105
106
  initializeImportMeta (meta) {
106
107
  meta.url = identifier;
107
108
  },
package/build/cli.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire, Module } from 'node:module';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SyntheticModule, createContext, SourceTextModule } from 'node:vm';\nimport { stat, readFile, writeFile } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport {\n Benchmark,\n printTableReports,\n printJSONReports,\n printSimpleReports,\n printMarkdownReports,\n printHistogramReports,\n printComparisonReports,\n reportsToBaseline,\n BaselineData,\n DEFAULT_REPORT_TYPES,\n DEFAULT_WORKERS,\n} from './index.js';\nimport { transpile } from './utils.js';\nimport { REPORT_TYPES } from './types.js';\n\nconst require = createRequire(import.meta.url);\nconst { name, description, version } = require('../package.json');\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nconst commander = new Command();\n\ncommander\n .name(name)\n .description(description)\n .version(version)\n .argument('<paths...>', 'glob pattern to find benchmarks')\n .addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES))\n .addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt))\n .addOption(new Option('-f, --format [format]', 'output format').default('simple').choices(['simple', 'json', 'pjson', 'table', 'markdown', 'histogram']))\n .addOption(new Option('--abs-threshold [absThreshold]', 'absolute error threshold in nanoseconds').argParser(parseFloat))\n .addOption(new Option('--rel-threshold [relThreshold]', 'relative error threshold (fraction between 0 and 1)').argParser(parseFloat))\n .addOption(new Option('--warmup-cycles [warmupCycles]', 'number of warmup cycles before measuring').argParser(parseInt))\n .addOption(new Option('--max-cycles [maxCycles]', 'maximum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--min-cycles [minCycles]', 'minimum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--no-gc-observer', 'disable GC overlap detection'))\n .addOption(new Option('--progress', 'show progress bar during benchmark execution'))\n .addOption(new Option('--save-baseline <file>', 'save benchmark results to baseline file'))\n .addOption(new Option('--compare-baseline <file>', 'compare results against baseline file'))\n .action(async (patterns: string[], executeOptions) => {\n let baseline: BaselineData | null = null;\n if (executeOptions.compareBaseline) {\n try {\n const content = await readFile(executeOptions.compareBaseline, 'utf8');\n baseline = JSON.parse(content) as BaselineData;\n } catch {\n console.error(`Warning: Could not load baseline file: ${executeOptions.compareBaseline}`);\n }\n }\n\n const files = new Set<string>();\n await Promise.all(\n patterns.map(async (pattern) => {\n const matches = await glob(pattern, { absolute: true, cwd: process.cwd() }).catch(() => []);\n matches.forEach((file) => files.add(file));\n }),\n );\n\n for (const file of files) {\n const stats = await stat(file).catch(() => false as const);\n if (stats && stats.isFile()) {\n const content = await readFile(file, 'utf8');\n const identifier = pathToFileURL(file).href;\n const code = await transpile(content);\n let instance: Benchmark<unknown> | undefined;\n const benchmark = (...args: Parameters<(typeof Benchmark)['create']>) => {\n if (instance) {\n throw new Error('Only one benchmark per file is supported');\n }\n instance = Benchmark.create(...args);\n return instance;\n };\n const script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\n initializeImportMeta(meta) {\n meta.url = identifier;\n },\n async importModuleDynamically(specifier, referencingModule) {\n if (Module.isBuiltin(specifier)) {\n return import(specifier);\n }\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const resolved = resolveFrom.resolve(specifier);\n return import(resolved);\n },\n });\n const imports = new Map<string, SyntheticModule>();\n await script.link(async (specifier: string, referencingModule) => {\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const target = Module.isBuiltin(specifier) ? specifier : resolveFrom.resolve(specifier);\n const cached = imports.get(target);\n if (cached) {\n return cached;\n }\n const mod = await import(target);\n const exportNames = Object.keys(mod);\n const imported = new SyntheticModule(\n exportNames,\n () => {\n exportNames.forEach((key) => imported.setExport(key, mod[key]));\n },\n { identifier: target, context: referencingModule.context },\n );\n\n imports.set(target, imported);\n return imported;\n });\n await script.evaluate();\n\n if (instance) {\n const reports = await instance.execute({\n ...executeOptions,\n [BENCHMARK_URL]: identifier,\n } as typeof executeOptions);\n\n if (executeOptions.saveBaseline) {\n const baselineData = reportsToBaseline(reports);\n await writeFile(executeOptions.saveBaseline, JSON.stringify(baselineData, null, 2));\n console.log(`Baseline saved to: ${executeOptions.saveBaseline}`);\n }\n\n if (baseline) {\n printComparisonReports(reports, baseline);\n } else {\n switch (executeOptions.format) {\n case 'json':\n printJSONReports(reports);\n break;\n case 'pjson':\n printJSONReports(reports, 2);\n break;\n case 'table':\n printTableReports(reports);\n break;\n case 'markdown':\n printMarkdownReports(reports);\n break;\n case 'histogram':\n printHistogramReports(reports);\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["require","createRequire","name","description","version","BENCHMARK_URL","Symbol","for","commander","Command","argument","addOption","Option","choices","REPORT_TYPES","default","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","argParser","parseInt","parseFloat","action","patterns","executeOptions","baseline","compareBaseline","content","readFile","JSON","parse","console","error","files","Set","Promise","all","map","pattern","matches","glob","absolute","cwd","process","catch","forEach","file","add","stats","stat","isFile","identifier","pathToFileURL","href","code","transpile","instance","benchmark","args","Error","Benchmark","create","script","SourceTextModule","context","createContext","Buffer","initializeImportMeta","meta","url","importModuleDynamically","specifier","referencingModule","Module","isBuiltin","baseIdentifier","resolveFrom","fileURLToPath","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","SyntheticModule","key","setExport","set","evaluate","reports","execute","saveBaseline","baselineData","reportsToBaseline","writeFile","stringify","log","printComparisonReports","format","printJSONReports","printTableReports","printMarkdownReports","printHistogramReports","printSimpleReports","argv"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire, Module } from 'node:module';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SyntheticModule, createContext, SourceTextModule } from 'node:vm';\nimport { stat, readFile, writeFile } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport {\n Benchmark,\n printTableReports,\n printJSONReports,\n printSimpleReports,\n printMarkdownReports,\n printHistogramReports,\n printComparisonReports,\n reportsToBaseline,\n BaselineData,\n DEFAULT_REPORT_TYPES,\n DEFAULT_WORKERS,\n} from './index.js';\nimport { transpile } from './utils.js';\nimport { REPORT_TYPES } from './types.js';\n\nconst require = createRequire(import.meta.url);\nconst { name, description, version } = require('../package.json');\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nconst commander = new Command();\n\ncommander\n .name(name)\n .description(description)\n .version(version)\n .argument('<paths...>', 'glob pattern to find benchmarks')\n .addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES))\n .addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt))\n .addOption(new Option('-f, --format [format]', 'output format').default('simple').choices(['simple', 'json', 'pjson', 'table', 'markdown', 'histogram']))\n .addOption(new Option('--abs-threshold [absThreshold]', 'absolute error threshold in nanoseconds').argParser(parseFloat))\n .addOption(new Option('--rel-threshold [relThreshold]', 'relative error threshold (fraction between 0 and 1)').argParser(parseFloat))\n .addOption(new Option('--warmup-cycles [warmupCycles]', 'number of warmup cycles before measuring').argParser(parseInt))\n .addOption(new Option('--max-cycles [maxCycles]', 'maximum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--min-cycles [minCycles]', 'minimum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--no-gc-observer', 'disable GC overlap detection'))\n .addOption(new Option('--progress', 'show progress bar during benchmark execution'))\n .addOption(new Option('--save-baseline <file>', 'save benchmark results to baseline file'))\n .addOption(new Option('--compare-baseline <file>', 'compare results against baseline file'))\n .action(async (patterns: string[], executeOptions) => {\n let baseline: BaselineData | null = null;\n if (executeOptions.compareBaseline) {\n try {\n const content = await readFile(executeOptions.compareBaseline, 'utf8');\n baseline = JSON.parse(content) as BaselineData;\n } catch {\n console.error(`Warning: Could not load baseline file: ${executeOptions.compareBaseline}`);\n }\n }\n\n const files = new Set<string>();\n await Promise.all(\n patterns.map(async (pattern) => {\n const matches = await glob(pattern, { absolute: true, cwd: process.cwd() }).catch(() => []);\n matches.forEach((file) => files.add(file));\n }),\n );\n\n for (const file of files) {\n const stats = await stat(file).catch(() => false as const);\n if (stats && stats.isFile()) {\n const content = await readFile(file, 'utf8');\n const identifier = pathToFileURL(file).href;\n const code = await transpile(content);\n let instance: Benchmark<unknown> | undefined;\n const benchmark = (...args: Parameters<(typeof Benchmark)['create']>) => {\n if (instance) {\n throw new Error('Only one benchmark per file is supported');\n }\n instance = Benchmark.create(...args);\n return instance;\n };\n const globals = Object.create(null);\n for (const k of Object.getOwnPropertyNames(globalThis)) {\n globals[k] = (globalThis as any)[k];\n }\n globals.benchmark = benchmark;\n const script = new SourceTextModule(code, {\n identifier,\n context: createContext(globals),\n initializeImportMeta(meta) {\n meta.url = identifier;\n },\n async importModuleDynamically(specifier, referencingModule) {\n if (Module.isBuiltin(specifier)) {\n return import(specifier);\n }\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const resolved = resolveFrom.resolve(specifier);\n return import(resolved);\n },\n });\n const imports = new Map<string, SyntheticModule>();\n await script.link(async (specifier: string, referencingModule) => {\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const target = Module.isBuiltin(specifier) ? specifier : resolveFrom.resolve(specifier);\n const cached = imports.get(target);\n if (cached) {\n return cached;\n }\n const mod = await import(target);\n const exportNames = Object.keys(mod);\n const imported = new SyntheticModule(\n exportNames,\n () => {\n exportNames.forEach((key) => imported.setExport(key, mod[key]));\n },\n { identifier: target, context: referencingModule.context },\n );\n\n imports.set(target, imported);\n return imported;\n });\n await script.evaluate();\n\n if (instance) {\n const reports = await instance.execute({\n ...executeOptions,\n [BENCHMARK_URL]: identifier,\n } as typeof executeOptions);\n\n if (executeOptions.saveBaseline) {\n const baselineData = reportsToBaseline(reports);\n await writeFile(executeOptions.saveBaseline, JSON.stringify(baselineData, null, 2));\n console.log(`Baseline saved to: ${executeOptions.saveBaseline}`);\n }\n\n if (baseline) {\n printComparisonReports(reports, baseline);\n } else {\n switch (executeOptions.format) {\n case 'json':\n printJSONReports(reports);\n break;\n case 'pjson':\n printJSONReports(reports, 2);\n break;\n case 'table':\n printTableReports(reports);\n break;\n case 'markdown':\n printMarkdownReports(reports);\n break;\n case 'histogram':\n printHistogramReports(reports);\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["require","createRequire","name","description","version","BENCHMARK_URL","Symbol","for","commander","Command","argument","addOption","Option","choices","REPORT_TYPES","default","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","argParser","parseInt","parseFloat","action","patterns","executeOptions","baseline","compareBaseline","content","readFile","JSON","parse","console","error","files","Set","Promise","all","map","pattern","matches","glob","absolute","cwd","process","catch","forEach","file","add","stats","stat","isFile","identifier","pathToFileURL","href","code","transpile","instance","benchmark","args","Error","Benchmark","create","globals","Object","k","getOwnPropertyNames","globalThis","script","SourceTextModule","context","createContext","initializeImportMeta","meta","url","importModuleDynamically","specifier","referencingModule","Module","isBuiltin","baseIdentifier","resolveFrom","fileURLToPath","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","keys","imported","SyntheticModule","key","setExport","set","evaluate","reports","execute","saveBaseline","baselineData","reportsToBaseline","writeFile","stringify","log","printComparisonReports","format","printJSONReports","printTableReports","printMarkdownReports","printHistogramReports","printSimpleReports","argv"],"mappings":"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"}
package/build/cli.js CHANGED
@@ -50,13 +50,14 @@ commander.name(name).description(description).version(version).argument('<paths.
50
50
  instance = Benchmark.create(...args);
51
51
  return instance;
52
52
  };
53
+ const globals = Object.create(null);
54
+ for (const k of Object.getOwnPropertyNames(globalThis)){
55
+ globals[k] = globalThis[k];
56
+ }
57
+ globals.benchmark = benchmark;
53
58
  const script = new SourceTextModule(code, {
54
59
  identifier,
55
- context: createContext({
56
- benchmark,
57
- Buffer,
58
- console
59
- }),
60
+ context: createContext(globals),
60
61
  initializeImportMeta (meta) {
61
62
  meta.url = identifier;
62
63
  },
package/build/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire, Module } from 'node:module';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SyntheticModule, createContext, SourceTextModule } from 'node:vm';\nimport { stat, readFile, writeFile } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport {\n Benchmark,\n printTableReports,\n printJSONReports,\n printSimpleReports,\n printMarkdownReports,\n printHistogramReports,\n printComparisonReports,\n reportsToBaseline,\n BaselineData,\n DEFAULT_REPORT_TYPES,\n DEFAULT_WORKERS,\n} from './index.js';\nimport { transpile } from './utils.js';\nimport { REPORT_TYPES } from './types.js';\n\nconst require = createRequire(import.meta.url);\nconst { name, description, version } = require('../package.json');\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nconst commander = new Command();\n\ncommander\n .name(name)\n .description(description)\n .version(version)\n .argument('<paths...>', 'glob pattern to find benchmarks')\n .addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES))\n .addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt))\n .addOption(new Option('-f, --format [format]', 'output format').default('simple').choices(['simple', 'json', 'pjson', 'table', 'markdown', 'histogram']))\n .addOption(new Option('--abs-threshold [absThreshold]', 'absolute error threshold in nanoseconds').argParser(parseFloat))\n .addOption(new Option('--rel-threshold [relThreshold]', 'relative error threshold (fraction between 0 and 1)').argParser(parseFloat))\n .addOption(new Option('--warmup-cycles [warmupCycles]', 'number of warmup cycles before measuring').argParser(parseInt))\n .addOption(new Option('--max-cycles [maxCycles]', 'maximum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--min-cycles [minCycles]', 'minimum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--no-gc-observer', 'disable GC overlap detection'))\n .addOption(new Option('--progress', 'show progress bar during benchmark execution'))\n .addOption(new Option('--save-baseline <file>', 'save benchmark results to baseline file'))\n .addOption(new Option('--compare-baseline <file>', 'compare results against baseline file'))\n .action(async (patterns: string[], executeOptions) => {\n let baseline: BaselineData | null = null;\n if (executeOptions.compareBaseline) {\n try {\n const content = await readFile(executeOptions.compareBaseline, 'utf8');\n baseline = JSON.parse(content) as BaselineData;\n } catch {\n console.error(`Warning: Could not load baseline file: ${executeOptions.compareBaseline}`);\n }\n }\n\n const files = new Set<string>();\n await Promise.all(\n patterns.map(async (pattern) => {\n const matches = await glob(pattern, { absolute: true, cwd: process.cwd() }).catch(() => []);\n matches.forEach((file) => files.add(file));\n }),\n );\n\n for (const file of files) {\n const stats = await stat(file).catch(() => false as const);\n if (stats && stats.isFile()) {\n const content = await readFile(file, 'utf8');\n const identifier = pathToFileURL(file).href;\n const code = await transpile(content);\n let instance: Benchmark<unknown> | undefined;\n const benchmark = (...args: Parameters<(typeof Benchmark)['create']>) => {\n if (instance) {\n throw new Error('Only one benchmark per file is supported');\n }\n instance = Benchmark.create(...args);\n return instance;\n };\n const script = new SourceTextModule(code, {\n identifier,\n context: createContext({\n benchmark,\n Buffer,\n console,\n }),\n initializeImportMeta(meta) {\n meta.url = identifier;\n },\n async importModuleDynamically(specifier, referencingModule) {\n if (Module.isBuiltin(specifier)) {\n return import(specifier);\n }\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const resolved = resolveFrom.resolve(specifier);\n return import(resolved);\n },\n });\n const imports = new Map<string, SyntheticModule>();\n await script.link(async (specifier: string, referencingModule) => {\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const target = Module.isBuiltin(specifier) ? specifier : resolveFrom.resolve(specifier);\n const cached = imports.get(target);\n if (cached) {\n return cached;\n }\n const mod = await import(target);\n const exportNames = Object.keys(mod);\n const imported = new SyntheticModule(\n exportNames,\n () => {\n exportNames.forEach((key) => imported.setExport(key, mod[key]));\n },\n { identifier: target, context: referencingModule.context },\n );\n\n imports.set(target, imported);\n return imported;\n });\n await script.evaluate();\n\n if (instance) {\n const reports = await instance.execute({\n ...executeOptions,\n [BENCHMARK_URL]: identifier,\n } as typeof executeOptions);\n\n if (executeOptions.saveBaseline) {\n const baselineData = reportsToBaseline(reports);\n await writeFile(executeOptions.saveBaseline, JSON.stringify(baselineData, null, 2));\n console.log(`Baseline saved to: ${executeOptions.saveBaseline}`);\n }\n\n if (baseline) {\n printComparisonReports(reports, baseline);\n } else {\n switch (executeOptions.format) {\n case 'json':\n printJSONReports(reports);\n break;\n case 'pjson':\n printJSONReports(reports, 2);\n break;\n case 'table':\n printTableReports(reports);\n break;\n case 'markdown':\n printMarkdownReports(reports);\n break;\n case 'histogram':\n printHistogramReports(reports);\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["createRequire","Module","fileURLToPath","pathToFileURL","SyntheticModule","createContext","SourceTextModule","stat","readFile","writeFile","Command","Option","glob","Benchmark","printTableReports","printJSONReports","printSimpleReports","printMarkdownReports","printHistogramReports","printComparisonReports","reportsToBaseline","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","transpile","REPORT_TYPES","require","url","name","description","version","BENCHMARK_URL","Symbol","for","commander","argument","addOption","choices","default","argParser","parseInt","parseFloat","action","patterns","executeOptions","baseline","compareBaseline","content","JSON","parse","console","error","files","Set","Promise","all","map","pattern","matches","absolute","cwd","process","catch","forEach","file","add","stats","isFile","identifier","href","code","instance","benchmark","args","Error","create","script","context","Buffer","initializeImportMeta","meta","importModuleDynamically","specifier","referencingModule","isBuiltin","baseIdentifier","resolveFrom","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","Object","keys","imported","key","setExport","set","evaluate","reports","execute","saveBaseline","baselineData","stringify","log","format","argv"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/cli.ts"],"sourcesContent":["import { createRequire, Module } from 'node:module';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { SyntheticModule, createContext, SourceTextModule } from 'node:vm';\nimport { stat, readFile, writeFile } from 'node:fs/promises';\nimport { Command, Option } from 'commander';\nimport { glob } from 'glob';\nimport {\n Benchmark,\n printTableReports,\n printJSONReports,\n printSimpleReports,\n printMarkdownReports,\n printHistogramReports,\n printComparisonReports,\n reportsToBaseline,\n BaselineData,\n DEFAULT_REPORT_TYPES,\n DEFAULT_WORKERS,\n} from './index.js';\nimport { transpile } from './utils.js';\nimport { REPORT_TYPES } from './types.js';\n\nconst require = createRequire(import.meta.url);\nconst { name, description, version } = require('../package.json');\nconst BENCHMARK_URL = Symbol.for('overtake.benchmarkUrl');\n\nconst commander = new Command();\n\ncommander\n .name(name)\n .description(description)\n .version(version)\n .argument('<paths...>', 'glob pattern to find benchmarks')\n .addOption(new Option('-r, --report-types [reportTypes...]', 'statistic types to include in the report').choices(REPORT_TYPES).default(DEFAULT_REPORT_TYPES))\n .addOption(new Option('-w, --workers [workers]', 'number of concurent workers').default(DEFAULT_WORKERS).argParser(parseInt))\n .addOption(new Option('-f, --format [format]', 'output format').default('simple').choices(['simple', 'json', 'pjson', 'table', 'markdown', 'histogram']))\n .addOption(new Option('--abs-threshold [absThreshold]', 'absolute error threshold in nanoseconds').argParser(parseFloat))\n .addOption(new Option('--rel-threshold [relThreshold]', 'relative error threshold (fraction between 0 and 1)').argParser(parseFloat))\n .addOption(new Option('--warmup-cycles [warmupCycles]', 'number of warmup cycles before measuring').argParser(parseInt))\n .addOption(new Option('--max-cycles [maxCycles]', 'maximum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--min-cycles [minCycles]', 'minimum measurement cycles per feed').argParser(parseInt))\n .addOption(new Option('--no-gc-observer', 'disable GC overlap detection'))\n .addOption(new Option('--progress', 'show progress bar during benchmark execution'))\n .addOption(new Option('--save-baseline <file>', 'save benchmark results to baseline file'))\n .addOption(new Option('--compare-baseline <file>', 'compare results against baseline file'))\n .action(async (patterns: string[], executeOptions) => {\n let baseline: BaselineData | null = null;\n if (executeOptions.compareBaseline) {\n try {\n const content = await readFile(executeOptions.compareBaseline, 'utf8');\n baseline = JSON.parse(content) as BaselineData;\n } catch {\n console.error(`Warning: Could not load baseline file: ${executeOptions.compareBaseline}`);\n }\n }\n\n const files = new Set<string>();\n await Promise.all(\n patterns.map(async (pattern) => {\n const matches = await glob(pattern, { absolute: true, cwd: process.cwd() }).catch(() => []);\n matches.forEach((file) => files.add(file));\n }),\n );\n\n for (const file of files) {\n const stats = await stat(file).catch(() => false as const);\n if (stats && stats.isFile()) {\n const content = await readFile(file, 'utf8');\n const identifier = pathToFileURL(file).href;\n const code = await transpile(content);\n let instance: Benchmark<unknown> | undefined;\n const benchmark = (...args: Parameters<(typeof Benchmark)['create']>) => {\n if (instance) {\n throw new Error('Only one benchmark per file is supported');\n }\n instance = Benchmark.create(...args);\n return instance;\n };\n const globals = Object.create(null);\n for (const k of Object.getOwnPropertyNames(globalThis)) {\n globals[k] = (globalThis as any)[k];\n }\n globals.benchmark = benchmark;\n const script = new SourceTextModule(code, {\n identifier,\n context: createContext(globals),\n initializeImportMeta(meta) {\n meta.url = identifier;\n },\n async importModuleDynamically(specifier, referencingModule) {\n if (Module.isBuiltin(specifier)) {\n return import(specifier);\n }\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const resolved = resolveFrom.resolve(specifier);\n return import(resolved);\n },\n });\n const imports = new Map<string, SyntheticModule>();\n await script.link(async (specifier: string, referencingModule) => {\n const baseIdentifier = referencingModule.identifier ?? identifier;\n const resolveFrom = createRequire(fileURLToPath(baseIdentifier));\n const target = Module.isBuiltin(specifier) ? specifier : resolveFrom.resolve(specifier);\n const cached = imports.get(target);\n if (cached) {\n return cached;\n }\n const mod = await import(target);\n const exportNames = Object.keys(mod);\n const imported = new SyntheticModule(\n exportNames,\n () => {\n exportNames.forEach((key) => imported.setExport(key, mod[key]));\n },\n { identifier: target, context: referencingModule.context },\n );\n\n imports.set(target, imported);\n return imported;\n });\n await script.evaluate();\n\n if (instance) {\n const reports = await instance.execute({\n ...executeOptions,\n [BENCHMARK_URL]: identifier,\n } as typeof executeOptions);\n\n if (executeOptions.saveBaseline) {\n const baselineData = reportsToBaseline(reports);\n await writeFile(executeOptions.saveBaseline, JSON.stringify(baselineData, null, 2));\n console.log(`Baseline saved to: ${executeOptions.saveBaseline}`);\n }\n\n if (baseline) {\n printComparisonReports(reports, baseline);\n } else {\n switch (executeOptions.format) {\n case 'json':\n printJSONReports(reports);\n break;\n case 'pjson':\n printJSONReports(reports, 2);\n break;\n case 'table':\n printTableReports(reports);\n break;\n case 'markdown':\n printMarkdownReports(reports);\n break;\n case 'histogram':\n printHistogramReports(reports);\n break;\n default:\n printSimpleReports(reports);\n }\n }\n }\n }\n }\n });\n\ncommander.parse(process.argv);\n"],"names":["createRequire","Module","fileURLToPath","pathToFileURL","SyntheticModule","createContext","SourceTextModule","stat","readFile","writeFile","Command","Option","glob","Benchmark","printTableReports","printJSONReports","printSimpleReports","printMarkdownReports","printHistogramReports","printComparisonReports","reportsToBaseline","DEFAULT_REPORT_TYPES","DEFAULT_WORKERS","transpile","REPORT_TYPES","require","url","name","description","version","BENCHMARK_URL","Symbol","for","commander","argument","addOption","choices","default","argParser","parseInt","parseFloat","action","patterns","executeOptions","baseline","compareBaseline","content","JSON","parse","console","error","files","Set","Promise","all","map","pattern","matches","absolute","cwd","process","catch","forEach","file","add","stats","isFile","identifier","href","code","instance","benchmark","args","Error","create","globals","Object","k","getOwnPropertyNames","globalThis","script","context","initializeImportMeta","meta","importModuleDynamically","specifier","referencingModule","isBuiltin","baseIdentifier","resolveFrom","resolved","resolve","imports","Map","link","target","cached","get","mod","exportNames","keys","imported","key","setExport","set","evaluate","reports","execute","saveBaseline","baselineData","stringify","log","format","argv"],"mappings":"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"}
package/build/worker.cjs CHANGED
@@ -73,10 +73,11 @@ export const pre = ${serialize(preCode)};
73
73
  export const run = ${serialize(runCode)};
74
74
  export const post = ${serialize(postCode)};
75
75
  `;
76
- const context = (0, _nodevm.createContext)({
77
- console,
78
- Buffer
79
- });
76
+ const globals = Object.create(null);
77
+ for (const k of Object.getOwnPropertyNames(globalThis)){
78
+ globals[k] = globalThis[k];
79
+ }
80
+ const context = (0, _nodevm.createContext)(globals);
80
81
  const imports = new Map();
81
82
  const createSyntheticModule = (moduleExports, exportNames, identifier)=>{
82
83
  const mod = new _nodevm.SyntheticModule(exportNames, ()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/worker.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport { SourceTextModule, SyntheticModule, createContext } from 'node:vm';\nimport { createRequire } from 'node:module';\nimport { isAbsolute } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { benchmark } from './runner.js';\nimport { WorkerOptions } from './types.js';\n\nconst {\n benchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n\n durationsSAB,\n controlSAB,\n}: WorkerOptions = workerData;\n\nconst serialize = (code?: string) => (code ? code : 'undefined');\n\nconst resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\nconst benchmarkDirUrl = new URL('.', resolvedBenchmarkUrl).href;\nconst requireFrom = createRequire(fileURLToPath(new URL('benchmark.js', benchmarkDirUrl)));\n\nconst resolveSpecifier = (specifier: string) => {\n if (specifier.startsWith('file:')) {\n return specifier;\n }\n if (specifier.startsWith('./') || specifier.startsWith('../')) {\n return new URL(specifier, benchmarkDirUrl).href;\n }\n if (isAbsolute(specifier)) {\n return pathToFileURL(specifier).href;\n }\n return requireFrom.resolve(specifier);\n};\n\nconst source = `\nexport const setup = ${serialize(setupCode)};\nexport const teardown = ${serialize(teardownCode)};\nexport const pre = ${serialize(preCode)};\nexport const run = ${serialize(runCode)};\nexport const post = ${serialize(postCode)};\n `;\n\nconst context = createContext({ console, Buffer });\nconst imports = new Map<string, SyntheticModule>();\n\nconst createSyntheticModule = (moduleExports: unknown, exportNames: string[], identifier: string) => {\n const mod = new SyntheticModule(\n exportNames,\n () => {\n for (const name of exportNames) {\n if (name === 'default') {\n mod.setExport(name, moduleExports);\n continue;\n }\n mod.setExport(name, (moduleExports as Record<string, unknown>)[name]);\n }\n },\n { identifier, context },\n );\n return mod;\n};\n\nconst isCjsModule = (target: string) => target.endsWith('.cjs') || target.endsWith('.cts');\n\nconst toRequireTarget = (target: string) => (target.startsWith('file:') ? fileURLToPath(target) : target);\n\nconst loadModule = async (target: string) => {\n const cached = imports.get(target);\n if (cached) return cached;\n\n if (isCjsModule(target)) {\n const required = requireFrom(toRequireTarget(target));\n const exportNames = required && (typeof required === 'object' || typeof required === 'function') ? Object.keys(required) : [];\n if (!exportNames.includes('default')) {\n exportNames.push('default');\n }\n const mod = createSyntheticModule(required, exportNames, target);\n imports.set(target, mod);\n return mod;\n }\n\n const importedModule = await import(target);\n const exportNames = Object.keys(importedModule);\n const mod = createSyntheticModule(importedModule, exportNames, target);\n imports.set(target, mod);\n return mod;\n};\n\nconst loadDynamicModule = async (target: string) => {\n const mod = await loadModule(target);\n if (mod.status !== 'evaluated') {\n await mod.evaluate();\n }\n return mod;\n};\nconst mod = new SourceTextModule(source, {\n identifier: resolvedBenchmarkUrl,\n context,\n initializeImportMeta(meta) {\n meta.url = resolvedBenchmarkUrl;\n },\n importModuleDynamically(specifier) {\n const resolved = resolveSpecifier(specifier);\n return loadDynamicModule(resolved);\n },\n});\n\nawait mod.link(async (specifier) => loadModule(resolveSpecifier(specifier)));\n\nawait mod.evaluate();\nconst { setup, teardown, pre, run, post } = mod.namespace as any;\n\nif (!run) {\n throw new Error('Benchmark run function is required');\n}\n\nprocess.exitCode = await benchmark({\n setup,\n teardown,\n pre,\n run,\n post,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n durationsSAB,\n controlSAB,\n});\n"],"names":["benchmarkUrl","setupCode","teardownCode","preCode","runCode","postCode","data","warmupCycles","minCycles","absThreshold","relThreshold","gcObserver","durationsSAB","controlSAB","workerData","serialize","code","resolvedBenchmarkUrl","pathToFileURL","process","cwd","href","benchmarkDirUrl","URL","requireFrom","createRequire","fileURLToPath","resolveSpecifier","specifier","startsWith","isAbsolute","resolve","source","context","createContext","console","Buffer","imports","Map","createSyntheticModule","moduleExports","exportNames","identifier","mod","SyntheticModule","name","setExport","isCjsModule","target","endsWith","toRequireTarget","loadModule","cached","get","required","Object","keys","includes","push","set","importedModule","loadDynamicModule","status","evaluate","SourceTextModule","initializeImportMeta","meta","url","importModuleDynamically","resolved","link","setup","teardown","pre","run","post","namespace","Error","exitCode","benchmark"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/worker.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport { SourceTextModule, SyntheticModule, createContext } from 'node:vm';\nimport { createRequire } from 'node:module';\nimport { isAbsolute } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { benchmark } from './runner.js';\nimport { WorkerOptions } from './types.js';\n\nconst {\n benchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n\n durationsSAB,\n controlSAB,\n}: WorkerOptions = workerData;\n\nconst serialize = (code?: string) => (code ? code : 'undefined');\n\nconst resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\nconst benchmarkDirUrl = new URL('.', resolvedBenchmarkUrl).href;\nconst requireFrom = createRequire(fileURLToPath(new URL('benchmark.js', benchmarkDirUrl)));\n\nconst resolveSpecifier = (specifier: string) => {\n if (specifier.startsWith('file:')) {\n return specifier;\n }\n if (specifier.startsWith('./') || specifier.startsWith('../')) {\n return new URL(specifier, benchmarkDirUrl).href;\n }\n if (isAbsolute(specifier)) {\n return pathToFileURL(specifier).href;\n }\n return requireFrom.resolve(specifier);\n};\n\nconst source = `\nexport const setup = ${serialize(setupCode)};\nexport const teardown = ${serialize(teardownCode)};\nexport const pre = ${serialize(preCode)};\nexport const run = ${serialize(runCode)};\nexport const post = ${serialize(postCode)};\n `;\n\nconst globals = Object.create(null);\nfor (const k of Object.getOwnPropertyNames(globalThis)) {\n globals[k] = (globalThis as any)[k];\n}\nconst context = createContext(globals);\nconst imports = new Map<string, SyntheticModule>();\n\nconst createSyntheticModule = (moduleExports: unknown, exportNames: string[], identifier: string) => {\n const mod = new SyntheticModule(\n exportNames,\n () => {\n for (const name of exportNames) {\n if (name === 'default') {\n mod.setExport(name, moduleExports);\n continue;\n }\n mod.setExport(name, (moduleExports as Record<string, unknown>)[name]);\n }\n },\n { identifier, context },\n );\n return mod;\n};\n\nconst isCjsModule = (target: string) => target.endsWith('.cjs') || target.endsWith('.cts');\n\nconst toRequireTarget = (target: string) => (target.startsWith('file:') ? fileURLToPath(target) : target);\n\nconst loadModule = async (target: string) => {\n const cached = imports.get(target);\n if (cached) return cached;\n\n if (isCjsModule(target)) {\n const required = requireFrom(toRequireTarget(target));\n const exportNames = required && (typeof required === 'object' || typeof required === 'function') ? Object.keys(required) : [];\n if (!exportNames.includes('default')) {\n exportNames.push('default');\n }\n const mod = createSyntheticModule(required, exportNames, target);\n imports.set(target, mod);\n return mod;\n }\n\n const importedModule = await import(target);\n const exportNames = Object.keys(importedModule);\n const mod = createSyntheticModule(importedModule, exportNames, target);\n imports.set(target, mod);\n return mod;\n};\n\nconst loadDynamicModule = async (target: string) => {\n const mod = await loadModule(target);\n if (mod.status !== 'evaluated') {\n await mod.evaluate();\n }\n return mod;\n};\nconst mod = new SourceTextModule(source, {\n identifier: resolvedBenchmarkUrl,\n context,\n initializeImportMeta(meta) {\n meta.url = resolvedBenchmarkUrl;\n },\n importModuleDynamically(specifier) {\n const resolved = resolveSpecifier(specifier);\n return loadDynamicModule(resolved);\n },\n});\n\nawait mod.link(async (specifier) => loadModule(resolveSpecifier(specifier)));\n\nawait mod.evaluate();\nconst { setup, teardown, pre, run, post } = mod.namespace as any;\n\nif (!run) {\n throw new Error('Benchmark run function is required');\n}\n\nprocess.exitCode = await benchmark({\n setup,\n teardown,\n pre,\n run,\n post,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n durationsSAB,\n controlSAB,\n});\n"],"names":["benchmarkUrl","setupCode","teardownCode","preCode","runCode","postCode","data","warmupCycles","minCycles","absThreshold","relThreshold","gcObserver","durationsSAB","controlSAB","workerData","serialize","code","resolvedBenchmarkUrl","pathToFileURL","process","cwd","href","benchmarkDirUrl","URL","requireFrom","createRequire","fileURLToPath","resolveSpecifier","specifier","startsWith","isAbsolute","resolve","source","globals","Object","create","k","getOwnPropertyNames","globalThis","context","createContext","imports","Map","createSyntheticModule","moduleExports","exportNames","identifier","mod","SyntheticModule","name","setExport","isCjsModule","target","endsWith","toRequireTarget","loadModule","cached","get","required","keys","includes","push","set","importedModule","loadDynamicModule","status","evaluate","SourceTextModule","initializeImportMeta","meta","url","importModuleDynamically","resolved","link","setup","teardown","pre","run","post","namespace","Error","exitCode","benchmark"],"mappings":"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"}
package/build/worker.js CHANGED
@@ -28,10 +28,11 @@ export const pre = ${serialize(preCode)};
28
28
  export const run = ${serialize(runCode)};
29
29
  export const post = ${serialize(postCode)};
30
30
  `;
31
- const context = createContext({
32
- console,
33
- Buffer
34
- });
31
+ const globals = Object.create(null);
32
+ for (const k of Object.getOwnPropertyNames(globalThis)){
33
+ globals[k] = globalThis[k];
34
+ }
35
+ const context = createContext(globals);
35
36
  const imports = new Map();
36
37
  const createSyntheticModule = (moduleExports, exportNames, identifier)=>{
37
38
  const mod = new SyntheticModule(exportNames, ()=>{
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/worker.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport { SourceTextModule, SyntheticModule, createContext } from 'node:vm';\nimport { createRequire } from 'node:module';\nimport { isAbsolute } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { benchmark } from './runner.js';\nimport { WorkerOptions } from './types.js';\n\nconst {\n benchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n\n durationsSAB,\n controlSAB,\n}: WorkerOptions = workerData;\n\nconst serialize = (code?: string) => (code ? code : 'undefined');\n\nconst resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\nconst benchmarkDirUrl = new URL('.', resolvedBenchmarkUrl).href;\nconst requireFrom = createRequire(fileURLToPath(new URL('benchmark.js', benchmarkDirUrl)));\n\nconst resolveSpecifier = (specifier: string) => {\n if (specifier.startsWith('file:')) {\n return specifier;\n }\n if (specifier.startsWith('./') || specifier.startsWith('../')) {\n return new URL(specifier, benchmarkDirUrl).href;\n }\n if (isAbsolute(specifier)) {\n return pathToFileURL(specifier).href;\n }\n return requireFrom.resolve(specifier);\n};\n\nconst source = `\nexport const setup = ${serialize(setupCode)};\nexport const teardown = ${serialize(teardownCode)};\nexport const pre = ${serialize(preCode)};\nexport const run = ${serialize(runCode)};\nexport const post = ${serialize(postCode)};\n `;\n\nconst context = createContext({ console, Buffer });\nconst imports = new Map<string, SyntheticModule>();\n\nconst createSyntheticModule = (moduleExports: unknown, exportNames: string[], identifier: string) => {\n const mod = new SyntheticModule(\n exportNames,\n () => {\n for (const name of exportNames) {\n if (name === 'default') {\n mod.setExport(name, moduleExports);\n continue;\n }\n mod.setExport(name, (moduleExports as Record<string, unknown>)[name]);\n }\n },\n { identifier, context },\n );\n return mod;\n};\n\nconst isCjsModule = (target: string) => target.endsWith('.cjs') || target.endsWith('.cts');\n\nconst toRequireTarget = (target: string) => (target.startsWith('file:') ? fileURLToPath(target) : target);\n\nconst loadModule = async (target: string) => {\n const cached = imports.get(target);\n if (cached) return cached;\n\n if (isCjsModule(target)) {\n const required = requireFrom(toRequireTarget(target));\n const exportNames = required && (typeof required === 'object' || typeof required === 'function') ? Object.keys(required) : [];\n if (!exportNames.includes('default')) {\n exportNames.push('default');\n }\n const mod = createSyntheticModule(required, exportNames, target);\n imports.set(target, mod);\n return mod;\n }\n\n const importedModule = await import(target);\n const exportNames = Object.keys(importedModule);\n const mod = createSyntheticModule(importedModule, exportNames, target);\n imports.set(target, mod);\n return mod;\n};\n\nconst loadDynamicModule = async (target: string) => {\n const mod = await loadModule(target);\n if (mod.status !== 'evaluated') {\n await mod.evaluate();\n }\n return mod;\n};\nconst mod = new SourceTextModule(source, {\n identifier: resolvedBenchmarkUrl,\n context,\n initializeImportMeta(meta) {\n meta.url = resolvedBenchmarkUrl;\n },\n importModuleDynamically(specifier) {\n const resolved = resolveSpecifier(specifier);\n return loadDynamicModule(resolved);\n },\n});\n\nawait mod.link(async (specifier) => loadModule(resolveSpecifier(specifier)));\n\nawait mod.evaluate();\nconst { setup, teardown, pre, run, post } = mod.namespace as any;\n\nif (!run) {\n throw new Error('Benchmark run function is required');\n}\n\nprocess.exitCode = await benchmark({\n setup,\n teardown,\n pre,\n run,\n post,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n durationsSAB,\n controlSAB,\n});\n"],"names":["workerData","SourceTextModule","SyntheticModule","createContext","createRequire","isAbsolute","fileURLToPath","pathToFileURL","benchmark","benchmarkUrl","setupCode","teardownCode","preCode","runCode","postCode","data","warmupCycles","minCycles","absThreshold","relThreshold","gcObserver","durationsSAB","controlSAB","serialize","code","resolvedBenchmarkUrl","process","cwd","href","benchmarkDirUrl","URL","requireFrom","resolveSpecifier","specifier","startsWith","resolve","source","context","console","Buffer","imports","Map","createSyntheticModule","moduleExports","exportNames","identifier","mod","name","setExport","isCjsModule","target","endsWith","toRequireTarget","loadModule","cached","get","required","Object","keys","includes","push","set","importedModule","loadDynamicModule","status","evaluate","initializeImportMeta","meta","url","importModuleDynamically","resolved","link","setup","teardown","pre","run","post","namespace","Error","exitCode"],"mappings":"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"}
1
+ {"version":3,"sources":["../src/worker.ts"],"sourcesContent":["import { workerData } from 'node:worker_threads';\nimport { SourceTextModule, SyntheticModule, createContext } from 'node:vm';\nimport { createRequire } from 'node:module';\nimport { isAbsolute } from 'node:path';\nimport { fileURLToPath, pathToFileURL } from 'node:url';\nimport { benchmark } from './runner.js';\nimport { WorkerOptions } from './types.js';\n\nconst {\n benchmarkUrl,\n setupCode,\n teardownCode,\n preCode,\n runCode,\n postCode,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver = true,\n\n durationsSAB,\n controlSAB,\n}: WorkerOptions = workerData;\n\nconst serialize = (code?: string) => (code ? code : 'undefined');\n\nconst resolvedBenchmarkUrl = typeof benchmarkUrl === 'string' ? benchmarkUrl : pathToFileURL(process.cwd()).href;\nconst benchmarkDirUrl = new URL('.', resolvedBenchmarkUrl).href;\nconst requireFrom = createRequire(fileURLToPath(new URL('benchmark.js', benchmarkDirUrl)));\n\nconst resolveSpecifier = (specifier: string) => {\n if (specifier.startsWith('file:')) {\n return specifier;\n }\n if (specifier.startsWith('./') || specifier.startsWith('../')) {\n return new URL(specifier, benchmarkDirUrl).href;\n }\n if (isAbsolute(specifier)) {\n return pathToFileURL(specifier).href;\n }\n return requireFrom.resolve(specifier);\n};\n\nconst source = `\nexport const setup = ${serialize(setupCode)};\nexport const teardown = ${serialize(teardownCode)};\nexport const pre = ${serialize(preCode)};\nexport const run = ${serialize(runCode)};\nexport const post = ${serialize(postCode)};\n `;\n\nconst globals = Object.create(null);\nfor (const k of Object.getOwnPropertyNames(globalThis)) {\n globals[k] = (globalThis as any)[k];\n}\nconst context = createContext(globals);\nconst imports = new Map<string, SyntheticModule>();\n\nconst createSyntheticModule = (moduleExports: unknown, exportNames: string[], identifier: string) => {\n const mod = new SyntheticModule(\n exportNames,\n () => {\n for (const name of exportNames) {\n if (name === 'default') {\n mod.setExport(name, moduleExports);\n continue;\n }\n mod.setExport(name, (moduleExports as Record<string, unknown>)[name]);\n }\n },\n { identifier, context },\n );\n return mod;\n};\n\nconst isCjsModule = (target: string) => target.endsWith('.cjs') || target.endsWith('.cts');\n\nconst toRequireTarget = (target: string) => (target.startsWith('file:') ? fileURLToPath(target) : target);\n\nconst loadModule = async (target: string) => {\n const cached = imports.get(target);\n if (cached) return cached;\n\n if (isCjsModule(target)) {\n const required = requireFrom(toRequireTarget(target));\n const exportNames = required && (typeof required === 'object' || typeof required === 'function') ? Object.keys(required) : [];\n if (!exportNames.includes('default')) {\n exportNames.push('default');\n }\n const mod = createSyntheticModule(required, exportNames, target);\n imports.set(target, mod);\n return mod;\n }\n\n const importedModule = await import(target);\n const exportNames = Object.keys(importedModule);\n const mod = createSyntheticModule(importedModule, exportNames, target);\n imports.set(target, mod);\n return mod;\n};\n\nconst loadDynamicModule = async (target: string) => {\n const mod = await loadModule(target);\n if (mod.status !== 'evaluated') {\n await mod.evaluate();\n }\n return mod;\n};\nconst mod = new SourceTextModule(source, {\n identifier: resolvedBenchmarkUrl,\n context,\n initializeImportMeta(meta) {\n meta.url = resolvedBenchmarkUrl;\n },\n importModuleDynamically(specifier) {\n const resolved = resolveSpecifier(specifier);\n return loadDynamicModule(resolved);\n },\n});\n\nawait mod.link(async (specifier) => loadModule(resolveSpecifier(specifier)));\n\nawait mod.evaluate();\nconst { setup, teardown, pre, run, post } = mod.namespace as any;\n\nif (!run) {\n throw new Error('Benchmark run function is required');\n}\n\nprocess.exitCode = await benchmark({\n setup,\n teardown,\n pre,\n run,\n post,\n data,\n\n warmupCycles,\n minCycles,\n absThreshold,\n relThreshold,\n gcObserver,\n\n durationsSAB,\n controlSAB,\n});\n"],"names":["workerData","SourceTextModule","SyntheticModule","createContext","createRequire","isAbsolute","fileURLToPath","pathToFileURL","benchmark","benchmarkUrl","setupCode","teardownCode","preCode","runCode","postCode","data","warmupCycles","minCycles","absThreshold","relThreshold","gcObserver","durationsSAB","controlSAB","serialize","code","resolvedBenchmarkUrl","process","cwd","href","benchmarkDirUrl","URL","requireFrom","resolveSpecifier","specifier","startsWith","resolve","source","globals","Object","create","k","getOwnPropertyNames","globalThis","context","imports","Map","createSyntheticModule","moduleExports","exportNames","identifier","mod","name","setExport","isCjsModule","target","endsWith","toRequireTarget","loadModule","cached","get","required","keys","includes","push","set","importedModule","loadDynamicModule","status","evaluate","initializeImportMeta","meta","url","importModuleDynamically","resolved","link","setup","teardown","pre","run","post","namespace","Error","exitCode"],"mappings":"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"}
package/context7.json ADDED
@@ -0,0 +1,4 @@
1
+ {
2
+ "url": "https://context7.com/3axap4ehko/overtake",
3
+ "public_key": "pk_cWMMIaGchuWIje6ayobfY"
4
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "overtake",
3
- "version": "1.3.0",
3
+ "version": "1.3.2",
4
4
  "description": "NodeJS performance benchmark",
5
5
  "type": "module",
6
6
  "types": "build/index.d.ts",
@@ -45,21 +45,21 @@
45
45
  "@swc/jest": "^0.2.39",
46
46
  "@types/async": "^3.2.25",
47
47
  "@types/jest": "^30.0.0",
48
- "@types/node": "^25.0.3",
48
+ "@types/node": "^25.3.0",
49
49
  "@types/progress": "^2.0.7",
50
50
  "husky": "^9.1.7",
51
- "inop": "^0.8.10",
51
+ "inop": "^0.9.0",
52
52
  "jest": "^30.2.0",
53
- "overtake": "^1.1.1",
54
- "prettier": "^3.7.4",
53
+ "overtake": "^1.3.1",
54
+ "prettier": "^3.8.1",
55
55
  "pretty-quick": "^4.2.2",
56
56
  "typescript": "^5.9.3"
57
57
  },
58
58
  "dependencies": {
59
- "@swc/core": "^1.15.8",
59
+ "@swc/core": "^1.15.11",
60
60
  "async": "^3.2.6",
61
- "commander": "^14.0.2",
62
- "glob": "^13.0.0",
61
+ "commander": "^14.0.3",
62
+ "glob": "^13.0.6",
63
63
  "progress": "^2.0.3"
64
64
  },
65
65
  "scripts": {
package/src/cli.ts CHANGED
@@ -76,13 +76,14 @@ commander
76
76
  instance = Benchmark.create(...args);
77
77
  return instance;
78
78
  };
79
+ const globals = Object.create(null);
80
+ for (const k of Object.getOwnPropertyNames(globalThis)) {
81
+ globals[k] = (globalThis as any)[k];
82
+ }
83
+ globals.benchmark = benchmark;
79
84
  const script = new SourceTextModule(code, {
80
85
  identifier,
81
- context: createContext({
82
- benchmark,
83
- Buffer,
84
- console,
85
- }),
86
+ context: createContext(globals),
86
87
  initializeImportMeta(meta) {
87
88
  meta.url = identifier;
88
89
  },
package/src/worker.ts CHANGED
@@ -52,7 +52,11 @@ export const run = ${serialize(runCode)};
52
52
  export const post = ${serialize(postCode)};
53
53
  `;
54
54
 
55
- const context = createContext({ console, Buffer });
55
+ const globals = Object.create(null);
56
+ for (const k of Object.getOwnPropertyNames(globalThis)) {
57
+ globals[k] = (globalThis as any)[k];
58
+ }
59
+ const context = createContext(globals);
56
60
  const imports = new Map<string, SyntheticModule>();
57
61
 
58
62
  const createSyntheticModule = (moduleExports: unknown, exportNames: string[], identifier: string) => {