diff --git a/packages/vitest/src/runtime/vm/commonjs-executor.ts b/packages/vitest/src/runtime/vm/commonjs-executor.ts index 9038ebb27..6d12b716e 100644 --- a/packages/vitest/src/runtime/vm/commonjs-executor.ts +++ b/packages/vitest/src/runtime/vm/commonjs-executor.ts @@ -166,7 +166,7 @@ export class CommonjsExecutor { const __dirname = dirname(filename) executor.requireCache.set(filename, this) try { - fn(this.exports, this.require, this, filename, __dirname) + fn.call(this.exports, this.exports, this.require, this, filename, __dirname) return this.exports } finally { this.loaded = true diff --git a/test/e2e/test/vm-threads.test.ts b/test/e2e/test/vm-threads.test.ts index 38de8d3b7..49eacb0ec 100644 --- a/test/e2e/test/vm-threads.test.ts +++ b/test/e2e/test/vm-threads.test.ts @@ -206,6 +206,37 @@ test.for(['vmThreads', 'vmForks'] as const)( }, ) +test.for(['vmThreads', 'vmForks'] as const)( + '%s binds top-level this to module.exports in CommonJS', + async (pool) => { + const { stderr, exitCode } = await runInlineTests( + { + 'node_modules/commonjs-this/package.json': JSON.stringify({ + name: 'commonjs-this', + main: './index.cjs', + }), + 'node_modules/commonjs-this/index.cjs': ` + 'use strict' + this.value = 42 + exports.isExports = this === module.exports + `, + 'basic.test.js': ` + import { expect, test } from 'vitest' + import commonjs from 'commonjs-this' + + test('this is module.exports', () => { + expect(commonjs).toEqual({ value: 42, isExports: true }) + }) + `, + }, + { pool }, + ) + + expect(stderr).toBe('') + expect(exitCode).toBe(0) + }, +) + // The module-sync condition was added in Node 22.12/20.19 when require(esm) // was unflagged. The fix uses the _resolveFilename conditions option which // is only available on Node 22.12+. Node 20 is unfixable and reaches EOL