fix(desktop): let Chromium allocate the debugging port

This commit is contained in:
Mohamed Boudra
2026-08-01 02:10:10 +02:00
parent 436da24e03
commit 1816e10de9
5 changed files with 21 additions and 74 deletions
+8 -7
View File
@@ -103,11 +103,11 @@ The iOS simulator shares the Mac's loopback, so `localhost:<port>` reaches the h
### Desktop renderer profiling
`npm run dev:desktop` starts Electron with Chromium remote debugging enabled so
renderer CPU profiles can be captured through CDP. It prefers
`http://127.0.0.1:9223` and automatically selects a free port when that port is
already occupied. The startup banner prints the selected URL. It launches its own
Electron-flavored Expo server and passes that URL to Electron. Set
`PASEO_ELECTRON_REMOTE_DEBUGGING_PORT` when a QA workflow requires a fixed port.
renderer CPU profiles can be captured through CDP. By default it passes
`--remote-debugging-port=0`, so Chromium atomically asks the OS for an available
port and prints the selected DevTools endpoint. Set
`PASEO_ELECTRON_REMOTE_DEBUGGING_PORT` when a QA workflow requires a validated,
fixed port.
Desktop dev also scopes Electron `userData` to the current dev root. This prevents
desktop-only environment inherited by terminals opened inside Paseo from coupling
@@ -126,8 +126,9 @@ npm run verify:electron-cdp --workspace=@getpaseo/desktop
```
The verifier reads the same `EXPO_PORT` and
`PASEO_ELECTRON_REMOTE_DEBUGGING_PORT` environment names as desktop dev. Set both when
testing an isolated instance on non-default ports.
`PASEO_ELECTRON_REMOTE_DEBUGGING_PORT` environment names as desktop dev. Set an
explicit remote-debugging port for verifier runs, and set both when testing an
isolated instance on non-default ports.
When running a dedicated Electron QA instance against a non-default Expo port, set
`EXPO_DEV_URL` explicitly. Desktop main defaults to `http://localhost:8081`, so
@@ -1,8 +1,5 @@
import net from "node:net";
import path from "node:path";
const DEFAULT_REMOTE_DEBUGGING_PORT = 9223;
export function resolveDevUserDataDir({ devRoot, inheritedUserDataDir, fallbackRoot }) {
if (devRoot) {
return path.join(devRoot, ".dev", "user-data");
@@ -33,53 +30,12 @@ function parsePort(value, name) {
return port;
}
export function findAvailablePort(preferredPort, host = "127.0.0.1") {
return new Promise((resolve, reject) => {
const server = net.createServer();
server.unref();
server.once("error", (error) => {
if (error.code === "EADDRINUSE" || error.code === "EACCES") {
resolve(findAvailablePort(0, host));
return;
}
reject(error);
});
server.listen(preferredPort, host, () => {
const address = server.address();
if (!address || typeof address === "string") {
server.close();
reject(new Error("Could not resolve an available CDP port"));
return;
}
server.close((error) => {
if (error) {
reject(error);
return;
}
resolve(address.port);
});
});
});
}
export async function selectRemoteDebuggingPort({
configuredPort,
preferredPort = DEFAULT_REMOTE_DEBUGGING_PORT,
findAvailablePort: findPort = findAvailablePort,
} = {}) {
if (configuredPort) {
return parsePort(configuredPort, "PASEO_ELECTRON_REMOTE_DEBUGGING_PORT");
}
return findPort(preferredPort);
}
export async function resolveDevRuntime(env = process.env) {
const remoteDebuggingPort = await selectRemoteDebuggingPort({
configuredPort: env.PASEO_ELECTRON_REMOTE_DEBUGGING_PORT,
});
export function resolveDevRuntime(env = process.env) {
const remoteDebuggingPort = env.PASEO_ELECTRON_REMOTE_DEBUGGING_PORT
? parsePort(env.PASEO_ELECTRON_REMOTE_DEBUGGING_PORT, "PASEO_ELECTRON_REMOTE_DEBUGGING_PORT")
: 0;
return {
electronFlags: buildElectronFlags(env.PASEO_ELECTRON_FLAGS, remoteDebuggingPort),
remoteDebuggingPort,
userDataDir: resolveDevUserDataDir({
devRoot: env.PASEO_DEV_ROOT,
inheritedUserDataDir: env.PASEO_ELECTRON_USER_DATA_DIR,
+9 -15
View File
@@ -2,8 +2,8 @@ import path from "node:path";
import { describe, expect, test } from "vitest";
import {
buildElectronFlags,
resolveDevRuntime,
resolveDevUserDataDir,
selectRemoteDebuggingPort,
} from "./dev-runtime-config.mjs";
describe("desktop dev runtime isolation", () => {
@@ -31,26 +31,20 @@ describe("desktop dev runtime isolation", () => {
);
});
test("selects another CDP port when the default is occupied", async () => {
const selectedPort = await selectRemoteDebuggingPort({
preferredPort: 9223,
findAvailablePort: async (preferredPort) => {
expect(preferredPort).toBe(9223);
return 43127;
},
test("lets Chromium atomically allocate the default CDP port", async () => {
const runtime = await resolveDevRuntime({
PASEO_DEV_RUNTIME_FALLBACK_ROOT: "/checkouts/paseo",
});
expect(selectedPort).toBe(43127);
expect(runtime.electronFlags).toBe("--remote-debugging-port=0");
});
test("honors an explicit CDP port without silently changing it", async () => {
const selectedPort = await selectRemoteDebuggingPort({
configuredPort: "9333",
findAvailablePort: async () => {
throw new Error("must not probe an explicit port");
},
const runtime = await resolveDevRuntime({
PASEO_DEV_RUNTIME_FALLBACK_ROOT: "/checkouts/paseo",
PASEO_ELECTRON_REMOTE_DEBUGGING_PORT: "9333",
});
expect(selectedPort).toBe(9333);
expect(runtime.electronFlags).toBe("--remote-debugging-port=9333");
});
});
-2
View File
@@ -36,7 +36,6 @@ $env:EXPO_DEV_URL = "http://localhost:$($env:EXPO_PORT)"
$env:PASEO_DEV_ROOT = $RootDir
$env:PASEO_DEV_RUNTIME_FALLBACK_ROOT = $RootDir
$DevRuntime = node "$ScriptDir\dev-runtime.mjs" | ConvertFrom-Json
$RemoteDebuggingPort = $DevRuntime.remoteDebuggingPort
$env:PASEO_ELECTRON_FLAGS = $DevRuntime.electronFlags
$env:PASEO_ELECTRON_USER_DATA_DIR = $DevRuntime.userDataDir
Remove-Item Env:\PASEO_DEV_RUNTIME_FALLBACK_ROOT -ErrorAction SilentlyContinue
@@ -104,7 +103,6 @@ Write-Host @"
Paseo Desktop Dev (Windows)
======================================================
Metro: http://localhost:$($env:EXPO_PORT)
CDP: http://127.0.0.1:$RemoteDebuggingPort
Daemon: $($env:PASEO_LISTEN) (isolated)
PASEO_HOME: $($env:PASEO_HOME)
userData: $($env:PASEO_ELECTRON_USER_DATA_DIR)
-2
View File
@@ -15,7 +15,6 @@ DEV_ROOT="${PASEO_DEV_ROOT:-$(default_dev_paseo_root)}"
export PASEO_DEV_ROOT="$DEV_ROOT"
export PASEO_DEV_RUNTIME_FALLBACK_ROOT="$DEV_ROOT"
DEV_RUNTIME="$(node "$SCRIPT_DIR/dev-runtime.mjs")"
REMOTE_DEBUGGING_PORT="$(node -e 'process.stdout.write(String(JSON.parse(process.argv[1]).remoteDebuggingPort))' "$DEV_RUNTIME")"
export PASEO_ELECTRON_FLAGS="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).electronFlags)' "$DEV_RUNTIME")"
export PASEO_ELECTRON_USER_DATA_DIR="$(node -e 'process.stdout.write(JSON.parse(process.argv[1]).userDataDir)' "$DEV_RUNTIME")"
unset PASEO_DEV_RUNTIME_FALLBACK_ROOT
@@ -38,7 +37,6 @@ echo "════════════════════════
echo " Paseo Desktop Dev"
echo "══════════════════════════════════════════════════════"
echo " Metro: ${EXPO_DEV_URL}"
echo " CDP: http://127.0.0.1:${REMOTE_DEBUGGING_PORT}"
echo " Daemon: ${PASEO_LISTEN}"
echo " Home: ${PASEO_HOME}"
echo " userData: ${PASEO_ELECTRON_USER_DATA_DIR}"