Skip to content

v11.4.0

Choose a tag to compare

@doronz88 doronz88 released this 05 Sep 22:29
· 6 commits to master since this release
86aa6ea

Highlights

webinspector cdp drives a device from Playwright and Puppeteer

A Chrome-protocol client can now attach to a page on the device and actually drive it. Everything below is a method or event that Chrome's protocol requires and WebKit's Web Inspector does not implement at all, so each one affected any CDP client rather than a particular app — and each is now synthesized from what WebKit does expose.

pymobiledevice3 webinspector cdp --port 9223
# then, in Node:
#   const browser = await chromium.connectOverCDP('http://127.0.0.1:9223');
#   const page = browser.contexts()[0].pages()[0];
#   await page.goto('https://example.com/');
#   await page.locator('#search').fill('hello');
#   await page.screenshot({ path: 'shot.png' });

What works now that did not before:

  • Attaching to a page that was already open. The execution context was never announced for it, so the client waited forever for a page it could already see (#1900).
  • Navigation. page.goto(), page.reload() and waitForNavigation() hung until they timed out: the modern Page.lifecycleEvent was never emitted, and Page.navigate did not report the document it started, so a client waited for an in-page navigation that a real page load never sends (#1902).
  • Clicking and hovering. Every interaction spun in its actionability check until timeout, because the two calls a client makes before acting on an element — DOM.scrollIntoViewIfNeeded and DOM.getContentQuads — did not exist (#1903).
  • Screenshots. page.screenshot() died before any capture was attempted. Page.getLayoutMetrics and Page.captureScreenshot are now answered, the capture built on WebKit's own Page.snapshotRect (#1904).
  • Typing. fill(), pressSequentially(), type(), press() and keyboard.insertText() all left fields empty — silently, with every call reporting success, so a test could assert a filled field and be wrong. Text is written through the prototype's native value setter, so a framework that tracks its inputs actually sees the change (#1907).
  • Child frames. Frames were never announced, so a client never learned they existed; a connection attaching after a frame already existed could not see it at all. Frame discovery, reads and re-attachment now work, including cross-origin frames nested several levels deep (#1908).

🐛 Fixed a crash that took down the whole debugger connection

Attaching to a page that was already attached handed back the existing session id rather than opening a second session. Two sessions numbering their requests independently then received each other's answers, which trips an assertion inside the client and drops the entire connection — not just the extra session. page.context().newCDPSession() hits this, which is exactly the escape hatch people reach for.

📝 Known limitations

Update: the first two were fixed in v11.4.2. Both turned out to be defects in the bridge rather than limits of the platform — the second in particular was a parameter-name mismatch (Chrome's userGesture vs WebKit's emulateUserGesture), not the focus restriction described below. Upgrade rather than working around them.

  • Interacting with a node inside a child frame through a locator (click(), evaluate()) is not supported yet; it needs Chrome's node identity model, which WebKit does not expose. Tracked in #1908. Fixed in v11.4.2.
  • fill() into a cross-origin frame reports success and leaves the field empty. An element inside a cross-origin frame cannot be given focus from an evaluated script on this platform, and fill() selects, focuses, then types. Setting the value directly inside that frame works. Fixed in v11.4.2.
  • The first frameLocator() call into a newly created frame takes several seconds while the client bootstraps its injected script in that frame over USB. It is not a hang.

What's Changed

Full Changelog: v11.3.1...v11.4.0