docs/playwright-maintenance.md
This document describes how to maintain Playwright integration in Camoufox.
Camoufox integrates Playwright's browser automation capabilities through patches and additional files. These need to be kept in sync with upstream Playwright development.
Location: patches/playwright/
| File | Purpose |
|---|---|
0-playwright.patch | Playwright's upstream patches. Must be kept up to date with bootstrap.diff |
1-leak-fixes.patch | Undos certain patches from 0-playwright.patch to fix memory leaks |
Location: additions/juggler/
The juggler directory contains Playwright's Juggler protocol implementation. These files must be kept in sync with:
Upstream Source: https://github.com/microsoft/playwright/tree/main/browser_patches/firefox/juggler
components/Juggler.js - Main Juggler component (legacy JSM format)components/Juggler.sys.mjs - ESM wrapper for Firefox 146+ compatibilitycomponents/components.conf - XPCOM component registrationFirefox 146 removed JSM (JavaScript Module) support in favor of ESM (ES Modules). To maintain compatibility:
components.conf uses esModule field instead of deprecated jsm field:
{
"esModule": "chrome://juggler/content/components/Juggler.sys.mjs",
"constructor": "JugglerFactory",
}
Juggler.sys.mjs acts as an ESM wrapper that imports the legacy JSM file:
const { JugglerFactory } = ChromeUtils.import(
"chrome://juggler/content/components/Juggler.js"
);
export { JugglerFactory };
This maintains backward compatibility while satisfying Firefox 146's static component generator requirements.
Compare the current patches/playwright/0-playwright.patch with Playwright's bootstrap.diff.
If changes are needed:
# Download latest bootstrap.diff
curl -o patches/playwright/0-playwright.patch \
https://raw.githubusercontent.com/microsoft/playwright/main/browser_patches/firefox/patches/bootstrap.diff
# Test the build
make clean && make dir && make build
Sync additions/juggler/ with upstream:
# Clone Playwright repository
git clone https://github.com/microsoft/playwright.git /tmp/playwright
# Compare directories
diff -r additions/juggler/ /tmp/playwright/browser_patches/firefox/juggler/
# Copy updated files (example)
cp -r /tmp/playwright/browser_patches/firefox/juggler/* additions/juggler/
# IMPORTANT: Preserve Firefox 146 ESM compatibility
# - Keep additions/juggler/components/Juggler.sys.mjs
# - Keep additions/juggler/components/components.conf with esModule field
After updating from upstream, ensure the ESM wrapper remains functional:
Check that Juggler.js still exports JugglerFactory:
var EXPORTED_SYMBOLS = ["Juggler", "JugglerFactory"];
var JugglerFactory = function() { /* ... */ };
If upstream changed the export name, update Juggler.sys.mjs accordingly.
Verify components.conf matches the format above (not upstream's format).
# Clean build to verify component registration
cd camoufox-146.0.1-beta.25
make clean
cd ..
make dir
cd camoufox-146.0.1-beta.25
./mach build
Expected: No linker errors about mozCreateComponent<nsICommandLineHandler>.
Common Error: If you see:
ld64.lld: error: undefined symbol: already_AddRefed<nsISupports> mozCreateComponent<nsICommandLineHandler>()
This means components.conf is not using ESM format. Fix by ensuring it has:
"esModule" field (not "jsm")"constructor": "JugglerFactory" field (not "type")Error: Externally-constructed components may not specify 'constructor' or 'legacy_constructor' properties
Cause: Using "jsm" field which is unsupported in Firefox 146.
Fix: Use "esModule" field instead.
Error: Externally-constructed components must specify a type other than nsISupports
Cause: Using external component without proper type specification.
Fix: Convert to ESM component with constructor.
Error: JavaScript components must specify a constructor
Cause: ESM component missing constructor field.
Fix: Add "constructor": "JugglerFactory" to components.conf.
If the build fails after updating Juggler files:
Juggler.js are still valid