Skip to content

Commit

Permalink
Merge pull request #1708 from endojs/mfig-bundle-source-types
Browse files Browse the repository at this point in the history
feat(bundle-source): type `bundleSource` more comprehensively
  • Loading branch information
michaelfig authored Aug 1, 2023
2 parents 25e0936 + 670a02c commit ee5961d
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 43 deletions.
92 changes: 61 additions & 31 deletions packages/bundle-source/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -219,22 +219,23 @@ async function bundleZipBase64(startFilename, options = {}, powers = {}) {
.readFile(sourceMapTrackerPath, 'utf-8')
.then(async oldSha512 => {
oldSha512 = oldSha512.trim();
if (oldSha512 !== sha512) {
const oldSha512Head = oldSha512.slice(0, 2);
const oldSha512Tail = oldSha512.slice(2);
const oldSourceMapDirectory = pathResolve(
sourceMapsCacheDirectory,
oldSha512Head,
);
const oldSourceMapPath = pathResolve(
oldSourceMapDirectory,
`${oldSha512Tail}.map.json`,
);
await fs.promises.unlink(oldSourceMapPath);
const entries = await fs.promises.readdir(oldSourceMapDirectory);
if (entries.length === 0) {
await fs.promises.rmdir(oldSourceMapDirectory);
}
if (oldSha512 === sha512) {
return;
}
const oldSha512Head = oldSha512.slice(0, 2);
const oldSha512Tail = oldSha512.slice(2);
const oldSourceMapDirectory = pathResolve(
sourceMapsCacheDirectory,
oldSha512Head,
);
const oldSourceMapPath = pathResolve(
oldSourceMapDirectory,
`${oldSha512Tail}.map.json`,
);
await fs.promises.unlink(oldSourceMapPath);
const entries = await fs.promises.readdir(oldSourceMapDirectory);
if (entries.length === 0) {
await fs.promises.rmdir(oldSourceMapDirectory);
}
})
.catch(error => {
Expand Down Expand Up @@ -276,15 +277,22 @@ async function bundleZipBase64(startFilename, options = {}, powers = {}) {
sourceMapJobs.add(writeSourceMap(sourceMap, sourceDescriptor));
},
});
assert(sha512);
await Promise.all(sourceMapJobs);
const endoZipBase64 = encodeBase64(bytes);
return harden({
moduleFormat: 'endoZipBase64',
moduleFormat: /** @type {const} */ ('endoZipBase64'),
endoZipBase64,
endoZipBase64Sha512: sha512,
});
}

/**
* @template {'nestedEvaluate' | 'getExport'} T
* @param {string} startFilename
* @param {T} moduleFormat
* @param {*} powers
*/
async function bundleNestedEvaluateAndGetExports(
startFilename,
moduleFormat,
Expand Down Expand Up @@ -388,7 +396,9 @@ async function bundleNestedEvaluateAndGetExports(
// const sourceMap = `//# sourceMappingURL=${output[0].map.toUrl()}\n`;

// console.log(sourceMap);
/** @type {string} */
let sourceMap;
/** @type {string} */
let source;
if (moduleFormat === 'getExport') {
sourceMap = `//# sourceURL=${DEFAULT_FILE_PREFIX}/${entrypoint}\n`;
Expand All @@ -407,6 +417,7 @@ ${sourceBundle[entrypoint]}
return module.exports;
}
${sourceMap}`;
return harden({ moduleFormat, source, sourceMap });
} else if (moduleFormat === 'nestedEvaluate') {
sourceMap = `//# sourceURL=${DEFAULT_FILE_PREFIX}-preamble.js\n`;

Expand Down Expand Up @@ -530,31 +541,50 @@ function getExportWithNestedEvaluate(filePrefix) {
return computeExports(entrypoint, { require: systemRequire, systemEval }, {});
}
${sourceMap}`;
return harden({ moduleFormat, source, sourceMap });
}

// console.log(sourceMap);
return harden({ moduleFormat, source, sourceMap });
throw Error(`unrecognized moduleFormat ${moduleFormat}`);
}

/** @type {BundleSource} */
export default async function bundleSource(
const bundleSource = async (
startFilename,
options = {},
powers = undefined,
) {
) => {
if (typeof options === 'string') {
options = { format: options };
}
/** @type {{ format: ModuleFormat }} */
const { format: moduleFormat = DEFAULT_MODULE_FORMAT } = options;

if (!SUPPORTED_FORMATS.includes(moduleFormat)) {
throw Error(`moduleFormat ${moduleFormat} is not implemented`);
}
if (moduleFormat === 'endoZipBase64') {
return bundleZipBase64(startFilename, options, {
...readPowers,
...powers,
});
switch (moduleFormat) {
case 'endoZipBase64':
return bundleZipBase64(startFilename, options, {
...readPowers,
...powers,
});
case 'getExport':
return bundleNestedEvaluateAndGetExports(
startFilename,
moduleFormat,
powers,
);
case 'nestedEvaluate':
return bundleNestedEvaluateAndGetExports(
startFilename,
moduleFormat,
powers,
);
default:
if (!SUPPORTED_FORMATS.includes(moduleFormat)) {
throw Error(`moduleFormat ${moduleFormat} is not supported`);
}
throw Error(
`moduleFormat ${moduleFormat} is not implemented but is in ${SUPPORTED_FORMATS}`,
);
}
return bundleNestedEvaluateAndGetExports(startFilename, moduleFormat, powers);
}
};

export default bundleSource;
51 changes: 44 additions & 7 deletions packages/bundle-source/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,60 @@
*/

/**
* @callback BundleSource
* @typedef {BundleSourceEndoZipBase64 & BundleSourceGetExport & BundleSourceNestedEvaluate} BundleSource
*/

/**
* @callback BundleSourceEndoZipBase64
* @param {string} startFilename - the filepath to start the bundling from
* @param {ModuleFormatOrOptions<'endoZipBase64' | undefined>} moduleFormat
* @param {object=} powers
* @param {ReadFn=} powers.read
* @param {CanonicalFn=} powers.canonical
* @returns {Promise<{
* moduleFormat: 'endoZipBase64',
* endoZipBase64: string,
* endoZipBase64Sha512: string,
* }>}
*/

/**
* @callback BundleSourceGetExport
* @param {string} startFilename - the filepath to start the bundling from
* @param {(ModuleFormat | BundleOptions)=} moduleFormat
* @param {ModuleFormatOrOptions<'getExport'>} moduleFormat
* @param {object=} powers
* @param {ReadFn=} powers.read
* @param {CanonicalFn=} powers.canonical
* @returns {Promise<{
* endoZipBase64?: string,
* moduleFormat: ModuleFormat;
* source?: string,
* sourceMap?: string,
* moduleFormat: 'getExport',
* source: string,
* sourceMap: string,
* }>}
*/

/**
* @callback BundleSourceNestedEvaluate
* @param {string} startFilename - the filepath to start the bundling from
* @param {ModuleFormatOrOptions<'nestedEvaluate'>} moduleFormat
* @param {object=} powers
* @param {ReadFn=} powers.read
* @param {CanonicalFn=} powers.canonical
* @returns {Promise<{
* moduleFormat: 'nestedEvaluate',
* source: string,
* sourceMap: string,
* }>}
*/

/**
* @template {ModuleFormat | undefined} T
* @typedef {T | BundleOptions<T>} ModuleFormatOrOptions
*/

/**
* @template {ModuleFormat | undefined} T
* @typedef {object} BundleOptions
* @property {ModuleFormat} [format]
* @property {T} format
* @property {boolean} [dev] - development mode, for test bundles that need
* access to devDependencies of the entry package.
*/
Expand Down
11 changes: 7 additions & 4 deletions packages/bundle-source/test/sanity.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
import { lockdown } from '@endo/lockdown';

import url from 'url';
Expand Down Expand Up @@ -30,12 +31,12 @@ export function makeSanityTests(stackFiltering) {
url.fileURLToPath(new URL('../demo/dir1/encourage.js', import.meta.url)),
'endoZipBase64',
);
assert(endoZipBase64);

const bytes = decodeBase64(endoZipBase64);
const archive = await parseArchive(bytes);
// Call import by property to bypass SES censoring for dynamic import.
// eslint-disable-next-line dot-notation
const { namespace } = await archive['import']('.');
const { namespace } = await archive['import']();
const { message, encourage } = namespace;

t.is(message, `You're great!`);
Expand Down Expand Up @@ -138,7 +139,8 @@ export function makeSanityTests(stackFiltering) {
const srcMap2 = `(${src2})\n${map2}`;

// eslint-disable-next-line no-eval
const ex2 = (1, eval)(srcMap2)();
const eval2 = eval;
const ex2 = eval2(srcMap2)();
t.is(ex2.message, `You're great!`, 'exported message matches');
t.is(
ex2.encourage('Nick'),
Expand Down Expand Up @@ -171,6 +173,7 @@ export function makeSanityTests(stackFiltering) {
t.truthy(!src1.match(/beforeExpr,;/), 'source is not mangled that one way');
// the mangled form wasn't syntactically valid, do a quick check
// eslint-disable-next-line no-eval
(1, eval)(`(${src1})`);
const eval2 = eval;
eval2(`(${src1})`);
});
}
2 changes: 1 addition & 1 deletion packages/bundle-source/test/test-bigint-transform.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// @ts-check
import url from 'url';
import { test } from './prepare-test-env-ava.js';
import bundleSource from '../src/index.js';
Expand All @@ -8,6 +9,5 @@ test('bigint transform', async t => {
'getExport',
);
// console.log(bundle.source);
assert(bundle.source);
t.assert(bundle.source.indexOf('37n') >= 0);
});

0 comments on commit ee5961d

Please sign in to comment.