← Commit history

Delete the destructive width-wiggle: it shrank windows to a marker width to identify them and left one stuck narrow when the restore failed (deformed John's window). Handle resolution now uses only read-only signals (birth-time capture, persisted handle, sole-window-of-profile); a window none resolve is left bare rather than resized

John Lauer ·54095b080a ·3mo ago ·parent 8d12708
4 files changed +13−35
adom-bridge-puppeteer-manifest.json+4−4
@@ -1,10 +1,10 @@ {   "manifest_version": 1,   "name": "puppeteer",-  "version": "1.9.307",-  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.307/adom-bridge-puppeteer-v1.9.307.zip",-  "sha256": "d4c827142ec12f31d70f59461361ebd1d2af85cc5105aae93854dcd4c87134ec",-  "size": 728109,+  "version": "1.9.308",+  "url": "https://wiki.adom.inc/download/adom/adom-desktop-puppeteer-bridge/1.9.308/adom-bridge-puppeteer-v1.9.308.zip",+  "sha256": "43c6bf1c78732a40140b035cb28e7c66e1e29e4e43d79087c78bd08559ab1f90",+  "size": 727455,   "verbPrefixes": [     "browser_",     "desktop_recorder_",
src/BRIDGE_VERSION+1−1
@@ -1 +1 @@-1.9.307+1.9.308
src/bridge.json+1−1
@@ -2,7 +2,7 @@   "manifest_version": 1,   "name": "puppeteer",   "displayName": "Puppeteer (Chrome for Testing + Native)",-  "version": "1.9.307",+  "version": "1.9.308",   "description": "Drives a browser ALREADY on the machine \u2014 installed Chrome, else Microsoft Edge (every Windows PC ships with Edge) \u2014 launched with a FRESH isolated profile, so the common case has NO ~150 MB Chrome-for-Testing download and it never touches the user's real tabs/logins. Binds its local server to LOOPBACK (127.0.0.1) only, so no Windows Firewall 'allow Node through the firewall' prompt ever pops. Chrome for Testing is fetched only as a LAST RESORT if the machine has no Chromium browser at all. SPAWN-VERIFIED fallback: pup tries each detected browser (Chrome \u2192 Edge \u2192 CfT) and actually launches it, falling through to the next if one won't start (and handling browsers like Edge that relaunch onto another PID), so a corrupt/partial install never hard-fails an open. The browser that launches is cached as the default (persisted across restarts) so it isn't re-probed each time. On spawn the bridge SELF-WARMS: detects browsers + disk, and only if the box has no Chrome/Edge and no cached CfT does it background-fetch CfT so the first open is instant. browser_use pins a specific browser (chrome | edge | cft | auto); {browser:'chrome',install:true} downloads & installs REAL Google Chrome (user-scoped, no admin) on an Edge-only box. browser_readiness (READ-ONLY) reports which browser will be used + the full candidate list + the default + free disk. Every failure returns a specific errorCode + _hint (chrome_install_no_disk, chrome_download_network, chrome_install_permission, chrome_stable_not_detected, \u2026). Launches with FULL browser permissions by default for full debug (strictPermissions:true opts out). Headful automation: open/close windows+tabs, navigate, screenshot, eval JS, record. pup is a GENERIC, non-profile browser only \u2014 every session is a fresh isolated Chrome/Edge process, never the user's real signed-in browser; profile defaults to sessionId. To drive the user's REAL Chrome/Edge (their profile, cookies, SSO), use the Adom browser EXTENSION's nbrowser_* verbs \u2014 a separate bridge, not pup's job. macOS (v1.9.74+): full parity with mac-native mechanics \u2014 background-by-default is the app-level hide (windows stay drivable/screenshottable while hidden), raise/lower map to unhide+activate/hide, browser_alert_window posts a native toast whose click focuses the window, browser_use {browser:'chrome',install:true} installs Chrome from the official dmg, and taskbar identity/badging remains Windows-only.",   "homepage": "https://wiki.adom.inc/adom/adom-desktop",   "author": "Adom Inc.",
src/server.js+7−29
@@ -5007,35 +5007,13 @@ async function resolveSessionHwndByBounds(session, sessionId) {     // sessions concurrently; if their width-changes + enumerations overlap, every session matches     // whichever window is momentarily at a marker width — collapsing them onto one hwnd. Take a     // global lock so exactly one wiggle (set width -> enumerate -> restore) runs at a time.-    if (!session._foreground) {-      // v1.9.300 (John: "you are way unsynchronized... still a disaster" — every window came back-      // hwnd=None and the regenerate sweep was stuck): the OLD lock did `await _prev` BEFORE assigning-      // _releaseWiggle, so if the previous holder ever hung, this call blocked forever at the await,-      // never set its own releaser (the outer catch couldn't free it), and it had ALREADY published an-      // unresolved promise as _wiggleLock — wedging the entire chain. Assign the releaser FIRST, then-      // time-box the wait so a hung holder can never wedge us: if _prev doesn't settle in 8s we proceed-      // anyway (a briefly-overlapping wiggle is far better than a permanent deadlock), and our own-      // releaser always frees the next caller.-      const _prev = _wiggleLock; let _res; _wiggleLock = new Promise(r => { _res = r; }); _releaseWiggle = _res;-      // v1.9.302: 15s wait (was 8s). The old 8s was SHORTER than the 9s PS enumeration each holder-      // runs, so under load the wait timed out and TWO wiggles ran concurrently — both windows sat at-      // a marker width at once and every session matched whichever the enum hit first (the collapse-      // that put 3 sessions on ONE handle). 15s comfortably exceeds a full wiggle, so normal operation-      // stays strictly serialized; the timeout only fires on a genuine hang (a deadlock ceiling).-      await Promise.race([Promise.resolve(_prev), new Promise(r => setTimeout(r, 15000))]);-      try {-        // DISTINCTIVE narrow marker (480-599) that no real browser window sits at, so the shrunk-        // target is the ONLY window in that band. The old near-original width (orig-3) sat right on-        // top of real ~1500px windows and matched them by accident.-        markerW = 480 + (_hwndWiggle++ % 120);-        await cdp.send('Browser.setWindowBounds', { windowId, bounds: { width: markerW } });-        _widthChanged = true;-        await new Promise(r => setTimeout(r, 140));-        // VERIFY the width actually applied — a minimized/un-settable window would otherwise leave us-        // matching on a width we never set (a wrong handle). If it didn't take, abandon the wiggle.-        try { const rb = await cdp.send('Browser.getWindowBounds', { windowId }); if (!rb || !rb.bounds || Math.abs(rb.bounds.width - markerW) > 2) markerW = null; } catch (e) { markerW = null; }-      } catch (e) { markerW = null; }-    }+    // v1.9.308 (John: "why did you resize this window so weird? what the fuck?"): the width-WIGGLE is+    // DELETED. It shrank the window to a marker width to identify it, and when the restore failed it+    // left the window stuck narrow — visibly deforming John's window. NEVER acceptable. Handle+    // resolution now uses ONLY read-only signals: the birth-time capture, the persisted handle, and+    // the sole-window-of-a-profile check below — none of which touch window geometry. A window none of+    // those can resolve is left BARE (no overlay), which is fine; mangling the user's window is not.+    // markerW stays null, so the matching loop below is pure read-only geometry (no setWindowBounds).     const scriptPath = path.join(require('os').tmpdir(), `_adom_hwnd_${process.pid}.ps1`);     // CSS bounds -> physical px via the DPI scale, then match a top-level window of ANY chrome.exe     // in this profile's process tree by position (a small tolerance absorbs frame/DPI rounding).