@@ -6,9 +6,10 @@ import { dirname } from 'node:path'
6
6
import { Module as _Module , createRequire } from 'node:module'
7
7
import { readFileSync , statSync } from 'node:fs'
8
8
import { basename , extname , join , normalize } from 'pathe'
9
- import { getCachedData , isNodeBuiltin , setCacheData } from 'vite-node/utils'
9
+ import { getCachedData , isNodeBuiltin , isPrimitive , setCacheData } from 'vite-node/utils'
10
10
import { CSS_LANGS_RE , KNOWN_ASSET_RE } from 'vite-node/constants'
11
11
import { getColors } from '@vitest/utils'
12
+ import type { ExecuteOptions } from './execute'
12
13
13
14
// need to copy paste types for vm
14
15
// because they require latest @types /node which we don't bundle
@@ -95,7 +96,7 @@ const nativeResolve = import.meta.resolve!
95
96
const dataURIRegex
96
97
= / ^ d a t a : (?< mime > t e x t \/ j a v a s c r i p t | a p p l i c a t i o n \/ j s o n | a p p l i c a t i o n \/ w a s m ) (?: ; (?< encoding > c h a r s e t = u t f - 8 | b a s e 6 4 ) ) ? , (?< code > .* ) $ /
97
98
98
- interface ExternalModulesExecutorOptions {
99
+ export interface ExternalModulesExecutorOptions extends ExecuteOptions {
99
100
context : vm . Context
100
101
packageCache : Map < string , any >
101
102
}
@@ -273,7 +274,7 @@ export class ExternalModulesExecutor {
273
274
return buffer
274
275
}
275
276
276
- private findNearestPackageData ( basedir : string ) {
277
+ private findNearestPackageData ( basedir : string ) : { type ?: 'module' | 'commonjs' } {
277
278
const originalBasedir = basedir
278
279
const packageCache = this . options . packageCache
279
280
while ( basedir ) {
@@ -300,12 +301,11 @@ export class ExternalModulesExecutor {
300
301
basedir = nextBasedir
301
302
}
302
303
303
- return null
304
+ return { }
304
305
}
305
306
306
- private wrapSynteticModule ( identifier : string , exports : Record < string , unknown > ) {
307
- // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
308
- const moduleKeys = Object . keys ( exports ) . filter ( key => key !== 'default' )
307
+ private wrapCoreSynteticModule ( identifier : string , exports : Record < string , unknown > ) {
308
+ const moduleKeys = Object . keys ( exports )
309
309
const m : any = new SyntheticModule (
310
310
[ ...moduleKeys , 'default' ] ,
311
311
( ) => {
@@ -321,6 +321,52 @@ export class ExternalModulesExecutor {
321
321
return m
322
322
}
323
323
324
+ private interopCommonJsModule ( mod : any ) {
325
+ if ( isPrimitive ( mod ) || Array . isArray ( mod ) || mod instanceof Promise ) {
326
+ return {
327
+ keys : [ ] ,
328
+ moduleExports : { } ,
329
+ defaultExport : mod ,
330
+ }
331
+ }
332
+
333
+ if ( this . options . interopDefault !== false && '__esModule' in mod && ! isPrimitive ( mod . default ) ) {
334
+ return {
335
+ keys : Array . from ( new Set ( Object . keys ( mod . default ) . concat ( Object . keys ( mod ) ) . filter ( key => key !== 'default' ) ) ) ,
336
+ moduleExports : new Proxy ( mod , {
337
+ get ( mod , prop ) {
338
+ return mod [ prop ] ?? mod . default ?. [ prop ]
339
+ } ,
340
+ } ) ,
341
+ defaultExport : mod ,
342
+ }
343
+ }
344
+
345
+ return {
346
+ keys : Object . keys ( mod ) . filter ( key => key !== 'default' ) ,
347
+ moduleExports : mod ,
348
+ defaultExport : mod ,
349
+ }
350
+ }
351
+
352
+ private wrapCommonJsSynteticModule ( identifier : string , exports : Record < string , unknown > ) {
353
+ // TODO: technically module should be parsed to find static exports, implement for strict mode in #2854
354
+ const { keys, moduleExports, defaultExport } = this . interopCommonJsModule ( exports )
355
+ const m : any = new SyntheticModule (
356
+ [ ...keys , 'default' ] ,
357
+ ( ) => {
358
+ for ( const key of keys )
359
+ m . setExport ( key , moduleExports [ key ] )
360
+ m . setExport ( 'default' , defaultExport )
361
+ } ,
362
+ {
363
+ context : this . context ,
364
+ identifier,
365
+ } ,
366
+ )
367
+ return m
368
+ }
369
+
324
370
private async evaluateModule < T extends VMModule > ( m : T ) : Promise < T > {
325
371
if ( m . status === 'unlinked' ) {
326
372
this . esmLinkMap . set (
@@ -582,7 +628,7 @@ c.green(`export default {
582
628
583
629
if ( extension === '.node' || isNodeBuiltin ( identifier ) ) {
584
630
const exports = this . requireCoreModule ( identifier )
585
- return this . wrapSynteticModule ( identifier , exports )
631
+ return this . wrapCoreSynteticModule ( identifier , exports )
586
632
}
587
633
588
634
const isFileUrl = identifier . startsWith ( 'file://' )
@@ -600,7 +646,7 @@ c.green(`export default {
600
646
if ( extension === '.cjs' ) {
601
647
const module = this . createCommonJSNodeModule ( pathUrl )
602
648
const exports = this . loadCommonJSModule ( module , pathUrl )
603
- return this . wrapSynteticModule ( fileUrl , exports )
649
+ return this . wrapCommonJsSynteticModule ( fileUrl , exports )
604
650
}
605
651
606
652
if ( extension === '.mjs' )
@@ -613,7 +659,7 @@ c.green(`export default {
613
659
614
660
const module = this . createCommonJSNodeModule ( pathUrl )
615
661
const exports = this . loadCommonJSModule ( module , pathUrl )
616
- return this . wrapSynteticModule ( fileUrl , exports )
662
+ return this . wrapCommonJsSynteticModule ( fileUrl , exports )
617
663
}
618
664
619
665
async import ( identifier : string ) {
0 commit comments