( filename: string, code: string, format: 'module' | 'commonjs', exports: string[] = [], )
| 31 | const cachedFileExports = new Map<string, string[]>() |
| 32 | |
| 33 | export function collectModuleExports( |
| 34 | filename: string, |
| 35 | code: string, |
| 36 | format: 'module' | 'commonjs', |
| 37 | exports: string[] = [], |
| 38 | ): string[] { |
| 39 | if (format === 'module') { |
| 40 | const [imports_, exports_] = parseModuleSyntax(code, filename) |
| 41 | const fileExports = [...exports_.map(p => p.n)] |
| 42 | imports_.forEach(({ ss: start, se: end, n: name }) => { |
| 43 | const substring = code.substring(start, end).replace(/ +/g, ' ') |
| 44 | if (name && substring.startsWith('export *') && !substring.startsWith('export * as')) { |
| 45 | fileExports.push(...tryParseModule(name)) |
| 46 | } |
| 47 | }) |
| 48 | cachedFileExports.set(filename, fileExports) |
| 49 | exports.push(...fileExports) |
| 50 | } |
| 51 | else { |
| 52 | const { exports: exports_, reexports } = parseCjsSyntax(code, filename) |
| 53 | const fileExports = [...exports_] |
| 54 | reexports.forEach((name) => { |
| 55 | fileExports.push(...tryParseModule(name)) |
| 56 | }) |
| 57 | cachedFileExports.set(filename, fileExports) |
| 58 | exports.push(...fileExports) |
| 59 | } |
| 60 | |
| 61 | function tryParseModule(name: string): string[] { |
| 62 | try { |
| 63 | return parseModule(name) |
| 64 | } |
| 65 | catch (error) { |
| 66 | console.warn(`[module mocking] Failed to parse '${name}' imported from ${filename}:`, error) |
| 67 | return [] |
| 68 | } |
| 69 | } |
| 70 | |
| 71 | let __require: NodeJS.Require | undefined |
| 72 | function getModuleRequire() { |
| 73 | return (__require ??= createRequire(filename)) |
| 74 | } |
| 75 | |
| 76 | function parseModule(name: string): string[] { |
| 77 | if (isBuiltin(name)) { |
| 78 | if (cachedFileExports.has(name)) { |
| 79 | const cachedExports = cachedFileExports.get(name)! |
| 80 | return cachedExports |
| 81 | } |
| 82 | |
| 83 | const builtinModule = getBuiltinModule(name) |
| 84 | const builtinExports = Object.keys(builtinModule) |
| 85 | cachedFileExports.set(name, builtinExports) |
| 86 | return builtinExports |
| 87 | } |
| 88 | |
| 89 | const resolvedModuleUrl = format === 'module' |
| 90 | ? import.meta.resolve(name, pathToFileURL(filename).toString()) |
no test coverage detected