1
1
import type { FileMap } from './file-map'
2
- import type { ImportModuleDynamically , VMModule } from './types'
2
+ import type { ImportModuleDynamically , VMSyntheticModule } from './types'
3
3
import { Module as _Module , createRequire } from 'node:module'
4
4
import vm from 'node:vm'
5
5
import { basename , dirname , extname } from 'pathe'
6
6
import { isNodeBuiltin } from 'vite-node/utils'
7
+ import { interopCommonJsModule , SyntheticModule } from './utils'
7
8
8
9
interface CommonjsExecutorOptions {
9
10
fileMap : FileMap
11
+ interopDefault ?: boolean
10
12
context : vm . Context
11
13
importModuleDynamically : ImportModuleDynamically
12
14
}
@@ -24,7 +26,7 @@ export class CommonjsExecutor {
24
26
private requireCache = new Map < string , NodeJS . Module > ( )
25
27
private publicRequireCache = this . createProxyCache ( )
26
28
27
- private moduleCache = new Map < string , VMModule | Promise < VMModule > > ( )
29
+ private moduleCache = new Map < string , VMSyntheticModule > ( )
28
30
private builtinCache : Record < string , NodeJS . Module > = Object . create ( null )
29
31
private extensions : Record <
30
32
string ,
@@ -33,10 +35,12 @@ export class CommonjsExecutor {
33
35
34
36
private fs : FileMap
35
37
private Module : typeof _Module
38
+ private interopDefault : boolean | undefined
36
39
37
40
constructor ( options : CommonjsExecutorOptions ) {
38
41
this . context = options . context
39
42
this . fs = options . fileMap
43
+ this . interopDefault = options . interopDefault
40
44
41
45
const primitives = vm . runInContext (
42
46
'({ Object, Array, Error })' ,
@@ -132,7 +136,7 @@ export class CommonjsExecutor {
132
136
static SourceMap = _Module . SourceMap
133
137
static syncBuiltinESMExports = _Module . syncBuiltinESMExports
134
138
135
- static _cache = executor . moduleCache
139
+ static _cache = executor . publicRequireCache
136
140
static _extensions = executor . extensions
137
141
138
142
static createRequire = ( filename : string | URL ) => {
@@ -256,6 +260,86 @@ export class CommonjsExecutor {
256
260
return '.js'
257
261
}
258
262
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
+
259
343
public require ( identifier : string ) : any {
260
344
const ext = extname ( identifier )
261
345
if ( ext === '.node' || isNodeBuiltin ( identifier ) ) {
0 commit comments