Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(compartment-mapper): Custom parser support #2304

Merged
merged 24 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
9da9817
feat(compartment-mapper): allow custom parsers [DRAFT]
boneskull May 17, 2024
b15077a
test(compartment-mapper): test whether custom parsers allow for node …
naugtur May 23, 2024
7781750
chore: renaming typo
boneskull May 23, 2024
a7deeed
feat(compartment-mapper): ParseFn now receives CompartmentDescriptor
boneskull May 24, 2024
6dbf4d9
chore(compartment-mapper): simplify custom parser test
boneskull May 24, 2024
6683bac
fix(compartment-mapper): fix types for custom languages
boneskull May 24, 2024
b3545d6
fix(compartment-mapper): fix incorrect return types of policy assertions
boneskull May 24, 2024
367b998
feat(compartment-mapper): add a prop for custom fields in policy
boneskull May 24, 2024
1f62ac0
fix(compartment-mapper): fix type in CompartmentDescriptor
boneskull May 28, 2024
455ea4e
chore(compartment-mapper): make language prop of CustomParser singular
boneskull May 28, 2024
7aba42a
chore(compartment-mapper): better variable names
boneskull May 29, 2024
e8e412c
chore(compartment-mapper): use textdecoder in custom parser test
boneskull May 29, 2024
17fb28c
chore(compartment-mapper): remove errant newline
boneskull May 29, 2024
cb4960f
chore(compartment-mapper): lint
boneskull May 29, 2024
09b9e64
chore(compartment-mapper): rename variables for style
boneskull May 29, 2024
fa164f7
chore(compartment-mapper): swipe full docstrings from type-fest
boneskull May 29, 2024
40dc47b
chore(compartment-mapper): review updates, more tests
boneskull May 30, 2024
ede29de
chore(compartment-mapper): freeze another parserForLanguage
boneskull May 30, 2024
5ebfddf
chore(compartment-mapper): update type imports
boneskull May 30, 2024
971bfe8
refactor(compartment-mapper): Distribute parsers between parserForLan…
kriskowal May 31, 2024
a728b7f
docs(compartment-mapper): News for parserForLanguage and languageForE…
kriskowal May 31, 2024
5aeb5e6
fix(compartment-mapper): fix var in bundle.js
boneskull Jun 3, 2024
3ec2ac3
chore(compartment-mapper): update function signature types
boneskull Jun 3, 2024
e49a293
docs(compartment-mapper): fix NEWS.md
boneskull Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/compartment-mapper/NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ User-visible changes to the compartment mapper:
- Fixes incompatible behavior with Node.js package conditional exports #2276.
Previously, the last matching tag would override all prior matches, often
causing a bundle to adopt the `default` instead of a more specific condition.
- Adds `parserForLanguage` and `languageForExtension` options to all modes of
operation such that the compartment mapper can analyze and bundle languages
apart from the built-in languages, which include `esm` and `cjs`.
The `languageForExtension` option provides defaults for the entire
application and the `"parsers"` property in individual `package.json`
descriptors may extend or override using any of the configured or built-in
language parser names.

# 0.9.0 (2023-08-07)

Expand Down
48 changes: 31 additions & 17 deletions packages/compartment-mapper/src/archive.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// @ts-check
/* eslint no-shadow: 0 */

/** @import {ArchiveOptions} from './types.js' */
/** @import {ArchiveOptions, ParserForLanguage} from './types.js' */
/** @import {ArchiveWriter} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {CompartmentMapDescriptor} from './types.js' */
/** @import {ModuleDescriptor} from './types.js' */
/** @import {ParserImplementation} from './types.js' */
/** @import {ReadFn} from './types.js' */
/** @import {CaptureSourceLocationHook} from './types.js' */
/** @import {ReadPowers} from './types.js' */
Expand Down Expand Up @@ -39,16 +38,20 @@

const textEncoder = new TextEncoder();

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

/** @satisfies {Readonly<ParserForLanguage>} */
const defaultParserForLanguage = freeze(
/** @type {const} */ ({
mjs: parserArchiveMjs,
'pre-mjs-json': parserArchiveMjs,
cjs: parserArchiveCjs,
'pre-cjs-json': parserArchiveCjs,
json: parserJson,
text: parserText,
bytes: parserBytes,
}),
);

/**
* @param {string} rel - a relative URL
Expand Down Expand Up @@ -92,7 +95,7 @@
*/
const renameCompartments = compartments => {
/** @type {Record<string, string>} */
const compartmentRenames = Object.create(null);
const compartmentRenames = create(null);
let index = 0;
let prev = '';

Expand Down Expand Up @@ -133,14 +136,14 @@
* @param {Record<string, string>} compartmentRenames
*/
const translateCompartmentMap = (compartments, sources, compartmentRenames) => {
const result = Object.create(null);
const result = create(null);
for (const compartmentName of keys(compartmentRenames)) {
const compartment = compartments[compartmentName];
const { name, label, retained, policy } = compartment;
if (retained) {
// rename module compartments
/** @type {Record<string, ModuleDescriptor>} */
const modules = Object.create(null);
const modules = create(null);
const compartmentModules = compartment.modules;
if (compartment.modules) {
for (const name of keys(compartmentModules).sort()) {
Expand Down Expand Up @@ -224,7 +227,7 @@
const path = new URL(moduleLocation).pathname.slice(1); // elide initial "/"
if (bytes !== undefined) {
// eslint-disable-next-line no-await-in-loop
await archive.write(path, bytes);

Check warning on line 230 in packages/compartment-mapper/src/archive.js

View workflow job for this annotation

GitHub Actions / lint (18.x, ubuntu-latest)

The first `await` appearing in an async function must not be nested

Check warning on line 230 in packages/compartment-mapper/src/archive.js

View workflow job for this annotation

GitHub Actions / lint (20.x, ubuntu-latest)

The first `await` appearing in an async function must not be nested
}
}
}
Expand Down Expand Up @@ -291,7 +294,7 @@
* @param {ArchiveOptions} [options]
* @returns {Promise<{sources: Sources, compartmentMapBytes: Uint8Array, sha512?: string}>}
*/
const digestLocation = async (powers, moduleLocation, options) => {
const digestLocation = async (powers, moduleLocation, options = {}) => {
const {
moduleTransforms,
modules: exitModules = {},
Expand All @@ -303,7 +306,17 @@
importHook: exitModuleImportHook = undefined,
policy = undefined,
sourceMapHook = undefined,
} = options || {};
parserForLanguage: parserForLanguageOption = {},
languageForExtension: languageForExtensionOption = {},
} = options;

const parserForLanguage = freeze(
assign(create(null), defaultParserForLanguage, parserForLanguageOption),
);
const languageForExtension = freeze(
assign(create(null), languageForExtensionOption),
);

const { read, computeSha512 } = unpackReadPowers(powers);
const {
packageLocation,
Expand Down Expand Up @@ -359,6 +372,7 @@
makeImportHook,
moduleTransforms,
parserForLanguage,
languageForExtension,
archiveOnly: true,
});
await compartment.load(entryModuleSpecifier);
Expand Down
50 changes: 31 additions & 19 deletions packages/compartment-mapper/src/bundle.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
// @ts-check
/* eslint no-shadow: 0 */

/** @import {ResolveHook} from 'ses' */
/** @import {PrecompiledStaticModuleInterface} from 'ses' */
/** @import {ParserImplementation} from './types.js' */
/** @import {ParserForLanguage} from './types.js' */
/** @import {CompartmentDescriptor} from './types.js' */
/** @import {CompartmentSources} from './types.js' */
/** @import {ReadFn} from './types.js' */
Expand All @@ -29,18 +28,23 @@ import cjsSupport from './bundle-cjs.js';

const textEncoder = new TextEncoder();

const { freeze } = Object;
const { quote: q } = assert;

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

/**
* @param {Record<string, CompartmentDescriptor>} compartmentDescriptors
Expand Down Expand Up @@ -161,13 +165,7 @@ function getBundlerKitForModule(module) {
/**
* @param {ReadFn} read
* @param {string} moduleLocation
* @param {object} [options]
* @param {ModuleTransforms} [options.moduleTransforms]
* @param {boolean} [options.dev]
* @param {Set<string>} [options.tags]
* @param {object} [options.commonDependencies]
* @param {Array<string>} [options.searchSuffixes]
* @param {import('./types.js').SourceMapHook} [options.sourceMapHook]
* @param {ArchiveOptions} [options]
* @returns {Promise<string>}
*/
export const makeBundle = async (read, moduleLocation, options) => {
Expand All @@ -178,9 +176,22 @@ export const makeBundle = async (read, moduleLocation, options) => {
searchSuffixes,
commonDependencies,
sourceMapHook = undefined,
parserForLanguage: parserForLanguageOption = {},
languageForExtension: languageForExtensionOption = {},
} = options || {};
const tags = new Set(tagsOption);

const parserForLanguage = Object.freeze(
Object.assign(
Object.create(null),
defaultParserForLanguage,
parserForLanguageOption,
),
);
const languageForExtension = Object.freeze(
Object.assign(Object.create(null), languageForExtensionOption),
);

const {
packageLocation,
packageDescriptorText,
Expand Down Expand Up @@ -223,6 +234,7 @@ export const makeBundle = async (read, moduleLocation, options) => {
makeImportHook,
moduleTransforms,
parserForLanguage,
languageForExtension,
});
await compartment.load(entryModuleSpecifier);

Expand Down
Loading
Loading