All skills
microsoft avatar

/playwright-dev

@08a37f2
by microsoftmicrosoft/playwright97k stars
6,529

Explains how to develop Playwright - add APIs, MCP tools, CLI commands, and vendor dependencies.

Use this Skill: https://skilld.dev/gh/microsoft/playwright/playwright-dev

This session only. Nothing lands on disk.

webview.md

≈1.7k tokens on demand. Your agent reads this file only when SKILL.md points to it.

WebView (iOS Safari) Backend Reference

Notes for developing the stock-Mobile-Safari backend in packages/playwright-core/src/server/webkit/webview/. The regular WebKit backend one level up (webkit/) runs against a Playwright-patched WebKit build; the webview/ folder targets unmodified Safari on real iOS/iPadOS or the iOS Simulator over the standard Web Inspector Protocol.

What is and isn't available

Stock Mobile Safari only exposes the upstream Web Inspector Protocol. Anything Playwright added to its forked WebKit is not available here.

Available — methods/events in Source/JavaScriptCore/inspector/protocol/*.json on browser_upstream/main:

git -C ~/webkit show browser_upstream/main:Source/JavaScriptCore/inspector/protocol/<Domain>.json

Not available — anything added by the Playwright WebKit patches:

ls ~/playwright-browsers/browser_patches/webkit/patches/  # bootstrap.diff lives here

Quick provenance check for a symbol — in ~/webkit:

git log --all -S "<symbol>" -- <path>

If every hit is a chore(webkit): bootstrap build commit, it's a Playwright patch. Some traps where the upstream name overlaps with a Playwright-only helper of similar intent:

  • Target.setPauseOnStart / Target.resume (upstream, gates loading of provisional process-swap targets) vs PageInspectorController::pauseOnStart / resumeIfPausedInNewWindow (Playwright patch, for window.open popups). They sound the same; they aren't.
  • Playwright.* domain (cookies, navigate, all global controls) — entirely Playwright. Use stock equivalents on the page session (e.g. Page.getCookies).
  • Network.continueWithAuth, intercepted-response body access via Network — Playwright extensions.

Architecture

This backend deliberately mirrors the regular WebKit backend one level up (wkConnection.ts / wkPage.ts / wkProvisionalPage.ts). When in doubt, read the WK equivalent — the WV class should look almost the same. The outerSession is the WV analogue of WK's page-proxy session.

WebSocketTransport (ws://localhost:9222/devtools/page/<n>, via ios_webkit_debug_proxy)
  → WVConnection            — dumb transport; owns only outerSession
      → WVConnection.outerSession (sessionId "")  — Target.sendMessageToTarget bridge
          → WVPage          — owns per-target WVSessions, routes
                              Target.dispatchMessageFromTarget, manages swaps
              → _session (current) + WVProvisionalPage (during a swap)
              → WVExecutionContext, WVWorkers, RawKeyboard/Mouse/Touchscreen
                (all hold a session reference, all have setSession() for swap)

WVConnection is intentionally minimal: it pumps the transport into outerSession and back. WVPage creates the per-target WVSessions (_createSession), routes Target.dispatchMessageFromTarget by targetId to either _session or _provisionalPage._session, and handles Target.targetCreated/targetDestroyed/didCommitProvisionalTarget — exactly like WKPage. WVPage is constructed with the outer session (not a target session); _session starts undefined and is bound on the first Target.targetCreated via _setSession. WVBrowser._attachTab awaits page.waitForInitialized() (resolves after the first target is reported as new) instead of waiting on the connection.

Process swap / provisional targets

Cross-origin navigation in an existing tab can make Mobile Safari spawn a new process. The protocol sequence is:

Target.targetCreated  targetInfo:{ isProvisional:true, isPaused:true }
... events on the provisional target during the navigation ...
Target.didCommitProvisionalTarget  oldTargetId, newTargetId
Target.targetDestroyed  oldTargetId

Handling mirrors WK — WVProvisionalPage ≈ WKProvisionalPage, swapped in by WVPage._onDidCommitProvisionalTarget. The one essential trick: Target.setPauseOnStart (sent in WVBrowser._attachTab) makes provisional targets arrive isPaused, so WVPage can set up interception / bootstrap before resuming them with Target.resume; otherwise the new process races ahead and page.route(...) never fires.

Not to be confused with the popup-pause path (window.open), which is a Playwright patch (PageInspectorController::pauseOnStart) with no stock-Safari equivalent.

Test infrastructure

tests/webview/
  playwright.config.ts        — single project "webkit-webview-page", runs tests/page/
  webviewTest.ts              — fixture: discovers tab via ios_webkit_debug_proxy /json,
                                resets Mobile Safari between tests
  expectations/
    webkit-webview-page.txt   — `<test path> › <name> [fail|flaky|timeout|skip]`
  expectationUtil.ts          — loader + skip-decision logic

[fail] entries cause it.skip() to fire before the test body runs — so a formerly-failing test that now passes won't be flagged automatically, you have to remove the line and re-run. The marker also has prefix-match semantics for it.step children.

Running locally

./utils/run_webview_tests.sh           # ensures ios_webkit_debug_proxy is up on 9222
npm run wvtest -- -g "<test title>"    # single test
npm run wvtest -- tests/page/foo.spec.ts
DEBUG=pw:protocol npm run wvtest -- -g "<title>" > /tmp/log 2>&1

The simulator needs to be booted with one Mobile Safari tab. The script's only job is keeping a single ios_webkit_debug_proxy -F -d -s unix:<socket> -c null:9221,:9222-9322 alive; everything else is done by the fixture.

Common local pitfalls

  • Multiple ios_webkit_debug_proxy processes — every protocol event is delivered through each instance, so debug logs show events duplicated and some tests flake. pgrep -lf ios_webkit_debug_proxy and clean up.
  • Chrome bound to 127.0.0.1:9222 — Chrome's --remote-debugging-port=9222 shadows iwdp's *:9222 listener for traffic addressed to localhost. Kill the Chrome instance (lsof -nP -iTCP -sTCP:LISTEN | grep 9222).
  • Stale launchd socket — lsof -aUc launchd_sim should show com.apple.webinspectord_sim.socket for the currently booted simulator. If iwdp was started against an older launchd_sim socket path it will silently serve nothing.

CI

.github/workflows/tests_webview_simulator.yml runs the same suite on macos-15 (booted iOS Simulator + brew install ios-webkit-debug-proxy). Triggers: workflow_dispatch, and pull_request only when paths under tests/webview/**, the webview/ source folder, or the workflow file itself change.

Source: SKILL.md on GitHub

1 warning16d5 checks · Risk SAFE
  • Gen Agent Trust Hub16d

    This skill provides a detailed set of development guides for the Playwright project, covering API implementation, tool creation, and architectural overview. It includes instructions for standard development tasks such as building, testing, and dependency management. While the skill describes the creation of tools that interact with untrusted agent input, it emphasizes the use of validation schemas to manage these boundaries.

  • Socket16d

    No alerts

  • Snyk16d

    Risk: LOW · No issues

  • Runlayer6mo

    2/5 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 08a37f2. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated 4 months ago
  • Testing
  • CLI
  • MCP
  • playwright
  • browser-automation
  • api-development
  • vendor-dependencies
  • webkit
  • monorepo

README badge

README badge for microsoft/playwright/playwright-dev

Explains how to extend Playwright itself — adding client/server APIs, MCP tools, CLI commands, and vendor dependencies. Targets contributors to the Playwright monorepo, not end users building test suites.

Generated from the current SKILL.md.

What does this skill help me do?
This skill explains how to develop Playwright itself — adding APIs, MCP tools, CLI commands, and managing vendor dependencies. It's for contributors working on the Playwright codebase, not for using Playwright as a testing library.
Does this cover the monorepo structure and build commands?
Yes. It references CLAUDE.md for monorepo structure, build/test/lint commands, and coding conventions.
Can I learn how to add new APIs or MCP tools to Playwright?
Yes. The skill includes detailed guides on adding and modifying APIs, implementing client/server logic, and adding MCP tools and CLI commands.
Does this cover WebView or WebKit backend development?
Yes. It includes guides for WebView (iOS Safari) backend work and updating WebKit Safari versions.
Is this for using Playwright as a test framework, or for developing Playwright itself?
This is for developing Playwright itself. If you want to write tests with Playwright, you need a different resource.

Generated from the current SKILL.md. These answers refresh after source changes.