@@ -67,28 +67,75 @@ export function isNodeAlsModule(path: string) {
6767 return / ^ ( n o d e : ) ? a s y n c _ h o o k s $ / . test ( path ) ;
6868}
6969
70+ /**
71+ * Map of module identifiers to
72+ * - `injectedName`: the name injected on `globalThis`
73+ * - `exportName`: the export name from the module
74+ * - `importName`: the imported name
75+ */
76+ const injectsByModule = new Map <
77+ string ,
78+ { injectedName : string ; exportName : string ; importName : string } [ ]
79+ > ( ) ;
80+ /**
81+ * Map of virtual module (prefixed by `virtualModulePrefix`) to injectable module id,
82+ * which then maps via `injectsByModule` to the global code to be injected.
83+ */
84+ const virtualModulePathToSpecifier = new Map < string , string > ( ) ;
85+ const virtualModulePrefix = `\0_nodejs_global_inject-` ;
86+
87+ for ( const [ injectedName , moduleSpecifier ] of Object . entries ( env . inject ) ) {
88+ const [ module , exportName , importName ] = Array . isArray ( moduleSpecifier )
89+ ? [ moduleSpecifier [ 0 ] , moduleSpecifier [ 1 ] , moduleSpecifier [ 1 ] ]
90+ : [ moduleSpecifier , "default" , "defaultExport" ] ;
91+
92+ if ( ! injectsByModule . has ( module ) ) {
93+ injectsByModule . set ( module , [ ] ) ;
94+ virtualModulePathToSpecifier . set (
95+ virtualModulePrefix + module . replaceAll ( "/" , "-" ) ,
96+ module
97+ ) ;
98+ }
99+ const injects = injectsByModule . get ( module ) ;
100+ assert ( injects , `expected injects for ${ module } to be defined` ) ;
101+ injects . push ( { injectedName, exportName, importName } ) ;
102+ }
103+
104+ /**
105+ * Does the given module id resolve to a virtual module corresponding to a global injection module?
106+ */
107+ export function isGlobalVirtualModule ( modulePath : string ) {
108+ return virtualModulePathToSpecifier . has ( modulePath ) ;
109+ }
110+
111+ /**
112+ * Get the contents of the virtual module corresponding to a global injection module.
113+ */
114+ export function getGlobalVirtualModule ( modulePath : string ) {
115+ const module = virtualModulePathToSpecifier . get ( modulePath ) ;
116+ if ( ! module ) {
117+ return undefined ;
118+ }
119+ const injects = injectsByModule . get ( module ) ;
120+ assert ( injects , `expected injects for ${ module } to be defined` ) ;
121+
122+ const imports = injects . map ( ( { exportName, importName } ) =>
123+ importName === exportName ? exportName : `${ exportName } as ${ importName } `
124+ ) ;
125+
126+ return (
127+ `import { ${ imports . join ( ", " ) } } from "${ module } ";\n` +
128+ `${ injects . map ( ( { injectedName, importName } ) => `globalThis.${ injectedName } = ${ importName } ;` ) . join ( "\n" ) } `
129+ ) ;
130+ }
131+
70132/**
71133 * Gets the necessary global polyfills to inject into the entry-point of the user's code.
72134 */
73135export function injectGlobalCode ( id : string , code : string ) {
74- const injectedCode = Object . entries ( env . inject )
75- . map ( ( [ globalName , globalInject ] ) => {
76- if ( typeof globalInject === "string" ) {
77- const moduleSpecifier = globalInject ;
78- // the mapping is a simple string, indicating a default export, so the string is just the module specifier.
79- return `import var_${ globalName } from "${ moduleSpecifier } ";\nglobalThis.${ globalName } = var_${ globalName } ;\n` ;
80- }
81-
82- // the mapping is a 2 item tuple, indicating a named export, made up of a module specifier and an export name.
83- const [ moduleSpecifier , exportName ] = globalInject ;
84- assert (
85- moduleSpecifier !== undefined ,
86- "Expected moduleSpecifier to be defined"
87- ) ;
88- assert ( exportName !== undefined , "Expected exportName to be defined" ) ;
89- return `import var_${ globalName } from "${ moduleSpecifier } ";\nglobalThis.${ globalName } = var_${ globalName } .${ exportName } ;\n` ;
90- } )
91- . join ( "\n" ) ;
136+ const injectedCode = Array . from ( virtualModulePathToSpecifier . keys ( ) )
137+ . map ( ( moduleId ) => `import "${ moduleId } ";\n` )
138+ . join ( "" ) ;
92139
93140 // Some globals are not injected using the approach above but are added to globalThis via side-effect imports of polyfills from the unenv-preset.
94141 const polyfillCode = env . polyfill
0 commit comments