diff --git a/packages/shims/scripts/bundle.js b/packages/shims/scripts/bundle.js index cd6e3cba2..954eb8ad0 100644 --- a/packages/shims/scripts/bundle.js +++ b/packages/shims/scripts/bundle.js @@ -3,27 +3,25 @@ import 'ses'; import '@endo/lockdown/commit.js'; -import { mkdir } from 'node:fs/promises'; +import bundleSource from '@endo/bundle-source'; +import { mkdir, writeFile } from 'node:fs/promises'; import path from 'node:path'; import { fileURLToPath } from 'node:url'; import { rimraf } from 'rimraf'; -import { generateEndoScriptBundle } from './helpers/generate-endo-script-bundle.js'; - console.log('Bundling shims...'); const rootDir = fileURLToPath(new URL('..', import.meta.url)); const srcDir = path.resolve(rootDir, 'src'); const distDir = path.resolve(rootDir, 'dist'); -const argv = Object.freeze([...process.argv]); +const shim = 'endoify.js'; await mkdir(distDir, { recursive: true }); await rimraf(`${distDir}/*`, { glob: true }); -await generateEndoScriptBundle( - path.resolve(srcDir, 'endoify.js'), - path.resolve(distDir, `endoify.js`), - { argv }, -); +const { source } = await bundleSource(path.resolve(srcDir, shim), { + format: 'endoScript', +}); +await writeFile(path.resolve(distDir, shim), source); console.log('Success!'); diff --git a/packages/shims/scripts/helpers/generate-endo-script-bundle.js b/packages/shims/scripts/helpers/generate-endo-script-bundle.js deleted file mode 100644 index 9c0a5e323..000000000 --- a/packages/shims/scripts/helpers/generate-endo-script-bundle.js +++ /dev/null @@ -1,73 +0,0 @@ -// @ts-check - -import bundleSource from '@endo/bundle-source'; -import { writeFile } from 'node:fs/promises'; -import { fileURLToPath } from 'node:url'; - -import endoScriptIdentifierTransformPlugin from './rollup-plugin-endo-script-identifier-transform.js'; - -/** - * Generate an `endoScript` bundle from a specified module and its - * dependencies. Optionally, also rewriting the module shimming - * identifiers introduced by `@endo/module-source` to avoid errors - * for unexpected zero-width-joiner characters. - * - * When the `bundle` options are omitted, the default options - * used are: `{ format: 'endoScript' }`. - * - * The `rewrite` operation will be skipped when: - * - The `rewrite` is `false` - * - The `rewrite` option and the `argv` options are omitted - * - The `argv` option does not include `--with-zwj-rewrite` - * - * Otherwise, when the `rewrite` option is `true` or some of its - * options are omitted, the `argv` option is checked for the - * following flags: - * - `--with-zwj-rewrite` (not recommended) - * - `--zwj-rewrite-without-validation` (not recommended) - * - `--zwj-rewrite-debug` - * - `--zwj-rewrite-verbose` - * - `--zwj-rewrite-time` - * - * @param {string} specifier - The specifier of the module. - * @param {string} outputPath - The file path where the bundle will be written. - * @param {object} [options] - The fine-grained options for the specific operations. - * @param {string} [options.scope] - The root path used for reporting sanitization. - * @param {EndoScriptBundleSourceOptions} [options.bundle] - The fine-grained options passed to `bundleSource`. - * @param {EndoScriptIdentifierTransformOptions | boolean} [options.rewrite] - Wether to explicitly opt-out (`false`), opt-in (`true`), or the fine-grained options passed to `endoScriptIdentifierTransformPlugin`. - * @param {string[] | Readonly} [options.argv] - The command-line arguments to use for determining the defaults. - * @returns {Promise} - */ -export async function generateEndoScriptBundle(specifier, outputPath, options) { - const sourcePath = fileURLToPath(import.meta.resolve(specifier)); - - let { source } = await bundleSource(sourcePath, { - format: 'endoScript', - ...options?.bundle, - }); - - if (options?.rewrite ?? options?.argv?.includes?.('--with-zwj-rewrite')) { - source = - endoScriptIdentifierTransformPlugin({ - validation: - options?.argv && - !options?.argv?.includes?.('--zwj-rewrite-without-validation'), - debugging: - options?.argv && - ((options?.argv?.includes?.('--zwj-rewrite-verbose') && 'VERBOSE') || - options?.argv?.includes?.('--zwj-rewrite-debug')), - timing: options?.argv?.includes?.('--zwj-rewrite-time'), - ...Object(options?.rewrite), - scopedRoot: - options?.scope ?? - // @ts-ignore - options?.rewrite?.scopedRoot ?? - fileURLToPath(new URL('../../../../', import.meta.url)), - }).transform(source, specifier)?.code ?? source; - } - - await writeFile(outputPath, source); -} - -/** @typedef {import('@endo/bundle-source').BundleOptions<'endoScript'>} EndoScriptBundleSourceOptions */ -/** @typedef {import('./rollup-plugin-endo-script-identifier-transform.js').EndoScriptIdentifierTransformOptions} EndoScriptIdentifierTransformOptions */ diff --git a/packages/shims/scripts/helpers/rollup-plugin-endo-script-identifier-transform.js b/packages/shims/scripts/helpers/rollup-plugin-endo-script-identifier-transform.js deleted file mode 100644 index a2af47025..000000000 --- a/packages/shims/scripts/helpers/rollup-plugin-endo-script-identifier-transform.js +++ /dev/null @@ -1,161 +0,0 @@ -// @ts-check - -/* eslint-disable jsdoc/require-returns-type */ -/* eslint-disable no-plusplus */ - -/** - * Quickly removes the normalized scope prefix from a normalized pathname. - * - * @param {string} normalizedPathname - The normalized pathname. - * @param {string} [normalizedScope] - The normalized scope. - * @returns {string} The scoped path. - */ -const scopedPath = (normalizedPathname, normalizedScope = '') => - normalizedPathname.slice( - normalizedPathname.indexOf(normalizedScope) + normalizedScope.length || 0, - ); - -/** - * Rollup plugin to transform endoScript identifiers. - * - * @param {object} [options] - The plugin options. - * @param {(id: string) => boolean} [options.maybeEndoScript] - A function to determine if the script should be transformed. - * @param {string} [options.scopedRoot] - The root directory to scope the transformed script. - * @param {boolean} [options.timing] - Whether to log the transform time. - * @param {boolean | 'VERBOSE'} [options.debugging] - Whether to log the transform details. - * @param {boolean} [options.validation] - Whether to validate the transform. - * @returns The Rollup plugin. - */ -export default function endoScriptIdentifierTransformPlugin({ - maybeEndoScript = undefined, - scopedRoot = undefined, - timing = false, - debugging = false, - validation = true, -} = {}) { - const zwjIdentifierMatcher = - /(? & Record<'length'|'delta',number>>} */ ({}) - : undefined; - - let replacements = 0; - - const replacedCode = code.replace( - zwjIdentifierMatcher, - (match, prefix, { length: underscores }, identifier, index) => { - const replacement = - prefix === 'h' - ? `$${'\u034f'.repeat(underscores)}${identifier}\u034f$` - : `$\u034f$${'\u034f'.repeat(underscores)}${identifier}`; - - if (changes) { - changes[index] = { - match, - replacement, - identifier, - prefix, - length: match.length, - delta: replacement.length - match.length, - }; - } - - replacements++; - return replacement; - }, - ); - - timing && console.timeLog(tag); - - const delta = replacedCode.length - code.length; - - debugging && delta !== 0 && console.warn(`Delta: ${delta} [expected: 0]`); - - if (debugging) { - debugging === 'VERBOSE' && console.table(changes); - console.dir( - { id: scopedId ?? id, replacements, delta }, - { - depth: debugging === 'VERBOSE' ? 2 : 1, - maxStringLength: 100, - compact: true, - }, - ); - } - - if (delta !== 0) { - throw new Error( - `Mismatched lengths: ${code.length} ${delta > 0 ? '<' : '>'} ${ - replacedCode.length - } in ${scopedId ?? id}`, - ); - } - - if (changes) { - let matched = 0; - for (const match of replacedCode.matchAll(cgjIdentifierMatcher)) { - if (match[0] !== changes[match.index ?? -1]?.replacement) { - throw new Error( - `Mismatched replacement: ${match[0]} !== ${ - changes[match.index ?? -1]?.replacement - } in ${scopedId ?? id}`, - ); - } - if (match[1] !== changes[match.index ?? -1]?.identifier) { - throw new Error( - `Mismatched replacement: ${match[1]} !== ${ - changes[match.index ?? -1]?.identifier - } in ${scopedId ?? id}`, - ); - } - matched++; - } - if (matched !== replacements) { - throw new Error( - `Mismatched replacements: ${matched} !== ${replacements} in ${ - scopedId ?? id - }`, - ); - } - } - - timing && console.timeEnd(tag); - - return { - code: replacedCode, - moduleSideEffects: 'no-treeshake', - }; - }, - }; -} - -/** @typedef {Exclude[0], undefined>} EndoScriptIdentifierTransformOptions */