From 21ba4935ad07876d42bd3d600943e65fbbc95452 Mon Sep 17 00:00:00 2001 From: Vladimir Date: Mon, 18 Sep 2023 10:03:28 +0200 Subject: [PATCH] perf: use lazy require in vm pool (#4136) --- .../vitest/src/runtime/vm/commonjs-executor.ts | 16 +++++++++++++--- test/vm-threads/test/module.test.js | 8 ++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) create mode 100644 test/vm-threads/test/module.test.js diff --git a/packages/vitest/src/runtime/vm/commonjs-executor.ts b/packages/vitest/src/runtime/vm/commonjs-executor.ts index 38782a7231d0..49a5d3a3640f 100644 --- a/packages/vitest/src/runtime/vm/commonjs-executor.ts +++ b/packages/vitest/src/runtime/vm/commonjs-executor.ts @@ -19,6 +19,8 @@ interface PrivateNodeModule extends NodeModule { _compile(code: string, filename: string): void } +const requiresCache = new WeakMap() + export class CommonjsExecutor { private context: vm.Context private requireCache = new Map() @@ -46,7 +48,6 @@ export class CommonjsExecutor { this.Module = class Module { exports: any isPreloading = false - require: NodeRequire id: string filename: string loaded: boolean @@ -55,9 +56,8 @@ export class CommonjsExecutor { path: string paths: string[] = [] - constructor(id: string, parent?: Module) { + constructor(id = '', parent?: Module) { this.exports = primitives.Object.create(Object.prototype) - this.require = Module.createRequire(id) // in our case the path should always be resolved already this.path = dirname(id) this.id = id @@ -66,6 +66,16 @@ export class CommonjsExecutor { this.parent = parent } + get require() { + const require = requiresCache.get(this) + if (require) + return require + + const _require = Module.createRequire(this.id) + requiresCache.set(this, _require) + return _require + } + _compile(code: string, filename: string) { const cjsModule = Module.wrap(code) const script = new vm.Script(cjsModule, { diff --git a/test/vm-threads/test/module.test.js b/test/vm-threads/test/module.test.js new file mode 100644 index 000000000000..377a933d7b38 --- /dev/null +++ b/test/vm-threads/test/module.test.js @@ -0,0 +1,8 @@ +import { Module } from 'node:module' +import { expect, it } from 'vitest' + +it('can create modules with incorrect filepath', () => { + expect(() => new Module('name')).not.toThrow() + // require will not work for these modules because native createRequire fails + expect(() => new Module('some-other-name').require('node:url')).toThrow() +})