/** * Host-resolved Bare / companion npm modules for in-image scripts (`ctx.bare`), * plus optional merge from trusted IIFE bundles on the system drive. */ import b4a from 'b4a' import { readFileSync } from '#host-fs' import { dirname, join } from '#host-path' import { fileURLToPath } from 'url' import bareModuleManifestEmbedded from './bare-module-manifest.data.mjs' import { bareOsHostBooterWarn } from './bare-os-host-booter-log.js' /** * Used only by {@link tryLoadBareCtxKeyFromDriveBundlePath}: some Bare booters lack * `TextDecoder`. Dynamic `import('b4a')` fails on Pear (no referrer); static import is fine. * @param {Uint8Array} buf */ function decodeUtf8BytesBareFallback(buf) { if (typeof TextDecoder !== 'undefined') { try { return new TextDecoder().decode(buf) } catch { /* ignore */ } } return b4a.toString(buf, 'utf8') } /** * `fileURLToPath` only accepts `file:` URLs. Pear uses `pear://dev/...` for `import.meta.url`, * so we must not call it at load time or when running under `pear run`. * @returns {string | null} */ function bareOsBooterPackageJsonPathForCreateRequire() { const href = String(import.meta.url) if (!href.startsWith('file:')) return null try { return fileURLToPath(new URL('../package.json', import.meta.url)) } catch { return null } } /** * Drive IIFEs call `require("events")`, `require("bare-stream")`, …; `new Function` has no * lexical `require`, so they look at **`globalThis.require`**. Bundled code also calls * **`__require.addon()`** (native bindings); that only works when `globalThis.require` is from * **`bare-module`'s `createRequire`** (exposes **`require.addon`**). A bare function or Node-only * `require` breaks eval with **`__require.addon is not a function`**. * * Order: if existing `require` already has **`addon`**, use it; else install **`createRequire`** * from the booter **`file:`** package.json when available; else **`createRequire(import.meta.url)`** * (covers **`pear://`** on Bare). If **`addon`** is still missing (e.g. Node dev), attach a stub * for the duration of eval only. * * @param {() => void | Promise} fn */ async function tryBareModuleCreateRequire(parentURL) { try { const bm = await import('bare-module') const createRequire = bm.createRequire || bm.default?.createRequire if (typeof createRequire !== 'function') return null return createRequire(parentURL) } catch { return null } } /** * Pear `import('pkg')` can fail when the current referrer is a `pear://` booter URL. * Try loading via bare-module's createRequire from the booter package root first, * then fall back to `createRequire(import.meta.url)`. * * @param {string} specifier * @returns {Promise} */ export async function tryRequireFromBooter(specifier) { if (typeof specifier !== 'string' || !specifier.trim()) return undefined const liveRequire = globalThis.require if (typeof liveRequire === 'function') { try { return liveRequire(specifier) } catch { /* continue */ } } const pkgJson = bareOsBooterPackageJsonPathForCreateRequire() if (pkgJson) { try { const urlMod = await import('url') const href = urlMod.pathToFileURL(pkgJson).href const req = await tryBareModuleCreateRequire(href) if (typeof req === 'function') return req(specifier) } catch { /* continue */ } } try { const req = await tryBareModuleCreateRequire(import.meta.url) if (typeof req === 'function') return req(specifier) } catch { /* continue */ } return undefined } /** @returns {import('bare-module').Require['addon']} */ function driveBundleRequireAddonStub() { const stub = function bareOsDriveBundleAddon() { return new Proxy( {}, { get() { return function bareOsDriveBundleAddonExport() { return {} } } } ) } stub.resolve = function bareOsDriveBundleAddonResolve() { return '' } stub.host = '' return stub } /** * Install a temporary `require` wrapper for drive-bundle eval so we control both * module resolution and the `require.addon` surface seen by esbuild IIFEs. * * @param {Function} delegate * @param {Function} addon */ function createDriveBundleRequireWrapper(delegate, addon) { const wrapped = function bareOsDriveBundleRequire(...args) { return Reflect.apply(delegate, this, args) } for (const key of ['resolve', 'cache', 'extensions', 'main']) { try { const v = delegate[key] if (v !== undefined) wrapped[key] = v } catch { /* ignore */ } } wrapped.addon = addon return wrapped } async function withDriveBundleGlobalRequire(fn) { const origRequire = globalThis.require /** @type {Function | null} */ let delegate = typeof origRequire === 'function' ? /** @type {Function} */ (origRequire) : null if (!delegate) { const pkgJson = bareOsBooterPackageJsonPathForCreateRequire() if (pkgJson) { try { const urlMod = await import('url') const href = urlMod.pathToFileURL(pkgJson).href const req = await tryBareModuleCreateRequire(href) if (typeof req === 'function') delegate = req } catch { /* continue */ } } } if (!delegate) { const req = await tryBareModuleCreateRequire(import.meta.url) if (typeof req === 'function') delegate = req } if (typeof delegate === 'function') { /** @type {Function | null} */ let addon = typeof delegate.addon === 'function' ? /** @type {Function} */ (delegate.addon) : null if (!addon) { const addonReq = await tryBareModuleCreateRequire(import.meta.url) if (addonReq && typeof addonReq.addon === 'function') addon = addonReq.addon } if (!addon) addon = driveBundleRequireAddonStub() globalThis.require = createDriveBundleRequireWrapper(delegate, addon) } try { return await fn() } finally { if (origRequire === undefined) delete globalThis.require else globalThis.require = origRequire } } export const BARE_OS_STDLIB_GLOBAL = '__bare_os_stdlib__' const MANIFEST_NAME = 'bare-module-manifest.json' /** * @param {unknown} m * @returns {typeof bareModuleManifestEmbedded} */ function cloneBareModuleManifest(m) { return /** @type {typeof bareModuleManifestEmbedded} */ ( JSON.parse(JSON.stringify(m)) ) } /** @type {{ version: number, entries: Array<{ ctxKey: string, package: string, export?: string, bundle?: boolean, optional?: boolean, tier?: string }> } | null} */ let _cachedManifest = null /** * Embedded copy of **`bare-module-manifest.json`** for Pear (`pear://` **import.meta.url**). * `bare-fs` coerces **`URL`** arguments through **`bare-url.fileURLToPath`**, which rejects * non-`file:` schemes, so **`readFileSync(new URL('pear:…'))`** cannot load the JSON from the * bundle. Static import of **`bare-module-manifest.data.mjs`** (regenerated by * **`npm run sync:bare-manifest`**) keeps the manifest in the Pear module graph. * * On **`file:`** trees, the JSON on disk is preferred so edits apply without regenerating `.data.mjs`. */ export function loadBareModuleManifest() { if (_cachedManifest) return _cachedManifest const href = String(import.meta.url) if (href.startsWith('pear:')) { _cachedManifest = cloneBareModuleManifest(bareModuleManifestEmbedded) return _cachedManifest } if (href.startsWith('file:')) { try { const libDir = dirname(fileURLToPath(href)) const raw = readFileSync(join(libDir, MANIFEST_NAME), 'utf8') _cachedManifest = JSON.parse(raw) } catch { _cachedManifest = cloneBareModuleManifest(bareModuleManifestEmbedded) } return _cachedManifest } _cachedManifest = cloneBareModuleManifest(bareModuleManifestEmbedded) return _cachedManifest } /** Exported for tests: default export object from **`bare-module-manifest.data.mjs`**. */ export function bareOsBareModuleManifestEmbeddedRef() { return bareModuleManifestEmbedded } /** * @param {Record} shellEnv */ export function bareOsBareModulesEnabled(shellEnv) { if (!shellEnv || typeof shellEnv !== 'object') return true const v = shellEnv.BARE_OS_BARE_MODULES return v !== '0' && v !== 'false' } /** * @param {Record} shellEnv */ export function bareOsBareDriveBundlesEnabled(shellEnv) { if (!shellEnv || typeof shellEnv !== 'object') return true const v = shellEnv.BARE_OS_BARE_DRIVE_BUNDLES if (v === '0' || v === 'false') return false return bareOsBareModulesEnabled(shellEnv) } /** * When false, skip host `import(pkg)` for ctx.bare (use only `/lib/bare` IIFEs). * Set **`BARE_OS_BARE_HOST_IMPORTS=0`** for a fully image-local stdlib. */ export function bareOsBareHostImportsEnabled(shellEnv) { if (!shellEnv || typeof shellEnv !== 'object') return true const v = shellEnv.BARE_OS_BARE_HOST_IMPORTS if (v === '0' || v === 'false') return false return true } /** * Populate object with host `import()` results (per manifest). Mutates `target`. * @param {Record} shellEnv * @param {Record} target */ function bareHostRuntime() { if (typeof globalThis.Bare !== 'undefined') return true const v = globalThis.process?.versions return Boolean(v && typeof v.bare === 'string') } export async function buildBareCtxObjectFromHost(shellEnv, target) { if (!bareOsBareModulesEnabled(shellEnv)) return if (!bareOsBareHostImportsEnabled(shellEnv)) return const pearBooter = typeof import.meta !== 'undefined' && String(import.meta.url || '').startsWith('pear:') const { entries } = loadBareModuleManifest() const skipHostKeys = new Set( String(shellEnv?.BARE_OS_BARE_HOST_SKIP_CTX_KEYS || '') .split(/[\s,]+/) .map((s) => s.trim()) .filter(Boolean) ) const onlyHostKeysRaw = String( shellEnv?.BARE_OS_BARE_HOST_ONLY_CTX_KEYS || '' ) .split(/[\s,]+/) .map((s) => s.trim()) .filter(Boolean) const onlyHostKeys = onlyHostKeysRaw.length > 0 ? new Set(onlyHostKeysRaw) : null const onBare = bareHostRuntime() const tasks = entries.map(async (ent) => { if (!onBare && ent.nativeHint === true) return null const key = ent.ctxKey if (!key || target[key] !== undefined) return null if (skipHostKeys.has(key)) return null if (onlyHostKeys && !onlyHostKeys.has(key)) return null // Pear (`pear:` import.meta.url): bare-module cannot resolve `import("holesail")` from // this booter URL (MODULE_NOT_FOUND / no referrer). Drive IIFEs supply bundle:true keys. if (pearBooter && ent.bundle === true) return null try { const mod = await import(/* webpackIgnore: true */ ent.package) const val = ent.sideEffectImport ? mod?.default !== undefined ? mod.default : true : ent.export === '*' ? mod : mod?.default !== undefined ? mod.default : mod return { key, ent, val } } catch (err) { return { key, ent, err } } }) const settled = await Promise.all(tasks) for (const r of settled) { if (!r) continue const { key, ent, val, err } = r if (err) { if (!ent.optional) { bareOsHostBooterWarn( 'ctx_bare_module_load_failed', `ctx.bare.${key}: failed to load "${ent.package}"`, err?.message || String(err) ) } continue } if (val !== undefined) target[key] = val } } /** * Execute trusted bundle sources that assign `globalThis.__bare_os_stdlib__[ctxKey]`. * Fills missing keys on `target` only. * @param {Record} shellEnv * @param {{ readFile: (p: string, opts?: unknown) => Promise }} vfs * @param {Record} target */ /** * Optional `/lib/bare/bare-module-lock.json` on the system image: `{ "pins": { "ctxKey": "semver" } }`. * Emits warnings for pins whose `ctxKey` is still missing after drive merge + host import. * @param {{ readFile: (p: string) => Promise }} vfs * @param {Record} target * @returns {Promise} */ export async function verifyBareModuleLockfile(vfs, target) { /** @type {string[]} */ const warnings = [] if (!vfs || typeof vfs.readFile !== 'function') return warnings let buf try { buf = await vfs.readFile('/lib/bare/bare-module-lock.json') } catch { return warnings } if (!buf || !buf.byteLength) return warnings let j try { j = JSON.parse(new TextDecoder().decode(buf)) } catch { warnings.push('bare-module-lock.json: invalid JSON') return warnings } const pins = j && typeof j === 'object' ? j.pins : null if (!pins || typeof pins !== 'object') return warnings for (const [k, ver] of Object.entries(pins)) { if (target[k] === undefined) { warnings.push( `bare-module-lock: ctx.bare.${k} missing (pinned ${String(ver)})` ) } } return warnings } /** * esbuild IIFE assigns `__bare_os_bundle_exports__` (CJS interop object), not the * default export itself. Entries use `export default ` → `{ default: binding }`. * @param {unknown} val */ function unwrapDriveBundleExport(val) { if (val === null || val === undefined) return val if (typeof val !== 'object') return val if (Object.prototype.hasOwnProperty.call(val, 'default')) { const d = /** @type {{ default?: unknown }} */ (val).default if (d !== undefined) return d } return val } /** * Eval a single `/lib/bare/bundles/*.js` IIFE (same as {@link maybeMergeBareFromDrive}) and * return one `ctxKey` from `globalThis.__bare_os_stdlib__`. Does not mutate `ctx.bare`. * Used when Pear skipped populating a key (merge short-circuit or eval failure). * * @param {Record} ctx * @param {{ readFile: (p: string) => Promise }} vfs * @param {string} logicalPath * @param {string} ctxKey * @returns {Promise} */ export async function tryLoadBareCtxKeyFromDriveBundlePath( ctx, vfs, logicalPath, ctxKey ) { void ctx if (!vfs || typeof vfs.readFile !== 'function') return undefined if ( typeof logicalPath !== 'string' || !logicalPath.startsWith('/lib/bare/') || typeof ctxKey !== 'string' || !ctxKey ) { return undefined } let buf try { buf = await vfs.readFile(logicalPath) } catch { return undefined } if (!buf || !buf.byteLength) return undefined const text = decodeUtf8BytesBareFallback(buf) if (text.length > 12 * 1024 * 1024) return undefined const g = globalThis const sym = BARE_OS_STDLIB_GLOBAL /** @type {string | null} */ let errMsg = null await withDriveBundleGlobalRequire(async () => { g[sym] = g[sym] && typeof g[sym] === 'object' ? g[sym] : {} try { const run = new Function( `"use strict"; var require = globalThis.require;\n${text}\n//# sourceURL=bare-drive-bundle:${logicalPath}` ) run() } catch (err) { errMsg = (err && /** @type {{ message?: string }} */ (err).message) || String(err) } }) if (errMsg) { bareOsHostBooterWarn( 'drive_bundle_eval_failed', `tryLoadBareCtxKeyFromDriveBundlePath ${logicalPath}`, errMsg ) return undefined } const snap = g[sym] if (!snap || typeof snap !== 'object') return undefined if (!Object.prototype.hasOwnProperty.call(snap, ctxKey)) return undefined return unwrapDriveBundleExport(snap[ctxKey]) } export async function maybeMergeBareFromDrive(shellEnv, vfs, target) { if (!bareOsBareModulesEnabled(shellEnv)) return if (!bareOsBareDriveBundlesEnabled(shellEnv)) return if (!vfs || typeof vfs.readFile !== 'function') return const perfBareStdlib = shellEnv?.BARE_OS_BOOT_PERF_DETAIL === '1' || shellEnv?.BARE_OS_BOOT_PERF_DETAIL === 'true' const hrtBig = typeof globalThis.process?.hrtime?.bigint === 'function' ? () => globalThis.process.hrtime.bigint() : null const t0 = perfBareStdlib && hrtBig ? hrtBig() : null let metaBuf try { metaBuf = await vfs.readFile('/lib/bare/manifest.json') } catch { metaBuf = null } if (!metaBuf || metaBuf.byteLength === 0) return let meta try { const text = new TextDecoder().decode(metaBuf) meta = JSON.parse(text) } catch { return } const bundles = meta?.bundles if (!Array.isArray(bundles)) return const g = globalThis const sym = BARE_OS_STDLIB_GLOBAL g[sym] = g[sym] && typeof g[sym] === 'object' ? g[sym] : {} const concRaw = String( shellEnv?.BARE_OS_BARE_STDLIB_RESOLVE_CONCURRENCY ?? '' ).trim() const concParsed = Number.parseInt(concRaw, 10) const readConc = Number.isFinite(concParsed) && concParsed >= 1 ? Math.min(concParsed, 32) : 4 await withDriveBundleGlobalRequire(async () => { /** @type {{ path: string, keys: string[] }[]} */ const work = [] /** @type {Set} */ const seenPaths = new Set() let allKeysSatisfied = true for (const b of bundles) { const path = typeof b?.path === 'string' ? b.path : '' const keys = Array.isArray(b?.keys) ? b.keys : [] if (!path.startsWith('/lib/bare/')) continue if (seenPaths.has(path)) continue seenPaths.add(path) for (const k of keys) { if (typeof k === 'string' && k && target[k] === undefined) { allKeysSatisfied = false } } work.push({ path, keys }) } if (work.length > 0 && allKeysSatisfied) { await tryBareFetchImportWhenDriveMissing(target) return } /** @type {{ path: string, keys: string[], source: string | null }[]} */ const prepared = [] for (let i = 0; i < work.length; ) { const slice = work.slice(i, i + readConc) i += slice.length const chunk = await Promise.all( slice.map(async ({ path, keys }) => { let srcBuf try { srcBuf = await vfs.readFile(path) } catch { srcBuf = null } if (!srcBuf || srcBuf.byteLength === 0) { return { path, keys, source: null } } const source = new TextDecoder().decode(srcBuf) if (source.length > 12 * 1024 * 1024) { return { path, keys, source: null } } return { path, keys, source } }) ) prepared.push(...chunk) } for (const { path, keys, source } of prepared) { if (!source) continue try { const run = new Function( `"use strict"; var require = globalThis.require;\n${source}\n//# sourceURL=bare-drive-bundle:${path}` ) run() } catch (err) { bareOsHostBooterWarn( 'drive_bundle_eval_failed', `drive bundle failed ${path}`, err?.message || String(err) ) continue } const snap = g[sym] if (!snap || typeof snap !== 'object') continue for (const k of keys) { if (typeof k !== 'string' || !k) continue if (target[k] !== undefined) continue if (Object.prototype.hasOwnProperty.call(snap, k)) { target[k] = unwrapDriveBundleExport(snap[k]) } } } }) await tryBareFetchImportWhenDriveMissing(target) if (t0 && hrtBig) { const ns = Number(hrtBig() - t0) bareOsHostBooterWarn( 'bare_stdlib_merge_ns', 'maybeMergeBareFromDrive wall (hrtime bigint delta ns)', String(ns) ) } } /** * When drive `fetch.js` eval fails (no `globalThis.require` or native addons), Bare can still * `import('bare-fetch')` from the booter — same as `buildBareCtxObjectFromHost`, but runs even * when the manifest marks the entry host-only. * @param {Record} target */ async function tryBareFetchImportWhenDriveMissing(target) { if (target.fetch !== undefined) return if (!bareHostRuntime()) return try { let mod if (typeof import.meta.resolve === 'function') { try { mod = await import(import.meta.resolve('bare-fetch')) } catch { mod = await import('bare-fetch') } } else { mod = await import('bare-fetch') } const f = mod?.default if (typeof f === 'function') target.fetch = f } catch { /* optional */ } }