11import type { FileMap } from './file-map'
2- import type { ImportModuleDynamically , VMModule } from './types'
2+ import type { ImportModuleDynamically , VMSyntheticModule } from './types'
33import { Module as _Module , createRequire } from 'node:module'
44import vm from 'node:vm'
55import { basename , dirname , extname } from 'pathe'
66import { isNodeBuiltin } from 'vite-node/utils'
7+ import { interopCommonJsModule , SyntheticModule } from './utils'
78
89interface CommonjsExecutorOptions {
910 fileMap : FileMap
11+ interopDefault ?: boolean
1012 context : vm . Context
1113 importModuleDynamically : ImportModuleDynamically
1214}
@@ -24,7 +26,7 @@ export class CommonjsExecutor {
2426 private requireCache = new Map < string , NodeJS . Module > ( )
2527 private publicRequireCache = this . createProxyCache ( )
2628
27- private moduleCache = new Map < string , VMModule | Promise < VMModule > > ( )
29+ private moduleCache = new Map < string , VMSyntheticModule > ( )
2830 private builtinCache : Record < string , NodeJS . Module > = Object . create ( null )
2931 private extensions : Record <
3032 string ,
@@ -33,10 +35,12 @@ export class CommonjsExecutor {
3335
3436 private fs : FileMap
3537 private Module : typeof _Module
38+ private interopDefault : boolean | undefined
3639
3740 constructor ( options : CommonjsExecutorOptions ) {
3841 this . context = options . context
3942 this . fs = options . fileMap
43+ this . interopDefault = options . interopDefault
4044
4145 const primitives = vm . runInContext (
4246 '({ Object, Array, Error })' ,
@@ -132,7 +136,7 @@ export class CommonjsExecutor {
132136 static SourceMap = _Module . SourceMap
133137 static syncBuiltinESMExports = _Module . syncBuiltinESMExports
134138
135- static _cache = executor . moduleCache
139+ static _cache = executor . publicRequireCache
136140 static _extensions = executor . extensions
137141
138142 static createRequire = ( filename : string | URL ) => {
@@ -256,6 +260,86 @@ export class CommonjsExecutor {
256260 return '.js'
257261 }
258262
263+ public getCoreSyntheticModule ( identifier : string ) : VMSyntheticModule {
264+ if ( this . moduleCache . has ( identifier ) ) {
265+ return this . moduleCache . get ( identifier ) !
266+ }
267+ const exports = this . require ( identifier )
268+ const keys = Object . keys ( exports )
269+ const module = new SyntheticModule ( [ ...keys , 'default' ] , ( ) => {
270+ for ( const key of keys ) {
271+ module . setExport ( key , exports [ key ] )
272+ }
273+ module . setExport ( 'default' , exports )
274+ } , { context : this . context , identifier } )
275+ this . moduleCache . set ( identifier , module )
276+ return module
277+ }
278+
279+ public getCjsSyntheticModule ( path : string , identifier : string ) : VMSyntheticModule {
280+ if ( this . moduleCache . has ( identifier ) ) {
281+ return this . moduleCache . get ( identifier ) !
282+ }
283+ const exports = this . require ( path )
284+ // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
285+ const { keys, moduleExports, defaultExport } = interopCommonJsModule (
286+ this . interopDefault ,
287+ exports ,
288+ )
289+ const module = new SyntheticModule ( [ ...keys , 'default' ] , function ( ) {
290+ for ( const key of keys ) {
291+ this . setExport ( key , moduleExports [ key ] )
292+ }
293+ this . setExport ( 'default' , defaultExport )
294+ } , { context : this . context , identifier } )
295+ this . moduleCache . set ( identifier , module )
296+ return module
297+ }
298+
299+ // TODO: use this in strict mode, when available in #2854
300+ // private _getNamedCjsExports(path: string): Set<string> {
301+ // const cachedNamedExports = this.cjsNamedExportsMap.get(path)
302+
303+ // if (cachedNamedExports) {
304+ // return cachedNamedExports
305+ // }
306+
307+ // if (extname(path) === '.node') {
308+ // const moduleExports = this.require(path)
309+ // const namedExports = new Set(Object.keys(moduleExports))
310+ // this.cjsNamedExportsMap.set(path, namedExports)
311+ // return namedExports
312+ // }
313+
314+ // const code = this.fs.readFile(path)
315+ // const { exports, reexports } = parseCjs(code, path)
316+ // const namedExports = new Set(exports)
317+ // this.cjsNamedExportsMap.set(path, namedExports)
318+
319+ // for (const reexport of reexports) {
320+ // if (isNodeBuiltin(reexport)) {
321+ // const exports = this.require(reexport)
322+ // if (exports !== null && typeof exports === 'object') {
323+ // for (const e of Object.keys(exports)) {
324+ // namedExports.add(e)
325+ // }
326+ // }
327+ // }
328+ // else {
329+ // const require = this.createRequire(path)
330+ // const resolved = require.resolve(reexport)
331+
332+ // const exports = this._getNamedCjsExports(resolved)
333+
334+ // for (const e of exports) {
335+ // namedExports.add(e)
336+ // }
337+ // }
338+ // }
339+
340+ // return namedExports
341+ // }
342+
259343 public require ( identifier : string ) : any {
260344 const ext = extname ( identifier )
261345 if ( ext === '.node' || isNodeBuiltin ( identifier ) ) {
0 commit comments