import { createRequire } from 'node:module'; import { dirname } from 'node:path'; import { pathToFileURL, fileURLToPath } from 'node:url'; import vm from 'node:vm'; import { isNodeBuiltin } from 'mlly'; import { resolve } from 'pathe'; import createDebug from 'debug'; import { normalizeModuleId, slash, isInternalRequest, VALID_ID_PREFIX, normalizeRequestId, toFilePath, cleanUrl, isPrimitive } from './utils.mjs'; import { extractSourceMap } from './source-map.mjs'; import 'node:fs'; import 'source-map-support'; const debugExecute = createDebug("vite-node:client:execute"); const debugNative = createDebug("vite-node:client:native"); const clientStub = { injectQuery: (id) => id, createHotContext() { return { accept: () => { }, prune: () => { }, dispose: () => { }, decline: () => { }, invalidate: () => { }, on: () => { } }; }, updateStyle(id, css) { if (typeof document === "undefined") return; const element = document.getElementById(id); if (element) element.remove(); const head = document.querySelector("head"); const style = document.createElement("style"); style.setAttribute("type", "text/css"); style.id = id; style.innerHTML = css; head == null ? void 0 : head.appendChild(style); } }; const DEFAULT_REQUEST_STUBS = { "/@vite/client": clientStub, "@vite/client": clientStub }; class ModuleCacheMap extends Map { normalizePath(fsPath) { return normalizeModuleId(fsPath); } update(fsPath, mod) { fsPath = this.normalizePath(fsPath); if (!super.has(fsPath)) super.set(fsPath, mod); else Object.assign(super.get(fsPath), mod); return this; } setByModuleId(modulePath, mod) { return super.set(modulePath, mod); } set(fsPath, mod) { return this.setByModuleId(this.normalizePath(fsPath), mod); } getByModuleId(modulePath) { if (!super.has(modulePath)) super.set(modulePath, {}); return super.get(modulePath); } get(fsPath) { return this.getByModuleId(this.normalizePath(fsPath)); } deleteByModuleId(modulePath) { return super.delete(modulePath); } delete(fsPath) { return this.deleteByModuleId(this.normalizePath(fsPath)); } invalidateDepTree(ids, invalidated = /* @__PURE__ */ new Set()) { for (const _id of ids) { const id = this.normalizePath(_id); if (invalidated.has(id)) continue; invalidated.add(id); const mod = super.get(id); if (mod == null ? void 0 : mod.importers) this.invalidateDepTree(mod.importers, invalidated); super.delete(id); } return invalidated; } invalidateSubDepTree(ids, invalidated = /* @__PURE__ */ new Set()) { for (const _id of ids) { const id = this.normalizePath(_id); if (invalidated.has(id)) continue; invalidated.add(id); const subIds = Array.from(super.entries()).filter(([, mod]) => { var _a; return (_a = mod.importers) == null ? void 0 : _a.has(id); }).map(([key]) => key); subIds.length && this.invalidateSubDepTree(subIds, invalidated); super.delete(id); } return invalidated; } getSourceMap(id) { const cache = this.get(id); if (cache.map) return cache.map; const map = cache.code && extractSourceMap(cache.code); if (map) { cache.map = map; return map; } return null; } } class ViteNodeRunner { constructor(options) { this.options = options; this.root = options.root ?? process.cwd(); this.moduleCache = options.moduleCache ?? new ModuleCacheMap(); this.debug = options.debug ?? (typeof process !== "undefined" ? !!process.env.VITE_NODE_DEBUG_RUNNER : false); } async executeFile(file) { const url = `/@fs/${slash(resolve(file))}`; return await this.cachedRequest(url, url, []); } async executeId(rawId) { const [id, url] = await this.resolveUrl(rawId); return await this.cachedRequest(id, url, []); } getSourceMap(id) { return this.moduleCache.getSourceMap(id); } async cachedRequest(id, fsPath, callstack) { const importee = callstack[callstack.length - 1]; const mod = this.moduleCache.get(fsPath); if (!mod.importers) mod.importers = /* @__PURE__ */ new Set(); if (importee) mod.importers.add(importee); if (callstack.includes(fsPath) && mod.exports) return mod.exports; if (mod.promise) return mod.promise; const promise = this.directRequest(id, fsPath, callstack); Object.assign(mod, { promise, evaluated: false }); try { return await promise; } finally { mod.evaluated = true; } } shouldResolveId(id, _importee) { return !isInternalRequest(id) && !isNodeBuiltin(id); } async _resolveUrl(id, importee) { if (!this.shouldResolveId(id)) return [id, id]; if (importee && id.startsWith(VALID_ID_PREFIX)) importee = void 0; id = normalizeRequestId(id, this.options.base); if (!this.options.resolveId) return [id, toFilePath(id, this.root)]; const resolved = await this.options.resolveId(id, importee); const resolvedId = resolved ? normalizeRequestId(resolved.id, this.options.base) : id; const fsPath = resolved ? resolvedId : toFilePath(id, this.root); return [resolvedId, fsPath]; } async resolveUrl(id, importee) { const resolveKey = `resolve:${id}`; this.moduleCache.setByModuleId(resolveKey, { resolving: true }); try { return await this._resolveUrl(id, importee); } finally { this.moduleCache.deleteByModuleId(resolveKey); } } async dependencyRequest(id, fsPath, callstack) { var _a; const getStack = () => { return `stack: ${[...callstack, fsPath].reverse().map((p) => `- ${p}`).join("\n")}`; }; let debugTimer; if (this.debug) debugTimer = setTimeout(() => console.warn(() => `module ${fsPath} takes over 2s to load. ${getStack()}`), 2e3); try { if (callstack.includes(fsPath)) { const depExports = (_a = this.moduleCache.get(fsPath)) == null ? void 0 : _a.exports; if (depExports) return depExports; throw new Error(`[vite-node] Failed to resolve circular dependency, ${getStack()}`); } return await this.cachedRequest(id, fsPath, callstack); } finally { if (debugTimer) clearTimeout(debugTimer); } } async directRequest(id, fsPath, _callstack) { const moduleId = normalizeModuleId(fsPath); const callstack = [..._callstack, moduleId]; const mod = this.moduleCache.getByModuleId(moduleId); const request = async (dep) => { const [id2, depFsPath] = await this.resolveUrl(dep, fsPath); return this.dependencyRequest(id2, depFsPath, callstack); }; const requestStubs = this.options.requestStubs || DEFAULT_REQUEST_STUBS; if (id in requestStubs) return requestStubs[id]; let { code: transformed, externalize } = await this.options.fetchModule(id); if (externalize) { debugNative(externalize); const exports2 = await this.interopedImport(externalize); mod.exports = exports2; return exports2; } if (transformed == null) throw new Error(`[vite-node] Failed to load "${id}" imported from ${callstack[callstack.length - 2]}`); const modulePath = cleanUrl(moduleId); const href = pathToFileURL(modulePath).href; const meta = { url: href }; const exports = /* @__PURE__ */ Object.create(null); Object.defineProperty(exports, Symbol.toStringTag, { value: "Module", enumerable: false, configurable: false }); const cjsExports = new Proxy(exports, { set: (_, p, value) => { if (p === "default" && this.shouldInterop(modulePath, { default: value })) { exportAll(cjsExports, value); exports.default = value; return true; } if (!Reflect.has(exports, "default")) exports.default = {}; if (isPrimitive(exports.default)) { defineExport(exports, p, () => void 0); return true; } exports.default[p] = value; if (p !== "default") defineExport(exports, p, () => value); return true; } }); Object.assign(mod, { code: transformed, exports }); const __filename = fileURLToPath(href); const moduleProxy = { set exports(value) { exportAll(cjsExports, value); exports.default = value; }, get exports() { return cjsExports; } }; let hotContext; if (this.options.createHotContext) { Object.defineProperty(meta, "hot", { enumerable: true, get: () => { var _a, _b; hotContext || (hotContext = (_b = (_a = this.options).createHotContext) == null ? void 0 : _b.call(_a, this, `/@fs/${fsPath}`)); return hotContext; }, set: (value) => { hotContext = value; } }); } const context = this.prepareContext({ __vite_ssr_import__: request, __vite_ssr_dynamic_import__: request, __vite_ssr_exports__: exports, __vite_ssr_exportAll__: (obj) => exportAll(exports, obj), __vite_ssr_import_meta__: meta, require: createRequire(href), exports: cjsExports, module: moduleProxy, __filename, __dirname: dirname(__filename) }); debugExecute(__filename); if (transformed[0] === "#") transformed = transformed.replace(/^\#\!.*/, (s) => " ".repeat(s.length)); const codeDefinition = `'use strict';async (${Object.keys(context).join(",")})=>{{`; const code = `${codeDefinition}${transformed} }}`; const fn = vm.runInThisContext(code, { filename: __filename, lineOffset: 0, columnOffset: -codeDefinition.length }); await fn(...Object.values(context)); return exports; } prepareContext(context) { return context; } shouldInterop(path, mod) { if (this.options.interopDefault === false) return false; return !path.endsWith(".mjs") && "default" in mod; } async interopedImport(path) { const importedModule = await import(path); if (!this.shouldInterop(path, importedModule)) return importedModule; const { mod, defaultExport } = interopModule(importedModule); const modKeys = Reflect.ownKeys(mod); let defaultKeys = !isPrimitive(defaultExport) ? Reflect.ownKeys(defaultExport) : []; if (typeof mod !== "function" && typeof defaultExport === "function") { const reservedKeys = ["arguments", "caller", "prototype", "name", "length"]; defaultKeys = defaultKeys.filter((n) => typeof n === "string" && !reservedKeys.includes(n)); } return new Proxy(mod, { get(mod2, prop) { if (prop === "default") return defaultExport; return mod2[prop] ?? (defaultExport == null ? void 0 : defaultExport[prop]); }, has(mod2, prop) { if (prop === "default") return defaultExport !== void 0; return prop in mod2 || defaultExport && prop in defaultExport; }, ownKeys() { if (!defaultExport || isPrimitive(defaultExport)) return modKeys; const allKeys = [...modKeys, "default", ...defaultKeys]; return Array.from(new Set(allKeys)); }, getOwnPropertyDescriptor(mod2, prop) { const descriptor = Reflect.getOwnPropertyDescriptor(mod2, prop); if (descriptor) return descriptor; if (prop === "default" && defaultExport !== void 0) { return { value: defaultExport, enumerable: true, configurable: true }; } } }); } } function interopModule(mod) { if (isPrimitive(mod)) { return { mod: { default: mod }, defaultExport: mod }; } let defaultExport = "default" in mod ? mod.default : mod; if (!isPrimitive(defaultExport) && "__esModule" in defaultExport) { mod = defaultExport; if ("default" in defaultExport) defaultExport = defaultExport.default; } return { mod, defaultExport }; } function defineExport(exports, key, value) { Object.defineProperty(exports, key, { enumerable: true, configurable: true, get: value }); } function exportAll(exports, sourceModule) { if (exports === sourceModule) return; if (isPrimitive(sourceModule) || Array.isArray(sourceModule)) return; for (const key in sourceModule) { if (key !== "default") { try { defineExport(exports, key, () => sourceModule[key]); } catch (_err) { } } } } export { DEFAULT_REQUEST_STUBS, ModuleCacheMap, ViteNodeRunner };