Skip to content

Conversation

@rekmarks
Copy link
Member

@rekmarks rekmarks commented Jan 31, 2026

Summary

This PR consolidates all console logs from the extension's various contexts (background, offscreen, kernel worker, vat iframes) into the background service worker, and captures them in packages/*/logs during Playwright e2e tests for debugging.

Previously, console logs from different extension contexts were difficult to capture in Playwright tests because:

  • Offscreen documents, workers, and iframes have limited Playwright console access
  • Each context required separate capture mechanisms (CDP, service worker events, etc.)

Now, all console logs flow through the background service worker using a standardized ConsoleForwardMessage format, making capture straightforward.

Changes

  • Console forwarding infrastructure (kernel-browser-runtime):

    • Add source field to ConsoleForwardMessage to identify log origins
    • Add setupConsoleForwarding() for stream-based forwarding (offscreen, kernel-worker)
    • Add setupPostMessageConsoleForwarding() for iframe-based forwarding (vat iframes)
    • Export stringifyConsoleArg() utility for consistent argument serialization
  • Extension integration:

    • Offscreen forwards its own logs and relays vat iframe logs to background
    • Kernel worker forwards logs through offscreen to background
    • Vat iframes post console messages to parent (offscreen) using standard format
    • Background receives all logs with source prefixes like [offscreen], [kernel-worker], [vat-v1]
  • Playwright test capture (repo-tools):

    • Capture background service worker console logs to file
    • Auto-attach log files to test results for HTML report viewing
    • Add CDP-based capture for additional context (workers, iframes)
  • Dependencies: Bump Playwright to latest version

Testing

Unit tests cover the console-forwarding module including message type guards, argument stringification, stream-based forwarding, and postMessage-based forwarding. The e2e tests exercise the full flow by running the extension and capturing logs.

🤖 Generated with Claude Code


Note

Medium Risk
Medium risk because it changes runtime behavior in multiple extension contexts by monkey-patching console and routing new JSON-RPC messages through existing streams; mistakes could affect logging/perf or message handling.

Overview
Adds a standardized JSON-RPC console-forward message flow to consolidate extension logs (vat iframes → offscreen → background; kernel worker/offscreen → background) and replay them in the background console for easier debugging.

Introduces kernel-browser-runtime utilities (setupConsoleForwarding, setupPostMessageConsoleForwarding, handleConsoleForwardMessage, isConsoleForwardMessage, stringifyConsoleArg) with unit tests, and wires them into background.ts, offscreen.ts, kernel-worker.ts, and vat/iframe.ts.

Enhances Playwright extension test utilities to persist per-test console logs to ./logs and auto-attach them to test reports; updates workspace clean scripts to remove ./logs and bumps Playwright deps to ^1.57.0.

Written by Cursor Bugbot for commit fbaaaef. This will update automatically on new commits. Configure here.

rekmarks and others added 11 commits January 30, 2026 11:41
…e tests

Add log capture for background service worker, offscreen document, and
popup page console output during e2e tests. Logs are written to a
timestamped file in <package>/logs/ and the path is attached to
Playwright test results for easy access.

Co-Authored-By: Claude <noreply@anthropic.com>
…ames

Log files are now named with a run ID (timestamp of Playwright invocation)
and test name to allow grouping logs from the same test run and easily
identifying which test produced which logs.

Format: <runId>-<testName>.log

Co-Authored-By: Claude <noreply@anthropic.com>
Update yarn constraints to enforce ./logs in all workspace clean scripts,
ensuring e2e test log files are cleaned up with other build artifacts.

Co-Authored-By: Claude <noreply@anthropic.com>
Move console message forwarding functionality from the extension package to
@metamask/kernel-browser-runtime as reusable utilities. This enables log
capture from offscreen documents and other contexts via DuplexStream.

- Create console-forwarding utilities with types and validators
- Update extension to import from kernel-browser-runtime
- Add console-forwarding exports to kernel-browser-runtime index

Co-Authored-By: Claude <noreply@anthropic.com>
…ude script

Implement a prelude script that wraps console methods BEFORE module code runs,
enabling capture of early initialization logs that were previously lost. Uses
chrome.runtime.sendMessage for immediate forwarding to background without
waiting for stream setup.

