/** * Iframe executor for browser environments. * * This executor runs code in a sandboxed iframe, providing DOM isolation * and configurable security policies via the sandbox attribute. * * Key characteristics: * - Per-execution lifecycle: fresh iframe for each execute() call * - Configurable sandbox attributes (default: allow-scripts only) * - No shared module support (use MainThreadExecutor for that) * - Communication via postMessage */ import type { IExecutor, ExecuteOptions, ExecuteResult } from "../types"; /** * Options for creating an IframeExecutor. */ export interface IframeExecutorOptions { /** * Sandbox attributes for the iframe. * @default ["allow-scripts"] * * Common options: * - "allow-scripts": Required for code execution * - "allow-same-origin": Enables localStorage, cookies (reduces isolation) * - "allow-modals": Enables alert/confirm/prompt * * Security note: "allow-scripts" + "allow-same-origin" together allows * the iframe code to potentially remove the sandbox via script. */ sandbox?: string[]; /** * Default timeout in milliseconds. * @default 30000 */ defaultTimeout?: number; /** * Container element for iframes. * Iframes are created hidden (display: none). * @default document.body */ container?: HTMLElement; } /** * Message types for parent -> iframe communication. */ interface ExecuteMessage { type: "execute"; code: string; entryExport: "main" | "default"; context: Record; } /** * Message types for iframe -> parent communication. */ interface LogMessage { type: "log"; level: "log" | "warn" | "error" | "info" | "debug"; args: string; } interface ResultMessage { type: "result"; success: boolean; returnValue?: unknown; error?: string; } interface ReadyMessage { type: "ready"; } type IframeMessage = LogMessage | ResultMessage | ReadyMessage; /** * Bootstrap HTML that runs inside the iframe. * This is injected via srcdoc and handles: * 1. Console capture and forwarding * 2. Code execution via Blob URL import * 3. Result reporting back to parent */ const BOOTSTRAP_HTML = `