chore(vendor): import pi 0.85.1
Imported as a linear vendor commit so forge rebases do not replay the upstream root tree. git-subtree-dir: third_party/pi git-subtree-split: d981de1229ef899957bbe968bc8dcda02a21f477
This commit is contained in:
416
third_party/pi/packages/chord/src/node/bundle-loader.ts
vendored
Normal file
416
third_party/pi/packages/chord/src/node/bundle-loader.ts
vendored
Normal file
@@ -0,0 +1,416 @@
|
||||
import { createHash } from "node:crypto";
|
||||
import { mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
||||
import { createRequire, isBuiltin } from "node:module";
|
||||
import { tmpdir } from "node:os";
|
||||
import { basename, dirname, isAbsolute, join, resolve } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { compileFunction } from "node:vm";
|
||||
import type { Facet, FacetLoader, LoadedFacets } from "../types.ts";
|
||||
import {
|
||||
FACET_BUNDLE_ARTIFACT_FORMAT,
|
||||
FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,
|
||||
FACET_BUNDLE_FORMAT,
|
||||
FACET_BUNDLE_FORMAT_VERSION,
|
||||
FACET_BUNDLE_MANIFEST_FILE,
|
||||
type FacetBundleArtifact,
|
||||
type FacetBundleEntry,
|
||||
type FacetBundleManifest,
|
||||
} from "./manifest.ts";
|
||||
|
||||
export type FacetBundleExternalResolver = (specifier: string) => string | URL | undefined;
|
||||
|
||||
export interface FacetBundleLoaderOptions {
|
||||
readonly manifestPath: string | URL;
|
||||
readonly entry: string;
|
||||
/** Verify the entry's SHA-256 integrity before evaluating it. Defaults to true. */
|
||||
readonly verifyIntegrity?: boolean;
|
||||
/** Resolve host-provided external imports when the bundle is outside the host's package tree. */
|
||||
readonly resolveExternal?: FacetBundleExternalResolver;
|
||||
}
|
||||
|
||||
export interface FacetBundleArtifactLoaderOptions {
|
||||
readonly artifact: unknown;
|
||||
/** Resolve host-provided external imports against the receiving application. */
|
||||
readonly resolveExternal?: FacetBundleExternalResolver;
|
||||
/** Parent directory for materialized module generations. Defaults to the operating system temp directory. */
|
||||
readonly temporaryDirectory?: string;
|
||||
}
|
||||
|
||||
interface CommonJsModule {
|
||||
exports: unknown;
|
||||
}
|
||||
|
||||
/** Read and validate a versioned facet bundle manifest. */
|
||||
export async function readFacetBundleManifest(path: string | URL): Promise<FacetBundleManifest> {
|
||||
const manifestPath = toFilePath(path);
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(await readFile(manifestPath, "utf8"));
|
||||
} catch (error) {
|
||||
throw new Error(`Could not read facet bundle manifest ${manifestPath}`, { cause: error });
|
||||
}
|
||||
return validateManifest(parsed, manifestPath);
|
||||
}
|
||||
|
||||
/** Read and verify one transportable entry from a facet bundle on disk. */
|
||||
export async function readFacetBundleArtifact(options: {
|
||||
readonly manifestPath: string | URL;
|
||||
readonly entry: string;
|
||||
}): Promise<FacetBundleArtifact> {
|
||||
if (options.entry.length === 0) throw new TypeError("Facet bundle entry name must not be empty");
|
||||
const manifestPath = toFilePath(options.manifestPath);
|
||||
const manifest = await readFacetBundleManifest(manifestPath);
|
||||
const entry = manifest.entries[options.entry];
|
||||
if (entry === undefined) throw new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);
|
||||
const modulePath = resolveBundleFile(manifestPath, entry.file, "entry");
|
||||
const source = await readFile(modulePath, "utf8");
|
||||
verifySource(source, entry);
|
||||
const sourceMapContents =
|
||||
entry.sourceMap === undefined
|
||||
? undefined
|
||||
: await readFile(resolveBundleFile(manifestPath, entry.sourceMap, "source map"), "utf8");
|
||||
return Object.freeze({
|
||||
format: FACET_BUNDLE_ARTIFACT_FORMAT,
|
||||
formatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,
|
||||
plugin: manifest.plugin,
|
||||
entryName: options.entry,
|
||||
entry,
|
||||
source,
|
||||
...(sourceMapContents === undefined ? {} : { sourceMapContents }),
|
||||
});
|
||||
}
|
||||
|
||||
/** Materialize a transported artifact and create a fresh VM-compiled CommonJS generation for each load. */
|
||||
export function createFacetBundleArtifactLoader(options: FacetBundleArtifactLoaderOptions): FacetLoader {
|
||||
const artifact = validateArtifact(options.artifact);
|
||||
const temporaryParent = resolve(options.temporaryDirectory ?? tmpdir());
|
||||
return {
|
||||
async load(): Promise<LoadedFacets> {
|
||||
await mkdir(temporaryParent, { recursive: true });
|
||||
const directory = await mkdtemp(join(temporaryParent, "chord-facet-"));
|
||||
try {
|
||||
await materializeArtifact(directory, artifact);
|
||||
const loaded = await createFacetBundleLoader({
|
||||
manifestPath: join(directory, FACET_BUNDLE_MANIFEST_FILE),
|
||||
entry: artifact.entryName,
|
||||
resolveExternal: options.resolveExternal,
|
||||
}).load();
|
||||
let disposed = false;
|
||||
return {
|
||||
get facets() {
|
||||
return loaded.facets;
|
||||
},
|
||||
async dispose() {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
const errors: unknown[] = [];
|
||||
try {
|
||||
await loaded.dispose();
|
||||
} catch (error) {
|
||||
errors.push(error);
|
||||
}
|
||||
try {
|
||||
await rm(directory, { force: true, recursive: true });
|
||||
} catch (error) {
|
||||
errors.push(error);
|
||||
}
|
||||
if (errors.length === 1) throw errors[0];
|
||||
if (errors.length > 1) throw new AggregateError(errors, "Failed to dispose facet bundle artifact");
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
try {
|
||||
await rm(directory, { force: true, recursive: true });
|
||||
} catch (cleanupError) {
|
||||
throw new AggregateError([error, cleanupError], "Facet bundle artifact loading and cleanup failed");
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
/** Create a reusable loader for one opaque entry in a facet bundle manifest. */
|
||||
export function createFacetBundleLoader(options: FacetBundleLoaderOptions): FacetLoader {
|
||||
if (options.entry.length === 0) throw new TypeError("Facet bundle entry name must not be empty");
|
||||
const manifestPath = toFilePath(options.manifestPath);
|
||||
return {
|
||||
async load(): Promise<LoadedFacets> {
|
||||
const manifest = await readFacetBundleManifest(manifestPath);
|
||||
const entry = manifest.entries[options.entry];
|
||||
if (entry === undefined) {
|
||||
throw new Error(`Facet bundle ${manifest.plugin.id} has no entry named ${options.entry}`);
|
||||
}
|
||||
const modulePath = resolveBundleFile(manifestPath, entry.file, "entry");
|
||||
try {
|
||||
const source = await readFile(modulePath, "utf8");
|
||||
if (options.verifyIntegrity !== false) verifySource(source, entry);
|
||||
const exported = executeCommonJsModule(source, modulePath, entry.externalImports, options.resolveExternal);
|
||||
let facets = facetsFromModule(exported, manifest.plugin.id, options.entry);
|
||||
let disposed = false;
|
||||
return {
|
||||
get facets() {
|
||||
return facets;
|
||||
},
|
||||
async dispose() {
|
||||
if (disposed) return;
|
||||
disposed = true;
|
||||
facets = Object.freeze([]);
|
||||
},
|
||||
};
|
||||
} catch (error) {
|
||||
const detail = error instanceof Error ? `: ${error.message}` : "";
|
||||
throw new Error(`Could not load facet bundle entry ${manifest.plugin.id}/${options.entry}${detail}`, {
|
||||
cause: error,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function executeCommonJsModule(
|
||||
source: string,
|
||||
modulePath: string,
|
||||
externalImports: readonly string[],
|
||||
resolver?: FacetBundleExternalResolver,
|
||||
): unknown {
|
||||
const requireFromModule = createRequire(modulePath);
|
||||
const externalTargets = new Map<string, string>();
|
||||
for (const specifier of externalImports) {
|
||||
if (!isBuiltin(specifier)) validatePackageSpecifier(specifier);
|
||||
externalTargets.set(specifier, toRequireSpecifier(resolveExternalTarget(specifier, resolver)));
|
||||
}
|
||||
const targetFor = (specifier: string): string => {
|
||||
const target = externalTargets.get(specifier);
|
||||
if (target === undefined) throw new Error(`Facet bundle required undeclared external import: ${specifier}`);
|
||||
return target;
|
||||
};
|
||||
const requireExternal = Object.assign((specifier: string): unknown => requireFromModule(targetFor(specifier)), {
|
||||
resolve: (specifier: string): string => requireFromModule.resolve(targetFor(specifier)),
|
||||
});
|
||||
const commonJsModule: CommonJsModule = { exports: Object.create(null) };
|
||||
const compiled = compileFunction(source, ["exports", "require", "module", "__filename", "__dirname"], {
|
||||
filename: modulePath,
|
||||
});
|
||||
Reflect.apply(compiled, commonJsModule.exports, [
|
||||
commonJsModule.exports,
|
||||
requireExternal,
|
||||
commonJsModule,
|
||||
modulePath,
|
||||
dirname(modulePath),
|
||||
]);
|
||||
return commonJsModule.exports;
|
||||
}
|
||||
|
||||
function toRequireSpecifier(target: string): string {
|
||||
if (isAbsolute(target) || isBuiltin(target)) return target;
|
||||
let url: URL;
|
||||
try {
|
||||
url = new URL(target);
|
||||
} catch {
|
||||
return target;
|
||||
}
|
||||
if (url.protocol === "file:") return fileURLToPath(url);
|
||||
if (url.protocol === "node:") return url.href;
|
||||
throw new Error(`Facet bundle external target must be a file, package, or built-in module: ${target}`);
|
||||
}
|
||||
|
||||
function toFilePath(path: string | URL): string {
|
||||
if (typeof path === "string") return resolve(path);
|
||||
if (path.protocol !== "file:") throw new TypeError(`Facet bundle manifest must be a file URL, not ${path.protocol}`);
|
||||
return fileURLToPath(path);
|
||||
}
|
||||
|
||||
function resolveBundleFile(manifestPath: string, file: string, label: string): string {
|
||||
if (file.length === 0 || isAbsolute(file) || basename(file) !== file || file === "." || file === "..") {
|
||||
throw new Error(`Facet bundle ${label} must be a filename relative to its manifest`);
|
||||
}
|
||||
return resolve(dirname(manifestPath), file);
|
||||
}
|
||||
|
||||
function verifySource(source: string, entry: FacetBundleEntry): void {
|
||||
const expected = parseIntegrity(entry.integrity);
|
||||
const actual = createHash("sha256").update(source, "utf8").digest("base64");
|
||||
if (actual !== expected) throw new Error(`Facet bundle integrity check failed for ${entry.file}`);
|
||||
}
|
||||
|
||||
function parseIntegrity(integrity: string): string {
|
||||
const prefix = "sha256-";
|
||||
if (!integrity.startsWith(prefix) || integrity.length === prefix.length) {
|
||||
throw new Error("Facet bundle entry has an invalid SHA-256 integrity value");
|
||||
}
|
||||
return integrity.slice(prefix.length);
|
||||
}
|
||||
|
||||
function facetsFromModule(imported: unknown, pluginId: string, entryName: string): readonly Facet[] {
|
||||
if (!isRecord(imported)) throw new Error(`Facet bundle entry ${pluginId}/${entryName} did not export a module`);
|
||||
const exported = imported.default;
|
||||
const candidates: readonly unknown[] = Array.isArray(exported) ? (exported as readonly unknown[]) : [exported];
|
||||
if (candidates.length === 0) {
|
||||
throw new Error(`Facet bundle entry ${pluginId}/${entryName} exported no facets`);
|
||||
}
|
||||
const facets: Facet[] = [];
|
||||
for (const candidate of candidates) {
|
||||
if (!isRecord(candidate) || typeof candidate.id !== "string" || candidate.id.length === 0) {
|
||||
throw new Error(`Facet bundle entry ${pluginId}/${entryName} has a facet with an invalid ID`);
|
||||
}
|
||||
if (typeof candidate.setup !== "function") {
|
||||
throw new Error(`Facet bundle entry ${pluginId}/${entryName} facet ${candidate.id} has no setup function`);
|
||||
}
|
||||
facets.push(candidate as unknown as Facet);
|
||||
}
|
||||
const ids = facets.map(({ id }) => id);
|
||||
if (new Set(ids).size !== ids.length) {
|
||||
throw new Error(`Facet bundle entry ${pluginId}/${entryName} exports duplicate facet IDs`);
|
||||
}
|
||||
return Object.freeze(facets);
|
||||
}
|
||||
|
||||
function validateArtifact(value: unknown): FacetBundleArtifact {
|
||||
if (
|
||||
!isRecord(value) ||
|
||||
value.format !== FACET_BUNDLE_ARTIFACT_FORMAT ||
|
||||
value.formatVersion !== FACET_BUNDLE_ARTIFACT_FORMAT_VERSION ||
|
||||
typeof value.entryName !== "string" ||
|
||||
value.entryName.length === 0 ||
|
||||
typeof value.source !== "string"
|
||||
) {
|
||||
throw new Error("Invalid facet bundle artifact");
|
||||
}
|
||||
const manifest = validateManifest(
|
||||
{
|
||||
format: FACET_BUNDLE_FORMAT,
|
||||
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
||||
plugin: value.plugin,
|
||||
entries: { [value.entryName]: value.entry },
|
||||
},
|
||||
"facet bundle artifact",
|
||||
);
|
||||
const entry = manifest.entries[value.entryName]!;
|
||||
if (entry.sourceMap === undefined) {
|
||||
if (value.sourceMapContents !== undefined) {
|
||||
throw new Error("Facet bundle artifact has source map contents without a source map");
|
||||
}
|
||||
} else if (typeof value.sourceMapContents !== "string") {
|
||||
throw new Error("Facet bundle artifact is missing its source map contents");
|
||||
}
|
||||
verifySource(value.source, entry);
|
||||
return Object.freeze({
|
||||
format: FACET_BUNDLE_ARTIFACT_FORMAT,
|
||||
formatVersion: FACET_BUNDLE_ARTIFACT_FORMAT_VERSION,
|
||||
plugin: manifest.plugin,
|
||||
entryName: value.entryName,
|
||||
entry,
|
||||
source: value.source,
|
||||
...(value.sourceMapContents === undefined ? {} : { sourceMapContents: value.sourceMapContents }),
|
||||
});
|
||||
}
|
||||
|
||||
async function materializeArtifact(directory: string, artifact: FacetBundleArtifact): Promise<void> {
|
||||
const manifest: FacetBundleManifest = {
|
||||
format: FACET_BUNDLE_FORMAT,
|
||||
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
||||
plugin: artifact.plugin,
|
||||
entries: { [artifact.entryName]: artifact.entry },
|
||||
};
|
||||
await Promise.all([
|
||||
writeFile(join(directory, artifact.entry.file), artifact.source, "utf8"),
|
||||
writeFile(join(directory, FACET_BUNDLE_MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`, "utf8"),
|
||||
...(artifact.entry.sourceMap === undefined
|
||||
? []
|
||||
: [writeFile(join(directory, artifact.entry.sourceMap), artifact.sourceMapContents!, "utf8")]),
|
||||
]);
|
||||
}
|
||||
|
||||
function resolveExternalTarget(specifier: string, resolver?: FacetBundleExternalResolver): string {
|
||||
const resolved = resolver?.(specifier);
|
||||
if (resolved !== undefined) return typeof resolved === "string" ? resolved : resolved.href;
|
||||
const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
||||
if (specifier === "@earendil-works/chord") return new URL(`../index.${extension}`, import.meta.url).href;
|
||||
if (specifier === "@earendil-works/chord/context") {
|
||||
return new URL(`../context/index.${extension}`, import.meta.url).href;
|
||||
}
|
||||
if (specifier === "@earendil-works/chord/node") return new URL(`../node.${extension}`, import.meta.url).href;
|
||||
return import.meta.resolve(specifier);
|
||||
}
|
||||
|
||||
function validatePackageSpecifier(specifier: string): void {
|
||||
const segments = specifier.split("/");
|
||||
const packageParts = specifier.startsWith("@") ? 2 : 1;
|
||||
if (
|
||||
specifier.startsWith(".") ||
|
||||
specifier.startsWith("/") ||
|
||||
specifier.startsWith("#") ||
|
||||
specifier.includes(":") ||
|
||||
specifier.includes("\\") ||
|
||||
segments.length < packageParts ||
|
||||
segments.some((part) => part.length === 0 || part === "." || part === "..")
|
||||
) {
|
||||
throw new Error(`Facet bundle artifact has an unsupported external import: ${specifier}`);
|
||||
}
|
||||
}
|
||||
|
||||
function validateManifest(value: unknown, path: string): FacetBundleManifest {
|
||||
if (!isRecord(value) || value.format !== FACET_BUNDLE_FORMAT) {
|
||||
throw new Error(`Invalid facet bundle manifest format in ${path}`);
|
||||
}
|
||||
if (value.formatVersion !== FACET_BUNDLE_FORMAT_VERSION) {
|
||||
throw new Error(`Unsupported facet bundle manifest version in ${path}: ${String(value.formatVersion)}`);
|
||||
}
|
||||
if (!isRecord(value.plugin) || typeof value.plugin.id !== "string" || value.plugin.id.length === 0) {
|
||||
throw new Error(`Facet bundle manifest has an invalid plugin identity in ${path}`);
|
||||
}
|
||||
if (
|
||||
value.plugin.version !== undefined &&
|
||||
(typeof value.plugin.version !== "string" || value.plugin.version.length === 0)
|
||||
) {
|
||||
throw new Error(`Facet bundle manifest has an invalid plugin version in ${path}`);
|
||||
}
|
||||
if (!isRecord(value.entries) || Object.keys(value.entries).length === 0) {
|
||||
throw new Error(`Facet bundle manifest has no entries in ${path}`);
|
||||
}
|
||||
const entries: Record<string, FacetBundleEntry> = {};
|
||||
for (const [name, candidate] of Object.entries(value.entries)) {
|
||||
if (name.length === 0 || !isRecord(candidate)) {
|
||||
throw new Error(`Facet bundle manifest has an invalid entry in ${path}`);
|
||||
}
|
||||
if (typeof candidate.file !== "string") throw new Error(`Facet bundle entry ${name} has no file`);
|
||||
resolveBundleFile(path, candidate.file, `entry ${name}`);
|
||||
if (typeof candidate.integrity !== "string") throw new Error(`Facet bundle entry ${name} has no integrity`);
|
||||
parseIntegrity(candidate.integrity);
|
||||
if (
|
||||
!Array.isArray(candidate.externalImports) ||
|
||||
candidate.externalImports.some((item) => typeof item !== "string")
|
||||
) {
|
||||
throw new Error(`Facet bundle entry ${name} has invalid external imports`);
|
||||
}
|
||||
const externalImports = Object.freeze([...(candidate.externalImports as readonly string[])]);
|
||||
if (new Set(externalImports).size !== externalImports.length) {
|
||||
throw new Error(`Facet bundle entry ${name} has duplicate external imports`);
|
||||
}
|
||||
if (candidate.sourceMap !== undefined) {
|
||||
if (typeof candidate.sourceMap !== "string")
|
||||
throw new Error(`Facet bundle entry ${name} has an invalid source map`);
|
||||
resolveBundleFile(path, candidate.sourceMap, `entry ${name} source map`);
|
||||
}
|
||||
entries[name] = Object.freeze({
|
||||
file: candidate.file,
|
||||
integrity: candidate.integrity,
|
||||
externalImports,
|
||||
...(candidate.sourceMap === undefined ? {} : { sourceMap: candidate.sourceMap }),
|
||||
});
|
||||
}
|
||||
return Object.freeze({
|
||||
format: FACET_BUNDLE_FORMAT,
|
||||
formatVersion: FACET_BUNDLE_FORMAT_VERSION,
|
||||
plugin: Object.freeze({
|
||||
id: value.plugin.id,
|
||||
...(value.plugin.version === undefined ? {} : { version: value.plugin.version }),
|
||||
}),
|
||||
entries: Object.freeze(entries),
|
||||
});
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null && !Array.isArray(value);
|
||||
}
|
||||
Reference in New Issue
Block a user