UNPKG

storybook

Version:

Storybook: Develop, document, and test UI components in isolation

225 lines (219 loc) • 8.21 kB
import CJS_COMPAT_NODE_URL_ret6ivvuly from 'node:url'; import CJS_COMPAT_NODE_PATH_ret6ivvuly from 'node:path'; import CJS_COMPAT_NODE_MODULE_ret6ivvuly from "node:module"; var __filename = CJS_COMPAT_NODE_URL_ret6ivvuly.fileURLToPath(import.meta.url); var __dirname = CJS_COMPAT_NODE_PATH_ret6ivvuly.dirname(__filename); var require = CJS_COMPAT_NODE_MODULE_ret6ivvuly.createRequire(import.meta.url); // ------------------------------------------------------------ // end of CJS compatibility banner, injected by Storybook's esbuild configuration // ------------------------------------------------------------ import { OxcParseError, oxcParse } from "../_node-chunks/chunk-FFFNDE22.js"; import "../_node-chunks/chunk-3LVSS6GN.js"; import "../_node-chunks/chunk-XSYEGQMM.js"; import "../_node-chunks/chunk-BV5YQP4B.js"; import "../_node-chunks/chunk-5IHDTMLC.js"; // src/oxc-parser/index.ts import { parse as oxcRawParse } from "oxc-parser"; // src/oxc-parser/worker-pool.ts import { existsSync } from "node:fs"; import { cpus } from "node:os"; import { fileURLToPath } from "node:url"; import { Worker } from "node:worker_threads"; import { logger } from "storybook/internal/node-logger"; var WORKER_RELATIVE_PATH = "../oxc-parser/worker.js", DEFAULT_TASK_TIMEOUT_MS = 3e4; function resolveWorkerScriptPath() { if (typeof import.meta.url != "string") return; let path = fileURLToPath(new URL(WORKER_RELATIVE_PATH, import.meta.url)); return existsSync(path) ? path : void 0; } function computePoolSize() { let cpuCount = cpus().length; return Math.max(1, Math.min(4, cpuCount - 1)); } var OxcWorkerPool = class { constructor(scriptPath, size, taskTimeoutMs = DEFAULT_TASK_TIMEOUT_MS) { this.workers = []; this.queue = []; this.pending = /* @__PURE__ */ new Map(); this.nextId = 0; this.disposed = !1; this.taskTimeoutMs = taskTimeoutMs; try { for (let i = 0; i < size; i++) { let worker = new Worker(scriptPath), slot = { worker, busy: !1 }; worker.on("message", (msg) => this.handleMessage(slot, msg)), worker.on("error", (error) => this.handleWorkerFailure(error)), worker.on("exit", (code) => { this.disposed || this.handleWorkerFailure(new Error(`oxc-worker exited unexpectedly with code ${code}`)); }), worker.unref(), this.workers.push(slot); } } catch (err) { for (let slot of this.workers) slot.worker.terminate().catch(() => 0); throw this.workers.length = 0, err; } } parse(filePath, source) { return this.disposed ? Promise.reject(new OxcParseError("oxc parse pool disposed")) : new Promise((resolve, reject) => { this.queue.push({ filePath, source, resolve, reject }), this.drain(); }); } drain() { for (; this.queue.length > 0; ) { let slot = this.workers.find((s) => !s.busy); if (!slot) return; let task = this.queue.shift(), id = this.nextId++; slot.busy = !0; let pending = { resolve: task.resolve, reject: task.reject }; this.taskTimeoutMs > 0 && (pending.timer = setTimeout(() => { this.handleWorkerFailure( new Error(`oxc-worker task ${id} timed out after ${this.taskTimeoutMs}ms`) ); }, this.taskTimeoutMs), pending.timer.unref?.()), this.pending.set(id, pending), slot.worker.postMessage({ id, filePath: task.filePath, source: task.source }); } } handleMessage(slot, msg) { let entry = this.pending.get(msg.id); if (entry) { if (entry.timer && clearTimeout(entry.timer), this.pending.delete(msg.id), slot.busy = !1, msg.ok && msg.edges) entry.resolve(msg.edges); else { let err = new OxcParseError(msg.message ?? "oxc-worker error"); msg.name && (err.name = msg.name), entry.reject(err); } this.drain(); } } /** * On any worker failure: reject all in-flight and queued tasks, dispose the pool so * subsequent parse() calls fail fast and the caller in index.ts falls back to inline * oxcParse. Nulls out the module-level pool reference so getOxcParsePool() returns null. */ handleWorkerFailure(error) { if (!this.disposed) { logger.debug(`oxc-worker failure: ${error.message}`), this.disposed = !0; for (let [, entry] of this.pending) entry.timer && clearTimeout(entry.timer), entry.reject(new OxcParseError(`oxc-worker failure: ${error.message}`, { cause: error })); this.pending.clear(); for (let queued of this.queue) queued.reject(new OxcParseError("oxc parse pool disposed")); this.queue.length = 0; for (let slot of this.workers) slot.worker.terminate().catch(() => 0); this.workers.length = 0, sharedPool = null; } } async dispose() { if (this.disposed) return; this.disposed = !0; for (let [, entry] of this.pending) entry.timer && clearTimeout(entry.timer), entry.reject(new OxcParseError("oxc parse pool disposed")); this.pending.clear(); for (let queued of this.queue) queued.reject(new OxcParseError("oxc parse pool disposed")); this.queue.length = 0; let terminations = this.workers.map((s) => s.worker.terminate().catch(() => 0)); this.workers.length = 0, await Promise.all(terminations); } }, sharedPool = null; function ensurePool() { if (sharedPool) return; let scriptPath = resolveWorkerScriptPath(); if (!scriptPath) { logger.debug( "oxc worker pool disabled: compiled worker script not found (running from source?)" ); return; } try { sharedPool = new OxcWorkerPool(scriptPath, computePoolSize()); } catch (error) { logger.debug( `oxc worker pool disabled: failed to spawn (${error instanceof Error ? error.message : String(error)})` ), sharedPool = null; } } function getOxcParsePool() { return ensurePool(), sharedPool; } async function disposeOxcParsePool() { let pool = sharedPool; sharedPool = null, pool && await pool.dispose().catch(() => { }); } // src/oxc-parser/index.ts async function parseWithOxc(filePath, source) { let pool = getOxcParsePool(); if (!pool) return oxcParse(filePath, source); try { return await pool.parse(filePath, source); } catch { return oxcParse(filePath, source); } } async function parseBarrelInfo(filePath, source) { let parseResult; try { parseResult = await oxcRawParse(filePath, source); } catch { return { named: /* @__PURE__ */ new Map(), wildcards: [] }; } let moduleInfo = parseResult.module; if (!moduleInfo) return { named: /* @__PURE__ */ new Map(), wildcards: [] }; let named = /* @__PURE__ */ new Map(), wildcards = []; for (let staticExport of moduleInfo.staticExports) for (let entry of staticExport.entries) { if (!entry.moduleRequest) continue; let specifier = entry.moduleRequest.value; if (entry.exportName.kind === "None") { wildcards.push(specifier); continue; } let exportedName = entry.exportName.name; exportedName && (entry.importName.kind !== "Name" || !entry.importName.name || named.set(exportedName, { specifier, importedName: entry.importName.name })); } return { named, wildcards }; } async function parseReExports(filePath, source) { let parseResult; try { parseResult = await oxcRawParse(filePath, source); } catch { return /* @__PURE__ */ new Map(); } let moduleInfo = parseResult.module; if (!moduleInfo) return /* @__PURE__ */ new Map(); let map = /* @__PURE__ */ new Map(); for (let staticExport of moduleInfo.staticExports) for (let entry of staticExport.entries) { if (entry.isType || !entry.moduleRequest || entry.exportName.kind === "None") continue; let exportedName = entry.exportName.name; if (!exportedName) continue; let specifier = entry.moduleRequest.value; if (entry.importName.kind !== "Name" || !entry.importName.name) continue; let importedName = entry.importName.name; map.set(exportedName, { specifier, importedName }); } return map; } export { disposeOxcParsePool, parseBarrelInfo, parseReExports, parseWithOxc };