Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@endo/compartment-mapper

Package Overview
Dependencies
Maintainers
5
Versions
58
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@endo/compartment-mapper - npm Package Compare versions

Comparing version 1.1.5 to 1.2.0

archive-lite.d.ts

37

package.json
{
"name": "@endo/compartment-mapper",
"version": "1.1.5",
"version": "1.2.0",
"description": "The compartment mapper assembles Node applications in a sandbox",

@@ -31,6 +31,14 @@ "keywords": [

"./import.js": "./import.js",
"./import-lite.js": "./import-lite.js",
"./import-parsers.js": "./import-parsers.js",
"./archive.js": "./archive.js",
"./archive-lite.js": "./archive-lite.js",
"./archive-parsers.js": "./archive-parsers.js",
"./capture-lite.js": "./capture-lite.js",
"./import-archive.js": "./import-archive.js",
"./import-archive-lite.js": "./import-archive-lite.js",
"./import-archive-parsers.js": "./import-archive-parsers.js",
"./bundle.js": "./bundle.js",
"./node-powers.js": "./node-powers.js",
"./node-modules.js": "./node-modules.js",
"./package.json": "./package.json"

@@ -40,4 +48,4 @@ },

"build": "exit 0",
"build:types": "tsc --build tsconfig.build.json",
"clean:types": "git clean -f '*.d.ts*'",
"prepack": "tsc --build tsconfig.build.json",
"postpack": "git clean -f '*.d.ts*'",
"cover": "c8 ava",

@@ -52,10 +60,10 @@ "lint": "yarn lint:types && yarn lint:eslint",

"dependencies": {
"@endo/cjs-module-analyzer": "^1.0.5",
"@endo/static-module-record": "^1.1.2",
"@endo/zip": "^1.0.5",
"ses": "^1.5.0"
"@endo/cjs-module-analyzer": "^1.0.6",
"@endo/module-source": "^1.0.0",
"@endo/zip": "^1.0.6",
"ses": "^1.6.0"
},
"devDependencies": {
"ava": "^6.1.2",
"babel-eslint": "^10.0.3",
"ava": "^6.1.3",
"babel-eslint": "^10.1.0",
"c8": "^7.14.0",

@@ -65,6 +73,6 @@ "eslint": "^8.57.0",

"eslint-config-prettier": "^9.1.0",
"eslint-plugin-eslint-comments": "^3.1.2",
"eslint-plugin-import": "^2.29.0",
"eslint-plugin-eslint-comments": "^3.2.0",
"eslint-plugin-import": "^2.29.1",
"prettier": "^3.2.5",
"typescript": "~5.5.0-dev.20240327"
"typescript": "5.5.2"
},

@@ -100,3 +108,4 @@ "files": [

"files": [
"test/**/test-*.js"
"test/**/test-*.*",
"test/**/*.test.*"
],

@@ -108,3 +117,3 @@ "timeout": "2m"

},
"gitHead": "08e59bc0d262565165636c2e3875bbe3dcb91cf8"
"gitHead": "681b813ccb1fa177905dabf2ed3f5f248cb33ce7"
}

@@ -167,24 +167,12 @@ # Compartment mapper

The `exports` property describes [package entry points] and can be influenced
by build _tags_.
Currently, the only tag supported by the compartment mapper is `import`, which
indicates that the module map should use ESM modules over CommonJS modules or
other variants.
The `exports` property describes [package entry points][] and can be influenced
by build _conditions_.
Currently, the only conditions supported by the compartment mapper are
`import`, `browser`, and `endo`.
The `imports` condition indicates that the module map should use ESM modules
over CommonJS modules or other variants, and `endo`.
The `browser` condition also draws in the `browser` property from
`package.json` instead of `main`.
The `endo` condition only indicates that this tool is in use.
> TODO
>
> A future version may reveal other tags like `browser` to prepare an
> application for use in a web client.
> For this case, the compartment mapper would prepare a JSON manifest like an
> `importmap` (if not precisely an `importmap`).
> The "compartment map" would be consistent except when the dependency graph
> changes so updates could be automated with a `postinstall` script.
> Preparing a web application for production would follow a process similar to
> creating an archive, but with the `browser` build tag.
The `browser` and `require` tags are well-known but not yet supported.
The `browser` tag will apply for compartment maps generated for use on the web.
The `require` tag is a fallback for environments that do not support ESM and
will never apply.
If no `exports` apply to the root of the compartment namespace (`"."`),

@@ -288,3 +276,3 @@ the `main` property serves as a default.

> During development, the compartment mapper would be able to load the
> translator in the client, with the `browser` tag.
> translator in the client, with the `browser` condition.
> The compartment mapper would also be able to run the translator in a separate

@@ -397,3 +385,3 @@ > non-browser compartment during bundling, so the translator can be excluded

