Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 16 additions & 9 deletions src/lib/console.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import ConsoleExecutor, {
applyConsoleViewport,
executeConsoleCommand,
executeConsoleScript,
resolveConsoleExecutionContext,
} from "./consoleRuntime";

(function () {
Expand Down Expand Up @@ -69,14 +70,14 @@ import ConsoleExecutor, {
title: "Choose isolated Worker execution or live page access",
},
children: [
tag("option", {
textContent: "Page",
attr: { value: "page" },
}),
tag("option", {
textContent: "Worker",
attr: { value: "worker" },
}),
tag("option", {
textContent: "Page (unsafe)",
attr: { value: "page" },
}),
],
onchange() {
if (this.value !== "page") return;
Expand All @@ -97,7 +98,10 @@ import ConsoleExecutor, {
children: [
$input,
tag("c-input-actions", {
children: [$executionContext, $stopExecution],
children: [
...(isStandaloneConsole ? [] : [$executionContext]),
$stopExecution,
],
}),
],
});
Expand Down Expand Up @@ -209,7 +213,7 @@ import ConsoleExecutor, {
async function runStartupScript() {
if (!startupScriptUrl) return;

setExecutionState(true, "worker");
setExecutionState(true);
const result = await executeConsoleScript({
scriptUrl: startupScriptUrl,
workerExecutor: executor,
Expand Down Expand Up @@ -448,10 +452,10 @@ import ConsoleExecutor, {
$input.focus();
}

function setExecutionState(running, context = $executionContext.value) {
function setExecutionState(running) {
isExecuting = running;
$console.toggleAttribute("running", running);
$stopExecution.hidden = !running || context !== "worker";
$stopExecution.hidden = !running || $executionContext.value !== "worker";
$input.disabled = running;
$executionContext.disabled = running;
}
Expand Down Expand Up @@ -861,7 +865,10 @@ import ConsoleExecutor, {

function executeCommand(code) {
return executeConsoleCommand({
context: $executionContext.value,
context: resolveConsoleExecutionContext(
isStandaloneConsole,
$executionContext.value,
),
code,
workerExecutor: executor,
pageExecutor: execute,
Expand Down
11 changes: 9 additions & 2 deletions src/lib/consoleRuntime.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,19 @@ export function applyConsoleViewport(element, windowObject = window) {
element.style.setProperty("--console-viewport-left", `${left}px`);
}

export function resolveConsoleExecutionContext(
isStandaloneConsole,
selectedContext,
) {
return isStandaloneConsole ? "worker" : selectedContext;
}

/**
* Routes a console command to the isolated worker or the live preview page.
* Page execution keeps browser objects inspectable; workers isolate scripts.
* Page execution is deliberately opt-in because it runs on the preview thread.
*/
export function executeConsoleCommand({
context = "page",
context,
code,
workerExecutor,
pageExecutor,
Expand Down
11 changes: 9 additions & 2 deletions tests/unit/consoleExecutionContext.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,16 @@ import { describe, expect, it } from "vitest";
import {
executeConsoleCommand,
executeConsoleScript,
resolveConsoleExecutionContext,
} from "lib/consoleRuntime";

describe("console execution context", () => {
it("uses isolated worker execution when selected", async () => {
it("forces standalone menu consoles to use the worker", () => {
expect(resolveConsoleExecutionContext(true, "page")).toBe("worker");
expect(resolveConsoleExecutionContext(false, "page")).toBe("page");
});

it("uses isolated worker execution by default", async () => {
const calls = [];
const result = await executeConsoleCommand({
context: "worker",
Expand All @@ -25,9 +31,10 @@ describe("console execution context", () => {
expect(result.value).toBe("isolated");
});

it("evaluates interactive commands in the live page by default", async () => {
it("restores live page execution when explicitly selected", async () => {
const calls = [];
const result = await executeConsoleCommand({
context: "page",
code: 'document.querySelector("main")',
workerExecutor: {
execute(code) {
Expand Down
Loading