Skip to content

Commit

Permalink
feat(bundle-source): --no-comment
Browse files Browse the repository at this point in the history
  • Loading branch information
kriskowal committed Aug 20, 2024
1 parent 1b4acf0 commit fa48cac
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 7 deletions.
7 changes: 7 additions & 0 deletions packages/bundle-source/NEWS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
User-visible changes to `@endo/bundle-source`:

# Next version

- Adds support for `--no-comment` (`-X`) that blanks out the interior of
comments in `endoScript` and `endoZipBase64` formats to reduce bundle size
without compromising cursor position correspondence between source and bundle
code.

# v3.3.0 (2024-07-30)

- Adds support for `--no-transforms` (`-T`) which generates bundles with
Expand Down
8 changes: 8 additions & 0 deletions packages/bundle-source/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ entry instead of `main` in `package.json`, if not overridden by explicit
The `development` condition additionally implies that the bundle may import
`devDependencies` from the package containing the entry module.
## Comment Elision
The `--no-comment` (`-X`) flag with `--format` `endoScript` or `endoZipBase64`
(default) causes the bundler to blank out the interior of comments, without
compromising line or column number cursor advancement.
This can reduce bundle size without harming the debug experience any more than
other transforms.
## Source maps
With the `moduleFormat` of `endoZipBase64`, the bundler can generate source
Expand Down
23 changes: 20 additions & 3 deletions packages/bundle-source/cache.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const { Fail, quote: q } = assert;
* @property {string} bundleTime ISO format
* @property {number} bundleSize
* @property {boolean} noTransforms
* @property {boolean} elideComments
* @property {ModuleFormat} format
* @property {string[]} conditions
* @property {{ relative: string, absolute: string }} moduleSource
Expand Down Expand Up @@ -52,6 +53,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
* @param {Logger} [log]
* @param {object} [options]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {string[]} [options.conditions]
* @param {ModuleFormat} [options.format]
*/
Expand All @@ -60,6 +62,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {

const {
noTransforms = false,
elideComments = false,
format = 'endoZipBase64',
conditions = [],
} = options;
Expand Down Expand Up @@ -93,7 +96,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {

const bundle = await bundleSource(
rootPath,
{ ...bundleOptions, noTransforms, format, conditions },
{ ...bundleOptions, noTransforms, elideComments, format, conditions },
{
...readPowers,
read: loggedRead,
Expand Down Expand Up @@ -122,6 +125,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
}),
),
noTransforms,
elideComments,
format,
conditions,
};
Expand Down Expand Up @@ -152,6 +156,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
* @param {BundleMeta} [meta]
* @param {object} [options]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {ModuleFormat} [options.format]
* @param {string[]} [options.conditions]
* @returns {Promise<BundleMeta>}
Expand All @@ -166,6 +171,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
await null;
const {
noTransforms: expectedNoTransforms = false,
elideComments: expectedElideComments = false,
format: expectedFormat = DEFAULT_MODULE_FORMAT,
conditions: expectedConditions = [],
} = options;
Expand Down Expand Up @@ -194,12 +200,14 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
moduleSource: { absolute: moduleSource },
format = 'endoZipBase64',
noTransforms = false,
elideComments = false,
conditions = [],
} = meta;
conditions.sort();
assert.equal(bundleFileName, toBundleName(targetName));
assert.equal(format, expectedFormat);
assert.equal(noTransforms, expectedNoTransforms);
assert.equal(elideComments, expectedElideComments);
assert.equal(conditions.length, expectedConditions.length);
conditions.forEach((tag, index) => {
assert.equal(tag, expectedConditions[index]);
Expand Down Expand Up @@ -249,6 +257,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
* @param {Logger} [log]
* @param {object} [options]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {ModuleFormat} [options.format]
* @param {string[]} [options.conditions]
* @returns {Promise<BundleMeta>}
Expand All @@ -269,13 +278,15 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
meta = await validate(targetName, rootPath, log, meta, {
format: options.format,
noTransforms: options.noTransforms,
elideComments: options.elideComments,
conditions: options.conditions,
});
const {
bundleTime,
bundleSize,
contents,
noTransforms,
elideComments,
format = 'endoZipBase64',
conditions = [],
} = meta;
Expand All @@ -288,7 +299,9 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
bundleTime,
'with size',
bundleSize,
noTransforms ? 'w/o transforms' : 'with transforms',
noTransforms
? 'w/o transforms'
: 'with transforms' + (elideComments ? ' and comments elided' : ''),

Check failure on line 304 in packages/bundle-source/cache.js

View workflow job for this annotation

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

Unexpected string concatenation

Check failure on line 304 in packages/bundle-source/cache.js

View workflow job for this annotation

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

Unexpected string concatenation
'with format',
format,
'and conditions',
Expand All @@ -308,6 +321,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
bundleTime,
contents,
noTransforms,
elideComments,
format = 'endoZipBase64',
conditions = [],
} = meta;
Expand All @@ -319,7 +333,9 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
bundleFileName,
'at',
bundleTime,
noTransforms ? 'w/o transforms' : 'with transforms',
noTransforms
? 'w/o transforms'
: 'with transforms' + (elideComments ? ' and comments elided' : ''),

Check failure on line 338 in packages/bundle-source/cache.js

View workflow job for this annotation

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

Unexpected string concatenation

Check failure on line 338 in packages/bundle-source/cache.js

View workflow job for this annotation

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

Unexpected string concatenation
'with format',
format,
'and conditions',
Expand All @@ -337,6 +353,7 @@ export const makeBundleCache = (wr, cwd, readPowers, opts) => {
* @param {Logger} [log]
* @param {object} [options]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {ModuleFormat} [options.format]
* @param {string[]} [options.conditions]
*/
Expand Down
4 changes: 4 additions & 0 deletions packages/bundle-source/demo/meaningful.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import json from './meaning.json';

/**
* This comment will be blanked with the elideComments / --no-comment feature
* enabled.
*/
export const meaning = json.meaning;
9 changes: 8 additions & 1 deletion packages/bundle-source/src/endo.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,14 @@ const textDecoder = new TextDecoder();

export const makeBundlingKit = (
{ pathResolve, userInfo, computeSha512, platform, env },
{ cacheSourceMaps, noTransforms, commonDependencies, dev },
{ cacheSourceMaps, elideComments, noTransforms, commonDependencies, dev },
) => {
if (noTransforms && elideComments) {
throw new Error(
'bundleSource endoZipBase64 cannot elideComments with noTransforms',
);
}

const sourceMapJobs = new Set();
let writeSourceMap = Function.prototype;
if (cacheSourceMaps) {
Expand Down Expand Up @@ -112,6 +118,7 @@ export const makeBundlingKit = (
sourceType: babelSourceType,
sourceMap,
sourceMapUrl: new URL(specifier, location).href,
elideComments,
}));
const objectBytes = textEncoder.encode(object);
return { bytes: objectBytes, parser, sourceMap };
Expand Down
16 changes: 15 additions & 1 deletion packages/bundle-source/src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,20 @@ bundle-source [-Tft] --cache-js|--cache-json <cache/> (<entry.js> <bundle-name>)
-f,--format endoZipBase64*|nestedEvaluate|getExport
-C,--condition <condition> (browser, node, development, &c)
-C development (to access devDependencies)
-T,--no-transforms`;
-T,--no-transforms
-X,--no-comment`;

const options = /** @type {const} */ ({
'no-transforms': {
type: 'boolean',
short: 'T',
multiple: false,
},
'no-comment': {
type: 'boolean',
short: 'X',
multiple: false,
},
'cache-js': {
type: 'string',
multiple: false,
Expand Down Expand Up @@ -61,6 +67,7 @@ export const main = async (args, { loadModule, pid, log }) => {
format: moduleFormat = 'endoZipBase64',
condition: conditions = [],
'no-transforms': noTransforms,
'no-comment': elideComments,
'cache-json': cacheJson,
'cache-js': cacheJs,
// deprecated
Expand All @@ -69,6 +76,11 @@ export const main = async (args, { loadModule, pid, log }) => {
positionals,
} = parseArgs({ args, options, allowPositionals: true });

if (noTransforms && elideComments) {
throw Error(
`Cannot elide comments without transforms (-T,--no-transforms + -X,--no-comment)`,
);
}
if (!SUPPORTED_FORMATS.includes(moduleFormat)) {
throw Error(`Unsupported format: ${moduleFormat}\n\n${USAGE}`);
}
Expand All @@ -94,6 +106,7 @@ export const main = async (args, { loadModule, pid, log }) => {
const [entryPath] = positionals;
const bundle = await bundleSource(entryPath, {
noTransforms,
elideComments,
format,
conditions,
});
Expand Down Expand Up @@ -125,6 +138,7 @@ export const main = async (args, { loadModule, pid, log }) => {
// eslint-disable-next-line no-await-in-loop
await cache.validateOrAdd(bundleRoot, bundleName, undefined, {
noTransforms,
elideComments,
format,
conditions,
});
Expand Down
4 changes: 4 additions & 0 deletions packages/bundle-source/src/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const readPowers = makeReadPowers({ fs, url, crypto });
* @param {boolean} [options.dev]
* @param {boolean} [options.cacheSourceMaps]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {Record<string, string>} [options.commonDependencies]
* @param {object} [grantedPowers]
* @param {(bytes: string | Uint8Array) => string} [grantedPowers.computeSha512]
Expand All @@ -37,9 +38,11 @@ export async function bundleScript(
dev = false,
cacheSourceMaps = false,
noTransforms = false,
elideComments = false,
conditions = [],
commonDependencies,
} = options;

const powers = { ...readPowers, ...grantedPowers };
const {
computeSha512,
Expand All @@ -63,6 +66,7 @@ export async function bundleScript(
{
cacheSourceMaps,
noTransforms,
elideComments,
commonDependencies,
dev,
},
Expand Down
3 changes: 3 additions & 0 deletions packages/bundle-source/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ export {};
* @property {T} [format]
* @property {boolean} [dev] - development mode, for test bundles that need
* access to devDependencies of the entry package.
* @property {boolean} [elideComments] - when true for the `endoScript` and
* `endoZipBase64` format, replaces the interior of comments with blank space
* that advances the cursor the same number of lines and columns.
* @property {boolean} [noTransforms] - when true, generates a bundle with the
* original sources instead of SES-shim specific ESM and CJS. This may become
* default in a future major version.
Expand Down
3 changes: 3 additions & 0 deletions packages/bundle-source/src/zip-base64.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const readPowers = makeReadPowers({ fs, url, crypto });
* @param {boolean} [options.dev]
* @param {boolean} [options.cacheSourceMaps]
* @param {boolean} [options.noTransforms]
* @param {boolean} [options.elideComments]
* @param {string[]} [options.conditions]
* @param {Record<string, string>} [options.commonDependencies]
* @param {object} [grantedPowers]
Expand All @@ -40,6 +41,7 @@ export async function bundleZipBase64(
dev = false,
cacheSourceMaps = false,
noTransforms = false,
elideComments = false,
conditions = [],
commonDependencies,
} = options;
Expand All @@ -66,6 +68,7 @@ export async function bundleZipBase64(
{
cacheSourceMaps,
noTransforms,
elideComments,
commonDependencies,
dev,
},
Expand Down
18 changes: 16 additions & 2 deletions packages/bundle-source/test/endo-script-format.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,30 @@ import test from '@endo/ses-ava/prepare-endo.js';
import * as url from 'url';
import bundleSource from '../src/index.js';

test('endo script format', async t => {
const generate = async (options = {}) => {
const entryPath = url.fileURLToPath(
new URL(`../demo/meaning.js`, import.meta.url),
);
const bundle = await bundleSource(entryPath, {
return bundleSource(entryPath, {
format: 'endoScript',
...options,
});
};

test('endo script format', async t => {
const bundle = await generate();
t.is(bundle.moduleFormat, 'endoScript');
const { source } = bundle;
const compartment = new Compartment();
const ns = compartment.evaluate(source);
t.is(ns.meaning, 42);
});

test('endo script format is smaller with blank comments', async t => {
const bigBundle = await generate();
const smallBundle = await generate({ elideComments: true });
const compartment = new Compartment();
const ns = compartment.evaluate(smallBundle.source);
t.is(ns.meaning, 42);
t.assert(smallBundle.source.length < bigBundle.source.length);
});

0 comments on commit fa48cac

Please sign in to comment.