Description
Description
applyScreenshotViewport returns the previous viewport so the finally block can restore it:
const current = page.viewportSize(); // null when the context uses the real OS window (viewport: null)
...
return current; // → null
...
} finally {
if (previousViewport) await lease.page.setViewportSize(previousViewport); // null is falsy → never restores
}
When page.viewportSize() is null (stealth/persistent contexts commonly launch with viewport: null so the fingerprint matches the real window), the override viewport (e.g. 1280×720) is applied but never reverted. Every subsequent command in that persistent session then renders against the forced viewport instead of the real window.
The existing test (provider.test.ts:6) hard-codes a non-null viewport, so this code path is not covered.
Actual Behavior
If the original viewport is null, the restoration is skipped because the finally block only restores when previousViewport is truthy, leaving the session permanently pinned to the override size.
Suggested Fix
Restore the previous state unconditionally by tracking whether a viewport existed separately (e.g. with a hadViewport boolean), or explicitly handle the null case instead of relying on a truthiness check.
Steps to Reproduce
- Launch a persistent browser session against any page whose layout is viewport-sensitive:
webcmd browser mysession navigate --url https://example.com
- Take a screenshot with an explicit --width/--height override (the flag help says this is "for this screenshot only"):
webcmd browser mysession screenshot --width 375 --height 812 --out phone.png
- Take a second screenshot in the same session with no override, expecting the original real-window size back:
webcmd browser mysession screenshot --out after.png
- See the bug: after.png is still rendered at 375×812 (the override was never reverted), instead of the session's real window size. Any later navigate/snapshot/exec in that session also renders at the pinned size. This happens whenever the Cloak context has no fixed viewport (page.viewportSize() returns null, i.e. the stealth context uses the real OS window) — the override is applied but the restore in the finally block is skipped because previousViewport is null.
Expected Behavior
A temporary screenshot viewport override should always be restored after the screenshot completes, including when the original viewport is null.
webcmd Version
0.3.4
Node.js Version
22.x
Operating System
macOS
Logs / Screenshots
Description
Description
applyScreenshotViewportreturns the previous viewport so thefinallyblock can restore it:When
page.viewportSize()isnull(stealth/persistent contexts commonly launch withviewport: nullso the fingerprint matches the real window), the override viewport (e.g.1280×720) is applied but never reverted. Every subsequent command in that persistent session then renders against the forced viewport instead of the real window.The existing test (
provider.test.ts:6) hard-codes a non-null viewport, so this code path is not covered.Actual Behavior
If the original viewport is
null, the restoration is skipped because thefinallyblock only restores whenpreviousViewportis truthy, leaving the session permanently pinned to the override size.Suggested Fix
Restore the previous state unconditionally by tracking whether a viewport existed separately (e.g. with a
hadViewportboolean), or explicitly handle thenullcase instead of relying on a truthiness check.Steps to Reproduce
webcmd browser mysession navigate --url https://example.com
webcmd browser mysession screenshot --width 375 --height 812 --out phone.png
webcmd browser mysession screenshot --out after.png
Expected Behavior
A temporary screenshot viewport override should always be restored after the screenshot completes, including when the original viewport is
null.webcmd Version
0.3.4
Node.js Version
22.x
Operating System
macOS
Logs / Screenshots