UNPKG

@babel/register

Version:
343 lines (333 loc) 8.62 kB
import { ACTIONS } from '../types-shared.js'; import { loadPartialConfigAsync, loadOptionsAsync, transformAsync, version, getEnv, DEFAULT_EXTENSIONS } from '@babel/core'; import cloneDeep from 'clone-deep'; import path, { isAbsolute, resolve, dirname, join } from 'node:path'; import fs, { constants, accessSync, existsSync, mkdirSync } from 'node:fs'; import crypto from 'node:crypto'; import os from 'node:os'; import { env } from 'node:process'; import 'node:module'; import 'node:url'; import cacache from 'cacache'; import { unzipSync, gzipSync } from 'node:zlib'; import { parentPort } from 'node:worker_threads'; function ok(path, mode) { try { accessSync(path, mode); return true; } catch { return false; } } function writable(path) { return ok(path, constants.W_OK); } function absolute(input, root) { return isAbsolute(input) ? input : resolve(root || ".", input); } function up$2(base, options) { let { last, cwd } = options || {}; let tmp = absolute(base, cwd); let root = absolute(last || "/", cwd); let prev, arr = []; while (prev !== root) { arr.push(tmp); tmp = dirname(prev = tmp); if (tmp === prev) break; } return arr; } function up$1(name, options) { let dir, tmp; let start = options && options.cwd || ""; for (dir of up$2(start, options)) { tmp = join(dir, name); if (existsSync(tmp)) return tmp; } } function up(options) { return up$1("package.json", options); } function cache$1(name, options) { options = options || {}; let dir = env.CACHE_DIR; if (!dir || /^(1|0|true|false)$/.test(dir)) { let pkg = up(options); if (dir = pkg && dirname(pkg)) { let mods = join(dir, "node_modules"); let exists = existsSync(mods); if (!writable(exists ? mods : dir)) return; dir = join(mods, ".cache"); } } if (dir) { dir = join(dir, name); if (options.create && !existsSync(dir)) { mkdirSync(dir, { recursive: true }); } return dir; } } let globalDisableCache = false; class Cache { enabled = false; cacheDir = process.env.BABEL_CACHE_PATH || cache$1("@babel/register") || path.join(os.tmpdir() || os.homedir(), `.babel-register`); batched = []; batchedSize = 0; cache = new Map(); index = new Map(); constructor() { globalDisableCache = !!process.env.BABEL_DISABLE_CACHE; if (fs.existsSync(this.cacheDir)) { if (fs.statSync(this.cacheDir).isFile()) { console.warn(`Cache directory ${this.cacheDir} is a file, not a directory.`); globalDisableCache = true; } return; } try { fs.mkdirSync(this.cacheDir, { recursive: true }); } catch (_) { console.warn(`Failed to create cache directory ${this.cacheDir}`); globalDisableCache = true; return; } try { fs.accessSync(this.cacheDir, fs.constants.W_OK | fs.constants.R_OK); } catch (_) { console.warn(`Cache directory ${this.cacheDir} is not writable or readable.`); globalDisableCache = true; } } async enable() { if (globalDisableCache) return; this.enabled = true; const entries = await cacache.ls(this.cacheDir); for (const [key, cache] of Object.entries(entries)) { const now = Date.now(); if (now - cache.time > 1000 * 60 * 60 * 24) { await cacache.rm.content(this.cacheDir, cache.integrity); await cacache.rm.entry(this.cacheDir, key); continue; } key.split("|").forEach(k => { this.index.set(k, cache.integrity); }); } } async get(key) { if (!this.enabled) return; if (this.cache.has(key)) { return this.cache.get(key); } const integrity = this.index.get(key); if (!integrity) return; try { let cache = await cacache.get.byDigest(this.cacheDir, integrity, { memoize: false }); cache = unzipSync(cache); const items = JSON.parse(cache.toString("utf8")); for (const item of items) { this.cache.set(item.key, item.data); } return this.cache.get(key); } catch (error) { if (error.code !== "ENOENT") { throw error; } } } async disable() { await this.flush(); this.enabled = false; } async set(key, data) { if (!this.enabled) return; this.cache.set(key, data); this.batched.push({ key, data }); this.batchedSize += JSON.stringify(data).length; if (this.batchedSize >= 1024 * 1024) { await this.flush(); } } async flush() { if (!this.enabled) return; const key = this.batched.map(item => item.key).join("|"); const buf = Buffer.from(JSON.stringify(this.batched)); await cacache.put(this.cacheDir, key, gzipSync(buf), { algorithms: ["sha1"] }); this.batched = []; this.batchedSize = 0; } } const cache = new Cache(); const nmRE = escapeRegExp(path.sep + "node_modules" + path.sep); function escapeRegExp(string) { return string.replace(/[|\\{}()[\]^$+*?.]/g, "\\$&"); } const id = value => value; async function cacheLookup(opts, filename) { if (!cache.enabled) { return { cached: null, store: id }; } let cacheKey = `${JSON.stringify(opts)}:${version}`; const env = getEnv(); if (env) cacheKey += `:${env}`; cacheKey = crypto.createHash("sha1").update(cacheKey).digest("hex"); const cached = await cache.get(cacheKey); const fileMtime = +fs.statSync(filename).mtime; if (cached?.mtime === fileMtime) { return { cached: cached.value, store: id }; } return { cached: null, async store(value) { await cache.set(cacheKey, { value, mtime: fileMtime }); return value; } }; } let transformOpts; async function setOptions(opts) { if (opts.cache === false && cache.enabled) { await cache.disable(); } else if (opts.cache !== false && !cache.enabled) { await cache.enable(); } delete opts.cache; delete opts.extensions; transformOpts = { ...opts, caller: { name: "@babel/register", supportsStaticESM: false, supportsDynamicImport: false, supportsExportNamespaceFrom: false, ...(opts.caller || {}) } }; let { cwd = "." } = transformOpts; cwd = transformOpts.cwd = path.resolve(cwd); if (transformOpts.ignore === undefined && transformOpts.only === undefined) { const cwdRE = escapeRegExp(cwd); transformOpts.only = [new RegExp("^" + cwdRE, "i")]; transformOpts.ignore = [new RegExp(`^${cwdRE}(?:${path.sep}.*)?${nmRE}`, "i")]; } } async function transform(input, filename) { const opts = await loadOptionsAsync({ sourceRoot: path.dirname(filename) + path.sep, ...cloneDeep(transformOpts), filename }); if (opts === null) { return null; } const { cached, store } = await cacheLookup(opts, filename); if (cached) return cached; const { code, map } = await transformAsync(input, { ...opts, sourceMaps: opts.sourceMaps === undefined ? "both" : opts.sourceMaps, ast: false }); return await store({ code, map }); } async function isFileIgnored(filename) { const opts = await loadPartialConfigAsync({ ...cloneDeep(transformOpts), filename, showIgnoredFiles: true, babelrc: false, configFile: false, browserslistConfigFile: false, plugins: [], presets: [], targets: { browsers: undefined } }); return opts === null; } function disableCache() { return cache.disable(); } function handleMessage(action, payload) { switch (action) { case ACTIONS.GET_DEFAULT_EXTENSIONS: return DEFAULT_EXTENSIONS; case ACTIONS.SET_OPTIONS: return setOptions(payload); case ACTIONS.TRANSFORM: return transform(payload.code, payload.filename); case ACTIONS.IS_FILE_IGNORED: return isFileIgnored(payload); case ACTIONS.CLOSE: return disableCache(); } throw new Error(`Unknown internal parser worker action: ${action}`); } parentPort.addListener("message", async ({ signal, port, action, payload }) => { let response; try { response = { result: await handleMessage(action, payload) }; } catch (error) { response = { error, errorData: { ...error } }; } try { port.postMessage(response); } catch { port.postMessage({ error: new Error("Cannot serialize worker response") }); } finally { port.close(); Atomics.store(signal, 0, 1); Atomics.notify(signal, 0); } }); //# sourceMappingURL=index.js.map