Changes:
- Add console-forwarding-prelude.js to kernel-browser-runtime/src/static
- Extend html-trusted-prelude Vite plugin to accept additional preludes
- Configure extension to inject prelude before endoify.js
- Update background.ts to handle console-forward-prelude messages
- Remove stream-based console forwarding from offscreen.ts (now handled by prelude)
- Configure eslint to ignore static/*.js files

Co-Authored-By: Claude <noreply@anthropic.com>
…via prelude script"

This reverts commit 20105ded24b211b08faab6d03d1efb6523c15d1f.
Enhance Playwright test logging to capture console output from all extension
contexts including vat iframes and kernel workers. Uses Chrome DevTools
Protocol (CDP) to access execution contexts that Playwright doesn't expose
directly through its API.

Changes:
- Add CDP-based console capture for iframe logs (vat iframes)
- Add worker.on('console') listener for kernel worker logs
- Add writeRawLog helper for CDP events without ConsoleMessage objects
- Track CDP sessions for proper cleanup
- Add CDP type definitions for Runtime domain events

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
…service worker

Add source field to ConsoleForwardMessage to identify log origins (offscreen,
kernel-worker, vat-*). Forward console logs from kernel worker and vat iframes
through offscreen to background, enabling centralized logging for production
and simplified Playwright capture.

- Add source field to ConsoleForwardMessage type
- Add source parameter to setupConsoleForwarding()
- Extract stringifyConsoleArg() as public utility
- Forward kernel worker logs via stream to background
- Forward vat iframe logs via postMessage to offscreen
- Add unit tests for console-forwarding module

Co-Authored-By: Claude <noreply@anthropic.com>
…me logs

Move setupIframeConsoleForwarding to console-forwarding.ts as
setupPostMessageConsoleForwarding and use the standard ConsoleForwardMessage
format. This allows offscreen to validate messages using isConsoleForwardMessage
and simplifies the relay logic.

- Add setupPostMessageConsoleForwarding() for iframe console forwarding
- Use standard ConsoleForwardMessage format (jsonrpc + params) via postMessage
- Simplify offscreen message handler to use isConsoleForwardMessage
- Add unit tests for setupPostMessageConsoleForwarding

Co-Authored-By: Claude <noreply@anthropic.com>
Add attachLogs() function that reads the log file and attaches it to test
results. The extension helper now wraps browserContext.close() to auto-attach
logs before closing, so tests don't need to be modified.

This fixes the issue where logs were written to packages/extension/logs/
but not attached to test-results for viewing in the Playwright HTML report.

Co-Authored-By: Claude <noreply@anthropic.com>
@rekmarks rekmarks requested a review from a team as a code owner January 31, 2026 00:45
@socket-security
Copy link

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updated@​playwright/​test@​1.58.0 ⏵ 1.57.010010010099100
Updatedplaywright@​1.58.0 ⏵ 1.57.010010010099100

View full report

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 5 potential issues.

}
// Objects, arrays, null, undefined, functions, symbols, etc.
return JSON.stringify(arg);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stringifyConsoleArg returns undefined instead of string

Medium Severity

The stringifyConsoleArg function declares return type string but returns undefined when given undefined input. JSON.stringify(undefined) returns the value undefined, not a string. This causes the args array (typed as string[]) to contain undefined values at runtime. When serialized for transmission, undefined in arrays becomes null, so logs containing undefined will incorrectly display as null, altering the meaning of debug output.

Additional Locations (1)

Fix in Cursor Fix in Web

// Only set up CDP for pages that might have iframes (offscreen document)
if (!page.url().includes('offscreen.html')) {
return;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CDP setup checks URL before page navigation completes

Low Severity

The setupCdpForIframeConsoleLogs function checks page.url() synchronously at line 222, but the comment on line 161 acknowledges that "Pages may start at about:blank". The console handler correctly checks URL inside its callback, but the CDP setup returns early if the page hasn't navigated yet, potentially causing iframe console logs to never be captured via CDP.

Fix in Cursor Fix in Web

typeof value === 'object' &&
value !== null &&
'method' in value &&
(value as { method: unknown }).method === 'console-forward';
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Type guard validates method but not params structure

Low Severity

The isConsoleForwardMessage type guard only validates that method === 'console-forward', but asserts the value is a full ConsoleForwardMessage with properly structured params. When handleConsoleForwardMessage destructures message.params to access source, method, and args, a malformed message like {method: 'console-forward'} would pass the guard but crash with a TypeError. Since offscreen.ts accepts messages via window.addEventListener('message') from any iframe, a malformed postMessage could crash the background script.

Additional Locations (1)

Fix in Cursor Fix in Web

});

harden(globalThis.console);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated console wrapping logic in two functions

Medium Severity

setupConsoleForwarding (lines 60-90) and setupPostMessageConsoleForwarding (lines 115-139) share nearly identical logic: copying original console, iterating the same methods array, wrapping each method, creating identical ConsoleForwardMessage structures, mapping args with stringifyConsoleArg, and calling harden(). Only the forwarding mechanism differs. A shared helper function could eliminate this duplication.

Fix in Cursor Fix in Web

});

// Track CDP sessions for cleanup
const cdpSessions: CDPSession[] = [];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused cdpSessions array tracked but never used

Low Severity

The cdpSessions array is declared with a comment "Track CDP sessions for cleanup" and CDP sessions are pushed to it (line 227), but the array is never read or used for any cleanup. This is dead code that serves no purpose.

Fix in Cursor Fix in Web

@rekmarks rekmarks marked this pull request as draft January 31, 2026 00:54
@github-actions
Copy link
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 87.62%
⬇️ -0.79%
5908 / 6742
🔵 Statements 87.53%
⬇️ -0.77%
6005 / 6860
🔵 Functions 86.36%
⬇️ -0.76%
1539 / 1782
🔵 Branches 83.85%
⬇️ -0.74%
2140 / 2552
File Coverage
File Stmts Branches Functions Lines Uncovered Lines
Changed Files
packages/extension/src/background.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
17-175
packages/extension/src/offscreen.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
19-102
packages/kernel-browser-runtime/src/kernel-worker/kernel-worker.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
26-103
packages/kernel-browser-runtime/src/utils/console-forwarding.ts 100% 100% 100% 100%
packages/kernel-browser-runtime/src/utils/index.ts 100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
100%
🟰 ±0%
packages/kernel-browser-runtime/src/vat/iframe.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
13-45
packages/repo-tools/src/test-utils/extension.ts 0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
0%
🟰 ±0%
35-274
Generated in workflow #3496 for commit fbaaaef by the Vitest Coverage Report Action

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants