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