From 1698612ee4863a6e1bef8335546913cf6f7252f8 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 16 Jul 2024 16:44:29 +0200 Subject: [PATCH 01/31] feat: Add Ocap Kernel playground extension --- .../src/extension/background.js | 64 +++++++++++++++++++ .../src/extension/manifest.json | 11 ++++ .../src/extension/offscreen.html | 2 + .../src/extension/offscreen.js | 24 +++++++ 4 files changed, 101 insertions(+) create mode 100644 packages/ocap-playground/src/extension/background.js create mode 100644 packages/ocap-playground/src/extension/manifest.json create mode 100644 packages/ocap-playground/src/extension/offscreen.html create mode 100644 packages/ocap-playground/src/extension/offscreen.js diff --git a/packages/ocap-playground/src/extension/background.js b/packages/ocap-playground/src/extension/background.js new file mode 100644 index 000000000..9772c3306 --- /dev/null +++ b/packages/ocap-playground/src/extension/background.js @@ -0,0 +1,64 @@ +const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; + +// Send +chrome.action.onClicked.addListener(async () => { + sendMessage( + 'greetings', + { name: 'Kernel' }, + ); +}); + +async function sendMessage(type, data) { + await provideOffScreenDocument(); + + chrome.runtime.sendMessage({ + type, + target: 'offscreen', + data + }); +} + +async function provideOffScreenDocument() { + if (!(await hasDocument())) { + await chrome.offscreen.createDocument({ + url: OFFSCREEN_DOCUMENT_PATH, + reasons: [chrome.offscreen.Reason.IFRAME_SCRIPTING], + justification: `Surely you won't object to our capabilities?`, + }); + } +} + +// Receive +chrome.runtime.onMessage.addListener(handleMessage); + +async function handleMessage(message) { + if (message.target !== 'background') { + return; + } + + switch (message.type) { + case 'salutations': + console.log(message.data); + closeOffscreenDocument(); + break; + default: + console.error(`Received unexpected message type: "${message.type}"`); + } +} + +async function closeOffscreenDocument() { + if (!(await hasDocument())) { + return; + } + await chrome.offscreen.closeDocument(); +} + +async function hasDocument() { + const allClients = await clients.matchAll(); + for (const client of allClients) { + if (client.url.endsWith(OFFSCREEN_DOCUMENT_PATH)) { + return true; + } + } + return false; +} diff --git a/packages/ocap-playground/src/extension/manifest.json b/packages/ocap-playground/src/extension/manifest.json new file mode 100644 index 000000000..5ad5854eb --- /dev/null +++ b/packages/ocap-playground/src/extension/manifest.json @@ -0,0 +1,11 @@ +{ + "name": "Ocap Kernel Playground Extension", + "version": "0.0", + "description": "For running Ocap Kernel experiments in an extension environment.", + "manifest_version": 3, + "background": { + "service_worker": "background.js" + }, + "action": {}, + "permissions": ["offscreen"] +} diff --git a/packages/ocap-playground/src/extension/offscreen.html b/packages/ocap-playground/src/extension/offscreen.html new file mode 100644 index 000000000..d4f61fc8b --- /dev/null +++ b/packages/ocap-playground/src/extension/offscreen.html @@ -0,0 +1,2 @@ + + diff --git a/packages/ocap-playground/src/extension/offscreen.js b/packages/ocap-playground/src/extension/offscreen.js new file mode 100644 index 000000000..ff1029077 --- /dev/null +++ b/packages/ocap-playground/src/extension/offscreen.js @@ -0,0 +1,24 @@ +chrome.runtime.onMessage.addListener(handleMessage); + +async function handleMessage(message) { + if (message.target !== 'offscreen') { + return; + } + + switch (message.type) { + case 'greetings': + reply('salutations', `Good day to you, ${message.data.name}!`) + break; + default: + console.error(`Received unexpected message type: "${message.type}"`); + return; + } +} + +function reply(type, data) { + chrome.runtime.sendMessage({ + data, + target: 'background', + type, + }) +} From d86a8c3035e104ce8a5fdffc7dd388973377c2e5 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 16 Jul 2024 16:46:45 +0200 Subject: [PATCH 02/31] refactor: Rename "playground" to "skunkworks" --- packages/{ocap-playground => ocap-skunkworks}/README.md | 8 ++++---- .../{ocap-playground => ocap-skunkworks}/jest.config.js | 0 .../{ocap-playground => ocap-skunkworks}/package.json | 6 +++--- .../src/extension/background.js | 0 .../src/extension/manifest.json | 2 +- .../src/extension/offscreen.html | 0 .../src/extension/offscreen.js | 0 .../src/index.test.ts | 0 .../{ocap-playground => ocap-skunkworks}/src/index.ts | 0 .../tsconfig.build.json | 0 .../{ocap-playground => ocap-skunkworks}/tsconfig.json | 0 .../{ocap-playground => ocap-skunkworks}/typedoc.json | 0 tsconfig.build.json | 2 +- tsconfig.json | 2 +- 14 files changed, 10 insertions(+), 10 deletions(-) rename packages/{ocap-playground => ocap-skunkworks}/README.md (57%) rename packages/{ocap-playground => ocap-skunkworks}/jest.config.js (100%) rename packages/{ocap-playground => ocap-skunkworks}/package.json (89%) rename packages/{ocap-playground => ocap-skunkworks}/src/extension/background.js (100%) rename packages/{ocap-playground => ocap-skunkworks}/src/extension/manifest.json (84%) rename packages/{ocap-playground => ocap-skunkworks}/src/extension/offscreen.html (100%) rename packages/{ocap-playground => ocap-skunkworks}/src/extension/offscreen.js (100%) rename packages/{ocap-playground => ocap-skunkworks}/src/index.test.ts (100%) rename packages/{ocap-playground => ocap-skunkworks}/src/index.ts (100%) rename packages/{ocap-playground => ocap-skunkworks}/tsconfig.build.json (100%) rename packages/{ocap-playground => ocap-skunkworks}/tsconfig.json (100%) rename packages/{ocap-playground => ocap-skunkworks}/typedoc.json (100%) diff --git a/packages/ocap-playground/README.md b/packages/ocap-skunkworks/README.md similarity index 57% rename from packages/ocap-playground/README.md rename to packages/ocap-skunkworks/README.md index d67d60bf3..fd48d79d9 100644 --- a/packages/ocap-playground/README.md +++ b/packages/ocap-skunkworks/README.md @@ -1,14 +1,14 @@ -# `@metamask/ocap-playground` +# `@metamask/ocap-skunkworks` -An Ocap Kernel playground. +A home for Ocap Kernel experiments. ## Installation -`yarn add @metamask/ocap-playground` +`yarn add @metamask/ocap-skunkworks` or -`npm install @metamask/ocap-playground` +`npm install @metamask/ocap-skunkworks` ## Contributing diff --git a/packages/ocap-playground/jest.config.js b/packages/ocap-skunkworks/jest.config.js similarity index 100% rename from packages/ocap-playground/jest.config.js rename to packages/ocap-skunkworks/jest.config.js diff --git a/packages/ocap-playground/package.json b/packages/ocap-skunkworks/package.json similarity index 89% rename from packages/ocap-playground/package.json rename to packages/ocap-skunkworks/package.json index 00ea9a73f..d5f121598 100644 --- a/packages/ocap-playground/package.json +++ b/packages/ocap-skunkworks/package.json @@ -1,8 +1,8 @@ { - "name": "@metamask/ocap-playground", + "name": "@metamask/ocap-skunkworks", "version": "0.0.0", "private": true, - "description": "An Ocap Kernel playground", + "description": "A home for Ocap Kernel experiments", "repository": { "type": "git", "url": "https://github.com/MetaMask/ocap-kernel.git" @@ -13,7 +13,7 @@ "scripts": { "build": "ts-bridge --project tsconfig.build.json --clean", "build:docs": "typedoc", - "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-playground", + "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-skunkworks", "publish:preview": "yarn npm publish --tag preview", "test": "jest --reporters=jest-silent-reporter", "posttest": "jest-it-up", diff --git a/packages/ocap-playground/src/extension/background.js b/packages/ocap-skunkworks/src/extension/background.js similarity index 100% rename from packages/ocap-playground/src/extension/background.js rename to packages/ocap-skunkworks/src/extension/background.js diff --git a/packages/ocap-playground/src/extension/manifest.json b/packages/ocap-skunkworks/src/extension/manifest.json similarity index 84% rename from packages/ocap-playground/src/extension/manifest.json rename to packages/ocap-skunkworks/src/extension/manifest.json index 5ad5854eb..5eb4ad00e 100644 --- a/packages/ocap-playground/src/extension/manifest.json +++ b/packages/ocap-skunkworks/src/extension/manifest.json @@ -1,5 +1,5 @@ { - "name": "Ocap Kernel Playground Extension", + "name": "Ocap Kernel Skunkworks Extension", "version": "0.0", "description": "For running Ocap Kernel experiments in an extension environment.", "manifest_version": 3, diff --git a/packages/ocap-playground/src/extension/offscreen.html b/packages/ocap-skunkworks/src/extension/offscreen.html similarity index 100% rename from packages/ocap-playground/src/extension/offscreen.html rename to packages/ocap-skunkworks/src/extension/offscreen.html diff --git a/packages/ocap-playground/src/extension/offscreen.js b/packages/ocap-skunkworks/src/extension/offscreen.js similarity index 100% rename from packages/ocap-playground/src/extension/offscreen.js rename to packages/ocap-skunkworks/src/extension/offscreen.js diff --git a/packages/ocap-playground/src/index.test.ts b/packages/ocap-skunkworks/src/index.test.ts similarity index 100% rename from packages/ocap-playground/src/index.test.ts rename to packages/ocap-skunkworks/src/index.test.ts diff --git a/packages/ocap-playground/src/index.ts b/packages/ocap-skunkworks/src/index.ts similarity index 100% rename from packages/ocap-playground/src/index.ts rename to packages/ocap-skunkworks/src/index.ts diff --git a/packages/ocap-playground/tsconfig.build.json b/packages/ocap-skunkworks/tsconfig.build.json similarity index 100% rename from packages/ocap-playground/tsconfig.build.json rename to packages/ocap-skunkworks/tsconfig.build.json diff --git a/packages/ocap-playground/tsconfig.json b/packages/ocap-skunkworks/tsconfig.json similarity index 100% rename from packages/ocap-playground/tsconfig.json rename to packages/ocap-skunkworks/tsconfig.json diff --git a/packages/ocap-playground/typedoc.json b/packages/ocap-skunkworks/typedoc.json similarity index 100% rename from packages/ocap-playground/typedoc.json rename to packages/ocap-skunkworks/typedoc.json diff --git a/tsconfig.build.json b/tsconfig.build.json index 44e5c2c8f..9bedded2e 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,5 +1,5 @@ { "files": [], "include": [], - "references": [{ "path": "./packages/ocap-playground/tsconfig.build.json" }] + "references": [{ "path": "./packages/ocap-skunkworks/tsconfig.build.json" }] } diff --git a/tsconfig.json b/tsconfig.json index 245e1f474..91235f869 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,5 +6,5 @@ }, "files": [], "include": [], - "references": [{ "path": "./packages/ocap-playground" }] + "references": [{ "path": "./packages/ocap-skunkworks" }] } From b8ee32f03f66b8e44ba92576c9f6300b83c0714c Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 16 Jul 2024 22:02:07 +0200 Subject: [PATCH 03/31] build: Build extension using Vite --- .eslintrc.js | 22 +- packages/ocap-skunkworks/.eslintrc.js | 13 + packages/ocap-skunkworks/package.json | 13 +- .../src/extension/background.js | 21 +- .../src/extension/offscreen.html | 2 +- .../src/extension/offscreen.js | 5 +- packages/ocap-skunkworks/src/index.test.ts | 9 - packages/ocap-skunkworks/src/index.ts | 9 - packages/ocap-skunkworks/tsconfig.json | 2 +- .../ocap-skunkworks/vite.config.extension.mjs | 29 + tsconfig.packages.json | 1 + yarn.lock | 578 ++++++++++++++++-- 12 files changed, 612 insertions(+), 92 deletions(-) create mode 100644 packages/ocap-skunkworks/.eslintrc.js delete mode 100644 packages/ocap-skunkworks/src/index.test.ts delete mode 100644 packages/ocap-skunkworks/src/index.ts create mode 100644 packages/ocap-skunkworks/vite.config.extension.mjs diff --git a/.eslintrc.js b/.eslintrc.js index b008601f1..be92250ac 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -40,6 +40,14 @@ module.exports = { }, }, + { + files: ['*.mjs'], + parserOptions: { + sourceType: 'module', + ecmaVersion: '2020', + }, + }, + { files: ['*.ts'], extends: ['@metamask/eslint-config-typescript'], @@ -50,20 +58,6 @@ module.exports = { rules: { // Enable rules that are disabled in `@metamask/eslint-config-typescript` '@typescript-eslint/no-explicit-any': 'error', - - // TODO: auto-fix breaks stuff - '@typescript-eslint/promise-function-async': 'off', - - // Without the `allowAny` option, this rule causes a lot of false - // positives. - '@typescript-eslint/restrict-template-expressions': [ - 'error', - { - allowAny: true, - allowBoolean: true, - allowNumber: true, - }, - ], }, }, diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/ocap-skunkworks/.eslintrc.js new file mode 100644 index 000000000..c0711cec2 --- /dev/null +++ b/packages/ocap-skunkworks/.eslintrc.js @@ -0,0 +1,13 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + + overrides: [ + { + files: ['src/extension/**/*.js'], + globals: { chrome: 'readonly', clients: 'readonly' }, + rules: { + 'jsdoc/require-jsdoc': 'off', + }, + }, + ], +}; diff --git a/packages/ocap-skunkworks/package.json b/packages/ocap-skunkworks/package.json index d5f121598..ff4d8b95a 100644 --- a/packages/ocap-skunkworks/package.json +++ b/packages/ocap-skunkworks/package.json @@ -11,15 +11,18 @@ "dist/" ], "scripts": { - "build": "ts-bridge --project tsconfig.build.json --clean", - "build:docs": "typedoc", + "build:extension": "vite build -c vite.config.extension.mjs", + "build:library": "ts-bridge --project tsconfig.build.json --clean", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-skunkworks", "publish:preview": "yarn npm publish --tag preview", + "start": "vite -c vite.config.extension.mjs", "test": "jest --reporters=jest-silent-reporter", "posttest": "jest-it-up", "test:clean": "jest --clearCache", "test:verbose": "jest --verbose", - "test:watch": "jest --watch" + "test:watch": "jest --watch", + "build": "ts-bridge --project tsconfig.build.json --clean", + "build:docs": "typedoc" }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", @@ -33,7 +36,9 @@ "ts-jest": "^28.0.7", "typedoc": "^0.24.8", "typedoc-plugin-missing-exports": "^2.0.0", - "typescript": "~4.9.5" + "typescript": "~4.9.5", + "vite": "^5.3.4", + "vite-plugin-static-copy": "^1.0.6" }, "engines": { "node": "^18.18 || >=20" diff --git a/packages/ocap-skunkworks/src/extension/background.js b/packages/ocap-skunkworks/src/extension/background.js index 9772c3306..a9850e8a1 100644 --- a/packages/ocap-skunkworks/src/extension/background.js +++ b/packages/ocap-skunkworks/src/extension/background.js @@ -2,10 +2,7 @@ const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; // Send chrome.action.onClicked.addListener(async () => { - sendMessage( - 'greetings', - { name: 'Kernel' }, - ); + sendMessage('greetings', { name: 'Kernel' }); }); async function sendMessage(type, data) { @@ -14,12 +11,12 @@ async function sendMessage(type, data) { chrome.runtime.sendMessage({ type, target: 'offscreen', - data + data, }); } async function provideOffScreenDocument() { - if (!(await hasDocument())) { + if (!(await chrome.offscreen.hasDocument())) { await chrome.offscreen.createDocument({ url: OFFSCREEN_DOCUMENT_PATH, reasons: [chrome.offscreen.Reason.IFRAME_SCRIPTING], @@ -47,18 +44,8 @@ async function handleMessage(message) { } async function closeOffscreenDocument() { - if (!(await hasDocument())) { + if (!(await chrome.offscreen.hasDocument())) { return; } await chrome.offscreen.closeDocument(); } - -async function hasDocument() { - const allClients = await clients.matchAll(); - for (const client of allClients) { - if (client.url.endsWith(OFFSCREEN_DOCUMENT_PATH)) { - return true; - } - } - return false; -} diff --git a/packages/ocap-skunkworks/src/extension/offscreen.html b/packages/ocap-skunkworks/src/extension/offscreen.html index d4f61fc8b..8079a5ed1 100644 --- a/packages/ocap-skunkworks/src/extension/offscreen.html +++ b/packages/ocap-skunkworks/src/extension/offscreen.html @@ -1,2 +1,2 @@ - + diff --git a/packages/ocap-skunkworks/src/extension/offscreen.js b/packages/ocap-skunkworks/src/extension/offscreen.js index ff1029077..c64fc3951 100644 --- a/packages/ocap-skunkworks/src/extension/offscreen.js +++ b/packages/ocap-skunkworks/src/extension/offscreen.js @@ -7,11 +7,10 @@ async function handleMessage(message) { switch (message.type) { case 'greetings': - reply('salutations', `Good day to you, ${message.data.name}!`) + reply('salutations', `Good day to you, ${message.data.name}!`); break; default: console.error(`Received unexpected message type: "${message.type}"`); - return; } } @@ -20,5 +19,5 @@ function reply(type, data) { data, target: 'background', type, - }) + }); } diff --git a/packages/ocap-skunkworks/src/index.test.ts b/packages/ocap-skunkworks/src/index.test.ts deleted file mode 100644 index bc062d369..000000000 --- a/packages/ocap-skunkworks/src/index.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import greeter from '.'; - -describe('Test', () => { - it('greets', () => { - const name = 'Huey'; - const result = greeter(name); - expect(result).toBe('Hello, Huey!'); - }); -}); diff --git a/packages/ocap-skunkworks/src/index.ts b/packages/ocap-skunkworks/src/index.ts deleted file mode 100644 index 6972c1172..000000000 --- a/packages/ocap-skunkworks/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Example function that returns a greeting for the given name. - * - * @param name - The name to greet. - * @returns The greeting. - */ -export default function greeter(name: string): string { - return `Hello, ${name}!`; -} diff --git a/packages/ocap-skunkworks/tsconfig.json b/packages/ocap-skunkworks/tsconfig.json index 6f1d89de4..fefbaf5a1 100644 --- a/packages/ocap-skunkworks/tsconfig.json +++ b/packages/ocap-skunkworks/tsconfig.json @@ -4,5 +4,5 @@ "baseUrl": "./" }, "references": [], - "include": ["./src"] + "include": [] } diff --git a/packages/ocap-skunkworks/vite.config.extension.mjs b/packages/ocap-skunkworks/vite.config.extension.mjs new file mode 100644 index 000000000..6eadeb388 --- /dev/null +++ b/packages/ocap-skunkworks/vite.config.extension.mjs @@ -0,0 +1,29 @@ +import path from 'path'; +import { defineConfig } from 'vite' +import { viteStaticCopy } from 'vite-plugin-static-copy'; + +const root = './src/extension'; + +// https://vitejs.dev/config/ +export default defineConfig({ + root, + assetsInclude: ['**/*.json'], + build: { + emptyOutDir: true, + outDir: path.resolve(root, '../../dist'), + rollupOptions: { + input: { + background: path.resolve(root, 'background.js'), + offscreen: path.resolve(root, 'offscreen.html'), + }, + output: { + entryFileNames: '[name].js', + chunkFileNames: '[name].js', + assetFileNames: '[name].[ext]' + } + } + }, + plugins: [ + viteStaticCopy({ targets: [{ src: 'manifest.json', dest: './' }]}) + ] +}); diff --git a/tsconfig.packages.json b/tsconfig.packages.json index d7ee52ad2..fcb314098 100644 --- a/tsconfig.packages.json +++ b/tsconfig.packages.json @@ -18,6 +18,7 @@ "paths": { "@metamask/*": ["../*/src"] }, + "resolveJsonModule": true, "strict": true, "target": "ES2020", "useUnknownInCatchVariables": true diff --git a/yarn.lock b/yarn.lock index c5189eb34..8b4869dc2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -469,6 +469,167 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@eslint-community/eslint-utils@npm:^4.2.0": version: 4.4.0 resolution: "@eslint-community/eslint-utils@npm:4.4.0" @@ -999,9 +1160,9 @@ __metadata: languageName: node linkType: hard -"@metamask/ocap-playground@workspace:packages/ocap-playground": +"@metamask/ocap-skunkworks@workspace:packages/ocap-skunkworks": version: 0.0.0-use.local - resolution: "@metamask/ocap-playground@workspace:packages/ocap-playground" + resolution: "@metamask/ocap-skunkworks@workspace:packages/ocap-skunkworks" dependencies: "@arethetypeswrong/cli": "npm:^0.15.3" "@metamask/auto-changelog": "npm:^3.4.4" @@ -1015,6 +1176,8 @@ __metadata: typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~4.9.5" + vite: "npm:^5.3.4" + vite-plugin-static-copy: "npm:^1.0.6" languageName: unknown linkType: soft @@ -1154,6 +1317,118 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.18.1" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-android-arm64@npm:4.18.1" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-darwin-arm64@npm:4.18.1" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-darwin-x64@npm:4.18.1" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.18.1" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.18.1" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.18.1" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.18.1" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.18.1" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.18.1" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.18.1" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.18.1" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.18.1" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.18.1" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.18.1" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.18.1": + version: 4.18.1 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.18.1" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.24.1": version: 0.24.28 resolution: "@sinclair/typebox@npm:0.24.28" @@ -1268,6 +1543,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 10/7de6d928dd4010b0e20c6919e1a6c27b61f8d4567befa89252055fad503d587ecb9a1e3eab1b1901f923964d7019796db810b7fd6430acb26c32866d126fd408 + languageName: node + linkType: hard + "@types/glob@npm:^7.1.1": version: 7.1.3 resolution: "@types/glob@npm:7.1.3" @@ -2202,7 +2484,7 @@ __metadata: languageName: node linkType: hard -"chokidar@npm:>=3.0.0 <4.0.0": +"chokidar@npm:>=3.0.0 <4.0.0, chokidar@npm:^3.5.3": version: 3.6.0 resolution: "chokidar@npm:3.6.0" dependencies: @@ -2776,6 +3058,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10/d2ff2ca84d30cce8e871517374d6c2290835380dc7cd413b2d49189ed170d45e407be14de2cb4794cf76f75cf89955c4714726ebd3de7444b3046f5cab23ab6b + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -3185,16 +3547,16 @@ __metadata: languageName: node linkType: hard -"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.9": - version: 3.2.12 - resolution: "fast-glob@npm:3.2.12" +"fast-glob@npm:^3.0.3, fast-glob@npm:^3.2.11, fast-glob@npm:^3.2.9": + version: 3.3.2 + resolution: "fast-glob@npm:3.3.2" dependencies: "@nodelib/fs.stat": "npm:^2.0.2" "@nodelib/fs.walk": "npm:^1.2.3" glob-parent: "npm:^5.1.2" merge2: "npm:^1.3.0" micromatch: "npm:^4.0.4" - checksum: 10/641e748664ae0fdc4dadd23c812fd7d6c80cd92d451571cb1f81fa87edb750e917f25abf74fc9503c97438b0b67ecf75b738bb8e50a83b16bd2a88b4d64e81fa + checksum: 10/222512e9315a0efca1276af9adb2127f02105d7288fa746145bf45e2716383fb79eb983c89601a72a399a56b7c18d38ce70457c5466218c5f13fad957cee16df languageName: node linkType: hard @@ -3311,6 +3673,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.1.0": + version: 11.2.0 + resolution: "fs-extra@npm:11.2.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10/0579bf6726a4cd054d4aa308f10b483f52478bb16284f32cf60b4ce0542063d551fca1a08a2af365e35db21a3fa5a06cf2a6ed614004b4368982bc754cb816b3 + languageName: node + linkType: hard + "fs-minipass@npm:^2.0.0, fs-minipass@npm:^2.1.0": version: 2.1.0 resolution: "fs-minipass@npm:2.1.0" @@ -3336,19 +3709,19 @@ __metadata: languageName: node linkType: hard -"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2": - version: 2.3.2 - resolution: "fsevents@npm:2.3.2" +"fsevents@npm:^2.3.2, fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" dependencies: node-gyp: "npm:latest" - checksum: 10/6b5b6f5692372446ff81cf9501c76e3e0459a4852b3b5f1fc72c103198c125a6b8c72f5f166bdd76ffb2fca261e7f6ee5565daf80dca6e571e55bcc589cc1256 + checksum: 10/4c1ade961ded57cdbfbb5cac5106ec17bc8bccd62e16343c569a0ceeca83b9dfef87550b4dc5cbb89642da412b20c5071f304c8c464b80415446e8e155a038c0 conditions: os=darwin languageName: node linkType: hard -"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin": - version: 2.3.2 - resolution: "fsevents@patch:fsevents@npm%3A2.3.2#optional!builtin::version=2.3.2&hash=df0bf1" +"fsevents@patch:fsevents@npm%3A^2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" dependencies: node-gyp: "npm:latest" conditions: os=darwin @@ -3594,7 +3967,7 @@ __metadata: languageName: node linkType: hard -"graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.4, graceful-fs@npm:^4.2.6, graceful-fs@npm:^4.2.9": version: 4.2.11 resolution: "graceful-fs@npm:4.2.11" checksum: 10/bf152d0ed1dc159239db1ba1f74fdbc40cb02f626770dcd5815c427ce0688c2635a06ed69af364396da4636d0408fcf7d4afdf7881724c3307e46aff30ca49e2 @@ -4773,6 +5146,19 @@ __metadata: languageName: node linkType: hard +"jsonfile@npm:^6.0.1": + version: 6.1.0 + resolution: "jsonfile@npm:6.1.0" + dependencies: + graceful-fs: "npm:^4.1.6" + universalify: "npm:^2.0.0" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10/03014769e7dc77d4cf05fa0b534907270b60890085dd5e4d60a382ff09328580651da0b8b4cdf44d91e4c8ae64d91791d965f05707beff000ed494a38b6fec85 + languageName: node + linkType: hard + "kleur@npm:^3.0.3": version: 3.0.3 resolution: "kleur@npm:3.0.3" @@ -5227,12 +5613,12 @@ __metadata: languageName: node linkType: hard -"nanoid@npm:^3.3.6": - version: 3.3.6 - resolution: "nanoid@npm:3.3.6" +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" bin: nanoid: bin/nanoid.cjs - checksum: 10/67235c39d1bc05851383dadde5cf77ae1c90c2a1d189e845c7f20f646f0488d875ad5f5226bbba072a88cebbb085a3f784a6673117daf785bdf614a852550362 + checksum: 10/ac1eb60f615b272bccb0e2b9cd933720dad30bf9708424f691b8113826bb91aca7e9d14ef5d9415a6ba15c266b37817256f58d8ce980c82b0ba3185352565679 languageName: node linkType: hard @@ -5668,10 +6054,10 @@ __metadata: languageName: node linkType: hard -"picocolors@npm:^1.0.0": - version: 1.0.0 - resolution: "picocolors@npm:1.0.0" - checksum: 10/a2e8092dd86c8396bdba9f2b5481032848525b3dc295ce9b57896f931e63fc16f79805144321f72976383fc249584672a75cc18d6777c6b757603f372f745981 +"picocolors@npm:^1.0.0, picocolors@npm:^1.0.1": + version: 1.0.1 + resolution: "picocolors@npm:1.0.1" + checksum: 10/fa68166d1f56009fc02a34cdfd112b0dd3cf1ef57667ac57281f714065558c01828cdf4f18600ad6851cbe0093952ed0660b1e0156bddf2184b6aaf5817553a5 languageName: node linkType: hard @@ -5707,14 +6093,14 @@ __metadata: languageName: node linkType: hard -"postcss@npm:^8.1.10": - version: 8.4.31 - resolution: "postcss@npm:8.4.31" +"postcss@npm:^8.1.10, postcss@npm:^8.4.39": + version: 8.4.39 + resolution: "postcss@npm:8.4.39" dependencies: - nanoid: "npm:^3.3.6" - picocolors: "npm:^1.0.0" - source-map-js: "npm:^1.0.2" - checksum: 10/1a6653e72105907377f9d4f2cd341d8d90e3fde823a5ddea1e2237aaa56933ea07853f0f2758c28892a1d70c53bbaca200eb8b80f8ed55f13093003dbec5afa0 + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: 10/ad9c1add892c96433b9a5502878201ede4a20c4ce02d056251f61f8d9a3e5426dab3683fe5a086edfa78a1a19f2b4988c8cea02c5122136d29758cb5a17e2621 languageName: node linkType: hard @@ -6008,6 +6394,69 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.13.0": + version: 4.18.1 + resolution: "rollup@npm:4.18.1" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.18.1" + "@rollup/rollup-android-arm64": "npm:4.18.1" + "@rollup/rollup-darwin-arm64": "npm:4.18.1" + "@rollup/rollup-darwin-x64": "npm:4.18.1" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.18.1" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.18.1" + "@rollup/rollup-linux-arm64-gnu": "npm:4.18.1" + "@rollup/rollup-linux-arm64-musl": "npm:4.18.1" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.18.1" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.18.1" + "@rollup/rollup-linux-s390x-gnu": "npm:4.18.1" + "@rollup/rollup-linux-x64-gnu": "npm:4.18.1" + "@rollup/rollup-linux-x64-musl": "npm:4.18.1" + "@rollup/rollup-win32-arm64-msvc": "npm:4.18.1" + "@rollup/rollup-win32-ia32-msvc": "npm:4.18.1" + "@rollup/rollup-win32-x64-msvc": "npm:4.18.1" + "@types/estree": "npm:1.0.5" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10/7a5f110d216e8599dc3cb11cf570316d989abae00785d99c2bcb6027287fe60d2eaed70e457d88a036622e7fc67e8db6e730d3c784aa90a258bd4c020676ad44 + languageName: node + linkType: hard + "run-async@npm:^2.3.0": version: 2.4.1 resolution: "run-async@npm:2.4.1" @@ -6284,10 +6733,10 @@ __metadata: languageName: node linkType: hard -"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.0.2": - version: 1.0.2 - resolution: "source-map-js@npm:1.0.2" - checksum: 10/38e2d2dd18d2e331522001fc51b54127ef4a5d473f53b1349c5cca2123562400e0986648b52e9407e348eaaed53bce49248b6e2641e6d793ca57cb2c360d6d51 +"source-map-js@npm:>=0.6.2 <2.0.0, source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10/74f331cfd2d121c50790c8dd6d3c9de6be21926de80583b23b37029b0f37aefc3e019fa91f9a10a5e120c08135297e1ecf312d561459c45908cb1e0e365f49e5 languageName: node linkType: hard @@ -6910,6 +7359,13 @@ __metadata: languageName: node linkType: hard +"universalify@npm:^2.0.0": + version: 2.0.1 + resolution: "universalify@npm:2.0.1" + checksum: 10/ecd8469fe0db28e7de9e5289d32bd1b6ba8f7183db34f3bfc4ca53c49891c2d6aa05f3fb3936a81285a905cc509fb641a0c3fc131ec786167eff41236ae32e60 + languageName: node + linkType: hard + "update-browserslist-db@npm:^1.0.13": version: 1.0.13 resolution: "update-browserslist-db@npm:1.0.13" @@ -6970,6 +7426,60 @@ __metadata: languageName: node linkType: hard +"vite-plugin-static-copy@npm:^1.0.6": + version: 1.0.6 + resolution: "vite-plugin-static-copy@npm:1.0.6" + dependencies: + chokidar: "npm:^3.5.3" + fast-glob: "npm:^3.2.11" + fs-extra: "npm:^11.1.0" + picocolors: "npm:^1.0.0" + peerDependencies: + vite: ^5.0.0 + checksum: 10/6a48cdaa32c3ebe450e173f2567994159ba9ffbd5042bc180dc3d84a50c8731debc297beb3a87308873f1d3db556ccac3d08bfac3c6da415fff39076c3cf37ae + languageName: node + linkType: hard + +"vite@npm:^5.3.4": + version: 5.3.4 + resolution: "vite@npm:5.3.4" + dependencies: + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.39" + rollup: "npm:^4.13.0" + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 10/9eadb261be1f5f6335a67cb44a8803febd8b190202909385fd2ae7849991095ee13c5af914da53da48a421ee0901a8fedbb7519dc7d1b8ade3ea6e42bd9b2b39 + languageName: node + linkType: hard + "vscode-oniguruma@npm:^1.7.0": version: 1.7.0 resolution: "vscode-oniguruma@npm:1.7.0" From 7420a5e75289a67461d081056ff3d79faa9bfebb Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 17 Jul 2024 10:47:50 +0200 Subject: [PATCH 04/31] chore: Convert vite config file from .mjs to .mts --- .eslintrc.js | 10 +--------- packages/ocap-skunkworks/.eslintrc.js | 8 ++++++++ packages/ocap-skunkworks/package.json | 10 +++++----- ....config.extension.mjs => vite.config.extension.mts} | 0 tsconfig.packages.build.json | 7 ++++++- 5 files changed, 20 insertions(+), 15 deletions(-) rename packages/ocap-skunkworks/{vite.config.extension.mjs => vite.config.extension.mts} (100%) diff --git a/.eslintrc.js b/.eslintrc.js index be92250ac..77a9fd660 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -41,15 +41,7 @@ module.exports = { }, { - files: ['*.mjs'], - parserOptions: { - sourceType: 'module', - ecmaVersion: '2020', - }, - }, - - { - files: ['*.ts'], + files: ['*.ts', '*.cts', '*.mts'], extends: ['@metamask/eslint-config-typescript'], parserOptions: { tsconfigRootDir: __dirname, diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/ocap-skunkworks/.eslintrc.js index c0711cec2..3b859c36a 100644 --- a/packages/ocap-skunkworks/.eslintrc.js +++ b/packages/ocap-skunkworks/.eslintrc.js @@ -9,5 +9,13 @@ module.exports = { 'jsdoc/require-jsdoc': 'off', }, }, + + { + files: ['vite.*.mts'], + parserOptions: { + sourceType: 'module', + tsconfigRootDir: __dirname, + }, + }, ], }; diff --git a/packages/ocap-skunkworks/package.json b/packages/ocap-skunkworks/package.json index ff4d8b95a..d9ebcc619 100644 --- a/packages/ocap-skunkworks/package.json +++ b/packages/ocap-skunkworks/package.json @@ -11,18 +11,18 @@ "dist/" ], "scripts": { - "build:extension": "vite build -c vite.config.extension.mjs", + "build": "ts-bridge --project tsconfig.build.json --clean", + "build:docs": "typedoc", + "build:extension": "vite build -c vite.config.extension.mts", "build:library": "ts-bridge --project tsconfig.build.json --clean", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-skunkworks", "publish:preview": "yarn npm publish --tag preview", - "start": "vite -c vite.config.extension.mjs", + "start": "vite -c vite.config.extension.mts", "test": "jest --reporters=jest-silent-reporter", "posttest": "jest-it-up", "test:clean": "jest --clearCache", "test:verbose": "jest --verbose", - "test:watch": "jest --watch", - "build": "ts-bridge --project tsconfig.build.json --clean", - "build:docs": "typedoc" + "test:watch": "jest --watch" }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", diff --git a/packages/ocap-skunkworks/vite.config.extension.mjs b/packages/ocap-skunkworks/vite.config.extension.mts similarity index 100% rename from packages/ocap-skunkworks/vite.config.extension.mjs rename to packages/ocap-skunkworks/vite.config.extension.mts diff --git a/tsconfig.packages.build.json b/tsconfig.packages.build.json index e77c1d80b..7f10e4b8b 100644 --- a/tsconfig.packages.build.json +++ b/tsconfig.packages.build.json @@ -7,5 +7,10 @@ "inlineSources": true, "sourceMap": true }, - "exclude": ["./jest.config.packages.ts", "**/*.test.ts", "**/jest.config.ts"] + "exclude": [ + "./jest.config.packages.ts", + "**/vite.*.mts", + "**/*.test.ts", + "**/jest.config.ts" + ] } From 486f1bffb9a7e9369ab872f26a9f31d8026d1bf2 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 17 Jul 2024 10:53:23 +0200 Subject: [PATCH 05/31] chore: Add passWithNoTests flag in CI --- .github/workflows/lint-build-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint-build-test.yml b/.github/workflows/lint-build-test.yml index 319f02df1..590095c79 100644 --- a/.github/workflows/lint-build-test.yml +++ b/.github/workflows/lint-build-test.yml @@ -144,7 +144,8 @@ jobs: node-version: ${{ matrix.node-version }} cache: yarn - run: yarn --immutable - - run: yarn workspace ${{ matrix.package-name }} run test + # TODO: Remove passWithNoTests flag + - run: yarn workspace ${{ matrix.package-name }} run test --passWithNoTests - name: Require clean working directory shell: bash run: | From 47db1a3bafba1b1381dd05a19aa2aa98e24d16cd Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 17 Jul 2024 12:03:27 +0200 Subject: [PATCH 06/31] refactor: Convert extension source files to TypeScript --- packages/ocap-skunkworks/.eslintrc.js | 3 - packages/ocap-skunkworks/package.json | 4 +- .../src/extension/background.js | 51 -------------- .../src/extension/background.ts | 70 +++++++++++++++++++ .../src/extension/lockdown.mjs | 0 .../src/extension/offscreen.html | 2 +- .../src/extension/offscreen.js | 23 ------ .../src/extension/offscreen.ts | 35 ++++++++++ .../ocap-skunkworks/src/extension/shared.ts | 23 ++++++ .../src/extension/tsconfig.json | 10 +++ .../ocap-skunkworks/vite.config.extension.mts | 2 +- yarn.lock | 34 +++++++++ 12 files changed, 177 insertions(+), 80 deletions(-) delete mode 100644 packages/ocap-skunkworks/src/extension/background.js create mode 100644 packages/ocap-skunkworks/src/extension/background.ts create mode 100644 packages/ocap-skunkworks/src/extension/lockdown.mjs delete mode 100644 packages/ocap-skunkworks/src/extension/offscreen.js create mode 100644 packages/ocap-skunkworks/src/extension/offscreen.ts create mode 100644 packages/ocap-skunkworks/src/extension/shared.ts create mode 100644 packages/ocap-skunkworks/src/extension/tsconfig.json diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/ocap-skunkworks/.eslintrc.js index 3b859c36a..5dd362b52 100644 --- a/packages/ocap-skunkworks/.eslintrc.js +++ b/packages/ocap-skunkworks/.eslintrc.js @@ -5,9 +5,6 @@ module.exports = { { files: ['src/extension/**/*.js'], globals: { chrome: 'readonly', clients: 'readonly' }, - rules: { - 'jsdoc/require-jsdoc': 'off', - }, }, { diff --git a/packages/ocap-skunkworks/package.json b/packages/ocap-skunkworks/package.json index d9ebcc619..9d0b85ac3 100644 --- a/packages/ocap-skunkworks/package.json +++ b/packages/ocap-skunkworks/package.json @@ -13,9 +13,10 @@ "scripts": { "build": "ts-bridge --project tsconfig.build.json --clean", "build:docs": "typedoc", - "build:extension": "vite build -c vite.config.extension.mts", + "build:extension": "yarn check:types:extension && vite build -c vite.config.extension.mts", "build:library": "ts-bridge --project tsconfig.build.json --clean", "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-skunkworks", + "check:types:extension": "tsc --project src/extension/tsconfig.json", "publish:preview": "yarn npm publish --tag preview", "start": "vite -c vite.config.extension.mts", "test": "jest --reporters=jest-silent-reporter", @@ -29,6 +30,7 @@ "@metamask/auto-changelog": "^3.4.4", "@ts-bridge/cli": "^0.1.4", "@ts-bridge/shims": "^0.1.1", + "@types/chrome": "^0.0.268", "@types/jest": "^28.1.6", "deepmerge": "^4.3.1", "jest": "^28.1.3", diff --git a/packages/ocap-skunkworks/src/extension/background.js b/packages/ocap-skunkworks/src/extension/background.js deleted file mode 100644 index a9850e8a1..000000000 --- a/packages/ocap-skunkworks/src/extension/background.js +++ /dev/null @@ -1,51 +0,0 @@ -const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; - -// Send -chrome.action.onClicked.addListener(async () => { - sendMessage('greetings', { name: 'Kernel' }); -}); - -async function sendMessage(type, data) { - await provideOffScreenDocument(); - - chrome.runtime.sendMessage({ - type, - target: 'offscreen', - data, - }); -} - -async function provideOffScreenDocument() { - if (!(await chrome.offscreen.hasDocument())) { - await chrome.offscreen.createDocument({ - url: OFFSCREEN_DOCUMENT_PATH, - reasons: [chrome.offscreen.Reason.IFRAME_SCRIPTING], - justification: `Surely you won't object to our capabilities?`, - }); - } -} - -// Receive -chrome.runtime.onMessage.addListener(handleMessage); - -async function handleMessage(message) { - if (message.target !== 'background') { - return; - } - - switch (message.type) { - case 'salutations': - console.log(message.data); - closeOffscreenDocument(); - break; - default: - console.error(`Received unexpected message type: "${message.type}"`); - } -} - -async function closeOffscreenDocument() { - if (!(await chrome.offscreen.hasDocument())) { - return; - } - await chrome.offscreen.closeDocument(); -} diff --git a/packages/ocap-skunkworks/src/extension/background.ts b/packages/ocap-skunkworks/src/extension/background.ts new file mode 100644 index 000000000..a249fa7f1 --- /dev/null +++ b/packages/ocap-skunkworks/src/extension/background.ts @@ -0,0 +1,70 @@ +import type { ExtensionMessage } from './shared'; +import { makeHandledCallback } from './shared'; + +const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; + +// Send +chrome.action.onClicked.addListener(() => { + sendMessage('greetings', { name: 'Kernel' }).catch(console.error); +}); + +/** + * Send a message to the offscreen document. + * @param type - The message type. + * @param data - The message data. + * @param data.name - The name to include in the message. + */ +async function sendMessage(type: string, data: { name: string }) { + await provideOffScreenDocument(); + + await chrome.runtime.sendMessage({ + type, + target: 'offscreen', + data, + }); +} + +/** + * Create the offscreen document if it doesn't already exist. + */ +async function provideOffScreenDocument() { + if (!(await chrome.offscreen.hasDocument())) { + await chrome.offscreen.createDocument({ + url: OFFSCREEN_DOCUMENT_PATH, + reasons: [chrome.offscreen.Reason.IFRAME_SCRIPTING], + justification: `Surely you won't object to our capabilities?`, + }); + } +} + +// Receive +chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); + +/** + * Receive a message from the offscreen document. + * @param message - The message to handle. + */ +async function handleMessage(message: ExtensionMessage) { + if (message.target !== 'background') { + return; + } + + switch (message.type) { + case 'salutations': + console.log(message.data); + await closeOffscreenDocument(); + break; + default: + console.error(`Received unexpected message type: "${message.type}"`); + } +} + +/** + * Close the offscreen document if it exists. + */ +async function closeOffscreenDocument() { + if (!(await chrome.offscreen.hasDocument())) { + return; + } + await chrome.offscreen.closeDocument(); +} diff --git a/packages/ocap-skunkworks/src/extension/lockdown.mjs b/packages/ocap-skunkworks/src/extension/lockdown.mjs new file mode 100644 index 000000000..e69de29bb diff --git a/packages/ocap-skunkworks/src/extension/offscreen.html b/packages/ocap-skunkworks/src/extension/offscreen.html index 8079a5ed1..7d47fabac 100644 --- a/packages/ocap-skunkworks/src/extension/offscreen.html +++ b/packages/ocap-skunkworks/src/extension/offscreen.html @@ -1,2 +1,2 @@ - + diff --git a/packages/ocap-skunkworks/src/extension/offscreen.js b/packages/ocap-skunkworks/src/extension/offscreen.js deleted file mode 100644 index c64fc3951..000000000 --- a/packages/ocap-skunkworks/src/extension/offscreen.js +++ /dev/null @@ -1,23 +0,0 @@ -chrome.runtime.onMessage.addListener(handleMessage); - -async function handleMessage(message) { - if (message.target !== 'offscreen') { - return; - } - - switch (message.type) { - case 'greetings': - reply('salutations', `Good day to you, ${message.data.name}!`); - break; - default: - console.error(`Received unexpected message type: "${message.type}"`); - } -} - -function reply(type, data) { - chrome.runtime.sendMessage({ - data, - target: 'background', - type, - }); -} diff --git a/packages/ocap-skunkworks/src/extension/offscreen.ts b/packages/ocap-skunkworks/src/extension/offscreen.ts new file mode 100644 index 000000000..d724e2189 --- /dev/null +++ b/packages/ocap-skunkworks/src/extension/offscreen.ts @@ -0,0 +1,35 @@ +import type { ExtensionMessage } from './shared'; +import { makeHandledCallback } from './shared'; + +chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); + +/** + * Handle a message from the background script. + * @param message - The message to handle. + */ +async function handleMessage(message: ExtensionMessage<{ name: string }>) { + if (message.target !== 'offscreen') { + return; + } + + switch (message.type) { + case 'greetings': + await reply('salutations', `Good day to you, ${message.data.name}!`); + break; + default: + console.error(`Received unexpected message type: "${message.type}"`); + } +} + +/** + * Reply to the background script. + * @param type - The message type. + * @param data - The message data. + */ +async function reply(type: string, data: string) { + await chrome.runtime.sendMessage({ + data, + target: 'background', + type, + }); +} diff --git a/packages/ocap-skunkworks/src/extension/shared.ts b/packages/ocap-skunkworks/src/extension/shared.ts new file mode 100644 index 000000000..367844a74 --- /dev/null +++ b/packages/ocap-skunkworks/src/extension/shared.ts @@ -0,0 +1,23 @@ +export type ExtensionMessage< + Data extends string | unknown[] | Record, +> = { + type: string; + target: 'background' | 'offscreen'; + data: Data; +}; + +/** + * Wrap an async callback to ensure any errors are re-thrown synchronously. + * @param callback - The async callback to wrap. + * @returns The wrapped callback. + */ +export const makeHandledCallback = ( + callback: (...args: Args) => Promise, +) => { + return (...args: Args): void => { + // eslint-disable-next-line n/no-callback-literal, n/callback-return + callback(...args).catch((error: Error) => { + throw error; + }); + }; +}; diff --git a/packages/ocap-skunkworks/src/extension/tsconfig.json b/packages/ocap-skunkworks/src/extension/tsconfig.json new file mode 100644 index 000000000..93156a844 --- /dev/null +++ b/packages/ocap-skunkworks/src/extension/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "isolatedModules": true, + "lib": ["DOM", "ES2020"], + "noEmit": true, + "types": ["chrome"] + }, + "include": ["./**/*.ts"] +} diff --git a/packages/ocap-skunkworks/vite.config.extension.mts b/packages/ocap-skunkworks/vite.config.extension.mts index 6eadeb388..a9ab1caee 100644 --- a/packages/ocap-skunkworks/vite.config.extension.mts +++ b/packages/ocap-skunkworks/vite.config.extension.mts @@ -13,7 +13,7 @@ export default defineConfig({ outDir: path.resolve(root, '../../dist'), rollupOptions: { input: { - background: path.resolve(root, 'background.js'), + background: path.resolve(root, 'background.ts'), offscreen: path.resolve(root, 'offscreen.html'), }, output: { diff --git a/yarn.lock b/yarn.lock index 8b4869dc2..56f8a4f89 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1168,6 +1168,7 @@ __metadata: "@metamask/auto-changelog": "npm:^3.4.4" "@ts-bridge/cli": "npm:^0.1.4" "@ts-bridge/shims": "npm:^0.1.1" + "@types/chrome": "npm:^0.0.268" "@types/jest": "npm:^28.1.6" deepmerge: "npm:^4.3.1" jest: "npm:^28.1.3" @@ -1536,6 +1537,16 @@ __metadata: languageName: node linkType: hard +"@types/chrome@npm:^0.0.268": + version: 0.0.268 + resolution: "@types/chrome@npm:0.0.268" + dependencies: + "@types/filesystem": "npm:*" + "@types/har-format": "npm:*" + checksum: 10/f03cf2f816f7c8f19319299af9399dd3eed8b46b3e4791bd7c1c70d982ae63634580a4c03509841cd65b91e99e6bc47f05358811d2c8b707968746d3d482b983 + languageName: node + linkType: hard + "@types/color-name@npm:^1.1.1": version: 1.1.1 resolution: "@types/color-name@npm:1.1.1" @@ -1550,6 +1561,22 @@ __metadata: languageName: node linkType: hard +"@types/filesystem@npm:*": + version: 0.0.36 + resolution: "@types/filesystem@npm:0.0.36" + dependencies: + "@types/filewriter": "npm:*" + checksum: 10/ec831040fe3aff066ffb7b7541e21a5dd59aa06e7175c61e592736e38b018b1d513551438254631e2a3fbc81ff671bf618401000f4c8ea79156934cbc7dcaeaa + languageName: node + linkType: hard + +"@types/filewriter@npm:*": + version: 0.0.33 + resolution: "@types/filewriter@npm:0.0.33" + checksum: 10/495a4bb424c27eda967fe9ac3b8f7b781e6b3f9ce59403a991590cb1073022f9c5383d3c7d808ef6956b785550c36664c4fcd502dc0baf69e340bd481171e0ca + languageName: node + linkType: hard + "@types/glob@npm:^7.1.1": version: 7.1.3 resolution: "@types/glob@npm:7.1.3" @@ -1569,6 +1596,13 @@ __metadata: languageName: node linkType: hard +"@types/har-format@npm:*": + version: 1.2.15 + resolution: "@types/har-format@npm:1.2.15" + checksum: 10/fcb397741076ed1095ef8dcccd408c9ef4e20fcfeef0d3fe700f837cc015fe72ee2a3c081cc9c03d73c115005b38ba7b1c563d27e050fa612d60bc2049f309ca + languageName: node + linkType: hard + "@types/istanbul-lib-coverage@npm:*, @types/istanbul-lib-coverage@npm:^2.0.0, @types/istanbul-lib-coverage@npm:^2.0.1": version: 2.0.3 resolution: "@types/istanbul-lib-coverage@npm:2.0.3" From 2bdcb4d120abfb492b4b00e75218a384219fe0f0 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Wed, 17 Jul 2024 12:49:34 +0200 Subject: [PATCH 07/31] fix: Make Chrome interpret the service worker as ESM --- packages/ocap-skunkworks/src/extension/manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/ocap-skunkworks/src/extension/manifest.json b/packages/ocap-skunkworks/src/extension/manifest.json index 5eb4ad00e..0b2410ba4 100644 --- a/packages/ocap-skunkworks/src/extension/manifest.json +++ b/packages/ocap-skunkworks/src/extension/manifest.json @@ -4,7 +4,8 @@ "description": "For running Ocap Kernel experiments in an extension environment.", "manifest_version": 3, "background": { - "service_worker": "background.js" + "service_worker": "background.js", + "type": "module" }, "action": {}, "permissions": ["offscreen"] From 54261ceb90c95ae764583661b0803e03531a17e8 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 10:45:51 +0200 Subject: [PATCH 08/31] feat: Add ses, lockdown all entry points --- .eslintrc.js | 10 ++++++- packages/ocap-skunkworks/.eslintrc.js | 8 ++++++ packages/ocap-skunkworks/package.json | 6 ++++- .../src/extension/apply-lockdown.mjs | 11 ++++++++ .../src/extension/background.ts | 3 +++ .../src/extension/lockdown.mjs | 0 .../src/extension/offscreen.ts | 3 +++ .../src/extension/tsconfig.json | 4 ++- packages/ocap-skunkworks/tsconfig.build.json | 3 ++- .../ocap-skunkworks/vite.config.extension.mts | 10 ++++++- yarn.lock | 27 +++++++++++++++++++ 11 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 packages/ocap-skunkworks/src/extension/apply-lockdown.mjs delete mode 100644 packages/ocap-skunkworks/src/extension/lockdown.mjs diff --git a/.eslintrc.js b/.eslintrc.js index 77a9fd660..b4ed6f764 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -33,13 +33,21 @@ module.exports = { overrides: [ { - files: ['*.js'], + files: ['*.js', '*.cjs'], parserOptions: { sourceType: 'script', ecmaVersion: '2020', }, }, + { + files: ['*.mjs'], + parserOptions: { + sourceType: 'module', + ecmaVersion: '2020', + }, + }, + { files: ['*.ts', '*.cts', '*.mts'], extends: ['@metamask/eslint-config-typescript'], diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/ocap-skunkworks/.eslintrc.js index 5dd362b52..bfe8c6244 100644 --- a/packages/ocap-skunkworks/.eslintrc.js +++ b/packages/ocap-skunkworks/.eslintrc.js @@ -7,6 +7,14 @@ module.exports = { globals: { chrome: 'readonly', clients: 'readonly' }, }, + { + files: ['apply-lockdown.mjs'], + globals: { lockdown: 'readonly' }, + rules: { + 'import/unambiguous': 'off', + }, + }, + { files: ['vite.*.mts'], parserOptions: { diff --git a/packages/ocap-skunkworks/package.json b/packages/ocap-skunkworks/package.json index 9d0b85ac3..339ac378a 100644 --- a/packages/ocap-skunkworks/package.json +++ b/packages/ocap-skunkworks/package.json @@ -11,7 +11,7 @@ "dist/" ], "scripts": { - "build": "ts-bridge --project tsconfig.build.json --clean", + "build": "yarn build:extension", "build:docs": "typedoc", "build:extension": "yarn check:types:extension && vite build -c vite.config.extension.mts", "build:library": "ts-bridge --project tsconfig.build.json --clean", @@ -25,6 +25,10 @@ "test:verbose": "jest --verbose", "test:watch": "jest --watch" }, + "dependencies": { + "@endo/lockdown": "^1.0.7", + "ses": "^1.5.0" + }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@metamask/auto-changelog": "^3.4.4", diff --git a/packages/ocap-skunkworks/src/extension/apply-lockdown.mjs b/packages/ocap-skunkworks/src/extension/apply-lockdown.mjs new file mode 100644 index 000000000..ef718651e --- /dev/null +++ b/packages/ocap-skunkworks/src/extension/apply-lockdown.mjs @@ -0,0 +1,11 @@ +import './ses.mjs'; +import './lockdown.mjs'; + +lockdown({ + consoleTaming: 'unsafe', + errorTaming: 'unsafe', + mathTaming: 'unsafe', + dateTaming: 'unsafe', + domainTaming: 'unsafe', + overrideTaming: 'severe', +}); diff --git a/packages/ocap-skunkworks/src/extension/background.ts b/packages/ocap-skunkworks/src/extension/background.ts index a249fa7f1..feba004ad 100644 --- a/packages/ocap-skunkworks/src/extension/background.ts +++ b/packages/ocap-skunkworks/src/extension/background.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line import/no-unassigned-import +import './apply-lockdown.mjs'; + import type { ExtensionMessage } from './shared'; import { makeHandledCallback } from './shared'; diff --git a/packages/ocap-skunkworks/src/extension/lockdown.mjs b/packages/ocap-skunkworks/src/extension/lockdown.mjs deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/ocap-skunkworks/src/extension/offscreen.ts b/packages/ocap-skunkworks/src/extension/offscreen.ts index d724e2189..c95905eac 100644 --- a/packages/ocap-skunkworks/src/extension/offscreen.ts +++ b/packages/ocap-skunkworks/src/extension/offscreen.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line import/no-unassigned-import +import './apply-lockdown.mjs'; + import type { ExtensionMessage } from './shared'; import { makeHandledCallback } from './shared'; diff --git a/packages/ocap-skunkworks/src/extension/tsconfig.json b/packages/ocap-skunkworks/src/extension/tsconfig.json index 93156a844..e68794cdb 100644 --- a/packages/ocap-skunkworks/src/extension/tsconfig.json +++ b/packages/ocap-skunkworks/src/extension/tsconfig.json @@ -1,10 +1,12 @@ { "extends": "../../tsconfig.json", "compilerOptions": { + "allowJs": true, "isolatedModules": true, "lib": ["DOM", "ES2020"], "noEmit": true, + "skipLibCheck": true, "types": ["chrome"] }, - "include": ["./**/*.ts"] + "include": ["./**/*.ts", "./apply-lockdown.mjs"] } diff --git a/packages/ocap-skunkworks/tsconfig.build.json b/packages/ocap-skunkworks/tsconfig.build.json index 02a0eea03..639f53e44 100644 --- a/packages/ocap-skunkworks/tsconfig.build.json +++ b/packages/ocap-skunkworks/tsconfig.build.json @@ -6,5 +6,6 @@ "rootDir": "./src" }, "references": [], - "include": ["../../types", "./src"] + "include": ["../../types", "./src"], + "exclude": ["./src/extension"] } diff --git a/packages/ocap-skunkworks/vite.config.extension.mts b/packages/ocap-skunkworks/vite.config.extension.mts index a9ab1caee..6e0fdba5a 100644 --- a/packages/ocap-skunkworks/vite.config.extension.mts +++ b/packages/ocap-skunkworks/vite.config.extension.mts @@ -12,6 +12,9 @@ export default defineConfig({ emptyOutDir: true, outDir: path.resolve(root, '../../dist'), rollupOptions: { + external: [ + './apply-lockdown.mjs', + ], input: { background: path.resolve(root, 'background.ts'), offscreen: path.resolve(root, 'offscreen.html'), @@ -24,6 +27,11 @@ export default defineConfig({ } }, plugins: [ - viteStaticCopy({ targets: [{ src: 'manifest.json', dest: './' }]}) + viteStaticCopy({ targets: [ + { src: 'manifest.json', dest: './' }, + { src: 'apply-lockdown.mjs', dest: './' }, + { src: '../../../../node_modules/ses/dist/ses.mjs', dest: './' }, + { src: '../../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, + ]}) ] }); diff --git a/yarn.lock b/yarn.lock index 56f8a4f89..3d98ed6d4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -458,6 +458,22 @@ __metadata: languageName: node linkType: hard +"@endo/env-options@npm:^1.1.4": + version: 1.1.4 + resolution: "@endo/env-options@npm:1.1.4" + checksum: 10/718c15ae91b5e3d00c8b90f64d07930cc6bc58297cbda55097c339121a8c63045cd909f4bd7a4c39635354d228fa68f6182eb43ac0b0eaa62b05618484ec8209 + languageName: node + linkType: hard + +"@endo/lockdown@npm:^1.0.7": + version: 1.0.7 + resolution: "@endo/lockdown@npm:1.0.7" + dependencies: + ses: "npm:^1.5.0" + checksum: 10/1d4d0df4460e5acfbccaf1e41492d2b4b4f60679e55b3e349a032d3eafd2b629c5b61052e51e77bbf7a7ff1bbfe63ccca1c684dc1914bfb45064915aa86bda0e + languageName: node + linkType: hard + "@es-joy/jsdoccomment@npm:~0.36.1": version: 0.36.1 resolution: "@es-joy/jsdoccomment@npm:0.36.1" @@ -1165,6 +1181,7 @@ __metadata: resolution: "@metamask/ocap-skunkworks@workspace:packages/ocap-skunkworks" dependencies: "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/lockdown": "npm:^1.0.7" "@metamask/auto-changelog": "npm:^3.4.4" "@ts-bridge/cli": "npm:^0.1.4" "@ts-bridge/shims": "npm:^0.1.1" @@ -1173,6 +1190,7 @@ __metadata: deepmerge: "npm:^4.3.1" jest: "npm:^28.1.3" jest-it-up: "npm:^2.0.2" + ses: "npm:^1.5.0" ts-jest: "npm:^28.0.7" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" @@ -6599,6 +6617,15 @@ __metadata: languageName: node linkType: hard +"ses@npm:^1.5.0": + version: 1.5.0 + resolution: "ses@npm:1.5.0" + dependencies: + "@endo/env-options": "npm:^1.1.4" + checksum: 10/6f2cd8f3607f98838d6458cc4b77e6c1cffe8fc30b923212c1dde73c89e9a0e1eaa8f44ac38811d73a6961560e5be4155a0e58879f6dfe69d3319433251891da + languageName: node + linkType: hard + "set-blocking@npm:^2.0.0": version: 2.0.0 resolution: "set-blocking@npm:2.0.0" From cf3b2e72057ba4626b1c5c828406bd5d043e2b86 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 10:54:20 +0200 Subject: [PATCH 09/31] fix: Exclude ocap-skunkworks from build script constraint --- constraints.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/constraints.pro b/constraints.pro index ae27a8921..890b88d3e 100644 --- a/constraints.pro +++ b/constraints.pro @@ -255,6 +255,7 @@ gen_enforced_field(WorkspaceCwd, 'files', []) :- % All non-root packages must have the same "build" script. gen_enforced_field(WorkspaceCwd, 'scripts.build', 'ts-bridge --project tsconfig.build.json --clean') :- + WorkspaceCwd \= 'packages/ocap-skunkworks', WorkspaceCwd \= '.'. % All non-root packages must have the same "build:docs" script. From 6f0f2e67364bb0a73e281b74ce409927abc2b705 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 11:09:27 +0200 Subject: [PATCH 10/31] chore: Clean up and document Vite config --- packages/ocap-skunkworks/vite.config.extension.mts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/ocap-skunkworks/vite.config.extension.mts b/packages/ocap-skunkworks/vite.config.extension.mts index 6e0fdba5a..762ef528a 100644 --- a/packages/ocap-skunkworks/vite.config.extension.mts +++ b/packages/ocap-skunkworks/vite.config.extension.mts @@ -7,14 +7,17 @@ const root = './src/extension'; // https://vitejs.dev/config/ export default defineConfig({ root, - assetsInclude: ['**/*.json'], build: { + // Clean the outDir on build emptyOutDir: true, outDir: path.resolve(root, '../../dist'), rollupOptions: { + // Ignore the following module specifiers if imported external: [ + // This file and its imports must not be modified './apply-lockdown.mjs', ], + // Our entry points input: { background: path.resolve(root, 'background.ts'), offscreen: path.resolve(root, 'offscreen.html'), From 0e15d8ee94f9b6921ccbe9ca2c7832c07e900380 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 11:34:45 +0200 Subject: [PATCH 11/31] fix: Ensure .mts files are linted, tweak tsconfigs --- package.json | 2 +- packages/ocap-skunkworks/.eslintrc.js | 1 + .../ocap-skunkworks/tsconfig.library.json | 9 +++++ .../ocap-skunkworks/tsconfig.scripts.json | 8 ++++ .../ocap-skunkworks/vite.config.extension.mts | 38 ++++++++++--------- 5 files changed, 39 insertions(+), 19 deletions(-) create mode 100644 packages/ocap-skunkworks/tsconfig.library.json create mode 100644 packages/ocap-skunkworks/tsconfig.scripts.json diff --git a/package.json b/package.json index 90bd16198..4e8e3340c 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lint": "yarn lint:eslint && yarn lint:misc --check && yarn constraints && yarn lint:dependencies", "lint:dependencies": "depcheck && yarn dedupe --check", "lint:dependencies:fix": "depcheck && yarn dedupe", - "lint:eslint": "eslint . --cache --ext js,cjs,ts", + "lint:eslint": "eslint . --cache --ext js,cjs,ts,mts,cts", "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write && yarn constraints --fix && yarn lint:dependencies:fix", "lint:misc": "prettier '**/*.json' '**/*.md' '!**/CHANGELOG.old.md' '**/*.yml' '!.yarnrc.yml' '!merged-packages/**' --ignore-path .gitignore", "prepack": "./scripts/prepack.sh", diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/ocap-skunkworks/.eslintrc.js index bfe8c6244..71c0515e6 100644 --- a/packages/ocap-skunkworks/.eslintrc.js +++ b/packages/ocap-skunkworks/.eslintrc.js @@ -20,6 +20,7 @@ module.exports = { parserOptions: { sourceType: 'module', tsconfigRootDir: __dirname, + project: ['./tsconfig.scripts.json'], }, }, ], diff --git a/packages/ocap-skunkworks/tsconfig.library.json b/packages/ocap-skunkworks/tsconfig.library.json new file mode 100644 index 000000000..6f36a0492 --- /dev/null +++ b/packages/ocap-skunkworks/tsconfig.library.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "baseUrl": "./" + }, + "references": [], + "include": ["./src"], + "exclude": ["./src/extension"] +} diff --git a/packages/ocap-skunkworks/tsconfig.scripts.json b/packages/ocap-skunkworks/tsconfig.scripts.json new file mode 100644 index 000000000..e03a486d6 --- /dev/null +++ b/packages/ocap-skunkworks/tsconfig.scripts.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "baseUrl": "./" + }, + "references": [], + "include": ["./vite.config.extension.mts"] +} diff --git a/packages/ocap-skunkworks/vite.config.extension.mts b/packages/ocap-skunkworks/vite.config.extension.mts index 762ef528a..39463e16f 100644 --- a/packages/ocap-skunkworks/vite.config.extension.mts +++ b/packages/ocap-skunkworks/vite.config.extension.mts @@ -1,40 +1,42 @@ import path from 'path'; -import { defineConfig } from 'vite' +import { defineConfig } from 'vite'; import { viteStaticCopy } from 'vite-plugin-static-copy'; -const root = './src/extension'; +const projectRoot = './src/extension'; // https://vitejs.dev/config/ export default defineConfig({ - root, + root: projectRoot, + build: { - // Clean the outDir on build emptyOutDir: true, - outDir: path.resolve(root, '../../dist'), + outDir: path.resolve(projectRoot, '../../dist'), rollupOptions: { // Ignore the following module specifiers if imported external: [ // This file and its imports must not be modified './apply-lockdown.mjs', ], - // Our entry points input: { - background: path.resolve(root, 'background.ts'), - offscreen: path.resolve(root, 'offscreen.html'), + background: path.resolve(projectRoot, 'background.ts'), + offscreen: path.resolve(projectRoot, 'offscreen.html'), }, output: { entryFileNames: '[name].js', chunkFileNames: '[name].js', - assetFileNames: '[name].[ext]' - } - } + assetFileNames: '[name].[ext]', + }, + }, }, + plugins: [ - viteStaticCopy({ targets: [ - { src: 'manifest.json', dest: './' }, - { src: 'apply-lockdown.mjs', dest: './' }, - { src: '../../../../node_modules/ses/dist/ses.mjs', dest: './' }, - { src: '../../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, - ]}) - ] + viteStaticCopy({ + targets: [ + { src: 'manifest.json', dest: './' }, + { src: 'apply-lockdown.mjs', dest: './' }, + { src: '../../../../node_modules/ses/dist/ses.mjs', dest: './' }, + { src: '../../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, + ], + }), + ], }); From 2b493773cd50dea7c084ed06249265bdd13ff31e Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 12:08:52 +0200 Subject: [PATCH 12/31] refactor: Just let the extension be its own entire package (duh) --- constraints.pro | 4 +- package.json | 4 +- .../.eslintrc.js | 4 +- .../{ocap-skunkworks => extension}/README.md | 8 ++-- .../jest.config.js | 0 .../package.json | 15 +++--- .../src}/apply-lockdown.mjs | 4 +- .../extension => extension/src}/background.ts | 0 .../extension => extension/src}/manifest.json | 2 +- .../src}/offscreen.html | 0 .../extension => extension/src}/offscreen.ts | 0 .../src/extension => extension/src}/shared.ts | 0 .../src => }/extension/tsconfig.json | 4 +- .../tsconfig.scripts.json} | 2 +- .../vite.config.mts} | 8 ++-- packages/ocap-skunkworks/tsconfig.build.json | 11 ----- .../ocap-skunkworks/tsconfig.library.json | 9 ---- .../ocap-skunkworks/tsconfig.scripts.json | 8 ---- packages/ocap-skunkworks/typedoc.json | 7 --- tsconfig.build.json | 2 +- tsconfig.json | 2 +- yarn.lock | 48 +++++++++---------- 22 files changed, 53 insertions(+), 89 deletions(-) rename packages/{ocap-skunkworks => extension}/.eslintrc.js (87%) rename packages/{ocap-skunkworks => extension}/README.md (57%) rename packages/{ocap-skunkworks => extension}/jest.config.js (100%) rename packages/{ocap-skunkworks => extension}/package.json (66%) rename packages/{ocap-skunkworks/src/extension => extension/src}/apply-lockdown.mjs (76%) rename packages/{ocap-skunkworks/src/extension => extension/src}/background.ts (100%) rename packages/{ocap-skunkworks/src/extension => extension/src}/manifest.json (85%) rename packages/{ocap-skunkworks/src/extension => extension/src}/offscreen.html (100%) rename packages/{ocap-skunkworks/src/extension => extension/src}/offscreen.ts (100%) rename packages/{ocap-skunkworks/src/extension => extension/src}/shared.ts (100%) rename packages/{ocap-skunkworks/src => }/extension/tsconfig.json (63%) rename packages/{ocap-skunkworks/tsconfig.json => extension/tsconfig.scripts.json} (76%) rename packages/{ocap-skunkworks/vite.config.extension.mts => extension/vite.config.mts} (78%) delete mode 100644 packages/ocap-skunkworks/tsconfig.build.json delete mode 100644 packages/ocap-skunkworks/tsconfig.library.json delete mode 100644 packages/ocap-skunkworks/tsconfig.scripts.json delete mode 100644 packages/ocap-skunkworks/typedoc.json diff --git a/constraints.pro b/constraints.pro index 890b88d3e..5599ee953 100644 --- a/constraints.pro +++ b/constraints.pro @@ -99,6 +99,7 @@ workspace_basename(WorkspaceCwd, WorkspaceBasename) :- % and is not private. workspace_package_name(WorkspaceCwd, WorkspacePackageName) :- workspace_basename(WorkspaceCwd, WorkspaceBasename), + workspace_field(WorkspaceCwd, 'private', false), atom_concat('@metamask/', WorkspaceBasename, WorkspacePackageName). % True if RepoName can be unified with the repository name part of RepoUrl, a @@ -255,11 +256,12 @@ gen_enforced_field(WorkspaceCwd, 'files', []) :- % All non-root packages must have the same "build" script. gen_enforced_field(WorkspaceCwd, 'scripts.build', 'ts-bridge --project tsconfig.build.json --clean') :- - WorkspaceCwd \= 'packages/ocap-skunkworks', + WorkspaceCwd \= 'packages/extension', WorkspaceCwd \= '.'. % All non-root packages must have the same "build:docs" script. gen_enforced_field(WorkspaceCwd, 'scripts.build:docs', 'typedoc') :- + WorkspaceCwd \= 'packages/extension', WorkspaceCwd \= '.'. % All published packages must have the same "publish:preview" script. diff --git a/package.json b/package.json index 4e8e3340c..d4ed68d35 100644 --- a/package.json +++ b/package.json @@ -11,9 +11,9 @@ "packages/*" ], "scripts": { - "build": "yarn run build:source && yarn run build:types", + "build": "yarn run build:source", "build:clean": "yarn clean && yarn build", - "build:docs": "yarn workspaces foreach --all --exclude ocap-kernel-monorepo --parallel --interlaced --verbose run build:docs", + "build:docs": "yarn workspaces foreach --all --exclude ocap-kernel-monorepo --exclude extension --parallel --interlaced --verbose run build:docs", "build:source": "yarn workspaces foreach --all --parallel --exclude ocap-kernel-monorepo --interlaced --verbose run build", "build:types": "tsc --build tsconfig.build.json --verbose", "build:watch": "yarn run build --watch", diff --git a/packages/ocap-skunkworks/.eslintrc.js b/packages/extension/.eslintrc.js similarity index 87% rename from packages/ocap-skunkworks/.eslintrc.js rename to packages/extension/.eslintrc.js index 71c0515e6..6446e3e70 100644 --- a/packages/ocap-skunkworks/.eslintrc.js +++ b/packages/extension/.eslintrc.js @@ -3,7 +3,7 @@ module.exports = { overrides: [ { - files: ['src/extension/**/*.js'], + files: ['src/**/*.js'], globals: { chrome: 'readonly', clients: 'readonly' }, }, @@ -16,7 +16,7 @@ module.exports = { }, { - files: ['vite.*.mts'], + files: ['vite.config.mts'], parserOptions: { sourceType: 'module', tsconfigRootDir: __dirname, diff --git a/packages/ocap-skunkworks/README.md b/packages/extension/README.md similarity index 57% rename from packages/ocap-skunkworks/README.md rename to packages/extension/README.md index fd48d79d9..608594e77 100644 --- a/packages/ocap-skunkworks/README.md +++ b/packages/extension/README.md @@ -1,14 +1,14 @@ -# `@metamask/ocap-skunkworks` +# `extension` -A home for Ocap Kernel experiments. +For running Ocap Kernel experiments in an extension environment. ## Installation -`yarn add @metamask/ocap-skunkworks` +`yarn add extension` or -`npm install @metamask/ocap-skunkworks` +`npm install extension` ## Contributing diff --git a/packages/ocap-skunkworks/jest.config.js b/packages/extension/jest.config.js similarity index 100% rename from packages/ocap-skunkworks/jest.config.js rename to packages/extension/jest.config.js diff --git a/packages/ocap-skunkworks/package.json b/packages/extension/package.json similarity index 66% rename from packages/ocap-skunkworks/package.json rename to packages/extension/package.json index 339ac378a..3dadd9ed5 100644 --- a/packages/ocap-skunkworks/package.json +++ b/packages/extension/package.json @@ -1,8 +1,8 @@ { - "name": "@metamask/ocap-skunkworks", + "name": "extension", "version": "0.0.0", "private": true, - "description": "A home for Ocap Kernel experiments", + "description": "For running Ocap Kernel experiments in an extension environment", "repository": { "type": "git", "url": "https://github.com/MetaMask/ocap-kernel.git" @@ -11,14 +11,11 @@ "dist/" ], "scripts": { - "build": "yarn build:extension", - "build:docs": "typedoc", - "build:extension": "yarn check:types:extension && vite build -c vite.config.extension.mts", - "build:library": "ts-bridge --project tsconfig.build.json --clean", - "changelog:validate": "../../scripts/validate-changelog.sh @metamask/ocap-skunkworks", - "check:types:extension": "tsc --project src/extension/tsconfig.json", + "build": "yarn check:types && vite build -c vite.config.mts", + "changelog:validate": "../../scripts/validate-changelog.sh extension", + "check:types": "tsc", "publish:preview": "yarn npm publish --tag preview", - "start": "vite -c vite.config.extension.mts", + "start": "vite -c vite.config.mts", "test": "jest --reporters=jest-silent-reporter", "posttest": "jest-it-up", "test:clean": "jest --clearCache", diff --git a/packages/ocap-skunkworks/src/extension/apply-lockdown.mjs b/packages/extension/src/apply-lockdown.mjs similarity index 76% rename from packages/ocap-skunkworks/src/extension/apply-lockdown.mjs rename to packages/extension/src/apply-lockdown.mjs index ef718651e..1a3fd7cd7 100644 --- a/packages/ocap-skunkworks/src/extension/apply-lockdown.mjs +++ b/packages/extension/src/apply-lockdown.mjs @@ -1,5 +1,5 @@ -import './ses.mjs'; -import './lockdown.mjs'; +import './ses.mjs.js'; +import './lockdown.mjs.js'; lockdown({ consoleTaming: 'unsafe', diff --git a/packages/ocap-skunkworks/src/extension/background.ts b/packages/extension/src/background.ts similarity index 100% rename from packages/ocap-skunkworks/src/extension/background.ts rename to packages/extension/src/background.ts diff --git a/packages/ocap-skunkworks/src/extension/manifest.json b/packages/extension/src/manifest.json similarity index 85% rename from packages/ocap-skunkworks/src/extension/manifest.json rename to packages/extension/src/manifest.json index 0b2410ba4..07d2de6ef 100644 --- a/packages/ocap-skunkworks/src/extension/manifest.json +++ b/packages/extension/src/manifest.json @@ -1,5 +1,5 @@ { - "name": "Ocap Kernel Skunkworks Extension", + "name": "Ocap Kernel Test Extension", "version": "0.0", "description": "For running Ocap Kernel experiments in an extension environment.", "manifest_version": 3, diff --git a/packages/ocap-skunkworks/src/extension/offscreen.html b/packages/extension/src/offscreen.html similarity index 100% rename from packages/ocap-skunkworks/src/extension/offscreen.html rename to packages/extension/src/offscreen.html diff --git a/packages/ocap-skunkworks/src/extension/offscreen.ts b/packages/extension/src/offscreen.ts similarity index 100% rename from packages/ocap-skunkworks/src/extension/offscreen.ts rename to packages/extension/src/offscreen.ts diff --git a/packages/ocap-skunkworks/src/extension/shared.ts b/packages/extension/src/shared.ts similarity index 100% rename from packages/ocap-skunkworks/src/extension/shared.ts rename to packages/extension/src/shared.ts diff --git a/packages/ocap-skunkworks/src/extension/tsconfig.json b/packages/extension/tsconfig.json similarity index 63% rename from packages/ocap-skunkworks/src/extension/tsconfig.json rename to packages/extension/tsconfig.json index e68794cdb..400bdc740 100644 --- a/packages/ocap-skunkworks/src/extension/tsconfig.json +++ b/packages/extension/tsconfig.json @@ -1,5 +1,5 @@ { - "extends": "../../tsconfig.json", + "extends": "../../tsconfig.packages.json", "compilerOptions": { "allowJs": true, "isolatedModules": true, @@ -8,5 +8,5 @@ "skipLibCheck": true, "types": ["chrome"] }, - "include": ["./**/*.ts", "./apply-lockdown.mjs"] + "include": ["./src/**/*.ts", "./src/apply-lockdown.mjs"] } diff --git a/packages/ocap-skunkworks/tsconfig.json b/packages/extension/tsconfig.scripts.json similarity index 76% rename from packages/ocap-skunkworks/tsconfig.json rename to packages/extension/tsconfig.scripts.json index fefbaf5a1..66e910cf8 100644 --- a/packages/ocap-skunkworks/tsconfig.json +++ b/packages/extension/tsconfig.scripts.json @@ -4,5 +4,5 @@ "baseUrl": "./" }, "references": [], - "include": [] + "include": ["./vite.config.mts"] } diff --git a/packages/ocap-skunkworks/vite.config.extension.mts b/packages/extension/vite.config.mts similarity index 78% rename from packages/ocap-skunkworks/vite.config.extension.mts rename to packages/extension/vite.config.mts index 39463e16f..1eefa37dc 100644 --- a/packages/ocap-skunkworks/vite.config.extension.mts +++ b/packages/extension/vite.config.mts @@ -2,7 +2,7 @@ import path from 'path'; import { defineConfig } from 'vite'; import { viteStaticCopy } from 'vite-plugin-static-copy'; -const projectRoot = './src/extension'; +const projectRoot = './src'; // https://vitejs.dev/config/ export default defineConfig({ @@ -10,7 +10,7 @@ export default defineConfig({ build: { emptyOutDir: true, - outDir: path.resolve(projectRoot, '../../dist'), + outDir: path.resolve(projectRoot, './dist'), rollupOptions: { // Ignore the following module specifiers if imported external: [ @@ -34,8 +34,8 @@ export default defineConfig({ targets: [ { src: 'manifest.json', dest: './' }, { src: 'apply-lockdown.mjs', dest: './' }, - { src: '../../../../node_modules/ses/dist/ses.mjs', dest: './' }, - { src: '../../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, + { src: '../../../node_modules/ses/dist/ses.mjs', dest: './' }, + { src: '../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, ], }), ], diff --git a/packages/ocap-skunkworks/tsconfig.build.json b/packages/ocap-skunkworks/tsconfig.build.json deleted file mode 100644 index 639f53e44..000000000 --- a/packages/ocap-skunkworks/tsconfig.build.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.packages.build.json", - "compilerOptions": { - "baseUrl": "./", - "outDir": "./dist", - "rootDir": "./src" - }, - "references": [], - "include": ["../../types", "./src"], - "exclude": ["./src/extension"] -} diff --git a/packages/ocap-skunkworks/tsconfig.library.json b/packages/ocap-skunkworks/tsconfig.library.json deleted file mode 100644 index 6f36a0492..000000000 --- a/packages/ocap-skunkworks/tsconfig.library.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "baseUrl": "./" - }, - "references": [], - "include": ["./src"], - "exclude": ["./src/extension"] -} diff --git a/packages/ocap-skunkworks/tsconfig.scripts.json b/packages/ocap-skunkworks/tsconfig.scripts.json deleted file mode 100644 index e03a486d6..000000000 --- a/packages/ocap-skunkworks/tsconfig.scripts.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "extends": "./tsconfig.json", - "compilerOptions": { - "baseUrl": "./" - }, - "references": [], - "include": ["./vite.config.extension.mts"] -} diff --git a/packages/ocap-skunkworks/typedoc.json b/packages/ocap-skunkworks/typedoc.json deleted file mode 100644 index c9da015db..000000000 --- a/packages/ocap-skunkworks/typedoc.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "entryPoints": ["./src/index.ts"], - "excludePrivate": true, - "hideGenerator": true, - "out": "docs", - "tsconfig": "./tsconfig.build.json" -} diff --git a/tsconfig.build.json b/tsconfig.build.json index 9bedded2e..c3f66a6bc 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,5 +1,5 @@ { "files": [], "include": [], - "references": [{ "path": "./packages/ocap-skunkworks/tsconfig.build.json" }] + "references": [] } diff --git a/tsconfig.json b/tsconfig.json index 91235f869..815a7a9f4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,5 +6,5 @@ }, "files": [], "include": [], - "references": [{ "path": "./packages/ocap-skunkworks" }] + "references": [{ "path": "./packages/extension" }] } diff --git a/yarn.lock b/yarn.lock index 3d98ed6d4..1c2774fe2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1176,30 +1176,6 @@ __metadata: languageName: node linkType: hard -"@metamask/ocap-skunkworks@workspace:packages/ocap-skunkworks": - version: 0.0.0-use.local - resolution: "@metamask/ocap-skunkworks@workspace:packages/ocap-skunkworks" - dependencies: - "@arethetypeswrong/cli": "npm:^0.15.3" - "@endo/lockdown": "npm:^1.0.7" - "@metamask/auto-changelog": "npm:^3.4.4" - "@ts-bridge/cli": "npm:^0.1.4" - "@ts-bridge/shims": "npm:^0.1.1" - "@types/chrome": "npm:^0.0.268" - "@types/jest": "npm:^28.1.6" - deepmerge: "npm:^4.3.1" - jest: "npm:^28.1.3" - jest-it-up: "npm:^2.0.2" - ses: "npm:^1.5.0" - ts-jest: "npm:^28.0.7" - typedoc: "npm:^0.24.8" - typedoc-plugin-missing-exports: "npm:^2.0.0" - typescript: "npm:~4.9.5" - vite: "npm:^5.3.4" - vite-plugin-static-copy: "npm:^1.0.6" - languageName: unknown - linkType: soft - "@nodelib/fs.scandir@npm:2.1.5": version: 2.1.5 resolution: "@nodelib/fs.scandir@npm:2.1.5" @@ -3585,6 +3561,30 @@ __metadata: languageName: node linkType: hard +"extension@workspace:packages/extension": + version: 0.0.0-use.local + resolution: "extension@workspace:packages/extension" + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/lockdown": "npm:^1.0.7" + "@metamask/auto-changelog": "npm:^3.4.4" + "@ts-bridge/cli": "npm:^0.1.4" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/chrome": "npm:^0.0.268" + "@types/jest": "npm:^28.1.6" + deepmerge: "npm:^4.3.1" + jest: "npm:^28.1.3" + jest-it-up: "npm:^2.0.2" + ses: "npm:^1.5.0" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~4.9.5" + vite: "npm:^5.3.4" + vite-plugin-static-copy: "npm:^1.0.6" + languageName: unknown + linkType: soft + "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" From 845c7e77b07fcd24e7540961d0ed687a92e9feca Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 13:12:36 +0200 Subject: [PATCH 13/31] feat: Add "germs" package --- constraints.pro | 9 +- package.json | 2 +- packages/extension/README.md | 8 - packages/extension/package.json | 7 +- packages/extension/tsconfig.build.json | 3 + packages/germs/CHANGELOG.md | 10 + packages/germs/LICENSE | 20 ++ packages/germs/README.md | 7 + packages/germs/jest.config.js | 26 ++ packages/germs/package.json | 56 +++ packages/germs/src/index.test.ts | 9 + packages/germs/src/index.ts | 9 + packages/germs/tsconfig.build.json | 10 + packages/germs/tsconfig.json | 8 + packages/germs/typedoc.json | 7 + tsconfig.build.json | 5 +- tsconfig.json | 5 +- tsconfig.packages.build.json | 1 + yarn.lock | 458 +++++++++++++------------ 19 files changed, 424 insertions(+), 236 deletions(-) create mode 100644 packages/extension/tsconfig.build.json create mode 100644 packages/germs/CHANGELOG.md create mode 100644 packages/germs/LICENSE create mode 100644 packages/germs/README.md create mode 100644 packages/germs/jest.config.js create mode 100644 packages/germs/package.json create mode 100644 packages/germs/src/index.test.ts create mode 100644 packages/germs/src/index.ts create mode 100644 packages/germs/tsconfig.build.json create mode 100644 packages/germs/tsconfig.json create mode 100644 packages/germs/typedoc.json diff --git a/constraints.pro b/constraints.pro index 5599ee953..0cde5de54 100644 --- a/constraints.pro +++ b/constraints.pro @@ -208,8 +208,10 @@ gen_enforced_field(WorkspaceCwd, 'module', './dist/index.mjs') :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify an entrypoint. gen_enforced_field(WorkspaceCwd, 'main', null) :- + WorkspaceCwd \= 'packages/germs', workspace_field(WorkspaceCwd, 'private', true). gen_enforced_field(WorkspaceCwd, 'module', null) :- + WorkspaceCwd \= 'packages/germs', workspace_field(WorkspaceCwd, 'private', true). % The type definitions entrypoint for all publishable packages must be the same. @@ -217,6 +219,7 @@ gen_enforced_field(WorkspaceCwd, 'types', './dist/index.d.cts') :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify a type definitions entrypoint. gen_enforced_field(WorkspaceCwd, 'types', null) :- + WorkspaceCwd \= 'packages/germs', workspace_field(WorkspaceCwd, 'private', true). % The exports for all published packages must be the same. @@ -235,6 +238,7 @@ gen_enforced_field(WorkspaceCwd, 'exports["./package.json"]', './package.json') \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify exports. gen_enforced_field(WorkspaceCwd, 'exports', null) :- + WorkspaceCwd \= 'packages/germs', workspace_field(WorkspaceCwd, 'private', true). % Published packages must not have side effects. @@ -242,6 +246,7 @@ gen_enforced_field(WorkspaceCwd, 'sideEffects', false) :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify side effects. gen_enforced_field(WorkspaceCwd, 'sideEffects', null) :- + WorkspaceCwd \= 'packages/germs', workspace_field(WorkspaceCwd, 'private', true). % The list of files included in published packages must only include files @@ -254,12 +259,12 @@ gen_enforced_field(WorkspaceCwd, 'files', ['dist/']) :- gen_enforced_field(WorkspaceCwd, 'files', []) :- WorkspaceCwd = '.'. -% All non-root packages must have the same "build" script. +% All packages except the root and extension must have the same "build" script. gen_enforced_field(WorkspaceCwd, 'scripts.build', 'ts-bridge --project tsconfig.build.json --clean') :- WorkspaceCwd \= 'packages/extension', WorkspaceCwd \= '.'. -% All non-root packages must have the same "build:docs" script. +% All packages except the root and extension must have the same "build:docs" script. gen_enforced_field(WorkspaceCwd, 'scripts.build:docs', 'typedoc') :- WorkspaceCwd \= 'packages/extension', WorkspaceCwd \= '.'. diff --git a/package.json b/package.json index d4ed68d35..ab7afdfeb 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "packages/*" ], "scripts": { - "build": "yarn run build:source", + "build": "yarn run build:source && yarn build:types", "build:clean": "yarn clean && yarn build", "build:docs": "yarn workspaces foreach --all --exclude ocap-kernel-monorepo --exclude extension --parallel --interlaced --verbose run build:docs", "build:source": "yarn workspaces foreach --all --parallel --exclude ocap-kernel-monorepo --interlaced --verbose run build", diff --git a/packages/extension/README.md b/packages/extension/README.md index 608594e77..0bca64f81 100644 --- a/packages/extension/README.md +++ b/packages/extension/README.md @@ -2,14 +2,6 @@ For running Ocap Kernel experiments in an extension environment. -## Installation - -`yarn add extension` - -or - -`npm install extension` - ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/ocap-kernel#readme). diff --git a/packages/extension/package.json b/packages/extension/package.json index 3dadd9ed5..2d6a8abbb 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -11,9 +11,10 @@ "dist/" ], "scripts": { - "build": "yarn check:types && vite build -c vite.config.mts", + "build": "yarn build:types && yarn build:vite", + "build:types": "tsc", + "build:vite": "vite build -c vite.config.mts", "changelog:validate": "../../scripts/validate-changelog.sh extension", - "check:types": "tsc", "publish:preview": "yarn npm publish --tag preview", "start": "vite -c vite.config.mts", "test": "jest --reporters=jest-silent-reporter", @@ -29,8 +30,6 @@ "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@metamask/auto-changelog": "^3.4.4", - "@ts-bridge/cli": "^0.1.4", - "@ts-bridge/shims": "^0.1.1", "@types/chrome": "^0.0.268", "@types/jest": "^28.1.6", "deepmerge": "^4.3.1", diff --git a/packages/extension/tsconfig.build.json b/packages/extension/tsconfig.build.json new file mode 100644 index 000000000..fc8520e73 --- /dev/null +++ b/packages/extension/tsconfig.build.json @@ -0,0 +1,3 @@ +{ + "extends": "./tsconfig.json" +} diff --git a/packages/germs/CHANGELOG.md b/packages/germs/CHANGELOG.md new file mode 100644 index 000000000..0c82cb1ed --- /dev/null +++ b/packages/germs/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [Unreleased] + +[Unreleased]: https://github.com/MetaMask/ocap-kernel/ diff --git a/packages/germs/LICENSE b/packages/germs/LICENSE new file mode 100644 index 000000000..6f8bff03f --- /dev/null +++ b/packages/germs/LICENSE @@ -0,0 +1,20 @@ +MIT License + +Copyright (c) 2024 MetaMask + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE diff --git a/packages/germs/README.md b/packages/germs/README.md new file mode 100644 index 000000000..ead6ceb8c --- /dev/null +++ b/packages/germs/README.md @@ -0,0 +1,7 @@ +# `germs` + +From these germs, a Kernel will form. + +## Contributing + +This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/ocap-kernel#readme). diff --git a/packages/germs/jest.config.js b/packages/germs/jest.config.js new file mode 100644 index 000000000..ca0841333 --- /dev/null +++ b/packages/germs/jest.config.js @@ -0,0 +1,26 @@ +/* + * For a detailed explanation regarding each configuration property and type check, visit: + * https://jestjs.io/docs/configuration + */ + +const merge = require('deepmerge'); +const path = require('path'); + +const baseConfig = require('../../jest.config.packages'); + +const displayName = path.basename(__dirname); + +module.exports = merge(baseConfig, { + // The display name when running multiple projects + displayName, + + // An object that configures minimum threshold enforcement for coverage results + coverageThreshold: { + global: { + branches: 100, + functions: 100, + lines: 100, + statements: 100, + }, + }, +}); diff --git a/packages/germs/package.json b/packages/germs/package.json new file mode 100644 index 000000000..55530ad9f --- /dev/null +++ b/packages/germs/package.json @@ -0,0 +1,56 @@ +{ + "name": "germs", + "version": "0.0.0", + "private": true, + "description": "From these germs, a Kernel will form", + "repository": { + "type": "git", + "url": "https://github.com/MetaMask/ocap-kernel.git" + }, + "sideEffects": false, + "exports": { + ".": { + "import": { + "types": "./dist/index.d.mts", + "default": "./dist/index.mjs" + }, + "require": { + "types": "./dist/index.d.cts", + "default": "./dist/index.cjs" + } + }, + "./package.json": "./package.json" + }, + "main": "./dist/index.cjs", + "module": "./dist/index.mjs", + "types": "./dist/index.d.cts", + "files": [ + "dist" + ], + "scripts": { + "build": "ts-bridge --project tsconfig.build.json --clean", + "build:docs": "typedoc", + "changelog:validate": "../../scripts/validate-changelog.sh germs", + "publish:preview": "yarn npm publish --tag preview", + "test": "jest --reporters=jest-silent-reporter", + "test:clean": "jest --clearCache", + "test:verbose": "jest --verbose", + "test:watch": "jest --watch" + }, + "devDependencies": { + "@arethetypeswrong/cli": "^0.15.3", + "@metamask/auto-changelog": "^3.4.4", + "@ts-bridge/cli": "^0.1.4", + "@ts-bridge/shims": "^0.1.1", + "@types/jest": "^28.1.6", + "deepmerge": "^4.3.1", + "jest": "^28.1.3", + "ts-jest": "^28.0.7", + "typedoc": "^0.24.8", + "typedoc-plugin-missing-exports": "^2.0.0", + "typescript": "~4.9.5" + }, + "engines": { + "node": "^18.18 || >=20" + } +} diff --git a/packages/germs/src/index.test.ts b/packages/germs/src/index.test.ts new file mode 100644 index 000000000..bc062d369 --- /dev/null +++ b/packages/germs/src/index.test.ts @@ -0,0 +1,9 @@ +import greeter from '.'; + +describe('Test', () => { + it('greets', () => { + const name = 'Huey'; + const result = greeter(name); + expect(result).toBe('Hello, Huey!'); + }); +}); diff --git a/packages/germs/src/index.ts b/packages/germs/src/index.ts new file mode 100644 index 000000000..6972c1172 --- /dev/null +++ b/packages/germs/src/index.ts @@ -0,0 +1,9 @@ +/** + * Example function that returns a greeting for the given name. + * + * @param name - The name to greet. + * @returns The greeting. + */ +export default function greeter(name: string): string { + return `Hello, ${name}!`; +} diff --git a/packages/germs/tsconfig.build.json b/packages/germs/tsconfig.build.json new file mode 100644 index 000000000..c622f4091 --- /dev/null +++ b/packages/germs/tsconfig.build.json @@ -0,0 +1,10 @@ +{ + "extends": "../../tsconfig.packages.build.json", + "compilerOptions": { + "baseUrl": "./", + "outDir": "./dist", + "rootDir": "./src" + }, + "references": [], + "include": ["./src"] +} diff --git a/packages/germs/tsconfig.json b/packages/germs/tsconfig.json new file mode 100644 index 000000000..6f1d89de4 --- /dev/null +++ b/packages/germs/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.packages.json", + "compilerOptions": { + "baseUrl": "./" + }, + "references": [], + "include": ["./src"] +} diff --git a/packages/germs/typedoc.json b/packages/germs/typedoc.json new file mode 100644 index 000000000..c9da015db --- /dev/null +++ b/packages/germs/typedoc.json @@ -0,0 +1,7 @@ +{ + "entryPoints": ["./src/index.ts"], + "excludePrivate": true, + "hideGenerator": true, + "out": "docs", + "tsconfig": "./tsconfig.build.json" +} diff --git a/tsconfig.build.json b/tsconfig.build.json index c3f66a6bc..14e9b8b63 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -1,5 +1,8 @@ { "files": [], "include": [], - "references": [] + "references": [ + { "path": "./packages/extension/tsconfig.build.json" }, + { "path": "./packages/germs/tsconfig.build.json" } + ] } diff --git a/tsconfig.json b/tsconfig.json index 815a7a9f4..13c37aad1 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,5 +6,8 @@ }, "files": [], "include": [], - "references": [{ "path": "./packages/extension" }] + "references": [ + { "path": "./packages/extension" }, + { "path": "./packages/germs" } + ] } diff --git a/tsconfig.packages.build.json b/tsconfig.packages.build.json index 7f10e4b8b..ffd5bb4db 100644 --- a/tsconfig.packages.build.json +++ b/tsconfig.packages.build.json @@ -5,6 +5,7 @@ "declarationMap": true, "emitDeclarationOnly": true, "inlineSources": true, + "skipLibCheck": true, "sourceMap": true }, "exclude": [ diff --git a/yarn.lock b/yarn.lock index 1c2774fe2..e8a7e7915 100644 --- a/yarn.lock +++ b/yarn.lock @@ -60,118 +60,121 @@ __metadata: languageName: node linkType: hard -"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.22.13": - version: 7.22.13 - resolution: "@babel/code-frame@npm:7.22.13" +"@babel/code-frame@npm:^7.0.0, @babel/code-frame@npm:^7.12.13, @babel/code-frame@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/code-frame@npm:7.24.7" dependencies: - "@babel/highlight": "npm:^7.22.13" - chalk: "npm:^2.4.2" - checksum: 10/bf6ae6ba3a510adfda6a211b4a89b0f1c98ca1352b745c077d113f3b568141e0d44ce750b9ac2a80143ba5c8c4080c50fcfc1aa11d86e194ea6785f62520eb5a + "@babel/highlight": "npm:^7.24.7" + picocolors: "npm:^1.0.0" + checksum: 10/4812e94885ba7e3213d49583a155fdffb05292330f0a9b2c41b49288da70cf3c746a3fda0bf1074041a6d741c33f8d7be24be5e96f41ef77395eeddc5c9ff624 languageName: node linkType: hard -"@babel/compat-data@npm:^7.22.9": - version: 7.23.2 - resolution: "@babel/compat-data@npm:7.23.2" - checksum: 10/c18eccd13975c1434a65d04f721075e30d03ba1608f4872d84e8538c16552b878aaac804ff31243d8c2c0e91524f3bc98de6305e117ba1a55c9956871973b4dc +"@babel/compat-data@npm:^7.24.8": + version: 7.24.9 + resolution: "@babel/compat-data@npm:7.24.9" + checksum: 10/fcdbf3dd978305880f06ae20a23f4f68a8eddbe64fc5d2fbc98dfe4cdf15c174cff41e3a8eb9d935f9f3a68d3a23fa432044082ee9768a2ed4b15f769b8f6853 languageName: node linkType: hard "@babel/core@npm:^7.11.6, @babel/core@npm:^7.12.3": - version: 7.23.2 - resolution: "@babel/core@npm:7.23.2" + version: 7.24.9 + resolution: "@babel/core@npm:7.24.9" dependencies: "@ampproject/remapping": "npm:^2.2.0" - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.0" - "@babel/helper-compilation-targets": "npm:^7.22.15" - "@babel/helper-module-transforms": "npm:^7.23.0" - "@babel/helpers": "npm:^7.23.2" - "@babel/parser": "npm:^7.23.0" - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.9" + "@babel/helper-compilation-targets": "npm:^7.24.8" + "@babel/helper-module-transforms": "npm:^7.24.9" + "@babel/helpers": "npm:^7.24.8" + "@babel/parser": "npm:^7.24.8" + "@babel/template": "npm:^7.24.7" + "@babel/traverse": "npm:^7.24.8" + "@babel/types": "npm:^7.24.9" convert-source-map: "npm:^2.0.0" debug: "npm:^4.1.0" gensync: "npm:^1.0.0-beta.2" json5: "npm:^2.2.3" semver: "npm:^6.3.1" - checksum: 10/b69d7008695b2ac7a3a2db83c5c712fbb79f7031c4480f6351cde327930e38873003d1d021059b729a1d0cb48093f1d384c64269b78f6189f50051fe4f64dc2d + checksum: 10/f00a372fa547f6e21f4db1b6e521e6eb01f77f5931726897aae6f4cf29a687f615b9b77147b539e851a68bf94e4850bcfba7eb11091dd8e2bc625f6d831ce257 languageName: node linkType: hard -"@babel/generator@npm:^7.23.0, @babel/generator@npm:^7.7.2": - version: 7.23.0 - resolution: "@babel/generator@npm:7.23.0" +"@babel/generator@npm:^7.24.8, @babel/generator@npm:^7.24.9, @babel/generator@npm:^7.7.2": + version: 7.24.10 + resolution: "@babel/generator@npm:7.24.10" dependencies: - "@babel/types": "npm:^7.23.0" - "@jridgewell/gen-mapping": "npm:^0.3.2" - "@jridgewell/trace-mapping": "npm:^0.3.17" + "@babel/types": "npm:^7.24.9" + "@jridgewell/gen-mapping": "npm:^0.3.5" + "@jridgewell/trace-mapping": "npm:^0.3.25" jsesc: "npm:^2.5.1" - checksum: 10/bd1598bd356756065d90ce26968dd464ac2b915c67623f6f071fb487da5f9eb454031a380e20e7c9a7ce5c4a49d23be6cb9efde404952b0b3f3c0c3a9b73d68a + checksum: 10/c2491fb7d985527a165546cbcf9e5f6a2518f2a968c7564409c012acce1019056b21e67a152af89b3f4d4a295ca2e75a1a16858152f750efbc4b5087f0cb7253 languageName: node linkType: hard -"@babel/helper-compilation-targets@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-compilation-targets@npm:7.22.15" +"@babel/helper-compilation-targets@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-compilation-targets@npm:7.24.8" dependencies: - "@babel/compat-data": "npm:^7.22.9" - "@babel/helper-validator-option": "npm:^7.22.15" - browserslist: "npm:^4.21.9" + "@babel/compat-data": "npm:^7.24.8" + "@babel/helper-validator-option": "npm:^7.24.8" + browserslist: "npm:^4.23.1" lru-cache: "npm:^5.1.1" semver: "npm:^6.3.1" - checksum: 10/9706decaa1591cf44511b6f3447eb9653b50ca3538215fe2e5387a8598c258c062f4622da5b95e61f0415706534deee619bbf53a2889f9bd967949b8f6024e0e + checksum: 10/3489280d07b871af565b32f9b11946ff9a999fac0db9bec5df960760f6836c7a4b52fccb9d64229ccce835d37a43afb85659beb439ecedde04dcea7eb062a143 languageName: node linkType: hard -"@babel/helper-environment-visitor@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-environment-visitor@npm:7.22.20" - checksum: 10/d80ee98ff66f41e233f36ca1921774c37e88a803b2f7dca3db7c057a5fea0473804db9fb6729e5dbfd07f4bed722d60f7852035c2c739382e84c335661590b69 +"@babel/helper-environment-visitor@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-environment-visitor@npm:7.24.7" + dependencies: + "@babel/types": "npm:^7.24.7" + checksum: 10/079d86e65701b29ebc10baf6ed548d17c19b808a07aa6885cc141b690a78581b180ee92b580d755361dc3b16adf975b2d2058b8ce6c86675fcaf43cf22f2f7c6 languageName: node linkType: hard -"@babel/helper-function-name@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-function-name@npm:7.23.0" +"@babel/helper-function-name@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-function-name@npm:7.24.7" dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/types": "npm:^7.23.0" - checksum: 10/7b2ae024cd7a09f19817daf99e0153b3bf2bc4ab344e197e8d13623d5e36117ed0b110914bc248faa64e8ccd3e97971ec7b41cc6fd6163a2b980220c58dcdf6d + "@babel/template": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10/2ceb3d9b2b35a0fc4100fc06ed7be3bc38f03ff0bf128ff0edbc0cc7dd842967b1496fc70b5c616c747d7711c2b87e7d025c8888f48740631d6148a9d3614f85 languageName: node linkType: hard -"@babel/helper-hoist-variables@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-hoist-variables@npm:7.22.5" +"@babel/helper-hoist-variables@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-hoist-variables@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/394ca191b4ac908a76e7c50ab52102669efe3a1c277033e49467913c7ed6f7c64d7eacbeabf3bed39ea1f41731e22993f763b1edce0f74ff8563fd1f380d92cc + "@babel/types": "npm:^7.24.7" + checksum: 10/6cfdcf2289cd12185dcdbdf2435fa8d3447b797ac75851166de9fc8503e2fd0021db6baf8dfbecad3753e582c08e6a3f805c8d00cbed756060a877d705bd8d8d languageName: node linkType: hard -"@babel/helper-module-imports@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-module-imports@npm:7.22.15" +"@babel/helper-module-imports@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-module-imports@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.15" - checksum: 10/5ecf9345a73b80c28677cfbe674b9f567bb0d079e37dcba9055e36cb337db24ae71992a58e1affa9d14a60d3c69907d30fe1f80aea105184501750a58d15c81c + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10/df8bfb2bb18413aa151ecd63b7d5deb0eec102f924f9de6bc08022ced7ed8ca7fed914562d2f6fa5b59b74a5d6e255dc35612b2bc3b8abf361e13f61b3704770 languageName: node linkType: hard -"@babel/helper-module-transforms@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/helper-module-transforms@npm:7.23.0" +"@babel/helper-module-transforms@npm:^7.24.9": + version: 7.24.9 + resolution: "@babel/helper-module-transforms@npm:7.24.9" dependencies: - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-module-imports": "npm:^7.22.15" - "@babel/helper-simple-access": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-module-imports": "npm:^7.24.7" + "@babel/helper-simple-access": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" + "@babel/helper-validator-identifier": "npm:^7.24.7" peerDependencies: "@babel/core": ^7.0.0 - checksum: 10/d72fe444f7b6c5aadaac8f393298d603eedd48e5dead67273a48e5c83a677cbccbd8a12a06c5bf5d97924666083279158a4bd0e799d28b86cbbfacba9e41f598 + checksum: 10/eaed9cb93edb11626758f76bfb482f9c3b6583f6756813c5ef849d6d52bbe7c2cb39f61646758e860732d14c2588b60eb4e2af78d7751450649a8d3d7ca41697 languageName: node linkType: hard @@ -182,64 +185,65 @@ __metadata: languageName: node linkType: hard -"@babel/helper-simple-access@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-simple-access@npm:7.22.5" +"@babel/helper-simple-access@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-simple-access@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/7d5430eecf880937c27d1aed14245003bd1c7383ae07d652b3932f450f60bfcf8f2c1270c593ab063add185108d26198c69d1aca0e6fb7c6fdada4bcf72ab5b7 + "@babel/traverse": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10/5083e190186028e48fc358a192e4b93ab320bd016103caffcfda81302a13300ccce46c9cd255ae520c25d2a6a9b47671f93e5fe5678954a2329dc0a685465c49 languageName: node linkType: hard -"@babel/helper-split-export-declaration@npm:^7.22.6": - version: 7.22.6 - resolution: "@babel/helper-split-export-declaration@npm:7.22.6" +"@babel/helper-split-export-declaration@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-split-export-declaration@npm:7.24.7" dependencies: - "@babel/types": "npm:^7.22.5" - checksum: 10/e141cace583b19d9195f9c2b8e17a3ae913b7ee9b8120246d0f9ca349ca6f03cb2c001fd5ec57488c544347c0bb584afec66c936511e447fd20a360e591ac921 + "@babel/types": "npm:^7.24.7" + checksum: 10/ff04a3071603c87de0d6ee2540b7291ab36305b329bd047cdbb6cbd7db335a12f9a77af1cf708779f75f13c4d9af46093c00b34432e50b2411872c658d1a2e5e languageName: node linkType: hard -"@babel/helper-string-parser@npm:^7.22.5": - version: 7.22.5 - resolution: "@babel/helper-string-parser@npm:7.22.5" - checksum: 10/7f275a7f1a9504da06afc33441e219796352a4a3d0288a961bc14d1e30e06833a71621b33c3e60ee3ac1ff3c502d55e392bcbc0665f6f9d2629809696fab7cdd +"@babel/helper-string-parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-string-parser@npm:7.24.8" + checksum: 10/6d1bf8f27dd725ce02bdc6dffca3c95fb9ab8a06adc2edbd9c1c9d68500274230d1a609025833ed81981eff560045b6b38f7b4c6fb1ab19fc90e5004e3932535 languageName: node linkType: hard -"@babel/helper-validator-identifier@npm:^7.22.20": - version: 7.22.20 - resolution: "@babel/helper-validator-identifier@npm:7.22.20" - checksum: 10/df882d2675101df2d507b95b195ca2f86a3ef28cb711c84f37e79ca23178e13b9f0d8b522774211f51e40168bf5142be4c1c9776a150cddb61a0d5bf3e95750b +"@babel/helper-validator-identifier@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/helper-validator-identifier@npm:7.24.7" + checksum: 10/86875063f57361471b531dbc2ea10bbf5406e12b06d249b03827d361db4cad2388c6f00936bcd9dc86479f7e2c69ea21412c2228d4b3672588b754b70a449d4b languageName: node linkType: hard -"@babel/helper-validator-option@npm:^7.22.15": - version: 7.22.15 - resolution: "@babel/helper-validator-option@npm:7.22.15" - checksum: 10/68da52b1e10002a543161494c4bc0f4d0398c8fdf361d5f7f4272e95c45d5b32d974896d44f6a0ea7378c9204988879d73613ca683e13bd1304e46d25ff67a8d +"@babel/helper-validator-option@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helper-validator-option@npm:7.24.8" + checksum: 10/a52442dfa74be6719c0608fee3225bd0493c4057459f3014681ea1a4643cd38b68ff477fe867c4b356da7330d085f247f0724d300582fa4ab9a02efaf34d107c languageName: node linkType: hard -"@babel/helpers@npm:^7.23.2": - version: 7.23.2 - resolution: "@babel/helpers@npm:7.23.2" +"@babel/helpers@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/helpers@npm:7.24.8" dependencies: - "@babel/template": "npm:^7.22.15" - "@babel/traverse": "npm:^7.23.2" - "@babel/types": "npm:^7.23.0" - checksum: 10/d66d949d41513f19e62e43a9426e283d46bc9a3c72f1e3dd136568542382edd411047403458aaa0ae3adf7c14d23e0e9a1126092bb56e72ba796a6dd7e4c082a + "@babel/template": "npm:^7.24.7" + "@babel/types": "npm:^7.24.8" + checksum: 10/61c08a2baa87382a87c7110e9b5574c782603e247b7e6267769ee0e8b7b54b70ff05f16466f05bb318622b7ac28e79b449edff565abf5adcb1adb1b0f42fee9c languageName: node linkType: hard -"@babel/highlight@npm:^7.22.13": - version: 7.22.20 - resolution: "@babel/highlight@npm:7.22.20" +"@babel/highlight@npm:^7.24.7": + version: 7.24.7 + resolution: "@babel/highlight@npm:7.24.7" dependencies: - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-validator-identifier": "npm:^7.24.7" chalk: "npm:^2.4.2" js-tokens: "npm:^4.0.0" - checksum: 10/1aabc95b2cb7f67adc26c7049554306f1435bfedb76b9731c36ff3d7cdfcb32bd65a6dd06985644124eb2100bd911721d9e5c4f5ac40b7f0da2995a61bf8da92 + picocolors: "npm:^1.0.0" + checksum: 10/69b73f38cdd4f881b09b939a711e76646da34f4834f4ce141d7a49a6bb1926eab1c594148970a8aa9360398dff800f63aade4e81fafdd7c8d8a8489ea93bfec1 languageName: node linkType: hard @@ -252,12 +256,12 @@ __metadata: languageName: node linkType: hard -"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.4, @babel/parser@npm:^7.22.15, @babel/parser@npm:^7.23.0": - version: 7.23.0 - resolution: "@babel/parser@npm:7.23.0" +"@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.14.7, @babel/parser@npm:^7.16.4, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.24.7, @babel/parser@npm:^7.24.8": + version: 7.24.8 + resolution: "@babel/parser@npm:7.24.8" bin: parser: ./bin/babel-parser.js - checksum: 10/201641e068f8cca1ff12b141fcba32d7ccbabc586961bd1b85ae89d9695867f84d57fc2e1176dc4981fd28e5e97ca0e7c32cd688bd5eabb641a302abc0cb5040 + checksum: 10/e44b8327da46e8659bc9fb77f66e2dc4364dd66495fb17d046b96a77bf604f0446f1e9a89cf2f011d78fc3f5cdfbae2e9e0714708e1c985988335683b2e781ef languageName: node linkType: hard @@ -404,43 +408,43 @@ __metadata: languageName: node linkType: hard -"@babel/template@npm:^7.22.15, @babel/template@npm:^7.3.3": - version: 7.22.15 - resolution: "@babel/template@npm:7.22.15" +"@babel/template@npm:^7.24.7, @babel/template@npm:^7.3.3": + version: 7.24.7 + resolution: "@babel/template@npm:7.24.7" dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/parser": "npm:^7.22.15" - "@babel/types": "npm:^7.22.15" - checksum: 10/21e768e4eed4d1da2ce5d30aa51db0f4d6d8700bc1821fec6292587df7bba2fe1a96451230de8c64b989740731888ebf1141138bfffb14cacccf4d05c66ad93f + "@babel/code-frame": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.7" + "@babel/types": "npm:^7.24.7" + checksum: 10/5975d404ef51cf379515eb0f80b115981d0b9dff5539e53a47516644abb8c83d7559f5b083eb1d4977b20d8359ebb2f911ccd4f729143f8958fdc465f976d843 languageName: node linkType: hard -"@babel/traverse@npm:^7.12.5, @babel/traverse@npm:^7.23.2, @babel/traverse@npm:^7.7.2": - version: 7.23.2 - resolution: "@babel/traverse@npm:7.23.2" +"@babel/traverse@npm:^7.12.5, @babel/traverse@npm:^7.24.7, @babel/traverse@npm:^7.24.8, @babel/traverse@npm:^7.7.2": + version: 7.24.8 + resolution: "@babel/traverse@npm:7.24.8" dependencies: - "@babel/code-frame": "npm:^7.22.13" - "@babel/generator": "npm:^7.23.0" - "@babel/helper-environment-visitor": "npm:^7.22.20" - "@babel/helper-function-name": "npm:^7.23.0" - "@babel/helper-hoist-variables": "npm:^7.22.5" - "@babel/helper-split-export-declaration": "npm:^7.22.6" - "@babel/parser": "npm:^7.23.0" - "@babel/types": "npm:^7.23.0" - debug: "npm:^4.1.0" + "@babel/code-frame": "npm:^7.24.7" + "@babel/generator": "npm:^7.24.8" + "@babel/helper-environment-visitor": "npm:^7.24.7" + "@babel/helper-function-name": "npm:^7.24.7" + "@babel/helper-hoist-variables": "npm:^7.24.7" + "@babel/helper-split-export-declaration": "npm:^7.24.7" + "@babel/parser": "npm:^7.24.8" + "@babel/types": "npm:^7.24.8" + debug: "npm:^4.3.1" globals: "npm:^11.1.0" - checksum: 10/e4fcb8f8395804956df4ae1301230a14b6eb35b74a7058a0e0b40f6f4be7281e619e6dafe400e833d4512da5d61cf17ea177d04b00a8f7cf3d8d69aff83ca3d8 + checksum: 10/47d8ecf8cfff58fe621fc4d8454b82c97c407816d8f9c435caa0c849ea7c357b91119a06f3c69f21a0228b5d06ac0b44f49d1f78cff032d6266317707f1fe615 languageName: node linkType: hard -"@babel/types@npm:^7.0.0, @babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0, @babel/types@npm:^7.3.0, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": - version: 7.23.0 - resolution: "@babel/types@npm:7.23.0" +"@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.24.7, @babel/types@npm:^7.24.8, @babel/types@npm:^7.24.9, @babel/types@npm:^7.3.3, @babel/types@npm:^7.8.3": + version: 7.24.9 + resolution: "@babel/types@npm:7.24.9" dependencies: - "@babel/helper-string-parser": "npm:^7.22.5" - "@babel/helper-validator-identifier": "npm:^7.22.20" + "@babel/helper-string-parser": "npm:^7.24.8" + "@babel/helper-validator-identifier": "npm:^7.24.7" to-fast-properties: "npm:^2.0.0" - checksum: 10/ca5b896a26c91c5672254725c4c892a35567d2122afc47bd5331d1611a7f9230c19fc9ef591a5a6f80bf0d80737e104a9ac205c96447c74bee01d4319db58001 + checksum: 10/21873a08a124646824aa230de06af52149ab88206dca59849dcb3003990a6306ec2cdaa4147ec1127c0cfc5f133853cfc18f80d7f6337b6662a3c378ed565f15 languageName: node linkType: hard @@ -1036,14 +1040,14 @@ __metadata: languageName: node linkType: hard -"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" +"@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.5": + version: 0.3.5 + resolution: "@jridgewell/gen-mapping@npm:0.3.5" dependencies: - "@jridgewell/set-array": "npm:^1.0.1" + "@jridgewell/set-array": "npm:^1.2.1" "@jridgewell/sourcemap-codec": "npm:^1.4.10" - "@jridgewell/trace-mapping": "npm:^0.3.9" - checksum: 10/072ace159c39ab85944bdabe017c3de15c5e046a4a4a772045b00ff05e2ebdcfa3840b88ae27e897d473eb4d4845b37be3c78e28910c779f5aeeeae2fb7f0cc2 + "@jridgewell/trace-mapping": "npm:^0.3.24" + checksum: 10/81587b3c4dd8e6c60252122937cea0c637486311f4ed208b52b62aae2e7a87598f63ec330e6cd0984af494bfb16d3f0d60d3b21d7e5b4aedd2602ff3fe9d32e2 languageName: node linkType: hard @@ -1054,10 +1058,10 @@ __metadata: languageName: node linkType: hard -"@jridgewell/set-array@npm:^1.0.1": - version: 1.1.2 - resolution: "@jridgewell/set-array@npm:1.1.2" - checksum: 10/69a84d5980385f396ff60a175f7177af0b8da4ddb81824cb7016a9ef914eee9806c72b6b65942003c63f7983d4f39a5c6c27185bbca88eb4690b62075602e28e +"@jridgewell/set-array@npm:^1.2.1": + version: 1.2.1 + resolution: "@jridgewell/set-array@npm:1.2.1" + checksum: 10/832e513a85a588f8ed4f27d1279420d8547743cc37fcad5a5a76fc74bb895b013dfe614d0eed9cb860048e6546b798f8f2652020b4b2ba0561b05caa8c654b10 languageName: node linkType: hard @@ -1068,13 +1072,13 @@ __metadata: languageName: node linkType: hard -"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.13, @jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.20 - resolution: "@jridgewell/trace-mapping@npm:0.3.20" +"@jridgewell/trace-mapping@npm:^0.3.12, @jridgewell/trace-mapping@npm:^0.3.13, @jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25, @jridgewell/trace-mapping@npm:^0.3.9": + version: 0.3.25 + resolution: "@jridgewell/trace-mapping@npm:0.3.25" dependencies: "@jridgewell/resolve-uri": "npm:^3.1.0" "@jridgewell/sourcemap-codec": "npm:^1.4.14" - checksum: 10/683117e4e6707ef50c725d6d0ec4234687ff751f36fa46c2b3068931eb6a86b49af374d3030200777666579a992b7470d1bd1c591e9bf64d764dda5295f33093 + checksum: 10/dced32160a44b49d531b80a4a2159dceab6b3ddf0c8e95a0deae4b0e894b172defa63d5ac52a19c2068e1fe7d31ea4ba931fbeec103233ecb4208953967120fc languageName: node linkType: hard @@ -1425,9 +1429,9 @@ __metadata: linkType: hard "@sinclair/typebox@npm:^0.24.1": - version: 0.24.28 - resolution: "@sinclair/typebox@npm:0.24.28" - checksum: 10/326152428f752bd3b5518e3998c1d24dea47dc1970b24dd34e89201f5836727633baf1486422b967b0c9477a2e767a53e04132c6c0f14628b9b8353394871cf3 + version: 0.24.51 + resolution: "@sinclair/typebox@npm:0.24.51" + checksum: 10/7886847b9deda1d926934066fe69165a1d9bbe7b0f836543c25efb96173c17009ef7a98619f48b379294bf27958844da3428eb35e65f8d941ea43563ad6e961e languageName: node linkType: hard @@ -1491,15 +1495,15 @@ __metadata: linkType: hard "@types/babel__core@npm:^7.1.14": - version: 7.1.19 - resolution: "@types/babel__core@npm:7.1.19" + version: 7.20.5 + resolution: "@types/babel__core@npm:7.20.5" dependencies: - "@babel/parser": "npm:^7.1.0" - "@babel/types": "npm:^7.0.0" + "@babel/parser": "npm:^7.20.7" + "@babel/types": "npm:^7.20.7" "@types/babel__generator": "npm:*" "@types/babel__template": "npm:*" "@types/babel__traverse": "npm:*" - checksum: 10/cd6850227184f078ffd412696c13393257e5808232cf993e0f19dc081cbeac6c9058eaf9b36797069c3f68857c16e0262a9ab4eb43fb0eb2edb70c563eaa6eed + checksum: 10/c32838d280b5ab59d62557f9e331d3831f8e547ee10b4f85cb78753d97d521270cebfc73ce501e9fb27fe71884d1ba75e18658692c2f4117543f0fc4e3e118b3 languageName: node linkType: hard @@ -1523,11 +1527,11 @@ __metadata: linkType: hard "@types/babel__traverse@npm:*, @types/babel__traverse@npm:^7.0.6": - version: 7.0.14 - resolution: "@types/babel__traverse@npm:7.0.14" + version: 7.20.6 + resolution: "@types/babel__traverse@npm:7.20.6" dependencies: - "@babel/types": "npm:^7.3.0" - checksum: 10/533bce23bbcf3acd19769e5fc43fe0d05bf49cd5d946f87a59994ffad1cdd85fbff3656733792cfe9e0e4ad3dcd2d8ea472af8f7acbc7e39a91946d93501b85f + "@babel/types": "npm:^7.20.7" + checksum: 10/63d13a3789aa1e783b87a8b03d9fb2c2c90078de7782422feff1631b8c2a25db626e63a63ac5a1465d47359201c73069dacb4b52149d17c568187625da3064ae languageName: node linkType: hard @@ -1582,11 +1586,11 @@ __metadata: linkType: hard "@types/graceful-fs@npm:^4.1.3": - version: 4.1.5 - resolution: "@types/graceful-fs@npm:4.1.5" + version: 4.1.9 + resolution: "@types/graceful-fs@npm:4.1.9" dependencies: "@types/node": "npm:*" - checksum: 10/d076bb61f45d0fc42dee496ef8b1c2f8742e15d5e47e90e20d0243386e426c04d4efd408a48875ab432f7960b4ce3414db20ed0fbbfc7bcc89d84e574f6e045a + checksum: 10/79d746a8f053954bba36bd3d94a90c78de995d126289d656fb3271dd9f1229d33f678da04d10bce6be440494a5a73438e2e363e92802d16b8315b051036c5256 languageName: node linkType: hard @@ -1623,12 +1627,12 @@ __metadata: linkType: hard "@types/jest@npm:^28.1.6": - version: 28.1.7 - resolution: "@types/jest@npm:28.1.7" + version: 28.1.8 + resolution: "@types/jest@npm:28.1.8" dependencies: expect: "npm:^28.0.0" pretty-format: "npm:^28.0.0" - checksum: 10/07cda8ee8ad7db8946883091c1516cf6fa8816471172957423543b5d24e59bfc75ff14c50f2b15d34df1e6df5ff8139a98f3d33317e4c18eb9bcc5c9e4ba9157 + checksum: 10/ef2024e72b27b0d5fa647955d35ef2ad19d1a753f21c3877897b18d544cae1f4930082097388d3929a6591ecf3f2c70f346e0ebd54586410fbb487c9a675c80e languageName: node linkType: hard @@ -1707,11 +1711,11 @@ __metadata: linkType: hard "@types/yargs@npm:^17.0.8": - version: 17.0.11 - resolution: "@types/yargs@npm:17.0.11" + version: 17.0.32 + resolution: "@types/yargs@npm:17.0.32" dependencies: "@types/yargs-parser": "npm:*" - checksum: 10/91e52a7f767151ed7dc9cac82ee7e3b51aa6d0d8c9356cdf1e2c35a9483e71e012f0246b04e8222b09181ea3c7e1d24c1c78b6f1b0484fa3cb47b0ab25d14f75 + checksum: 10/1e2b2673847011ce43607df690d392f137d95a2d6ea85aa319403eadda2ef4277365efd4982354d8843f2611ef3846c88599660aaeb537fa9ccddae83c2a89de languageName: node linkType: hard @@ -1938,11 +1942,11 @@ __metadata: linkType: hard "acorn@npm:^8.9.0": - version: 8.10.0 - resolution: "acorn@npm:8.10.0" + version: 8.12.1 + resolution: "acorn@npm:8.12.1" bin: acorn: bin/acorn - checksum: 10/522310c20fdc3c271caed3caf0f06c51d61cb42267279566edd1d58e83dbc12eebdafaab666a0f0be1b7ad04af9c6bc2a6f478690a9e6391c3c8b165ada917dd + checksum: 10/d08c2d122bba32d0861e0aa840b2ee25946c286d5dc5990abca991baf8cdbfbe199b05aacb221b979411a2fea36f83e26b5ac4f6b4e0ce49038c62316c1848f0 languageName: node linkType: hard @@ -2332,17 +2336,17 @@ __metadata: languageName: node linkType: hard -"browserslist@npm:^4.21.9": - version: 4.22.1 - resolution: "browserslist@npm:4.22.1" +"browserslist@npm:^4.23.1": + version: 4.23.2 + resolution: "browserslist@npm:4.23.2" dependencies: - caniuse-lite: "npm:^1.0.30001541" - electron-to-chromium: "npm:^1.4.535" - node-releases: "npm:^2.0.13" - update-browserslist-db: "npm:^1.0.13" + caniuse-lite: "npm:^1.0.30001640" + electron-to-chromium: "npm:^1.4.820" + node-releases: "npm:^2.0.14" + update-browserslist-db: "npm:^1.1.0" bin: browserslist: cli.js - checksum: 10/4a515168e0589c7b1ccbf13a93116ce0418cc5e65d228ec036022cf0e08773fdfb732e2abbf1e1188b96d19ecd4dd707504e75b6d393cba2782fc7d6a7fdefe8 + checksum: 10/326a98b1c39bcc9a99b197f15790dc28e122b1aead3257c837421899377ac96239123f26868698085b3d9be916d72540602738e1f857e86a387e810af3fda6e5 languageName: node linkType: hard @@ -2458,10 +2462,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001541": - version: 1.0.30001550 - resolution: "caniuse-lite@npm:1.0.30001550" - checksum: 10/a5a475bff94109d326760deabb214f9234e908697d12c5d96b4a6fe6f2e960a0d16451df1188fa4d69bff5b5bd6d3de5eb792fd7dfdffb613685223ce9a43567 +"caniuse-lite@npm:^1.0.30001640": + version: 1.0.30001642 + resolution: "caniuse-lite@npm:1.0.30001642" + checksum: 10/8d80ea82be453ae0fdfea8766d82740a4945c1b99189650f29bfc458d4e235d7e99027a8f8bc5a4228d8c4457ba896315284b0703f300353ad5f09d8e693de10 languageName: node linkType: hard @@ -2712,7 +2716,7 @@ __metadata: languageName: node linkType: hard -"convert-source-map@npm:^1.4.0, convert-source-map@npm:^1.6.0": +"convert-source-map@npm:^1.4.0": version: 1.7.0 resolution: "convert-source-map@npm:1.7.0" dependencies: @@ -2752,7 +2756,7 @@ __metadata: languageName: node linkType: hard -"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": +"debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.1.1, debug@npm:^4.2.0, debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.3.3, debug@npm:^4.3.4": version: 4.3.5 resolution: "debug@npm:4.3.5" dependencies: @@ -2941,10 +2945,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.535": - version: 1.4.559 - resolution: "electron-to-chromium@npm:1.4.559" - checksum: 10/240df9bef689b761591235f08b49ad7d4bfcd8c22cccee36ea6aded973f26c66fea7cc5d3063e1b72d2ae296335015191afa22effe09e24b19d4f2b9fa8e8bde +"electron-to-chromium@npm:^1.4.820": + version: 1.4.829 + resolution: "electron-to-chromium@npm:1.4.829" + checksum: 10/43279561337582ff47bb3486439efbc7c1f2192455c76ebc7374754fca61334380025af9e5da7646b4d8c007d9dc6c25d8f6059dffb2207dc39d2f79287a296a languageName: node linkType: hard @@ -3166,10 +3170,10 @@ __metadata: languageName: node linkType: hard -"escalade@npm:^3.1.1": - version: 3.1.1 - resolution: "escalade@npm:3.1.1" - checksum: 10/afa618e73362576b63f6ca83c975456621095a1ed42ff068174e3f5cea48afc422814dda548c96e6ebb5333e7265140c7292abcc81bbd6ccb1757d50d3a4e182 +"escalade@npm:^3.1.1, escalade@npm:^3.1.2": + version: 3.1.2 + resolution: "escalade@npm:3.1.2" + checksum: 10/a1e07fea2f15663c30e40b9193d658397846ffe28ce0a3e4da0d8e485fedfeca228ab846aee101a05015829adf39f9934ff45b2a3fca47bed37a29646bd05cd3 languageName: node linkType: hard @@ -3568,8 +3572,6 @@ __metadata: "@arethetypeswrong/cli": "npm:^0.15.3" "@endo/lockdown": "npm:^1.0.7" "@metamask/auto-changelog": "npm:^3.4.4" - "@ts-bridge/cli": "npm:^0.1.4" - "@ts-bridge/shims": "npm:^0.1.1" "@types/chrome": "npm:^0.0.268" "@types/jest": "npm:^28.1.6" deepmerge: "npm:^4.3.1" @@ -3829,6 +3831,24 @@ __metadata: languageName: node linkType: hard +"germs@workspace:packages/germs": + version: 0.0.0-use.local + resolution: "germs@workspace:packages/germs" + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@metamask/auto-changelog": "npm:^3.4.4" + "@ts-bridge/cli": "npm:^0.1.4" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/jest": "npm:^28.1.6" + deepmerge: "npm:^4.3.1" + jest: "npm:^28.1.3" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~4.9.5" + languageName: unknown + linkType: soft + "get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -3929,16 +3949,16 @@ __metadata: linkType: hard "glob@npm:^7.1.3, glob@npm:^7.1.4": - version: 7.1.6 - resolution: "glob@npm:7.1.6" + version: 7.2.3 + resolution: "glob@npm:7.2.3" dependencies: fs.realpath: "npm:^1.0.0" inflight: "npm:^1.0.4" inherits: "npm:2" - minimatch: "npm:^3.0.4" + minimatch: "npm:^3.1.1" once: "npm:^1.3.0" path-is-absolute: "npm:^1.0.0" - checksum: 10/7d6ec98bc746980d5fe4d764b9c7ada727e3fbd2a7d85cd96dd95fb18638c9c54a70c692fd2ab5d68a186dc8cd9d6a4192d3df220beed891f687db179c430237 + checksum: 10/59452a9202c81d4508a43b8af7082ca5c76452b9fcc4a9ab17655822e6ce9b21d4f8fbadabe4fe3faef448294cec249af305e2cd824b7e9aaf689240e5e96a7b languageName: node linkType: hard @@ -5480,7 +5500,7 @@ __metadata: languageName: node linkType: hard -"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.2": +"minimatch@npm:^3.0.4, minimatch@npm:^3.0.5, minimatch@npm:^3.1.1, minimatch@npm:^3.1.2": version: 3.1.2 resolution: "minimatch@npm:3.1.2" dependencies: @@ -5754,10 +5774,10 @@ __metadata: languageName: node linkType: hard -"node-releases@npm:^2.0.13": - version: 2.0.13 - resolution: "node-releases@npm:2.0.13" - checksum: 10/c9bb813aab2717ff8b3015ecd4c7c5670a5546e9577699a7c84e8d69230cd3b1ce8f863f8e9b50f18b19a5ffa4b9c1a706bbbfe4c378de955fedbab04488a338 +"node-releases@npm:^2.0.14": + version: 2.0.17 + resolution: "node-releases@npm:2.0.17" + checksum: 10/199e4128db3c415368abf344c0bff527c1300c67094b2d5592a67f9388b434cdad8bf76829dace65c9318fbb27cda8ecb91c5758057bbdf0b59e9408ab92408b languageName: node linkType: hard @@ -6249,9 +6269,9 @@ __metadata: linkType: hard "punycode@npm:^2.1.0": - version: 2.1.1 - resolution: "punycode@npm:2.1.1" - checksum: 10/939daa010c2cacebdb060c40ecb52fef0a739324a66f7fffe0f94353a1ee83e3b455e9032054c4a0c4977b0a28e27086f2171c392832b59a01bd948fd8e20914 + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: 10/febdc4362bead22f9e2608ff0171713230b57aff9dddc1c273aa2a651fbd366f94b7d6a71d78342a7c0819906750351ca7f2edd26ea41b626d87d6a13d1bd059 languageName: node linkType: hard @@ -6273,9 +6293,9 @@ __metadata: linkType: hard "react-is@npm:^18.0.0": - version: 18.2.0 - resolution: "react-is@npm:18.2.0" - checksum: 10/200cd65bf2e0be7ba6055f647091b725a45dd2a6abef03bf2380ce701fd5edccee40b49b9d15edab7ac08a762bf83cb4081e31ec2673a5bfb549a36ba21570df + version: 18.3.1 + resolution: "react-is@npm:18.3.1" + checksum: 10/d5f60c87d285af24b1e1e7eaeb123ec256c3c8bdea7061ab3932e3e14685708221bf234ec50b21e10dd07f008f1b966a2730a0ce4ff67905b3872ff2042aec22 languageName: node linkType: hard @@ -7427,17 +7447,17 @@ __metadata: languageName: node linkType: hard -"update-browserslist-db@npm:^1.0.13": - version: 1.0.13 - resolution: "update-browserslist-db@npm:1.0.13" +"update-browserslist-db@npm:^1.1.0": + version: 1.1.0 + resolution: "update-browserslist-db@npm:1.1.0" dependencies: - escalade: "npm:^3.1.1" - picocolors: "npm:^1.0.0" + escalade: "npm:^3.1.2" + picocolors: "npm:^1.0.1" peerDependencies: browserslist: ">= 4.21.0" bin: update-browserslist-db: cli.js - checksum: 10/9074b4ef34d2ed931f27d390aafdd391ee7c45ad83c508e8fed6aaae1eb68f81999a768ed8525c6f88d4001a4fbf1b8c0268f099d0e8e72088ec5945ac796acf + checksum: 10/d70b9efeaf4601aadb1a4f6456a7a5d9118e0063d995866b8e0c5e0cf559482671dab6ce7b079f9536b06758a344fbd83f974b965211e1c6e8d1958540b0c24c languageName: node linkType: hard @@ -7458,13 +7478,13 @@ __metadata: linkType: hard "v8-to-istanbul@npm:^9.0.1": - version: 9.0.1 - resolution: "v8-to-istanbul@npm:9.0.1" + version: 9.3.0 + resolution: "v8-to-istanbul@npm:9.3.0" dependencies: "@jridgewell/trace-mapping": "npm:^0.3.12" "@types/istanbul-lib-coverage": "npm:^2.0.1" - convert-source-map: "npm:^1.6.0" - checksum: 10/0bbaffbb344af7172884a6f9868fa55df96230caf7100fa250b63d95ad0e24848141b35731d16607ae0d0023baa064b75c8e4197f6071f3bd3b09540c98490a1 + convert-source-map: "npm:^2.0.0" + checksum: 10/fb1d70f1176cb9dc46cabbb3fd5c52c8f3e8738b61877b6e7266029aed0870b04140e3f9f4550ac32aebcfe1d0f38b0bac57e1e8fb97d68fec82f2b416148166 languageName: node linkType: hard @@ -7699,9 +7719,9 @@ __metadata: linkType: hard "yargs-parser@npm:^20.2.2": - version: 20.2.7 - resolution: "yargs-parser@npm:20.2.7" - checksum: 10/402e468ca9875543e9c679c5cf3b4c77b24735b0b3c32d1e6c8d9088742be55a589e04ddda7e93613c3378fce33a0134c63d6145ac3c474c58f4dcfe5c45a193 + version: 20.2.9 + resolution: "yargs-parser@npm:20.2.9" + checksum: 10/0188f430a0f496551d09df6719a9132a3469e47fe2747208b1dd0ab2bb0c512a95d0b081628bbca5400fb20dbf2fabe63d22badb346cecadffdd948b049f3fcc languageName: node linkType: hard From 566955ac167d7500222dc1e8ab50e6ba9bd0196e Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 14:32:09 +0200 Subject: [PATCH 14/31] refactor: Move apply-lockdown.js to germs/shims, fix various issues --- .eslintrc.js | 1 - constraints.pro | 1 + package.json | 4 ++-- packages/extension/.eslintrc.js | 8 ------- packages/extension/src/background.ts | 2 +- packages/extension/src/offscreen.ts | 2 +- packages/extension/tsconfig.build.json | 3 ++- packages/extension/tsconfig.json | 2 +- packages/extension/vite.config.mts | 4 ++-- packages/germs/.eslintrc.js | 16 +++++++++++++ packages/germs/package.json | 12 +++++++++- .../src/shims}/apply-lockdown.mjs | 4 ++-- packages/germs/tsconfig.build.json | 3 ++- yarn.lock | 24 +++++++++++++++---- 14 files changed, 60 insertions(+), 26 deletions(-) create mode 100644 packages/germs/.eslintrc.js rename packages/{extension/src => germs/src/shims}/apply-lockdown.mjs (76%) diff --git a/.eslintrc.js b/.eslintrc.js index b4ed6f764..530ca2930 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -56,7 +56,6 @@ module.exports = { project: ['./tsconfig.packages.json'], }, rules: { - // Enable rules that are disabled in `@metamask/eslint-config-typescript` '@typescript-eslint/no-explicit-any': 'error', }, }, diff --git a/constraints.pro b/constraints.pro index 0cde5de54..cb3cec12e 100644 --- a/constraints.pro +++ b/constraints.pro @@ -262,6 +262,7 @@ gen_enforced_field(WorkspaceCwd, 'files', []) :- % All packages except the root and extension must have the same "build" script. gen_enforced_field(WorkspaceCwd, 'scripts.build', 'ts-bridge --project tsconfig.build.json --clean') :- WorkspaceCwd \= 'packages/extension', + WorkspaceCwd \= 'packages/germs', WorkspaceCwd \= '.'. % All packages except the root and extension must have the same "build:docs" script. diff --git a/package.json b/package.json index ab7afdfeb..e1173bf1b 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ "lint": "yarn lint:eslint && yarn lint:misc --check && yarn constraints && yarn lint:dependencies", "lint:dependencies": "depcheck && yarn dedupe --check", "lint:dependencies:fix": "depcheck && yarn dedupe", - "lint:eslint": "eslint . --cache --ext js,cjs,ts,mts,cts", + "lint:eslint": "eslint . --cache --ext js,mjs,cjs,ts,mts,cts", "lint:fix": "yarn lint:eslint --fix && yarn lint:misc --write && yarn constraints --fix && yarn lint:dependencies:fix", "lint:misc": "prettier '**/*.json' '**/*.md' '!**/CHANGELOG.old.md' '**/*.yml' '!.yarnrc.yml' '!merged-packages/**' --ignore-path .gitignore", "prepack": "./scripts/prepack.sh", @@ -60,7 +60,7 @@ "jest-silent-reporter": "^0.6.0", "prettier": "^2.7.1", "prettier-plugin-packagejson": "^2.3.0", - "rimraf": "^6.0.0", + "rimraf": "^6.0.1", "ts-jest": "^28.0.7", "typedoc": "^0.24.8", "typescript": "~4.9.5" diff --git a/packages/extension/.eslintrc.js b/packages/extension/.eslintrc.js index 6446e3e70..a5d78dc80 100644 --- a/packages/extension/.eslintrc.js +++ b/packages/extension/.eslintrc.js @@ -7,14 +7,6 @@ module.exports = { globals: { chrome: 'readonly', clients: 'readonly' }, }, - { - files: ['apply-lockdown.mjs'], - globals: { lockdown: 'readonly' }, - rules: { - 'import/unambiguous': 'off', - }, - }, - { files: ['vite.config.mts'], parserOptions: { diff --git a/packages/extension/src/background.ts b/packages/extension/src/background.ts index feba004ad..b3040727b 100644 --- a/packages/extension/src/background.ts +++ b/packages/extension/src/background.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line import/no-unassigned-import +// eslint-disable-next-line import/extensions,import/no-unassigned-import import './apply-lockdown.mjs'; import type { ExtensionMessage } from './shared'; diff --git a/packages/extension/src/offscreen.ts b/packages/extension/src/offscreen.ts index c95905eac..3c5019697 100644 --- a/packages/extension/src/offscreen.ts +++ b/packages/extension/src/offscreen.ts @@ -1,4 +1,4 @@ -// eslint-disable-next-line import/no-unassigned-import +// eslint-disable-next-line import/extensions,import/no-unassigned-import import './apply-lockdown.mjs'; import type { ExtensionMessage } from './shared'; diff --git a/packages/extension/tsconfig.build.json b/packages/extension/tsconfig.build.json index fc8520e73..428b08ab0 100644 --- a/packages/extension/tsconfig.build.json +++ b/packages/extension/tsconfig.build.json @@ -1,3 +1,4 @@ { - "extends": "./tsconfig.json" + "extends": "./tsconfig.json", + "references": [{ "path": "../germs/tsconfig.build.json" }] } diff --git a/packages/extension/tsconfig.json b/packages/extension/tsconfig.json index 400bdc740..943a90c6c 100644 --- a/packages/extension/tsconfig.json +++ b/packages/extension/tsconfig.json @@ -8,5 +8,5 @@ "skipLibCheck": true, "types": ["chrome"] }, - "include": ["./src/**/*.ts", "./src/apply-lockdown.mjs"] + "include": ["./src/**/*.ts"] } diff --git a/packages/extension/vite.config.mts b/packages/extension/vite.config.mts index 1eefa37dc..82a0114e2 100644 --- a/packages/extension/vite.config.mts +++ b/packages/extension/vite.config.mts @@ -10,7 +10,7 @@ export default defineConfig({ build: { emptyOutDir: true, - outDir: path.resolve(projectRoot, './dist'), + outDir: path.resolve(projectRoot, '../dist'), rollupOptions: { // Ignore the following module specifiers if imported external: [ @@ -33,7 +33,7 @@ export default defineConfig({ viteStaticCopy({ targets: [ { src: 'manifest.json', dest: './' }, - { src: 'apply-lockdown.mjs', dest: './' }, + { src: '../../germs/src/shims/apply-lockdown.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/ses.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, ], diff --git a/packages/germs/.eslintrc.js b/packages/germs/.eslintrc.js new file mode 100644 index 000000000..5c61fee0b --- /dev/null +++ b/packages/germs/.eslintrc.js @@ -0,0 +1,16 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + + overrides: [ + { + files: ['apply-lockdown.mjs'], + globals: { lockdown: 'readonly' }, + rules: { + 'import/extensions': 'off', + 'import/no-unassigned-import': 'off', + 'import/no-unresolved': 'off', + 'import/unambiguous': 'off', + }, + }, + ], +}; diff --git a/packages/germs/package.json b/packages/germs/package.json index 55530ad9f..0614ac599 100644 --- a/packages/germs/package.json +++ b/packages/germs/package.json @@ -19,6 +19,7 @@ "default": "./dist/index.cjs" } }, + "./shims": "./dist/shims", "./package.json": "./package.json" }, "main": "./dist/index.cjs", @@ -28,15 +29,22 @@ "dist" ], "scripts": { - "build": "ts-bridge --project tsconfig.build.json --clean", + "build": "yarn clean && yarn build:typescript && yarn build:javascript", "build:docs": "typedoc", + "build:javascript": "yarn mkdirp dist && cp -r src/shims dist/", + "build:typescript": "ts-bridge --project tsconfig.build.json --clean", "changelog:validate": "../../scripts/validate-changelog.sh germs", + "clean": "rimraf ./dist", "publish:preview": "yarn npm publish --tag preview", "test": "jest --reporters=jest-silent-reporter", "test:clean": "jest --clearCache", "test:verbose": "jest --verbose", "test:watch": "jest --watch" }, + "dependencies": { + "@endo/lockdown": "^1.0.7", + "ses": "^1.5.0" + }, "devDependencies": { "@arethetypeswrong/cli": "^0.15.3", "@metamask/auto-changelog": "^3.4.4", @@ -45,6 +53,8 @@ "@types/jest": "^28.1.6", "deepmerge": "^4.3.1", "jest": "^28.1.3", + "mkdirp": "^3.0.1", + "rimraf": "^6.0.1", "ts-jest": "^28.0.7", "typedoc": "^0.24.8", "typedoc-plugin-missing-exports": "^2.0.0", diff --git a/packages/extension/src/apply-lockdown.mjs b/packages/germs/src/shims/apply-lockdown.mjs similarity index 76% rename from packages/extension/src/apply-lockdown.mjs rename to packages/germs/src/shims/apply-lockdown.mjs index 1a3fd7cd7..ef718651e 100644 --- a/packages/extension/src/apply-lockdown.mjs +++ b/packages/germs/src/shims/apply-lockdown.mjs @@ -1,5 +1,5 @@ -import './ses.mjs.js'; -import './lockdown.mjs.js'; +import './ses.mjs'; +import './lockdown.mjs'; lockdown({ consoleTaming: 'unsafe', diff --git a/packages/germs/tsconfig.build.json b/packages/germs/tsconfig.build.json index c622f4091..1a4b71624 100644 --- a/packages/germs/tsconfig.build.json +++ b/packages/germs/tsconfig.build.json @@ -6,5 +6,6 @@ "rootDir": "./src" }, "references": [], - "include": ["./src"] + "include": ["./src"], + "exclude": ["./src/shims"] } diff --git a/yarn.lock b/yarn.lock index e8a7e7915..9cc58f6b6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3836,12 +3836,16 @@ __metadata: resolution: "germs@workspace:packages/germs" dependencies: "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/lockdown": "npm:^1.0.7" "@metamask/auto-changelog": "npm:^3.4.4" "@ts-bridge/cli": "npm:^0.1.4" "@ts-bridge/shims": "npm:^0.1.1" "@types/jest": "npm:^28.1.6" deepmerge: "npm:^4.3.1" jest: "npm:^28.1.3" + mkdirp: "npm:^3.0.1" + rimraf: "npm:^6.0.1" + ses: "npm:^1.5.0" ts-jest: "npm:^28.0.7" typedoc: "npm:^0.24.8" typedoc-plugin-missing-exports: "npm:^2.0.0" @@ -5644,6 +5648,15 @@ __metadata: languageName: node linkType: hard +"mkdirp@npm:^3.0.1": + version: 3.0.1 + resolution: "mkdirp@npm:3.0.1" + bin: + mkdirp: dist/cjs/src/bin.js + checksum: 10/16fd79c28645759505914561e249b9a1f5fe3362279ad95487a4501e4467abeb714fd35b95307326b8fd03f3c7719065ef11a6f97b7285d7888306d1bd2232ba + languageName: node + linkType: hard + "ms@npm:2.0.0": version: 2.0.0 resolution: "ms@npm:2.0.0" @@ -5952,7 +5965,7 @@ __metadata: jest-silent-reporter: "npm:^0.6.0" prettier: "npm:^2.7.1" prettier-plugin-packagejson: "npm:^2.3.0" - rimraf: "npm:^6.0.0" + rimraf: "npm:^6.0.1" ts-jest: "npm:^28.0.7" typedoc: "npm:^0.24.8" typescript: "npm:~4.9.5" @@ -6455,14 +6468,15 @@ __metadata: languageName: node linkType: hard -"rimraf@npm:^6.0.0": - version: 6.0.0 - resolution: "rimraf@npm:6.0.0" +"rimraf@npm:^6.0.1": + version: 6.0.1 + resolution: "rimraf@npm:6.0.1" dependencies: glob: "npm:^11.0.0" + package-json-from-dist: "npm:^1.0.0" bin: rimraf: dist/esm/bin.mjs - checksum: 10/8a2e161f89b4fb8d7f3cab9bdea5360e9ab2ddc13d8120508b56eb93ba0c6f4506b799598900db6558628194b09f89705d1b98a591d7f727508e427e247befea + checksum: 10/0eb7edf08aa39017496c99ba675552dda11a20811ba78f8232da2ba945308c91e9cd673f95998b1a8202bc7436d33390831d23ea38ae52751038d56373ad99e2 languageName: node linkType: hard From ceb64aa968677a2d5cc9a5d91b6e059811451159 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Thu, 18 Jul 2024 14:34:01 +0200 Subject: [PATCH 15/31] docs: Add readme to germs/src/shims --- packages/germs/package.json | 2 +- packages/germs/src/shims/README.md | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100644 packages/germs/src/shims/README.md diff --git a/packages/germs/package.json b/packages/germs/package.json index 0614ac599..ad7c6115b 100644 --- a/packages/germs/package.json +++ b/packages/germs/package.json @@ -31,7 +31,7 @@ "scripts": { "build": "yarn clean && yarn build:typescript && yarn build:javascript", "build:docs": "typedoc", - "build:javascript": "yarn mkdirp dist && cp -r src/shims dist/", + "build:javascript": "yarn mkdirp dist/shims && cp src/shims/*js dist/shims", "build:typescript": "ts-bridge --project tsconfig.build.json --clean", "changelog:validate": "../../scripts/validate-changelog.sh germs", "clean": "rimraf ./dist", diff --git a/packages/germs/src/shims/README.md b/packages/germs/src/shims/README.md new file mode 100644 index 000000000..9cf6a8124 --- /dev/null +++ b/packages/germs/src/shims/README.md @@ -0,0 +1,3 @@ +# Shims + +For storing plain JavaScript shims, such as `lockdown` and eventually others. From 69beffea9b1da78eaaf4f9d18024bd41ce531510 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Fri, 19 Jul 2024 16:32:01 +0200 Subject: [PATCH 16/31] feat: Add eventual-send shim to germs package - The names of all private, unpublished packages are now prefixed with `@ocap` to make them more distinguishable in monorepo scripts. - Adds eventual-send shim to `@ocap/germs` - This was created using Agoric's `bundle-source` in the `endo` repo. - When they have published the latest version of `bundle-source`, we can simply run it on builds ourselves. --- .eslintrc.js | 11 + README.md | 13 +- package.json | 6 +- packages/extension/README.md | 10 +- packages/extension/package.json | 5 +- packages/germs/.eslintrc.js | 29 +- packages/germs/README.md | 2 +- packages/germs/package.json | 9 +- packages/germs/scripts/bundle-shims.mjs | 37 + packages/germs/src/shims/README.md | 2 +- packages/germs/src/shims/eventual-send.mjs | 1461 ++++++++++++++++++++ yarn.lock | 177 +-- 12 files changed, 1654 insertions(+), 108 deletions(-) create mode 100644 packages/germs/scripts/bundle-shims.mjs create mode 100644 packages/germs/src/shims/eventual-send.mjs diff --git a/.eslintrc.js b/.eslintrc.js index 530ca2930..65325c886 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -48,6 +48,17 @@ module.exports = { }, }, + { + files: ['**/scripts/*.mjs'], + parserOptions: { + ecmaVersion: '2022', + }, + rules: { + 'import/extensions': 'off', + 'import/no-unassigned-import': 'off', + }, + }, + { files: ['*.ts', '*.cts', '*.mts'], extends: ['@metamask/eslint-config-typescript'], diff --git a/README.md b/README.md index b22da4f87..b0cd4b689 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ # Ocap Kernel Monorepo -Welcome to the Ocap Kernel team's monorepo. It is a work in progress. +Welcome to the Ocap Kernel team's monorepo! It is a work in progress. + +## Contributing + +To get started: + +- `yarn install` +- `yarn build` + - This will build the entire monorepo in the correct order. + You may need to re-run it when other packages change. + +Linting is done via `yarn lint` or `yarn lint:fix` from the root. diff --git a/package.json b/package.json index e1173bf1b..05558fe58 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "ocap-kernel-monorepo", + "name": "@ocap/monorepo", "version": "0.0.0", "private": true, "repository": { @@ -13,8 +13,8 @@ "scripts": { "build": "yarn run build:source && yarn build:types", "build:clean": "yarn clean && yarn build", - "build:docs": "yarn workspaces foreach --all --exclude ocap-kernel-monorepo --exclude extension --parallel --interlaced --verbose run build:docs", - "build:source": "yarn workspaces foreach --all --parallel --exclude ocap-kernel-monorepo --interlaced --verbose run build", + "build:docs": "yarn workspaces foreach --all --exclude @ocap/monorepo --exclude @ocap/extension --parallel --interlaced --verbose run build:docs", + "build:source": "yarn workspaces foreach --all --topological --parallel --interlaced --exclude @ocap/monorepo --verbose run build", "build:types": "tsc --build tsconfig.build.json --verbose", "build:watch": "yarn run build --watch", "changelog:update": "yarn workspaces foreach --all --no-private --parallel --interlaced --verbose run changelog:update", diff --git a/packages/extension/README.md b/packages/extension/README.md index 0bca64f81..7546fe1be 100644 --- a/packages/extension/README.md +++ b/packages/extension/README.md @@ -1,7 +1,15 @@ -# `extension` +# `@ocap/extension` For running Ocap Kernel experiments in an extension environment. +## Getting started + +`yarn build` creates a production build of the extension, while `yarn start` runs a dev server with hot reloading. + +To use the extension, load the `dist` directory as an unpacked extension in your +browser of choice. You may have to manually reload the extension, even with the dev +server running. + ## Contributing This package is part of a monorepo. Instructions for contributing can be found in the [monorepo README](https://github.com/MetaMask/ocap-kernel#readme). diff --git a/packages/extension/package.json b/packages/extension/package.json index 2d6a8abbb..5a03b1716 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -1,5 +1,5 @@ { - "name": "extension", + "name": "@ocap/extension", "version": "0.0.0", "private": true, "description": "For running Ocap Kernel experiments in an extension environment", @@ -14,7 +14,7 @@ "build": "yarn build:types && yarn build:vite", "build:types": "tsc", "build:vite": "vite build -c vite.config.mts", - "changelog:validate": "../../scripts/validate-changelog.sh extension", + "changelog:validate": "../../scripts/validate-changelog.sh @ocap/extension", "publish:preview": "yarn npm publish --tag preview", "start": "vite -c vite.config.mts", "test": "jest --reporters=jest-silent-reporter", @@ -25,6 +25,7 @@ }, "dependencies": { "@endo/lockdown": "^1.0.7", + "@ocap/germs": "^0.0.0", "ses": "^1.5.0" }, "devDependencies": { diff --git a/packages/germs/.eslintrc.js b/packages/germs/.eslintrc.js index 5c61fee0b..dab61e7e3 100644 --- a/packages/germs/.eslintrc.js +++ b/packages/germs/.eslintrc.js @@ -1,16 +1,21 @@ module.exports = { extends: ['../../.eslintrc.js'], - overrides: [ - { - files: ['apply-lockdown.mjs'], - globals: { lockdown: 'readonly' }, - rules: { - 'import/extensions': 'off', - 'import/no-unassigned-import': 'off', - 'import/no-unresolved': 'off', - 'import/unambiguous': 'off', - }, - }, - ], + ignorePatterns: ['**/shims/*.mjs'], + + // overrides: [ + // { + // files: ['src/**/*.js'], + // globals: { chrome: 'readonly', clients: 'readonly' }, + // }, + + // { + // files: ['vite.config.mts'], + // parserOptions: { + // sourceType: 'module', + // tsconfigRootDir: __dirname, + // project: ['./tsconfig.scripts.json'], + // }, + // }, + // ], }; diff --git a/packages/germs/README.md b/packages/germs/README.md index ead6ceb8c..974894c2d 100644 --- a/packages/germs/README.md +++ b/packages/germs/README.md @@ -1,4 +1,4 @@ -# `germs` +# `@ocap/germs` From these germs, a Kernel will form. diff --git a/packages/germs/package.json b/packages/germs/package.json index ad7c6115b..a2dea1e7d 100644 --- a/packages/germs/package.json +++ b/packages/germs/package.json @@ -1,5 +1,5 @@ { - "name": "germs", + "name": "@ocap/germs", "version": "0.0.0", "private": true, "description": "From these germs, a Kernel will form", @@ -29,11 +29,11 @@ "dist" ], "scripts": { - "build": "yarn clean && yarn build:typescript && yarn build:javascript", + "build": "yarn clean && yarn build:typescript && yarn build:shims", "build:docs": "typedoc", - "build:javascript": "yarn mkdirp dist/shims && cp src/shims/*js dist/shims", + "build:shims": "node scripts/bundle-shims.mjs", "build:typescript": "ts-bridge --project tsconfig.build.json --clean", - "changelog:validate": "../../scripts/validate-changelog.sh germs", + "changelog:validate": "../../scripts/validate-changelog.sh @ocap/germs", "clean": "rimraf ./dist", "publish:preview": "yarn npm publish --tag preview", "test": "jest --reporters=jest-silent-reporter", @@ -42,6 +42,7 @@ "test:watch": "jest --watch" }, "dependencies": { + "@endo/eventual-send": "^1.2.2", "@endo/lockdown": "^1.0.7", "ses": "^1.5.0" }, diff --git a/packages/germs/scripts/bundle-shims.mjs b/packages/germs/scripts/bundle-shims.mjs new file mode 100644 index 000000000..677d81dc0 --- /dev/null +++ b/packages/germs/scripts/bundle-shims.mjs @@ -0,0 +1,37 @@ +import 'ses'; +import '@endo/lockdown/commit.js'; + +import { copyFile } from 'fs/promises'; +import { mkdirp } from 'mkdirp'; +import path from 'path'; +// import bundleSource from '@endo/bundle-source'; +import { rimraf } from 'rimraf'; + +console.log('Bundling shims...') + +const rootDir = path.resolve(import.meta.dirname, '..'); +const shimsSrc = path.resolve(rootDir, 'src/shims'); +const shimsDist = path.resolve(rootDir, 'dist/shims'); + +// const eventualSendSrc = path.resolve(rootDir, '../../node_modules/@endo/eventual-send/shim.js'); + +const fileNames = { + lockdown: 'apply-lockdown.mjs', + eventualSend: 'eventual-send.mjs', +}; + +await mkdirp(shimsDist); +await rimraf(`${shimsDist}/*`); + +await copyFile( + path.resolve(shimsSrc, fileNames.lockdown), + path.resolve(shimsDist, fileNames.lockdown), +); +await copyFile( + path.resolve(shimsSrc, fileNames.eventualSend), + path.resolve(shimsDist, fileNames.eventualSend), +); + +// const { source } = await bundleSource(eventualSendSrc, { format: 'endoScript' }); + +console.log('Success!') diff --git a/packages/germs/src/shims/README.md b/packages/germs/src/shims/README.md index 9cf6a8124..afe45d575 100644 --- a/packages/germs/src/shims/README.md +++ b/packages/germs/src/shims/README.md @@ -1,3 +1,3 @@ # Shims -For storing plain JavaScript shims, such as `lockdown` and eventually others. +For storing plain JavaScript shims that we want to import statically, such as `lockdown` and `eventual-send`. diff --git a/packages/germs/src/shims/eventual-send.mjs b/packages/germs/src/shims/eventual-send.mjs new file mode 100644 index 000000000..1d6699605 --- /dev/null +++ b/packages/germs/src/shims/eventual-send.mjs @@ -0,0 +1,1461 @@ +'use strict'; +(functors => { + + const cell = (name, value = undefined) => { + const observers = []; + return Object.freeze({ + get: Object.freeze(() => { + return value; + }), + set: Object.freeze((newValue) => { + value = newValue; + for (const observe of observers) { + observe(value); + } + }), + observe: Object.freeze((observe) => { + observers.push(observe); + observe(value); + }), + enumerable: true, + }); + }; + + const cells = [ + { + makeEnvironmentCaptor: cell("makeEnvironmentCaptor"), + getEnvironmentOption: cell("getEnvironmentOption"), + getEnvironmentOptionsList: cell("getEnvironmentOptionsList"), + environmentOptionsListHas: cell("environmentOptionsListHas"), + }, + { + }, + { + trackTurns: cell("trackTurns"), + }, + { + makeMessageBreakpointTester: cell("makeMessageBreakpointTester"), + }, + { + getMethodNames: cell("getMethodNames"), + localApplyFunction: cell("localApplyFunction"), + localApplyMethod: cell("localApplyMethod"), + localGet: cell("localGet"), + }, + { + makePostponedHandler: cell("makePostponedHandler"), + }, + { + makeHandledPromise: cell("makeHandledPromise"), + }, + { + }, + ]; + + Object.defineProperties(cells[1], Object.getOwnPropertyDescriptors(cells[0])); + + const namespaces = cells.map(cells => Object.freeze(Object.create(null, { + ...cells, + // Make this appear like an ESM module namespace object. + [Symbol.toStringTag]: { + value: 'Module', + writable: false, + enumerable: false, + configurable: false, + }, + }))); + + for (let index = 0; index < namespaces.length; index += 1) { + cells[index]['*'] = cell('*', namespaces[index]); + } + +function observeImports(map, importName, importIndex) { + for (const [name, observers] of map.get(importName)) { + const cell = cells[importIndex][name]; + if (cell === undefined) { + throw new ReferenceError(`Cannot import name ${name}`); + } + for (const observer of observers) { + cell.observe(observer); + } + } +} + + + functors[0]({ + imports(entries) { + const map = new Map(entries); + }, + liveVar: { + }, + onceVar: { + makeEnvironmentCaptor: cells[0].makeEnvironmentCaptor.set, + getEnvironmentOption: cells[0].getEnvironmentOption.set, + getEnvironmentOptionsList: cells[0].getEnvironmentOptionsList.set, + environmentOptionsListHas: cells[0].environmentOptionsListHas.set, + }, + importMeta: {}, + }); + functors[1]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "./src/env-options.js", 0); + }, + liveVar: { + }, + onceVar: { + }, + importMeta: {}, + }); + functors[2]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "@endo/env-options", 1); + }, + liveVar: { + }, + onceVar: { + trackTurns: cells[2].trackTurns.set, + }, + importMeta: {}, + }); + functors[3]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "@endo/env-options", 1); + }, + liveVar: { + }, + onceVar: { + makeMessageBreakpointTester: cells[3].makeMessageBreakpointTester.set, + }, + importMeta: {}, + }); + functors[4]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "./message-breakpoints.js", 3); + }, + liveVar: { + }, + onceVar: { + getMethodNames: cells[4].getMethodNames.set, + localApplyFunction: cells[4].localApplyFunction.set, + localApplyMethod: cells[4].localApplyMethod.set, + localGet: cells[4].localGet.set, + }, + importMeta: {}, + }); + functors[5]({ + imports(entries) { + const map = new Map(entries); + }, + liveVar: { + }, + onceVar: { + makePostponedHandler: cells[5].makePostponedHandler.set, + }, + importMeta: {}, + }); + functors[6]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "./track-turns.js", 2); + observeImports(map, "./local.js", 4); + observeImports(map, "./postponed.js", 5); + }, + liveVar: { + }, + onceVar: { + makeHandledPromise: cells[6].makeHandledPromise.set, + }, + importMeta: {}, + }); + functors[7]({ + imports(entries) { + const map = new Map(entries); + observeImports(map, "./src/handled-promise.js", 6); + }, + liveVar: { + }, + onceVar: { + }, + importMeta: {}, + }); + + return cells[cells.length - 1]['*'].get(); +})([// === functors[0] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; $h‍_imports([]); /* global globalThis */ +/* @ts-check*/ + +/* `@endo/env-options` needs to be imported quite early, and so should*/ +/* avoid importing from ses or anything that depends on ses.*/ + +/* /////////////////////////////////////////////////////////////////////////////*/ +/* Prelude of cheap good - enough imitations of things we'd use or*/ +/* do differently if we could depend on ses*/ + +const{freeze}=Object; +const{apply}=Reflect; + +/* Should be equivalent to the one in ses' commons.js even though it*/ +/* uses the other technique.*/ +const uncurryThis= +(fn)=> +(receiver,...args)=> +apply(fn,receiver,args); +const arrayPush=uncurryThis(Array.prototype.push); +const arrayIncludes=uncurryThis(Array.prototype.includes); +const stringSplit=uncurryThis(String.prototype.split); + +const q=JSON.stringify; + +const Fail=(literals,...args)=>{ +let msg=literals[0]; +for(let i=0;i{ +const capturedEnvironmentOptionNames=[]; + +/** + * Gets an environment option by name and returns the option value or the + * given default. + * + * @param {string} optionName + * @param {string} defaultSetting + * @param {string[]} [optOtherValues] + * If provided, the option value must be included or match `defaultSetting`. + * @returns {string} + */ +const getEnvironmentOption=( +optionName, +defaultSetting, +optOtherValues=undefined)=> +{ +typeof optionName==='string'|| +Fail `Environment option name ${q(optionName)} must be a string.`; +typeof defaultSetting==='string'|| +Fail `Environment option default setting ${q( +defaultSetting) + } must be a string.`; + +/** @type {string} */ +let setting=defaultSetting; +const globalProcess=aGlobal.process||undefined; +const globalEnv= +typeof globalProcess==='object'&&globalProcess.env||undefined; +if(typeof globalEnv==='object'){ +if(optionName in globalEnv){ +if(!dropNames){ +arrayPush(capturedEnvironmentOptionNames,optionName); + } +const optionValue=globalEnv[optionName]; +/* eslint-disable-next-line @endo/no-polymorphic-call*/ +typeof optionValue==='string'|| +Fail `Environment option named ${q( +optionName) + }, if present, must have a corresponding string value, got ${q( +optionValue) + }`; +setting=optionValue; + } + } +optOtherValues===undefined|| +setting===defaultSetting|| +arrayIncludes(optOtherValues,setting)|| +Fail `Unrecognized ${q(optionName)} value ${q( +setting) + }. Expected one of ${q([defaultSetting,...optOtherValues])}`; +return setting; + }; +freeze(getEnvironmentOption); + +/** + * @param {string} optionName + * @returns {string[]} + */ +const getEnvironmentOptionsList=(optionName)=>{ +const option=getEnvironmentOption(optionName,''); +return freeze(option===''?[]:stringSplit(option,',')); + }; +freeze(getEnvironmentOptionsList); + +const environmentOptionsListHas=(optionName,element)=> +arrayIncludes(getEnvironmentOptionsList(optionName),element); + +const getCapturedEnvironmentOptionNames=()=>{ +return freeze([...capturedEnvironmentOptionNames]); + }; +freeze(getCapturedEnvironmentOptionNames); + +return freeze({ +getEnvironmentOption, +getEnvironmentOptionsList, +environmentOptionsListHas, +getCapturedEnvironmentOptionNames}); + + };$h‍_once.makeEnvironmentCaptor(makeEnvironmentCaptor); +freeze(makeEnvironmentCaptor); + +/** + * For the simple case, where the global in question is `globalThis` and no + * reporting of option names is desired. + */ +const { +getEnvironmentOption, +getEnvironmentOptionsList, +environmentOptionsListHas}= +makeEnvironmentCaptor(globalThis,true);$h‍_once.getEnvironmentOption(getEnvironmentOption);$h‍_once.getEnvironmentOptionsList(getEnvironmentOptionsList);$h‍_once.environmentOptionsListHas(environmentOptionsListHas); +})() +, +// === functors[1] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; $h‍_imports([["./src/env-options.js", []]]); +})() +, +// === functors[2] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; let getEnvironmentOption,environmentOptionsListHas;$h‍_imports([["@endo/env-options", [["getEnvironmentOption", [$h‍_a => (getEnvironmentOption = $h‍_a)]],["environmentOptionsListHas", [$h‍_a => (environmentOptionsListHas = $h‍_a)]]]]]); + + + + + +/* NOTE: We can't import these because they're not in scope before lockdown.*/ +/* We also cannot currently import them because it would create a cyclic*/ +/* dependency, though this is more easily fixed.*/ +/* import { assert, X, Fail } from '@endo/errors';*/ +/* See also https://github.com/Agoric/agoric-sdk/issues/9515*/ + +/* WARNING: Global Mutable State!*/ +/* This state is communicated to `assert` that makes it available to the*/ +/* causal console, which affects the console log output. Normally we*/ +/* regard the ability to see console log output as a meta-level privilege*/ +/* analogous to the ability to debug. Aside from that, this module should*/ +/* not have any observably mutable state.*/ + +let hiddenPriorError; +let hiddenCurrentTurn=0; +let hiddenCurrentEvent=0; + +/* Turn on if you seem to be losing error logging at the top of the event loop*/ +const VERBOSE=environmentOptionsListHas('DEBUG','track-turns'); + +/* Track-turns is disabled by default and can be enabled by an environment*/ +/* option.*/ +const ENABLED= +getEnvironmentOption('TRACK_TURNS','disabled',['enabled'])==='enabled'; + +/* We hoist the following functions out of trackTurns() to discourage the*/ +/* closures from holding onto 'args' or 'func' longer than necessary,*/ +/* which we've seen cause HandledPromise arguments to be retained for*/ +/* a surprisingly long time.*/ + +const addRejectionNote=(detailsNote)=>(reason)=>{ +if(reason instanceof Error){ +globalThis.assert.note(reason,detailsNote); + } +if(VERBOSE){ +console.log('REJECTED at top of event loop',reason); + } + }; + +const wrapFunction= +(func,sendingError,X)=> +(...args)=>{ +hiddenPriorError=sendingError; +hiddenCurrentTurn+=1; +hiddenCurrentEvent=0; +try{ +let result; +try{ +result=func(...args); + }catch(err){ +if(err instanceof Error){ +globalThis.assert.note( +err, +X `Thrown from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`); + + } +if(VERBOSE){ +console.log('THROWN to top of event loop',err); + } +throw err; + } +/* Must capture this now, not when the catch triggers.*/ +const detailsNote=X `Rejection from: ${hiddenPriorError}:${hiddenCurrentTurn}.${hiddenCurrentEvent}`; +Promise.resolve(result).catch(addRejectionNote(detailsNote)); +return result; + }finally{ +hiddenPriorError=undefined; + } + }; + +/** + * Given a list of `TurnStarterFn`s, returns a list of `TurnStarterFn`s whose + * `this`-free call behaviors are not observably different to those that + * cannot see console output. The only purpose is to cause additional + * information to appear on the console. + * + * The call to `trackTurns` is itself a sending event, that occurs in some call + * stack in some turn number at some event number within that turn. Each call + * to any of the returned `TurnStartFn`s is a receiving event that begins a new + * turn. This sending event caused each of those receiving events. + * + * @template {TurnStarterFn[]} T + * @param {T} funcs + * @returns {T} + */ +const trackTurns=(funcs)=>{ +if(!ENABLED||typeof globalThis==='undefined'||!globalThis.assert){ +return funcs; + } +const{details:X,note:annotateError}=globalThis.assert; + +hiddenCurrentEvent+=1; +const sendingError=Error( + `Event: ${hiddenCurrentTurn}.${hiddenCurrentEvent}`); + +if(hiddenPriorError!==undefined){ +annotateError(sendingError,X `Caused by: ${hiddenPriorError}`); + } + +return (/** @type {T} */ +funcs.map((func)=>func&&wrapFunction(func,sendingError,X))); + + }; + +/** + * An optional function that is not this-sensitive, expected to be called at + * bottom of stack to start a new turn. + * + * @typedef {((...args: any[]) => any) | undefined} TurnStarterFn + */$h‍_once.trackTurns(trackTurns); +})() +, +// === functors[3] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; let getEnvironmentOption;$h‍_imports([["@endo/env-options", [["getEnvironmentOption", [$h‍_a => (getEnvironmentOption = $h‍_a)]]]]]); + +const{quote:q,Fail}=assert; + +const{hasOwn,freeze,entries}=Object; + +/** + * @typedef {string | '*'} MatchStringTag + * A star `'*'` matches any recipient. Otherwise, the string is + * matched against the value of a recipient's `@@toStringTag` + * after stripping out any leading `'Alleged: '` or `'DebugName: '` + * prefix. For objects defined with `Far` this is the first argument, + * known as the `farName`. For exos, this is the tag. + */ +/** + * @typedef {string | '*'} MatchMethodName + * A star `'*'` matches any method name. Otherwise, the string is + * matched against the method name. Currently, this is only an exact match. + * However, beware that we may introduce a string syntax for + * symbol method names. + */ +/** + * @typedef {number | '*'} MatchCountdown + * A star `'*'` will always breakpoint. Otherwise, the string + * must be a non-negative integer. Once that is zero, always breakpoint. + * Otherwise decrement by one each time it matches until it reaches zero. + * In other words, the countdown represents the number of + * breakpoint occurrences to skip before actually breakpointing. + */ + +/** + * This is the external JSON representation, in which + * - the outer property name is the class-like tag or '*', + * - the inner property name is the method name or '*', + * - the value is a non-negative integer countdown or '*'. + * + * @typedef {Record>} MessageBreakpoints + */ + +/** + * This is the internal JSON representation, in which + * - the outer property name is the method name or '*', + * - the inner property name is the class-like tag or '*', + * - the value is a non-negative integer countdown or '*'. + * + * @typedef {Record>} BreakpointTable + */ + +/** + * @typedef {object} MessageBreakpointTester + * @property {() => MessageBreakpoints} getBreakpoints + * @property {(newBreakpoints?: MessageBreakpoints) => void} setBreakpoints + * @property {( + * recipient: object, + * methodName: string | symbol | undefined + * ) => boolean} shouldBreakpoint + */ + +/** + * @param {any} val + * @returns {val is Record} + */ +const isJSONRecord=(val)=> +typeof val==='object'&&val!==null&&!Array.isArray(val); + +/** + * Return `tag` after stripping off any `'Alleged: '` or `'DebugName: '` + * prefix if present. + * ```js + * simplifyTag('Alleged: moola issuer') === 'moola issuer' + * ``` + * If there are multiple such prefixes, only the outer one is removed. + * + * @param {string} tag + * @returns {string} + */ +const simplifyTag=(tag)=>{ +for(const prefix of['Alleged: ','DebugName: ']){ +if(tag.startsWith(prefix)){ +return tag.slice(prefix.length); + } + } +return tag; + }; + +/** + * @param {string} optionName + * @returns {MessageBreakpointTester | undefined} + */ +const makeMessageBreakpointTester=(optionName)=>{ +let breakpoints=JSON.parse(getEnvironmentOption(optionName,'null')); + +if(breakpoints===null){ +return undefined; + } + +/** @type {BreakpointTable} */ +let breakpointsTable; + +const getBreakpoints=()=>breakpoints; +freeze(getBreakpoints); + +const setBreakpoints=(newBreakpoints=breakpoints)=>{ +isJSONRecord(newBreakpoints)|| +Fail `Expected ${q(optionName)} option to be a JSON breakpoints record`; + +/** @type {BreakpointTable} */ +/* @ts-expect-error confused by __proto__*/ +const newBreakpointsTable={__proto__:null}; + +for(const[tag,methodBPs]of entries(newBreakpoints)){ +tag===simplifyTag(tag)|| +Fail `Just use simple tag ${q(simplifyTag(tag))} rather than ${q(tag)}`; +isJSONRecord(methodBPs)|| +Fail `Expected ${q(optionName)} option's ${q( +tag) + } to be a JSON methods breakpoints record`; +for(const[methodName,count]of entries(methodBPs)){ +count==='*'|| +typeof count==='number'&& +Number.isSafeInteger(count)&& +count>=0|| +Fail `Expected ${q(optionName)} option's ${q(tag)}.${q( +methodName) + } to be "*" or a non-negative integer`; + +const classBPs=hasOwn(newBreakpointsTable,methodName)? +newBreakpointsTable[methodName]: +newBreakpointsTable[methodName]={ +/* @ts-expect-error confused by __proto__*/ +__proto__:null}; + +classBPs[tag]=count; + } + } +breakpoints=newBreakpoints; +breakpointsTable=newBreakpointsTable; + }; +freeze(setBreakpoints); + +const shouldBreakpoint=(recipient,methodName)=>{ +if(methodName===undefined||methodName===null){ +/* TODO enable function breakpointing*/ +return false; + } +const classBPs=breakpointsTable[methodName]||breakpointsTable['*']; +if(classBPs===undefined){ +return false; + } +let tag=simplifyTag(recipient[Symbol.toStringTag]); +let count=classBPs[tag]; +if(count===undefined){ +tag='*'; +count=classBPs[tag]; +if(count===undefined){ +return false; + } + } +if(count==='*'){ +return true; + } +if(count===0){ +return true; + } +assert(typeof count==='number'&&count>=1); +classBPs[tag]=count-1; +return false; + }; +freeze(shouldBreakpoint); + +const breakpointTester=freeze({ +getBreakpoints, +setBreakpoints, +shouldBreakpoint}); + +breakpointTester.setBreakpoints(); +return breakpointTester; + };$h‍_once.makeMessageBreakpointTester(makeMessageBreakpointTester); +freeze(makeMessageBreakpointTester); +})() +, +// === functors[4] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; let makeMessageBreakpointTester;$h‍_imports([["./message-breakpoints.js", [["makeMessageBreakpointTester", [$h‍_a => (makeMessageBreakpointTester = $h‍_a)]]]]]); + +const{details:X,quote:q,Fail}=assert; + +const{getOwnPropertyDescriptors,getPrototypeOf,freeze}=Object; +const{apply,ownKeys}=Reflect; + +const ntypeof=(specimen)=>specimen===null?'null':typeof specimen; + +const onDelivery=makeMessageBreakpointTester('ENDO_DELIVERY_BREAKPOINTS'); + +/** + * TODO Consolidate with `isObject` that's currently in `@endo/marshal` + * + * @param {any} val + * @returns {boolean} + */ +const isObject=(val)=>Object(val)===val; + +/** + * Prioritize symbols as earlier than strings. + * + * @param {string|symbol} a + * @param {string|symbol} b + * @returns {-1 | 0 | 1} + */ +const compareStringified=(a,b)=>{ +if(typeof a===typeof b){ +const left=String(a); +const right=String(b); +/* eslint-disable-next-line no-nested-ternary*/ +return leftright?1:0; + } +if(typeof a==='symbol'){ +assert(typeof b==='string'); +return-1; + } +assert(typeof a==='string'); +assert(typeof b==='symbol'); +return 1; + }; + +/** + * @param {any} val + * @returns {(string|symbol)[]} + */ +const getMethodNames=(val)=>{ +let layer=val; +const names=new Set();/* Set to deduplicate*/ +while(layer!==null&&layer!==Object.prototype){ +/* be tolerant of non-objects*/ +const descs=getOwnPropertyDescriptors(layer); +for(const name of ownKeys(descs)){ +/* In case a method is overridden by a non-method,*/ +/* test `val[name]` rather than `layer[name]`*/ +if(typeof val[name]==='function'){ +names.add(name); + } + } +if(!isObject(val)){ +break; + } +layer=getPrototypeOf(layer); + } +return harden([...names].sort(compareStringified)); + }; +/* The top level of the eventual send modules can be evaluated before*/ +/* ses creates `harden`, and so cannot rely on `harden` at top level.*/$h‍_once.getMethodNames(getMethodNames); +freeze(getMethodNames); + +const localApplyFunction=(recipient,args)=>{ +typeof recipient==='function'|| +assert.fail( +X `Cannot invoke target as a function; typeof target is ${q( +ntypeof(recipient)) + }`, +TypeError); + +if(onDelivery&&onDelivery.shouldBreakpoint(recipient,undefined)){ +/* eslint-disable-next-line no-debugger*/ +debugger;/* STEP INTO APPLY*/ +/* Stopped at a breakpoint on this delivery of an eventual function call*/ +/* so that you can step *into* the following `apply` in order to see the*/ +/* function call as it happens. Or step *over* to see what happens*/ +/* after the function call returns.*/ + } +const result=apply(recipient,undefined,args); +return result; + };$h‍_once.localApplyFunction(localApplyFunction); + +const localApplyMethod=(recipient,methodName,args)=>{ +if(methodName===undefined||methodName===null){ +/* Base case; bottom out to apply functions.*/ +return localApplyFunction(recipient,args); + } +if(recipient===undefined||recipient===null){ +assert.fail( +X `Cannot deliver ${q(methodName)} to target; typeof target is ${q( +ntypeof(recipient)) + }`, +TypeError); + + } +const fn=recipient[methodName]; +if(fn===undefined){ +assert.fail( +X `target has no method ${q(methodName)}, has ${q( +getMethodNames(recipient)) + }`, +TypeError); + + } +const ftype=ntypeof(fn); +typeof fn==='function'|| +Fail `invoked method ${q(methodName)} is not a function; it is a ${q( +ftype) + }`; +if(onDelivery&&onDelivery.shouldBreakpoint(recipient,methodName)){ +/* eslint-disable-next-line no-debugger*/ +debugger;/* STEP INTO APPLY*/ +/* Stopped at a breakpoint on this delivery of an eventual method call*/ +/* so that you can step *into* the following `apply` in order to see the*/ +/* method call as it happens. Or step *over* to see what happens*/ +/* after the method call returns.*/ + } +const result=apply(fn,recipient,args); +return result; + };$h‍_once.localApplyMethod(localApplyMethod); + +const localGet=(t,key)=>t[key];$h‍_once.localGet(localGet); +})() +, +// === functors[5] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; $h‍_imports([]); /*/ */ + +/** + * Create a simple postponedHandler that just postpones until donePostponing is + * called. + * + * @param {IMPORT('./types').HandledPromiseConstructor} HandledPromise + * @returns {[Required>, () => void]} postponedHandler and donePostponing callback. + */ +const makePostponedHandler=(HandledPromise)=>{ +/** @type {() => void} */ +let donePostponing; + +const interlockP=new Promise((resolve)=>{ +donePostponing=()=>resolve(undefined); + }); + +const makePostponedOperation=(postponedOperation)=>{ +/* Just wait until the handler is resolved/rejected.*/ +return function postpone(x,...args){ +/* console.log(`forwarding ${postponedOperation} ${args[0]}`);*/ +return new HandledPromise((resolve,reject)=>{ +interlockP. +then((_)=>{ +resolve(HandledPromise[postponedOperation](x,...args)); + }). +catch(reject); + }); + }; + }; + +/** @type {Required>} */ +const postponedHandler={ +get:makePostponedOperation('get'), +getSendOnly:makePostponedOperation('getSendOnly'), +applyFunction:makePostponedOperation('applyFunction'), +applyFunctionSendOnly:makePostponedOperation('applyFunctionSendOnly'), +applyMethod:makePostponedOperation('applyMethod'), +applyMethodSendOnly:makePostponedOperation('applyMethodSendOnly')}; + + +/* @ts-expect-error 2454*/ +assert(donePostponing); + +return[postponedHandler,donePostponing]; + };$h‍_once.makePostponedHandler(makePostponedHandler); +})() +, +// === functors[6] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; let trackTurns,localApplyFunction,localApplyMethod,localGet,getMethodNames,makePostponedHandler;$h‍_imports([["./track-turns.js", [["trackTurns", [$h‍_a => (trackTurns = $h‍_a)]]]],["./local.js", [["localApplyFunction", [$h‍_a => (localApplyFunction = $h‍_a)]],["localApplyMethod", [$h‍_a => (localApplyMethod = $h‍_a)]],["localGet", [$h‍_a => (localGet = $h‍_a)]],["getMethodNames", [$h‍_a => (getMethodNames = $h‍_a)]]]],["./postponed.js", [["makePostponedHandler", [$h‍_a => (makePostponedHandler = $h‍_a)]]]]]); + + + + + + + + + + +const{Fail,details:X,quote:q,note:annotateError}=assert; + +const{ +create, +freeze, +getOwnPropertyDescriptor, +getOwnPropertyDescriptors, +defineProperties, +getPrototypeOf, +setPrototypeOf, +isFrozen, +is:objectIs}= +Object; + +const{apply,construct,ownKeys}=Reflect; + +const SEND_ONLY_RE=/^(.*)SendOnly$/; + +/** + * Coerce to an object property (string or symbol). + * + * @param {any} specimen + * @returns {string | symbol} + */ +const coerceToObjectProperty=(specimen)=>{ +if(typeof specimen==='symbol'){ +return specimen; + } +return String(specimen); + }; + +/* the following method (makeHandledPromise) is part*/ +/* of the shim, and will not be exported by the module once the feature*/ +/* becomes a part of standard javascript*/ + +/** + * Create a HandledPromise class to have it support eventual send + * (wavy-dot) operations. + * + * Based heavily on nanoq + * https://github.com/drses/nanoq/blob/master/src/nanoq.js + * + * Original spec for the infix-bang (predecessor to wavy-dot) desugaring: + * https://web.archive.org/web/20161026162206/http://wiki.ecmascript.org/doku.php?id=strawman:concurrency + * + */ +const makeHandledPromise=()=>{ +const presenceToHandler=new WeakMap(); +/** @type {WeakMap} */ +const presenceToPromise=new WeakMap(); +const promiseToPendingHandler=new WeakMap(); +const promiseToPresence=new WeakMap(); +const forwardedPromiseToPromise=new WeakMap();/* forwarding, union-find-ish*/ + +/** + * You can imagine a forest of trees in which the roots of each tree is an + * unresolved HandledPromise or a non-Promise, and each node's parent is the + * HandledPromise to which it was forwarded. We maintain that mapping of + * forwarded HandledPromise to its resolution in forwardedPromiseToPromise. + * + * We use something like the description of "Find" with "Path splitting" + * to propagate changes down to the children efficiently: + * https://en.wikipedia.org/wiki/Disjoint-set_data_structure + * + * @param {any} target Any value. + * @returns {any} If the target was a HandledPromise, the most-resolved parent + * of it, otherwise the target. + */ +const shorten=(target)=>{ +let p=target; +/* Find the most-resolved value for p.*/ +while(forwardedPromiseToPromise.has(p)){ +p=forwardedPromiseToPromise.get(p); + } +const presence=promiseToPresence.get(p); +if(presence){ +/* Presences are final, so it is ok to propagate*/ +/* this upstream.*/ +while(!objectIs(target,p)){ +const parent=forwardedPromiseToPromise.get(target); +forwardedPromiseToPromise.delete(target); +promiseToPendingHandler.delete(target); +promiseToPresence.set(target,presence); +target=parent; + } + }else{ +/* We propagate p and remove all other pending handlers*/ +/* upstream.*/ +/* Note that everything except presences is covered here.*/ +while(!objectIs(target,p)){ +const parent=forwardedPromiseToPromise.get(target); +forwardedPromiseToPromise.set(target,p); +promiseToPendingHandler.delete(target); +target=parent; + } + } +return target; + }; + +/** + * This special handler accepts Promises, and forwards + * handled Promises to their corresponding fulfilledHandler. + * + * @type {Required>} + */ +let forwardingHandler; +let handle; + +/** + * @param {string} handlerName + * @param {Handler} handler + * @param {string} operation + * @param {any} o + * @param {any[]} opArgs + * @param {Promise} [returnedP] + * @returns {any} + */ +const dispatchToHandler=( +handlerName, +handler, +operation, +o, +opArgs, +returnedP)=> +{ +let actualOp=operation; + +const matchSendOnly=SEND_ONLY_RE.exec(actualOp); + +const makeResult=(result)=>matchSendOnly?undefined:result; + +if(matchSendOnly){ +/* We don't specify the resulting promise if it is sendonly.*/ +returnedP=undefined; + } + +if(matchSendOnly&&typeof handler[actualOp]!=='function'){ +/* Substitute for sendonly with the corresponding non-sendonly operation.*/ +actualOp=matchSendOnly[1]; + } + +/* Fast path: just call the actual operation.*/ +const hfn=handler[actualOp]; +if(typeof hfn==='function'){ +const result=apply(hfn,handler,[o,...opArgs,returnedP]); +return makeResult(result); + } + +if(actualOp==='applyMethod'){ +/* Compose a missing applyMethod by get followed by applyFunction.*/ +const[prop,args]=opArgs; +const getResultP=handle( +o, +'get', +/* The argument to 'get' is a string or symbol.*/ +[coerceToObjectProperty(prop)], +undefined); + +return makeResult(handle(getResultP,'applyFunction',[args],returnedP)); + } + +/* BASE CASE: applyFunction bottoms out into applyMethod, if it exists.*/ +if(actualOp==='applyFunction'){ +const amfn=handler.applyMethod; +if(typeof amfn==='function'){ +/* Downlevel a missing applyFunction to applyMethod with undefined name.*/ +const[args]=opArgs; +const result=apply(amfn,handler,[o,undefined,[args],returnedP]); +return makeResult(result); + } + } + +throw assert.fail( +X `${q(handlerName)} is defined but has no methods needed for ${q( +operation) + } (has ${q(getMethodNames(handler))})`, +TypeError); + + }; + +/** @typedef {{new (executor: HandledExecutor, unfulfilledHandler?: Handler>): Promise, prototype: Promise} & PromiseConstructor & HandledPromiseStaticMethods} HandledPromiseConstructor */ +/** @type {HandledPromiseConstructor} */ +let HandledPromise; + +/** + * This *needs* to be a `function X` so that we can use it as a constructor. + * + * @template R + * @param {HandledExecutor} executor + * @param {Handler>} [pendingHandler] + * @returns {Promise} + */ +function baseHandledPromise(executor,pendingHandler=undefined){ +new.target||Fail `must be invoked with "new"`; +let handledResolve; +let handledReject; +let resolved=false; +let resolvedTarget=null; +let handledP; +let continueForwarding=()=>{ }; +const assertNotYetForwarded=()=>{ +!forwardedPromiseToPromise.has(handledP)|| +assert.fail(X `internal: already forwarded`,TypeError); + }; +const superExecutor=(superResolve,superReject)=>{ +handledResolve=(value)=>{ +if(resolved){ +return; + } +assertNotYetForwarded(); +value=shorten(value); +let targetP; +if( +promiseToPendingHandler.has(value)|| +promiseToPresence.has(value)) +{ +targetP=value; + }else{ +/* We're resolving to a non-promise, so remove our handler.*/ +promiseToPendingHandler.delete(handledP); +targetP=presenceToPromise.get(value); + } +/* Ensure our data structure is a proper tree (avoid cycles).*/ +if(targetP&&!objectIs(targetP,handledP)){ +forwardedPromiseToPromise.set(handledP,targetP); + }else{ +forwardedPromiseToPromise.delete(handledP); + } + +/* Remove stale pending handlers, set to canonical form.*/ +shorten(handledP); + +/* Finish the resolution.*/ +superResolve(value); +resolved=true; +resolvedTarget=value; + +/* We're resolved, so forward any postponed operations to us.*/ +continueForwarding(); + }; +handledReject=(reason)=>{ +if(resolved){ +return; + } +harden(reason); +assertNotYetForwarded(); +promiseToPendingHandler.delete(handledP); +resolved=true; +superReject(reason); +continueForwarding(); + }; + }; +handledP=harden(construct(Promise,[superExecutor],new.target)); + +if(!pendingHandler){ +/* This is insufficient for actual remote handled Promises*/ +/* (too many round-trips), but is an easy way to create a*/ +/* local handled Promise.*/ +[pendingHandler,continueForwarding]= +makePostponedHandler(HandledPromise); + } + +const validateHandler=(h)=>{ +Object(h)===h|| +assert.fail(X `Handler ${h} cannot be a primitive`,TypeError); + }; +validateHandler(pendingHandler); + +/* Until the handled promise is resolved, we use the pendingHandler.*/ +promiseToPendingHandler.set(handledP,pendingHandler); + +const rejectHandled=(reason)=>{ +if(resolved){ +return; + } +assertNotYetForwarded(); +handledReject(reason); + }; + +const resolveWithPresence=( +presenceHandler=pendingHandler, +options={})=> +{ +if(resolved){ +return resolvedTarget; + } +assertNotYetForwarded(); +try{ +/* Sanity checks.*/ +validateHandler(presenceHandler); + +const{proxy:proxyOpts}=options; +let presence; +if(proxyOpts){ +const{ +handler:proxyHandler, +target:proxyTarget, +revokerCallback}= +proxyOpts; +if(revokerCallback){ +/* Create a proxy and its revoke function.*/ +const{proxy,revoke}=Proxy.revocable( +proxyTarget, +proxyHandler); + +presence=proxy; +revokerCallback(revoke); + }else{ +presence=new Proxy(proxyTarget,proxyHandler); + } + }else{ +/* Default presence.*/ +presence=create(null); + } + +/* Validate and install our mapped target (i.e. presence).*/ +resolvedTarget=presence; + +/* Create table entries for the presence mapped to the*/ +/* fulfilledHandler.*/ +presenceToPromise.set(resolvedTarget,handledP); +promiseToPresence.set(handledP,resolvedTarget); +presenceToHandler.set(resolvedTarget,presenceHandler); + +/* We committed to this presence, so resolve.*/ +handledResolve(resolvedTarget); +return resolvedTarget; + }catch(e){ +annotateError(e,X `during resolveWithPresence`); +handledReject(e); +throw e; + } + }; + +const resolveHandled=(target)=>{ +if(resolved){ +return; + } +assertNotYetForwarded(); +try{ +/* Resolve the target.*/ +handledResolve(target); + }catch(e){ +handledReject(e); + } + }; + +/* Invoke the callback to let the user resolve/reject.*/ +executor(resolveHandled,rejectHandled,resolveWithPresence); + +return handledP; + } + +/** + * If the promise `p` is safe, then during the evaluation of the + * expressopns `p.then` and `await p`, `p` cannot mount a reentrancy attack. + * Unfortunately, due to limitations of the current JavaScript standard, + * it seems impossible to prevent `p` from mounting a reentrancy attack + * during the evaluation of `isSafePromise(p)`, and therefore during + * operations like `HandledPromise.resolve(p)` that call + * `isSafePromise(p)` synchronously. + * + * The `@endo/marshal` package defines a related notion of a passable + * promise, i.e., one for which which `passStyleOf(p) === 'promise'`. All + * passable promises are also safe. But not vice versa because the + * requirements for a promise to be passable are slightly greater. A safe + * promise must not override `then` or `constructor`. A passable promise + * must not have any own properties. The requirements are otherwise + * identical. + * + * @param {Promise} p + * @returns {boolean} + */ +const isSafePromise=(p)=>{ +return( +isFrozen(p)&& +getPrototypeOf(p)===Promise.prototype&& +Promise.resolve(p)===p&& +getOwnPropertyDescriptor(p,'then')===undefined&& +getOwnPropertyDescriptor(p,'constructor')===undefined); + + }; + +/** @type {HandledPromiseStaticMethods & Pick} */ +const staticMethods={ +get(target,prop){ +prop=coerceToObjectProperty(prop); +return handle(target,'get',[prop]); + }, +getSendOnly(target,prop){ +prop=coerceToObjectProperty(prop); +handle(target,'getSendOnly',[prop]).catch(()=>{ }); + }, +applyFunction(target,args){ +/* Ensure args is an array.*/ +args=[...args]; +return handle(target,'applyFunction',[args]); + }, +applyFunctionSendOnly(target,args){ +/* Ensure args is an array.*/ +args=[...args]; +handle(target,'applyFunctionSendOnly',[args]).catch(()=>{ }); + }, +applyMethod(target,prop,args){ +prop=coerceToObjectProperty(prop); +/* Ensure args is an array.*/ +args=[...args]; +return handle(target,'applyMethod',[prop,args]); + }, +applyMethodSendOnly(target,prop,args){ +prop=coerceToObjectProperty(prop); +/* Ensure args is an array.*/ +args=[...args]; +handle(target,'applyMethodSendOnly',[prop,args]).catch(()=>{ }); + }, +resolve(value){ +/* Resolving a Presence returns the pre-registered handled promise.*/ +let resolvedPromise=presenceToPromise.get(/** @type {any} */value); +if(!resolvedPromise){ +resolvedPromise=Promise.resolve(value); + } +/* Prevent any proxy trickery.*/ +harden(resolvedPromise); +if(isSafePromise(resolvedPromise)){ +/* We can use the `resolvedPromise` directly, since it is guaranteed to*/ +/* have a `then` which is actually `Promise.prototype.then`.*/ +return resolvedPromise; + } +/* Assimilate the `resolvedPromise` as an actual frozen Promise, by*/ +/* treating `resolvedPromise` as if it is a non-promise thenable.*/ +const executeThen=(resolve,reject)=> +resolvedPromise.then(resolve,reject); +return harden( +Promise.resolve().then(()=>new HandledPromise(executeThen))); + + }}; + + +const makeForwarder=(operation,localImpl)=>{ +return(o,...args)=>{ +/* We are in another turn already, and have the naked object.*/ +const presenceHandler=presenceToHandler.get(o); +if(!presenceHandler){ +return localImpl(o,...args); + } +return dispatchToHandler( +'presenceHandler', +presenceHandler, +operation, +o, +args); + + }; + }; + +/* eslint-disable-next-line prefer-const*/ +forwardingHandler={ +get:makeForwarder('get',localGet), +getSendOnly:makeForwarder('getSendOnly',localGet), +applyFunction:makeForwarder('applyFunction',localApplyFunction), +applyFunctionSendOnly:makeForwarder( +'applyFunctionSendOnly', +localApplyFunction), + +applyMethod:makeForwarder('applyMethod',localApplyMethod), +applyMethodSendOnly:makeForwarder('applyMethodSendOnly',localApplyMethod)}; + + +handle=(...handleArgs)=>{ +/* We're in SES mode, so we should harden.*/ +harden(handleArgs); +const[_p,operation,opArgs,...dispatchArgs]=handleArgs; +let[p]=handleArgs; +const doDispatch=(handlerName,handler,o)=> +dispatchToHandler( +handlerName, +handler, +operation, +o, +opArgs, +/* eslint-disable-next-line no-use-before-define*/ +...(dispatchArgs.length===0?[returnedP]:dispatchArgs)); + +const[trackedDoDispatch]=trackTurns([doDispatch]); +const returnedP=new HandledPromise((resolve,reject)=>{ +/* We run in a future turn to prevent synchronous attacks,*/ +let raceIsOver=false; + +const win=(handlerName,handler,o)=>{ +if(raceIsOver){ +return; + } +try{ +resolve(harden(trackedDoDispatch(handlerName,handler,o))); + }catch(reason){ +reject(harden(reason)); + } +raceIsOver=true; + }; + +const lose=(reason)=>{ +if(raceIsOver){ +return; + } +reject(harden(reason)); +raceIsOver=true; + }; + +/* This contestant tries to win with the target's resolution.*/ +staticMethods. +resolve(p). +then((o)=>win('forwardingHandler',forwardingHandler,o)). +catch(lose); + +/* This contestant sleeps a turn, but then tries to win immediately.*/ +staticMethods. +resolve(). +then(()=>{ +p=shorten(p); +const pendingHandler=promiseToPendingHandler.get(p); +if(pendingHandler){ +/* resolve to the answer from the specific pending handler,*/ +win('pendingHandler',pendingHandler,p); + }else if(!p||typeof p.then!=='function'){ +/* Not a Thenable, so use it.*/ +win('forwardingHandler',forwardingHandler,p); + }else if(promiseToPresence.has(p)){ +/* We have the object synchronously, so resolve with it.*/ +const o=promiseToPresence.get(p); +win('forwardingHandler',forwardingHandler,o); + } +/* If we made it here without winning, then we will wait*/ +/* for the other contestant to win instead.*/ + }). +catch(lose); + }); + +/* We return a handled promise with the default pending handler. This*/ +/* prevents a race between the above Promise.resolves and pipelining.*/ +return harden(returnedP); + }; + +/* Add everything needed on the constructor.*/ +baseHandledPromise.prototype=Promise.prototype; +setPrototypeOf(baseHandledPromise,Promise); +defineProperties( +baseHandledPromise, +getOwnPropertyDescriptors(staticMethods)); + + +/* FIXME: This is really ugly to bypass the type system, but it will be better*/ +/* once we use Promise.delegated and don't have any [[Constructor]] behaviours.*/ +/* @ts-expect-error cast*/ +HandledPromise=baseHandledPromise; + +/* We're a vetted shim which runs before `lockdown` allows*/ +/* `harden(HandledPromise)` to function, but single-level `freeze` is a*/ +/* suitable replacement because all mutable objects reachable afterwards are*/ +/* intrinsics hardened by lockdown.*/ +freeze(HandledPromise); +for(const key of ownKeys(HandledPromise)){ +/* prototype is the intrinsic Promise.prototype to be hardened by lockdown.*/ +if(key!=='prototype'){ +freeze(HandledPromise[key]); + } + } + +return HandledPromise; + }; + +/** + * @template T + * @typedef {{ + * get?(p: T, name: PropertyKey, returnedP?: Promise): unknown; + * getSendOnly?(p: T, name: PropertyKey): void; + * applyFunction?(p: T, args: unknown[], returnedP?: Promise): unknown; + * applyFunctionSendOnly?(p: T, args: unknown[]): void; + * applyMethod?(p: T, name: PropertyKey | undefined, args: unknown[], returnedP?: Promise): unknown; + * applyMethodSendOnly?(p: T, name: PropertyKey | undefined, args: unknown[]): void; + * }} Handler + */ + +/** + * @template {{}} T + * @typedef {{ + * proxy?: { + * handler: ProxyHandler; + * target: unknown; + * revokerCallback?(revoker: () => void): void; + * }; + * }} ResolveWithPresenceOptionsBag + */ + +/** + * @template [R = unknown] + * @typedef {( + * resolveHandled: (value?: R) => void, + * rejectHandled: (reason?: unknown) => void, + * resolveWithPresence: (presenceHandler: Handler<{}>, options?: ResolveWithPresenceOptionsBag<{}>) => object, + * ) => void} HandledExecutor + */ + +/** + * @template [R = unknown] + * @typedef {{ + * resolve(value?: R): void; + * reject(reason: unknown): void; + * resolveWithPresence(presenceHandler?: Handler<{}>, options?: ResolveWithPresenceOptionsBag<{}>): object; + * }} Settler + */ + +/** + * @typedef {{ + * applyFunction(target: unknown, args: unknown[]): Promise; + * applyFunctionSendOnly(target: unknown, args: unknown[]): void; + * applyMethod(target: unknown, prop: PropertyKey | undefined, args: unknown[]): Promise; + * applyMethodSendOnly(target: unknown, prop: PropertyKey, args: unknown[]): void; + * get(target: unknown, prop: PropertyKey): Promise; + * getSendOnly(target: unknown, prop: PropertyKey): void; + * }} HandledPromiseStaticMethods + */ + +/** @typedef {ReturnType} HandledPromiseConstructor */$h‍_once.makeHandledPromise(makeHandledPromise); +})() +, +// === functors[7] === +({ imports: $h‍_imports, liveVar: $h‍_live, onceVar: $h‍_once, importMeta: $h‍____meta, }) => (function () { 'use strict'; let makeHandledPromise;$h‍_imports([["./src/handled-promise.js", [["makeHandledPromise", [$h‍_a => (makeHandledPromise = $h‍_a)]]]]]); + + +if(typeof globalThis.HandledPromise==='undefined'){ +globalThis.HandledPromise=makeHandledPromise(); + } +})() +, +]); + diff --git a/yarn.lock b/yarn.lock index 9cc58f6b6..ed66a188d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -469,6 +469,15 @@ __metadata: languageName: node linkType: hard +"@endo/eventual-send@npm:^1.2.2": + version: 1.2.2 + resolution: "@endo/eventual-send@npm:1.2.2" + dependencies: + "@endo/env-options": "npm:^1.1.4" + checksum: 10/780449d9d5e8be2b75697521b9727971b7232d00dccef1fabd364650237b82025b582940eedb8951eae55e16a8271fbf7b2f69f9442e37a595e9dbb4632c1c2a + languageName: node + linkType: hard + "@endo/lockdown@npm:^1.0.7": version: 1.0.7 resolution: "@endo/lockdown@npm:1.0.7" @@ -1309,6 +1318,91 @@ __metadata: languageName: node linkType: hard +"@ocap/extension@workspace:packages/extension": + version: 0.0.0-use.local + resolution: "@ocap/extension@workspace:packages/extension" + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/lockdown": "npm:^1.0.7" + "@metamask/auto-changelog": "npm:^3.4.4" + "@ocap/germs": "npm:^0.0.0" + "@types/chrome": "npm:^0.0.268" + "@types/jest": "npm:^28.1.6" + deepmerge: "npm:^4.3.1" + jest: "npm:^28.1.3" + jest-it-up: "npm:^2.0.2" + ses: "npm:^1.5.0" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~4.9.5" + vite: "npm:^5.3.4" + vite-plugin-static-copy: "npm:^1.0.6" + languageName: unknown + linkType: soft + +"@ocap/germs@npm:^0.0.0, @ocap/germs@workspace:packages/germs": + version: 0.0.0-use.local + resolution: "@ocap/germs@workspace:packages/germs" + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/eventual-send": "npm:^1.2.2" + "@endo/lockdown": "npm:^1.0.7" + "@metamask/auto-changelog": "npm:^3.4.4" + "@ts-bridge/cli": "npm:^0.1.4" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/jest": "npm:^28.1.6" + deepmerge: "npm:^4.3.1" + jest: "npm:^28.1.3" + mkdirp: "npm:^3.0.1" + rimraf: "npm:^6.0.1" + ses: "npm:^1.5.0" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~4.9.5" + languageName: unknown + linkType: soft + +"@ocap/monorepo@workspace:.": + version: 0.0.0-use.local + resolution: "@ocap/monorepo@workspace:." + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@lavamoat/allow-scripts": "npm:^3.0.4" + "@lavamoat/preinstall-always-fail": "npm:^2.0.0" + "@metamask/auto-changelog": "npm:^3.4.4" + "@metamask/eslint-config": "npm:^12.2.0" + "@metamask/eslint-config-jest": "npm:^12.1.0" + "@metamask/eslint-config-nodejs": "npm:^12.1.0" + "@metamask/eslint-config-typescript": "npm:^12.1.0" + "@ts-bridge/cli": "npm:^0.1.4" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/jest": "npm:^28.1.6" + "@types/node": "npm:^18.18.14" + "@typescript-eslint/eslint-plugin": "npm:^5.43.0" + "@typescript-eslint/parser": "npm:^5.43.0" + "@yarnpkg/types": "npm:^4.0.0" + depcheck: "npm:^1.4.3" + eslint: "npm:^8.44.0" + eslint-config-prettier: "npm:^8.8.0" + eslint-plugin-import: "npm:~2.26.0" + eslint-plugin-jest: "npm:^27.2.2" + eslint-plugin-jsdoc: "npm:^39.9.1" + eslint-plugin-n: "npm:^15.7.0" + eslint-plugin-prettier: "npm:^4.2.1" + eslint-plugin-promise: "npm:^6.1.1" + jest: "npm:^28.1.3" + jest-silent-reporter: "npm:^0.6.0" + prettier: "npm:^2.7.1" + prettier-plugin-packagejson: "npm:^2.3.0" + rimraf: "npm:^6.0.1" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typescript: "npm:~4.9.5" + languageName: unknown + linkType: soft + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" @@ -3565,28 +3659,6 @@ __metadata: languageName: node linkType: hard -"extension@workspace:packages/extension": - version: 0.0.0-use.local - resolution: "extension@workspace:packages/extension" - dependencies: - "@arethetypeswrong/cli": "npm:^0.15.3" - "@endo/lockdown": "npm:^1.0.7" - "@metamask/auto-changelog": "npm:^3.4.4" - "@types/chrome": "npm:^0.0.268" - "@types/jest": "npm:^28.1.6" - deepmerge: "npm:^4.3.1" - jest: "npm:^28.1.3" - jest-it-up: "npm:^2.0.2" - ses: "npm:^1.5.0" - ts-jest: "npm:^28.0.7" - typedoc: "npm:^0.24.8" - typedoc-plugin-missing-exports: "npm:^2.0.0" - typescript: "npm:~4.9.5" - vite: "npm:^5.3.4" - vite-plugin-static-copy: "npm:^1.0.6" - languageName: unknown - linkType: soft - "fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": version: 3.1.3 resolution: "fast-deep-equal@npm:3.1.3" @@ -3831,28 +3903,6 @@ __metadata: languageName: node linkType: hard -"germs@workspace:packages/germs": - version: 0.0.0-use.local - resolution: "germs@workspace:packages/germs" - dependencies: - "@arethetypeswrong/cli": "npm:^0.15.3" - "@endo/lockdown": "npm:^1.0.7" - "@metamask/auto-changelog": "npm:^3.4.4" - "@ts-bridge/cli": "npm:^0.1.4" - "@ts-bridge/shims": "npm:^0.1.1" - "@types/jest": "npm:^28.1.6" - deepmerge: "npm:^4.3.1" - jest: "npm:^28.1.3" - mkdirp: "npm:^3.0.1" - rimraf: "npm:^6.0.1" - ses: "npm:^1.5.0" - ts-jest: "npm:^28.0.7" - typedoc: "npm:^0.24.8" - typedoc-plugin-missing-exports: "npm:^2.0.0" - typescript: "npm:~4.9.5" - languageName: unknown - linkType: soft - "get-caller-file@npm:^2.0.5": version: 2.0.5 resolution: "get-caller-file@npm:2.0.5" @@ -5933,45 +5983,6 @@ __metadata: languageName: node linkType: hard -"ocap-kernel-monorepo@workspace:.": - version: 0.0.0-use.local - resolution: "ocap-kernel-monorepo@workspace:." - dependencies: - "@arethetypeswrong/cli": "npm:^0.15.3" - "@lavamoat/allow-scripts": "npm:^3.0.4" - "@lavamoat/preinstall-always-fail": "npm:^2.0.0" - "@metamask/auto-changelog": "npm:^3.4.4" - "@metamask/eslint-config": "npm:^12.2.0" - "@metamask/eslint-config-jest": "npm:^12.1.0" - "@metamask/eslint-config-nodejs": "npm:^12.1.0" - "@metamask/eslint-config-typescript": "npm:^12.1.0" - "@ts-bridge/cli": "npm:^0.1.4" - "@ts-bridge/shims": "npm:^0.1.1" - "@types/jest": "npm:^28.1.6" - "@types/node": "npm:^18.18.14" - "@typescript-eslint/eslint-plugin": "npm:^5.43.0" - "@typescript-eslint/parser": "npm:^5.43.0" - "@yarnpkg/types": "npm:^4.0.0" - depcheck: "npm:^1.4.3" - eslint: "npm:^8.44.0" - eslint-config-prettier: "npm:^8.8.0" - eslint-plugin-import: "npm:~2.26.0" - eslint-plugin-jest: "npm:^27.2.2" - eslint-plugin-jsdoc: "npm:^39.9.1" - eslint-plugin-n: "npm:^15.7.0" - eslint-plugin-prettier: "npm:^4.2.1" - eslint-plugin-promise: "npm:^6.1.1" - jest: "npm:^28.1.3" - jest-silent-reporter: "npm:^0.6.0" - prettier: "npm:^2.7.1" - prettier-plugin-packagejson: "npm:^2.3.0" - rimraf: "npm:^6.0.1" - ts-jest: "npm:^28.0.7" - typedoc: "npm:^0.24.8" - typescript: "npm:~4.9.5" - languageName: unknown - linkType: soft - "once@npm:^1.3.0": version: 1.4.0 resolution: "once@npm:1.4.0" From bc7a5524ddb9727154e538fe2b1d6137bb245074 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Fri, 19 Jul 2024 17:48:41 +0200 Subject: [PATCH 17/31] feat: Apply eventual-send shim in extension, add dev console --- packages/extension/package.json | 2 +- packages/extension/src/background.ts | 28 ++++++++++++++------- packages/extension/src/dev-console.mjs | 8 ++++++ packages/extension/src/offscreen.ts | 17 +++++++------ packages/extension/src/shared.ts | 15 ++++++++--- packages/extension/tsconfig.json | 2 +- packages/extension/vite.config.mts | 12 ++++----- packages/germs/scripts/bundle-shims.mjs | 21 ++++++++-------- packages/germs/src/shims/apply-lockdown.mjs | 1 - packages/germs/src/shims/endoify.mjs | 12 +++++++++ 10 files changed, 79 insertions(+), 39 deletions(-) create mode 100644 packages/extension/src/dev-console.mjs create mode 100644 packages/germs/src/shims/endoify.mjs diff --git a/packages/extension/package.json b/packages/extension/package.json index 5a03b1716..3786735a2 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -16,7 +16,7 @@ "build:vite": "vite build -c vite.config.mts", "changelog:validate": "../../scripts/validate-changelog.sh @ocap/extension", "publish:preview": "yarn npm publish --tag preview", - "start": "vite -c vite.config.mts", + "start": "vite -c vite.config.mts & vite build --watch -c vite.config.mts", "test": "jest --reporters=jest-silent-reporter", "posttest": "jest-it-up", "test:clean": "jest --clearCache", diff --git a/packages/extension/src/background.ts b/packages/extension/src/background.ts index b3040727b..cf4e9c7ef 100644 --- a/packages/extension/src/background.ts +++ b/packages/extension/src/background.ts @@ -1,14 +1,23 @@ -// eslint-disable-next-line import/extensions,import/no-unassigned-import -import './apply-lockdown.mjs'; +/* eslint-disable import/extensions,import/no-unassigned-import */ +import './dev-console.mjs'; +import './endoify.mjs'; +/* eslint-enable import/extensions,import/no-unassigned-import */ import type { ExtensionMessage } from './shared'; -import { makeHandledCallback } from './shared'; +import { Command, Reply, makeHandledCallback } from './shared'; + +// globalThis.kernel will exist due to dev-console.mjs +Object.defineProperties(globalThis.kernel, { + sendMessage: { + value: sendMessage, + }, +}); const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; -// Send +// With this we can click the extension action button to wake up the service worker. chrome.action.onClicked.addListener(() => { - sendMessage('greetings', { name: 'Kernel' }).catch(console.error); + sendMessage(Command.Ping, { name: 'Kernel' }).catch(console.error); }); /** @@ -40,24 +49,25 @@ async function provideOffScreenDocument() { } } -// Receive +// Here we handle replies from the offscreen document chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); /** * Receive a message from the offscreen document. * @param message - The message to handle. */ -async function handleMessage(message: ExtensionMessage) { +async function handleMessage(message: ExtensionMessage) { if (message.target !== 'background') { return; } switch (message.type) { - case 'salutations': - console.log(message.data); + case Reply.Pong: + console.log(Reply.Pong); await closeOffscreenDocument(); break; default: + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions console.error(`Received unexpected message type: "${message.type}"`); } } diff --git a/packages/extension/src/dev-console.mjs b/packages/extension/src/dev-console.mjs new file mode 100644 index 000000000..275afbcb6 --- /dev/null +++ b/packages/extension/src/dev-console.mjs @@ -0,0 +1,8 @@ +/* eslint-disable import/unambiguous */ +// We set this property on globalThis in the background before lockdown. +Object.defineProperty(globalThis, 'kernel', { + configurable: false, + enumerable: true, + writable: false, + value: {}, +}); diff --git a/packages/extension/src/offscreen.ts b/packages/extension/src/offscreen.ts index 3c5019697..0d1f44536 100644 --- a/packages/extension/src/offscreen.ts +++ b/packages/extension/src/offscreen.ts @@ -1,8 +1,8 @@ // eslint-disable-next-line import/extensions,import/no-unassigned-import -import './apply-lockdown.mjs'; +import './endoify.mjs'; import type { ExtensionMessage } from './shared'; -import { makeHandledCallback } from './shared'; +import { Command, Reply, makeHandledCallback } from './shared'; chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); @@ -10,16 +10,19 @@ chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); * Handle a message from the background script. * @param message - The message to handle. */ -async function handleMessage(message: ExtensionMessage<{ name: string }>) { +async function handleMessage( + message: ExtensionMessage, +) { if (message.target !== 'offscreen') { return; } switch (message.type) { - case 'greetings': - await reply('salutations', `Good day to you, ${message.data.name}!`); + case Command.Ping: + await reply(Reply.Pong); break; default: + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions console.error(`Received unexpected message type: "${message.type}"`); } } @@ -29,9 +32,9 @@ async function handleMessage(message: ExtensionMessage<{ name: string }>) { * @param type - The message type. * @param data - The message data. */ -async function reply(type: string, data: string) { +async function reply(type: string, data?: string) { await chrome.runtime.sendMessage({ - data, + data: data ?? null, target: 'background', type, }); diff --git a/packages/extension/src/shared.ts b/packages/extension/src/shared.ts index 367844a74..a0d03822d 100644 --- a/packages/extension/src/shared.ts +++ b/packages/extension/src/shared.ts @@ -1,13 +1,22 @@ +export enum Command { + Ping = 'ping', +} + +export enum Reply { + Pong = 'pong', +} + export type ExtensionMessage< - Data extends string | unknown[] | Record, + Type extends string, + Data extends null | string | unknown[] | Record, > = { - type: string; + type: Type; target: 'background' | 'offscreen'; data: Data; }; /** - * Wrap an async callback to ensure any errors are re-thrown synchronously. + * Wrap an async callback to ensure any errors are re-thrown. * @param callback - The async callback to wrap. * @returns The wrapped callback. */ diff --git a/packages/extension/tsconfig.json b/packages/extension/tsconfig.json index 943a90c6c..7083dabd1 100644 --- a/packages/extension/tsconfig.json +++ b/packages/extension/tsconfig.json @@ -8,5 +8,5 @@ "skipLibCheck": true, "types": ["chrome"] }, - "include": ["./src/**/*.ts"] + "include": ["./src/**/*.ts", "./src/dev-console.mjs"] } diff --git a/packages/extension/vite.config.mts b/packages/extension/vite.config.mts index 82a0114e2..6f1a50f0e 100644 --- a/packages/extension/vite.config.mts +++ b/packages/extension/vite.config.mts @@ -12,11 +12,9 @@ export default defineConfig({ emptyOutDir: true, outDir: path.resolve(projectRoot, '../dist'), rollupOptions: { - // Ignore the following module specifiers if imported - external: [ - // This file and its imports must not be modified - './apply-lockdown.mjs', - ], + // This tells Rollup to ignore the following module specifiers if imported. + // Their contents must not be modified. + external: ['./dev-console.mjs', './endoify.mjs'], input: { background: path.resolve(projectRoot, 'background.ts'), offscreen: path.resolve(projectRoot, 'offscreen.html'), @@ -33,7 +31,9 @@ export default defineConfig({ viteStaticCopy({ targets: [ { src: 'manifest.json', dest: './' }, - { src: '../../germs/src/shims/apply-lockdown.mjs', dest: './' }, + { src: 'dev-console.mjs', dest: './' }, + { src: '../../germs/dist/shims/endoify.mjs', dest: './' }, + { src: '../../germs/dist/shims/eventual-send.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/ses.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, ], diff --git a/packages/germs/scripts/bundle-shims.mjs b/packages/germs/scripts/bundle-shims.mjs index 677d81dc0..06ebf3c29 100644 --- a/packages/germs/scripts/bundle-shims.mjs +++ b/packages/germs/scripts/bundle-shims.mjs @@ -7,7 +7,7 @@ import path from 'path'; // import bundleSource from '@endo/bundle-source'; import { rimraf } from 'rimraf'; -console.log('Bundling shims...') +console.log('Bundling shims...'); const rootDir = path.resolve(import.meta.dirname, '..'); const shimsSrc = path.resolve(rootDir, 'src/shims'); @@ -16,22 +16,21 @@ const shimsDist = path.resolve(rootDir, 'dist/shims'); // const eventualSendSrc = path.resolve(rootDir, '../../node_modules/@endo/eventual-send/shim.js'); const fileNames = { - lockdown: 'apply-lockdown.mjs', + endoify: 'endoify.mjs', eventualSend: 'eventual-send.mjs', + lockdown: 'apply-lockdown.mjs', }; await mkdirp(shimsDist); await rimraf(`${shimsDist}/*`); -await copyFile( - path.resolve(shimsSrc, fileNames.lockdown), - path.resolve(shimsDist, fileNames.lockdown), -); -await copyFile( - path.resolve(shimsSrc, fileNames.eventualSend), - path.resolve(shimsDist, fileNames.eventualSend), -); +for (const fileName of Object.values(fileNames)) { + await copyFile( + path.resolve(shimsSrc, fileName), + path.resolve(shimsDist, fileName), + ); +} // const { source } = await bundleSource(eventualSendSrc, { format: 'endoScript' }); -console.log('Success!') +console.log('Success!'); diff --git a/packages/germs/src/shims/apply-lockdown.mjs b/packages/germs/src/shims/apply-lockdown.mjs index ef718651e..b5808fd25 100644 --- a/packages/germs/src/shims/apply-lockdown.mjs +++ b/packages/germs/src/shims/apply-lockdown.mjs @@ -1,4 +1,3 @@ -import './ses.mjs'; import './lockdown.mjs'; lockdown({ diff --git a/packages/germs/src/shims/endoify.mjs b/packages/germs/src/shims/endoify.mjs new file mode 100644 index 000000000..8293320db --- /dev/null +++ b/packages/germs/src/shims/endoify.mjs @@ -0,0 +1,12 @@ +import './ses.mjs'; +import './eventual-send.mjs'; +import './lockdown.mjs'; + +lockdown({ + consoleTaming: 'unsafe', + errorTaming: 'unsafe', + mathTaming: 'unsafe', + dateTaming: 'unsafe', + domainTaming: 'unsafe', + overrideTaming: 'severe', +}); From 2a139d7ae2b61a57dc22fdf044c075886559cbc4 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Fri, 19 Jul 2024 17:56:38 +0200 Subject: [PATCH 18/31] chore: Remove extraneous comments --- packages/germs/.eslintrc.js | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/packages/germs/.eslintrc.js b/packages/germs/.eslintrc.js index dab61e7e3..48c28e5f1 100644 --- a/packages/germs/.eslintrc.js +++ b/packages/germs/.eslintrc.js @@ -2,20 +2,4 @@ module.exports = { extends: ['../../.eslintrc.js'], ignorePatterns: ['**/shims/*.mjs'], - - // overrides: [ - // { - // files: ['src/**/*.js'], - // globals: { chrome: 'readonly', clients: 'readonly' }, - // }, - - // { - // files: ['vite.config.mts'], - // parserOptions: { - // sourceType: 'module', - // tsconfigRootDir: __dirname, - // project: ['./tsconfig.scripts.json'], - // }, - // }, - // ], }; From 72dba1839e28b26a85c1f71b5276b76995d89338 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Fri, 19 Jul 2024 17:56:55 +0200 Subject: [PATCH 19/31] chore: Remove license from germs --- packages/germs/LICENSE | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 packages/germs/LICENSE diff --git a/packages/germs/LICENSE b/packages/germs/LICENSE deleted file mode 100644 index 6f8bff03f..000000000 --- a/packages/germs/LICENSE +++ /dev/null @@ -1,20 +0,0 @@ -MIT License - -Copyright (c) 2024 MetaMask - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE From 56a33aa6b480a1ecc0e07e027ac6c76f605627c3 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Mon, 22 Jul 2024 16:43:38 +0200 Subject: [PATCH 20/31] refactor: Rename germs package to shims --- constraints.pro | 12 ++--- packages/extension/package.json | 2 +- packages/extension/tsconfig.build.json | 2 +- packages/extension/vite.config.mts | 4 +- packages/germs/.eslintrc.js | 5 -- packages/germs/src/index.test.ts | 9 ---- packages/germs/src/index.ts | 9 ---- packages/germs/src/shims/README.md | 3 -- packages/shims/.eslintrc.js | 17 +++++++ packages/{germs => shims}/CHANGELOG.md | 0 packages/{germs => shims}/README.md | 4 +- packages/{germs => shims}/jest.config.js | 0 packages/{germs => shims}/package.json | 34 ++++--------- .../scripts/bundle.mjs} | 13 ++--- .../shims => shims/src}/apply-lockdown.mjs | 0 .../src/shims => shims/src}/endoify.mjs | 0 .../src/shims => shims/src}/eventual-send.mjs | 0 packages/{germs => shims}/tsconfig.build.json | 3 +- packages/{germs => shims}/tsconfig.json | 0 packages/{germs => shims}/typedoc.json | 0 tsconfig.build.json | 2 +- tsconfig.json | 2 +- yarn.lock | 48 +++++++++---------- 23 files changed, 69 insertions(+), 100 deletions(-) delete mode 100644 packages/germs/.eslintrc.js delete mode 100644 packages/germs/src/index.test.ts delete mode 100644 packages/germs/src/index.ts delete mode 100644 packages/germs/src/shims/README.md create mode 100644 packages/shims/.eslintrc.js rename packages/{germs => shims}/CHANGELOG.md (100%) rename packages/{germs => shims}/README.md (59%) rename packages/{germs => shims}/jest.config.js (100%) rename packages/{germs => shims}/package.json (54%) rename packages/{germs/scripts/bundle-shims.mjs => shims/scripts/bundle.mjs} (72%) rename packages/{germs/src/shims => shims/src}/apply-lockdown.mjs (100%) rename packages/{germs/src/shims => shims/src}/endoify.mjs (100%) rename packages/{germs/src/shims => shims/src}/eventual-send.mjs (100%) rename packages/{germs => shims}/tsconfig.build.json (76%) rename packages/{germs => shims}/tsconfig.json (100%) rename packages/{germs => shims}/typedoc.json (100%) diff --git a/constraints.pro b/constraints.pro index cb3cec12e..b95db8c8f 100644 --- a/constraints.pro +++ b/constraints.pro @@ -208,10 +208,10 @@ gen_enforced_field(WorkspaceCwd, 'module', './dist/index.mjs') :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify an entrypoint. gen_enforced_field(WorkspaceCwd, 'main', null) :- - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', workspace_field(WorkspaceCwd, 'private', true). gen_enforced_field(WorkspaceCwd, 'module', null) :- - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', workspace_field(WorkspaceCwd, 'private', true). % The type definitions entrypoint for all publishable packages must be the same. @@ -219,7 +219,7 @@ gen_enforced_field(WorkspaceCwd, 'types', './dist/index.d.cts') :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify a type definitions entrypoint. gen_enforced_field(WorkspaceCwd, 'types', null) :- - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', workspace_field(WorkspaceCwd, 'private', true). % The exports for all published packages must be the same. @@ -238,7 +238,7 @@ gen_enforced_field(WorkspaceCwd, 'exports["./package.json"]', './package.json') \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify exports. gen_enforced_field(WorkspaceCwd, 'exports', null) :- - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', workspace_field(WorkspaceCwd, 'private', true). % Published packages must not have side effects. @@ -246,7 +246,7 @@ gen_enforced_field(WorkspaceCwd, 'sideEffects', false) :- \+ workspace_field(WorkspaceCwd, 'private', true). % Non-published packages must not specify side effects. gen_enforced_field(WorkspaceCwd, 'sideEffects', null) :- - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', workspace_field(WorkspaceCwd, 'private', true). % The list of files included in published packages must only include files @@ -262,7 +262,7 @@ gen_enforced_field(WorkspaceCwd, 'files', []) :- % All packages except the root and extension must have the same "build" script. gen_enforced_field(WorkspaceCwd, 'scripts.build', 'ts-bridge --project tsconfig.build.json --clean') :- WorkspaceCwd \= 'packages/extension', - WorkspaceCwd \= 'packages/germs', + WorkspaceCwd \= 'packages/shims', WorkspaceCwd \= '.'. % All packages except the root and extension must have the same "build:docs" script. diff --git a/packages/extension/package.json b/packages/extension/package.json index 3786735a2..c4acac439 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -25,7 +25,7 @@ }, "dependencies": { "@endo/lockdown": "^1.0.7", - "@ocap/germs": "^0.0.0", + "@ocap/shims": "^0.0.0", "ses": "^1.5.0" }, "devDependencies": { diff --git a/packages/extension/tsconfig.build.json b/packages/extension/tsconfig.build.json index 428b08ab0..26f46029b 100644 --- a/packages/extension/tsconfig.build.json +++ b/packages/extension/tsconfig.build.json @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "references": [{ "path": "../germs/tsconfig.build.json" }] + "references": [{ "path": "../shims/tsconfig.build.json" }] } diff --git a/packages/extension/vite.config.mts b/packages/extension/vite.config.mts index 6f1a50f0e..4003ba26c 100644 --- a/packages/extension/vite.config.mts +++ b/packages/extension/vite.config.mts @@ -32,8 +32,8 @@ export default defineConfig({ targets: [ { src: 'manifest.json', dest: './' }, { src: 'dev-console.mjs', dest: './' }, - { src: '../../germs/dist/shims/endoify.mjs', dest: './' }, - { src: '../../germs/dist/shims/eventual-send.mjs', dest: './' }, + { src: '../../shims/dist/endoify.mjs', dest: './' }, + { src: '../../shims/dist/eventual-send.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/ses.mjs', dest: './' }, { src: '../../../node_modules/ses/dist/lockdown.mjs', dest: './' }, ], diff --git a/packages/germs/.eslintrc.js b/packages/germs/.eslintrc.js deleted file mode 100644 index 48c28e5f1..000000000 --- a/packages/germs/.eslintrc.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - extends: ['../../.eslintrc.js'], - - ignorePatterns: ['**/shims/*.mjs'], -}; diff --git a/packages/germs/src/index.test.ts b/packages/germs/src/index.test.ts deleted file mode 100644 index bc062d369..000000000 --- a/packages/germs/src/index.test.ts +++ /dev/null @@ -1,9 +0,0 @@ -import greeter from '.'; - -describe('Test', () => { - it('greets', () => { - const name = 'Huey'; - const result = greeter(name); - expect(result).toBe('Hello, Huey!'); - }); -}); diff --git a/packages/germs/src/index.ts b/packages/germs/src/index.ts deleted file mode 100644 index 6972c1172..000000000 --- a/packages/germs/src/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/** - * Example function that returns a greeting for the given name. - * - * @param name - The name to greet. - * @returns The greeting. - */ -export default function greeter(name: string): string { - return `Hello, ${name}!`; -} diff --git a/packages/germs/src/shims/README.md b/packages/germs/src/shims/README.md deleted file mode 100644 index afe45d575..000000000 --- a/packages/germs/src/shims/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Shims - -For storing plain JavaScript shims that we want to import statically, such as `lockdown` and `eventual-send`. diff --git a/packages/shims/.eslintrc.js b/packages/shims/.eslintrc.js new file mode 100644 index 000000000..4bdcd0aca --- /dev/null +++ b/packages/shims/.eslintrc.js @@ -0,0 +1,17 @@ +module.exports = { + extends: ['../../.eslintrc.js'], + + ignorePatterns: ['src/eventual-send.mjs'], + + overrides: [ + { + files: ['src/**/*.mjs'], + globals: { lockdown: 'readonly' }, + rules: { + 'import/extensions': 'off', + 'import/no-unassigned-import': 'off', + 'import/no-unresolved': 'off', + }, + }, + ], +}; diff --git a/packages/germs/CHANGELOG.md b/packages/shims/CHANGELOG.md similarity index 100% rename from packages/germs/CHANGELOG.md rename to packages/shims/CHANGELOG.md diff --git a/packages/germs/README.md b/packages/shims/README.md similarity index 59% rename from packages/germs/README.md rename to packages/shims/README.md index 974894c2d..82683d3aa 100644 --- a/packages/germs/README.md +++ b/packages/shims/README.md @@ -1,6 +1,6 @@ -# `@ocap/germs` +# `@ocap/shims` -From these germs, a Kernel will form. +Shims for ocap programming that we want to import statically, such as `lockdown` and `eventual-send`. ## Contributing diff --git a/packages/germs/jest.config.js b/packages/shims/jest.config.js similarity index 100% rename from packages/germs/jest.config.js rename to packages/shims/jest.config.js diff --git a/packages/germs/package.json b/packages/shims/package.json similarity index 54% rename from packages/germs/package.json rename to packages/shims/package.json index a2dea1e7d..39dd9e324 100644 --- a/packages/germs/package.json +++ b/packages/shims/package.json @@ -1,39 +1,28 @@ { - "name": "@ocap/germs", + "name": "@ocap/shims", "version": "0.0.0", "private": true, - "description": "From these germs, a Kernel will form", + "description": "Shims for ocap programming", "repository": { "type": "git", "url": "https://github.com/MetaMask/ocap-kernel.git" }, "sideEffects": false, "exports": { - ".": { - "import": { - "types": "./dist/index.d.mts", - "default": "./dist/index.mjs" - }, - "require": { - "types": "./dist/index.d.cts", - "default": "./dist/index.cjs" - } - }, - "./shims": "./dist/shims", + "./apply-lockdown": "./dist/apply-lockdown.mjs", + "./endoify": "./dist/endoify.mjs", + "./eventual-send": "./dist/eventual-send.mjs", "./package.json": "./package.json" }, "main": "./dist/index.cjs", "module": "./dist/index.mjs", - "types": "./dist/index.d.cts", "files": [ "dist" ], "scripts": { - "build": "yarn clean && yarn build:typescript && yarn build:shims", + "build": "node scripts/bundle.mjs", "build:docs": "typedoc", - "build:shims": "node scripts/bundle-shims.mjs", - "build:typescript": "ts-bridge --project tsconfig.build.json --clean", - "changelog:validate": "../../scripts/validate-changelog.sh @ocap/germs", + "changelog:validate": "../../scripts/validate-changelog.sh @ocap/shims", "clean": "rimraf ./dist", "publish:preview": "yarn npm publish --tag preview", "test": "jest --reporters=jest-silent-reporter", @@ -47,19 +36,12 @@ "ses": "^1.5.0" }, "devDependencies": { - "@arethetypeswrong/cli": "^0.15.3", "@metamask/auto-changelog": "^3.4.4", - "@ts-bridge/cli": "^0.1.4", - "@ts-bridge/shims": "^0.1.1", "@types/jest": "^28.1.6", "deepmerge": "^4.3.1", "jest": "^28.1.3", "mkdirp": "^3.0.1", - "rimraf": "^6.0.1", - "ts-jest": "^28.0.7", - "typedoc": "^0.24.8", - "typedoc-plugin-missing-exports": "^2.0.0", - "typescript": "~4.9.5" + "rimraf": "^6.0.1" }, "engines": { "node": "^18.18 || >=20" diff --git a/packages/germs/scripts/bundle-shims.mjs b/packages/shims/scripts/bundle.mjs similarity index 72% rename from packages/germs/scripts/bundle-shims.mjs rename to packages/shims/scripts/bundle.mjs index 06ebf3c29..7c7232a7b 100644 --- a/packages/germs/scripts/bundle-shims.mjs +++ b/packages/shims/scripts/bundle.mjs @@ -10,8 +10,8 @@ import { rimraf } from 'rimraf'; console.log('Bundling shims...'); const rootDir = path.resolve(import.meta.dirname, '..'); -const shimsSrc = path.resolve(rootDir, 'src/shims'); -const shimsDist = path.resolve(rootDir, 'dist/shims'); +const src = path.resolve(rootDir, 'src'); +const dist = path.resolve(rootDir, 'dist'); // const eventualSendSrc = path.resolve(rootDir, '../../node_modules/@endo/eventual-send/shim.js'); @@ -21,14 +21,11 @@ const fileNames = { lockdown: 'apply-lockdown.mjs', }; -await mkdirp(shimsDist); -await rimraf(`${shimsDist}/*`); +await mkdirp(dist); +await rimraf(`${dist}/*`); for (const fileName of Object.values(fileNames)) { - await copyFile( - path.resolve(shimsSrc, fileName), - path.resolve(shimsDist, fileName), - ); + await copyFile(path.resolve(src, fileName), path.resolve(dist, fileName)); } // const { source } = await bundleSource(eventualSendSrc, { format: 'endoScript' }); diff --git a/packages/germs/src/shims/apply-lockdown.mjs b/packages/shims/src/apply-lockdown.mjs similarity index 100% rename from packages/germs/src/shims/apply-lockdown.mjs rename to packages/shims/src/apply-lockdown.mjs diff --git a/packages/germs/src/shims/endoify.mjs b/packages/shims/src/endoify.mjs similarity index 100% rename from packages/germs/src/shims/endoify.mjs rename to packages/shims/src/endoify.mjs diff --git a/packages/germs/src/shims/eventual-send.mjs b/packages/shims/src/eventual-send.mjs similarity index 100% rename from packages/germs/src/shims/eventual-send.mjs rename to packages/shims/src/eventual-send.mjs diff --git a/packages/germs/tsconfig.build.json b/packages/shims/tsconfig.build.json similarity index 76% rename from packages/germs/tsconfig.build.json rename to packages/shims/tsconfig.build.json index 1a4b71624..c622f4091 100644 --- a/packages/germs/tsconfig.build.json +++ b/packages/shims/tsconfig.build.json @@ -6,6 +6,5 @@ "rootDir": "./src" }, "references": [], - "include": ["./src"], - "exclude": ["./src/shims"] + "include": ["./src"] } diff --git a/packages/germs/tsconfig.json b/packages/shims/tsconfig.json similarity index 100% rename from packages/germs/tsconfig.json rename to packages/shims/tsconfig.json diff --git a/packages/germs/typedoc.json b/packages/shims/typedoc.json similarity index 100% rename from packages/germs/typedoc.json rename to packages/shims/typedoc.json diff --git a/tsconfig.build.json b/tsconfig.build.json index 14e9b8b63..5107ebe6e 100644 --- a/tsconfig.build.json +++ b/tsconfig.build.json @@ -3,6 +3,6 @@ "include": [], "references": [ { "path": "./packages/extension/tsconfig.build.json" }, - { "path": "./packages/germs/tsconfig.build.json" } + { "path": "./packages/shims/tsconfig.build.json" } ] } diff --git a/tsconfig.json b/tsconfig.json index 13c37aad1..1e0c7163e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -8,6 +8,6 @@ "include": [], "references": [ { "path": "./packages/extension" }, - { "path": "./packages/germs" } + { "path": "./packages/shims" } ] } diff --git a/yarn.lock b/yarn.lock index ed66a188d..a6f57356c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1325,7 +1325,7 @@ __metadata: "@arethetypeswrong/cli": "npm:^0.15.3" "@endo/lockdown": "npm:^1.0.7" "@metamask/auto-changelog": "npm:^3.4.4" - "@ocap/germs": "npm:^0.0.0" + "@ocap/shims": "npm:^0.0.0" "@types/chrome": "npm:^0.0.268" "@types/jest": "npm:^28.1.6" deepmerge: "npm:^4.3.1" @@ -1341,29 +1341,6 @@ __metadata: languageName: unknown linkType: soft -"@ocap/germs@npm:^0.0.0, @ocap/germs@workspace:packages/germs": - version: 0.0.0-use.local - resolution: "@ocap/germs@workspace:packages/germs" - dependencies: - "@arethetypeswrong/cli": "npm:^0.15.3" - "@endo/eventual-send": "npm:^1.2.2" - "@endo/lockdown": "npm:^1.0.7" - "@metamask/auto-changelog": "npm:^3.4.4" - "@ts-bridge/cli": "npm:^0.1.4" - "@ts-bridge/shims": "npm:^0.1.1" - "@types/jest": "npm:^28.1.6" - deepmerge: "npm:^4.3.1" - jest: "npm:^28.1.3" - mkdirp: "npm:^3.0.1" - rimraf: "npm:^6.0.1" - ses: "npm:^1.5.0" - ts-jest: "npm:^28.0.7" - typedoc: "npm:^0.24.8" - typedoc-plugin-missing-exports: "npm:^2.0.0" - typescript: "npm:~4.9.5" - languageName: unknown - linkType: soft - "@ocap/monorepo@workspace:.": version: 0.0.0-use.local resolution: "@ocap/monorepo@workspace:." @@ -1403,6 +1380,29 @@ __metadata: languageName: unknown linkType: soft +"@ocap/shims@npm:^0.0.0, @ocap/shims@workspace:packages/shims": + version: 0.0.0-use.local + resolution: "@ocap/shims@workspace:packages/shims" + dependencies: + "@arethetypeswrong/cli": "npm:^0.15.3" + "@endo/eventual-send": "npm:^1.2.2" + "@endo/lockdown": "npm:^1.0.7" + "@metamask/auto-changelog": "npm:^3.4.4" + "@ts-bridge/cli": "npm:^0.1.4" + "@ts-bridge/shims": "npm:^0.1.1" + "@types/jest": "npm:^28.1.6" + deepmerge: "npm:^4.3.1" + jest: "npm:^28.1.3" + mkdirp: "npm:^3.0.1" + rimraf: "npm:^6.0.1" + ses: "npm:^1.5.0" + ts-jest: "npm:^28.0.7" + typedoc: "npm:^0.24.8" + typedoc-plugin-missing-exports: "npm:^2.0.0" + typescript: "npm:~4.9.5" + languageName: unknown + linkType: soft + "@pkgjs/parseargs@npm:^0.11.0": version: 0.11.0 resolution: "@pkgjs/parseargs@npm:0.11.0" From fe450ca54128d9bda92783030e63b42c7a3518e8 Mon Sep 17 00:00:00 2001 From: Erik Marks Date: Tue, 23 Jul 2024 10:29:38 +0200 Subject: [PATCH 21/31] feat: Expose Compartment.evaluate() via dev console Adds `kernel.evaluate()` method to dev console, which causes the provided source string to be evaluated within a Compartment in an iframe attached to the offscreen document. This is the same approach used to evaluate Snaps in the MetaMask extension, as well as Google's recommended way to use `eval()` as an MV3 extension. --- .eslintrc.js | 11 + packages/extension/.eslintrc.js | 6 +- packages/extension/package.json | 3 + packages/extension/src/background.ts | 30 +- packages/extension/src/iframe-manager.ts | 110 ++++ packages/extension/src/iframe.html | 11 + packages/extension/src/iframe.ts | 94 +++ packages/extension/src/manifest.json | 9 +- packages/extension/src/offscreen.html | 11 +- packages/extension/src/offscreen.ts | 50 +- packages/extension/src/shared.ts | 31 +- packages/extension/tsconfig.json | 3 +- packages/extension/vite.config.mts | 1 + packages/shims/src/apply-lockdown.mjs | 5 +- yarn.lock | 763 ++++++++++++++++++++++- 15 files changed, 1088 insertions(+), 50 deletions(-) create mode 100644 packages/extension/src/iframe-manager.ts create mode 100644 packages/extension/src/iframe.html create mode 100644 packages/extension/src/iframe.ts diff --git a/.eslintrc.js b/.eslintrc.js index 65325c886..3d4aa04b7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -68,6 +68,17 @@ module.exports = { }, rules: { '@typescript-eslint/no-explicit-any': 'error', + + // This rule is broken, and without the `allowAny` option, it causes + // a lot of false positives. + '@typescript-eslint/restrict-template-expressions': [ + 'error', + { + allowAny: true, + allowBoolean: true, + allowNumber: true, + }, + ], }, }, diff --git a/packages/extension/.eslintrc.js b/packages/extension/.eslintrc.js index a5d78dc80..f80c40260 100644 --- a/packages/extension/.eslintrc.js +++ b/packages/extension/.eslintrc.js @@ -4,7 +4,11 @@ module.exports = { overrides: [ { files: ['src/**/*.js'], - globals: { chrome: 'readonly', clients: 'readonly' }, + globals: { + chrome: 'readonly', + clients: 'readonly', + Compartment: 'readonly', + }, }, { diff --git a/packages/extension/package.json b/packages/extension/package.json index c4acac439..881eaf242 100644 --- a/packages/extension/package.json +++ b/packages/extension/package.json @@ -25,6 +25,9 @@ }, "dependencies": { "@endo/lockdown": "^1.0.7", + "@endo/promise-kit": "^1.1.2", + "@metamask/snaps-utils": "^7.8.0", + "@metamask/utils": "^9.1.0", "@ocap/shims": "^0.0.0", "ses": "^1.5.0" }, diff --git a/packages/extension/src/background.ts b/packages/extension/src/background.ts index cf4e9c7ef..7ffa31e75 100644 --- a/packages/extension/src/background.ts +++ b/packages/extension/src/background.ts @@ -4,20 +4,26 @@ import './endoify.mjs'; /* eslint-enable import/extensions,import/no-unassigned-import */ import type { ExtensionMessage } from './shared'; -import { Command, Reply, makeHandledCallback } from './shared'; +import { Command, makeHandledCallback } from './shared'; // globalThis.kernel will exist due to dev-console.mjs Object.defineProperties(globalThis.kernel, { sendMessage: { value: sendMessage, }, + evaluate: { + value: async (source: string) => sendMessage(Command.Evaluate, source), + }, + ping: { + value: async () => sendMessage(Command.Ping), + }, }); const OFFSCREEN_DOCUMENT_PATH = '/offscreen.html'; // With this we can click the extension action button to wake up the service worker. chrome.action.onClicked.addListener(() => { - sendMessage(Command.Ping, { name: 'Kernel' }).catch(console.error); + sendMessage(Command.Ping).catch(console.error); }); /** @@ -26,13 +32,13 @@ chrome.action.onClicked.addListener(() => { * @param data - The message data. * @param data.name - The name to include in the message. */ -async function sendMessage(type: string, data: { name: string }) { +async function sendMessage(type: string, data?: string) { await provideOffScreenDocument(); await chrome.runtime.sendMessage({ type, target: 'offscreen', - data, + data: data ?? null, }); } @@ -56,19 +62,25 @@ chrome.runtime.onMessage.addListener(makeHandledCallback(handleMessage)); * Receive a message from the offscreen document. * @param message - The message to handle. */ -async function handleMessage(message: ExtensionMessage) { +async function handleMessage(message: ExtensionMessage) { if (message.target !== 'background') { + console.warn( + `Background received message with unexpected target: "${message.target}"`, + ); return; } switch (message.type) { - case Reply.Pong: - console.log(Reply.Pong); + case Command.Evaluate: + case Command.Ping: + console.log(message.data); await closeOffscreenDocument(); break; default: - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions - console.error(`Received unexpected message type: "${message.type}"`); + console.error( + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + `Background received unexpected message type: "${message.type}"`, + ); } } diff --git a/packages/extension/src/iframe-manager.ts b/packages/extension/src/iframe-manager.ts new file mode 100644 index 000000000..53b98c460 --- /dev/null +++ b/packages/extension/src/iframe-manager.ts @@ -0,0 +1,110 @@ +import type { PromiseKit } from '@endo/promise-kit'; +import { makePromiseKit } from '@endo/promise-kit'; +import { createWindow } from '@metamask/snaps-utils'; + +import type { IframeMessage } from './shared'; +import { Command, isWrappedIframeMessage } from './shared'; + +const URI = 'iframe.html'; + +// The actual