@@ -6,9 +6,10 @@ import { dirname } from 'node:path'
66import { Module as _Module , createRequire } from 'node:module'
77import { readFileSync , statSync } from 'node:fs'
88import { 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'
1010import { CSS_LANGS_RE , KNOWN_ASSET_RE } from 'vite-node/constants'
1111import { getColors } from '@vitest/utils'
12+ import type { ExecuteOptions } from './execute'
1213
1314// need to copy paste types for vm
1415// because they require latest @types /node which we don't bundle
@@ -95,7 +96,7 @@ const nativeResolve = import.meta.resolve!
9596const dataURIRegex
9697 = / ^ 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 > .* ) $ /
9798
98- interface ExternalModulesExecutorOptions {
99+ export interface ExternalModulesExecutorOptions extends ExecuteOptions {
99100 context : vm . Context
100101 packageCache : Map < string , any >
101102}
@@ -273,7 +274,7 @@ export class ExternalModulesExecutor {
273274 return buffer
274275 }
275276
276- private findNearestPackageData ( basedir : string ) {
277+ private findNearestPackageData ( basedir : string ) : { type ?: 'module' | 'commonjs' } {
277278 const originalBasedir = basedir
278279 const packageCache = this . options . packageCache
279280 while ( basedir ) {
@@ -300,12 +301,11 @@ export class ExternalModulesExecutor {
300301 basedir = nextBasedir
301302 }
302303
303- return null
304+ return { }
304305 }
305306
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 )
309309 const m : any = new SyntheticModule (
310310 [ ...moduleKeys , 'default' ] ,
311311 ( ) => {
@@ -321,6 +321,52 @@ export class ExternalModulesExecutor {
321321 return m
322322 }
323323
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+
324370 private async evaluateModule < T extends VMModule > ( m : T ) : Promise < T > {
325371 if ( m . status === 'unlinked' ) {
326372 this . esmLinkMap . set (
@@ -582,7 +628,7 @@ c.green(`export default {
582628
583629 if ( extension === '.node' || isNodeBuiltin ( identifier ) ) {
584630 const exports = this . requireCoreModule ( identifier )
585- return this . wrapSynteticModule ( identifier , exports )
631+ return this . wrapCoreSynteticModule ( identifier , exports )
586632 }
587633
588634 const isFileUrl = identifier . startsWith ( 'file://' )
@@ -600,7 +646,7 @@ c.green(`export default {
600646 if ( extension === '.cjs' ) {
601647 const module = this . createCommonJSNodeModule ( pathUrl )
602648 const exports = this . loadCommonJSModule ( module , pathUrl )
603- return this . wrapSynteticModule ( fileUrl , exports )
649+ return this . wrapCommonJsSynteticModule ( fileUrl , exports )
604650 }
605651
606652 if ( extension === '.mjs' )
@@ -613,7 +659,7 @@ c.green(`export default {
613659
614660 const module = this . createCommonJSNodeModule ( pathUrl )
615661 const exports = this . loadCommonJSModule ( module , pathUrl )
616- return this . wrapSynteticModule ( fileUrl , exports )
662+ return this . wrapCommonJsSynteticModule ( fileUrl , exports )
617663 }
618664
619665 async import ( identifier : string ) {
0 commit comments