Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 | import { JsonRpcServer } from '@metamask/json-rpc-engine/v2';
import { makeSQLKernelDatabase } from '@metamask/kernel-store/sqlite/wasm';
import { isJsonRpcMessage, stringify } from '@metamask/kernel-utils';
import type { JsonRpcMessage } from '@metamask/kernel-utils';
import { Logger } from '@metamask/logger';
import { Kernel } from '@metamask/ocap-kernel';
import type { PostMessageTarget } from '@metamask/streams/browser';
import {
MessagePortDuplexStream,
receiveMessagePort,
} from '@metamask/streams/browser';
import {
isCapTPNotification,
makeCapTPNotification,
} from '../background-captp.ts';
import type { CapTPMessage } from '../background-captp.ts';
import { receiveInternalConnections } from '../internal-comms/internal-connections.ts';
import { PlatformServicesClient } from '../PlatformServicesClient.ts';
import { setupConsoleForwarding } from '../utils/console-forwarding.ts';
import { makeKernelCapTP } from './captp/index.ts';
import { makeLoggingMiddleware } from './middleware/logging.ts';
import { makePanelMessageMiddleware } from './middleware/panel-message.ts';
import { getRelaysFromCurrentLocation } from '../utils/relay-query-string.ts';
const logger = new Logger('kernel-worker');
const DB_FILENAME = 'store.db';
main().catch(logger.error);
/**
* Run the kernel.
*/
async function main(): Promise<void> {
const port = await receiveMessagePort(
(listener) => globalThis.addEventListener('message', listener),
(listener) => globalThis.removeEventListener('message', listener),
);
const [messageStream, platformServicesClient, kernelDatabase] =
await Promise.all([
MessagePortDuplexStream.make<JsonRpcMessage, JsonRpcMessage>(
port,
isJsonRpcMessage,
),
PlatformServicesClient.make(globalThis as PostMessageTarget),
makeSQLKernelDatabase({ dbFilename: DB_FILENAME }),
]);
// Set up console forwarding - messages flow through offscreen to background
setupConsoleForwarding({
source: 'kernel-worker',
onMessage: (message) => {
messageStream.write(message).catch(() => undefined);
},
});
const resetStorage =
new URLSearchParams(globalThis.location.search).get('reset-storage') ===
'true';
const kernelP = Kernel.make(platformServicesClient, kernelDatabase, {
resetStorage,
});
const handlerP = kernelP.then((kernel) => {
const server = new JsonRpcServer({
middleware: [
makeLoggingMiddleware(logger.subLogger('internal-rpc')),
makePanelMessageMiddleware(kernel, kernelDatabase),
],
});
return async (request: JsonRpcMessage) => server.handle(request);
});
receiveInternalConnections({
handlerPromise: handlerP,
logger,
});
const kernel = await kernelP;
const kernelCapTP = makeKernelCapTP({
kernel,
send: (captpMessage: CapTPMessage) => {
const notification = makeCapTPNotification(captpMessage);
messageStream.write(notification).catch((error) => {
logger.error('Failed to send CapTP message:', error);
});
},
});
messageStream
.drain((message) => {
if (isCapTPNotification(message)) {
const captpMessage = message.params[0];
kernelCapTP.dispatch(captpMessage);
} else {
throw new Error(`Unexpected message: ${stringify(message)}`);
}
})
.catch((error) => {
kernelCapTP.abort(error);
logger.error('Message stream error:', error);
});
const relays = getRelaysFromCurrentLocation();
await kernel.initRemoteComms({ relays });
}
|