type CompartmentMap = {
tags: Tags,
tags: Conditions,
entry: Entry,

@@ -404,8 +392,9 @@ compartments: Record<CompartmentName, Compartment>,

// Tags are the build tags for the compartment.
// Conditions influence which modules are selected
// to represent the implementation of various modules.
// These may include terms like "browser", meaning
// each compartment uses the implementation of each
// module suitable for use in a browser environment.
type Tags = Array<Tag>;
type Tag = string;
type Conditions = Array<Condition>;
type Condition = string;

@@ -492,3 +481,3 @@ // Entry is a reference to the module that is the module to initially import.

// ParserMap indicates which parser to use to construct static module records
// ParserMap indicates which parser to use to construct module sources
// from sources, for each supported file extension.

@@ -508,3 +497,3 @@ // For parity with Node.js, a package with `"type": "module"` in its

// Parser is a union of built-in parsers for static module records.
// Parser is a union of built-in parsers for module sources.
// "mjs" corresponds to ECMAScript modules.

@@ -511,0 +500,0 @@ // "cjs" corresponds to CommonJS modules.

@@ -1,5 +0,1 @@

export function makeArchiveCompartmentMap(compartmentMap: CompartmentMapDescriptor, sources: Sources): {
archiveCompartmentMap: CompartmentMapDescriptor;
archiveSources: Sources;
};
export function makeAndHashArchive(powers: ReadFn | ReadPowers, moduleLocation: string, options?: ArchiveOptions | undefined): Promise<{

@@ -13,4 +9,2 @@ bytes: Uint8Array;

export function writeArchive(write: WriteFn, readPowers: ReadFn | ReadPowers, archiveLocation: string, moduleLocation: string, options?: ArchiveOptions | undefined): Promise<void>;
import type { CompartmentMapDescriptor } from './types.js';
import type { Sources } from './types.js';
import type { ReadFn } from './types.js';

@@ -17,0 +11,0 @@ import type { ReadPowers } from './types.js';

@@ -0,402 +1,66 @@

/* Provides mechanisms for creating archives (zip files with a
* `compartmeent-map.json` and a file for every static dependency of an entry
* module).
*
* Uses the conventions of Node.js package managers and the `node_modules`.
* Archives will contain a copy for every physical copy of a package on disk,
* such that importing will construct a separate instance for each.
*
* These archives will contain pre-compiled ESM and CJS and this module
* entrains a dependency on the core of Babel.
*
* See `archive-lite.js` for a variation that does not depend on Babel
* for cases like XS native Compartments where pre-compilation is not
* necessary or where the dependency on Babel can be dererred to runtime.
*/
// @ts-check
/* eslint no-shadow: 0 */
import { defaultParserForLanguage } from './archive-parsers.js';
import { mapNodeModules } from './node-modules.js';
import {
makeAndHashArchiveFromMap,
makeArchiveFromMap,
mapFromMap,
hashFromMap,
writeArchiveFromMap,
} from './archive-lite.js';
const { assign, create, freeze } = Object;
/** @import {ArchiveOptions} from './types.js' */
/** @import {ArchiveWriter} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {CompartmentMapDescriptor} from './types.js' */
/** @import {ModuleDescriptor} from './types.js' */
/** @import {ParserImplementation} from './types.js' */
/** @import {ReadFn} from './types.js' */
/** @import {CaptureSourceLocationHook} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {HashPowers} from './types.js' */
/** @import {Sources} from './types.js' */
/** @import {WriteFn} from './types.js' */
import { writeZip } from '@endo/zip';
import { resolve } from './node-module-specifier.js';
import { compartmentMapForNodeModules } from './node-modules.js';
import { search } from './search.js';
import { link } from './link.js';
import {
exitModuleImportHookMaker,
makeImportHookMaker,
} from './import-hook.js';
import parserJson from './parse-json.js';
import parserText from './parse-text.js';
import parserBytes from './parse-bytes.js';
import parserArchiveCjs from './parse-archive-cjs.js';
import parserArchiveMjs from './parse-archive-mjs.js';
import { parseLocatedJson } from './json.js';
import { unpackReadPowers } from './powers.js';
import {
assertCompartmentMap,
stringCompare,
pathCompare,
} from './compartment-map.js';
import { detectAttenuators } from './policy.js';
const textEncoder = new TextEncoder();
/** @type {Record<string, ParserImplementation>} */
const parserForLanguage = {
mjs: parserArchiveMjs,
'pre-mjs-json': parserArchiveMjs,
cjs: parserArchiveCjs,
'pre-cjs-json': parserArchiveCjs,
json: parserJson,
text: parserText,
bytes: parserBytes,
};
/**
* @param {string} rel - a relative URL
* @param {string} abs - a fully qualified URL
* @returns {string}
* Add the default parserForLanguage option.
* @param {ArchiveOptions} [options]
* @returns {ArchiveOptions}
*/
const resolveLocation = (rel, abs) => new URL(rel, abs).toString();
const { keys, entries, fromEntries } = Object;
/**
* We attempt to produce compartment maps that are consistent regardless of
* whether the packages were originally laid out on disk for development or
* production, and other trivia like the fully qualified path of a specific
* installation.
*
* Naming compartments for the self-ascribed name and version of each Node.js
* package is insufficient because they are not guaranteed to be unique.
* Dependencies do not necessarilly come from the npm registry and may be
* for example derived from fully qualified URL's or Github org and project
* names.
* Package managers are also not required to fully deduplicate the hard
* copy of each package even when they are identical resources.
* Duplication is undesirable, but we elect to defer that problem to solutions
* in the package managers, as the alternative would be to consistently hash
* the original sources of the packages themselves, which may not even be
* available much less pristine for us.
*
* So, instead, we use the lexically least path of dependency names, delimited
* by hashes.
* The compartment maps generated by the ./node-modules.js tooling pre-compute
* these traces for our use here.
* We sort the compartments lexically on their self-ascribed name and version,
* and use the lexically least dependency name path as a tie-breaker.
* The dependency path is logical and orthogonal to the package manager's
* actual installation location, so should be orthogonal to the vagaries of the
* package manager's deduplication algorithm.
*
* @param {Record<string, CompartmentDescriptor>} compartments
* @returns {Record<string, string>} map from old to new compartment names.
*/
const renameCompartments = compartments => {
/** @type {Record<string, string>} */
const compartmentRenames = Object.create(null);
let index = 0;
let prev = '';
// The sort below combines two comparators to avoid depending on sort
// stability, which became standard as recently as 2019.
// If that date seems quaint, please accept my regards from the distant past.
// We are very proud of you.
const compartmentsByPath = Object.entries(compartments)
.map(([name, compartment]) => ({
name,
path: compartment.path,
label: compartment.label,
}))
.sort((a, b) => {
if (a.label === b.label) {
assert(a.path !== undefined && b.path !== undefined);
return pathCompare(a.path, b.path);
}
return stringCompare(a.label, b.label);
});
for (const { name, label } of compartmentsByPath) {
if (label === prev) {
compartmentRenames[name] = `${label}-n${index}`;
index += 1;
} else {
compartmentRenames[name] = label;
prev = label;
index = 1;
}
}
return compartmentRenames;
};
/**
* @param {Record<string, CompartmentDescriptor>} compartments
* @param {Sources} sources
* @param {Record<string, string>} compartmentRenames
*/
const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
const result = Object.create(null);
for (const compartmentName of keys(compartmentRenames)) {
const compartment = compartments[compartmentName];
const { name, label, retained, policy } = compartment;
if (retained) {
// rename module compartments
/** @type {Record<string, ModuleDescriptor>} */
const modules = Object.create(null);
const compartmentModules = compartment.modules;
if (compartment.modules) {
for (const name of keys(compartmentModules).sort()) {
const module = compartmentModules[name];
if (module.compartment !== undefined) {
modules[name] = {
...module,
compartment: compartmentRenames[module.compartment],
};
} else {
modules[name] = module;
}
}
}
// integrate sources into modules
const compartmentSources = sources[compartmentName];
if (compartmentSources) {
for (const name of keys(compartmentSources).sort()) {
const source = compartmentSources[name];
const { location, parser, exit, sha512, deferredError } = source;
if (location !== undefined) {
modules[name] = {
location,
parser,
sha512,
};
} else if (exit !== undefined) {
modules[name] = {
exit,
};
} else if (deferredError !== undefined) {
modules[name] = {
deferredError,
};
}
}
}
result[compartmentRenames[compartmentName]] = {
name,
label,
location: compartmentRenames[compartmentName],
modules,
policy,
// `scopes`, `types`, and `parsers` are not necessary since every
// loadable module is captured in `modules`.
};
}
}
return result;
};
/**
* @param {Sources} sources
* @param {Record<string, string>} compartmentRenames
* @returns {Sources}
*/
const renameSources = (sources, compartmentRenames) => {
return fromEntries(
entries(sources).map(([name, compartmentSources]) => [
compartmentRenames[name],
compartmentSources,
]),
const assignParserForLanguage = (options = {}) => {
const { parserForLanguage: parserForLanguageOption, ...rest } = options;
const parserForLanguage = freeze(
assign(create(null), defaultParserForLanguage, parserForLanguageOption),
);
return { ...rest, parserForLanguage };
};
/**
* @param {ArchiveWriter} archive
* @param {Sources} sources
*/
const addSourcesToArchive = async (archive, sources) => {
for (const compartment of keys(sources).sort()) {
const modules = sources[compartment];
const compartmentLocation = resolveLocation(`${compartment}/`, 'file:///');
for (const specifier of keys(modules).sort()) {
const { bytes, location } = modules[specifier];
if (location !== undefined) {
const moduleLocation = resolveLocation(location, compartmentLocation);
const path = new URL(moduleLocation).pathname.slice(1); // elide initial "/"
if (bytes !== undefined) {
// eslint-disable-next-line no-await-in-loop
await archive.write(path, bytes);
}
}
}
}
};
/**
* @param {Sources} sources
* @param {CaptureSourceLocationHook} captureSourceLocation
*/
const captureSourceLocations = async (sources, captureSourceLocation) => {
for (const compartmentName of keys(sources).sort()) {
const modules = sources[compartmentName];
for (const moduleSpecifier of keys(modules).sort()) {
const { sourceLocation } = modules[moduleSpecifier];
if (sourceLocation !== undefined) {
captureSourceLocation(compartmentName, moduleSpecifier, sourceLocation);
}
}
}
};
/**
* @param {CompartmentMapDescriptor} compartmentMap
* @param {Sources} sources
* @returns {{archiveCompartmentMap: CompartmentMapDescriptor, archiveSources: Sources}}
*/
export const makeArchiveCompartmentMap = (compartmentMap, sources) => {
const {
compartments,
entry: { compartment: entryCompartmentName, module: entryModuleSpecifier },
} = compartmentMap;
const compartmentRenames = renameCompartments(compartments);
const archiveCompartments = translateCompartmentMap(
compartments,
sources,
compartmentRenames,
);
const archiveEntryCompartmentName = compartmentRenames[entryCompartmentName];
const archiveSources = renameSources(sources, compartmentRenames);
const archiveCompartmentMap = {
tags: [],
entry: {
compartment: archiveEntryCompartmentName,
module: entryModuleSpecifier,
},
compartments: archiveCompartments,
};
// Cross-check:
// We assert that we have constructed a valid compartment map, not because it
// might not be, but to ensure that the assertCompartmentMap function can
// accept all valid compartment maps.
assertCompartmentMap(archiveCompartmentMap);
return { archiveCompartmentMap, archiveSources };
};
/**
* @param {ReadFn | ReadPowers} powers
* @param {string} moduleLocation
* @param {ArchiveOptions} [options]
* @returns {Promise<{sources: Sources, compartmentMapBytes: Uint8Array, sha512?: string}>}
* @returns {Promise<{bytes: Uint8Array, sha512?: string}>}
*/
const digestLocation = async (powers, moduleLocation, options) => {
const {
moduleTransforms,
modules: exitModules = {},
dev = false,
tags = new Set(),
captureSourceLocation = undefined,
searchSuffixes = undefined,
commonDependencies = undefined,
importHook: exitModuleImportHook = undefined,
policy = undefined,
sourceMapHook = undefined,
} = options || {};
const { read, computeSha512 } = unpackReadPowers(powers);
const {
packageLocation,
packageDescriptorText,
packageDescriptorLocation,
moduleSpecifier,
} = await search(read, moduleLocation);
tags.add('endo');
tags.add('import');
tags.add('default');
const packageDescriptor = parseLocatedJson(
packageDescriptorText,
packageDescriptorLocation,
);
const compartmentMap = await compartmentMapForNodeModules(
export const makeAndHashArchive = async (
powers,
moduleLocation,
options = {},
) => {
const compartmentMap = await mapNodeModules(powers, moduleLocation, options);
return makeAndHashArchiveFromMap(
powers,
packageLocation,
tags,
packageDescriptor,
moduleSpecifier,
{ dev, commonDependencies, policy },
);
const {
compartments,
entry: { module: entryModuleSpecifier, compartment: entryCompartmentName },
} = compartmentMap;
/** @type {Sources} */
const sources = Object.create(null);
const consolidatedExitModuleImportHook = exitModuleImportHookMaker({
modules: exitModules,
exitModuleImportHook,
});
const makeImportHook = makeImportHookMaker(read, packageLocation, {
sources,
compartmentDescriptors: compartments,
archiveOnly: true,
computeSha512,
searchSuffixes,
entryCompartmentName,
entryModuleSpecifier,
exitModuleImportHook: consolidatedExitModuleImportHook,
sourceMapHook,
});
// Induce importHook to record all the necessary modules to import the given module specifier.
const { compartment, attenuatorsCompartment } = link(compartmentMap, {
resolve,
makeImportHook,
moduleTransforms,
parserForLanguage,
archiveOnly: true,
});
await compartment.load(entryModuleSpecifier);
if (policy) {
// retain all attenuators.
await Promise.all(
detectAttenuators(policy).map(attenuatorSpecifier =>
attenuatorsCompartment.load(attenuatorSpecifier),
),
);
}
const { archiveCompartmentMap, archiveSources } = makeArchiveCompartmentMap(
compartmentMap,
sources,
assignParserForLanguage(options),
);
const archiveCompartmentMapText = JSON.stringify(
archiveCompartmentMap,
null,
2,
);
const archiveCompartmentMapBytes = textEncoder.encode(
archiveCompartmentMapText,
);
if (captureSourceLocation !== undefined) {
captureSourceLocations(archiveSources, captureSourceLocation);
}
let archiveSha512;
if (computeSha512 !== undefined) {
archiveSha512 = computeSha512(archiveCompartmentMapBytes);
}
return {
compartmentMapBytes: archiveCompartmentMapBytes,
sources: archiveSources,
sha512: archiveSha512,
};
};

@@ -408,17 +72,19 @@

* @param {ArchiveOptions} [options]
* @returns {Promise<{bytes: Uint8Array, sha512?: string}>}
* @returns {Promise<Uint8Array>}
*/
export const makeAndHashArchive = async (powers, moduleLocation, options) => {
const { compartmentMapBytes, sources, sha512 } = await digestLocation(
export const makeArchive = async (powers, moduleLocation, options = {}) => {
const { dev, tags, conditions = tags, commonDependencies, policy } = options;
const compartmentMap = await mapNodeModules(powers, moduleLocation, {
dev,
conditions,
commonDependencies,
policy,
});
return makeArchiveFromMap(
powers,
moduleLocation,
options,
compartmentMap,
assignParserForLanguage(options),
);
const archive = writeZip();
await archive.write('compartment-map.json', compartmentMapBytes);
await addSourcesToArchive(archive, sources);
const bytes = await archive.snapshot();
return { bytes, sha512 };
};

@@ -432,20 +98,13 @@

*/
export const makeArchive = async (powers, moduleLocation, options) => {
const { bytes } = await makeAndHashArchive(powers, moduleLocation, options);
return bytes;
};
export const mapLocation = async (powers, moduleLocation, options = {}) => {
const { dev, tags, conditions = tags, commonDependencies, policy } = options;
/**
* @param {ReadFn | ReadPowers} powers
* @param {string} moduleLocation
* @param {ArchiveOptions} [options]
* @returns {Promise<Uint8Array>}
*/
export const mapLocation = async (powers, moduleLocation, options) => {
const { compartmentMapBytes } = await digestLocation(
powers,
moduleLocation,
options,
);
return compartmentMapBytes;
const compartmentMap = await mapNodeModules(powers, moduleLocation, {
dev,
conditions,
commonDependencies,
policy,
});
return mapFromMap(powers, compartmentMap, assignParserForLanguage(options));
};

@@ -459,10 +118,13 @@

*/
export const hashLocation = async (powers, moduleLocation, options) => {
const { compartmentMapBytes } = await digestLocation(
powers,
moduleLocation,
options,
);
const { computeSha512 } = powers;
return computeSha512(compartmentMapBytes);
export const hashLocation = async (powers, moduleLocation, options = {}) => {
const { dev, tags, conditions = tags, commonDependencies, policy } = options;
const compartmentMap = await mapNodeModules(powers, moduleLocation, {
dev,
conditions,
commonDependencies,
policy,
});
return hashFromMap(powers, compartmentMap, assignParserForLanguage(options));
};

@@ -482,6 +144,18 @@

moduleLocation,
options,
options = {},
) => {
const archiveBytes = await makeArchive(readPowers, moduleLocation, options);
await write(archiveLocation, archiveBytes);
const { dev, tags, conditions = tags, commonDependencies, policy } = options;
const compartmentMap = await mapNodeModules(readPowers, moduleLocation, {
dev,
conditions,
commonDependencies,
policy,
});
return writeArchiveFromMap(
write,
readPowers,
archiveLocation,
compartmentMap,
assignParserForLanguage(options),
);
};

@@ -1,19 +0,8 @@

declare namespace _default {
export { runtime };
export function getBundlerKit({ index, indexedImports, record: { cjsFunctor, exports: exportsList }, }: {
index: any;
indexedImports: any;
record: {
cjsFunctor: any;
exports?: {} | undefined;
};
}): {
getFunctor: () => string;
getCells: () => string;
getReexportsWiring: () => string;
getFunctorCall: () => string;
};
}
declare const _default: BundlerSupport<CjsModuleSource>;
export default _default;
declare const runtime: string;
export type CjsModuleSource = VirtualModuleSource & {
cjsFunctor: string;
};
import type { BundlerSupport } from './bundle.js';
import type { VirtualModuleSource } from 'ses';
//# sourceMappingURL=bundle-cjs.d.ts.map

@@ -1,2 +0,8 @@

// @ts-nocheck
/* Provides CommonJS support for `bundle.js`. */
/** @import {VirtualModuleSource} from 'ses' */
/** @import {BundlerSupport} from './bundle.js' */
/** @typedef {VirtualModuleSource & {cjsFunctor: string}} CjsModuleSource */
/** quotes strings */

@@ -17,3 +23,4 @@ const q = JSON.stringify;

// This function is serialized and references variables from its destination scope.
const runtime = function wrapCjsFunctor(num) {
const runtime = `\
function wrapCjsFunctor(num) {
/* eslint-disable no-undef */

@@ -53,4 +60,5 @@ return ({ imports = {} }) => {

/* eslint-enable no-undef */
}.toString();
}`;
/** @type {BundlerSupport<CjsModuleSource>} */
export default {

@@ -57,0 +65,0 @@ runtime,

export const runtime: "function observeImports(map, importName, importIndex) {\n for (const [name, observers] of map.get(importName)) {\n const cell = cells[importIndex][name];\n if (cell === undefined) {\n throw new ReferenceError(`Cannot import name ${name}`);\n }\n for (const observer of observers) {\n cell.observe(observer);\n }\n }\n}\n";
declare namespace _default {
export { runtime };
export function getBundlerKit({ index, indexedImports, record: { __syncModuleProgram__, __fixedExportMap__, __liveExportMap__, __reexportMap__, reexports, }, }: {
index: any;
indexedImports: any;
record: {
__syncModuleProgram__: any;
__fixedExportMap__?: {} | undefined;
__liveExportMap__?: {} | undefined;
__reexportMap__?: {} | undefined;
reexports: any;
};
}): {
getFunctor: () => string;
getCells: () => string;
getReexportsWiring: () => any;
getFunctorCall: () => string;
};
}
declare const _default: BundlerSupport<PrecompiledModuleSource>;
export default _default;
import type { PrecompiledModuleSource } from 'ses';
import type { BundlerSupport } from './bundle.js';
//# sourceMappingURL=bundle-mjs.d.ts.map

@@ -0,1 +1,6 @@

/* Provides ESM support for `bundle.js`. */
/** @import {PrecompiledModuleSource} from 'ses' */
/** @import {BundlerSupport} from './bundle.js' */
/** quotes strings */

@@ -48,2 +53,3 @@ const q = JSON.stringify;

/** @type {BundlerSupport<PrecompiledModuleSource>} */
export default {

@@ -50,0 +56,0 @@ runtime,

@@ -1,14 +0,57 @@

export function makeBundle(read: ReadFn, moduleLocation: string, options?: {
moduleTransforms?: ModuleTransforms | undefined;
dev?: boolean | undefined;
tags?: Set<string> | undefined;
commonDependencies?: object;
searchSuffixes?: string[] | undefined;
sourceMapHook?: import("./types.js").SourceMapHook | undefined;
} | undefined): Promise<string>;
export function makeBundle(readPowers: ReadFn | ReadPowers | MaybeReadPowers, moduleLocation: string, options?: ArchiveOptions | undefined): Promise<string>;
export function writeBundle(write: WriteFn, read: ReadFn, bundleLocation: string, moduleLocation: string, options?: ArchiveOptions | undefined): Promise<void>;
export type BundlerKit = {
/**
* Produces a JavaScript string consisting of
* a function expression followed by a comma delimiter that will be evaluated in
* a lexical scope with no free variables except the globals.
* In the generated bundle runtime, the function will receive an environment
* record: a record mapping every name of the corresponding module's internal
* namespace to a "cell" it can use to get, set, or observe the linked
* variable.
*/
getFunctor: () => string;
/**
* Produces a JavaScript string consisting of
* a JavaScript object and a trailing comma.
* The string is evaluated in a lexical context with a `cell` maker, the `cells`
* array of every module's internal environment record.
*/
getCells: () => string;
/**
* Produces a JavaScript string may
* be a statement that calls this module's functor with the calling convention
* appropriate for its language, injecting whatever cells it needs to link to
* other module namespaces.
*/
getFunctorCall: () => string;
/**
* Produces a JavaScript string
* that may include statements that bind the cells reexported by this module.
*/
getReexportsWiring: () => string;
};
export type BundleModule<SpecificModuleSource extends unknown> = {
key: string;
compartmentName: string;
moduleSpecifier: string;
parser: string;
record: StaticModuleType & SpecificModuleSource;
resolvedImports: Record<string, string>;
indexedImports: Record<string, number>;
bytes: Uint8Array;
index: number;
bundlerKit: BundlerKit;
};
export type GetBundlerKit<SpecificModuleSource extends unknown> = (module: BundleModule<SpecificModuleSource>) => BundlerKit;
export type BundlerSupport<SpecificModuleSource extends unknown> = {
runtime: string;
getBundlerKit: GetBundlerKit<SpecificModuleSource>;
};
import type { ReadFn } from './types.js';
import type { ModuleTransforms } from './types.js';
import type { ReadPowers } from './types.js';
import type { MaybeReadPowers } from './types.js';
import type { ArchiveOptions } from './types.js';
import type { WriteFn } from './types.js';
import type { ArchiveOptions } from './types.js';
import type { StaticModuleType } from 'ses';
//# sourceMappingURL=bundle.d.ts.map
// @ts-check
/* eslint no-shadow: 0 */
/** @import {ResolveHook} from 'ses' */
/** @import {PrecompiledStaticModuleInterface} from 'ses' */
/** @import {ParserImplementation} from './types.js' */
/** @import {StaticModuleType} from 'ses' */
/** @import {ArchiveOptions} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {CompartmentSources} from './types.js' */
/** @import {MaybeReadPowers} from './types.js' */
/** @import {PrecompiledStaticModuleInterface} from 'ses' */
/** @import {ReadFn} from './types.js' */
/** @import {ModuleTransforms} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {Sources} from './types.js' */
/** @import {WriteFn} from './types.js' */
/** @import {ArchiveOptions} from './types.js' */
/**
* @typedef {object} BundlerKit
* @property {() => string} getFunctor Produces a JavaScript string consisting of
* a function expression followed by a comma delimiter that will be evaluated in
* a lexical scope with no free variables except the globals.
* In the generated bundle runtime, the function will receive an environment
* record: a record mapping every name of the corresponding module's internal
* namespace to a "cell" it can use to get, set, or observe the linked
* variable.
* @property {() => string} getCells Produces a JavaScript string consisting of
* a JavaScript object and a trailing comma.
* The string is evaluated in a lexical context with a `cell` maker, the `cells`
* array of every module's internal environment record.
* @property {() => string} getFunctorCall Produces a JavaScript string may
* be a statement that calls this module's functor with the calling convention
* appropriate for its language, injecting whatever cells it needs to link to
* other module namespaces.
* @property {() => string} getReexportsWiring Produces a JavaScript string
* that may include statements that bind the cells reexported by this module.
*/
/**
* @template {unknown} SpecificModuleSource
* @typedef {object} BundleModule
* @property {string} key
* @property {string} compartmentName
* @property {string} moduleSpecifier
* @property {string} parser
* @property {StaticModuleType & SpecificModuleSource} record
* @property {Record<string, string>} resolvedImports
* @property {Record<string, number>} indexedImports
* @property {Uint8Array} bytes
* @property {number} index
* @property {BundlerKit} bundlerKit
*/
/**
* @template {unknown} SpecificModuleSource
* @callback GetBundlerKit
* @param {BundleModule<SpecificModuleSource>} module
* @returns {BundlerKit}
*/
/**
* @template {unknown} SpecificModuleSource
* @typedef {object} BundlerSupport
* @property {string} runtime
* @property {GetBundlerKit<SpecificModuleSource>} getBundlerKit
*/
import { resolve } from './node-module-specifier.js';

@@ -19,8 +70,5 @@ import { compartmentMapForNodeModules } from './node-modules.js';

import { link } from './link.js';
import { unpackReadPowers } from './powers.js';
import { makeImportHookMaker } from './import-hook.js';
import parserJson from './parse-json.js';
import parserText from './parse-text.js';
import parserBytes from './parse-bytes.js';
import parserArchiveCjs from './parse-archive-cjs.js';
import parserArchiveMjs from './parse-archive-mjs.js';
import { defaultParserForLanguage } from './archive-parsers.js';
import { parseLocatedJson } from './json.js';

@@ -30,2 +78,3 @@

import cjsSupport from './bundle-cjs.js';
import jsonSupport from './bundle-json.js';

@@ -36,13 +85,2 @@ const textEncoder = new TextEncoder();

/** @type {Record<string, ParserImplementation>} */
const parserForLanguage = {
mjs: parserArchiveMjs,
'pre-mjs-json': parserArchiveMjs,
cjs: parserArchiveCjs,
'pre-cjs-json': parserArchiveCjs,
json: parserJson,
text: parserText,
bytes: parserBytes,
};
/**

@@ -60,4 +98,7 @@ * @param {Record<string, CompartmentDescriptor>} compartmentDescriptors

) => {
/** @type {BundleModule<unknown>[]} */
const modules = [];
/** @type {Map<string, string>} aliaes */
const aliases = new Map();
/** @type {Set<string>} seen */
const seen = new Set();

@@ -78,3 +119,5 @@

if (source !== undefined) {
const { record, parser, deferredError } = source;
const { record, parser, deferredError, bytes } = source;
assert(parser !== undefined);
assert(bytes !== undefined);
if (deferredError) {

@@ -107,2 +150,7 @@ throw Error(

resolvedImports,
bytes,
// @ts-expect-error
index: undefined,
// @ts-expect-error
bundlerKit: null,
});

@@ -141,41 +189,43 @@

const implementationPerParser = {
/** @type {Record<string, BundlerSupport<unknown>>} */
const bundlerSupportForLanguage = {
'pre-mjs-json': mjsSupport,
'pre-cjs-json': cjsSupport,
json: jsonSupport,
};
function getRuntime(parser) {
return implementationPerParser[parser]
? implementationPerParser[parser].runtime
: `/*unknown parser:${parser}*/`;
}
/** @param {string} language */
const getRuntime = language =>
bundlerSupportForLanguage[language]
? bundlerSupportForLanguage[language].runtime
: `/*unknown language:${language}*/`;
function getBundlerKitForModule(module) {
const parser = module.parser;
if (!implementationPerParser[parser]) {
const warning = `/*unknown parser:${parser}*/`;
/** @param {BundleModule<unknown>} module */
const getBundlerKitForModule = module => {
const language = module.parser;
assert(language !== undefined);
if (bundlerSupportForLanguage[language] === undefined) {
const warning = `/*unknown language:${language}*/`;
// each item is a function to avoid creating more in-memory copies of the source text etc.
/** @type {BundlerKit} */
return {
getFunctor: () => `(()=>{${warning}})`,
getCells: `{${warning}}`,
getFunctorCall: warning,
getFunctor: () => `(()=>{${warning}}),`,
getCells: () => `{${warning}},`,
getFunctorCall: () => warning,
getReexportsWiring: () => '',
};
}
const { getBundlerKit } = implementationPerParser[parser];
const { getBundlerKit } = bundlerSupportForLanguage[language];
return getBundlerKit(module);
}
};
/**
* @param {ReadFn} read
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
* @param {string} moduleLocation
* @param {object} [options]
* @param {ModuleTransforms} [options.moduleTransforms]
* @param {boolean} [options.dev]
* @param {Set<string>} [options.tags]
* @param {object} [options.commonDependencies]
* @param {Array<string>} [options.searchSuffixes]
* @param {import('./types.js').SourceMapHook} [options.sourceMapHook]
* @param {ArchiveOptions} [options]
* @returns {Promise<string>}
*/
export const makeBundle = async (read, moduleLocation, options) => {
export const makeBundle = async (readPowers, moduleLocation, options) => {
const { read } = unpackReadPowers(readPowers);
const {

@@ -185,8 +235,22 @@ moduleTransforms,

tags: tagsOption,
conditions: conditionsOption = tagsOption,
searchSuffixes,
commonDependencies,
sourceMapHook = undefined,
parserForLanguage: parserForLanguageOption = {},
languageForExtension: languageForExtensionOption = {},
} = options || {};
const tags = new Set(tagsOption);
const conditions = new Set(conditionsOption);
const parserForLanguage = Object.freeze(
Object.assign(
Object.create(null),
defaultParserForLanguage,
parserForLanguageOption,
),
);
const languageForExtension = Object.freeze(
Object.assign(Object.create(null), languageForExtensionOption),
);
const {

@@ -197,3 +261,3 @@ packageLocation,

moduleSpecifier,
} = await search(read, moduleLocation);
} = await search(readPowers, moduleLocation);

@@ -207,3 +271,3 @@ const packageDescriptor = parseLocatedJson(

packageLocation,
tags,
conditions,
packageDescriptor,

@@ -236,2 +300,3 @@ moduleSpecifier,

parserForLanguage,
languageForExtension,
});

@@ -285,6 +350,3 @@ await compartment.load(entryModuleSpecifier);

'use strict';
(() => {
const functors = [
${''.concat(...modules.map(m => m.bundlerKit.getFunctor()))}\
]; // functors end
(functors => {

@@ -317,3 +379,3 @@ const cell = (name, value = undefined) => {

const namespaces = cells.map(cells => Object.freeze(Object.create(null, {
const namespaces = cells.map(cells => Object.freeze(Object.create(null, {
...cells,

@@ -338,3 +400,3 @@ // Make this appear like an ESM module namespace object.

return cells[cells.length - 1]['*'].get();
})();
})([${''.concat(...modules.map(m => m.bundlerKit.getFunctor()))}]);
`;

@@ -341,0 +403,0 @@

/** @type {(a: string, b: string) => number} */
export const stringCompare: (a: string, b: string) => number;
export function pathCompare(a: Array<string> | undefined, b: Array<string> | undefined): number;
export function assertCompartmentMap(allegedCompartmentMap: unknown, url?: string | undefined): asserts compartmentMap is import('./types.js').CompartmentMapDescriptor;
export function assertCompartmentMap(allegedCompartmentMap: unknown, url?: string | undefined): asserts compartmentMap is import("./types.js").CompartmentMapDescriptor;
//# sourceMappingURL=compartment-map.d.ts.map

@@ -0,1 +1,3 @@

/* Validates a compartment map against its schema. */
// @ts-check

@@ -12,12 +14,2 @@ /// <reference types="ses"/>

const moduleLanguages = [
'cjs',
'mjs',
'json',
'text',
'bytes',
'pre-mjs-json',
'pre-cjs-json',
];
/** @type {(a: string, b: string) => number} */

@@ -97,16 +89,16 @@ // eslint-disable-next-line no-nested-ternary

/**
* @param {unknown} tags
* @param {unknown} conditions
* @param {string} url
*/
const assertTags = (tags, url) => {
if (tags === undefined) return;
const assertConditions = (conditions, url) => {
if (conditions === undefined) return;
assert(
Array.isArray(tags),
`tags must be an array, got ${tags} in ${q(url)}`,
Array.isArray(conditions),
`conditions must be an array, got ${conditions} in ${q(url)}`,
);
for (const [index, value] of enumerate(tags)) {
for (const [index, value] of enumerate(conditions)) {
assert.typeof(
value,
'string',
`tags[${index}] must be a string, got ${value} in ${q(url)}`,
`conditions[${index}] must be a string, got ${value} in ${q(url)}`,
);

@@ -165,8 +157,2 @@ }

);
assert(
moduleLanguages.includes(parser),
`${path}.parser must be one of ${q(moduleLanguages)}, got ${parser} in ${q(
url,
)}`,
);

@@ -279,8 +265,2 @@ if (sha512 !== undefined) {

);
assert(
moduleLanguages.includes(value),
`${path}.parsers[${q(key)}] must be one of ${q(
moduleLanguages,
)}, got ${value} in ${q(url)}`,
);
}

@@ -367,8 +347,2 @@ };

);
assert(
moduleLanguages.includes(value),
`${path}.types[${q(key)}] must be one of ${q(
moduleLanguages,
)}, got ${value} in ${q(url)}`,
);
}

@@ -514,3 +488,10 @@ };

);
const { tags, entry, compartments, ...extra } = Object(compartmentMap);
const {
// TODO migrate tags to conditions
// https://github.com/endojs/endo/issues/2388
tags: conditions,
entry,
compartments,
...extra
} = Object(compartmentMap);
assertEmptyObject(

@@ -522,5 +503,5 @@ extra,

);
assertTags(tags, url);
assertConditions(conditions, url);
assertEntry(entry, url);
assertCompartments(compartments, url);
};

@@ -0,1 +1,3 @@

/* Extracts the extension from a URL pathname. */
// @ts-check

@@ -2,0 +4,0 @@

@@ -1,2 +0,6 @@

export function parseArchive(archiveBytes: Uint8Array, archiveLocation?: string | undefined, options?: {
export function parseArchive(archiveBytes: Uint8Array, archiveLocation?: string | undefined, options?: Options | undefined): Promise<Application>;
export function loadArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options?: LoadArchiveOptions | undefined): Promise<Application>;
export function importArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options: ExecuteOptions & LoadArchiveOptions): Promise<object>;
export type CompartmentConstructor = typeof Compartment;
export type Options = {
expectedSha512?: string | undefined;

@@ -9,6 +13,8 @@ computeSha512?: HashFn | undefined;

computeSourceMapLocation?: ComputeSourceMapLocationHook | undefined;
} | undefined): Promise<Application>;
export function loadArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options?: LoadArchiveOptions | undefined): Promise<Application>;
export function importArchive(readPowers: import("@endo/zip").ReadFn | ReadPowers, archiveLocation: string, options: ExecuteOptions & LoadArchiveOptions): Promise<object>;
export type CompartmentConstructor = typeof Compartment;
parserForLanguage?: ParserForLanguage | undefined;
};
import type { Application } from './types.js';
import type { ReadPowers } from './types.js';
import type { LoadArchiveOptions } from './types.js';
import type { ExecuteOptions } from './types.js';
import type { HashFn } from './types.js';

@@ -18,6 +24,3 @@ import type { ExitModuleImportHook } from './types.js';

import type { ComputeSourceMapLocationHook } from './types.js';
import type { Application } from './types.js';
import type { ReadPowers } from './types.js';
import type { LoadArchiveOptions } from './types.js';
import type { ExecuteOptions } from './types.js';
import type { ParserForLanguage } from './types.js';
//# sourceMappingURL=import-archive.d.ts.map

@@ -0,256 +1,73 @@

/* Provides functions for evaluating modules in an archive (a zip file
* with a `compartment-map.json` and a file for a module and each of its
* transitive dependencies.)
*
* These functions accept the URL of an entry module and find its transitive
* dependencies through the Node.js `node_modules` conventions.
*
* These functions use the default parsers in `import-archive-parsers.js`,
* which support only pre-compiled ESM and CommonJS.
*
* See `import-archive-lite.js` for functions that are not coupled to these
* parsers or the `node_modules` conventions without necessarily entraining a
* dependency on Babel.
*/
// @ts-check
/* eslint no-shadow: "off" */
import { ZipReader } from '@endo/zip';
import { link } from './link.js';
import parserPreCjs from './parse-pre-cjs.js';
import parserJson from './parse-json.js';
import parserText from './parse-text.js';
import parserBytes from './parse-bytes.js';
import parserPreMjs from './parse-pre-mjs.js';
import { parseLocatedJson } from './json.js';
import { unpackReadPowers } from './powers.js';
import { join } from './node-module-specifier.js';
import { assertCompartmentMap } from './compartment-map.js';
import { exitModuleImportHookMaker } from './import-hook.js';
import { attenuateModuleHook, enforceModulePolicy } from './policy.js';
import { defaultParserForLanguage } from './import-archive-parsers.js';
import {
parseArchive as parseArchiveLite,
loadArchive as loadArchiveLite,
importArchive as importArchiveLite,
} from './import-archive-lite.js';
/** @import {StaticModuleType} from 'ses' */
/** @import {Application, CompartmentDescriptor, ComputeSourceLocationHook, ComputeSourceMapLocationHook, ExecuteFn, ExecuteOptions, ExitModuleImportHook, HashFn, ImportHookMaker, LoadArchiveOptions, ParserImplementation, ReadPowers} from './types.js' */
const { assign, create, freeze } = Object;
const DefaultCompartment = Compartment;
/** @import {Application} from './types.js' */
/** @import {ComputeSourceLocationHook} from './types.js' */
/** @import {ComputeSourceMapLocationHook} from './types.js' */
/** @import {ExecuteOptions} from './types.js' */
/** @import {ExitModuleImportHook} from './types.js' */
/** @import {HashFn} from './types.js' */
/** @import {LoadArchiveOptions} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {ParserForLanguage} from './types.js' */
const { Fail, quote: q } = assert;
// Must give the type of Compartment a name to capture the external meaning of
// Compartment Otherwise @param {typeof Compartment} takes the Compartment to
// mean the const variable defined within the function.
//
/** @typedef {typeof Compartment} CompartmentConstructor */
const textDecoder = new TextDecoder();
const { freeze } = Object;
/** @type {Record<string, ParserImplementation>} */
const parserForLanguage = {
'pre-cjs-json': parserPreCjs,
'pre-mjs-json': parserPreMjs,
json: parserJson,
text: parserText,
bytes: parserBytes,
};
/**
* @param {string} errorMessage - error to throw on execute
* @returns {StaticModuleType}
* @typedef {object} Options
* @property {string} [expectedSha512]
* @property {HashFn} [computeSha512]
* @property {Record<string, unknown>} [modules]
* @property {ExitModuleImportHook} [importHook]
* @property {CompartmentConstructor} [Compartment]
* @property {ComputeSourceLocationHook} [computeSourceLocation]
* @property {ComputeSourceMapLocationHook} [computeSourceMapLocation]
* @property {ParserForLanguage} [parserForLanguage]
*/
const postponeErrorToExecute = errorMessage => {
// Return a place-holder that'd throw an error if executed
// This allows cjs parser to more eagerly find calls to require
// - if parser identified a require call that's a local function, execute will never be called
// - if actual required module is missing, the error will happen anyway - at execution time
const record = freeze({
imports: [],
exports: [],
execute: () => {
throw Error(errorMessage);
},
});
return record;
};
/**
* @param {(path: string) => Uint8Array} get
* @param {Record<string, CompartmentDescriptor>} compartments
* @param {string} archiveLocation
* @param {HashFn} [computeSha512]
* @param {ComputeSourceLocationHook} [computeSourceLocation]
* @param {ExitModuleImportHook} [exitModuleImportHook]
* @param {ComputeSourceMapLocationHook} [computeSourceMapLocation]
* @returns {ImportHookMaker}
* Add the default parserForLanguage option.
* @param {Options} [options]
* @returns {Options}
*/
const makeArchiveImportHookMaker = (
get,
compartments,
archiveLocation,
computeSha512 = undefined,
computeSourceLocation = undefined,
exitModuleImportHook = undefined,
computeSourceMapLocation = undefined,
) => {
// per-assembly:
/** @type {ImportHookMaker} */
const makeImportHook = ({
packageLocation,
packageName,
attenuators,
// note `compartments` are not passed to makeImportHook because
// the reference was passed to makeArchiveImportHookMaker.
}) => {
// per-compartment:
const compartmentDescriptor = compartments[packageLocation];
const { modules } = compartmentDescriptor;
/** @type {import('ses').ImportHook} */
const importHook = async moduleSpecifier => {
// per-module:
const module = modules[moduleSpecifier];
if (module === undefined) {
if (exitModuleImportHook) {
// At this point in archive importing, if a module is not found and
// exitModuleImportHook exists, the only possibility is that the
// module is a "builtin" module and the policy needs to be enforced.
enforceModulePolicy(moduleSpecifier, compartmentDescriptor, {
exit: true,
errorHint: `Blocked in loading. ${q(
moduleSpecifier,
)} was not in the archive and an attempt was made to load it as a builtin`,
});
const record = await exitModuleImportHook(moduleSpecifier);
if (record) {
// note it's not being marked as exit in sources
// it could get marked and the second pass, when the archive is being executed, would have the data
// to enforce which exits can be dynamically imported
return {
record: await attenuateModuleHook(
moduleSpecifier,
record,
compartmentDescriptor.policy,
attenuators,
),
specifier: moduleSpecifier,
};
} else {
// if exitModuleImportHook is allowed, the mechanism to defer
// errors in archive creation is never used. We don't want to
// throw until the module execution is attempted. This is because
// the cjs parser eagerly looks for require calls, and if it finds
// one, it will try to import the module even if the require is
// never reached.
return postponeErrorToExecute(
`Cannot find external module ${q(moduleSpecifier)} in package ${q(
packageLocation,
)} in archive ${q(archiveLocation)}`,
);
}
}
throw Error(
`Cannot find module ${q(moduleSpecifier)} in package ${q(
packageLocation,
)} in archive ${q(archiveLocation)}`,
);
}
if (module.deferredError !== undefined) {
return postponeErrorToExecute(module.deferredError);
}
if (module.parser === undefined) {
throw Error(
`Cannot parse module ${q(moduleSpecifier)} in package ${q(
packageLocation,
)} in archive ${q(archiveLocation)}`,
);
}
if (parserForLanguage[module.parser] === undefined) {
throw Error(
`Cannot parse ${q(module.parser)} module ${q(
moduleSpecifier,
)} in package ${q(packageLocation)} in archive ${q(archiveLocation)}`,
);
}
const { parse } = parserForLanguage[module.parser];
const moduleLocation = `${packageLocation}/${module.location}`;
const moduleBytes = get(moduleLocation);
if (computeSha512 !== undefined && module.sha512 !== undefined) {
const sha512 = computeSha512(moduleBytes);
if (sha512 !== module.sha512) {
throw Error(
`Module ${q(module.location)} of package ${q(
packageLocation,
)} in archive ${q(
archiveLocation,
)} failed a SHA-512 integrity check`,
);
}
}
let sourceLocation = `file:///${moduleLocation}`;
if (packageName !== undefined) {
const base = packageName.split('/').slice(-1).join('/');
sourceLocation = `.../${join(base, moduleSpecifier)}`;
}
if (computeSourceLocation !== undefined) {
sourceLocation =
computeSourceLocation(packageLocation, moduleSpecifier) ||
sourceLocation;
}
let sourceMapUrl;
if (
computeSourceMapLocation !== undefined &&
module.sha512 !== undefined
) {
sourceMapUrl = computeSourceMapLocation({
compartment: packageLocation,
module: moduleSpecifier,
location: sourceLocation,
sha512: module.sha512,
});
}
// eslint-disable-next-line no-await-in-loop
const { record } = await parse(
moduleBytes,
moduleSpecifier,
sourceLocation,
packageLocation,
{
sourceMapUrl,
},
);
return { record, specifier: moduleSpecifier };
};
return importHook;
};
return makeImportHook;
};
/**
* Creates a fake module namespace object that passes a brand check.
*
* @param {typeof Compartment} Compartment
* @returns {import('ses').ModuleExportsNamespace}
*/
const makeFauxModuleExportsNamespace = Compartment => {
const compartment = new Compartment(
{},
{},
{
resolveHook() {
return '.';
},
async importHook() {
return {
imports: [],
execute() {},
exports: [],
};
},
},
const assignParserForLanguage = (options = {}) => {
const { parserForLanguage: parserForLanguageOption, ...rest } = options;
/** @type {ParserForLanguage} */
const parserForLanguage = freeze(
assign(create(null), defaultParserForLanguage, parserForLanguageOption),
);
return compartment.module('.');
return { ...rest, parserForLanguage };
};
// Have to give it a name to capture the external meaning of Compartment
// Otherwise @param {typeof Compartment} takes the Compartment to mean
// the const variable defined within the function.
/** @typedef {typeof Compartment} CompartmentConstructor */
/**
* @param {Uint8Array} archiveBytes
* @param {string} [archiveLocation]
* @param {object} [options]
* @param {string} [options.expectedSha512]
* @param {HashFn} [options.computeSha512]
* @param {Record<string, unknown>} [options.modules]
* @param {ExitModuleImportHook} [options.importHook]
* @param {CompartmentConstructor} [options.Compartment]
* @param {ComputeSourceLocationHook} [options.computeSourceLocation]
* @param {ComputeSourceMapLocationHook} [options.computeSourceMapLocation]
* @param {Options} [options]
* @returns {Promise<Application>}

@@ -262,145 +79,9 @@ */

options = {},
) => {
const {
computeSha512 = undefined,
expectedSha512 = undefined,
computeSourceLocation = undefined,
computeSourceMapLocation = undefined,
Compartment = DefaultCompartment,
modules = undefined,
importHook: exitModuleImportHook = undefined,
} = options;
const compartmentExitModuleImportHook = exitModuleImportHookMaker({
modules,
exitModuleImportHook,
});
const archive = new ZipReader(archiveBytes, { name: archiveLocation });
// Track all modules that get loaded, all files that are used.
const unseen = new Set(archive.files.keys());
unseen.size >= 2 ||
Fail`Archive failed sanity check: should contain at least a compartment map file and one module file in ${q(
archiveLocation,
)}`;
/**
* @param {string} path
*/
const get = path => {
unseen.delete(path);
return archive.read(path);
};
const compartmentMapBytes = get('compartment-map.json');
let sha512;
if (computeSha512 !== undefined) {
sha512 = computeSha512(compartmentMapBytes);
}
if (expectedSha512 !== undefined) {
if (sha512 === undefined) {
throw Error(
`Cannot verify expectedSha512 without also providing computeSha512, for archive ${archiveLocation}`,
);
}
if (sha512 !== expectedSha512) {
throw Error(
`Archive compartment map failed a SHA-512 integrity check, expected ${expectedSha512}, got ${sha512}, for archive ${archiveLocation}`,
);
}
}
const compartmentMapText = textDecoder.decode(compartmentMapBytes);
const compartmentMap = parseLocatedJson(
compartmentMapText,
'compartment-map.json',
) =>
parseArchiveLite(
archiveBytes,
archiveLocation,
assignParserForLanguage(options),
);
assertCompartmentMap(compartmentMap, archiveLocation);
const {
compartments,
entry: { module: moduleSpecifier },
} = compartmentMap;
// Archive integrity checks: ensure every module is pre-loaded so its hash
// gets checked, and ensure that every file in the archive is used, and
// therefore checked.
if (computeSha512 !== undefined) {
const makeImportHook = makeArchiveImportHookMaker(
get,
compartments,
archiveLocation,
computeSha512,
computeSourceLocation,
compartmentExitModuleImportHook,
computeSourceMapLocation,
);
// A weakness of the current Compartment design is that the `modules` map
// must be given a module namespace object that passes a brand check.
// We don't have module instances for the preload phase, so we supply fake
// namespaces.
const { compartment, pendingJobsPromise } = link(compartmentMap, {
makeImportHook,
parserForLanguage,
modules: Object.fromEntries(
Object.keys(modules || {}).map(specifier => {
return [specifier, makeFauxModuleExportsNamespace(Compartment)];
}),
),
Compartment,
});
await pendingJobsPromise;
await compartment.load(moduleSpecifier);
unseen.size === 0 ||
Fail`Archive contains extraneous files: ${q([...unseen])} in ${q(
archiveLocation,
)}`;
}
/** @type {ExecuteFn} */
const execute = async options => {
const {
globals,
modules,
transforms,
__shimTransforms__,
Compartment,
importHook: exitModuleImportHook,
} = options || {};
const compartmentExitModuleImportHook = exitModuleImportHookMaker({
modules,
exitModuleImportHook,
});
const makeImportHook = makeArchiveImportHookMaker(
get,
compartments,
archiveLocation,
computeSha512,
computeSourceLocation,
compartmentExitModuleImportHook,
computeSourceMapLocation,
);
const { compartment, pendingJobsPromise } = link(compartmentMap, {
makeImportHook,
parserForLanguage,
globals,
modules,
transforms,
__shimTransforms__,
Compartment,
});
await pendingJobsPromise;
// eslint-disable-next-line dot-notation
return compartment['import'](moduleSpecifier);
};
return { import: execute, sha512 };
};
/**

@@ -412,23 +93,8 @@ * @param {import('@endo/zip').ReadFn | ReadPowers} readPowers

*/
export const loadArchive = async (
readPowers,
archiveLocation,
options = {},
) => {
const { read, computeSha512 } = unpackReadPowers(readPowers);
const {
expectedSha512,
computeSourceLocation,
modules,
computeSourceMapLocation,
} = options;
const archiveBytes = await read(archiveLocation);
return parseArchive(archiveBytes, archiveLocation, {
computeSha512,
expectedSha512,
computeSourceLocation,
modules,
computeSourceMapLocation,
});
};
export const loadArchive = async (readPowers, archiveLocation, options) =>
loadArchiveLite(
readPowers,
archiveLocation,
assignParserForLanguage(options),
);

@@ -441,5 +107,7 @@ /**

*/
export const importArchive = async (readPowers, archiveLocation, options) => {
const archive = await loadArchive(readPowers, archiveLocation, options);
return archive.import(options);
};
export const importArchive = async (readPowers, archiveLocation, options) =>
importArchiveLite(
readPowers,
archiveLocation,
assignParserForLanguage(options),
);

@@ -0,1 +1,9 @@

/* Provides the implementation of each compartment's `importHook` when using
* `import.js`, `import-lite.js`, `archive.js`, or `archive-lite.js`.
* However, `import-archive.js` and `import-archive-lite.js` use their own variant.
*
* For building archives, these import hooks create a table of all the modules
* in a "working set" of transitive dependencies.
*/
// @ts-check

@@ -6,3 +14,2 @@

/** @import {RedirectStaticModuleInterface} from 'ses' */
/** @import {ThirdPartyStaticModuleInterface} from 'ses' */
/** @import {ReadFn} from './types.js' */

@@ -12,6 +19,4 @@ /** @import {ReadPowers} from './types.js' */

/** @import {Sources} from './types.js' */
/** @import {CompartmentSources} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {ImportHookMaker} from './types.js' */
/** @import {DeferredAttenuatorsProvider} from './types.js' */
/** @import {ExitModuleImportHook} from './types.js' */

@@ -209,2 +214,3 @@

const importHook = async moduleSpecifier => {
await null;
compartmentDescriptor.retained = true;

@@ -322,2 +328,3 @@

}),
compartmentDescriptor,
},

@@ -324,0 +331,0 @@ );

@@ -1,6 +0,3 @@

/** @type {Record<string, ParserImplementation>} */
export const parserForLanguage: Record<string, ParserImplementation>;
export function loadLocation(readPowers: ReadFn | ReadPowers, moduleLocation: string, options?: ArchiveOptions | undefined): Promise<Application>;
export function importLocation(readPowers: ReadFn | ReadPowers, moduleLocation: string, options?: (ExecuteOptions & ArchiveOptions) | undefined): Promise<import('./types.js').SomeObject>;
import type { ParserImplementation } from './types.js';
export function importLocation(readPowers: ReadFn | ReadPowers, moduleLocation: string, options?: (ExecuteOptions & ArchiveOptions) | undefined): Promise<import("./types.js").SomeObject>;
import type { ReadFn } from './types.js';

@@ -7,0 +4,0 @@ import type { ReadPowers } from './types.js';

@@ -0,34 +1,38 @@

/* Provides functions for evaluating a module and its transitive
* dependencies given the URL of the entry module and assuming packages
* laid out according to the `node_modules` conventions.
*
* To import modules according to any other convention, use `import-lite.js`
* and provide a compartment map with a custom analog to `mapNodeModules` from
* `node-modules.js`.
*
* The default `parserForLanguage` is `import-parsers.js`, which is suitable
* for most cases.
*/
// @ts-check
/* eslint no-shadow: "off" */
import { defaultParserForLanguage } from './import-parsers.js';
import { mapNodeModules } from './node-modules.js';
import { loadFromMap } from './import-lite.js';
const { assign, create, freeze } = Object;
/** @import {Application} from './types.js' */
/** @import {ArchiveOptions} from './types.js' */
/** @import {ExecuteFn} from './types.js' */
/** @import {ExecuteOptions} from './types.js' */
/** @import {ParserImplementation} from './types.js' */
/** @import {ReadFn} from './types.js' */
/** @import {ReadPowers} from './types.js' */
import { compartmentMapForNodeModules } from './node-modules.js';
import { search } from './search.js';
import { link } from './link.js';
import {
exitModuleImportHookMaker,
makeImportHookMaker,
} from './import-hook.js';
import parserJson from './parse-json.js';
import parserText from './parse-text.js';
import parserBytes from './parse-bytes.js';
import parserCjs from './parse-cjs.js';
import parserMjs from './parse-mjs.js';
import { parseLocatedJson } from './json.js';
import { unpackReadPowers } from './powers.js';
/** @type {Record<string, ParserImplementation>} */
export const parserForLanguage = {
mjs: parserMjs,
cjs: parserCjs,
json: parserJson,
text: parserText,
bytes: parserBytes,
/**
* Add the default parserForLanguage option.
* @param {ArchiveOptions} [options]
* @returns {ArchiveOptions}
*/
const assignParserForLanguage = (options = {}) => {
const { parserForLanguage: parserForLanguageOption, ...rest } = options;
const parserForLanguage = freeze(
assign(create(null), defaultParserForLanguage, parserForLanguageOption),
);
return { ...rest, parserForLanguage };
};

@@ -42,72 +46,19 @@

*/
export const loadLocation = async (readPowers, moduleLocation, options) => {
const {
moduleTransforms = {},
dev = false,
tags = new Set(),
searchSuffixes = undefined,
commonDependencies = undefined,
export const loadLocation = async (
readPowers,
moduleLocation,
options = {},
) => {
const { dev, tags, conditions = tags, commonDependencies, policy } = options;
const compartmentMap = await mapNodeModules(readPowers, moduleLocation, {
dev,
conditions,
commonDependencies,
policy,
} = options || {};
const { read } = unpackReadPowers(readPowers);
const {
packageLocation,
packageDescriptorText,
packageDescriptorLocation,
moduleSpecifier,
} = await search(read, moduleLocation);
const packageDescriptor = parseLocatedJson(
packageDescriptorText,
packageDescriptorLocation,
);
const compartmentMap = await compartmentMapForNodeModules(
});
return loadFromMap(
readPowers,
packageLocation,
tags,
packageDescriptor,
moduleSpecifier,
{ dev, commonDependencies, policy },
compartmentMap,
assignParserForLanguage(options),
);
/** @type {ExecuteFn} */
const execute = async (options = {}) => {
const {
globals,
modules,
transforms,
__shimTransforms__,
Compartment,
importHook: exitModuleImportHook,
} = options;
const compartmentExitModuleImportHook = exitModuleImportHookMaker({
modules,
exitModuleImportHook,
});
const makeImportHook = makeImportHookMaker(readPowers, packageLocation, {
compartmentDescriptors: compartmentMap.compartments,
searchSuffixes,
archiveOnly: false,
entryCompartmentName: packageLocation,
entryModuleSpecifier: moduleSpecifier,
exitModuleImportHook: compartmentExitModuleImportHook,
});
const { compartment, pendingJobsPromise } = link(compartmentMap, {
makeImportHook,
parserForLanguage,
globals,
transforms,
moduleTransforms,
__shimTransforms__,
Compartment,
});
await pendingJobsPromise;
return compartment.import(moduleSpecifier);
};
return { import: execute };
};

@@ -122,9 +73,5 @@

*/
export const importLocation = async (
readPowers,
moduleLocation,
options = {},
) => {
export const importLocation = async (readPowers, moduleLocation, options) => {
const application = await loadLocation(readPowers, moduleLocation, options);
return application.import(options);
};

@@ -5,6 +5,6 @@ export function inferExportsEntries({ main, module, exports }: {

exports?: object;
}, tags: Set<string>, types: Record<string, Language>): Generator<string[], void, any>;
export function inferExports(descriptor: object, tags: Set<string>, types: Record<string, Language>): Record<string, string>;
export function inferExportsAndAliases(descriptor: any, externalAliases: any, internalAliases: any, tags: any, types: any): void;
import type { Language } from './types.js';
}, conditions: Set<string>, types: LanguageForExtension): Generator<string[], void, any>;
export function inferExports(descriptor: object, conditions: Set<string>, types: LanguageForExtension): Record<string, string>;
export function inferExportsAndAliases(descriptor: any, externalAliases: any, internalAliases: any, conditions: any, types: any): void;
import type { LanguageForExtension } from './types.js';
//# sourceMappingURL=infer-exports.d.ts.map

@@ -0,4 +1,11 @@

/* Provides functions needed by `node-modules.js` for building
* inter-compartment linkage according to the specifications in a
* `package.json` as laid out in the `node_modules` convention.
* These functions implement the behavior for a package's `"main"`,
* `"browser"`, `"imports"`, and `"exports"` properties in a `package.json`.
*/
// @ts-check
/** @import {Language} from './types.js' */
/** @import {LanguageForExtension} from './types.js' */

@@ -53,3 +60,3 @@ import { join, relativize } from './node-module-specifier.js';

* @param {object} exports - the `exports` field from a package.json.
* @param {Set<string>} tags - build tags about the target environment
* @param {Set<string>} conditions - build conditions about the target environment
* for selecting relevant exports, e.g., "browser" or "node".

@@ -59,6 +66,6 @@ * @yields {[string, string]}

*/
function* interpretExports(name, exports, tags) {
function* interpretExports(name, exports, conditions) {
if (isArray(exports)) {
for (const section of exports) {
const results = [...interpretExports(name, section, tags)];
const results = [...interpretExports(name, section, conditions)];
if (results.length > 0) {

@@ -82,8 +89,10 @@ yield* results;

if (name === '.') {
yield* interpretExports(key, value, tags);
yield* interpretExports(key, value, conditions);
} else {
yield* interpretExports(join(name, key), value, tags);
yield* interpretExports(join(name, key), value, conditions);
}
} else if (tags.has(key)) {
yield* interpretExports(name, value, tags);
} else if (conditions.has(key)) {
yield* interpretExports(name, value, conditions);
// Take only the first matching tag.
break;
}

@@ -107,5 +116,5 @@ }

* @param {object} [packageDescriptor.exports]
* @param {Set<string>} tags - build tags about the target environment
* @param {Set<string>} conditions - build conditions about the target environment
* for selecting relevant exports, e.g., "browser" or "node".
* @param {Record<string, Language>} types - an object to populate
* @param {LanguageForExtension} types - an object to populate
* with any recognized module's type, if implied by a tag.

@@ -116,3 +125,3 @@ * @yields {[string, string]}

{ main, module, exports },
tags,
conditions,
types,

@@ -122,3 +131,3 @@ ) {

// entries.
if (module !== undefined && tags.has('import')) {
if (module !== undefined && conditions.has('import')) {
// In this one case, the key "module" has carried a hint that the

@@ -135,3 +144,3 @@ // referenced module is an ECMASCript module, and that hint may be

if (exports !== undefined) {
yield* interpretExports('.', exports, tags);
yield* interpretExports('.', exports, conditions);
}

@@ -152,10 +161,10 @@ // TODO Otherwise, glob 'files' for all '.js', '.cjs', and '.mjs' entry

* @param {object} descriptor - the parsed body of a package.json file.
* @param {Set<string>} tags - build tags about the target environment
* @param {Set<string>} conditions - build conditions about the target environment
* for selecting relevant exports, e.g., "browser" or "node".
* @param {Record<string, Language>} types - an object to populate
* @param {LanguageForExtension} types - an object to populate
* with any recognized module's type, if implied by a tag.
* @returns {Record<string, string>}
*/
export const inferExports = (descriptor, tags, types) =>
fromEntries(inferExportsEntries(descriptor, tags, types));
export const inferExports = (descriptor, conditions, types) =>
fromEntries(inferExportsEntries(descriptor, conditions, types));

@@ -166,3 +175,3 @@ export const inferExportsAndAliases = (

internalAliases,
tags,
conditions,
types,

@@ -175,3 +184,3 @@ ) => {

externalAliases,
fromEntries(inferExportsEntries(descriptor, tags, types)),
fromEntries(inferExportsEntries(descriptor, conditions, types)),
);

@@ -192,3 +201,3 @@

// if present, allow "browser" field to populate moduleMap
if (tags.has('browser') && browser !== undefined) {
if (conditions.has('browser') && browser !== undefined) {
for (const [specifier, target] of interpretBrowserField(

@@ -195,0 +204,0 @@ name,

@@ -0,1 +1,2 @@

/* Annotates JSON parse exceptions with the location of the source. */
// @ts-check

@@ -2,0 +3,0 @@

@@ -1,3 +0,3 @@

export function mapParsers(languageForExtension: Record<string, Language>, languageForModuleSpecifier: Record<string, string>, parserForLanguage: Record<string, ParserImplementation>, moduleTransforms?: ModuleTransforms): ParseFn;
export function link({ entry, compartments: compartmentDescriptors }: CompartmentMapDescriptor, { resolve, makeImportHook, parserForLanguage, globals, transforms, moduleTransforms, __shimTransforms__, archiveOnly, Compartment, }: LinkOptions): {
export function mapParsers(languageForExtension: LanguageForExtension, languageForModuleSpecifier: Record<string, string>, parserForLanguage: ParserForLanguage, moduleTransforms?: ModuleTransforms): ParseFn;
export function link({ entry, compartments: compartmentDescriptors }: CompartmentMapDescriptor, { resolve, makeImportHook, parserForLanguage: parserForLanguageOption, languageForExtension: languageForExtensionOption, globals, transforms, moduleTransforms, __shimTransforms__, archiveOnly, Compartment, }: LinkOptions): {
compartment: Compartment;

@@ -9,4 +9,4 @@ compartments: Record<string, Compartment>;

export function assemble(compartmentMap: CompartmentMapDescriptor, options: LinkOptions): Compartment;
import type { Language } from './types.js';
import type { ParserImplementation } from './types.js';
import type { LanguageForExtension } from './types.js';
import type { ParserForLanguage } from './types.js';
import type { ModuleTransforms } from './types.js';

@@ -13,0 +13,0 @@ import type { ParseFn } from './types.js';

@@ -0,10 +1,17 @@

/* Provides the linking behavior shared by all Compartment Mapper workflows.
* This involves creating and configuring compartments according to the
* specifications in a compartment map, and is suitable for compartment maps
* that just outline the locations of compartments and their inter-linkage and
* also compartment maps that include every module descriptor in the transitive
* dependencies of their entry module.
*/
// @ts-check
/** @import {ModuleMapHook} from 'ses' */
/** @import {ResolveHook} from 'ses' */
/** @import {ParseFn} from './types.js' */
/** @import {ParseFn, ParserForLanguage} from './types.js' */
/** @import {ParserImplementation} from './types.js' */
/** @import {ShouldDeferError} from './types.js' */
/** @import {ModuleTransforms} from './types.js' */
/** @import {Language} from './types.js' */
/** @import {LanguageForExtension} from './types.js' */
/** @import {ModuleDescriptor} from './types.js' */

@@ -25,3 +32,3 @@ /** @import {CompartmentDescriptor} from './types.js' */

const { entries, fromEntries } = Object;
const { assign, create, entries, freeze, fromEntries } = Object;
const { hasOwnProperty } = Object.prototype;

@@ -70,3 +77,3 @@ const { apply } = Reflect;

* from its extension.
* @param {Record<string, ParserImplementation>} parserForLanguage
* @param {ParserForLanguage} parserForLanguage
* @param {ModuleTransforms} moduleTransforms

@@ -82,2 +89,3 @@ * @returns {ParseFn}

return async (bytes, specifier, location, packageLocation, options) => {
await null;
let language;

@@ -130,3 +138,5 @@ const extension = parseExtension(location);

}
const { parse } = parserForLanguage[language];
const { parse } = /** @type {ParserImplementation} */ (
parserForLanguage[language]
);
return parse(bytes, specifier, location, packageLocation, {

@@ -140,6 +150,6 @@ sourceMap,

/**
* @param {Record<string, Language>} languageForExtension
* @param {LanguageForExtension} languageForExtension
* @param {Record<string, string>} languageForModuleSpecifier - In a rare case, the type of a module
* is implied by package.json and should not be inferred from its extension.
* @param {Record<string, ParserImplementation>} parserForLanguage
* @param {ParserForLanguage} parserForLanguage
* @param {ModuleTransforms} moduleTransforms

@@ -257,3 +267,6 @@ * @returns {ParseFn}

}
return foreignCompartment.module(foreignModuleSpecifier);
return {
compartment: foreignCompartment,
namespace: foreignModuleSpecifier,
};
}

@@ -309,3 +322,6 @@ }

};
return foreignCompartment.module(foreignModuleSpecifier);
return {
compartment: foreignCompartment,
namespace: foreignModuleSpecifier,
};
}

@@ -342,3 +358,4 @@ }

makeImportHook,
parserForLanguage,
parserForLanguage: parserForLanguageOption = {},
languageForExtension: languageForExtensionOption = {},
globals = {},

@@ -355,3 +372,3 @@ transforms = [],

/** @type {Record<string, Compartment>} */
const compartments = Object.create(null);
const compartments = create(null);

@@ -368,12 +385,22 @@ /**

/** @type {LanguageForExtension} */
const defaultLanguageForExtension = freeze(
assign(create(null), languageForExtensionOption),
);
/** @type {ParserForLanguage} */
const parserForLanguage = freeze(
assign(create(null), parserForLanguageOption),
);
for (const [compartmentName, compartmentDescriptor] of entries(
compartmentDescriptors,
)) {
// TODO: The default assignments seem to break type inference
const {
location,
name,
modules = Object.create(null),
parsers: languageForExtension = Object.create(null),
types: languageForModuleSpecifier = Object.create(null),
scopes = Object.create(null),
modules = create(null),
parsers: languageForExtensionOverrides = {},
types: languageForModuleSpecifierOverrides = {},
scopes = create(null),
} = compartmentDescriptor;

@@ -385,2 +412,15 @@

/** @type {Record<string, string>} */
const languageForModuleSpecifier = freeze(
assign(create(null), languageForModuleSpecifierOverrides),
);
/** @type {LanguageForExtension} */
const languageForExtension = freeze(
assign(
create(null),
defaultLanguageForExtension,
languageForExtensionOverrides,
),
);
const parse = mapParsers(

@@ -395,3 +435,4 @@ languageForExtension,

if (language && has(parserForLanguage, language)) {
return parserForLanguage[language].heuristicImports;
return /** @type {ParserImplementation} */ (parserForLanguage[language])
.heuristicImports;
} else {

@@ -423,3 +464,4 @@ // If language is undefined or there's no parser, the error we could consider deferring is surely related to

const compartment = new Compartment(Object.create(null), undefined, {
const compartment = new Compartment({
name: location,
resolveHook,

@@ -430,3 +472,3 @@ importHook,

__shimTransforms__,
name: location,
__options__: true,
});

@@ -485,4 +527,5 @@

* @param {LinkOptions} options
* @deprecated Use {@link link}.
*/
export const assemble = (compartmentMap, options) =>
link(compartmentMap, options).compartment;

@@ -0,1 +1,6 @@

/* Provides functions for interacting with Node.js module specifiers in
* their canonical form.
* This is a kind of path math that is platform-agnostic.
*/
// @ts-check

@@ -2,0 +7,0 @@

@@ -1,2 +0,2 @@

export function compartmentMapForNodeModules(readPowers: any, packageLocation: string, tags: Set<string>, packageDescriptor: object, moduleSpecifier: string, options?: {
export function compartmentMapForNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers, packageLocation: string, conditions: Set<string>, packageDescriptor: object, moduleSpecifier: string, options?: {
dev?: boolean | undefined;

@@ -6,2 +6,9 @@ commonDependencies?: object;

} | undefined): Promise<CompartmentMapDescriptor>;
export function mapNodeModules(readPowers: ReadFn | ReadPowers | MaybeReadPowers, moduleLocation: string, options?: {
tags?: Set<string> | undefined;
conditions?: Set<string> | undefined;
dev?: boolean | undefined;
commonDependencies?: object;
policy?: object;
} | undefined): Promise<CompartmentMapDescriptor>;
/**

@@ -31,3 +38,3 @@ * The graph is an intermediate object model that the functions of this module

*/
parsers: Record<string, Language>;
parsers: LanguageForExtension;
/**

@@ -44,4 +51,8 @@ * - the parser for specific

export type ReadDescriptorFn = (packageLocation: string) => Promise<object>;
import type { ReadFn } from './types.js';
import type { ReadPowers } from './types.js';
import type { MaybeReadPowers } from './types.js';
import type { CompartmentMapDescriptor } from './types.js';
import type { LanguageForExtension } from './types.js';
import type { Language } from './types.js';
//# sourceMappingURL=node-modules.d.ts.map

@@ -0,14 +1,26 @@

/* Provides functions for constructing a compartment map that has a compartment
* descriptor corresponding to every reachable package from an entry module and
* how to create links between them.
* The resulting compartment map does not describe individual modules but does
* capture every usable route between packages including those generalized by
* wildcard expansion.
* See {@link link} to expand a compartment map to capture module descriptors
* for transitive dependencies.
*/
// @ts-check
/* eslint no-shadow: 0 */
/** @import {CanonicalFn} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {CompartmentMapDescriptor} from './types.js' */
/** @import {Language} from './types.js' */
/** @import {ReadFn} from './types.js' */
/** @import {LanguageForExtension} from './types.js' */
/** @import {MaybeReadFn} from './types.js' */
/** @import {CanonicalFn} from './types.js' */
/** @import {CompartmentMapDescriptor} from './types.js' */
/** @import {MaybeReadPowers} from './types.js' */
/** @import {ModuleDescriptor} from './types.js' */
/** @import {ReadFn} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {ScopeDescriptor} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {MaybeReadPowers} from './types.js' */
/** @import {SomePackagePolicy} from './types.js' */

@@ -35,3 +47,3 @@ /**

* location in storage.
* @property {Record<string, Language>} parsers - the parser for
* @property {LanguageForExtension} parsers - the parser for
* modules based on their extension.

@@ -57,3 +69,3 @@ * @property {Record<string, Language>} types - the parser for specific

import { unpackReadPowers } from './powers.js';
import { searchDescriptor } from './search.js';
import { search, searchDescriptor } from './search.js';

@@ -145,2 +157,3 @@ const { assign, create, keys, values } = Object;

const findPackage = async (readDescriptor, canonical, directory, name) => {
await null;
for (;;) {

@@ -175,4 +188,10 @@ // eslint-disable-next-line no-await-in-loop

const languages = ['mjs', 'cjs', 'json', 'text', 'bytes'];
const uncontroversialParsers = {
const defaultLanguages = /** @type {const} */ ([
'mjs',
'cjs',
'json',
'text',
'bytes',
]);
const defaultUncontroversialParsers = /** @type {const} */ ({
cjs: 'cjs',

@@ -183,5 +202,11 @@ mjs: 'mjs',

bytes: 'bytes',
};
const commonParsers = { js: 'cjs', ...uncontroversialParsers };
const moduleParsers = { js: 'mjs', ...uncontroversialParsers };
});
const defaultCommonParsers = /** @type {const} */ ({
js: 'cjs',
...defaultUncontroversialParsers,
});
const defaultModuleParsers = /** @type {const} */ ({
js: 'mjs',
...defaultUncontroversialParsers,
});

@@ -191,5 +216,19 @@ /**

* @param {string} location
* @param {object} [options]
* @param {readonly string[]|string[]} [options.languages]
* @param {Record<string, string>} [options.uncontroversialParsers]
* @param {Record<string, string>} [options.commonParsers]
* @param {Record<string, string>} [options.moduleParsers]
* @returns {Record<string, string>}
*/
const inferParsers = (descriptor, location) => {
const inferParsers = (
descriptor,
location,
{
languages = defaultLanguages,
uncontroversialParsers = defaultUncontroversialParsers,
commonParsers = defaultCommonParsers,
moduleParsers = defaultModuleParsers,
} = {},
) => {
const { type, module, parsers } = descriptor;

@@ -246,4 +285,4 @@ let additionalParsers = Object.create(null);

* @param {object} packageDetails.packageDescriptor
* @param {Set<string>} tags
* @param {boolean} dev
* @param {Set<string>} conditions
* @param {boolean | undefined} dev
* @param {CommonDependencyDescriptors} commonDependencyDescriptors

@@ -260,3 +299,3 @@ * @param {Map<string, Array<string>>} preferredPackageLogicalPathMap

{ packageLocation, packageDescriptor },
tags,
conditions,
dev,

@@ -314,3 +353,3 @@ commonDependencyDescriptors,

}
if (dev) {
if (dev !== undefined && dev !== null ? dev : conditions.has('development')) {
assign(allDependencies, devDependencies);

@@ -332,3 +371,3 @@ }

name,
tags,
conditions,
preferredPackageLogicalPathMap,

@@ -362,3 +401,3 @@ childLogicalPath,

internalAliases,
tags,
conditions,
types,

@@ -428,3 +467,3 @@ );

* @param {string} name - name of the package of interest.
* @param {Set<string>} tags
* @param {Set<string>} conditions
* @param {Map<string, Array<string>>} preferredPackageLogicalPathMap

@@ -442,3 +481,3 @@ * @param {Array<string>} [childLogicalPath]

name,
tags,
conditions,
preferredPackageLogicalPathMap,

@@ -478,3 +517,3 @@ childLogicalPath = [],

dependency,
tags,
conditions,
false,

@@ -499,6 +538,6 @@ commonDependencyDescriptors,

* @param {string} packageLocation - location of the main package.
* @param {Set<string>} tags
* @param {Set<string>} conditions
* @param {object} mainPackageDescriptor - the parsed contents of the main
* package.json, which was already read when searching for the package.json.
* @param {boolean} dev - whether to use devDependencies from this package (and
* @param {boolean|undefined} dev - whether to use devDependencies from this package (and
* only this package).

@@ -511,3 +550,3 @@ * @param {Record<string,string>} [commonDependencies] - dependencies to be added to all packages

packageLocation,
tags,
conditions,
mainPackageDescriptor,

@@ -531,6 +570,6 @@ dev,

tags = new Set(tags || []);
tags.add('import');
tags.add('default');
tags.add('endo');
conditions = new Set(conditions || []);
conditions.add('import');
conditions.add('default');
conditions.add('endo');

@@ -570,3 +609,3 @@ if (packageDescriptor === undefined) {

},
tags,
conditions,
dev,

@@ -585,3 +624,3 @@ commonDependencyDescriptors,

* @param {Graph} graph
* @param {Set<string>} tags - build tags about the target environment
* @param {Set<string>} conditions - build conditions about the target environment
* for selecting relevant exports, e.g., "browser" or "node".

@@ -595,3 +634,3 @@ * @param {import('./types.js').Policy} [policy]

graph,
tags,
conditions,
policy,

@@ -707,3 +746,3 @@ ) => {

types,
policy: packagePolicy,
policy: /** @type {SomePackagePolicy} */ (packagePolicy),
};

@@ -713,3 +752,5 @@ }

return {
tags: [...tags],
// TODO graceful migration from tags to conditions
// https://github.com/endojs/endo/issues/2388
tags: [...conditions],
entry: {

@@ -726,3 +767,3 @@ compartment: entryPackageLocation,

* @param {string} packageLocation
* @param {Set<string>} tags
* @param {Set<string>} conditions
* @param {object} packageDescriptor

@@ -739,3 +780,3 @@ * @param {string} moduleSpecifier

packageLocation,
tags,
conditions,
packageDescriptor,

@@ -745,3 +786,3 @@ moduleSpecifier,

) => {
const { dev = false, commonDependencies, policy } = options;
const { dev = undefined, commonDependencies, policy } = options;
const { maybeRead, canonical } = unpackReadPowers(readPowers);

@@ -752,3 +793,3 @@ const graph = await graphPackages(

packageLocation,
tags,
conditions,
packageDescriptor,

@@ -779,3 +820,3 @@ dev,

graph,
tags,
conditions,
policy,

@@ -786,1 +827,47 @@ );

};
/**
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
* @param {string} moduleLocation
* @param {object} [options]
* @param {Set<string>} [options.tags] deprecated in favor of `conditions`
* @param {Set<string>} [options.conditions]
* @param {boolean} [options.dev]
* @param {object} [options.commonDependencies]
* @param {object} [options.policy]
* @returns {Promise<CompartmentMapDescriptor>}
*/
export const mapNodeModules = async (
readPowers,
moduleLocation,
options = {},
) => {
const {
tags = new Set(),
conditions = tags,
dev = undefined,
commonDependencies,
policy,
} = options;
const {
packageLocation,
packageDescriptorText,
packageDescriptorLocation,
moduleSpecifier,
} = await search(readPowers, moduleLocation);
const packageDescriptor = parseLocatedJson(
packageDescriptorText,
packageDescriptorLocation,
);
return compartmentMapForNodeModules(
readPowers,
packageLocation,
conditions,
packageDescriptor,
moduleSpecifier,
{ dev, commonDependencies, policy },
);
};

@@ -12,3 +12,3 @@ /**

export function makeReadPowers({ fs, url, crypto }: {
fs: typeof import('fs');
fs: typeof import("fs");
url?: typeof import("url") | undefined;

@@ -35,3 +35,3 @@ crypto?: typeof import("crypto") | undefined;

export function makeWritePowers({ fs, url }: {
fs: typeof import('fs');
fs: typeof import("fs");
url?: typeof import("url") | undefined;

@@ -41,4 +41,4 @@ }): {

};
export function makeNodeReadPowers(fs: typeof import('fs'), crypto?: typeof import("crypto") | undefined): ReadPowers;
export function makeNodeWritePowers(fs: typeof import('fs')): WritePowers;
export function makeNodeReadPowers(fs: typeof import("fs"), crypto?: typeof import("crypto") | undefined): ReadPowers;
export function makeNodeWritePowers(fs: typeof import("fs")): WritePowers;
import type { HashFn } from './types.js';

@@ -45,0 +45,0 @@ import type { ReadPowers } from './types.js';

@@ -0,1 +1,9 @@

/* Provides adapters for Compartment Mapper I/O to the corresponding Node.js
* implementations of those behaviors.
*
* The Compartment Mapper generalizes its I/O interface to allow for a wide
* variety of I/O providers, but especially for reading and writing from
* virtualized file systems like zip files.
*/
// @ts-check

@@ -99,2 +107,3 @@

const canonical = async location => {
await null;
try {

@@ -153,2 +162,3 @@ if (location.endsWith('/')) {

const write = async (location, data) => {
await null;
try {

@@ -155,0 +165,0 @@ return await fs.promises.writeFile(fileURLToPath(location), data);

/** @type {import('./types.js').ParseFn} */
export const parseArchiveCjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseArchiveCjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-archive-cjs.d.ts.map

@@ -0,1 +1,5 @@

/* Provides language behavior for analyzing, pre-compiling, and storing
* CommonJS modules for an archive.
*/
// @ts-check

@@ -2,0 +6,0 @@

/** @type {import('./types.js').ParseFn} */
export const parseArchiveMjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseArchiveMjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-archive-mjs.d.ts.map

@@ -0,4 +1,7 @@

/* Provides language behavior for analyzing, pre-compiling, and storing ESM
* modules for an archive.
*/
// @ts-check
import { StaticModuleRecord } from '@endo/static-module-record';
import { ModuleSource } from '@endo/module-source';

@@ -18,3 +21,3 @@ const textEncoder = new TextEncoder();

const source = textDecoder.decode(bytes);
const record = new StaticModuleRecord(source, {
const record = new ModuleSource(source, {
sourceMap,

@@ -21,0 +24,0 @@ sourceMapUrl: sourceUrl,

/** @type {import('./types.js').ParseFn} */
export const parseBytes: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseBytes: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-bytes.d.ts.map

@@ -0,1 +1,5 @@

/* Provides rudimentary support for treating an arbitrary file as a module that
* exports the bytes of that file.
*/
// @ts-check

@@ -2,0 +6,0 @@

@@ -1,2 +0,2 @@

export function getModulePaths(readPowers: ReadFn | ReadPowers | undefined, location: string): {
export function getModulePaths(readPowers: ReadPowers | ReadFn | undefined, location: string): {
filename: string | null;

@@ -19,4 +19,4 @@ dirname: string | null;

};
import type { ReadPowers } from './types.js';
import type { ReadFn } from './types.js';
import type { ReadPowers } from './types.js';
//# sourceMappingURL=parse-cjs-shared-export-wrapper.d.ts.map

@@ -0,1 +1,6 @@

/* Provides shared functionality for {@link parse-cjs.js} and {@link
* parse-archive-cjs.js} toward importing or archiving CommonJS as a virtual
* module source.
*/
// @ts-check

@@ -101,2 +106,4 @@

const redefined = new Set();
const originalExports = new Proxy(moduleEnvironmentRecord.default, {

@@ -120,2 +127,5 @@ set(_target, prop, value) {

defineProperty(target, prop, descriptor);
// Make a note to propagate the value from the getter to the module
// environment record when the module finishes executing.
redefined.add(prop);
return true;

@@ -176,5 +186,10 @@ },

for (const prop of keys(moduleEnvironmentRecord.default || {})) {
if (prop !== 'default')
if (prop !== 'default') {
moduleEnvironmentRecord[prop] = moduleEnvironmentRecord.default[prop];
}
}
} else {
for (const prop of redefined) {
moduleEnvironmentRecord[prop] = moduleEnvironmentRecord.default[prop];
}
}

@@ -181,0 +196,0 @@ };

/** @type {import('./types.js').ParseFn} */
export const parseCjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseCjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-cjs.d.ts.map

@@ -0,1 +1,5 @@

/* Provides language behavior (parser) for importing CommonJS as a virtual
* module source.
*/
// @ts-check

@@ -2,0 +6,0 @@

/** @type {import('./types.js').ParseFn} */
export const parseJson: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseJson: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-json.d.ts.map

@@ -0,1 +1,3 @@

/* Provides language support for importing JSON modules. */
// @ts-check

@@ -2,0 +4,0 @@

/** @type {import('./types.js').ParseFn} */
export const parseMjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseMjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-mjs.d.ts.map

@@ -0,4 +1,6 @@

/* Provides language behavior (a parser) for importing ESM. */
// @ts-check
import { StaticModuleRecord } from '@endo/static-module-record';
import { ModuleSource } from '@endo/module-source';

@@ -17,3 +19,3 @@ const textDecoder = new TextDecoder();

const source = textDecoder.decode(bytes);
const record = new StaticModuleRecord(source, {
const record = new ModuleSource(source, {
sourceUrl,

@@ -20,0 +22,0 @@ sourceMap,

/** @type {import('./types.js').ParseFn} */
export const parsePreCjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parsePreCjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-pre-cjs.d.ts.map

@@ -0,1 +1,7 @@

/* Provides language-specific behavior for importing pre-compiled CommonJS.
* Pre-compiled CommonJS is a module in JSON format that describes its imports,
* exports, and source to execute in the presence of `require`, `module`, and
* `exports`.
*/
// @ts-check

@@ -2,0 +8,0 @@

/** @type {import('./types.js').ParseFn} */
export const parsePreMjs: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parsePreMjs: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-pre-mjs.d.ts.map

@@ -0,1 +1,7 @@

/* Provides language-specific behaviors for importing pre-compiled ESM.
* Pre-compiling or translating ESM from a module to a script with a
* calling-convention is necessary to prepare an archive so that it can be
* imported by the SES shim without entraining a dependency on Babel.
*/
// @ts-check

@@ -2,0 +8,0 @@

/** @type {import('./types.js').ParseFn} */
export const parseText: import('./types.js').ParseFn;
declare const _default: import('./types.js').ParserImplementation;
export const parseText: import("./types.js").ParseFn;
declare const _default: import("./types.js").ParserImplementation;
export default _default;
//# sourceMappingURL=parse-text.d.ts.map

@@ -0,1 +1,6 @@

/* Provides language-behaviors for importing a module as a document that
* exports itself as a string based on a UTF-8 interpretation of the module's
* text.
*/
// @ts-check

@@ -2,0 +7,0 @@

@@ -1,7 +0,9 @@

export function policyLookupHelper(packagePolicy: import('./types.js').PackagePolicy, field: 'builtins' | 'globals' | 'packages', itemName: string): boolean | import('./types.js').AttenuationDefinition;
export function isAllowingEverything(policyValue: unknown): policyValue is import('./types.js').WildcardPolicy;
export function isAttenuationDefinition(allegedDefinition: unknown): allegedDefinition is import('./types.js').AttenuationDefinition;
export function getAttenuatorFromDefinition(attenuationDefinition: import('./types.js').AttenuationDefinition): import('./types.js').UnifiedAttenuationDefinition;
export function assertPackagePolicy(allegedPackagePolicy: unknown, path: string, url?: string | undefined): asserts allegedPackagePolicy is import('./types.js').PackagePolicy | undefined;
export function assertPolicy(allegedPolicy: unknown): asserts allegedPolicy is import('./types.js').Policy | undefined;
export function policyLookupHelper(packagePolicy: import("./types.js").PackagePolicy, field: "builtins" | "globals" | "packages", itemName: string): boolean | import("./types.js").AttenuationDefinition;
export function isAllowingEverything(policyValue: unknown): policyValue is import("./types.js").WildcardPolicy;
export function isAttenuationDefinition(allegedDefinition: unknown): allegedDefinition is import("./types.js").AttenuationDefinition;
export function getAttenuatorFromDefinition(attenuationDefinition: import("./types.js").AttenuationDefinition): import("./types.js").UnifiedAttenuationDefinition;
export function assertPackagePolicy(allegedPackagePolicy: unknown, path: string, url?: string | undefined): asserts allegedPackagePolicy is SomePackagePolicy | undefined;
export function assertPolicy(allegedPolicy: unknown): asserts allegedPolicy is SomePolicy | undefined;
import type { SomePackagePolicy } from './types.js';
import type { SomePolicy } from './types.js';
//# sourceMappingURL=policy-format.d.ts.map

@@ -0,3 +1,10 @@

/* Provides functions for enforcing compartment-map linkage and global variable
* policies for each compartment.
*/
// @ts-check
/** @import {SomePackagePolicy} from './types.js' */
/** @import {SomePolicy} from './types.js' */
const { entries, keys } = Object;

@@ -137,3 +144,3 @@ const { isArray } = Array;

* @param {string} [url] - URL of the policy file; used for error messages only
* @returns {asserts allegedPackagePolicy is import('./types.js').PackagePolicy|undefined}
* @returns {asserts allegedPackagePolicy is SomePackagePolicy|undefined}
*/

@@ -157,4 +164,6 @@ export const assertPackagePolicy = (allegedPackagePolicy, path, url) => {

defaultAttenuator: _ignore, // a carve out for the default attenuator in compartment map
// eslint-disable-next-line no-unused-vars
options, // any extra options
...extra
} = packagePolicy;
} = /** @type {SomePackagePolicy} */ (packagePolicy);

@@ -205,3 +214,3 @@ assert(

* @param {unknown} allegedPolicy - Alleged `Policy` to test
* @returns {asserts allegedPolicy is import('./types.js').Policy|undefined}
* @returns {asserts allegedPolicy is SomePolicy|undefined}
*/

@@ -208,0 +217,0 @@ export const assertPolicy = allegedPolicy => {

@@ -5,4 +5,4 @@ /**

export const ATTENUATORS_COMPARTMENT: "<ATTENUATORS>";
export function detectAttenuators(policy?: import("./types.js").Policy<void, void, void> | undefined): Array<string>;
export function dependencyAllowedByPolicy(namingKit: import('./types.js').PackageNamingKit, packagePolicy: import('./types.js').PackagePolicy): boolean;
export function detectAttenuators(policy?: import("./types.js").Policy<void, void, void, unknown> | undefined): Array<string>;
export function dependencyAllowedByPolicy(namingKit: import("./types.js").PackageNamingKit, packagePolicy: import("./types.js").PackagePolicy): boolean;
/**

@@ -16,3 +16,3 @@ * Returns the policy applicable to the canonicalName of the package

*/
export function getPolicyForPackage(namingKit: import('./types.js').PackageNamingKit, policy: import('./types.js').Policy): import('./types.js').PackagePolicy;
export function getPolicyForPackage(namingKit: import("./types.js").PackageNamingKit, policy: import("./types.js").Policy): import("./types.js").PackagePolicy;
/**

@@ -26,9 +26,9 @@ * Returns `undefined`

*/
export function getPolicyForPackage(namingKit: import('./types.js').PackageNamingKit, policy?: import("./types.js").Policy<void, void, void> | undefined): import('./types.js').PackagePolicy | undefined;
export function makeDeferredAttenuatorsProvider(compartments: Record<string, Compartment>, compartmentDescriptors: Record<string, import('./types.js').CompartmentDescriptor>): import('./types.js').DeferredAttenuatorsProvider;
export function attenuateGlobals(globalThis: object, globals: object, packagePolicy: import('./types.js').PackagePolicy, attenuators: import('./types.js').DeferredAttenuatorsProvider, pendingJobs: Array<Promise<any>>, name?: string): void;
export function enforceModulePolicy(specifier: string, compartmentDescriptor: import('./types.js').CompartmentDescriptor, { exit, errorHint }?: EnforceModulePolicyOptions | undefined): void;
export function attenuateModuleHook(specifier: string, originalModuleRecord: import('ses').ThirdPartyStaticModuleInterface, policy: import('./types.js').PackagePolicy, attenuators: import('./types.js').DeferredAttenuatorsProvider): Promise<import('ses').ThirdPartyStaticModuleInterface>;
export function getPolicyForPackage(namingKit: import("./types.js").PackageNamingKit, policy?: import("./types.js").Policy<void, void, void, unknown> | undefined): import("./types.js").PackagePolicy | undefined;
export function makeDeferredAttenuatorsProvider(compartments: Record<string, Compartment>, compartmentDescriptors: Record<string, import("./types.js").CompartmentDescriptor>): import("./types.js").DeferredAttenuatorsProvider;
export function attenuateGlobals(globalThis: object, globals: object, packagePolicy: import("./types.js").PackagePolicy, attenuators: import("./types.js").DeferredAttenuatorsProvider, pendingJobs: Array<Promise<any>>, name?: string): void;
export function enforceModulePolicy(specifier: string, compartmentDescriptor: import("./types.js").CompartmentDescriptor, { exit, errorHint }?: EnforceModulePolicyOptions | undefined): void;
export function attenuateModuleHook(specifier: string, originalModuleRecord: import("ses").ThirdPartyStaticModuleInterface, policy: import("./types.js").PackagePolicy, attenuators: import("./types.js").DeferredAttenuatorsProvider): Promise<import("ses").ThirdPartyStaticModuleInterface>;
/**
* Options for {@link enforceModulePolicy }
* Options for {@link enforceModulePolicy}
*/

@@ -35,0 +35,0 @@ export type EnforceModulePolicyOptions = {

@@ -0,1 +1,4 @@

/* Provides mechanisms for interacting with Compartment Map runtime policies.
*/
// @ts-check

@@ -2,0 +5,0 @@

@@ -1,2 +0,2 @@

export function unpackReadPowers(powers: import('./types.js').ReadFn | import('./types.js').ReadPowers | import('./types.js').MaybeReadPowers): import('./types.js').MaybeReadPowers;
export function unpackReadPowers(powers: import("./types.js").ReadFn | import("./types.js").ReadPowers | import("./types.js").MaybeReadPowers): import("./types.js").MaybeReadPowers;
//# sourceMappingURL=powers.d.ts.map

@@ -0,1 +1,8 @@

/* As the interface of the Compartment Mapper evolved, it became necessary to
* expand some function signatures that accepted a single power to one that
* accepted a powers object.
* This module provides functions for safely unpacking I/O capabilities and
* maintaining backward-compatibility with older accepted usage patterns.
*/
// @ts-check

@@ -2,0 +9,0 @@

@@ -1,2 +0,2 @@

export function searchDescriptor<T>(location: string, readDescriptor: (location: string) => Promise<T>): Promise<{
export function searchDescriptor<T>(location: string, maybeReadDescriptor: (location: string) => Promise<T | undefined>): Promise<{
data: T;

@@ -7,3 +7,3 @@ directory: string;

}>;
export function search(read: ReadFn, moduleLocation: string): Promise<{
export function search(readPowers: ReadFn | ReadPowers | MaybeReadPowers, moduleLocation: string): Promise<{
packageLocation: string;

@@ -15,2 +15,4 @@ packageDescriptorLocation: string;

import type { ReadFn } from './types.js';
import type { ReadPowers } from './types.js';
import type { MaybeReadPowers } from './types.js';
//# sourceMappingURL=search.d.ts.map

@@ -0,7 +1,14 @@

/* Provides the behavior for `node-modules.js` to find modules and packages
* according to the Node.js `node_modules` convention.
*/
// @ts-check
/** @import {ReadFn} from './types.js' */
/** @import {ReadPowers} from './types.js' */
/** @import {MaybeReadPowers} from './types.js' */
import { relativize } from './node-module-specifier.js';
import { relative } from './url.js';
import { unpackReadPowers } from './powers.js';

@@ -23,11 +30,12 @@ // q, as in quote, for enquoting strings in error messages.

* package.json.
* Probes by calling readDescriptor.
* Returns the result of readDescriptor as data whenever a value is returned.
* Probes by calling maybeReadDescriptor.
* Returns the result of maybeReadDescriptor as data whenever a value is returned.
*
* @template T
* @param {string} location
* @param {(location:string)=>Promise<T>} readDescriptor
* @param {(location:string)=>Promise<T|undefined>} maybeReadDescriptor
* @returns {Promise<{data:T, directory: string, location:string, packageDescriptorLocation: string}>}
*/
export const searchDescriptor = async (location, readDescriptor) => {
export const searchDescriptor = async (location, maybeReadDescriptor) => {
await null;
let directory = resolveLocation('./', location);

@@ -40,5 +48,3 @@ for (;;) {

// eslint-disable-next-line no-await-in-loop
const data = await readDescriptor(packageDescriptorLocation).catch(
() => undefined,
);
const data = await maybeReadDescriptor(packageDescriptorLocation);
if (data !== undefined) {

@@ -61,14 +67,13 @@ return {

/**
* @param {ReadFn} read
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
* @param {string} packageDescriptorLocation
* @returns {Promise<string | undefined>}
*/
const readDescriptorDefault = async (
read,
const maybeReadDescriptorDefault = async (
readPowers,
packageDescriptorLocation,
// eslint-disable-next-line consistent-return
) => {
const packageDescriptorBytes = await read(packageDescriptorLocation).catch(
() => undefined,
);
const { maybeRead } = unpackReadPowers(readPowers);
const packageDescriptorBytes = await maybeRead(packageDescriptorLocation);
if (packageDescriptorBytes !== undefined) {

@@ -87,3 +92,3 @@ const packageDescriptorText = decoder.decode(packageDescriptorBytes);

*
* @param {ReadFn} read
* @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers
* @param {string} moduleLocation

@@ -97,6 +102,7 @@ * @returns {Promise<{

*/
export const search = async (read, moduleLocation) => {
export const search = async (readPowers, moduleLocation) => {
const { maybeRead } = unpackReadPowers(readPowers);
const { data, directory, location, packageDescriptorLocation } =
await searchDescriptor(moduleLocation, loc =>
readDescriptorDefault(read, loc),
maybeReadDescriptorDefault(maybeRead, loc),
);

@@ -103,0 +109,0 @@

@@ -48,11 +48,11 @@ /**

*/
parsers: Record<string, Language>;
parsers: LanguageForExtension;
/**
* - language for module specifier
*/
types: Record<string, Language>;
types: LanguageForModuleSpecifier;
/**
* - policy specific to compartment
*/
policy: object;
policy: SomePackagePolicy;
};

@@ -86,3 +86,10 @@ /**

};
export type Language = 'mjs' | 'cjs' | 'json' | 'bytes' | 'text' | 'pre-mjs-json' | 'pre-cjs-json';
/**
* Natively-recognized and custom languages
*/
export type Language = LiteralUnion<BuiltinLanguage, string>;
/**
* Languages natively recognized by `compartment-mapper`
*/
export type BuiltinLanguage = "mjs" | "cjs" | "json" | "bytes" | "text" | "pre-mjs-json" | "pre-cjs-json";
export type ArchiveWriter = {

@@ -161,2 +168,3 @@ write: WriteFn;

readPowers?: ReadFn | ReadPowers | undefined;
compartmentDescriptor?: CompartmentDescriptor | undefined;
} | undefined) => Promise<{

@@ -166,3 +174,3 @@ bytes: Uint8Array;

record: FinalStaticModuleType;
sourceMap?: string | undefined;
sourceMap?: string;
}>;

@@ -179,3 +187,3 @@ /**

export type ExitModuleImportHook = (specifier: string) => Promise<ThirdPartyStaticModuleInterface | undefined>;
export type LoadArchiveOptions = {
export type ExtraLoadArchiveOptions = {
expectedSha512?: string | undefined;

@@ -186,3 +194,14 @@ modules?: Record<string, any> | undefined;

computeSourceMapLocation?: ComputeSourceMapLocationHook | undefined;
parserForLanguage?: ParserForLanguage | undefined;
languageForExtension?: LanguageForExtension | undefined;
};
/**
* Options for `loadArchive()`
*/
export type LoadArchiveOptions = ExecuteOptions & ExtraLoadArchiveOptions;
/**
* Set of options available in the context of code execution.
*
* May be used only as an intersection with other "options" types
*/
export type ExecuteOptions = {

@@ -197,10 +216,29 @@ globals?: object;

};
export type ParserForLanguage = Record<string, ParserImplementation>;
/**
* Mapping of {@link Language Languages} to {@link ParserImplementation ParserImplementations}
*/
export type ParserForLanguage = Record<Language | string, ParserImplementation>;
/**
* Mapping of file extension to {@link Language Languages}.
*/
export type LanguageForExtension = Record<string, Language>;
/**
* Mapping of module specifier to {@link Language Languages}.
*/
export type LanguageForModuleSpecifier = Record<string, Language>;
/**
* Options for `loadLocation()`
*/
export type LoadLocationOptions = ArchiveOptions;
export type ExtraLinkOptions = {
resolve?: ResolveHook | undefined;
makeImportHook: ImportHookMaker;
parserForLanguage: ParserForLanguage;
parserForLanguage?: ParserForLanguage | undefined;
languageForExtension?: LanguageForExtension | undefined;
moduleTransforms?: ModuleTransforms | undefined;
archiveOnly?: boolean | undefined;
};
/**
* Options for `link()`
*/
export type LinkOptions = ExecuteOptions & ExtraLinkOptions;

@@ -248,4 +286,8 @@ export type ModuleTransforms = Record<string, ModuleTransform>;

dev?: boolean | undefined;
policy?: object;
policy?: SomePolicy | undefined;
/**
* deprecated in favor of `conditions`
*/
tags?: Set<string> | undefined;
conditions?: Set<string> | undefined;
captureSourceLocation?: CaptureSourceLocationHook | undefined;

@@ -256,2 +298,4 @@ importHook?: ExitModuleImportHook | undefined;

sourceMapHook?: SourceMapHook | undefined;
parserForLanguage?: Record<string, ParserImplementation> | undefined;
languageForExtension?: LanguageForExtension | undefined;
};

@@ -286,3 +330,3 @@ export type PackageNamingKit = {

*/
export type AttenuationDefinition = FullAttenuationDefinition | [any, ...any[]];
export type AttenuationDefinition = FullAttenuationDefinition | ImplicitAttenuationDefinition;
export type UnifiedAttenuationDefinition = {

@@ -305,3 +349,3 @@ displayName: string;

*/
export type WildcardPolicy = 'any';
export type WildcardPolicy = "any";
/**

@@ -322,3 +366,3 @@ * A type representing a property policy, which is a record of string keys and boolean values.

*/
export type PackagePolicy<PackagePolicyItem = void, GlobalsPolicyItem = void, BuiltinsPolicyItem = void> = {
export type PackagePolicy<PackagePolicyItem = void, GlobalsPolicyItem = void, BuiltinsPolicyItem = void, ExtraOptions = unknown> = {
/**

@@ -344,2 +388,6 @@ * - The default attenuator.

noGlobalFreeze?: boolean | undefined;
/**
* - Any additional user-defined options can be added to the policy here
*/
options?: ExtraOptions | undefined;
};

@@ -349,7 +397,7 @@ /**

*/
export type Policy<PackagePolicyItem = void, GlobalsPolicyItem = void, BuiltinsPolicyItem = void> = {
export type Policy<PackagePolicyItem = void, GlobalsPolicyItem = void, BuiltinsPolicyItem = void, ExtraOptions = unknown> = {
/**
* - The package policies for the resources.
*/
resources: Record<string, PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem>>;
resources: Record<string, PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem, ExtraOptions>>;
/**

@@ -362,3 +410,3 @@ * - The default attenuator.

*/
entry?: PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem> | undefined;
entry?: PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem, ExtraOptions> | undefined;
};

@@ -369,2 +417,60 @@ /**

export type SomeObject = Record<PropertyKey, any>;
/**
* Any {@link PackagePolicy}
*/
export type SomePackagePolicy = PackagePolicy<any, any, any, any>;
/**
* Any {@link Policy}
*/
export type SomePolicy = Policy<any, any, any, any>;
/**
* Matches any {@link https://developer.mozilla.org/en-US/docs/Glossary/Primitive primitive value}.
*/
export type Primitive = null | undefined | string | number | boolean | symbol | bigint;
/**
* Allows creating a union type by combining primitive types and literal
* types without sacrificing auto-completion in IDEs for the literal type part
* of the union.
*
* Currently, when a union type of a primitive type is combined with literal types,
* TypeScript loses all information about the combined literals. Thus, when such
* a type is used in an IDE with autocompletion, no suggestions are made for the
* declared literals.
*
* This type is a workaround for {@link https://github.com/Microsoft/TypeScript/issues/29729 Microsoft/TypeScript#29729}.
* It will be removed as soon as it's not needed anymore.
*/
export type LiteralUnion<LiteralType, PrimitiveType extends Primitive> = LiteralType | (PrimitiveType & Record<never, never>);
/**
* Options for `importLocation()`
*/
export type ImportLocationOptions = ExecuteOptions & ArchiveOptions;
/**
* Options for `captureFromMap()`
*/
export type CaptureOptions = {
moduleTransforms?: ModuleTransforms | undefined;
modules?: Record<string, any> | undefined;
dev?: boolean | undefined;
policy?: SomePolicy | undefined;
/**
* deprecated in favor of `conditions`
*/
tags?: Set<string> | undefined;
conditions?: Set<string> | undefined;
importHook?: ExitModuleImportHook | undefined;
searchSuffixes?: string[] | undefined;
commonDependencies?: Record<string, string> | undefined;
sourceMapHook?: SourceMapHook | undefined;
parserForLanguage?: Record<string, ParserImplementation> | undefined;
languageForExtension?: LanguageForExtension | undefined;
};
/**
* The result of `captureFromMap()`
*/
export type CaptureResult = {
captureCompartmentMap: CompartmentMapDescriptor;
captureSources: Sources;
compartmentRenames: Record<string, string>;
};
import type { ImportHook } from 'ses';

@@ -371,0 +477,0 @@ import type { FinalStaticModuleType } from 'ses';

// @ts-check
/// <reference types="ses"/>

@@ -7,5 +6,5 @@ export {};

/** @import {FinalStaticModuleType} from 'ses' */
/** @import {ThirdPartyStaticModuleInterface} from 'ses' */
/** @import {ImportHook} from 'ses' */
/** @import {StaticModuleType} from 'ses' */
/** @import {ThirdPartyStaticModuleInterface} from 'ses' */
/** @import {Transform} from 'ses' */

@@ -54,5 +53,5 @@

* @property {Record<string, ScopeDescriptor>} scopes
* @property {Record<string, Language>} parsers - language for extension
* @property {Record<string, Language>} types - language for module specifier
* @property {object} policy - policy specific to compartment
* @property {LanguageForExtension} parsers - language for extension
* @property {LanguageForModuleSpecifier} types - language for module specifier
* @property {SomePackagePolicy} policy - policy specific to compartment
*/

@@ -87,5 +86,13 @@

/**
* @typedef {'mjs' | 'cjs' | 'json' | 'bytes' | 'text' | 'pre-mjs-json' | 'pre-cjs-json'} Language
* Natively-recognized and custom languages
*
* @typedef {LiteralUnion<BuiltinLanguage, string>} Language
*/
/**
* Languages natively recognized by `compartment-mapper`
*
* @typedef {'mjs' | 'cjs' | 'json' | 'bytes' | 'text' | 'pre-mjs-json' | 'pre-cjs-json'} BuiltinLanguage
*/
// /////////////////////////////////////////////////////////////////////////////

@@ -259,2 +266,3 @@

* @param {ReadFn | ReadPowers} [options.readPowers]
* @param {CompartmentDescriptor} [options.compartmentDescriptor]
* @returns {Promise<{

@@ -291,3 +299,4 @@ * bytes: Uint8Array,

/**
* @typedef {object} LoadArchiveOptions
* @see {@link LoadArchiveOptions}
* @typedef {object} ExtraLoadArchiveOptions
* @property {string} [expectedSha512]

@@ -298,5 +307,17 @@ * @property {Record<string, any>} [modules]

* @property {ComputeSourceMapLocationHook} [computeSourceMapLocation]
* @property {ParserForLanguage} [parserForLanguage]
* @property {LanguageForExtension} [languageForExtension]
*/
/**
* Options for `loadArchive()`
*
* @typedef {ExecuteOptions & ExtraLoadArchiveOptions} LoadArchiveOptions
*/
/**
* Set of options available in the context of code execution.
*
* May be used only as an intersection with other "options" types
*
* @typedef {object} ExecuteOptions

@@ -313,10 +334,32 @@ * @property {object} [globals]

/**
* @typedef {Record<string, ParserImplementation>} ParserForLanguage
* Mapping of {@link Language Languages} to {@link ParserImplementation ParserImplementations}
*
* @typedef {Record<Language | string, ParserImplementation>} ParserForLanguage
*/
/**
* Mapping of file extension to {@link Language Languages}.
*
* @typedef {Record<string, Language>} LanguageForExtension
*/
/**
* Mapping of module specifier to {@link Language Languages}.
*
* @typedef {Record<string, Language>} LanguageForModuleSpecifier
*/
/**
* Options for `loadLocation()`
*
* @typedef {ArchiveOptions} LoadLocationOptions
*/
/**
* @see {@link LinkOptions}
* @typedef {object} ExtraLinkOptions
* @property {ResolveHook} [resolve]
* @property {ImportHookMaker} makeImportHook
* @property {ParserForLanguage} parserForLanguage
* @property {ParserForLanguage} [parserForLanguage]
* @property {LanguageForExtension} [languageForExtension]
* @property {ModuleTransforms} [moduleTransforms]

@@ -327,2 +370,4 @@ * @property {boolean} [archiveOnly]

/**
* Options for `link()`
*
* @typedef {ExecuteOptions & ExtraLinkOptions} LinkOptions

@@ -389,4 +434,5 @@ */

* @property {boolean} [dev]
* @property {object} [policy]
* @property {Set<string>} [tags]
* @property {SomePolicy} [policy]
* @property {Set<string>} [tags] deprecated in favor of `conditions`
* @property {Set<string>} [conditions]
* @property {CaptureSourceLocationHook} [captureSourceLocation]

@@ -397,2 +443,4 @@ * @property {ExitModuleImportHook} [importHook]

* @property {SourceMapHook} [sourceMapHook]
* @property {Record<string, ParserImplementation>} [parserForLanguage]
* @property {LanguageForExtension} [languageForExtension]
*/

@@ -491,5 +539,7 @@

* An object representing a base package policy.
* @template [PackagePolicyItem=void]
* @template [GlobalsPolicyItem=void]
* @template [BuiltinsPolicyItem=void]
*
* @template [PackagePolicyItem=void] Additional types for a package policy item
* @template [GlobalsPolicyItem=void] Additional types for a global policy item
* @template [BuiltinsPolicyItem=void] Additional types for a builtin policy item
* @template [ExtraOptions=unknown] Additional options
* @typedef {object} PackagePolicy

@@ -501,2 +551,3 @@ * @property {string} [defaultAttenuator] - The default attenuator.

* @property {boolean} [noGlobalFreeze] - Whether to disable global freeze.
* @property {ExtraOptions} [options] - Any additional user-defined options can be added to the policy here
*/

@@ -506,9 +557,11 @@

* An object representing a base policy.
* @template [PackagePolicyItem=void]
* @template [GlobalsPolicyItem=void]
* @template [BuiltinsPolicyItem=void]
*
* @template [PackagePolicyItem=void] Additional types for a package policy item
* @template [GlobalsPolicyItem=void] Additional types for a global policy item
* @template [BuiltinsPolicyItem=void] Additional types for a builtin policy item
* @template [ExtraOptions=unknown] Additional package-level options
* @typedef {object} Policy
* @property {Record<string, PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem>>} resources - The package policies for the resources.
* @property {Record<string, PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem, ExtraOptions>>} resources - The package policies for the resources.
* @property {string} [defaultAttenuator] - The default attenuator.
* @property {PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem>} [entry] - The package policy for the entry.
* @property {PackagePolicy<PackagePolicyItem, GlobalsPolicyItem, BuiltinsPolicyItem, ExtraOptions>} [entry] - The package policy for the entry.
*/

@@ -520,1 +573,90 @@

*/
/**
* Any {@link PackagePolicy}
*
* @typedef {PackagePolicy<any, any, any, any>} SomePackagePolicy
*/
/**
* Any {@link Policy}
*
* @typedef {Policy<any, any, any, any>} SomePolicy
*/
/**
* Matches any {@link https://developer.mozilla.org/en-US/docs/Glossary/Primitive primitive value}.
*
* @typedef {null|undefined|string|number|boolean|symbol|bigint} Primitive
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/primitive.d.ts original source}
*/
/**
* Allows creating a union type by combining primitive types and literal
* types without sacrificing auto-completion in IDEs for the literal type part
* of the union.
*
* Currently, when a union type of a primitive type is combined with literal types,
* TypeScript loses all information about the combined literals. Thus, when such
* a type is used in an IDE with autocompletion, no suggestions are made for the
* declared literals.
*
* This type is a workaround for {@link https://github.com/Microsoft/TypeScript/issues/29729 Microsoft/TypeScript#29729}.
* It will be removed as soon as it's not needed anymore.
*
*
* @see {@link https://github.com/sindresorhus/type-fest/blob/main/source/literal-union.d.ts original source}
* @template LiteralType The literal type
* @template {Primitive} PrimitiveType The primitive type
* @typedef {LiteralType | (PrimitiveType & Record<never, never>)} LiteralUnion
* @example
* ```ts
* // Before
*
* type Pet = 'dog' | 'cat' | string;
*
* const pet: Pet = '';
* // Start typing in your TypeScript-enabled IDE.
* // You **will not** get auto-completion for `dog` and `cat` literals.
*
* // After
*
* type Pet2 = LiteralUnion<'dog' | 'cat', string>;
*
* const pet: Pet2 = '';
* // You **will** get auto-completion for `dog` and `cat` literals.
* ```
*/
/**
* Options for `importLocation()`
*
* @typedef {ExecuteOptions & ArchiveOptions} ImportLocationOptions
*/
/**
* Options for `captureFromMap()`
*
* @typedef CaptureOptions
* @property {ModuleTransforms} [moduleTransforms]
* @property {Record<string, any>} [modules]
* @property {boolean} [dev]
* @property {SomePolicy} [policy]
* @property {Set<string>} [tags] deprecated in favor of `conditions`
* @property {Set<string>} [conditions]
* @property {ExitModuleImportHook} [importHook]
* @property {Array<string>} [searchSuffixes]
* @property {Record<string, string>} [commonDependencies]
* @property {SourceMapHook} [sourceMapHook]
* @property {Record<string, ParserImplementation>} [parserForLanguage]
* @property {LanguageForExtension} [languageForExtension]
*/
/**
* The result of `captureFromMap()`
*
* @typedef CaptureResult
* @property {CompartmentMapDescriptor} captureCompartmentMap
* @property {Sources} captureSources
* @property {Record<string, string>} compartmentRenames
*/

@@ -0,1 +1,6 @@

/* Minimal support for URL manipulation beyond what most hosts provide
* natively, used to normalize URLs before capturing them in a platform- and
* location-agnostic archive.
*/
// @ts-check

@@ -2,0 +7,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc