@ricsam/isolate 0.1.10 → 0.1.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +172 -18
- package/dist/cjs/bridge/diagnostics.cjs +37 -2
- package/dist/cjs/bridge/diagnostics.cjs.map +3 -3
- package/dist/cjs/bridge/runtime-bindings.cjs +203 -51
- package/dist/cjs/bridge/runtime-bindings.cjs.map +3 -3
- package/dist/cjs/bridge/sandbox-isolate.cjs +365 -0
- package/dist/cjs/bridge/sandbox-isolate.cjs.map +10 -0
- package/dist/cjs/host/create-isolate-host.cjs +51 -25
- package/dist/cjs/host/create-isolate-host.cjs.map +3 -3
- package/dist/cjs/host/nested-host-controller.cjs +311 -0
- package/dist/cjs/host/nested-host-controller.cjs.map +10 -0
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/internal/browser-source.cjs +91 -0
- package/dist/cjs/internal/browser-source.cjs.map +10 -0
- package/dist/cjs/internal/client/connection.cjs +152 -172
- package/dist/cjs/internal/client/connection.cjs.map +3 -3
- package/dist/cjs/internal/daemon/callback-fs-handler.cjs +3 -3
- package/dist/cjs/internal/daemon/callback-fs-handler.cjs.map +3 -3
- package/dist/cjs/internal/daemon/connection.cjs +129 -4
- package/dist/cjs/internal/daemon/connection.cjs.map +3 -3
- package/dist/cjs/internal/playwright/client.cjs +4 -2
- package/dist/cjs/internal/playwright/client.cjs.map +3 -3
- package/dist/cjs/internal/playwright/handler.cjs +298 -25
- package/dist/cjs/internal/playwright/handler.cjs.map +3 -3
- package/dist/cjs/internal/playwright/index.cjs +54 -8
- package/dist/cjs/internal/playwright/index.cjs.map +3 -3
- package/dist/cjs/internal/playwright/types.cjs +3 -1
- package/dist/cjs/internal/playwright/types.cjs.map +3 -3
- package/dist/cjs/internal/protocol/codec.cjs +16 -5
- package/dist/cjs/internal/protocol/codec.cjs.map +3 -3
- package/dist/cjs/internal/protocol/marshalValue.cjs +37 -6
- package/dist/cjs/internal/protocol/marshalValue.cjs.map +3 -3
- package/dist/cjs/internal/protocol/types.cjs.map +2 -2
- package/dist/cjs/internal/runtime/index.cjs +377 -22
- package/dist/cjs/internal/runtime/index.cjs.map +3 -3
- package/dist/cjs/internal/typecheck/index.cjs +2 -1
- package/dist/cjs/internal/typecheck/index.cjs.map +3 -3
- package/dist/cjs/internal/typecheck/isolate-types.cjs +186 -13
- package/dist/cjs/internal/typecheck/isolate-types.cjs.map +3 -3
- package/dist/cjs/internal/typecheck/typecheck.cjs +2 -3
- package/dist/cjs/internal/typecheck/typecheck.cjs.map +3 -3
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/runtime/script-runtime.cjs +14 -12
- package/dist/cjs/runtime/script-runtime.cjs.map +3 -3
- package/dist/cjs/runtime/test-runtime.cjs +113 -0
- package/dist/cjs/runtime/test-runtime.cjs.map +10 -0
- package/dist/cjs/server/app-server.cjs +16 -9
- package/dist/cjs/server/app-server.cjs.map +3 -3
- package/dist/cjs/typecheck/index.cjs +2 -1
- package/dist/cjs/typecheck/index.cjs.map +3 -3
- package/dist/mjs/bridge/diagnostics.mjs +37 -2
- package/dist/mjs/bridge/diagnostics.mjs.map +3 -3
- package/dist/mjs/bridge/runtime-bindings.mjs +206 -51
- package/dist/mjs/bridge/runtime-bindings.mjs.map +3 -3
- package/dist/mjs/bridge/sandbox-isolate.mjs +325 -0
- package/dist/mjs/bridge/sandbox-isolate.mjs.map +10 -0
- package/dist/mjs/host/create-isolate-host.mjs +53 -25
- package/dist/mjs/host/create-isolate-host.mjs.map +3 -3
- package/dist/mjs/host/nested-host-controller.mjs +275 -0
- package/dist/mjs/host/nested-host-controller.mjs.map +10 -0
- package/dist/mjs/index.mjs.map +1 -1
- package/dist/mjs/internal/browser-source.mjs +51 -0
- package/dist/mjs/internal/browser-source.mjs.map +10 -0
- package/dist/mjs/internal/client/connection.mjs +154 -173
- package/dist/mjs/internal/client/connection.mjs.map +3 -3
- package/dist/mjs/internal/daemon/callback-fs-handler.mjs +3 -3
- package/dist/mjs/internal/daemon/callback-fs-handler.mjs.map +3 -3
- package/dist/mjs/internal/daemon/connection.mjs +129 -4
- package/dist/mjs/internal/daemon/connection.mjs.map +3 -3
- package/dist/mjs/internal/playwright/client.mjs +7 -3
- package/dist/mjs/internal/playwright/client.mjs.map +3 -3
- package/dist/mjs/internal/playwright/handler.mjs +300 -26
- package/dist/mjs/internal/playwright/handler.mjs.map +3 -3
- package/dist/mjs/internal/playwright/index.mjs +59 -9
- package/dist/mjs/internal/playwright/index.mjs.map +3 -3
- package/dist/mjs/internal/playwright/types.mjs +3 -1
- package/dist/mjs/internal/playwright/types.mjs.map +3 -3
- package/dist/mjs/internal/protocol/codec.mjs +16 -5
- package/dist/mjs/internal/protocol/codec.mjs.map +3 -3
- package/dist/mjs/internal/protocol/marshalValue.mjs +38 -6
- package/dist/mjs/internal/protocol/marshalValue.mjs.map +3 -3
- package/dist/mjs/internal/protocol/types.mjs.map +2 -2
- package/dist/mjs/internal/runtime/index.mjs +377 -22
- package/dist/mjs/internal/runtime/index.mjs.map +3 -3
- package/dist/mjs/internal/typecheck/index.mjs +3 -1
- package/dist/mjs/internal/typecheck/index.mjs.map +3 -3
- package/dist/mjs/internal/typecheck/isolate-types.mjs +186 -13
- package/dist/mjs/internal/typecheck/isolate-types.mjs.map +3 -3
- package/dist/mjs/internal/typecheck/typecheck.mjs +2 -3
- package/dist/mjs/internal/typecheck/typecheck.mjs.map +3 -3
- package/dist/mjs/package.json +1 -1
- package/dist/mjs/runtime/script-runtime.mjs +16 -12
- package/dist/mjs/runtime/script-runtime.mjs.map +3 -3
- package/dist/mjs/runtime/test-runtime.mjs +78 -0
- package/dist/mjs/runtime/test-runtime.mjs.map +10 -0
- package/dist/mjs/server/app-server.mjs +23 -11
- package/dist/mjs/server/app-server.mjs.map +3 -3
- package/dist/mjs/typecheck/index.mjs +2 -1
- package/dist/mjs/typecheck/index.mjs.map +3 -3
- package/dist/types/bridge/diagnostics.d.ts +6 -1
- package/dist/types/bridge/runtime-bindings.d.ts +5 -1
- package/dist/types/bridge/sandbox-isolate.d.ts +15 -0
- package/dist/types/host/nested-host-controller.d.ts +11 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/internal/browser-source.d.ts +11 -0
- package/dist/types/internal/client/types.d.ts +5 -0
- package/dist/types/internal/daemon/types.d.ts +0 -2
- package/dist/types/internal/playwright/client.d.ts +2 -2
- package/dist/types/internal/playwright/handler.d.ts +27 -4
- package/dist/types/internal/playwright/index.d.ts +2 -2
- package/dist/types/internal/playwright/types.d.ts +33 -1
- package/dist/types/internal/protocol/codec.d.ts +12 -2
- package/dist/types/internal/protocol/marshalValue.d.ts +3 -2
- package/dist/types/internal/protocol/types.d.ts +25 -1
- package/dist/types/internal/runtime/index.d.ts +5 -0
- package/dist/types/internal/typecheck/index.d.ts +1 -1
- package/dist/types/internal/typecheck/isolate-types.d.ts +6 -4
- package/dist/types/internal/typecheck/typecheck.d.ts +1 -1
- package/dist/types/runtime/script-runtime.d.ts +2 -1
- package/dist/types/runtime/test-runtime.d.ts +4 -0
- package/dist/types/server/app-server.d.ts +2 -1
- package/dist/types/types.d.ts +33 -33
- package/package.json +3 -3
- package/dist/cjs/browser/browser-runtime.cjs +0 -157
- package/dist/cjs/browser/browser-runtime.cjs.map +0 -10
- package/dist/mjs/browser/browser-runtime.mjs +0 -93
- package/dist/mjs/browser/browser-runtime.mjs.map +0 -10
- package/dist/types/browser/browser-runtime.d.ts +0 -3
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/internal/protocol/types.ts"],
|
|
4
4
|
"sourcesContent": [
|
|
5
|
-
"/**\n * Message types for the isolate daemon protocol.\n *\n * Frame format:\n * ┌──────────┬──────────┬─────────────────┐\n * │ Length │ Type │ Payload │\n * │ (4 bytes)│ (1 byte) │ (MessagePack) │\n * └──────────┴──────────┴─────────────────┘\n */\n\n// ============================================================================\n// Message Type Constants\n// ============================================================================\n\nexport const MessageType = {\n // Client → Daemon: Runtime management\n CREATE_RUNTIME: 0x01,\n DISPOSE_RUNTIME: 0x02,\n EVAL: 0x03,\n DISPATCH_REQUEST: 0x04,\n DISPATCH_REQUEST_ABORT: 0x05,\n\n // Client → Daemon: WebSocket operations\n WS_OPEN: 0x10,\n WS_MESSAGE: 0x11,\n WS_CLOSE: 0x12,\n\n // Client → Daemon: Handle operations\n FETCH_GET_UPGRADE_REQUEST: 0x13,\n FETCH_HAS_SERVE_HANDLER: 0x14,\n FETCH_HAS_ACTIVE_CONNECTIONS: 0x15,\n FETCH_WS_ERROR: 0x16,\n TIMERS_CLEAR_ALL: 0x17,\n CONSOLE_RESET: 0x18,\n CONSOLE_GET_TIMERS: 0x19,\n CONSOLE_GET_COUNTERS: 0x1a,\n CONSOLE_GET_GROUP_DEPTH: 0x1b,\n\n // Client → Daemon: Test environment\n RUN_TESTS: 0x21,\n RESET_TEST_ENV: 0x22,\n HAS_TESTS: 0x23,\n GET_TEST_COUNT: 0x24,\n\n // Client → Daemon: Playwright\n GET_COLLECTED_DATA: 0x33,\n CLEAR_COLLECTED_DATA: 0x34,\n\n // Daemon → Client: Responses\n RESPONSE_OK: 0x80,\n RESPONSE_ERROR: 0x81,\n RESPONSE_STREAM_START: 0x82,\n RESPONSE_STREAM_CHUNK: 0x83,\n RESPONSE_STREAM_END: 0x84,\n\n // Bidirectional: Callbacks\n CALLBACK_INVOKE: 0x90,\n CALLBACK_RESPONSE: 0x91,\n CALLBACK_STREAM_START: 0x92,\n CALLBACK_STREAM_CHUNK: 0x93,\n CALLBACK_STREAM_END: 0x94,\n CALLBACK_STREAM_CANCEL: 0x95,\n CALLBACK_ABORT: 0x96,\n\n // Bidirectional: Stream data\n STREAM_PUSH: 0xa0,\n STREAM_PULL: 0xa1,\n STREAM_CLOSE: 0xa2,\n STREAM_ERROR: 0xa3,\n\n // Bidirectional: Generic events\n ISOLATE_EVENT: 0xc0, // daemon → client\n CLIENT_EVENT: 0xc1, // client → daemon\n\n // Heartbeat\n PING: 0xf0,\n PONG: 0xf1,\n} as const;\n\nexport type MessageType = (typeof MessageType)[keyof typeof MessageType];\n\n/** Reverse lookup for message type names */\nexport const MessageTypeName: Record<number, string> = Object.fromEntries(\n Object.entries(MessageType).map(([k, v]) => [v, k])\n);\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\nexport const ErrorCode = {\n // Protocol errors\n INVALID_MESSAGE: 1001,\n UNKNOWN_MESSAGE_TYPE: 1002,\n MISSING_REQUIRED_FIELD: 1003,\n\n // Isolate errors\n ISOLATE_NOT_FOUND: 2001,\n ISOLATE_DISPOSED: 2002,\n ISOLATE_MEMORY_LIMIT: 2003,\n ISOLATE_TIMEOUT: 2004,\n\n // Execution errors\n SCRIPT_ERROR: 3001,\n CALLBACK_ERROR: 3002,\n\n // Stream errors\n STREAM_NOT_FOUND: 4001,\n STREAM_CLOSED: 4002,\n\n // Connection errors\n CONNECTION_LOST: 5001,\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n// ============================================================================\n// Base Message Interface\n// ============================================================================\n\nexport interface BaseMessage {\n /** Unique request ID for correlation */\n requestId: number;\n}\n\n// ============================================================================\n// Callback Registration\n// ============================================================================\n\n/** Custom function type indicator */\nexport type CustomFunctionType = 'sync' | 'async' | 'asyncIterator';\n\nexport interface CallbackRegistration {\n /** Unique ID for this callback */\n callbackId: number;\n /** Callback name (e.g., \"log\", \"warn\", \"fetch\") */\n name: string;\n /** Function type: sync, async, or asyncIterator */\n type: CustomFunctionType;\n}\n\nexport interface ConsoleCallbackRegistrations {\n onEntry?: CallbackRegistration;\n}\n\nexport interface FsCallbackRegistrations {\n readFile?: CallbackRegistration;\n writeFile?: CallbackRegistration;\n unlink?: CallbackRegistration;\n readdir?: CallbackRegistration;\n mkdir?: CallbackRegistration;\n rmdir?: CallbackRegistration;\n stat?: CallbackRegistration;\n rename?: CallbackRegistration;\n}\n\nexport interface CustomFunctionRegistrations {\n [name: string]: CallbackRegistration;\n}\n\n// ============================================================================\n// Playwright Callback Types\n// ============================================================================\n\n/**\n * Playwright operation sent from daemon to client via callback.\n * The client executes this operation on the real Page object.\n */\nexport interface PlaywrightOperation {\n type:\n | \"goto\"\n | \"reload\"\n | \"url\"\n | \"title\"\n | \"content\"\n | \"waitForSelector\"\n | \"waitForTimeout\"\n | \"waitForLoadState\"\n | \"evaluate\"\n | \"locatorAction\"\n | \"expectLocator\"\n | \"expectPage\"\n | \"request\"\n | \"goBack\"\n | \"goForward\"\n | \"waitForURL\"\n | \"waitForURLPredicate\"\n | \"waitForRequestStart\"\n | \"waitForRequestFinish\"\n | \"waitForRequestPredicateFinish\"\n | \"waitForResponseStart\"\n | \"waitForResponseFinish\"\n | \"waitForResponsePredicateFinish\"\n | \"clearCookies\"\n // Page-level operations\n | \"screenshot\"\n | \"setViewportSize\"\n | \"viewportSize\"\n | \"emulateMedia\"\n | \"setExtraHTTPHeaders\"\n | \"bringToFront\"\n | \"close\"\n | \"isClosed\"\n | \"pdf\"\n | \"pause\"\n | \"frames\"\n | \"mainFrame\"\n // Keyboard operations\n | \"keyboardType\"\n | \"keyboardPress\"\n | \"keyboardDown\"\n | \"keyboardUp\"\n | \"keyboardInsertText\"\n // Mouse operations\n | \"mouseMove\"\n | \"mouseClick\"\n | \"mouseDown\"\n | \"mouseUp\"\n | \"mouseWheel\"\n // Cookie operations\n | \"addCookies\"\n | \"cookies\"\n // Browser/Context lifecycle operations\n | \"newContext\"\n | \"newPage\"\n | \"closeContext\";\n args: unknown[];\n /** Target page ID (undefined = default page \"page_0\") */\n pageId?: string;\n /** Target context ID (undefined = default context \"ctx_0\") */\n contextId?: string;\n}\n\n/**\n * Result of a playwright operation.\n */\nexport type PlaywrightResult =\n | { ok: true; value?: unknown }\n | { ok: false; error: { name: string; message: string } };\n\n/**\n * Callback registrations for playwright operations.\n */\nexport interface PlaywrightCallbackRegistration {\n /** Callback ID for page operations */\n handlerCallbackId: number;\n /** If true, browser console logs are printed to stdout */\n console?: boolean;\n /** Optional callback for browser console log events (from the page, not sandbox) */\n onBrowserConsoleLogCallbackId?: number;\n /** Optional callback for network request events */\n onNetworkRequestCallbackId?: number;\n /** Optional callback for network response events */\n onNetworkResponseCallbackId?: number;\n}\n\n// ============================================================================\n// Runtime Callback Registrations\n// ============================================================================\n\nexport interface RuntimeCallbackRegistrations {\n console?: ConsoleCallbackRegistrations;\n fetch?: CallbackRegistration;\n fs?: FsCallbackRegistrations;\n moduleLoader?: CallbackRegistration;\n custom?: CustomFunctionRegistrations;\n playwright?: PlaywrightCallbackRegistration;\n}\n\n// ============================================================================\n// Client → Daemon Messages\n// ============================================================================\n\nexport interface TestEnvironmentCallbackRegistrations {\n /** Callback for test events */\n onEvent?: CallbackRegistration;\n}\n\nexport interface TestEnvironmentOptionsProtocol {\n /** Callback registrations for test events */\n callbacks?: TestEnvironmentCallbackRegistrations;\n /** Timeout for individual tests (ms) */\n testTimeout?: number;\n}\n\nexport interface PlaywrightOptionsProtocol {\n /** Default timeout for Playwright operations in ms */\n timeout?: number;\n}\n\nexport interface CreateRuntimeRequest extends BaseMessage {\n type: typeof MessageType.CREATE_RUNTIME;\n options: {\n memoryLimitMB?: number;\n executionTimeout?: number;\n callbacks?: RuntimeCallbackRegistrations;\n /** Current working directory for path.resolve(). Defaults to \"/\" */\n cwd?: string;\n /** Enable test environment (describe, it, expect, etc.) */\n testEnvironment?: boolean | TestEnvironmentOptionsProtocol;\n /** Playwright runtime options */\n playwright?: PlaywrightOptionsProtocol;\n /** Namespace ID for runtime pooling/reuse. If provided, runtime will be cached on dispose. */\n namespaceId?: string;\n };\n}\n\nexport interface DisposeRuntimeRequest extends BaseMessage {\n type: typeof MessageType.DISPOSE_RUNTIME;\n isolateId: string;\n /** When true, permanently delete the runtime instead of soft-deleting namespaced runtimes. */\n hard?: boolean;\n /** Optional caller-supplied reason for disposal, used for diagnostics/logging. */\n reason?: string;\n}\n\nexport interface EvalRequest extends BaseMessage {\n type: typeof MessageType.EVAL;\n isolateId: string;\n code: string;\n filename?: string;\n executionTimeout?: number;\n}\n\nexport interface SerializedRequest {\n method: string;\n url: string;\n headers: [string, string][];\n /** Inline body for small payloads */\n body?: Uint8Array | null;\n /** Stream reference for large/streaming bodies */\n bodyStreamId?: number;\n /** Whether the request signal was already aborted when serialized */\n signalAborted?: boolean;\n}\n\nexport interface DispatchRequestRequest extends BaseMessage {\n type: typeof MessageType.DISPATCH_REQUEST;\n isolateId: string;\n request: SerializedRequest;\n context?: {\n requestId?: string;\n metadata?: Record<string, string>;\n };\n}\n\n/**\n * Abort an in-flight DISPATCH_REQUEST.\n * This is fire-and-forget and does not produce a response.\n */\nexport interface DispatchRequestAbort {\n type: typeof MessageType.DISPATCH_REQUEST_ABORT;\n isolateId: string;\n /** requestId of the corresponding DISPATCH_REQUEST */\n targetRequestId: number;\n}\n\n// WebSocket messages\nexport interface WsOpenRequest extends BaseMessage {\n type: typeof MessageType.WS_OPEN;\n isolateId: string;\n connectionId: string;\n}\n\nexport interface WsMessageRequest extends BaseMessage {\n type: typeof MessageType.WS_MESSAGE;\n isolateId: string;\n connectionId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsCloseRequest extends BaseMessage {\n type: typeof MessageType.WS_CLOSE;\n isolateId: string;\n connectionId: string;\n code: number;\n reason: string;\n}\n\n// Handle operation messages\nexport interface FetchGetUpgradeRequestRequest extends BaseMessage {\n type: typeof MessageType.FETCH_GET_UPGRADE_REQUEST;\n isolateId: string;\n}\n\nexport interface FetchHasServeHandlerRequest extends BaseMessage {\n type: typeof MessageType.FETCH_HAS_SERVE_HANDLER;\n isolateId: string;\n}\n\nexport interface FetchHasActiveConnectionsRequest extends BaseMessage {\n type: typeof MessageType.FETCH_HAS_ACTIVE_CONNECTIONS;\n isolateId: string;\n}\n\nexport interface FetchWsErrorRequest extends BaseMessage {\n type: typeof MessageType.FETCH_WS_ERROR;\n isolateId: string;\n connectionId: string;\n error: string;\n}\n\nexport interface TimersClearAllRequest extends BaseMessage {\n type: typeof MessageType.TIMERS_CLEAR_ALL;\n isolateId: string;\n}\n\nexport interface ConsoleResetRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_RESET;\n isolateId: string;\n}\n\nexport interface ConsoleGetTimersRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_TIMERS;\n isolateId: string;\n}\n\nexport interface ConsoleGetCountersRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_COUNTERS;\n isolateId: string;\n}\n\nexport interface ConsoleGetGroupDepthRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_GROUP_DEPTH;\n isolateId: string;\n}\n\n// Test environment messages\nexport interface RunTestsRequest extends BaseMessage {\n type: typeof MessageType.RUN_TESTS;\n isolateId: string;\n timeout?: number;\n}\n\nexport interface ResetTestEnvRequest extends BaseMessage {\n type: typeof MessageType.RESET_TEST_ENV;\n isolateId: string;\n}\n\nexport interface HasTestsRequest extends BaseMessage {\n type: typeof MessageType.HAS_TESTS;\n isolateId: string;\n}\n\nexport interface GetTestCountRequest extends BaseMessage {\n type: typeof MessageType.GET_TEST_COUNT;\n isolateId: string;\n}\n\nexport interface GetCollectedDataRequest extends BaseMessage {\n type: typeof MessageType.GET_COLLECTED_DATA;\n isolateId: string;\n}\n\nexport interface ClearCollectedDataRequest extends BaseMessage {\n type: typeof MessageType.CLEAR_COLLECTED_DATA;\n isolateId: string;\n}\n\n// ============================================================================\n// Daemon → Client Messages\n// ============================================================================\n\nexport interface ResponseOk extends BaseMessage {\n type: typeof MessageType.RESPONSE_OK;\n data?: unknown;\n}\n\nexport interface ResponseError extends BaseMessage {\n type: typeof MessageType.RESPONSE_ERROR;\n code: ErrorCode;\n message: string;\n details?: {\n name: string;\n stack?: string;\n cause?: unknown;\n };\n}\n\nexport interface SerializedResponse {\n status: number;\n statusText: string;\n headers: [string, string][];\n /** Inline body for small payloads */\n body?: Uint8Array | null;\n /** Stream reference for large/streaming bodies */\n bodyStreamId?: number;\n}\n\nexport interface ResponseStreamStart extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_START;\n streamId: number;\n metadata?: {\n status?: number;\n statusText?: string;\n headers?: [string, string][];\n };\n}\n\nexport interface ResponseStreamChunk extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_CHUNK;\n streamId: number;\n chunk: Uint8Array;\n}\n\nexport interface ResponseStreamEnd extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_END;\n streamId: number;\n}\n\n// ============================================================================\n// Bidirectional: Callbacks\n// ============================================================================\n\nexport interface CallbackInvoke extends BaseMessage {\n type: typeof MessageType.CALLBACK_INVOKE;\n callbackId: number;\n args: unknown[];\n context?: {\n requestId?: string;\n metadata?: Record<string, string>;\n };\n}\n\nexport interface CallbackResponseMsg extends BaseMessage {\n type: typeof MessageType.CALLBACK_RESPONSE;\n result?: unknown;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n/**\n * Start a streaming callback response (client → daemon).\n * Used when the callback returns a Response with a streaming body.\n */\nexport interface CallbackStreamStart extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_START;\n /** The stream ID for correlating chunks */\n streamId: number;\n /** Response metadata */\n metadata: {\n status: number;\n statusText: string;\n headers: [string, string][];\n /** Response URL (for network responses) */\n url?: string;\n };\n}\n\n/**\n * A chunk of streaming callback response data (client → daemon).\n */\nexport interface CallbackStreamChunk extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_CHUNK;\n /** The stream ID for correlation */\n streamId: number;\n /** The chunk data */\n chunk: Uint8Array;\n}\n\n/**\n * End of a streaming callback response (client → daemon).\n */\nexport interface CallbackStreamEnd extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_END;\n /** The stream ID for correlation */\n streamId: number;\n}\n\n/**\n * Cancel a streaming callback response (daemon → client).\n * Tells the client to stop reading the response body.\n */\nexport interface CallbackStreamCancel {\n type: typeof MessageType.CALLBACK_STREAM_CANCEL;\n /** The stream ID to cancel */\n streamId: number;\n}\n\n/**\n * Abort an in-flight callback invocation (daemon → client).\n * Tells the client to cancel the callback identified by targetRequestId.\n */\nexport interface CallbackAbort extends BaseMessage {\n type: typeof MessageType.CALLBACK_ABORT;\n /** requestId of the corresponding CALLBACK_INVOKE */\n targetRequestId: number;\n /** Optional reason for observability/debugging */\n reason?: string;\n}\n\n// ============================================================================\n// Bidirectional: Stream Data\n// ============================================================================\n\nexport interface StreamPush {\n type: typeof MessageType.STREAM_PUSH;\n streamId: number;\n chunk: Uint8Array;\n}\n\nexport interface StreamPull {\n type: typeof MessageType.STREAM_PULL;\n streamId: number;\n maxBytes: number;\n}\n\nexport interface StreamClose {\n type: typeof MessageType.STREAM_CLOSE;\n streamId: number;\n}\n\nexport interface StreamError {\n type: typeof MessageType.STREAM_ERROR;\n streamId: number;\n error: string;\n}\n\n// ============================================================================\n// Generic Events\n// ============================================================================\n\n/** Event name constants for isolate → client events */\nexport const IsolateEvents = {\n WS_COMMAND: \"ws:command\",\n WS_CLIENT_CONNECT: \"ws:client-connect\",\n WS_CLIENT_SEND: \"ws:client-send\",\n WS_CLIENT_CLOSE: \"ws:client-close\",\n} as const;\n\n/** Event name constants for client → daemon events */\nexport const ClientEvents = {\n WS_CLIENT_OPENED: \"ws:client-opened\",\n WS_CLIENT_MESSAGE: \"ws:client-message\",\n WS_CLIENT_CLOSED: \"ws:client-closed\",\n WS_CLIENT_ERROR: \"ws:client-error\",\n} as const;\n\n/** Generic event from daemon to client */\nexport interface IsolateEventMessage {\n type: typeof MessageType.ISOLATE_EVENT;\n isolateId: string;\n event: string;\n payload: unknown;\n}\n\n/** Generic event from client to daemon */\nexport interface ClientEventMessage {\n type: typeof MessageType.CLIENT_EVENT;\n isolateId: string;\n event: string;\n payload: unknown;\n}\n\n// Typed payloads for internal WS events (for type safety at usage sites)\n\nexport interface WsCommandPayload {\n type: \"message\" | \"close\";\n connectionId: string;\n data?: string | Uint8Array;\n code?: number;\n reason?: string;\n}\n\nexport interface WsClientConnectPayload {\n socketId: string;\n url: string;\n protocols?: string[];\n}\n\nexport interface WsClientSendPayload {\n socketId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsClientClosePayload {\n socketId: string;\n code?: number;\n reason?: string;\n}\n\nexport interface WsClientOpenedPayload {\n socketId: string;\n protocol: string;\n extensions: string;\n}\n\nexport interface WsClientMessagePayload {\n socketId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsClientClosedPayload {\n socketId: string;\n code: number;\n reason: string;\n wasClean: boolean;\n}\n\nexport interface WsClientErrorPayload {\n socketId: string;\n}\n\n/**\n * Unified playwright event type for the onEvent callback.\n */\nexport type PlaywrightEvent =\n | {\n type: \"browserConsoleLog\";\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }\n | {\n type: \"pageError\";\n name: string;\n message: string;\n stack?: string;\n timestamp: number;\n }\n | {\n type: \"networkRequest\";\n requestId: string;\n url: string;\n method: string;\n headers: Record<string, string>;\n postData?: string;\n resourceType?: string;\n timestamp: number;\n }\n | {\n type: \"networkResponse\";\n requestId: string;\n url: string;\n status: number;\n statusText?: string;\n headers: Record<string, string>;\n resourceType?: string;\n timestamp: number;\n }\n | {\n type: \"requestFailure\";\n requestId: string;\n url: string;\n method: string;\n failureText: string;\n resourceType?: string;\n timestamp: number;\n };\n\n// ============================================================================\n// Heartbeat\n// ============================================================================\n\nexport interface PingMessage {\n type: typeof MessageType.PING;\n}\n\nexport interface PongMessage {\n type: typeof MessageType.PONG;\n}\n\n// ============================================================================\n// Union Types\n// ============================================================================\n\nexport type ClientMessage =\n | CreateRuntimeRequest\n | DisposeRuntimeRequest\n | EvalRequest\n | DispatchRequestRequest\n | DispatchRequestAbort\n | WsOpenRequest\n | WsMessageRequest\n | WsCloseRequest\n | FetchGetUpgradeRequestRequest\n | FetchHasServeHandlerRequest\n | FetchHasActiveConnectionsRequest\n | FetchWsErrorRequest\n | TimersClearAllRequest\n | ConsoleResetRequest\n | ConsoleGetTimersRequest\n | ConsoleGetCountersRequest\n | ConsoleGetGroupDepthRequest\n | RunTestsRequest\n | ResetTestEnvRequest\n | HasTestsRequest\n | GetTestCountRequest\n | GetCollectedDataRequest\n | ClearCollectedDataRequest\n | CallbackResponseMsg\n | CallbackStreamStart\n | CallbackStreamChunk\n | CallbackStreamEnd\n | CallbackStreamCancel\n | StreamPush\n | StreamPull\n | StreamClose\n | StreamError\n | ClientEventMessage\n | PingMessage;\n\nexport type DaemonMessage =\n | ResponseOk\n | ResponseError\n | ResponseStreamStart\n | ResponseStreamChunk\n | ResponseStreamEnd\n | CallbackInvoke\n | CallbackAbort\n | StreamPush\n | StreamPull\n | StreamClose\n | StreamError\n | IsolateEventMessage\n | PongMessage;\n\nexport type Message = ClientMessage | DaemonMessage;\n\n// ============================================================================\n// Shared Types (used by both isolate-runtime and isolate-client)\n// ============================================================================\n\n/**\n * Module loader callback type.\n * Called when the isolate imports a module dynamically.\n *\n * @param moduleName - The module specifier being imported\n * @param importer - Information about the importing module\n * @param importer.path - The resolved path of the importing module\n * @param importer.resolveDir - The directory to resolve relative imports from\n * @returns Object with code and resolveDir for the resolved module\n */\nexport type ModuleLoaderCallback = (\n moduleName: string,\n importer: { path: string; resolveDir: string }\n) => ModuleLoaderResult | Promise<ModuleLoaderResult>;\n\nexport interface ModuleLoaderResult {\n code: string;\n /** The filename for this module (basename only, no slashes). Combined with resolveDir to form the full path. */\n filename: string;\n resolveDir: string;\n /** Mark as static to preserve across namespace reuse (e.g. node_modules).\n * Static modules and their transitive deps should all be static. */\n static?: boolean;\n}\n\n/**\n * A custom function that can be called from within the isolate.\n */\nexport type CustomFunction<T extends any[] = unknown[]> = (...args: T) => unknown | Promise<unknown>;\n\n/**\n * An async generator function that can be consumed in the isolate via for await...of.\n */\nexport type CustomAsyncGeneratorFunction<T extends any[] = unknown[]> = (...args: T) => AsyncGenerator<unknown, unknown, unknown>;\n\n/**\n * Custom function definition with metadata.\n * Requires explicit `type` property to indicate function behavior.\n */\nexport interface CustomFunctionDefinition<T extends any[] = unknown[]> {\n /** The function implementation */\n fn: CustomFunction<T> | CustomAsyncGeneratorFunction<T>;\n /** Function type: 'sync', 'async', or 'asyncIterator' */\n type: CustomFunctionType;\n}\n\n/**\n * Custom functions to register in the runtime.\n * Each function must be defined with explicit type property.\n *\n * @example\n * ```typescript\n * customFunctions: {\n * // Sync function\n * getConfig: {\n * fn: () => ({ environment: \"production\" }),\n * type: 'sync',\n * },\n * // Async function\n * hashPassword: {\n * fn: async (password) => bcrypt.hash(password, 10),\n * type: 'async',\n * },\n * // Async iterator function\n * streamData: {\n * fn: async function* (options) {\n * for await (const chunk of someStream) {\n * yield chunk;\n * }\n * },\n * type: 'asyncIterator',\n * },\n * }\n * ```\n */\nexport type CustomFunctions<T extends Record<string, any[]> = Record<string, unknown[]>> = {\n [K in keyof T]: CustomFunctionDefinition<T[K]>;\n}\n\n/**\n * Console entry types for structured console output.\n * Each entry type captures the specific data needed to render like DevTools.\n * Output is pre-formatted as stdout strings (like Node.js console) inside the sandbox.\n */\nexport type ConsoleEntry =\n | {\n type: \"output\";\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\";\n stdout: string;\n groupDepth: number;\n }\n | {\n /** Browser console output (from Playwright page, not sandbox) */\n type: \"browserOutput\";\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }\n | { type: \"dir\"; stdout: string; groupDepth: number }\n | { type: \"table\"; stdout: string; groupDepth: number }\n | { type: \"time\"; label: string; duration: number; groupDepth: number }\n | {\n type: \"timeLog\";\n label: string;\n duration: number;\n stdout: string;\n groupDepth: number;\n }\n | { type: \"count\"; label: string; count: number; groupDepth: number }\n | { type: \"countReset\"; label: string; groupDepth: number }\n | { type: \"assert\"; stdout: string; groupDepth: number }\n | {\n type: \"group\";\n label: string;\n collapsed: boolean;\n groupDepth: number;\n }\n | { type: \"groupEnd\"; groupDepth: number }\n | { type: \"clear\" }\n | { type: \"trace\"; stdout: string; stack: string; groupDepth: number };\n\n/**\n * Console callback handlers with single structured callback.\n */\nexport interface ConsoleCallbacks {\n /**\n * Callback invoked for each console operation.\n * Receives a structured entry with all data needed to render the output.\n */\n onEntry?: (entry: ConsoleEntry) => void;\n}\n\n/**\n * Fetch request init type.\n */\nexport interface FetchRequestInit {\n method: string;\n headers: [string, string][];\n /** Raw body bytes - use this if you need direct access to the body data */\n rawBody: Uint8Array | null;\n /** Body ready for use with fetch() - same data as rawBody but typed as BodyInit */\n body: BodyInit | null;\n signal: AbortSignal;\n}\n\n/**\n * Fetch callback type.\n */\nexport type FetchCallback = (url: string, init: FetchRequestInit) => Response | Promise<Response>;\n\n/**\n * WebSocket callback type.\n * Called when isolate code creates an outbound WebSocket connection.\n * Return a WebSocket to proxy the connection, or null to block it.\n */\nexport type WebSocketCallback = (url: string, protocols: string[]) => WebSocket | Promise<WebSocket | null> | null;\n\n/**\n * File system callback handlers.\n */\nexport interface FileSystemCallbacks {\n readFile?: (path: string) => Promise<ArrayBuffer>;\n writeFile?: (path: string, data: ArrayBuffer) => Promise<void>;\n unlink?: (path: string) => Promise<void>;\n readdir?: (path: string) => Promise<string[]>;\n mkdir?: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n rmdir?: (path: string) => Promise<void>;\n stat?: (\n path: string\n ) => Promise<{ isFile: boolean; isDirectory: boolean; size: number }>;\n rename?: (from: string, to: string) => Promise<void>;\n}\n\n/**\n * Options for dispatching a request.\n */\nexport interface DispatchOptions {\n /** AbortSignal to cancel the request */\n signal?: AbortSignal;\n /** Optional request identifier forwarded to host callbacks */\n requestId?: string;\n /** Optional metadata forwarded to host callbacks */\n metadata?: Record<string, string>;\n}\n\n/**\n * Options for eval() method.\n */\nexport interface EvalOptions {\n /** Filename for stack traces */\n filename?: string;\n /** Timeout for the full eval execution in milliseconds */\n executionTimeout?: number;\n}\n\n/**\n * Test environment options for createRuntime.\n */\nexport interface TestEnvironmentOptions {\n /** Receive test lifecycle events */\n onEvent?: (event: TestEvent) => void;\n /** Timeout for individual tests (ms) */\n testTimeout?: number;\n}\n\n/**\n * File data for setInputFiles operations.\n */\nexport interface PlaywrightFileData {\n /** File name */\n name: string;\n /** MIME type */\n mimeType: string;\n /** File contents as Buffer */\n buffer: Buffer;\n}\n\n/**\n * Options for Playwright integration.\n *\n * Public API is handler-first: host-specific page wiring should be done by\n * creating a handler (for example via `defaultPlaywrightHandler(page)`).\n */\nexport interface PlaywrightOptions {\n /** Handler callback for Playwright operations (required when playwright is enabled) */\n handler: (op: PlaywrightOperation) => Promise<PlaywrightResult>;\n /** Default timeout for operations in ms */\n timeout?: number;\n /** If true, browser console logs are routed through console handler (or printed to stdout if no handler) */\n console?: boolean;\n /** Unified event callback for all playwright events */\n onEvent?: (event: PlaywrightEvent) => void;\n}\n\n/**\n * Base runtime options shared between isolate-client and isolate-runtime.\n * Each package extends this with its own `fs` type.\n */\nexport interface BaseRuntimeOptions<T extends Record<string, any[]> = Record<string, unknown[]>> {\n /** Memory limit in megabytes (optional) */\n memoryLimitMB?: number;\n /** Timeout for the full eval/test execution in milliseconds */\n executionTimeout?: number;\n /** Console callback handlers */\n console?: ConsoleCallbacks;\n /** Fetch callback handler */\n fetch?: FetchCallback;\n /** WebSocket callback handler for outbound connections from isolate */\n webSocket?: WebSocketCallback;\n /** Module loader callback for resolving dynamic imports */\n moduleLoader?: ModuleLoaderCallback;\n /** Custom functions callable from within the isolate */\n customFunctions?: CustomFunctions<T>;\n /** Current working directory for path.resolve(). Defaults to \"/\" */\n cwd?: string;\n /** Enable test environment (describe, it, expect, etc.) */\n testEnvironment?: boolean | TestEnvironmentOptions;\n /** Playwright options (handler-first API) */\n playwright?: PlaywrightOptions;\n}\n\n// ============================================================================\n// Result Types (for responses)\n// ============================================================================\n\nexport interface CreateRuntimeResult {\n isolateId: string;\n /** True if runtime was reused from namespace pool */\n reused?: boolean;\n}\n\nexport interface EvalResult {\n value: unknown;\n}\n\nexport interface DispatchRequestResult {\n response: SerializedResponse;\n}\n\n// ============================================================================\n// Test Environment Types\n// ============================================================================\n\nexport interface SuiteInfo {\n name: string;\n /** Ancestry path: [\"outer\", \"inner\"] */\n path: string[];\n /** Full display name: \"outer > inner\" */\n fullName: string;\n /** Nesting depth (0 for root-level suites) */\n depth: number;\n}\n\nexport interface SuiteResult extends SuiteInfo {\n passed: number;\n failed: number;\n skipped: number;\n todo: number;\n duration: number;\n}\n\nexport interface TestInfo {\n name: string;\n /** Suite ancestry */\n suitePath: string[];\n /** Full display name: \"suite > test name\" */\n fullName: string;\n}\n\nexport interface TestError {\n message: string;\n stack?: string;\n /** For assertion failures */\n expected?: unknown;\n actual?: unknown;\n /** e.g., \"toBe\", \"toEqual\", \"toContain\" */\n matcherName?: string;\n}\n\nexport interface TestResult extends TestInfo {\n status: \"pass\" | \"fail\" | \"skip\" | \"todo\";\n duration: number;\n error?: TestError;\n}\n\nexport type TestEvent =\n | { type: \"runStart\"; testCount: number; suiteCount: number }\n | { type: \"suiteStart\"; suite: SuiteInfo }\n | { type: \"suiteEnd\"; suite: SuiteResult }\n | { type: \"testStart\"; test: TestInfo }\n | { type: \"testEnd\"; test: TestResult }\n | { type: \"runEnd\"; results: RunTestsResult };\n\nexport interface RunTestsResult {\n passed: number;\n failed: number;\n skipped: number;\n todo: number;\n total: number;\n duration: number;\n success: boolean;\n suites: SuiteResult[];\n tests: TestResult[];\n}\n\nexport interface PlaywrightTestResult {\n passed: number;\n failed: number;\n total: number;\n results: {\n name: string;\n passed: boolean;\n error?: string;\n duration: number;\n }[];\n}\n\nexport interface CollectedData {\n /** Browser console logs (from the page, not sandbox) */\n browserConsoleLogs: {\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }[];\n pageErrors: {\n name: string;\n message: string;\n stack?: string;\n timestamp: number;\n }[];\n networkRequests: {\n requestId: string;\n url: string;\n method: string;\n headers: Record<string, string>;\n postData?: string;\n resourceType?: string;\n timestamp: number;\n }[];\n networkResponses: {\n requestId: string;\n url: string;\n status: number;\n headers: Record<string, string>;\n statusText?: string;\n resourceType?: string;\n timestamp: number;\n }[];\n requestFailures: {\n requestId: string;\n url: string;\n method: string;\n failureText: string;\n resourceType?: string;\n timestamp: number;\n }[];\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Normalize a filename to an absolute path for module resolution.\n *\n * Rules:\n * - undefined/empty/\"\" → \"/index.js\"\n * - Absolute paths (start with /) → normalized as-is\n * - Relative paths starting with \"./\" → converted to absolute from root\n * - Bare filenames (no leading ./ or /) → converted to absolute from root\n * - Paths starting with \"../\" → Error (can't resolve parent of root)\n * - Directory paths (\"/\" or \"./\") → append \"index.js\"\n *\n * @example\n * normalizeEntryFilename(undefined) // \"/index.js\"\n * normalizeEntryFilename(\"\") // \"/index.js\"\n * normalizeEntryFilename(\"app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"./app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"/app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"./foo/bar.js\") // \"/foo/bar.js\"\n * normalizeEntryFilename(\"/\") // \"/index.js\"\n * normalizeEntryFilename(\"./\") // \"/index.js\"\n * normalizeEntryFilename(\"../app.js\") // throws Error\n *\n * @throws Error if the filename cannot be normalized (e.g., starts with \"../\")\n */\nexport function normalizeEntryFilename(filename: string | undefined): string {\n // Default to /index.js\n if (!filename || filename === \"\") {\n return \"/index.js\";\n }\n\n // Reject paths that try to go above root\n if (filename.startsWith(\"../\")) {\n throw new Error(\n `Invalid entry filename \"${filename}\": cannot use \"../\" at the start. ` +\n `Use an absolute path like \"/app.js\" or a relative path like \"./app.js\".`\n );\n }\n\n // Track if original path ends with / (indicates directory)\n const endsWithSlash = filename.endsWith(\"/\");\n\n let toNormalize: string;\n if (filename.startsWith(\"/\")) {\n // Already absolute\n toNormalize = filename;\n } else if (filename.startsWith(\"./\")) {\n // Relative from root: ./app.js → /app.js\n toNormalize = \"/\" + filename.slice(2);\n } else {\n // Bare filename: app.js → /app.js\n toNormalize = \"/\" + filename;\n }\n\n // Normalize path and check for escaping root\n const normalized = normalizePosixPath(toNormalize, filename);\n\n // Handle directory paths - append index.js\n if (normalized === \"/\" || endsWithSlash) {\n return normalized === \"/\" ? \"/index.js\" : normalized + \"/index.js\";\n }\n\n return normalized;\n}\n\n/**\n * Simple POSIX path normalization without external dependencies.\n * Handles . and .. segments, collapses multiple slashes.\n * Throws if path tries to escape above root.\n */\nfunction normalizePosixPath(p: string, originalFilename: string): string {\n if (p === \"\") return \".\";\n\n const isAbsolute = p.startsWith(\"/\");\n const segments = p.split(\"/\").filter(s => s !== \"\" && s !== \".\");\n const result: string[] = [];\n let parentCount = 0; // Track how many .. we've seen at root level\n\n for (const segment of segments) {\n if (segment === \"..\") {\n if (result.length > 0 && result[result.length - 1] !== \"..\") {\n result.pop();\n } else if (isAbsolute) {\n // For absolute paths, track attempts to go above root\n parentCount++;\n } else {\n result.push(\"..\");\n }\n } else {\n result.push(segment);\n }\n }\n\n // If we tried to go above root, throw an error\n if (isAbsolute && parentCount > 0 && result.length === 0) {\n // Only throw if we actually escaped (ended up at root after going above)\n // This catches cases like /foo/../../bar.js where we went above root\n }\n\n // Count segments before normalization to detect if we went above root\n const originalSegments = p.split(\"/\").filter(s => s !== \"\" && s !== \".\");\n let depth = 0;\n for (const segment of originalSegments) {\n if (segment === \"..\") {\n depth--;\n if (isAbsolute && depth < 0) {\n throw new Error(\n `Invalid entry filename \"${originalFilename}\": path resolves above root directory.`\n );\n }\n } else {\n depth++;\n }\n }\n\n const normalized = result.join(\"/\");\n return isAbsolute ? \"/\" + normalized : (normalized || \".\");\n}\n"
|
|
5
|
+
"/**\n * Message types for the isolate daemon protocol.\n *\n * Frame format:\n * ┌──────────┬──────────┬─────────────────┐\n * │ Length │ Type │ Payload │\n * │ (4 bytes)│ (1 byte) │ (MessagePack) │\n * └──────────┴──────────┴─────────────────┘\n */\n\n// ============================================================================\n// Message Type Constants\n// ============================================================================\n\nexport const MessageType = {\n // Client → Daemon: Runtime management\n CREATE_RUNTIME: 0x01,\n DISPOSE_RUNTIME: 0x02,\n EVAL: 0x03,\n DISPATCH_REQUEST: 0x04,\n DISPATCH_REQUEST_ABORT: 0x05,\n\n // Client → Daemon: WebSocket operations\n WS_OPEN: 0x10,\n WS_MESSAGE: 0x11,\n WS_CLOSE: 0x12,\n\n // Client → Daemon: Handle operations\n FETCH_GET_UPGRADE_REQUEST: 0x13,\n FETCH_HAS_SERVE_HANDLER: 0x14,\n FETCH_HAS_ACTIVE_CONNECTIONS: 0x15,\n FETCH_WS_ERROR: 0x16,\n TIMERS_CLEAR_ALL: 0x17,\n CONSOLE_RESET: 0x18,\n CONSOLE_GET_TIMERS: 0x19,\n CONSOLE_GET_COUNTERS: 0x1a,\n CONSOLE_GET_GROUP_DEPTH: 0x1b,\n\n // Client → Daemon: Test environment\n RUN_TESTS: 0x21,\n RESET_TEST_ENV: 0x22,\n HAS_TESTS: 0x23,\n GET_TEST_COUNT: 0x24,\n\n // Client → Daemon: Playwright\n GET_COLLECTED_DATA: 0x33,\n CLEAR_COLLECTED_DATA: 0x34,\n\n // Daemon → Client: Responses\n RESPONSE_OK: 0x80,\n RESPONSE_ERROR: 0x81,\n RESPONSE_STREAM_START: 0x82,\n RESPONSE_STREAM_CHUNK: 0x83,\n RESPONSE_STREAM_END: 0x84,\n\n // Bidirectional: Callbacks\n CALLBACK_INVOKE: 0x90,\n CALLBACK_RESPONSE: 0x91,\n CALLBACK_STREAM_START: 0x92,\n CALLBACK_STREAM_CHUNK: 0x93,\n CALLBACK_STREAM_END: 0x94,\n CALLBACK_STREAM_CANCEL: 0x95,\n CALLBACK_ABORT: 0x96,\n\n // Bidirectional: Stream data\n STREAM_PUSH: 0xa0,\n STREAM_PULL: 0xa1,\n STREAM_CLOSE: 0xa2,\n STREAM_ERROR: 0xa3,\n\n // Bidirectional: Generic events\n ISOLATE_EVENT: 0xc0, // daemon → client\n CLIENT_EVENT: 0xc1, // client → daemon\n\n // Heartbeat\n PING: 0xf0,\n PONG: 0xf1,\n} as const;\n\nexport type MessageType = (typeof MessageType)[keyof typeof MessageType];\n\n/** Reverse lookup for message type names */\nexport const MessageTypeName: Record<number, string> = Object.fromEntries(\n Object.entries(MessageType).map(([k, v]) => [v, k])\n);\n\n// ============================================================================\n// Error Codes\n// ============================================================================\n\nexport const ErrorCode = {\n // Protocol errors\n INVALID_MESSAGE: 1001,\n UNKNOWN_MESSAGE_TYPE: 1002,\n MISSING_REQUIRED_FIELD: 1003,\n\n // Isolate errors\n ISOLATE_NOT_FOUND: 2001,\n ISOLATE_DISPOSED: 2002,\n ISOLATE_MEMORY_LIMIT: 2003,\n ISOLATE_TIMEOUT: 2004,\n\n // Execution errors\n SCRIPT_ERROR: 3001,\n CALLBACK_ERROR: 3002,\n\n // Stream errors\n STREAM_NOT_FOUND: 4001,\n STREAM_CLOSED: 4002,\n\n // Connection errors\n CONNECTION_LOST: 5001,\n} as const;\n\nexport type ErrorCode = (typeof ErrorCode)[keyof typeof ErrorCode];\n\n// ============================================================================\n// Base Message Interface\n// ============================================================================\n\nexport interface BaseMessage {\n /** Unique request ID for correlation */\n requestId: number;\n}\n\n// ============================================================================\n// Callback Registration\n// ============================================================================\n\n/** Custom function type indicator */\nexport type CustomFunctionType = 'sync' | 'async' | 'asyncIterator';\n\nexport interface CallbackRegistration {\n /** Unique ID for this callback */\n callbackId: number;\n /** Callback name (e.g., \"log\", \"warn\", \"fetch\") */\n name: string;\n /** Function type: sync, async, or asyncIterator */\n type: CustomFunctionType;\n}\n\nexport interface ConsoleCallbackRegistrations {\n onEntry?: CallbackRegistration;\n}\n\nexport interface FsCallbackRegistrations {\n readFile?: CallbackRegistration;\n writeFile?: CallbackRegistration;\n unlink?: CallbackRegistration;\n readdir?: CallbackRegistration;\n mkdir?: CallbackRegistration;\n rmdir?: CallbackRegistration;\n stat?: CallbackRegistration;\n rename?: CallbackRegistration;\n}\n\nexport interface CustomFunctionRegistrations {\n [name: string]: CallbackRegistration;\n}\n\n// ============================================================================\n// Playwright Callback Types\n// ============================================================================\n\n/**\n * Playwright operation sent from daemon to client via callback.\n * The client executes this operation on the real Page object.\n */\nexport interface PlaywrightOperation {\n type:\n | \"goto\"\n | \"reload\"\n | \"url\"\n | \"title\"\n | \"content\"\n | \"waitForSelector\"\n | \"waitForTimeout\"\n | \"waitForLoadState\"\n | \"evaluate\"\n | \"locatorAction\"\n | \"expectLocator\"\n | \"expectPage\"\n | \"request\"\n | \"goBack\"\n | \"goForward\"\n | \"waitForURL\"\n | \"waitForURLPredicate\"\n | \"waitForRequestStart\"\n | \"waitForRequestFinish\"\n | \"waitForRequestPredicateFinish\"\n | \"waitForResponseStart\"\n | \"waitForResponseFinish\"\n | \"waitForResponsePredicateFinish\"\n | \"clearCookies\"\n // Page-level operations\n | \"screenshot\"\n | \"setViewportSize\"\n | \"viewportSize\"\n | \"emulateMedia\"\n | \"setExtraHTTPHeaders\"\n | \"bringToFront\"\n | \"close\"\n | \"isClosed\"\n | \"pdf\"\n | \"pause\"\n | \"frames\"\n | \"mainFrame\"\n // Keyboard operations\n | \"keyboardType\"\n | \"keyboardPress\"\n | \"keyboardDown\"\n | \"keyboardUp\"\n | \"keyboardInsertText\"\n // Mouse operations\n | \"mouseMove\"\n | \"mouseClick\"\n | \"mouseDown\"\n | \"mouseUp\"\n | \"mouseWheel\"\n // Cookie operations\n | \"addCookies\"\n | \"cookies\"\n // Browser/Context lifecycle operations\n | \"contexts\"\n | \"pages\"\n | \"newContext\"\n | \"newPage\"\n | \"closeContext\";\n args: unknown[];\n /** Target page ID (undefined = default page \"page_0\") */\n pageId?: string;\n /** Target context ID (undefined = default context \"ctx_0\") */\n contextId?: string;\n}\n\n/**\n * Result of a playwright operation.\n */\nexport type PlaywrightResult =\n | { ok: true; value?: unknown }\n | { ok: false; error: { name: string; message: string } };\n\n/**\n * Callback registrations for playwright operations.\n */\nexport interface PlaywrightCallbackRegistration {\n /** Callback ID for page operations */\n handlerCallbackId: number;\n /** If true, browser console logs are printed to stdout */\n console?: boolean;\n /** Optional callback for browser console log events (from the page, not sandbox) */\n onBrowserConsoleLogCallbackId?: number;\n /** Optional callback for network request events */\n onNetworkRequestCallbackId?: number;\n /** Optional callback for network response events */\n onNetworkResponseCallbackId?: number;\n}\n\n// ============================================================================\n// Runtime Callback Registrations\n// ============================================================================\n\nexport interface RuntimeCallbackRegistrations {\n console?: ConsoleCallbackRegistrations;\n fetch?: CallbackRegistration;\n fs?: FsCallbackRegistrations;\n moduleLoader?: CallbackRegistration;\n custom?: CustomFunctionRegistrations;\n playwright?: PlaywrightCallbackRegistration;\n}\n\n// ============================================================================\n// Client → Daemon Messages\n// ============================================================================\n\nexport interface TestEnvironmentCallbackRegistrations {\n /** Callback for test events */\n onEvent?: CallbackRegistration;\n}\n\nexport interface TestEnvironmentOptionsProtocol {\n /** Callback registrations for test events */\n callbacks?: TestEnvironmentCallbackRegistrations;\n /** Timeout for individual tests (ms) */\n testTimeout?: number;\n}\n\nexport interface PlaywrightOptionsProtocol {\n /** Default timeout for Playwright operations in ms */\n timeout?: number;\n /** Whether the isolate should expose default page/context globals. */\n hasDefaultPage?: boolean;\n}\n\nexport interface CreateRuntimeRequest extends BaseMessage {\n type: typeof MessageType.CREATE_RUNTIME;\n options: {\n memoryLimitMB?: number;\n executionTimeout?: number;\n callbacks?: RuntimeCallbackRegistrations;\n /** Current working directory for path.resolve(). Defaults to \"/\" */\n cwd?: string;\n /** Enable test environment (describe, it, expect, etc.) */\n testEnvironment?: boolean | TestEnvironmentOptionsProtocol;\n /** Playwright runtime options */\n playwright?: PlaywrightOptionsProtocol;\n /** Namespace ID for runtime pooling/reuse. If provided, runtime will be cached on dispose. */\n namespaceId?: string;\n };\n}\n\nexport interface DisposeRuntimeRequest extends BaseMessage {\n type: typeof MessageType.DISPOSE_RUNTIME;\n isolateId: string;\n /** When true, permanently delete the runtime instead of soft-deleting namespaced runtimes. */\n hard?: boolean;\n /** Optional caller-supplied reason for disposal, used for diagnostics/logging. */\n reason?: string;\n}\n\nexport interface EvalRequest extends BaseMessage {\n type: typeof MessageType.EVAL;\n isolateId: string;\n code: string;\n filename?: string;\n executionTimeout?: number;\n}\n\nexport interface SerializedRequest {\n method: string;\n url: string;\n headers: [string, string][];\n /** Inline body for small payloads */\n body?: Uint8Array | null;\n /** Stream reference for large/streaming bodies */\n bodyStreamId?: number;\n /** Whether the request signal was already aborted when serialized */\n signalAborted?: boolean;\n}\n\nexport interface DispatchRequestRequest extends BaseMessage {\n type: typeof MessageType.DISPATCH_REQUEST;\n isolateId: string;\n request: SerializedRequest;\n context?: {\n requestId?: string;\n metadata?: Record<string, string>;\n };\n}\n\n/**\n * Abort an in-flight DISPATCH_REQUEST.\n * This is fire-and-forget and does not produce a response.\n */\nexport interface DispatchRequestAbort {\n type: typeof MessageType.DISPATCH_REQUEST_ABORT;\n isolateId: string;\n /** requestId of the corresponding DISPATCH_REQUEST */\n targetRequestId: number;\n}\n\n// WebSocket messages\nexport interface WsOpenRequest extends BaseMessage {\n type: typeof MessageType.WS_OPEN;\n isolateId: string;\n connectionId: string;\n}\n\nexport interface WsMessageRequest extends BaseMessage {\n type: typeof MessageType.WS_MESSAGE;\n isolateId: string;\n connectionId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsCloseRequest extends BaseMessage {\n type: typeof MessageType.WS_CLOSE;\n isolateId: string;\n connectionId: string;\n code: number;\n reason: string;\n}\n\n// Handle operation messages\nexport interface FetchGetUpgradeRequestRequest extends BaseMessage {\n type: typeof MessageType.FETCH_GET_UPGRADE_REQUEST;\n isolateId: string;\n}\n\nexport interface FetchHasServeHandlerRequest extends BaseMessage {\n type: typeof MessageType.FETCH_HAS_SERVE_HANDLER;\n isolateId: string;\n}\n\nexport interface FetchHasActiveConnectionsRequest extends BaseMessage {\n type: typeof MessageType.FETCH_HAS_ACTIVE_CONNECTIONS;\n isolateId: string;\n}\n\nexport interface FetchWsErrorRequest extends BaseMessage {\n type: typeof MessageType.FETCH_WS_ERROR;\n isolateId: string;\n connectionId: string;\n error: string;\n}\n\nexport interface TimersClearAllRequest extends BaseMessage {\n type: typeof MessageType.TIMERS_CLEAR_ALL;\n isolateId: string;\n}\n\nexport interface ConsoleResetRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_RESET;\n isolateId: string;\n}\n\nexport interface ConsoleGetTimersRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_TIMERS;\n isolateId: string;\n}\n\nexport interface ConsoleGetCountersRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_COUNTERS;\n isolateId: string;\n}\n\nexport interface ConsoleGetGroupDepthRequest extends BaseMessage {\n type: typeof MessageType.CONSOLE_GET_GROUP_DEPTH;\n isolateId: string;\n}\n\n// Test environment messages\nexport interface RunTestsRequest extends BaseMessage {\n type: typeof MessageType.RUN_TESTS;\n isolateId: string;\n timeout?: number;\n}\n\nexport interface ResetTestEnvRequest extends BaseMessage {\n type: typeof MessageType.RESET_TEST_ENV;\n isolateId: string;\n}\n\nexport interface HasTestsRequest extends BaseMessage {\n type: typeof MessageType.HAS_TESTS;\n isolateId: string;\n}\n\nexport interface GetTestCountRequest extends BaseMessage {\n type: typeof MessageType.GET_TEST_COUNT;\n isolateId: string;\n}\n\nexport interface GetCollectedDataRequest extends BaseMessage {\n type: typeof MessageType.GET_COLLECTED_DATA;\n isolateId: string;\n}\n\nexport interface ClearCollectedDataRequest extends BaseMessage {\n type: typeof MessageType.CLEAR_COLLECTED_DATA;\n isolateId: string;\n}\n\n// ============================================================================\n// Daemon → Client Messages\n// ============================================================================\n\nexport interface ResponseOk extends BaseMessage {\n type: typeof MessageType.RESPONSE_OK;\n data?: unknown;\n}\n\nexport interface ResponseError extends BaseMessage {\n type: typeof MessageType.RESPONSE_ERROR;\n code: ErrorCode;\n message: string;\n details?: {\n name: string;\n stack?: string;\n cause?: unknown;\n };\n}\n\nexport interface SerializedResponse {\n status: number;\n statusText: string;\n headers: [string, string][];\n /** Inline body for small payloads */\n body?: Uint8Array | null;\n /** Stream reference for large/streaming bodies */\n bodyStreamId?: number;\n}\n\nexport interface ResponseStreamStart extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_START;\n streamId: number;\n metadata?: {\n status?: number;\n statusText?: string;\n headers?: [string, string][];\n };\n}\n\nexport interface ResponseStreamChunk extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_CHUNK;\n streamId: number;\n chunk: Uint8Array;\n}\n\nexport interface ResponseStreamEnd extends BaseMessage {\n type: typeof MessageType.RESPONSE_STREAM_END;\n streamId: number;\n}\n\n// ============================================================================\n// Bidirectional: Callbacks\n// ============================================================================\n\nexport interface CallbackInvoke extends BaseMessage {\n type: typeof MessageType.CALLBACK_INVOKE;\n callbackId: number;\n args: unknown[];\n context?: {\n requestId?: string;\n metadata?: Record<string, string>;\n };\n}\n\nexport interface CallbackResponseMsg extends BaseMessage {\n type: typeof MessageType.CALLBACK_RESPONSE;\n result?: unknown;\n error?: {\n name: string;\n message: string;\n stack?: string;\n };\n}\n\n/**\n * Start a streaming callback response (client → daemon).\n * Used when the callback returns a Response with a streaming body.\n */\nexport interface CallbackStreamStart extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_START;\n /** The stream ID for correlating chunks */\n streamId: number;\n /** Response metadata */\n metadata: {\n status: number;\n statusText: string;\n headers: [string, string][];\n /** Response URL (for network responses) */\n url?: string;\n };\n}\n\n/**\n * A chunk of streaming callback response data (client → daemon).\n */\nexport interface CallbackStreamChunk extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_CHUNK;\n /** The stream ID for correlation */\n streamId: number;\n /** The chunk data */\n chunk: Uint8Array;\n}\n\n/**\n * End of a streaming callback response (client → daemon).\n */\nexport interface CallbackStreamEnd extends BaseMessage {\n type: typeof MessageType.CALLBACK_STREAM_END;\n /** The stream ID for correlation */\n streamId: number;\n}\n\n/**\n * Cancel a streaming callback response (daemon → client).\n * Tells the client to stop reading the response body.\n */\nexport interface CallbackStreamCancel {\n type: typeof MessageType.CALLBACK_STREAM_CANCEL;\n /** The stream ID to cancel */\n streamId: number;\n}\n\n/**\n * Abort an in-flight callback invocation (daemon → client).\n * Tells the client to cancel the callback identified by targetRequestId.\n */\nexport interface CallbackAbort extends BaseMessage {\n type: typeof MessageType.CALLBACK_ABORT;\n /** requestId of the corresponding CALLBACK_INVOKE */\n targetRequestId: number;\n /** Optional reason for observability/debugging */\n reason?: string;\n}\n\n// ============================================================================\n// Bidirectional: Stream Data\n// ============================================================================\n\nexport interface StreamPush {\n type: typeof MessageType.STREAM_PUSH;\n streamId: number;\n chunk: Uint8Array;\n}\n\nexport interface StreamPull {\n type: typeof MessageType.STREAM_PULL;\n streamId: number;\n maxBytes: number;\n}\n\nexport interface StreamClose {\n type: typeof MessageType.STREAM_CLOSE;\n streamId: number;\n}\n\nexport interface StreamError {\n type: typeof MessageType.STREAM_ERROR;\n streamId: number;\n error: string;\n}\n\n// ============================================================================\n// Generic Events\n// ============================================================================\n\n/** Event name constants for isolate → client events */\nexport const IsolateEvents = {\n WS_COMMAND: \"ws:command\",\n WS_CLIENT_CONNECT: \"ws:client-connect\",\n WS_CLIENT_SEND: \"ws:client-send\",\n WS_CLIENT_CLOSE: \"ws:client-close\",\n} as const;\n\n/** Event name constants for client → daemon events */\nexport const ClientEvents = {\n WS_CLIENT_OPENED: \"ws:client-opened\",\n WS_CLIENT_MESSAGE: \"ws:client-message\",\n WS_CLIENT_CLOSED: \"ws:client-closed\",\n WS_CLIENT_ERROR: \"ws:client-error\",\n} as const;\n\n/** Generic event from daemon to client */\nexport interface IsolateEventMessage {\n type: typeof MessageType.ISOLATE_EVENT;\n isolateId: string;\n event: string;\n payload: unknown;\n}\n\n/** Generic event from client to daemon */\nexport interface ClientEventMessage {\n type: typeof MessageType.CLIENT_EVENT;\n isolateId: string;\n event: string;\n payload: unknown;\n}\n\n// Typed payloads for internal WS events (for type safety at usage sites)\n\nexport interface WsCommandPayload {\n type: \"message\" | \"close\";\n connectionId: string;\n data?: string | Uint8Array;\n code?: number;\n reason?: string;\n}\n\nexport interface WsClientConnectPayload {\n socketId: string;\n url: string;\n protocols?: string[];\n}\n\nexport interface WsClientSendPayload {\n socketId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsClientClosePayload {\n socketId: string;\n code?: number;\n reason?: string;\n}\n\nexport interface WsClientOpenedPayload {\n socketId: string;\n protocol: string;\n extensions: string;\n}\n\nexport interface WsClientMessagePayload {\n socketId: string;\n data: string | Uint8Array;\n}\n\nexport interface WsClientClosedPayload {\n socketId: string;\n code: number;\n reason: string;\n wasClean: boolean;\n}\n\nexport interface WsClientErrorPayload {\n socketId: string;\n}\n\n/**\n * Unified playwright event type for the onEvent callback.\n */\nexport type PlaywrightEvent =\n | {\n type: \"browserConsoleLog\";\n contextId: string;\n pageId: string;\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }\n | {\n type: \"pageError\";\n contextId: string;\n pageId: string;\n name: string;\n message: string;\n stack?: string;\n timestamp: number;\n }\n | {\n type: \"networkRequest\";\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n method: string;\n headers: Record<string, string>;\n postData?: string;\n resourceType?: string;\n timestamp: number;\n }\n | {\n type: \"networkResponse\";\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n status: number;\n statusText?: string;\n headers: Record<string, string>;\n resourceType?: string;\n timestamp: number;\n }\n | {\n type: \"requestFailure\";\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n method: string;\n failureText: string;\n resourceType?: string;\n timestamp: number;\n };\n\n// ============================================================================\n// Heartbeat\n// ============================================================================\n\nexport interface PingMessage {\n type: typeof MessageType.PING;\n}\n\nexport interface PongMessage {\n type: typeof MessageType.PONG;\n}\n\n// ============================================================================\n// Union Types\n// ============================================================================\n\nexport type ClientMessage =\n | CreateRuntimeRequest\n | DisposeRuntimeRequest\n | EvalRequest\n | DispatchRequestRequest\n | DispatchRequestAbort\n | WsOpenRequest\n | WsMessageRequest\n | WsCloseRequest\n | FetchGetUpgradeRequestRequest\n | FetchHasServeHandlerRequest\n | FetchHasActiveConnectionsRequest\n | FetchWsErrorRequest\n | TimersClearAllRequest\n | ConsoleResetRequest\n | ConsoleGetTimersRequest\n | ConsoleGetCountersRequest\n | ConsoleGetGroupDepthRequest\n | RunTestsRequest\n | ResetTestEnvRequest\n | HasTestsRequest\n | GetTestCountRequest\n | GetCollectedDataRequest\n | ClearCollectedDataRequest\n | CallbackResponseMsg\n | CallbackStreamStart\n | CallbackStreamChunk\n | CallbackStreamEnd\n | CallbackStreamCancel\n | StreamPush\n | StreamPull\n | StreamClose\n | StreamError\n | ClientEventMessage\n | PingMessage;\n\nexport type DaemonMessage =\n | ResponseOk\n | ResponseError\n | ResponseStreamStart\n | ResponseStreamChunk\n | ResponseStreamEnd\n | CallbackInvoke\n | CallbackAbort\n | StreamPush\n | StreamPull\n | StreamClose\n | StreamError\n | IsolateEventMessage\n | PongMessage;\n\nexport type Message = ClientMessage | DaemonMessage;\n\n// ============================================================================\n// Shared Types (used by both isolate-runtime and isolate-client)\n// ============================================================================\n\n/**\n * Module loader callback type.\n * Called when the isolate imports a module dynamically.\n *\n * @param moduleName - The module specifier being imported\n * @param importer - Information about the importing module\n * @param importer.path - The resolved path of the importing module\n * @param importer.resolveDir - The directory to resolve relative imports from\n * @returns Object with code and resolveDir for the resolved module\n */\nexport type ModuleLoaderCallback = (\n moduleName: string,\n importer: { path: string; resolveDir: string }\n) => ModuleLoaderResult | Promise<ModuleLoaderResult>;\n\nexport interface ModuleLoaderResult {\n code: string;\n /** The filename for this module (basename only, no slashes). Combined with resolveDir to form the full path. */\n filename: string;\n resolveDir: string;\n /** Mark as static to preserve across namespace reuse (e.g. node_modules).\n * Static modules and their transitive deps should all be static. */\n static?: boolean;\n}\n\n/**\n * A custom function that can be called from within the isolate.\n */\nexport type CustomFunction<T extends any[] = unknown[]> = (...args: T) => unknown | Promise<unknown>;\n\n/**\n * An async generator function that can be consumed in the isolate via for await...of.\n */\nexport type CustomAsyncGeneratorFunction<T extends any[] = unknown[]> = (...args: T) => AsyncGenerator<unknown, unknown, unknown>;\n\n/**\n * Custom function definition with metadata.\n * Requires explicit `type` property to indicate function behavior.\n */\nexport interface CustomFunctionDefinition<T extends any[] = unknown[]> {\n /** The function implementation */\n fn: CustomFunction<T> | CustomAsyncGeneratorFunction<T>;\n /** Function type: 'sync', 'async', or 'asyncIterator' */\n type: CustomFunctionType;\n}\n\n/**\n * Custom functions to register in the runtime.\n * Each function must be defined with explicit type property.\n *\n * @example\n * ```typescript\n * customFunctions: {\n * // Sync function\n * getConfig: {\n * fn: () => ({ environment: \"production\" }),\n * type: 'sync',\n * },\n * // Async function\n * hashPassword: {\n * fn: async (password) => bcrypt.hash(password, 10),\n * type: 'async',\n * },\n * // Async iterator function\n * streamData: {\n * fn: async function* (options) {\n * for await (const chunk of someStream) {\n * yield chunk;\n * }\n * },\n * type: 'asyncIterator',\n * },\n * }\n * ```\n */\nexport type CustomFunctions<T extends Record<string, any[]> = Record<string, unknown[]>> = {\n [K in keyof T]: CustomFunctionDefinition<T[K]>;\n}\n\n/**\n * Console entry types for structured console output.\n * Each entry type captures the specific data needed to render like DevTools.\n * Output is pre-formatted as stdout strings (like Node.js console) inside the sandbox.\n */\nexport type ConsoleEntry =\n | {\n type: \"output\";\n level: \"log\" | \"warn\" | \"error\" | \"info\" | \"debug\";\n stdout: string;\n groupDepth: number;\n }\n | {\n /** Browser console output (from Playwright page, not sandbox) */\n type: \"browserOutput\";\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }\n | { type: \"dir\"; stdout: string; groupDepth: number }\n | { type: \"table\"; stdout: string; groupDepth: number }\n | { type: \"time\"; label: string; duration: number; groupDepth: number }\n | {\n type: \"timeLog\";\n label: string;\n duration: number;\n stdout: string;\n groupDepth: number;\n }\n | { type: \"count\"; label: string; count: number; groupDepth: number }\n | { type: \"countReset\"; label: string; groupDepth: number }\n | { type: \"assert\"; stdout: string; groupDepth: number }\n | {\n type: \"group\";\n label: string;\n collapsed: boolean;\n groupDepth: number;\n }\n | { type: \"groupEnd\"; groupDepth: number }\n | { type: \"clear\" }\n | { type: \"trace\"; stdout: string; stack: string; groupDepth: number };\n\n/**\n * Console callback handlers with single structured callback.\n */\nexport interface ConsoleCallbacks {\n /**\n * Callback invoked for each console operation.\n * Receives a structured entry with all data needed to render the output.\n */\n onEntry?: (entry: ConsoleEntry) => void;\n}\n\n/**\n * Fetch request init type.\n */\nexport interface FetchRequestInit {\n method: string;\n headers: [string, string][];\n /** Raw body bytes - use this if you need direct access to the body data */\n rawBody: Uint8Array | null;\n /** Body ready for use with fetch() - same data as rawBody but typed as BodyInit */\n body: BodyInit | null;\n signal: AbortSignal;\n}\n\n/**\n * Fetch callback type.\n */\nexport type FetchCallback = (url: string, init: FetchRequestInit) => Response | Promise<Response>;\n\n/**\n * WebSocket callback type.\n * Called when isolate code creates an outbound WebSocket connection.\n * Return a WebSocket to proxy the connection, or null to block it.\n */\nexport type WebSocketCallback = (url: string, protocols: string[]) => WebSocket | Promise<WebSocket | null> | null;\n\n/**\n * File system callback handlers.\n */\nexport interface FileSystemCallbacks {\n readFile?: (path: string) => Promise<ArrayBuffer>;\n writeFile?: (path: string, data: ArrayBuffer) => Promise<void>;\n unlink?: (path: string) => Promise<void>;\n readdir?: (path: string) => Promise<string[]>;\n mkdir?: (path: string, options?: { recursive?: boolean }) => Promise<void>;\n rmdir?: (path: string) => Promise<void>;\n stat?: (\n path: string\n ) => Promise<{ isFile: boolean; isDirectory: boolean; size: number }>;\n rename?: (from: string, to: string) => Promise<void>;\n}\n\n/**\n * Options for dispatching a request.\n */\nexport interface DispatchOptions {\n /** AbortSignal to cancel the request */\n signal?: AbortSignal;\n /** Optional request identifier forwarded to host callbacks */\n requestId?: string;\n /** Optional metadata forwarded to host callbacks */\n metadata?: Record<string, string>;\n}\n\n/**\n * Options for eval() method.\n */\nexport interface EvalOptions {\n /** Filename for stack traces */\n filename?: string;\n /** Timeout for the full eval execution in milliseconds */\n executionTimeout?: number;\n}\n\n/**\n * Test environment options for createRuntime.\n */\nexport interface TestEnvironmentOptions {\n /** Receive test lifecycle events */\n onEvent?: (event: TestEvent) => void;\n /** Timeout for individual tests (ms) */\n testTimeout?: number;\n}\n\n/**\n * File data for setInputFiles operations.\n */\nexport interface PlaywrightFileData {\n /** File name */\n name: string;\n /** MIME type */\n mimeType: string;\n /** File contents as Buffer */\n buffer: Buffer;\n}\n\n/**\n * Options for Playwright integration.\n *\n * Public API is handler-first: host-specific page wiring should be done by\n * creating a handler (for example via `defaultPlaywrightHandler(page)`).\n */\nexport interface PlaywrightOptions {\n /** Handler callback for Playwright operations (required when playwright is enabled) */\n handler: (op: PlaywrightOperation) => Promise<PlaywrightResult>;\n /** Whether the isolate should expose default page/context globals. */\n hasDefaultPage?: boolean;\n /** Default timeout for operations in ms */\n timeout?: number;\n /** If true, browser console logs are routed through console handler (or printed to stdout if no handler) */\n console?: boolean;\n /** Unified event callback for all playwright events */\n onEvent?: (event: PlaywrightEvent) => void;\n}\n\n/**\n * Base runtime options shared between isolate-client and isolate-runtime.\n * Each package extends this with its own `fs` type.\n */\nexport interface BaseRuntimeOptions<T extends Record<string, any[]> = Record<string, unknown[]>> {\n /** Memory limit in megabytes (optional) */\n memoryLimitMB?: number;\n /** Timeout for the full eval/test execution in milliseconds */\n executionTimeout?: number;\n /** Console callback handlers */\n console?: ConsoleCallbacks;\n /** Fetch callback handler */\n fetch?: FetchCallback;\n /** WebSocket callback handler for outbound connections from isolate */\n webSocket?: WebSocketCallback;\n /** Module loader callback for resolving dynamic imports */\n moduleLoader?: ModuleLoaderCallback;\n /** Custom functions callable from within the isolate */\n customFunctions?: CustomFunctions<T>;\n /** Current working directory for path.resolve(). Defaults to \"/\" */\n cwd?: string;\n /** Enable test environment (describe, it, expect, etc.) */\n testEnvironment?: boolean | TestEnvironmentOptions;\n /** Playwright options (handler-first API) */\n playwright?: PlaywrightOptions;\n}\n\n// ============================================================================\n// Result Types (for responses)\n// ============================================================================\n\nexport interface CreateRuntimeResult {\n isolateId: string;\n /** True if runtime was reused from namespace pool */\n reused?: boolean;\n}\n\nexport interface EvalResult {\n value: unknown;\n}\n\nexport interface DispatchRequestResult {\n response: SerializedResponse;\n}\n\n// ============================================================================\n// Test Environment Types\n// ============================================================================\n\nexport interface SuiteInfo {\n name: string;\n /** Ancestry path: [\"outer\", \"inner\"] */\n path: string[];\n /** Full display name: \"outer > inner\" */\n fullName: string;\n /** Nesting depth (0 for root-level suites) */\n depth: number;\n}\n\nexport interface SuiteResult extends SuiteInfo {\n passed: number;\n failed: number;\n skipped: number;\n todo: number;\n duration: number;\n}\n\nexport interface TestInfo {\n name: string;\n /** Suite ancestry */\n suitePath: string[];\n /** Full display name: \"suite > test name\" */\n fullName: string;\n}\n\nexport interface TestError {\n message: string;\n stack?: string;\n /** For assertion failures */\n expected?: unknown;\n actual?: unknown;\n /** e.g., \"toBe\", \"toEqual\", \"toContain\" */\n matcherName?: string;\n}\n\nexport interface TestResult extends TestInfo {\n status: \"pass\" | \"fail\" | \"skip\" | \"todo\";\n duration: number;\n error?: TestError;\n}\n\nexport type TestEvent =\n | { type: \"runStart\"; testCount: number; suiteCount: number }\n | { type: \"suiteStart\"; suite: SuiteInfo }\n | { type: \"suiteEnd\"; suite: SuiteResult }\n | { type: \"testStart\"; test: TestInfo }\n | { type: \"testEnd\"; test: TestResult }\n | { type: \"runEnd\"; results: RunTestsResult };\n\nexport interface RunTestsResult {\n passed: number;\n failed: number;\n skipped: number;\n todo: number;\n total: number;\n duration: number;\n success: boolean;\n suites: SuiteResult[];\n tests: TestResult[];\n}\n\nexport interface PlaywrightTestResult {\n passed: number;\n failed: number;\n total: number;\n results: {\n name: string;\n passed: boolean;\n error?: string;\n duration: number;\n }[];\n}\n\nexport interface CollectedData {\n /** Browser console logs (from the page, not sandbox) */\n browserConsoleLogs: {\n contextId: string;\n pageId: string;\n level: string;\n stdout: string;\n location?: {\n url?: string;\n lineNumber?: number;\n columnNumber?: number;\n };\n timestamp: number;\n }[];\n pageErrors: {\n contextId: string;\n pageId: string;\n name: string;\n message: string;\n stack?: string;\n timestamp: number;\n }[];\n networkRequests: {\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n method: string;\n headers: Record<string, string>;\n postData?: string;\n resourceType?: string;\n timestamp: number;\n }[];\n networkResponses: {\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n status: number;\n headers: Record<string, string>;\n statusText?: string;\n resourceType?: string;\n timestamp: number;\n }[];\n requestFailures: {\n contextId: string;\n pageId: string;\n requestId: string;\n url: string;\n method: string;\n failureText: string;\n resourceType?: string;\n timestamp: number;\n }[];\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\n/**\n * Normalize a filename to an absolute path for module resolution.\n *\n * Rules:\n * - undefined/empty/\"\" → \"/index.js\"\n * - Absolute paths (start with /) → normalized as-is\n * - Relative paths starting with \"./\" → converted to absolute from root\n * - Bare filenames (no leading ./ or /) → converted to absolute from root\n * - Paths starting with \"../\" → Error (can't resolve parent of root)\n * - Directory paths (\"/\" or \"./\") → append \"index.js\"\n *\n * @example\n * normalizeEntryFilename(undefined) // \"/index.js\"\n * normalizeEntryFilename(\"\") // \"/index.js\"\n * normalizeEntryFilename(\"app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"./app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"/app.js\") // \"/app.js\"\n * normalizeEntryFilename(\"./foo/bar.js\") // \"/foo/bar.js\"\n * normalizeEntryFilename(\"/\") // \"/index.js\"\n * normalizeEntryFilename(\"./\") // \"/index.js\"\n * normalizeEntryFilename(\"../app.js\") // throws Error\n *\n * @throws Error if the filename cannot be normalized (e.g., starts with \"../\")\n */\nexport function normalizeEntryFilename(filename: string | undefined): string {\n // Default to /index.js\n if (!filename || filename === \"\") {\n return \"/index.js\";\n }\n\n // Reject paths that try to go above root\n if (filename.startsWith(\"../\")) {\n throw new Error(\n `Invalid entry filename \"${filename}\": cannot use \"../\" at the start. ` +\n `Use an absolute path like \"/app.js\" or a relative path like \"./app.js\".`\n );\n }\n\n // Track if original path ends with / (indicates directory)\n const endsWithSlash = filename.endsWith(\"/\");\n\n let toNormalize: string;\n if (filename.startsWith(\"/\")) {\n // Already absolute\n toNormalize = filename;\n } else if (filename.startsWith(\"./\")) {\n // Relative from root: ./app.js → /app.js\n toNormalize = \"/\" + filename.slice(2);\n } else {\n // Bare filename: app.js → /app.js\n toNormalize = \"/\" + filename;\n }\n\n // Normalize path and check for escaping root\n const normalized = normalizePosixPath(toNormalize, filename);\n\n // Handle directory paths - append index.js\n if (normalized === \"/\" || endsWithSlash) {\n return normalized === \"/\" ? \"/index.js\" : normalized + \"/index.js\";\n }\n\n return normalized;\n}\n\n/**\n * Simple POSIX path normalization without external dependencies.\n * Handles . and .. segments, collapses multiple slashes.\n * Throws if path tries to escape above root.\n */\nfunction normalizePosixPath(p: string, originalFilename: string): string {\n if (p === \"\") return \".\";\n\n const isAbsolute = p.startsWith(\"/\");\n const segments = p.split(\"/\").filter(s => s !== \"\" && s !== \".\");\n const result: string[] = [];\n let parentCount = 0; // Track how many .. we've seen at root level\n\n for (const segment of segments) {\n if (segment === \"..\") {\n if (result.length > 0 && result[result.length - 1] !== \"..\") {\n result.pop();\n } else if (isAbsolute) {\n // For absolute paths, track attempts to go above root\n parentCount++;\n } else {\n result.push(\"..\");\n }\n } else {\n result.push(segment);\n }\n }\n\n // If we tried to go above root, throw an error\n if (isAbsolute && parentCount > 0 && result.length === 0) {\n // Only throw if we actually escaped (ended up at root after going above)\n // This catches cases like /foo/../../bar.js where we went above root\n }\n\n // Count segments before normalization to detect if we went above root\n const originalSegments = p.split(\"/\").filter(s => s !== \"\" && s !== \".\");\n let depth = 0;\n for (const segment of originalSegments) {\n if (segment === \"..\") {\n depth--;\n if (isAbsolute && depth < 0) {\n throw new Error(\n `Invalid entry filename \"${originalFilename}\": path resolves above root directory.`\n );\n }\n } else {\n depth++;\n }\n }\n\n const normalized = result.join(\"/\");\n return isAbsolute ? \"/\" + normalized : (normalized || \".\");\n}\n"
|
|
6
6
|
],
|
|
7
|
-
"mappings": ";AAcO,IAAM,cAAc;AAAA,EAEzB,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EAGxB,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EAGV,2BAA2B;AAAA,EAC3B,yBAAyB;AAAA,EACzB,8BAA8B;AAAA,EAC9B,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EAGzB,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,gBAAgB;AAAA,EAGhB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EAGtB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EAGrB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,gBAAgB;AAAA,EAGhB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EAGd,eAAe;AAAA,EACf,cAAc;AAAA,EAGd,MAAM;AAAA,EACN,MAAM;AACR;AAKO,IAAM,kBAA0C,OAAO,YAC5D,OAAO,QAAQ,WAAW,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CACpD;AAMO,IAAM,YAAY;AAAA,EAEvB,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EAGxB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EAGjB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAGhB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAGf,iBAAiB;AACnB;
|
|
7
|
+
"mappings": ";AAcO,IAAM,cAAc;AAAA,EAEzB,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,MAAM;AAAA,EACN,kBAAkB;AAAA,EAClB,wBAAwB;AAAA,EAGxB,SAAS;AAAA,EACT,YAAY;AAAA,EACZ,UAAU;AAAA,EAGV,2BAA2B;AAAA,EAC3B,yBAAyB;AAAA,EACzB,8BAA8B;AAAA,EAC9B,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EACtB,yBAAyB;AAAA,EAGzB,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,WAAW;AAAA,EACX,gBAAgB;AAAA,EAGhB,oBAAoB;AAAA,EACpB,sBAAsB;AAAA,EAGtB,aAAa;AAAA,EACb,gBAAgB;AAAA,EAChB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EAGrB,iBAAiB;AAAA,EACjB,mBAAmB;AAAA,EACnB,uBAAuB;AAAA,EACvB,uBAAuB;AAAA,EACvB,qBAAqB;AAAA,EACrB,wBAAwB;AAAA,EACxB,gBAAgB;AAAA,EAGhB,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,cAAc;AAAA,EAGd,eAAe;AAAA,EACf,cAAc;AAAA,EAGd,MAAM;AAAA,EACN,MAAM;AACR;AAKO,IAAM,kBAA0C,OAAO,YAC5D,OAAO,QAAQ,WAAW,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CACpD;AAMO,IAAM,YAAY;AAAA,EAEvB,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,wBAAwB;AAAA,EAGxB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,sBAAsB;AAAA,EACtB,iBAAiB;AAAA,EAGjB,cAAc;AAAA,EACd,gBAAgB;AAAA,EAGhB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EAGf,iBAAiB;AACnB;AAsgBO,IAAM,gBAAgB;AAAA,EAC3B,YAAY;AAAA,EACZ,mBAAmB;AAAA,EACnB,gBAAgB;AAAA,EAChB,iBAAiB;AACnB;AAGO,IAAM,eAAe;AAAA,EAC1B,kBAAkB;AAAA,EAClB,mBAAmB;AAAA,EACnB,kBAAkB;AAAA,EAClB,iBAAiB;AACnB;AA0oBO,SAAS,sBAAsB,CAAC,UAAsC;AAAA,EAE3E,IAAI,CAAC,YAAY,aAAa,IAAI;AAAA,IAChC,OAAO;AAAA,EACT;AAAA,EAGA,IAAI,SAAS,WAAW,KAAK,GAAG;AAAA,IAC9B,MAAM,IAAI,MACR,2BAA2B,+CAC3B,yEACF;AAAA,EACF;AAAA,EAGA,MAAM,gBAAgB,SAAS,SAAS,GAAG;AAAA,EAE3C,IAAI;AAAA,EACJ,IAAI,SAAS,WAAW,GAAG,GAAG;AAAA,IAE5B,cAAc;AAAA,EAChB,EAAO,SAAI,SAAS,WAAW,IAAI,GAAG;AAAA,IAEpC,cAAc,MAAM,SAAS,MAAM,CAAC;AAAA,EACtC,EAAO;AAAA,IAEL,cAAc,MAAM;AAAA;AAAA,EAItB,MAAM,aAAa,mBAAmB,aAAa,QAAQ;AAAA,EAG3D,IAAI,eAAe,OAAO,eAAe;AAAA,IACvC,OAAO,eAAe,MAAM,cAAc,aAAa;AAAA,EACzD;AAAA,EAEA,OAAO;AAAA;AAQT,SAAS,kBAAkB,CAAC,GAAW,kBAAkC;AAAA,EACvE,IAAI,MAAM;AAAA,IAAI,OAAO;AAAA,EAErB,MAAM,aAAa,EAAE,WAAW,GAAG;AAAA,EACnC,MAAM,WAAW,EAAE,MAAM,GAAG,EAAE,OAAO,OAAK,MAAM,MAAM,MAAM,GAAG;AAAA,EAC/D,MAAM,SAAmB,CAAC;AAAA,EAC1B,IAAI,cAAc;AAAA,EAElB,WAAW,WAAW,UAAU;AAAA,IAC9B,IAAI,YAAY,MAAM;AAAA,MACpB,IAAI,OAAO,SAAS,KAAK,OAAO,OAAO,SAAS,OAAO,MAAM;AAAA,QAC3D,OAAO,IAAI;AAAA,MACb,EAAO,SAAI,YAAY;AAAA,QAErB;AAAA,MACF,EAAO;AAAA,QACL,OAAO,KAAK,IAAI;AAAA;AAAA,IAEpB,EAAO;AAAA,MACL,OAAO,KAAK,OAAO;AAAA;AAAA,EAEvB;AAAA,EAGA,IAAI,cAAc,cAAc,KAAK,OAAO,WAAW,GAAG,CAG1D;AAAA,EAGA,MAAM,mBAAmB,EAAE,MAAM,GAAG,EAAE,OAAO,OAAK,MAAM,MAAM,MAAM,GAAG;AAAA,EACvE,IAAI,QAAQ;AAAA,EACZ,WAAW,WAAW,kBAAkB;AAAA,IACtC,IAAI,YAAY,MAAM;AAAA,MACpB;AAAA,MACA,IAAI,cAAc,QAAQ,GAAG;AAAA,QAC3B,MAAM,IAAI,MACR,2BAA2B,wDAC7B;AAAA,MACF;AAAA,IACF,EAAO;AAAA,MACL;AAAA;AAAA,EAEJ;AAAA,EAEA,MAAM,aAAa,OAAO,KAAK,GAAG;AAAA,EAClC,OAAO,aAAa,MAAM,aAAc,cAAc;AAAA;",
|
|
8
8
|
"debugId": "28FA9B4C27FCEF6764756E2164756E21",
|
|
9
9
|
"names": []
|
|
10
10
|
}
|