diff --git a/constraints.pro b/constraints.pro index bfe1280c9..48aa60a24 100644 --- a/constraints.pro +++ b/constraints.pro @@ -309,7 +309,6 @@ gen_enforced_field(WorkspaceCwd, 'scripts.changelog:update', CorrectChangelogUpd % All non-root packages must have the same "test" script. gen_enforced_field(WorkspaceCwd, 'scripts.test', 'vitest run --config vitest.config.ts') :- - WorkspaceCwd \= 'packages/shims', WorkspaceCwd \= 'packages/test-utils', WorkspaceCwd \= '.'. diff --git a/packages/extension/src/background.ts b/packages/extension/src/background.ts index b899e06a7..eff0c6b8e 100644 --- a/packages/extension/src/background.ts +++ b/packages/extension/src/background.ts @@ -1,6 +1,6 @@ /* eslint-disable import-x/no-unassigned-import */ import './dev-console.js'; -import './endoify.mjs'; +import './endoify.js'; /* eslint-enable import-x/no-unassigned-import */ import type { ExtensionMessage } from './shared.js'; diff --git a/packages/extension/src/endoify.test.ts b/packages/extension/src/endoify.test.ts new file mode 100644 index 000000000..645882923 --- /dev/null +++ b/packages/extension/src/endoify.test.ts @@ -0,0 +1,47 @@ +import './endoify.js'; +// eslint-disable-next-line n/no-extraneous-import +import type { HandledPromiseConstructor } from '@endo/eventual-send'; +import { describe, expect, it } from 'vitest'; + +describe('endoified', () => { + it('calls lockdown', () => { + expect(Object.isFrozen(Array.prototype)).toBe(true); // Due to `lockdown()`, and therefore `ses` + }); + + it('loads eventual-send', () => { + expect(typeof HandledPromise).not.toBe('undefined'); // Due to eventual send + }); +}); + +describe(`endoify`, () => { + const assertions = [ + (): boolean => typeof globalThis === 'object', + (): boolean => typeof lockdown === 'function', + (): boolean => typeof repairIntrinsics === 'function', + (): boolean => typeof Compartment === 'function', + (): boolean => typeof assert === 'function', + (): boolean => typeof HandledPromise === 'function', + (): boolean => typeof harden === 'function', + (): boolean => typeof getStackString === 'function', + (): boolean => { + try { + return !Object.assign(harden({ a: 1 }), { b: 2 }); + } catch { + return true; + } + }, + ]; + + for (const assertion of assertions) { + it(`asserts ${String(assertion).replace(/^.*?=>\s*/u, '')}`, () => { + expect(assertion()).toBe(true); + }); + } +}); + +declare global { + // eslint-disable-next-line no-var + var getStackString: (error: Error) => string; + // eslint-disable-next-line no-var + var HandledPromise: HandledPromiseConstructor; +} diff --git a/packages/extension/src/endoify.ts b/packages/extension/src/endoify.ts new file mode 100644 index 000000000..11479b6c9 --- /dev/null +++ b/packages/extension/src/endoify.ts @@ -0,0 +1,3 @@ +/* eslint-disable import-x/extensions */ +/* eslint-disable import-x/no-unassigned-import */ +import '@ocap/shims/endoify'; diff --git a/packages/extension/src/iframe-manager.test.ts b/packages/extension/src/iframe-manager.test.ts index 6c3d4c9a1..b8dd6ef16 100644 --- a/packages/extension/src/iframe-manager.test.ts +++ b/packages/extension/src/iframe-manager.test.ts @@ -1,3 +1,4 @@ +import './endoify.js'; import * as snapsUtils from '@metamask/snaps-utils'; import { delay, makePromiseKitMock } from '@ocap/test-utils'; import { vi, describe, it, expect } from 'vitest'; diff --git a/packages/extension/src/shared.test.ts b/packages/extension/src/shared.test.ts index 2412a8716..d10870d46 100644 --- a/packages/extension/src/shared.test.ts +++ b/packages/extension/src/shared.test.ts @@ -1,3 +1,4 @@ +import './endoify.js'; import { delay } from '@ocap/test-utils'; import { vi, describe, it, expect } from 'vitest'; diff --git a/packages/extension/vite.config.ts b/packages/extension/vite.config.ts index 7d5e5d364..36a591a40 100644 --- a/packages/extension/vite.config.ts +++ b/packages/extension/vite.config.ts @@ -14,10 +14,7 @@ const projectRoot = './src'; * Module specifiers that will be ignored by Rollup if imported, and therefore * not transformed. **Only applies to JavaScript and TypeScript files.** */ -const externalModules: readonly string[] = [ - './dev-console.js', - './endoify.mjs', -]; +const externalModules: readonly string[] = ['./dev-console.js', './endoify.js']; /** * Files that need to be statically copied to the destination directory. @@ -28,10 +25,7 @@ const staticCopyTargets: readonly string[] = [ 'manifest.json', // External modules 'dev-console.js', - '../../shims/dist/endoify.mjs', - // Dependencies of external modules - '../../shims/dist/eventual-send.mjs', - '../../../node_modules/ses/dist/ses.mjs', + '../../shims/dist/endoify.js', ]; // https://vitejs.dev/config/ @@ -56,6 +50,15 @@ export default defineConfig({ }, }, + resolve: { + alias: [ + { + find: '@ocap/shims/endoify', + replacement: './endoify.js', + }, + ], + }, + plugins: [ endoifyHtmlFilesPlugin(), viteStaticCopy({ @@ -73,25 +76,33 @@ export default defineConfig({ * @returns The Vite plugin. */ function endoifyHtmlFilesPlugin(): Plugin { - const endoifyElement = ''; + const endoifyElement = ''; return { name: 'externalize-plugin', async transformIndexHtml(htmlString): Promise { - if (htmlString.includes('endoify.mjs')) { + const htmlDoc = loadHtml(htmlString); + + if (htmlDoc('script[src="endoify.ts"]').length > 0) { + throw new Error( + `HTML document should not reference "endoify.ts" directly:\n${htmlString}`, + ); + } + + if (htmlDoc('script[src="endoify.js"]').length > 0) { throw new Error( `HTML document already references endoify script:\n${htmlString}`, ); } - const htmlDoc = loadHtml(htmlString); - if (htmlDoc('head').length !== 1 || htmlDoc('head script').length < 1) { + if (htmlDoc('head').length !== 1 || htmlDoc('head > script').length < 1) { throw new Error( `Expected HTML document with a single containing at least one