From c31c31fc258f8b733b677216d492b7655af45c0d Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Tue, 5 Nov 2024 11:08:40 -0800 Subject: [PATCH 1/6] feat(compartment-mapper): languageForExtensions options but parameterized on package type --- packages/compartment-mapper/NEWS.md | 7 + packages/compartment-mapper/src/archive.js | 116 ++++++++++-- packages/compartment-mapper/src/bundle.js | 16 +- packages/compartment-mapper/src/import.js | 29 ++- packages/compartment-mapper/src/map-parser.js | 8 + .../compartment-mapper/src/node-modules.js | 175 +++++++++++------- packages/compartment-mapper/src/parse-json.js | 1 + .../compartment-mapper/src/types/external.ts | 4 + .../compartment-mapper/test/_parse-jsonp.js | 45 +++++ .../node_modules/commonjs-app/module.xsonp | 1 + .../node_modules/commonjs-app/package.json | 7 + .../node_modules/module-app/module.xsonp | 1 + .../node_modules/module-app/package.json | 7 + .../node_modules/parsers-app/module.xsonp | 1 + .../node_modules/parsers-app/package.json | 9 + .../test/language-for-extension.test.js | 110 +++++++++++ packages/compartment-mapper/test/scaffold.js | 53 ++++++ 17 files changed, 499 insertions(+), 91 deletions(-) create mode 100644 packages/compartment-mapper/test/_parse-jsonp.js create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/package.json create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/package.json create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/package.json create mode 100644 packages/compartment-mapper/test/language-for-extension.test.js diff --git a/packages/compartment-mapper/NEWS.md b/packages/compartment-mapper/NEWS.md index 968df14ef1..8d37eb98e0 100644 --- a/packages/compartment-mapper/NEWS.md +++ b/packages/compartment-mapper/NEWS.md @@ -2,6 +2,13 @@ User-visible changes to `@endo/compartment-mapper`: # Next version +- Adds options `languageForExtension`, `moduleLanguageForExtension`, + `commonjsLanguageForExtension`, and `languages` to `mapNodeModules` and + `compartmentMapForNodeModules` allowing for certain mappings from extension + (e.g., `ts`) to language (e.g., `mts` or `cts`) to depend on the each + package’s `type` in the way we already vary `js` between `cjs` and `mjs`. + These options enter through the high level functions including `makeArchive` + and `importLocation`. - Omits unused module descriptors from `compartment-map.json` in archived applications, potentially reducing file sizes. - Fixes an issue where errors thrown from exit module hooks (`importHook`) would diff --git a/packages/compartment-mapper/src/archive.js b/packages/compartment-mapper/src/archive.js index fafb0615be..992449b25f 100644 --- a/packages/compartment-mapper/src/archive.js +++ b/packages/compartment-mapper/src/archive.js @@ -47,7 +47,8 @@ const assignParserForLanguage = (options = {}) => { const parserForLanguage = freeze( assign(create(null), defaultParserForLanguage, parserForLanguageOption), ); - return { ...rest, parserForLanguage }; + const languages = Object.keys(parserForLanguage); + return { ...rest, parserForLanguage, languages }; }; /** @@ -61,12 +62,16 @@ export const makeAndHashArchive = async ( moduleLocation, options = {}, ) => { - const compartmentMap = await mapNodeModules(powers, moduleLocation, options); - return makeAndHashArchiveFromMap( - powers, - compartmentMap, - assignParserForLanguage(options), - ); + const { parserForLanguage, languages, ...otherOptions } = + assignParserForLanguage(options); + const compartmentMap = await mapNodeModules(powers, moduleLocation, { + languages, + ...otherOptions, + }); + return makeAndHashArchiveFromMap(powers, compartmentMap, { + parserForLanguage, + ...otherOptions, + }); }; /** @@ -76,20 +81,35 @@ export const makeAndHashArchive = async ( * @returns {Promise} */ export const makeArchive = async (powers, moduleLocation, options = {}) => { - const { dev, tags, conditions = tags, commonDependencies, policy } = options; - + const { + dev, + tags, + conditions = tags, + commonDependencies, + policy, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + parserForLanguage, + languages, + ...otherOptions + } = assignParserForLanguage(options); const compartmentMap = await mapNodeModules(powers, moduleLocation, { dev, conditions, commonDependencies, policy, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + languages, }); - return makeArchiveFromMap( - powers, - compartmentMap, - assignParserForLanguage(options), - ); + return makeArchiveFromMap(powers, compartmentMap, { + parserForLanguage, + policy, + ...otherOptions, + }); }; /** @@ -99,16 +119,36 @@ export const makeArchive = async (powers, moduleLocation, options = {}) => { * @returns {Promise} */ export const mapLocation = async (powers, moduleLocation, options = {}) => { - const { dev, tags, conditions = tags, commonDependencies, policy } = options; + const { + dev, + tags, + conditions = tags, + commonDependencies, + policy, + parserForLanguage, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...otherOptions + } = assignParserForLanguage(options); const compartmentMap = await mapNodeModules(powers, moduleLocation, { dev, conditions, commonDependencies, policy, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, }); - return mapFromMap(powers, compartmentMap, assignParserForLanguage(options)); + return mapFromMap(powers, compartmentMap, { + parserForLanguage, + policy, + ...otherOptions, + }); }; /** @@ -118,16 +158,36 @@ export const mapLocation = async (powers, moduleLocation, options = {}) => { * @returns {Promise} */ export const hashLocation = async (powers, moduleLocation, options = {}) => { - const { dev, tags, conditions = tags, commonDependencies, policy } = options; + const { + dev, + tags, + conditions = tags, + commonDependencies, + policy, + parserForLanguage, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...otherOptions + } = assignParserForLanguage(options); const compartmentMap = await mapNodeModules(powers, moduleLocation, { dev, conditions, commonDependencies, policy, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, }); - return hashFromMap(powers, compartmentMap, assignParserForLanguage(options)); + return hashFromMap(powers, compartmentMap, { + parserForLanguage, + policy, + ...otherOptions, + }); }; /** @@ -144,18 +204,34 @@ export const writeArchive = async ( moduleLocation, options = {}, ) => { - const { dev, tags, conditions = tags, commonDependencies, policy } = options; + const { + dev, + tags, + conditions = tags, + commonDependencies, + policy, + parserForLanguage, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...otherOptions + } = assignParserForLanguage(options); const compartmentMap = await mapNodeModules(readPowers, moduleLocation, { dev, conditions, commonDependencies, policy, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + languages, }); return writeArchiveFromMap( write, readPowers, archiveLocation, compartmentMap, - assignParserForLanguage(options), + { policy, parserForLanguage, ...otherOptions }, ); }; diff --git a/packages/compartment-mapper/src/bundle.js b/packages/compartment-mapper/src/bundle.js index 29f5d60e78..3884db3bb8 100644 --- a/packages/compartment-mapper/src/bundle.js +++ b/packages/compartment-mapper/src/bundle.js @@ -235,6 +235,8 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { sourceMapHook = undefined, parserForLanguage: parserForLanguageOption = {}, languageForExtension: languageForExtensionOption = {}, + commonjsLanguageForExtension: commonjsLanguageForExtensionOption = {}, + moduleLanguageForExtension: moduleLanguageForExtensionOption = {}, } = options || {}; const conditions = new Set(conditionsOption); @@ -248,6 +250,12 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { const languageForExtension = Object.freeze( Object.assign(Object.create(null), languageForExtensionOption), ); + const commonjsLanguageForExtension = Object.freeze( + Object.assign(Object.create(null), commonjsLanguageForExtensionOption), + ); + const moduleLanguageForExtension = Object.freeze( + Object.assign(Object.create(null), moduleLanguageForExtensionOption), + ); const { packageLocation, @@ -266,7 +274,13 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { conditions, packageDescriptor, moduleSpecifier, - { dev, commonDependencies }, + { + dev, + commonDependencies, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + }, ); const { diff --git a/packages/compartment-mapper/src/import.js b/packages/compartment-mapper/src/import.js index 754d94987b..faf7c48bc3 100644 --- a/packages/compartment-mapper/src/import.js +++ b/packages/compartment-mapper/src/import.js @@ -42,7 +42,8 @@ const assignParserForLanguage = (options = {}) => { const parserForLanguage = freeze( assign(create(null), defaultParserForLanguage, parserForLanguageOption), ); - return { ...rest, parserForLanguage }; + const languages = Object.keys(parserForLanguage); + return { ...rest, parserForLanguage, languages }; }; /** @@ -72,7 +73,18 @@ export const loadLocation = async ( moduleLocation, options = {}, ) => { - const { dev, tags, commonDependencies, policy } = options; + const { + dev, + tags, + commonDependencies, + policy, + parserForLanguage, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...otherOptions + } = assignParserForLanguage(options); // conditions are not present in SyncArchiveOptions const conditions = 'conditions' in options ? options.conditions || tags : tags; @@ -81,12 +93,15 @@ export const loadLocation = async ( conditions, commonDependencies, policy, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + languages, + }); + return loadFromMap(readPowers, compartmentMap, { + parserForLanguage, + ...otherOptions, }); - return loadFromMap( - readPowers, - compartmentMap, - assignParserForLanguage(options), - ); }; /** diff --git a/packages/compartment-mapper/src/map-parser.js b/packages/compartment-mapper/src/map-parser.js index 74dc243c0e..49b2acfa66 100644 --- a/packages/compartment-mapper/src/map-parser.js +++ b/packages/compartment-mapper/src/map-parser.js @@ -101,6 +101,14 @@ const makeExtensionParser = ( ) { language = languageForModuleSpecifier[specifier]; } else { + // We should revisit this design decision: + // Defaulting the language to the extension conflates those namespaces. + // So, a transform keyed by extension can be used to coerce a language + // (e.g., .mts to mjs) as a shorthand for configuring a parser for that + // extension that pre-processes the file before handing off to the + // parser. + // But, this forces us to support the case of using weird language + // names like pre-mjs-json as valid, unconfigured extensions. language = languageForExtension[extension] || extension; } diff --git a/packages/compartment-mapper/src/node-modules.js b/packages/compartment-mapper/src/node-modules.js index 1a0803e07a..f8754c681c 100644 --- a/packages/compartment-mapper/src/node-modules.js +++ b/packages/compartment-mapper/src/node-modules.js @@ -57,6 +57,13 @@ * modules. */ +/** + * @typedef {object} LanguageOptions + * @property {LanguageForExtension} commonjsLanguageForExtension + * @property {LanguageForExtension} moduleLanguageForExtension + * @property {Set} languages + */ + /** * @typedef {Record} CommonDependencyDescriptors */ @@ -189,83 +196,73 @@ const findPackage = async (readDescriptor, canonical, directory, name) => { } }; -const defaultLanguages = /** @type {const} */ ([ - 'mjs', - 'cjs', - 'json', - 'text', - 'bytes', -]); -const defaultUncontroversialParsers = /** @type {const} */ ({ - cjs: 'cjs', +const defaultLanguageForExtension = /** @type {const} */ ({ mjs: 'mjs', + cjs: 'cjs', json: 'json', text: 'text', bytes: 'bytes', }); -const defaultCommonParsers = /** @type {const} */ ({ +const defaultCommonjsLanguageForExtension = /** @type {const} */ ({ js: 'cjs', - ...defaultUncontroversialParsers, }); -const defaultModuleParsers = /** @type {const} */ ({ +const defaultModuleLanguageForExtension = /** @type {const} */ ({ js: 'mjs', - ...defaultUncontroversialParsers, }); /** * @param {object} descriptor * @param {string} location - * @param {object} [options] - * @param {readonly string[]|string[]} [options.languages] - * @param {Record} [options.uncontroversialParsers] - * @param {Record} [options.commonParsers] - * @param {Record} [options.moduleParsers] + * @param {LanguageOptions} languageOptions * @returns {Record} */ -const inferParsers = ( - descriptor, - location, - { - languages = defaultLanguages, - uncontroversialParsers = defaultUncontroversialParsers, - commonParsers = defaultCommonParsers, - moduleParsers = defaultModuleParsers, - } = {}, -) => { - const { type, module, parsers } = descriptor; - let additionalParsers = Object.create(null); - if (parsers !== undefined) { - if (typeof parsers !== 'object') { - throw Error( - `Cannot interpret parser map ${JSON.stringify( - parsers, - )} of package at ${location}, must be an object mapping file extensions to corresponding languages (mjs for ECMAScript modules, cjs for CommonJS modules, or json for JSON modules`, - ); - } - const invalidLanguages = values(parsers).filter( - language => !languages.includes(language), +const inferParsers = (descriptor, location, languageOptions) => { + const { + languages, + moduleLanguageForExtension, + commonjsLanguageForExtension, + } = languageOptions; + + const { + type, + module, + parsers: packageLanguageForExtension = {}, + } = descriptor; + + // Validate package-local "parsers" + if ( + typeof packageLanguageForExtension !== 'object' || + packageLanguageForExtension === null + ) { + throw Error( + `Cannot interpret parser map ${JSON.stringify( + packageLanguageForExtension, + )} of package at ${location}, must be an object mapping file extensions to corresponding languages (for example, mjs for ECMAScript modules, cjs for CommonJS modules, or json for JSON modules`, + ); + } + const invalidLanguages = values(packageLanguageForExtension).filter( + language => !languages.has(language), + ); + if (invalidLanguages.length > 0) { + throw Error( + `Cannot interpret parser map language values ${JSON.stringify( + invalidLanguages, + )} of package at ${location}, must be an object mapping file extensions to corresponding languages (for example, mjs for ECMAScript modules, cjs for CommonJS modules, or json for JSON modules`, ); - if (invalidLanguages.length > 0) { - throw Error( - `Cannot interpret parser map language values ${JSON.stringify( - invalidLanguages, - )} of package at ${location}, must be an object mapping file extensions to corresponding languages (mjs for ECMAScript modules, cjs for CommonJS modules, or json for JSON modules`, - ); - } - additionalParsers = { ...uncontroversialParsers, ...parsers }; } + if (type === 'module' || module !== undefined) { - return { ...moduleParsers, ...additionalParsers }; + return { ...moduleLanguageForExtension, ...packageLanguageForExtension }; } if (type === 'commonjs') { - return { ...commonParsers, ...additionalParsers }; + return { ...commonjsLanguageForExtension, ...packageLanguageForExtension }; } if (type !== undefined) { throw Error( `Cannot infer parser map for package of type ${type} at ${location}`, ); } - return { ...commonParsers, ...additionalParsers }; + return { ...commonjsLanguageForExtension, ...packageLanguageForExtension }; }; /** @@ -286,6 +283,7 @@ const inferParsers = ( * @param {Set} conditions * @param {boolean | undefined} dev * @param {CommonDependencyDescriptors} commonDependencyDescriptors + * @param {LanguageOptions} languageOptions * @param {Map>} preferredPackageLogicalPathMap * @param {Array} logicalPath * @returns {Promise} @@ -299,6 +297,7 @@ const graphPackage = async ( conditions, dev, commonDependencyDescriptors, + languageOptions, preferredPackageLogicalPathMap = new Map(), logicalPath = [], ) => { @@ -368,6 +367,7 @@ const graphPackage = async ( name, conditions, preferredPackageLogicalPathMap, + languageOptions, childLogicalPath, optional, commonDependencyDescriptors, @@ -399,6 +399,12 @@ const graphPackage = async ( types, ); + const parsers = inferParsers( + packageDescriptor, + packageLocation, + languageOptions, + ); + Object.assign(result, { name, path: logicalPath, @@ -408,7 +414,7 @@ const graphPackage = async ( internalAliases, dependencyLocations, types, - parsers: inferParsers(packageDescriptor, packageLocation), + parsers, }); await Promise.all( @@ -462,6 +468,7 @@ const graphPackage = async ( * @param {string} name - name of the package of interest. * @param {Set} conditions * @param {Map>} preferredPackageLogicalPathMap + * @param {LanguageOptions} languageOptions * @param {Array} [childLogicalPath] * @param {boolean} [optional] - whether the dependency is optional * @param {object} [commonDependencyDescriptors] - dependencies to be added to all packages @@ -475,6 +482,7 @@ const gatherDependency = async ( name, conditions, preferredPackageLogicalPathMap, + languageOptions, childLogicalPath = [], optional = false, commonDependencyDescriptors = undefined, @@ -511,6 +519,7 @@ const gatherDependency = async ( conditions, false, commonDependencyDescriptors, + languageOptions, preferredPackageLogicalPathMap, childLogicalPath, ); @@ -533,7 +542,8 @@ const gatherDependency = async ( * package.json, which was already read when searching for the package.json. * @param {boolean|undefined} dev - whether to use devDependencies from this package (and * only this package). - * @param {Record} [commonDependencies] - dependencies to be added to all packages + * @param {Record} commonDependencies - dependencies to be added to all packages + * @param {LanguageOptions} languageOptions */ const graphPackages = async ( maybeRead, @@ -542,7 +552,8 @@ const graphPackages = async ( conditions, mainPackageDescriptor, dev, - commonDependencies = {}, + commonDependencies, + languageOptions, ) => { const memo = create(null); /** @@ -599,6 +610,7 @@ const graphPackages = async ( conditions, dev, commonDependencyDescriptors, + languageOptions, ); return graph; }; @@ -754,6 +766,46 @@ const translateGraph = ( }; }; +/** + * @param {Pick} options + */ +const makeLanguageOptions = ({ + languageForExtension: additionalLanguageForExtension = {}, + moduleLanguageForExtension: additionalModuleLanguageForExtension = {}, + commonjsLanguageForExtension: additionalCommonjsLanguageForExtension = {}, + languages: additionalLanguages = [], +}) => { + const commonjsLanguageForExtension = { + ...defaultLanguageForExtension, + ...additionalLanguageForExtension, + ...defaultCommonjsLanguageForExtension, + ...additionalCommonjsLanguageForExtension, + }; + const moduleLanguageForExtension = { + ...defaultLanguageForExtension, + ...additionalLanguageForExtension, + ...defaultModuleLanguageForExtension, + ...additionalModuleLanguageForExtension, + }; + + const languages = new Set([ + ...Object.values(moduleLanguageForExtension), + ...Object.values(commonjsLanguageForExtension), + ...additionalLanguages, + ]); + + return { + languages, + commonjsLanguageForExtension, + moduleLanguageForExtension, + }; +}; + /** * @param {ReadFn | ReadPowers | MaybeReadPowers} readPowers * @param {string} packageLocation @@ -771,8 +823,10 @@ export const compartmentMapForNodeModules = async ( moduleSpecifier, options = {}, ) => { - const { dev = undefined, commonDependencies, policy } = options; + const { dev = undefined, commonDependencies = {}, policy } = options; const { maybeRead, canonical } = unpackReadPowers(readPowers); + const languageOptions = makeLanguageOptions(options); + const graph = await graphPackages( maybeRead, canonical, @@ -781,6 +835,7 @@ export const compartmentMapForNodeModules = async ( packageDescriptor, dev, commonDependencies, + languageOptions, ); if (policy) { @@ -821,13 +876,7 @@ export const mapNodeModules = async ( moduleLocation, options = {}, ) => { - const { - tags = new Set(), - conditions = tags, - dev = undefined, - commonDependencies, - policy, - } = options; + const { tags = new Set(), conditions = tags, ...otherOptions } = options; const { packageLocation, @@ -847,6 +896,6 @@ export const mapNodeModules = async ( conditions, packageDescriptor, moduleSpecifier, - { dev, commonDependencies, policy }, + otherOptions, ); }; diff --git a/packages/compartment-mapper/src/parse-json.js b/packages/compartment-mapper/src/parse-json.js index 54fe440c9f..6d9119facc 100644 --- a/packages/compartment-mapper/src/parse-json.js +++ b/packages/compartment-mapper/src/parse-json.js @@ -20,6 +20,7 @@ const textDecoder = new TextDecoder(); /** @type {ParseFn} */ export const parseJson = (bytes, _specifier, location, _packageLocation) => { const source = textDecoder.decode(bytes); + /** @type {Array} */ const imports = freeze([]); /** diff --git a/packages/compartment-mapper/src/types/external.ts b/packages/compartment-mapper/src/types/external.ts index c1282763bc..33f261ae5a 100644 --- a/packages/compartment-mapper/src/types/external.ts +++ b/packages/compartment-mapper/src/types/external.ts @@ -72,6 +72,10 @@ type MapNodeModulesOptionsOmitPolicy = Partial<{ commonDependencies: Record; /** Maps extensions to languages for all packages, like `txt` to `text` */ languageForExtension: LanguageForExtension; + /** Maps extensions to languages for all type=module packages */ + moduleLanguageForExtension: LanguageForExtension; + /** Maps extensions to languages for all type=commonjs packages (default) */ + commonjsLanguageForExtension: LanguageForExtension; /** * Accounts for languages not present as values in any of the extension to * language mappings. diff --git a/packages/compartment-mapper/test/_parse-jsonp.js b/packages/compartment-mapper/test/_parse-jsonp.js new file mode 100644 index 0000000000..5bb7448742 --- /dev/null +++ b/packages/compartment-mapper/test/_parse-jsonp.js @@ -0,0 +1,45 @@ +/** @module Provides joke language support for importing JSONP modules. */ + +/** + * @import {ParseFn, ParserImplementation} from '../src/types.js' + */ + +const textDecoder = new TextDecoder(); + +/** @type {ParseFn} */ +export const parseJsonp = (bytes, _specifier, _location, _packageLocation) => { + // Presumes that all JSONP module bytes are retrieved with ?callback=exports. + const source = textDecoder.decode(bytes); + const imports = harden([]); + + /** + * @param {object} exports + */ + const execute = exports => { + const compartment = new Compartment({ + __options__: true, + globals: harden({ + exports(value) { + exports.default = value; + }, + }), + }); + compartment.evaluate(source); + }; + return { + parser: 'jsonp', + bytes, + record: harden({ + imports, + exports: ['default'], + execute, + }), + }; +}; + +/** @type {ParserImplementation} */ +export default { + parse: parseJsonp, + heuristicImports: false, + synchronous: true, +}; diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/package.json new file mode 100644 index 0000000000..cec862f1c0 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/package.json @@ -0,0 +1,7 @@ +{ + "name": "app", + "type": "commonjs", + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/package.json new file mode 100644 index 0000000000..68d335f7bd --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/package.json @@ -0,0 +1,7 @@ +{ + "name": "app", + "type": "module", + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/package.json new file mode 100644 index 0000000000..8004f6bd58 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/node_modules/parsers-app/package.json @@ -0,0 +1,9 @@ +{ + "name": "app", + "parsers": { + "xsonp": "jsonp" + }, + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/language-for-extension.test.js b/packages/compartment-mapper/test/language-for-extension.test.js new file mode 100644 index 0000000000..591cae76d3 --- /dev/null +++ b/packages/compartment-mapper/test/language-for-extension.test.js @@ -0,0 +1,110 @@ +import 'ses'; +import test from 'ava'; +import { scaffold } from './scaffold.js'; +import jsonp from './_parse-jsonp.js'; + +// The JSONP parser uses harden, as a bit. +lockdown({ + errorTaming: 'unsafe', + errorTrapping: 'none', +}); + +scaffold( + 'languageForExtension', + test, + new URL( + 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', + import.meta.url, + ).href, + (t, { namespace }) => { + t.deepEqual(namespace, { + default: { + meaning: 42, + }, + __proto__: { + __proto__: null, + [Symbol.toStringTag]: 'Module', + }, + }); + }, + 1, + { + parserForLanguage: { jsonp }, + languageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'moduleLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', + import.meta.url, + ).href, + (t, { namespace }) => { + t.deepEqual(namespace, { + default: { + meaning: 42, + }, + __proto__: { + __proto__: null, + [Symbol.toStringTag]: 'Module', + }, + }); + }, + 1, + { + parserForLanguage: { jsonp }, + moduleLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'commonjsLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp', + import.meta.url, + ).href, + (t, { namespace }) => { + t.deepEqual(namespace, { + default: { + meaning: 42, + }, + __proto__: { + __proto__: null, + [Symbol.toStringTag]: 'Module', + }, + }); + }, + 1, + { + parserForLanguage: { jsonp }, + commonjsLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'package.json parsers override languageForExtension', + test, + new URL( + 'fixtures-language-for-extension/node_modules/parsers-app/module.xsonp', + import.meta.url, + ).href, + (t, { namespace }) => { + t.deepEqual(namespace, { + default: { + meaning: 42, + }, + __proto__: { + __proto__: null, + [Symbol.toStringTag]: 'Module', + }, + }); + }, + 1, + { + parserForLanguage: { jsonp }, + languageForExtension: { xsonp: 'text' }, + }, +); diff --git a/packages/compartment-mapper/test/scaffold.js b/packages/compartment-mapper/test/scaffold.js index 467d965ff1..de99135b02 100644 --- a/packages/compartment-mapper/test/scaffold.js +++ b/packages/compartment-mapper/test/scaffold.js @@ -90,6 +90,10 @@ export function scaffold( conditions = tags, searchSuffixes = undefined, commonDependencies = undefined, + parserForLanguage = undefined, + languageForExtension = undefined, + commonjsLanguageForExtension = undefined, + moduleLanguageForExtension = undefined, additionalOptions = {}, } = {}, ) { @@ -133,6 +137,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); const { namespace } = await application.import({ @@ -156,6 +164,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); return namespace; @@ -173,6 +185,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); const application = await parseArchive(archive, '', { @@ -185,6 +201,8 @@ export function scaffold( }), ), Compartment, + parserForLanguage, + ...additionalOptions, }); const { namespace } = await application.import({ globals: { ...globals, ...addGlobals }, @@ -209,6 +227,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); const prefixArchive = new Uint8Array(archive.length + 10); @@ -217,6 +239,8 @@ export function scaffold( const application = await parseArchive(prefixArchive, '', { modules, Compartment, + parserForLanguage, + ...additionalOptions, }); const { namespace } = await application.import({ globals: { ...globals, ...addGlobals }, @@ -253,11 +277,17 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); const application = await loadArchive(fakeRead, 'app.agar', { modules, Compartment, + parserForLanguage, + ...additionalOptions, }); const { namespace } = await application.import({ globals: { ...globals, ...addGlobals }, @@ -306,6 +336,10 @@ export function scaffold( searchSuffixes, commonDependencies, sourceMapHook, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); @@ -314,6 +348,7 @@ export function scaffold( modules, Compartment, computeSourceMapLocation, + parserForLanguage, ...additionalOptions, }); @@ -341,6 +376,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); @@ -349,6 +388,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); @@ -361,6 +404,7 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), computeSha512, expectedSha512, + parserForLanguage, ...additionalOptions, }, ); @@ -378,6 +422,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); @@ -386,6 +434,10 @@ export function scaffold( conditions: new Set(['development', ...(conditions || [])]), searchSuffixes, commonDependencies, + parserForLanguage, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, ...additionalOptions, }); @@ -403,6 +455,7 @@ export function scaffold( parseArchive(corruptArchive, 'app.agar', { computeSha512, expectedSha512, + parserForLanguage, ...additionalOptions, }), { From 0147dce70e80995b8d17eaa86e49e82a77b8cd33 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Sun, 3 Nov 2024 23:21:45 -0800 Subject: [PATCH 2/6] refactor(compartment-mapper): Remove languageForExtension from link options --- .../compartment-mapper/src/archive-lite.js | 5 ----- packages/compartment-mapper/src/bundle.js | 1 - .../compartment-mapper/src/capture-lite.js | 7 ++----- .../src/import-archive-lite.js | 8 -------- packages/compartment-mapper/src/import-lite.js | 6 ------ packages/compartment-mapper/src/link.js | 18 ++---------------- .../compartment-mapper/src/types/external.ts | 2 -- .../compartment-mapper/src/types/internal.ts | 4 +--- 8 files changed, 5 insertions(+), 46 deletions(-) diff --git a/packages/compartment-mapper/src/archive-lite.js b/packages/compartment-mapper/src/archive-lite.js index 85f02d48c4..4822bc4170 100644 --- a/packages/compartment-mapper/src/archive-lite.js +++ b/packages/compartment-mapper/src/archive-lite.js @@ -322,15 +322,11 @@ const digestFromMap = async (powers, compartmentMap, options = {}) => { policy = undefined, sourceMapHook = undefined, parserForLanguage: parserForLanguageOption = {}, - languageForExtension: languageForExtensionOption = {}, } = options; const parserForLanguage = freeze( assign(create(null), parserForLanguageOption), ); - const languageForExtension = freeze( - assign(create(null), languageForExtensionOption), - ); const { read, computeSha512 } = unpackReadPowers(powers); @@ -365,7 +361,6 @@ const digestFromMap = async (powers, compartmentMap, options = {}) => { makeImportHook, moduleTransforms, parserForLanguage, - languageForExtension, archiveOnly: true, }); await compartment.load(entryModuleSpecifier); diff --git a/packages/compartment-mapper/src/bundle.js b/packages/compartment-mapper/src/bundle.js index 3884db3bb8..068f205433 100644 --- a/packages/compartment-mapper/src/bundle.js +++ b/packages/compartment-mapper/src/bundle.js @@ -305,7 +305,6 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { makeImportHook, moduleTransforms, parserForLanguage, - languageForExtension, }); await compartment.load(entryModuleSpecifier); diff --git a/packages/compartment-mapper/src/capture-lite.js b/packages/compartment-mapper/src/capture-lite.js index 9513e9b973..20da5b58b0 100644 --- a/packages/compartment-mapper/src/capture-lite.js +++ b/packages/compartment-mapper/src/capture-lite.js @@ -263,22 +263,19 @@ const captureCompartmentMap = (compartmentMap, sources) => { export const captureFromMap = async (powers, compartmentMap, options = {}) => { const { moduleTransforms, + syncModuleTransforms, modules: exitModules = {}, searchSuffixes = undefined, importHook: exitModuleImportHook = undefined, policy = undefined, sourceMapHook = undefined, parserForLanguage: parserForLanguageOption = {}, - languageForExtension: languageForExtensionOption = {}, Compartment = defaultCompartment, } = options; const parserForLanguage = freeze( assign(create(null), parserForLanguageOption), ); - const languageForExtension = freeze( - assign(create(null), languageForExtensionOption), - ); const { read, computeSha512 } = unpackReadPowers(powers); @@ -312,8 +309,8 @@ export const captureFromMap = async (powers, compartmentMap, options = {}) => { resolve, makeImportHook, moduleTransforms, + syncModuleTransforms, parserForLanguage, - languageForExtension, archiveOnly: true, Compartment, }); diff --git a/packages/compartment-mapper/src/import-archive-lite.js b/packages/compartment-mapper/src/import-archive-lite.js index b05c6b79ac..6f2ff27e94 100644 --- a/packages/compartment-mapper/src/import-archive-lite.js +++ b/packages/compartment-mapper/src/import-archive-lite.js @@ -259,15 +259,11 @@ export const parseArchive = async ( modules = undefined, importHook: exitModuleImportHook = undefined, parserForLanguage: parserForLanguageOption = {}, - languageForExtension: languageForExtensionOption = {}, } = options; const parserForLanguage = freeze( assign(create(null), parserForLanguageOption), ); - const languageForExtension = freeze( - assign(create(null), languageForExtensionOption), - ); const archive = new ZipReader(archiveBytes, { name: archiveLocation }); @@ -343,7 +339,6 @@ export const parseArchive = async ( const { compartment, pendingJobsPromise } = link(compartmentMap, { makeImportHook, parserForLanguage, - languageForExtension, modules: Object.fromEntries( Object.keys(modules || {}).map(specifier => { return [specifier, { namespace: {} }]; @@ -390,7 +385,6 @@ export const parseArchive = async ( const { compartment, pendingJobsPromise } = link(compartmentMap, { makeImportHook, parserForLanguage, - languageForExtension, globals, modules, transforms, @@ -425,7 +419,6 @@ export const loadArchive = async ( modules, computeSourceMapLocation, parserForLanguage, - languageForExtension, } = options; const archiveBytes = await read(archiveLocation); return parseArchive(archiveBytes, archiveLocation, { @@ -435,7 +428,6 @@ export const loadArchive = async ( modules, computeSourceMapLocation, parserForLanguage, - languageForExtension, }); }; diff --git a/packages/compartment-mapper/src/import-lite.js b/packages/compartment-mapper/src/import-lite.js index 39118c5d36..d97ae195a0 100644 --- a/packages/compartment-mapper/src/import-lite.js +++ b/packages/compartment-mapper/src/import-lite.js @@ -95,15 +95,11 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { const { searchSuffixes = undefined, parserForLanguage: parserForLanguageOption = {}, - languageForExtension: languageForExtensionOption = {}, } = options; const parserForLanguage = freeze( assign(create(null), parserForLanguageOption), ); - const languageForExtension = freeze( - assign(create(null), languageForExtensionOption), - ); /** * Object containing options and read powers that fulfills all requirements @@ -199,7 +195,6 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { makeImportHook, makeImportNowHook, parserForLanguage, - languageForExtension, globals, transforms, syncModuleTransforms, @@ -213,7 +208,6 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { ({ compartment, pendingJobsPromise } = link(compartmentMap, { makeImportHook, parserForLanguage, - languageForExtension, globals, transforms, moduleTransforms, diff --git a/packages/compartment-mapper/src/link.js b/packages/compartment-mapper/src/link.js index 42e4c842c5..b2b1414f5d 100644 --- a/packages/compartment-mapper/src/link.js +++ b/packages/compartment-mapper/src/link.js @@ -11,15 +11,14 @@ /** * @import {ModuleMapHook} from 'ses' * @import { - * AsyncParseFn, * CompartmentDescriptor, * CompartmentMapDescriptor, * ImportNowHookMaker, - * LanguageForExtension, * LinkOptions, * LinkResult, * ModuleDescriptor, * ParseFn, + * AsyncParseFn, * ParserForLanguage, * ParserImplementation, * ShouldDeferError, @@ -254,7 +253,6 @@ export const link = ( makeImportHook, makeImportNowHook = impossibleImportNowHookMaker, parserForLanguage: parserForLanguageOption = {}, - languageForExtension: languageForExtensionOption = {}, globals = {}, transforms = [], moduleTransforms, @@ -279,10 +277,6 @@ export const link = ( const pendingJobs = []; - /** @type {LanguageForExtension} */ - const defaultLanguageForExtension = freeze( - assign(create(null), languageForExtensionOption), - ); /** @type {ParserForLanguage} */ const parserForLanguage = freeze( assign(create(null), parserForLanguageOption), @@ -300,7 +294,7 @@ export const link = ( const { location, name, - parsers: languageForExtensionOverrides = {}, + parsers: languageForExtension = {}, types: languageForModuleSpecifier = {}, } = compartmentDescriptor; @@ -314,14 +308,6 @@ export const link = ( // The `moduleMapHook` writes back to the compartment map. compartmentDescriptor.modules = modules; - /** @type {LanguageForExtension} */ - const languageForExtension = freeze( - assign( - create(null), - defaultLanguageForExtension, - languageForExtensionOverrides, - ), - ); // TS is kind of dumb about this, so we can use a type assertion to avoid a // pointless ternary. const parse = /** @type {ParseFn|AsyncParseFn} */ ( diff --git a/packages/compartment-mapper/src/types/external.ts b/packages/compartment-mapper/src/types/external.ts index 33f261ae5a..b922cb66f7 100644 --- a/packages/compartment-mapper/src/types/external.ts +++ b/packages/compartment-mapper/src/types/external.ts @@ -42,7 +42,6 @@ export type ParseArchiveOptions = Partial<{ ModulesOption & CompartmentOption & ParserForLanguageOption & - LanguageForExtensionOption & ExitModuleImportHookOption; export type LoadArchiveOptions = ParseArchiveOptions; @@ -204,7 +203,6 @@ type SyncImportingOptions = ModulesOption & type LinkingOptions = ParserForLanguageOption & CompartmentOption & - LanguageForExtensionOption & SyncModuleTransformsOption & ModuleTransformsOption; diff --git a/packages/compartment-mapper/src/types/internal.ts b/packages/compartment-mapper/src/types/internal.ts index 2fd8c37afe..8cce0cd5f4 100644 --- a/packages/compartment-mapper/src/types/internal.ts +++ b/packages/compartment-mapper/src/types/internal.ts @@ -26,7 +26,6 @@ import type { CompartmentSources, ExecuteOptions, ExitModuleImportNowHook, - LanguageForExtensionOption, ModuleTransforms, ParseFn, ParserForLanguage, @@ -45,8 +44,7 @@ export type LinkOptions = { moduleTransforms?: ModuleTransforms; syncModuleTransforms?: SyncModuleTransforms; archiveOnly?: boolean; -} & ExecuteOptions & - LanguageForExtensionOption; +} & ExecuteOptions; export type LinkResult = { compartment: Compartment; From eb8a9b725090ca8b591d1c8692166cc9a36b7d9d Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Wed, 6 Nov 2024 16:53:38 -0800 Subject: [PATCH 3/6] doc(compartment-mapper): Language extensions documentation --- packages/compartment-mapper/README.md | 70 ++++++++++++++++----------- 1 file changed, 43 insertions(+), 27 deletions(-) diff --git a/packages/compartment-mapper/README.md b/packages/compartment-mapper/README.md index 4013b692ec..9481a112d0 100644 --- a/packages/compartment-mapper/README.md +++ b/packages/compartment-mapper/README.md @@ -204,6 +204,8 @@ does not exist, to the `index.js` file in the directory with the same name. > `fetch` global, in conjunction with usable values for `import.meta.url` in > ECMAScript modules or `__dirname` and `__filename` in CommonJS modules. +## Language Extensions + Officially beginning with Node.js 14, Node.js treats `.mjs` files as ECMAScript modules and `.cjs` files as CommonJS modules. The `.js` extension indicates a CommonJS module by default, to maintain @@ -211,30 +213,6 @@ backward compatibility. However, packages that have a `type` property that explicitly says `module` will treat a `.js` file as an ECMAScript module. -This unforunately conflicts with packages written to work with the ECMAScript -module system emulator in the `esm` package on npm, which allows every file -with the `js` extension to be an ECMAScript module that presents itself to -Node.js as a CommonJS module. -To overcome such obstacles, the compartment mapper will accept a non-standard -`parsers` property in `package.json` that maps file extensions, specifically -`js` to the corresponding language name, one of `mjs` for ECMAScript modules, -`cjs` for CommonJS modules, and `json` for JSON modules. -All other language names are reserved and the defaults for files with the -extensions `cjs`, `mjs`, `json`, `text`, and `bytes` default to the language of -the same name unless overridden. -JSON modules export a default object resulting from the conventional JSON.parse -of the module's UTF-8 encoded bytes. -Text modules export a default string from the module's UTF-8 encoded bytes. -Bytes modules export a default ArrayBuffer capturing the module's bytes. -If compartment mapper sees `parsers`, it ignores `type`, so these can -contradict where using the `esm` emulator requires. - -```json -{ - "parsers": {"js": "mjs"} -} -``` - Many Node.js applications using CommonJS modules expect to be able to `require` a JSON file like `package.json`. The compartment mapper supports loading JSON modules from any type of module. @@ -252,9 +230,47 @@ As of Node.js 14, Node does not support loading ECMAScript modules from CommonJS modules, so using this feature may limit compatibility with the Node.js platform. -> TODO A future version may introduce language plugins, so a package may state -> that files with a particular extension are either parsed or linked with -> another module. +The compartment mapper supports language plugins. +The languages supported by default are: + +- `mjs` for ECMAScript modules, +- `cjs` for CommonJS modules, +- `json` for JSON modules, +- `text` for UTF-8 encoded text files, +- `bytes` for any file, exporting a `Uint8Array` as `default`, +- `pre-mjs-json` for pre-compiled ECMAScript modules captured as JSON in + archives, and +- `pre-cjs-json` for pre-compiled CommonJS modules captured as JSON in + archives. + +The compartment mapper accepts extensions to this set of languages with +the `parserForLanguage` option supported by many functions. +See `src/types/external.ts` for the type and expected behavior for +parsers. + +These language identifiers are keys for the `moduleTransforms` and +`syncModuleTransforms` options, which may map each language to a transform +function. +The language identifiers are also the values for a `languageForExtension`, +`moduleLanguageForExtension`, and `commonjsLanguageForExtension` options to +configure additional extension-to-language mappings for a module and its +transitive dependencies. + +For any package that has `type` set to `"module"` in its `package.json`, +`moduleLangaugeForExtension` will precede `languageForExtension`. +Packages with `type` set to `"commonjs"` or simply not set, +`commonjsLanguageForExtension` will precede `languageForExtension`. +This provides an hook for mapping TypeScript's `.ts` to either `.cts` or +`.mts`. + +In the scope any given package, the `parsers` property in `package.json` may +override the extension-to-language mapping. + +```json +{ + "parsers": { "png": "bytes" } +} +``` > TODO > From 3f6d963ec9e3b8728293ddf4a134422a70a58ba5 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Fri, 8 Nov 2024 14:27:09 -0800 Subject: [PATCH 4/6] test(compartment-mapper): Expand test coverage over lite interfaces --- .../src/import-archive-lite.js | 10 +- .../compartment-mapper/src/import-lite.js | 7 +- packages/compartment-mapper/test/scaffold.js | 149 ++++++++++++++++++ .../test/snapshots/error-handling.test.js.md | 73 +++++++++ .../snapshots/error-handling.test.js.snap | Bin 805 -> 910 bytes .../test/snapshots/policy.test.js.md | 54 +++++++ .../test/snapshots/policy.test.js.snap | Bin 782 -> 922 bytes 7 files changed, 284 insertions(+), 9 deletions(-) diff --git a/packages/compartment-mapper/src/import-archive-lite.js b/packages/compartment-mapper/src/import-archive-lite.js index 6f2ff27e94..5c50c41358 100644 --- a/packages/compartment-mapper/src/import-archive-lite.js +++ b/packages/compartment-mapper/src/import-archive-lite.js @@ -46,8 +46,6 @@ import { assertCompartmentMap } from './compartment-map.js'; import { exitModuleImportHookMaker } from './import-hook.js'; import { attenuateModuleHook, enforceModulePolicy } from './policy.js'; -const DefaultCompartment = Compartment; - const { Fail, quote: q } = assert; const textDecoder = new TextDecoder(); @@ -255,7 +253,7 @@ export const parseArchive = async ( expectedSha512 = undefined, computeSourceLocation = undefined, computeSourceMapLocation = undefined, - Compartment = DefaultCompartment, + Compartment: CompartmentParseOption = Compartment, modules = undefined, importHook: exitModuleImportHook = undefined, parserForLanguage: parserForLanguageOption = {}, @@ -344,7 +342,7 @@ export const parseArchive = async ( return [specifier, { namespace: {} }]; }), ), - Compartment, + Compartment: CompartmentParseOption, }); await pendingJobsPromise; @@ -363,7 +361,7 @@ export const parseArchive = async ( modules, transforms, __shimTransforms__, - Compartment, + Compartment: CompartmentOption = CompartmentParseOption, importHook: exitModuleImportHook, } = options || {}; @@ -389,7 +387,7 @@ export const parseArchive = async ( modules, transforms, __shimTransforms__, - Compartment, + Compartment: CompartmentOption, }); await pendingJobsPromise; diff --git a/packages/compartment-mapper/src/import-lite.js b/packages/compartment-mapper/src/import-lite.js index d97ae195a0..71d748f992 100644 --- a/packages/compartment-mapper/src/import-lite.js +++ b/packages/compartment-mapper/src/import-lite.js @@ -95,6 +95,7 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { const { searchSuffixes = undefined, parserForLanguage: parserForLanguageOption = {}, + Compartment: LoadCompartmentOption = Compartment, } = options; const parserForLanguage = freeze( @@ -150,7 +151,7 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { modules, transforms, __shimTransforms__, - Compartment, + Compartment: CompartmentOption = LoadCompartmentOption, importHook: exitModuleImportHook, } = options; const compartmentExitModuleImportHook = exitModuleImportHookMaker({ @@ -199,7 +200,7 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { transforms, syncModuleTransforms, __shimTransforms__, - Compartment, + Compartment: CompartmentOption, })); } else { // sync module transforms are allowed, because they are "compatible" @@ -213,7 +214,7 @@ export const loadFromMap = async (readPowers, compartmentMap, options = {}) => { moduleTransforms, syncModuleTransforms, __shimTransforms__, - Compartment, + Compartment: CompartmentOption, })); } diff --git a/packages/compartment-mapper/test/scaffold.js b/packages/compartment-mapper/test/scaffold.js index de99135b02..a150378726 100644 --- a/packages/compartment-mapper/test/scaffold.js +++ b/packages/compartment-mapper/test/scaffold.js @@ -13,6 +13,13 @@ import { importArchive, hashLocation, } from '../index.js'; + +import { mapNodeModules } from '../src/node-modules.js'; +import { loadFromMap, importFromMap } from '../src/import-lite.js'; +import { makeArchiveFromMap } from '../src/archive-lite.js'; +import { defaultParserForLanguage } from '../src/import-parsers.js'; +import { defaultParserForLanguage as defaultArchiveParserForLanguage } from '../src/archive-parsers.js'; + import { makeReadPowers } from '../src/node-powers.js'; export const readPowers = makeReadPowers({ @@ -152,6 +159,93 @@ export function scaffold( return namespace; }); + wrap(test, 'Location')( + `${name} / mapNodeModules / importFromMap`, + async (t, Compartment) => { + t.plan(fixtureAssertionCount); + await setup(); + + const languages = Object.keys({ + ...defaultParserForLanguage, + ...parserForLanguage, + }); + + const map = await mapNodeModules(readPowers, fixture, { + languages, + policy, + modules, + Compartment, + conditions: new Set(['development', ...(conditions || [])]), + commonDependencies, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...additionalOptions, + }); + + const { namespace } = await importFromMap(readPowers, map, { + globals: { ...globals, ...addGlobals }, + policy, + modules, + Compartment, + searchSuffixes, + parserForLanguage: { + ...defaultParserForLanguage, + ...parserForLanguage, + }, + ...additionalOptions, + }); + + return namespace; + }, + ); + + wrap(test, 'Location')( + `${name} / mapNodeModules / loadFromMap / import`, + async (t, Compartment) => { + t.plan(fixtureAssertionCount); + await setup(); + + const languages = Object.keys({ + ...defaultParserForLanguage, + ...parserForLanguage, + }); + + const map = await mapNodeModules(readPowers, fixture, { + languages, + policy, + modules, + Compartment, + conditions: new Set(['development', ...(conditions || [])]), + commonDependencies, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...additionalOptions, + }); + + const app = await loadFromMap(readPowers, map, { + policy, + Compartment, + searchSuffixes, + parserForLanguage: { + ...defaultParserForLanguage, + ...parserForLanguage, + }, + ...additionalOptions, + }); + + const { namespace } = await app.import({ + globals: { ...globals, ...addGlobals }, + modules, + Compartment, + ...additionalOptions, + }); + + return namespace; + }, + ); + wrap(test, 'Location')(`${name} / importLocation`, async (t, Compartment) => { t.plan(fixtureAssertionCount); await setup(); @@ -365,6 +459,61 @@ export function scaffold( }, ); + wrap(test, 'Archive')( + `${name} / mapNodeModules / makeArchiveFromMap / importArchive`, + async (t, Compartment) => { + t.plan(fixtureAssertionCount); + await setup(); + + const languages = Object.keys({ + ...defaultArchiveParserForLanguage, + ...parserForLanguage, + }); + + const map = await mapNodeModules(readPowers, fixture, { + policy, + conditions: new Set(['development', ...(conditions || [])]), + commonDependencies, + languages, + languageForExtension, + commonjsLanguageForExtension, + moduleLanguageForExtension, + ...additionalOptions, + }); + + const archive = await makeArchiveFromMap(readPowers, map, { + modules, + policy, + searchSuffixes, + parserForLanguage: { + ...defaultArchiveParserForLanguage, + ...parserForLanguage, + }, + ...additionalOptions, + }); + const application = await parseArchive(archive, '', { + modules: Object.fromEntries( + Object.keys(modules).map((specifier, index) => { + // Replacing the namespace with an arbitrary index ensures that the + // parse phase does not depend on the type or values of the exit module + // set. + return [specifier, index]; + }), + ), + Compartment, + parserForLanguage, + ...additionalOptions, + }); + const { namespace } = await application.import({ + globals: { ...globals, ...addGlobals }, + modules, + Compartment, + ...additionalOptions, + }); + return namespace; + }, + ); + if (!onError) { test(`${name} / makeArchive / parseArchive / hashArchive consistency`, async (t, Compartment) => { t.plan(1); diff --git a/packages/compartment-mapper/test/snapshots/error-handling.test.js.md b/packages/compartment-mapper/test/snapshots/error-handling.test.js.md index be0ed22671..efd4c6c1e4 100644 --- a/packages/compartment-mapper/test/snapshots/error-handling.test.js.md +++ b/packages/compartment-mapper/test/snapshots/error-handling.test.js.md @@ -6,6 +6,26 @@ Generated by [AVA](https://avajs.dev). ## fixtures-error-handling / esm / loadLocation +> Snapshot 1 + + `TypeError: Failed to load module "./main.js" in package "file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/" (1 underlying failures: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/␊ + at throwAggregateError (file://.../ses/src/module-load.js:…)␊ + at load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` + +## fixtures-error-handling / esm / mapNodeModules / importFromMap + +> Snapshot 1 + + `TypeError: Failed to load module "./main.js" in package "file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/" (1 underlying failures: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/␊ + at throwAggregateError (file://.../ses/src/module-load.js:…)␊ + at load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` + +## fixtures-error-handling / esm / mapNodeModules / loadFromMap / import + > Snapshot 1 `TypeError: Failed to load module "./main.js" in package "file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/" (1 underlying failures: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/␊ @@ -78,8 +98,45 @@ Generated by [AVA](https://avajs.dev). at async file://.../compartment-mapper/test/scaffold.js:…␊ at async file://.../compartment-mapper/test/scaffold.js:…` +## fixtures-error-handling / esm / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + `TypeError: Failed to load module "./main.js" in package "file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/" (1 underlying failures: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/esm/␊ + at throwAggregateError (file://.../ses/src/module-load.js:…)␊ + at load (file://.../ses/src/module-load.js:…)␊ + at async digestFromMap (file://.../compartment-mapper/src/archive-lite.js:…)␊ + at async makeAndHashArchiveFromMap (file://.../compartment-mapper/src/archive-lite.js:…)␊ + at async makeArchiveFromMap (file://.../compartment-mapper/src/archive-lite.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` + ## fixtures-error-handling / cjs / loadLocation +> Snapshot 1 + + `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ + at importHook (file://.../compartment-mapper/src/import-hook.js:…)␊ + at async asyncTrampoline (file://.../ses/src/module-load.js:…)␊ + at async drainQueue (file://.../ses/src/module-load.js:…)␊ + at async load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` + +## fixtures-error-handling / cjs / mapNodeModules / importFromMap + +> Snapshot 1 + + `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ + at importHook (file://.../compartment-mapper/src/import-hook.js:…)␊ + at async asyncTrampoline (file://.../ses/src/module-load.js:…)␊ + at async drainQueue (file://.../ses/src/module-load.js:…)␊ + at async load (file://.../ses/src/module-load.js:…)␊ + at async file://.../compartment-mapper/test/scaffold.js:…␊ + at async file://.../compartment-mapper/test/scaffold.js:…` + +## fixtures-error-handling / cjs / mapNodeModules / loadFromMap / import + > Snapshot 1 `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ @@ -165,3 +222,19 @@ Generated by [AVA](https://avajs.dev). at execute (file://.../ses/src/module-instance.js:…)␊ at compartmentImportNow (file://.../ses/src/compartment.js:…)␊ at file://.../ses/src/compartment.js:…` + +## fixtures-error-handling / cjs / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + `Error: Cannot find external module "missing" in package file://.../compartment-mapper/test/fixtures-error-handling/node_modules/cjs/␊ + at Object.execute (file://.../compartment-mapper/src/import-archive-lite.js:…)␊ + at execute (file://.../ses/src/module-instance.js:…)␊ + at compartmentImportNow (file://.../ses/src/compartment.js:…)␊ + at Compartment.importNow (file://.../ses/src/compartment.js:…)␊ + at require (file://.../compartment-mapper/src/parse-cjs-shared-export-wrapper.js:…)␊ + at Proxy.eval (eval at (eval at makeEvaluate (file://.../ses/src/make-evaluate.js:…)), :…)␊ + at Object.execute (file://.../compartment-mapper/src/parse-pre-cjs.js:…)␊ + at execute (file://.../ses/src/module-instance.js:…)␊ + at compartmentImportNow (file://.../ses/src/compartment.js:…)␊ + at file://.../ses/src/compartment.js:…` diff --git a/packages/compartment-mapper/test/snapshots/error-handling.test.js.snap b/packages/compartment-mapper/test/snapshots/error-handling.test.js.snap index d5b62f73817fe30af18fff6e065f7baa7a8f0d14..dd06112fd364d1c34ff44addabb513d236af6c58 100644 GIT binary patch literal 910 zcmV;919AL8RzVS>djL|m(B(ll)v5*r|P;e_6j zm&UDQ2ixf%ae)J0fNwAkd@w!(G!AO5v=f001ea~*F*Gsrm{1VBRz6s+BsUTg6De!HUIhVI_)u%qcOLCz zuLlozp4Oh#E`|vnXOUX$1h~L}S(V3Nu?kXwtl@ewaOrkTgK^0c@Vn4P)(E-4mgl*y z>-j29K-(Clbz(>o)Sg9Sy*ZcaNfqG7BE0d?#9o8#zGSHkP>W$Umk_wfI=0vmNU1Cf zxeOQ%ENThj`pRN%443Vx>$=O!ddwJOV401y>L0e-8rxutY_Z*mfeaeYXx}UPI$8GI zj%oe+@^fz-BF|{WK46B@UuHtahcHxP9AMr4W7H1HP>UfsR{@?CDPtbvaiX+6(JDTJ zgy19iR)_DnGJM%AM(ACmNDLB#t25}9F<3xGyDh=CK5VV>8(tR=wIA^wGLI#o&G_SO z@aoMe@Ltpjye$VW;B7SHN2jR}Gv=2?gktR-!7a`XnFAw(Q!vp8l)DfA7vgSC!PC_h zWPNTU1}xDS@&O4+LXwdGU{CC8ZYPY)R&)NI_-#tT9w|r)-WLTYIsZ@G-mmC(@n4JV zCcDY*?YH}V<>R{<$t{AD%TE)I-+ikqTw9s zmMj_)d<5Sb)xrY4(rO`5MwG2_Bs#vuRVWjFo+3`vw~4qnmmT!2iv#piixsF_^z1z= z+KpA`(pZrGt*#S;zRCwWSN)lBCK}$1aWwH0Up0uvPbt?+Wh7sI$L|=&M4&NnaFC~{ zuk$uHBfr&ZFm$m8g6-z-VA(!MC5N#}&B329Gsup6AX1o@OX#A5qZZ>~_L`H?rbe#5 z*u~TmolkGemU*exOH>`pj4rJ@lHcSv`Mp`cOLy!_MNBf9j3%QuYxIKBGzmQ8$Wg?BF zwO709?#hQvr@rU8uIu?S zNl}@EgmDr~Q&OHGZMIoUp$4Xv%q!X_P+s`2r0VzHy_7WoFMPMHePzY%tWFi2{ z4Jm>AVr2=_nu(~fuG?JJLjV9YU}7c5`%$DQLQ`c6wrdk<(wBJdzZ zrKgWqjo00681Grv8gIjm7qE!5IZ`rtjcG$-#{LRLtZMIYW@xr#X&4b4qmIvwa{Kas zL3e!!9sAU=M{9lSF3v#h)JwlO2wbXLwyM zaYzoGkC;xgvs+hd%)ETDtF5J~+}?(jd7;q@wE5bIZf)~fzAfLD@AdNCdSWltHMB%q jqAk(uC3;S;a3;}hy+X^hW!f^m9;SZ-hE-XI(I)@^sS}Bp diff --git a/packages/compartment-mapper/test/snapshots/policy.test.js.md b/packages/compartment-mapper/test/snapshots/policy.test.js.md index a74af4324b..54570ac6ad 100644 --- a/packages/compartment-mapper/test/snapshots/policy.test.js.md +++ b/packages/compartment-mapper/test/snapshots/policy.test.js.md @@ -6,6 +6,18 @@ Generated by [AVA](https://avajs.dev). ## policy - attack - browser alias - with alias hint / loadLocation +> Snapshot 1 + + 'Failed to load module "./attack.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (1 underlying failures: Importing "dan" in "eve-v1.0.0" was not allowed by packages policy {"dan":true} (info: Blocked in linking. "dan" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/hackity/".)' + +## policy - attack - browser alias - with alias hint / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./attack.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (1 underlying failures: Importing "dan" in "eve-v1.0.0" was not allowed by packages policy {"dan":true} (info: Blocked in linking. "dan" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/hackity/".)' + +## policy - attack - browser alias - with alias hint / mapNodeModules / loadFromMap / import + > Snapshot 1 'Failed to load module "./attack.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (1 underlying failures: Importing "dan" in "eve-v1.0.0" was not allowed by packages policy {"dan":true} (info: Blocked in linking. "dan" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/hackity/".)' @@ -36,12 +48,30 @@ Generated by [AVA](https://avajs.dev). ## policy - attack - browser alias - with alias hint / writeArchive / importArchive +> Snapshot 1 + + 'Failed to load module "./attack.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (1 underlying failures: Importing "dan" in "eve-v1.0.0" was not allowed by packages policy {"dan":true} (info: Blocked in linking. "dan" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/hackity/".)' + +## policy - attack - browser alias - with alias hint / mapNodeModules / makeArchiveFromMap / importArchive + > Snapshot 1 'Failed to load module "./attack.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (1 underlying failures: Importing "dan" in "eve-v1.0.0" was not allowed by packages policy {"dan":true} (info: Blocked in linking. "dan" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/hackity/".)' ## policy - disallowed package with error hint / loadLocation +> Snapshot 1 + + 'Failed to load module "./index.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (2 underlying failures: Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".), Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".)' + +## policy - disallowed package with error hint / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./index.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (2 underlying failures: Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".), Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".)' + +## policy - disallowed package with error hint / mapNodeModules / loadFromMap / import + > Snapshot 1 'Failed to load module "./index.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (2 underlying failures: Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".), Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".)' @@ -72,12 +102,30 @@ Generated by [AVA](https://avajs.dev). ## policy - disallowed package with error hint / writeArchive / importArchive +> Snapshot 1 + + 'Failed to load module "./index.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (2 underlying failures: Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".), Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".)' + +## policy - disallowed package with error hint / mapNodeModules / makeArchiveFromMap / importArchive + > Snapshot 1 'Failed to load module "./index.js" in package "file://.../compartment-mapper/test/fixtures-policy/node_modules/app/" (2 underlying failures: Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".), Importing "carol" in "alice-v1.0.0" was not allowed by packages policy {"alice>carol":false} (info: Blocked in linking. "carol" is part of the compartment map and resolves to "file://.../compartment-mapper/test/fixtures-policy/node_modules/alice/node_modules/carol/".)' ## policy - attenuator error aggregation / loadLocation +> Snapshot 1 + + 'Globals attenuation errors: Error while attenuating globals for "alice" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "carol" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "app" with "myattenuator": "I attenuate, I throw."' + +## policy - attenuator error aggregation / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Globals attenuation errors: Error while attenuating globals for "alice" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "carol" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "app" with "myattenuator": "I attenuate, I throw."' + +## policy - attenuator error aggregation / mapNodeModules / loadFromMap / import + > Snapshot 1 'Globals attenuation errors: Error while attenuating globals for "alice" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "carol" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "app" with "myattenuator": "I attenuate, I throw."' @@ -111,3 +159,9 @@ Generated by [AVA](https://avajs.dev). > Snapshot 1 'Globals attenuation errors: Error while attenuating globals for "alice" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "app" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "carol" with "myattenuator": "I attenuate, I throw."' + +## policy - attenuator error aggregation / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Globals attenuation errors: Error while attenuating globals for "alice" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "app" with "myattenuator": "I attenuate, I throw.", Error while attenuating globals for "carol" with "myattenuator": "I attenuate, I throw."' diff --git a/packages/compartment-mapper/test/snapshots/policy.test.js.snap b/packages/compartment-mapper/test/snapshots/policy.test.js.snap index a541d7c80026bb1fac4986c2cce956356d14265b..40cd9b14eaa23cb315dffd95b6b9f4f784a483f7 100644 GIT binary patch literal 922 zcmV;L17-X{RzV0FXHJN0` zoy>%p*)PR|NB;w__2Pfv-zWLnZe=B3TVY`Kmff9~nfbk65?Yc zb-h3&DN3CXu7?SxDUqHgN_!EV>xm?4SWMsJA|xM+z{ejU{0gj!{0QJa(%SD9F|TA_6@ku(BjbFa_ixNTLLr5|!;y@8yp$7*oCQ9QSTT z`Arwf38p6^B*#Tq@POt!cOXS_jH%^r0Qb|4aL?$K)R$Rc@f(1DzYG3?uf4n*#QCI~ z=40|y1|vEp;AKlt)uCl>0P_!(nA7{7Ay|NCj)CWAT2;4hOQq^eq2wcmLf5GjRhR;$_meTna{?SJy6JS6k0 z!h5e4Z-7#;0x&Wfv_zZ_d0fQsBV?+Eb#=D?Ogo?E<*)LYWcYXNZmjG^CBsoW8QPY# ztRAK$gw)HB3nctHwGtUiDI=re1I5FeM$V9P8x3o&~Ee z@3^cpreukAW}P$lSKkg3K0z&HsR_ohBynD+s&CtVa7lyPgBMJkAydn!S&%%e^5JQ>sh|4jNkR=wU(AG&77qfGGa1NK_$POHW9!W8CotCvmc8H00000000B+nca%hKoo$tE8?|paL9$M&?dX0UIYy2;V^GW`8yHH8fA0aTkOWHXzbH4MDPR>O%;WC)&pTEd3!)fs( zlbi)h7y%lC!4yU?Q8L%0069YqBgmOa>WhR410HaR;TsvCVNx(HFw==N`ujx~qQMV? zA2*I}9TlI!&7<4LUj{FbaSFl6av-EKoN)rj^{Oe|&)NYdAj4paF@X~?PQK^4uImLd z%}|+?gc+rnWu!bq+ISILn3*Cys+R8w8PcaJu=X&^JO@tBU?xIRe91%%5i(v3@L`;0 zQkmkO6QU?*c4$tc`I&p_o;r}D1|ba~=Q5`dCd+1J8tPz*g4hikX!XDA-x+ z`@{U*9++1TcuT!M)cs59A=AyqntYeMNhzr|`=5UN=NjMN$N%KZL`aK6;l0<2H$WwM z1sFLCIwCHIJg#E+5pvzax|!`i(=L~J{Z_e>0{_rvVG=}T!?QTFf*>GBT2s?nEXuxhMR8PLS)%s6~)6toGq~89q-K zr>pNp3~@aslB&kyRDL??@@jRC56<{<91UR%CQ&kXo#AGYYZ?cLj9Jz#ZbRYWrW9H` zyOzT)9L_i8(5ds Date: Fri, 8 Nov 2024 15:45:15 -0800 Subject: [PATCH 5/6] docs(compartment-mapper): Workspace language-for-extension options --- packages/compartment-mapper/NEWS.md | 6 ++++++ packages/compartment-mapper/README.md | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/packages/compartment-mapper/NEWS.md b/packages/compartment-mapper/NEWS.md index 8d37eb98e0..085ebe73ff 100644 --- a/packages/compartment-mapper/NEWS.md +++ b/packages/compartment-mapper/NEWS.md @@ -9,6 +9,12 @@ User-visible changes to `@endo/compartment-mapper`: package’s `type` in the way we already vary `js` between `cjs` and `mjs`. These options enter through the high level functions including `makeArchive` and `importLocation`. +- The new options `workspaceLanguageForExtension`, + `workspaceModuleLanguageForExtension`, and + `workspaceCommonjsLanguageForExtension` apply like the above except more + specifically and for packages that are not physically located under a + `node_modules` directory, indicating that JavaScript has not yet been + generated from any non-JavaScript source files. - Omits unused module descriptors from `compartment-map.json` in archived applications, potentially reducing file sizes. - Fixes an issue where errors thrown from exit module hooks (`importHook`) would diff --git a/packages/compartment-mapper/README.md b/packages/compartment-mapper/README.md index 9481a112d0..6cfbdfb6b9 100644 --- a/packages/compartment-mapper/README.md +++ b/packages/compartment-mapper/README.md @@ -263,6 +263,13 @@ Packages with `type` set to `"commonjs"` or simply not set, This provides an hook for mapping TypeScript's `.ts` to either `.cts` or `.mts`. +The analogous `workspaceLanguageForExtension`, +`workspaceCommonjsLanguageForExtension`, and +`workspaceModuleLanguageForExtension` options apply more specifically for +packages that are not under a `node_modules` directory, indicating that they +are in the set of linked workspaces and have not been built or published to +npm. + In the scope any given package, the `parsers` property in `package.json` may override the extension-to-language mapping. From 389de7b6f9ff4b191f17c442199c289f12c5b855 Mon Sep 17 00:00:00 2001 From: Kris Kowal Date: Fri, 8 Nov 2024 15:46:19 -0800 Subject: [PATCH 6/6] feat(compartment-mapper): Workspace language-for-extension options --- packages/compartment-mapper/src/archive.js | 24 ++ packages/compartment-mapper/src/bundle.js | 23 ++ packages/compartment-mapper/src/import.js | 6 + .../compartment-mapper/src/node-modules.js | 44 ++- .../compartment-mapper/src/types/external.ts | 16 +- .../packages/commonjs-app/module.xsonp | 1 + .../packages/commonjs-app/package.json | 7 + .../packages/module-app/module.xsonp | 1 + .../packages/module-app/package.json | 7 + .../packages/parsers-app/module.xsonp | 1 + .../packages/parsers-app/package.json | 9 + .../test/language-for-extension.test.js | 248 ++++++++++--- .../test/missing-entry.test.js | 8 +- packages/compartment-mapper/test/scaffold.js | 42 +++ .../language-for-extension.test.js.md | 329 ++++++++++++++++++ .../language-for-extension.test.js.snap | Bin 0 -> 1110 bytes 16 files changed, 709 insertions(+), 57 deletions(-) create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/package.json create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/package.json create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/module.xsonp create mode 100644 packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/package.json create mode 100644 packages/compartment-mapper/test/snapshots/language-for-extension.test.js.md create mode 100644 packages/compartment-mapper/test/snapshots/language-for-extension.test.js.snap diff --git a/packages/compartment-mapper/src/archive.js b/packages/compartment-mapper/src/archive.js index 992449b25f..b9b4af7837 100644 --- a/packages/compartment-mapper/src/archive.js +++ b/packages/compartment-mapper/src/archive.js @@ -90,6 +90,9 @@ export const makeArchive = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, parserForLanguage, languages, ...otherOptions @@ -102,6 +105,9 @@ export const makeArchive = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, languages, }); @@ -130,6 +136,9 @@ export const mapLocation = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...otherOptions } = assignParserForLanguage(options); @@ -142,6 +151,9 @@ export const mapLocation = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, }); return mapFromMap(powers, compartmentMap, { @@ -169,6 +181,9 @@ export const hashLocation = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...otherOptions } = assignParserForLanguage(options); @@ -181,6 +196,9 @@ export const hashLocation = async (powers, moduleLocation, options = {}) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, }); return hashFromMap(powers, compartmentMap, { @@ -215,6 +233,9 @@ export const writeArchive = async ( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...otherOptions } = assignParserForLanguage(options); const compartmentMap = await mapNodeModules(readPowers, moduleLocation, { @@ -225,6 +246,9 @@ export const writeArchive = async ( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, languages, }); return writeArchiveFromMap( diff --git a/packages/compartment-mapper/src/bundle.js b/packages/compartment-mapper/src/bundle.js index 068f205433..fe63135f1b 100644 --- a/packages/compartment-mapper/src/bundle.js +++ b/packages/compartment-mapper/src/bundle.js @@ -237,6 +237,11 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { languageForExtension: languageForExtensionOption = {}, commonjsLanguageForExtension: commonjsLanguageForExtensionOption = {}, moduleLanguageForExtension: moduleLanguageForExtensionOption = {}, + workspaceLanguageForExtension: workspaceLanguageForExtensionOption = {}, + workspaceCommonjsLanguageForExtension: + workspaceCommonjsLanguageForExtensionOption = {}, + workspaceModuleLanguageForExtension: + workspaceModuleLanguageForExtensionOption = {}, } = options || {}; const conditions = new Set(conditionsOption); @@ -256,6 +261,21 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { const moduleLanguageForExtension = Object.freeze( Object.assign(Object.create(null), moduleLanguageForExtensionOption), ); + const workspaceLanguageForExtension = Object.freeze( + Object.assign(Object.create(null), workspaceLanguageForExtensionOption), + ); + const workspaceCommonjsLanguageForExtension = Object.freeze( + Object.assign( + Object.create(null), + workspaceCommonjsLanguageForExtensionOption, + ), + ); + const workspaceModuleLanguageForExtension = Object.freeze( + Object.assign( + Object.create(null), + workspaceModuleLanguageForExtensionOption, + ), + ); const { packageLocation, @@ -280,6 +300,9 @@ export const makeBundle = async (readPowers, moduleLocation, options) => { languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, }, ); diff --git a/packages/compartment-mapper/src/import.js b/packages/compartment-mapper/src/import.js index faf7c48bc3..1c6c3cedef 100644 --- a/packages/compartment-mapper/src/import.js +++ b/packages/compartment-mapper/src/import.js @@ -83,6 +83,9 @@ export const loadLocation = async ( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...otherOptions } = assignParserForLanguage(options); // conditions are not present in SyncArchiveOptions @@ -96,6 +99,9 @@ export const loadLocation = async ( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, languages, }); return loadFromMap(readPowers, compartmentMap, { diff --git a/packages/compartment-mapper/src/node-modules.js b/packages/compartment-mapper/src/node-modules.js index f8754c681c..a3f41ace75 100644 --- a/packages/compartment-mapper/src/node-modules.js +++ b/packages/compartment-mapper/src/node-modules.js @@ -61,6 +61,8 @@ * @typedef {object} LanguageOptions * @property {LanguageForExtension} commonjsLanguageForExtension * @property {LanguageForExtension} moduleLanguageForExtension + * @property {LanguageForExtension} workspaceCommonjsLanguageForExtension + * @property {LanguageForExtension} workspaceModuleLanguageForExtension * @property {Set} languages */ @@ -217,12 +219,22 @@ const defaultModuleLanguageForExtension = /** @type {const} */ ({ * @returns {Record} */ const inferParsers = (descriptor, location, languageOptions) => { + let { moduleLanguageForExtension, commonjsLanguageForExtension } = + languageOptions; const { languages, - moduleLanguageForExtension, - commonjsLanguageForExtension, + workspaceModuleLanguageForExtension, + workspaceCommonjsLanguageForExtension, } = languageOptions; + // Select languageForExtension options based on whether they are physically + // under node_modules, indicating that they have not been built for npm, + // so any languages that compile to JavaScript may need additional parsers. + if (!location.includes('/node_modules/')) { + moduleLanguageForExtension = workspaceModuleLanguageForExtension; + commonjsLanguageForExtension = workspaceCommonjsLanguageForExtension; + } + const { type, module, @@ -771,6 +783,9 @@ const translateGraph = ( * 'languageForExtension' | * 'moduleLanguageForExtension' | * 'commonjsLanguageForExtension' | + * 'workspaceLanguageForExtension' | + * 'workspaceModuleLanguageForExtension' | + * 'workspaceCommonjsLanguageForExtension' | * 'languages' * >} options */ @@ -778,6 +793,11 @@ const makeLanguageOptions = ({ languageForExtension: additionalLanguageForExtension = {}, moduleLanguageForExtension: additionalModuleLanguageForExtension = {}, commonjsLanguageForExtension: additionalCommonjsLanguageForExtension = {}, + workspaceLanguageForExtension: additionalWorkspaceLanguageForExtension = {}, + workspaceModuleLanguageForExtension: + additionalWorkspaceModuleLanguageForExtension = {}, + workspaceCommonjsLanguageForExtension: + additionalWorkspaceCommonjsLanguageForExtension = {}, languages: additionalLanguages = [], }) => { const commonjsLanguageForExtension = { @@ -792,10 +812,28 @@ const makeLanguageOptions = ({ ...defaultModuleLanguageForExtension, ...additionalModuleLanguageForExtension, }; + const workspaceCommonjsLanguageForExtension = { + ...defaultLanguageForExtension, + ...additionalLanguageForExtension, + ...defaultCommonjsLanguageForExtension, + ...additionalCommonjsLanguageForExtension, + ...additionalWorkspaceLanguageForExtension, + ...additionalWorkspaceCommonjsLanguageForExtension, + }; + const workspaceModuleLanguageForExtension = { + ...defaultLanguageForExtension, + ...additionalLanguageForExtension, + ...defaultModuleLanguageForExtension, + ...additionalModuleLanguageForExtension, + ...additionalWorkspaceLanguageForExtension, + ...additionalWorkspaceModuleLanguageForExtension, + }; const languages = new Set([ ...Object.values(moduleLanguageForExtension), ...Object.values(commonjsLanguageForExtension), + ...Object.values(workspaceModuleLanguageForExtension), + ...Object.values(workspaceCommonjsLanguageForExtension), ...additionalLanguages, ]); @@ -803,6 +841,8 @@ const makeLanguageOptions = ({ languages, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, }; }; diff --git a/packages/compartment-mapper/src/types/external.ts b/packages/compartment-mapper/src/types/external.ts index b922cb66f7..d0de4e9916 100644 --- a/packages/compartment-mapper/src/types/external.ts +++ b/packages/compartment-mapper/src/types/external.ts @@ -71,10 +71,22 @@ type MapNodeModulesOptionsOmitPolicy = Partial<{ commonDependencies: Record; /** Maps extensions to languages for all packages, like `txt` to `text` */ languageForExtension: LanguageForExtension; - /** Maps extensions to languages for all type=module packages */ + /** Maps additional extensions to languages for all type=module packages */ moduleLanguageForExtension: LanguageForExtension; - /** Maps extensions to languages for all type=commonjs packages (default) */ + /** Maps additional extensions to languages for all type=commonjs packages (default) */ commonjsLanguageForExtension: LanguageForExtension; + /** Maps extensions to languages for packages not under node_modules */ + workspaceLanguageForExtension: LanguageForExtension; + /** + * Maps additional extensions to languages for all type=module packages that + * are not under node_modules + */ + workspaceModuleLanguageForExtension: LanguageForExtension; + /** + * Maps additional extensions to languages for all type=commonjs packages + * (default) + */ + workspaceCommonjsLanguageForExtension: LanguageForExtension; /** * Accounts for languages not present as values in any of the extension to * language mappings. diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/package.json new file mode 100644 index 0000000000..cec862f1c0 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/commonjs-app/package.json @@ -0,0 +1,7 @@ +{ + "name": "app", + "type": "commonjs", + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/package.json new file mode 100644 index 0000000000..68d335f7bd --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/module-app/package.json @@ -0,0 +1,7 @@ +{ + "name": "app", + "type": "module", + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/module.xsonp b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/module.xsonp new file mode 100644 index 0000000000..f1dad2cdf6 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/module.xsonp @@ -0,0 +1 @@ +exports({ meaning: 42 }); diff --git a/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/package.json b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/package.json new file mode 100644 index 0000000000..8004f6bd58 --- /dev/null +++ b/packages/compartment-mapper/test/fixtures-language-for-extension/packages/parsers-app/package.json @@ -0,0 +1,9 @@ +{ + "name": "app", + "parsers": { + "xsonp": "jsonp" + }, + "scripts": { + "preinstall": "echo DO NOT INSTALL TEST FIXTURES; exit -1" + } +} diff --git a/packages/compartment-mapper/test/language-for-extension.test.js b/packages/compartment-mapper/test/language-for-extension.test.js index 591cae76d3..6e6d3ae4c6 100644 --- a/packages/compartment-mapper/test/language-for-extension.test.js +++ b/packages/compartment-mapper/test/language-for-extension.test.js @@ -1,6 +1,6 @@ import 'ses'; import test from 'ava'; -import { scaffold } from './scaffold.js'; +import { scaffold, sanitizePaths } from './scaffold.js'; import jsonp from './_parse-jsonp.js'; // The JSONP parser uses harden, as a bit. @@ -9,6 +9,22 @@ lockdown({ errorTrapping: 'none', }); +const meaningfulModule = { + default: { + meaning: 42, + }, + __proto__: { + __proto__: null, + [Symbol.toStringTag]: 'Module', + }, +}; + +const assertions = (t, { namespace }) => { + t.deepEqual(namespace, meaningfulModule); +}; + +const assertionCount = 1; + scaffold( 'languageForExtension', test, @@ -16,18 +32,8 @@ scaffold( 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', import.meta.url, ).href, - (t, { namespace }) => { - t.deepEqual(namespace, { - default: { - meaning: 42, - }, - __proto__: { - __proto__: null, - [Symbol.toStringTag]: 'Module', - }, - }); - }, - 1, + assertions, + assertionCount, { parserForLanguage: { jsonp }, languageForExtension: { xsonp: 'jsonp' }, @@ -41,21 +47,30 @@ scaffold( 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', import.meta.url, ).href, - (t, { namespace }) => { - t.deepEqual(namespace, { - default: { - meaning: 42, - }, - __proto__: { - __proto__: null, - [Symbol.toStringTag]: 'Module', - }, - }); - }, - 1, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + moduleLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'moduleLanguageForExtension should not be available in commonjs package', + test, + new URL( + 'fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions { parserForLanguage: { jsonp }, moduleLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, }, ); @@ -66,21 +81,30 @@ scaffold( 'fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp', import.meta.url, ).href, - (t, { namespace }) => { - t.deepEqual(namespace, { - default: { - meaning: 42, - }, - __proto__: { - __proto__: null, - [Symbol.toStringTag]: 'Module', - }, - }); - }, - 1, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + commonjsLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'commonjsLanguageForExtension should not be available in module package', + test, + new URL( + 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions { parserForLanguage: { jsonp }, commonjsLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, }, ); @@ -91,20 +115,146 @@ scaffold( 'fixtures-language-for-extension/node_modules/parsers-app/module.xsonp', import.meta.url, ).href, - (t, { namespace }) => { - t.deepEqual(namespace, { - default: { - meaning: 42, - }, - __proto__: { - __proto__: null, - [Symbol.toStringTag]: 'Module', - }, - }); - }, - 1, + assertions, + assertionCount, { parserForLanguage: { jsonp }, languageForExtension: { xsonp: 'text' }, }, ); + +scaffold( + 'workspaceLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/packages/module-app/module.xsonp', + import.meta.url, + ).href, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + workspaceLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'workspaceModuleLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/packages/module-app/module.xsonp', + import.meta.url, + ).href, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + workspaceModuleLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'workspaceModuleLanguageForExtension should not be available in commonjs package', + test, + new URL( + 'fixtures-language-for-extension/package/commonjs-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions + { + parserForLanguage: { jsonp }, + workspaceModuleLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, + }, +); + +scaffold( + 'workspaceModuleLanguageForExtension should not be available under node_modules', + test, + new URL( + 'fixtures-language-for-extension/node_modules/module-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions + { + parserForLanguage: { jsonp }, + workspaceModuleLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, + }, +); + +scaffold( + 'workspaceCommonjsLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/packages/commonjs-app/module.xsonp', + import.meta.url, + ).href, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + workspaceCommonjsLanguageForExtension: { xsonp: 'jsonp' }, + }, +); + +scaffold( + 'workspaceCommonjsLanguageForExtension should not be available in module package', + test, + new URL( + 'fixtures-language-for-extension/packages/module-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions + { + parserForLanguage: { jsonp }, + workspaceCommonjsLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, + }, +); + +scaffold( + 'workspaceCommonjsLanguageForExtension should not be available under node_modules', + test, + new URL( + 'fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp', + import.meta.url, + ).href, + assertions, + 1, // expected number of assertions + { + parserForLanguage: { jsonp }, + workspaceCommonjsLanguageForExtension: { xsonp: 'jsonp' }, + shouldFailBeforeArchiveOperations: true, + onError(t, { error }) { + t.snapshot(sanitizePaths(error.message)); + }, + }, +); + +scaffold( + 'package.json parsers override workspaceLanguageForExtension', + test, + new URL( + 'fixtures-language-for-extension/packages/parsers-app/module.xsonp', + import.meta.url, + ).href, + assertions, + assertionCount, + { + parserForLanguage: { jsonp }, + workspaceLanguageForExtension: { xsonp: 'text' }, + }, +); diff --git a/packages/compartment-mapper/test/missing-entry.test.js b/packages/compartment-mapper/test/missing-entry.test.js index f53cff9bdd..4c2f70becc 100644 --- a/packages/compartment-mapper/test/missing-entry.test.js +++ b/packages/compartment-mapper/test/missing-entry.test.js @@ -1,6 +1,5 @@ import 'ses'; import test from 'ava'; -import path from 'path'; import fs from 'fs'; import url from 'url'; import crypto from 'crypto'; @@ -11,9 +10,10 @@ import { makeReadPowers } from '../node-powers.js'; const readPowers = makeReadPowers({ fs, url, crypto }); test('missing entry', async t => { - const entry = url.pathToFileURL( - path.resolve('i-solemnly-swear-i-do-not-exist.js'), - ); + const entry = new URL( + 'fixtures-missing/i-solemnly-swear-i-do-not-exist.js', + import.meta.url, + ).href; await t.throwsAsync( makeAndHashArchive(readPowers, entry, {}).then(() => {}), { diff --git a/packages/compartment-mapper/test/scaffold.js b/packages/compartment-mapper/test/scaffold.js index a150378726..00ee4ea127 100644 --- a/packages/compartment-mapper/test/scaffold.js +++ b/packages/compartment-mapper/test/scaffold.js @@ -101,6 +101,9 @@ export function scaffold( languageForExtension = undefined, commonjsLanguageForExtension = undefined, moduleLanguageForExtension = undefined, + workspaceLanguageForExtension = undefined, + workspaceCommonjsLanguageForExtension = undefined, + workspaceModuleLanguageForExtension = undefined, additionalOptions = {}, } = {}, ) { @@ -148,6 +151,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); const { namespace } = await application.import({ @@ -180,6 +186,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -221,6 +230,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -262,6 +274,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); return namespace; @@ -283,6 +298,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); const application = await parseArchive(archive, '', { @@ -325,6 +343,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); const prefixArchive = new Uint8Array(archive.length + 10); @@ -375,6 +396,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); const application = await loadArchive(fakeRead, 'app.agar', { @@ -434,6 +458,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -478,6 +505,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -529,6 +559,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -541,6 +574,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -575,6 +611,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); @@ -587,6 +626,9 @@ export function scaffold( languageForExtension, commonjsLanguageForExtension, moduleLanguageForExtension, + workspaceLanguageForExtension, + workspaceCommonjsLanguageForExtension, + workspaceModuleLanguageForExtension, ...additionalOptions, }); diff --git a/packages/compartment-mapper/test/snapshots/language-for-extension.test.js.md b/packages/compartment-mapper/test/snapshots/language-for-extension.test.js.md new file mode 100644 index 0000000000..684f541900 --- /dev/null +++ b/packages/compartment-mapper/test/snapshots/language-for-extension.test.js.md @@ -0,0 +1,329 @@ +# Snapshot report for `test/language-for-extension.test.js` + +The actual snapshot is saved in `language-for-extension.test.js.snap`. + +Generated by [AVA](https://avajs.dev). + +## moduleLanguageForExtension should not be available in commonjs package / loadLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / importLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## moduleLanguageForExtension should not be available in commonjs package / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / loadLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / importLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## commonjsLanguageForExtension should not be available in module package / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / loadLocation + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / importLocation + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available in commonjs package / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" in package "file://.../compartment-mapper/" (1 underlying failures: Cannot find file for internal module "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp" (with candidates "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp.node", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.js", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.json", "./test/fixtures-language-for-extension/package/commonjs-app/module.xsonp/index.node") in package file://.../compartment-mapper/' + +## workspaceModuleLanguageForExtension should not be available under node_modules / loadLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / importLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceModuleLanguageForExtension should not be available under node_modules / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / loadLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / importLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available in module package / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../module-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../module-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / loadLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / mapNodeModules / importFromMap + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / mapNodeModules / loadFromMap / import + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / importLocation + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / makeArchive / parseArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / makeArchive / parseArchive with a prefix + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / writeArchive / loadArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / writeArchive / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' + +## workspaceCommonjsLanguageForExtension should not be available under node_modules / mapNodeModules / makeArchiveFromMap / importArchive + +> Snapshot 1 + + 'Failed to load module "./module.xsonp" in package "file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/" (1 underlying failures: Cannot parse module ./module.xsonp at file://.../compartment-mapper/test/fixtures-language-for-extension/node_modules/commonjs-app/module.xsonp, no parser configured for the language xsonp' diff --git a/packages/compartment-mapper/test/snapshots/language-for-extension.test.js.snap b/packages/compartment-mapper/test/snapshots/language-for-extension.test.js.snap new file mode 100644 index 0000000000000000000000000000000000000000..35fa4cc350c95c923aff06061659cef99ec2f480 GIT binary patch literal 1110 zcmV-c1gZN$RzV>rB=00000000B+ok36AFcinj(6sZufz=a}Xro;;&@W=6wH@}Fc znvvOYB!USehnNp1ct{R}dNkHmxphzpGd1mR0e86Gf#C`Z1CBEipNB(Xon zLxMcS1P%^`k2MvX#vIFdBy{}sJ_xYJAGapkofn08>T+q(%CNDC-95 z_Py+<{wx+;c9U!6m*|F+kv-4r_xqkNB8iob2-m#`OG%WcNvyq)&h$i)xX0!<)C+~` zk^GiCE&_6zT_N`Jo9JOFy)N2$jV3%Gid|7YL?NauX=xAbW1fUSVil9TpUd4uSR<>Q zTfEpV;v(yeLcZW39ZnPpP$(4ABZBg_QTod{=Akjn5ti>oK#sC*A`j6>3Z)N}h>oxX z@Q#7!_P{6j=GY%(0Q?=}e`1V(1{fUPQP94@L?4s4${*3o<#7@{Qv(kJ*dG=H5}*7 zmDR)iepfEtTr6Q8xPUqP?j+=eu5DhnF^0Hw*#@B31)bZ2zGBG+*w@AW#2EX+at%PP z3$kx8!Aq2C0C-)%FDd|DSf&B|&CmBzB^m%;7jR+=c+rF$kk^I$#@?WPtq&tt>Q32wB(ByCJK=usY!nc>@hXw>Y@&zns{@M6WqE@6s(7XQGii^QMhju zw-qdWtn)k#_y_n0_=o%c@o5wPNOK4+J{Sgj|o z7w+pS!(A|2Ze8##XuZT7wRPd<*2DeuJfL*}zpY@Pvc`O@bsSDN