browxai 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +139 -0
- package/THIRD_PARTY_NOTICES.md +45 -0
- package/dist/cli/chrome.d.ts +1 -0
- package/dist/cli/chrome.js +130 -0
- package/dist/cli/command-registry.d.ts +15 -0
- package/dist/cli/command-registry.js +35 -0
- package/dist/cli/doctor-plugins.d.ts +18 -0
- package/dist/cli/doctor-plugins.js +338 -0
- package/dist/cli/doctor.d.ts +9 -0
- package/dist/cli/doctor.js +407 -0
- package/dist/cli/init.d.ts +1 -0
- package/dist/cli/init.js +200 -0
- package/dist/cli/register-commands.d.ts +1 -0
- package/dist/cli/register-commands.js +22 -0
- package/dist/cli/serve.d.ts +14 -0
- package/dist/cli/serve.js +151 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.js +129 -0
- package/dist/engine/adapters/adb.d.ts +72 -0
- package/dist/engine/adapters/adb.js +200 -0
- package/dist/engine/adapters/android-cdp.d.ts +54 -0
- package/dist/engine/adapters/android-cdp.js +110 -0
- package/dist/engine/adapters/android.engine.d.ts +1 -0
- package/dist/engine/adapters/android.engine.js +31 -0
- package/dist/engine/adapters/chromium.engine.d.ts +1 -0
- package/dist/engine/adapters/chromium.engine.js +44 -0
- package/dist/engine/adapters/firefox.engine.d.ts +1 -0
- package/dist/engine/adapters/firefox.engine.js +43 -0
- package/dist/engine/adapters/playwright-chromium.d.ts +43 -0
- package/dist/engine/adapters/playwright-chromium.js +56 -0
- package/dist/engine/adapters/playwright-firefox.d.ts +52 -0
- package/dist/engine/adapters/playwright-firefox.js +97 -0
- package/dist/engine/adapters/playwright-webkit.d.ts +40 -0
- package/dist/engine/adapters/playwright-webkit.js +79 -0
- package/dist/engine/adapters/safari/bidi-client.d.ts +46 -0
- package/dist/engine/adapters/safari/bidi-client.js +130 -0
- package/dist/engine/adapters/safari/launch.d.ts +56 -0
- package/dist/engine/adapters/safari/launch.js +104 -0
- package/dist/engine/adapters/safari/webdriver-client.d.ts +102 -0
- package/dist/engine/adapters/safari/webdriver-client.js +175 -0
- package/dist/engine/adapters/safari.engine.d.ts +1 -0
- package/dist/engine/adapters/safari.engine.js +52 -0
- package/dist/engine/adapters/safaridriver-hybrid.d.ts +56 -0
- package/dist/engine/adapters/safaridriver-hybrid.js +127 -0
- package/dist/engine/adapters/webkit.engine.d.ts +1 -0
- package/dist/engine/adapters/webkit.engine.js +47 -0
- package/dist/engine/capabilities.d.ts +53 -0
- package/dist/engine/capabilities.js +122 -0
- package/dist/engine/capability-registry.d.ts +9 -0
- package/dist/engine/capability-registry.js +20 -0
- package/dist/engine/index.d.ts +18 -0
- package/dist/engine/index.js +14 -0
- package/dist/engine/register-engines.d.ts +5 -0
- package/dist/engine/register-engines.js +16 -0
- package/dist/engine/registry.d.ts +145 -0
- package/dist/engine/registry.js +67 -0
- package/dist/engine/select.d.ts +48 -0
- package/dist/engine/select.js +128 -0
- package/dist/engine/session-cdp.d.ts +13 -0
- package/dist/engine/session-cdp.js +22 -0
- package/dist/engine/tool-gate.d.ts +19 -0
- package/dist/engine/tool-gate.js +226 -0
- package/dist/engine/types.d.ts +71 -0
- package/dist/engine/types.js +16 -0
- package/dist/helper/bridge.d.ts +48 -0
- package/dist/helper/bridge.js +200 -0
- package/dist/helper/browx-page.d.ts +1 -0
- package/dist/helper/browx-page.js +47 -0
- package/dist/helper/overlay-hide.d.ts +9 -0
- package/dist/helper/overlay-hide.js +49 -0
- package/dist/helper/stealth.d.ts +10 -0
- package/dist/helper/stealth.js +88 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +15 -0
- package/dist/page/a11y.d.ts +81 -0
- package/dist/page/a11y.js +219 -0
- package/dist/page/action-substrate.d.ts +64 -0
- package/dist/page/action-substrate.js +118 -0
- package/dist/page/actionresult-blocks.d.ts +99 -0
- package/dist/page/actionresult-blocks.js +144 -0
- package/dist/page/actionresult-shape.d.ts +48 -0
- package/dist/page/actionresult-shape.js +155 -0
- package/dist/page/actionresult-types.d.ts +368 -0
- package/dist/page/actionresult-types.js +4 -0
- package/dist/page/actionresult.d.ts +4 -0
- package/dist/page/actionresult.js +299 -0
- package/dist/page/actions-probe.d.ts +32 -0
- package/dist/page/actions-probe.js +294 -0
- package/dist/page/actions-scroll.d.ts +40 -0
- package/dist/page/actions-scroll.js +53 -0
- package/dist/page/actions.d.ts +132 -0
- package/dist/page/actions.js +453 -0
- package/dist/page/archive-assets.d.ts +39 -0
- package/dist/page/archive-assets.js +187 -0
- package/dist/page/archive.d.ts +47 -0
- package/dist/page/archive.js +349 -0
- package/dist/page/asset-export.d.ts +122 -0
- package/dist/page/asset-export.js +376 -0
- package/dist/page/await_network.d.ts +16 -0
- package/dist/page/await_network.js +23 -0
- package/dist/page/bbox.d.ts +37 -0
- package/dist/page/bbox.js +115 -0
- package/dist/page/canvas-capture.d.ts +82 -0
- package/dist/page/canvas-capture.js +257 -0
- package/dist/page/canvas-diff.d.ts +51 -0
- package/dist/page/canvas-diff.js +131 -0
- package/dist/page/canvas-gesture.d.ts +53 -0
- package/dist/page/canvas-gesture.js +167 -0
- package/dist/page/canvas-transform.d.ts +96 -0
- package/dist/page/canvas-transform.js +150 -0
- package/dist/page/canvas.d.ts +8 -0
- package/dist/page/canvas.js +50 -0
- package/dist/page/capture-substrate.d.ts +111 -0
- package/dist/page/capture-substrate.js +139 -0
- package/dist/page/clipboard.d.ts +25 -0
- package/dist/page/clipboard.js +50 -0
- package/dist/page/clock.d.ts +36 -0
- package/dist/page/clock.js +167 -0
- package/dist/page/compose.d.ts +55 -0
- package/dist/page/compose.js +169 -0
- package/dist/page/console.d.ts +39 -0
- package/dist/page/console.js +73 -0
- package/dist/page/coverage.d.ts +97 -0
- package/dist/page/coverage.js +280 -0
- package/dist/page/dom-export.d.ts +41 -0
- package/dist/page/dom-export.js +193 -0
- package/dist/page/dom-walk.d.ts +91 -0
- package/dist/page/dom-walk.js +267 -0
- package/dist/page/dom_diff.d.ts +48 -0
- package/dist/page/dom_diff.js +121 -0
- package/dist/page/downloads.d.ts +80 -0
- package/dist/page/downloads.js +244 -0
- package/dist/page/drop-files.d.ts +78 -0
- package/dist/page/drop-files.js +310 -0
- package/dist/page/element-export-discovery.d.ts +64 -0
- package/dist/page/element-export-discovery.js +346 -0
- package/dist/page/element-export.d.ts +46 -0
- package/dist/page/element-export.js +251 -0
- package/dist/page/emulation-substrate.d.ts +53 -0
- package/dist/page/emulation-substrate.js +87 -0
- package/dist/page/emulation.d.ts +60 -0
- package/dist/page/emulation.js +162 -0
- package/dist/page/export-playwright-script.d.ts +47 -0
- package/dist/page/export-playwright-script.js +304 -0
- package/dist/page/extract-resolve.d.ts +22 -0
- package/dist/page/extract-resolve.js +341 -0
- package/dist/page/extract-schema.d.ts +20 -0
- package/dist/page/extract-schema.js +200 -0
- package/dist/page/extract-types.d.ts +127 -0
- package/dist/page/extract-types.js +8 -0
- package/dist/page/extract-warnings.d.ts +8 -0
- package/dist/page/extract-warnings.js +56 -0
- package/dist/page/extract.d.ts +9 -0
- package/dist/page/extract.js +174 -0
- package/dist/page/fill-form.d.ts +58 -0
- package/dist/page/fill-form.js +261 -0
- package/dist/page/find.d.ts +158 -0
- package/dist/page/find.js +470 -0
- package/dist/page/frames.d.ts +45 -0
- package/dist/page/frames.js +133 -0
- package/dist/page/generate-locator.d.ts +57 -0
- package/dist/page/generate-locator.js +136 -0
- package/dist/page/gestures.d.ts +128 -0
- package/dist/page/gestures.js +198 -0
- package/dist/page/har.d.ts +91 -0
- package/dist/page/har.js +174 -0
- package/dist/page/heap.d.ts +97 -0
- package/dist/page/heap.js +285 -0
- package/dist/page/inspect.d.ts +34 -0
- package/dist/page/inspect.js +75 -0
- package/dist/page/layout-thrash.d.ts +34 -0
- package/dist/page/layout-thrash.js +232 -0
- package/dist/page/learning.d.ts +21 -0
- package/dist/page/learning.js +84 -0
- package/dist/page/locator.d.ts +54 -0
- package/dist/page/locator.js +142 -0
- package/dist/page/memory-diff.d.ts +48 -0
- package/dist/page/memory-diff.js +105 -0
- package/dist/page/network-mask.d.ts +8 -0
- package/dist/page/network-mask.js +18 -0
- package/dist/page/network-playwright.d.ts +96 -0
- package/dist/page/network-playwright.js +353 -0
- package/dist/page/network-substrate-select.d.ts +18 -0
- package/dist/page/network-substrate-select.js +32 -0
- package/dist/page/network-substrate.d.ts +109 -0
- package/dist/page/network-substrate.js +161 -0
- package/dist/page/network-ws.d.ts +46 -0
- package/dist/page/network-ws.js +113 -0
- package/dist/page/network.d.ts +194 -0
- package/dist/page/network.js +415 -0
- package/dist/page/overflow-detect.d.ts +102 -0
- package/dist/page/overflow-detect.js +449 -0
- package/dist/page/pdf.d.ts +69 -0
- package/dist/page/pdf.js +109 -0
- package/dist/page/perf-audit-analysers.d.ts +40 -0
- package/dist/page/perf-audit-analysers.js +369 -0
- package/dist/page/perf-audit-runner.d.ts +20 -0
- package/dist/page/perf-audit-runner.js +195 -0
- package/dist/page/perf-audit-types.d.ts +41 -0
- package/dist/page/perf-audit-types.js +5 -0
- package/dist/page/perf-audit.d.ts +37 -0
- package/dist/page/perf-audit.js +377 -0
- package/dist/page/perf.d.ts +127 -0
- package/dist/page/perf.js +373 -0
- package/dist/page/plan.d.ts +192 -0
- package/dist/page/plan.js +308 -0
- package/dist/page/point_probe.d.ts +46 -0
- package/dist/page/point_probe.js +99 -0
- package/dist/page/recording.d.ts +67 -0
- package/dist/page/recording.js +172 -0
- package/dist/page/refs.d.ts +92 -0
- package/dist/page/refs.js +134 -0
- package/dist/page/regions.d.ts +23 -0
- package/dist/page/regions.js +32 -0
- package/dist/page/routes.d.ts +40 -0
- package/dist/page/routes.js +87 -0
- package/dist/page/safari-actions.d.ts +12 -0
- package/dist/page/safari-actions.js +144 -0
- package/dist/page/sample.d.ts +64 -0
- package/dist/page/sample.js +216 -0
- package/dist/page/screenshot-on.d.ts +51 -0
- package/dist/page/screenshot-on.js +150 -0
- package/dist/page/screenshot-save.d.ts +36 -0
- package/dist/page/screenshot-save.js +53 -0
- package/dist/page/screenshot-schedule.d.ts +50 -0
- package/dist/page/screenshot-schedule.js +155 -0
- package/dist/page/script-substrate.d.ts +32 -0
- package/dist/page/script-substrate.js +47 -0
- package/dist/page/seed-random.d.ts +45 -0
- package/dist/page/seed-random.js +144 -0
- package/dist/page/set-of-marks.d.ts +96 -0
- package/dist/page/set-of-marks.js +245 -0
- package/dist/page/shadow.d.ts +136 -0
- package/dist/page/shadow.js +400 -0
- package/dist/page/shortcut.d.ts +50 -0
- package/dist/page/shortcut.js +147 -0
- package/dist/page/snapshot-substrate-safari.d.ts +30 -0
- package/dist/page/snapshot-substrate-safari.js +84 -0
- package/dist/page/snapshot-substrate-select.d.ts +24 -0
- package/dist/page/snapshot-substrate-select.js +34 -0
- package/dist/page/snapshot-substrate.d.ts +58 -0
- package/dist/page/snapshot-substrate.js +135 -0
- package/dist/page/snapshot.d.ts +24 -0
- package/dist/page/snapshot.js +162 -0
- package/dist/page/solve-captcha.d.ts +76 -0
- package/dist/page/solve-captcha.js +286 -0
- package/dist/page/storage-substrate-types.d.ts +221 -0
- package/dist/page/storage-substrate-types.js +6 -0
- package/dist/page/storage-substrate.d.ts +215 -0
- package/dist/page/storage-substrate.js +280 -0
- package/dist/page/structural.d.ts +9 -0
- package/dist/page/structural.js +152 -0
- package/dist/page/substrate-bundle-safari.d.ts +8 -0
- package/dist/page/substrate-bundle-safari.js +42 -0
- package/dist/page/substrate-bundle.d.ts +6 -0
- package/dist/page/substrate-bundle.js +53 -0
- package/dist/page/text_search.d.ts +44 -0
- package/dist/page/text_search.js +90 -0
- package/dist/page/upload.d.ts +28 -0
- package/dist/page/upload.js +62 -0
- package/dist/page/verify.d.ts +63 -0
- package/dist/page/verify.js +451 -0
- package/dist/page/video.d.ts +115 -0
- package/dist/page/video.js +169 -0
- package/dist/page/visibility.d.ts +22 -0
- package/dist/page/visibility.js +94 -0
- package/dist/page/watch.d.ts +29 -0
- package/dist/page/watch.js +99 -0
- package/dist/page/workers.d.ts +126 -0
- package/dist/page/workers.js +490 -0
- package/dist/page/ws-interactive.d.ts +82 -0
- package/dist/page/ws-interactive.js +318 -0
- package/dist/plugin/cli.d.ts +45 -0
- package/dist/plugin/cli.js +496 -0
- package/dist/plugin/command-registry.d.ts +9 -0
- package/dist/plugin/command-registry.js +23 -0
- package/dist/plugin/depgraph.d.ts +37 -0
- package/dist/plugin/depgraph.js +186 -0
- package/dist/plugin/manifest.d.ts +182 -0
- package/dist/plugin/manifest.js +219 -0
- package/dist/plugin/package-manager.d.ts +22 -0
- package/dist/plugin/package-manager.js +40 -0
- package/dist/plugin/resolver.d.ts +85 -0
- package/dist/plugin/resolver.js +166 -0
- package/dist/plugin/runtime.d.ts +77 -0
- package/dist/plugin/runtime.js +402 -0
- package/dist/plugin/types.d.ts +113 -0
- package/dist/plugin/types.js +4 -0
- package/dist/policy/confirm.d.ts +76 -0
- package/dist/policy/confirm.js +162 -0
- package/dist/policy/origin.d.ts +17 -0
- package/dist/policy/origin.js +79 -0
- package/dist/sdk/client.d.ts +21 -0
- package/dist/sdk/client.js +174 -0
- package/dist/sdk/index.d.ts +32 -0
- package/dist/sdk/index.js +61 -0
- package/dist/sdk/plugin-types.d.ts +33 -0
- package/dist/sdk/plugin-types.js +22 -0
- package/dist/sdk/registry.d.ts +17 -0
- package/dist/sdk/registry.js +94 -0
- package/dist/sdk/socket-transport.d.ts +20 -0
- package/dist/sdk/socket-transport.js +90 -0
- package/dist/sdk/tool-types.d.ts +634 -0
- package/dist/sdk/tool-types.js +28 -0
- package/dist/sdk/transport-in-process.d.ts +21 -0
- package/dist/sdk/transport-in-process.js +44 -0
- package/dist/sdk/transport-registry.d.ts +19 -0
- package/dist/sdk/transport-registry.js +31 -0
- package/dist/sdk/transport-socket.d.ts +12 -0
- package/dist/sdk/transport-socket.js +77 -0
- package/dist/sdk/transport-stdio-child.d.ts +10 -0
- package/dist/sdk/transport-stdio-child.js +47 -0
- package/dist/sdk/transport.d.ts +10 -0
- package/dist/sdk/transport.js +35 -0
- package/dist/sdk/types.d.ts +176 -0
- package/dist/sdk/types.js +10 -0
- package/dist/server.d.ts +33 -0
- package/dist/server.js +327 -0
- package/dist/session/artifacts.d.ts +52 -0
- package/dist/session/artifacts.js +177 -0
- package/dist/session/byob-attach.d.ts +26 -0
- package/dist/session/byob-attach.js +187 -0
- package/dist/session/byob.d.ts +8 -0
- package/dist/session/byob.js +20 -0
- package/dist/session/cache-storage.d.ts +100 -0
- package/dist/session/cache-storage.js +166 -0
- package/dist/session/device-emu.d.ts +149 -0
- package/dist/session/device-emu.js +545 -0
- package/dist/session/device.d.ts +14 -0
- package/dist/session/device.js +44 -0
- package/dist/session/dialog.d.ts +62 -0
- package/dist/session/dialog.js +164 -0
- package/dist/session/emulation.d.ts +69 -0
- package/dist/session/emulation.js +168 -0
- package/dist/session/extensions.d.ts +113 -0
- package/dist/session/extensions.js +237 -0
- package/dist/session/fs-picker.d.ts +144 -0
- package/dist/session/fs-picker.js +666 -0
- package/dist/session/idb-storage.d.ts +86 -0
- package/dist/session/idb-storage.js +229 -0
- package/dist/session/incognito.d.ts +3 -0
- package/dist/session/incognito.js +20 -0
- package/dist/session/launch-options.d.ts +41 -0
- package/dist/session/launch-options.js +200 -0
- package/dist/session/managed.d.ts +3 -0
- package/dist/session/managed.js +16 -0
- package/dist/session/metrics.d.ts +45 -0
- package/dist/session/metrics.js +75 -0
- package/dist/session/notification.d.ts +122 -0
- package/dist/session/notification.js +426 -0
- package/dist/session/permission.d.ts +144 -0
- package/dist/session/permission.js +600 -0
- package/dist/session/playwright-post-wire.d.ts +8 -0
- package/dist/session/playwright-post-wire.js +148 -0
- package/dist/session/policy-buffer.d.ts +21 -0
- package/dist/session/policy-buffer.js +47 -0
- package/dist/session/profile-snapshot.d.ts +11 -0
- package/dist/session/profile-snapshot.js +53 -0
- package/dist/session/registry.d.ts +365 -0
- package/dist/session/registry.js +98 -0
- package/dist/session/safari-post-wire.d.ts +8 -0
- package/dist/session/safari-post-wire.js +28 -0
- package/dist/session/safari-session.d.ts +10 -0
- package/dist/session/safari-session.js +39 -0
- package/dist/session/storage.d.ts +148 -0
- package/dist/session/storage.js +350 -0
- package/dist/session/types.d.ts +113 -0
- package/dist/session/types.js +5 -0
- package/dist/session/wedge.d.ts +15 -0
- package/dist/session/wedge.js +41 -0
- package/dist/tools/action-core-tools.d.ts +13 -0
- package/dist/tools/action-core-tools.js +156 -0
- package/dist/tools/action-form-tools.d.ts +12 -0
- package/dist/tools/action-form-tools.js +179 -0
- package/dist/tools/action-gesture-tools.d.ts +9 -0
- package/dist/tools/action-gesture-tools.js +115 -0
- package/dist/tools/action-history-tools.d.ts +8 -0
- package/dist/tools/action-history-tools.js +67 -0
- package/dist/tools/action-tool.d.ts +42 -0
- package/dist/tools/action-tool.js +58 -0
- package/dist/tools/action-tools.d.ts +20 -0
- package/dist/tools/action-tools.js +28 -0
- package/dist/tools/batch-act-tools.d.ts +10 -0
- package/dist/tools/batch-act-tools.js +276 -0
- package/dist/tools/batch-human-tools.d.ts +8 -0
- package/dist/tools/batch-human-tools.js +148 -0
- package/dist/tools/canvas-tools.d.ts +40 -0
- package/dist/tools/canvas-tools.js +368 -0
- package/dist/tools/capture-report-diagnostics-tools.d.ts +7 -0
- package/dist/tools/capture-report-diagnostics-tools.js +318 -0
- package/dist/tools/capture-report-element-export-tools.d.ts +8 -0
- package/dist/tools/capture-report-element-export-tools.js +197 -0
- package/dist/tools/capture-report-export-tools.d.ts +8 -0
- package/dist/tools/capture-report-export-tools.js +246 -0
- package/dist/tools/capture-report-marks-tools.d.ts +9 -0
- package/dist/tools/capture-report-marks-tools.js +221 -0
- package/dist/tools/capture-report-upload-tools.d.ts +8 -0
- package/dist/tools/capture-report-upload-tools.js +277 -0
- package/dist/tools/config-approval-tools.d.ts +8 -0
- package/dist/tools/config-approval-tools.js +166 -0
- package/dist/tools/deep-coverage-tools.d.ts +8 -0
- package/dist/tools/deep-coverage-tools.js +325 -0
- package/dist/tools/deep-determinism-tools.d.ts +8 -0
- package/dist/tools/deep-determinism-tools.js +276 -0
- package/dist/tools/deep-perf-tools.d.ts +19 -0
- package/dist/tools/deep-perf-tools.js +324 -0
- package/dist/tools/device-emulation-tools.d.ts +9 -0
- package/dist/tools/device-emulation-tools.js +137 -0
- package/dist/tools/extensions-batch-tools.d.ts +18 -0
- package/dist/tools/extensions-batch-tools.js +24 -0
- package/dist/tools/extensions-rebuild.d.ts +22 -0
- package/dist/tools/extensions-rebuild.js +208 -0
- package/dist/tools/extensions-tools.d.ts +2 -0
- package/dist/tools/extensions-tools.js +331 -0
- package/dist/tools/forms-fill-tools.d.ts +8 -0
- package/dist/tools/forms-fill-tools.js +109 -0
- package/dist/tools/forms-plan-tools.d.ts +7 -0
- package/dist/tools/forms-plan-tools.js +159 -0
- package/dist/tools/forms-recording-mode-tools.d.ts +8 -0
- package/dist/tools/forms-recording-mode-tools.js +71 -0
- package/dist/tools/forms-recording-tools.d.ts +14 -0
- package/dist/tools/forms-recording-tools.js +22 -0
- package/dist/tools/forms-refs-tools.d.ts +8 -0
- package/dist/tools/forms-refs-tools.js +90 -0
- package/dist/tools/gesture-coord-tools.d.ts +8 -0
- package/dist/tools/gesture-coord-tools.js +168 -0
- package/dist/tools/gesture-emulation-tools.d.ts +8 -0
- package/dist/tools/gesture-emulation-tools.js +135 -0
- package/dist/tools/gesture-network-tools.d.ts +17 -0
- package/dist/tools/gesture-network-tools.js +27 -0
- package/dist/tools/gesture-route-tools.d.ts +8 -0
- package/dist/tools/gesture-route-tools.js +142 -0
- package/dist/tools/gesture-websocket-tools.d.ts +8 -0
- package/dist/tools/gesture-websocket-tools.js +122 -0
- package/dist/tools/gesture-worker-tools.d.ts +9 -0
- package/dist/tools/gesture-worker-tools.js +200 -0
- package/dist/tools/host-build.d.ts +76 -0
- package/dist/tools/host-build.js +516 -0
- package/dist/tools/host.d.ts +287 -0
- package/dist/tools/host.js +1 -0
- package/dist/tools/input-tools.d.ts +10 -0
- package/dist/tools/input-tools.js +176 -0
- package/dist/tools/live-emulation-tools.d.ts +9 -0
- package/dist/tools/live-emulation-tools.js +353 -0
- package/dist/tools/plugin-runtime.d.ts +36 -0
- package/dist/tools/plugin-runtime.js +274 -0
- package/dist/tools/read-observe-buffer-tools.d.ts +9 -0
- package/dist/tools/read-observe-buffer-tools.js +385 -0
- package/dist/tools/read-observe-capture-tools.d.ts +12 -0
- package/dist/tools/read-observe-capture-tools.js +376 -0
- package/dist/tools/read-observe-dom-tools.d.ts +8 -0
- package/dist/tools/read-observe-dom-tools.js +308 -0
- package/dist/tools/read-observe-extract-tools.d.ts +8 -0
- package/dist/tools/read-observe-extract-tools.js +232 -0
- package/dist/tools/read-observe-verify-tools.d.ts +8 -0
- package/dist/tools/read-observe-verify-tools.js +316 -0
- package/dist/tools/schemas.d.ts +29 -0
- package/dist/tools/schemas.js +58 -0
- package/dist/tools/secrets-captcha-tools.d.ts +9 -0
- package/dist/tools/secrets-captcha-tools.js +231 -0
- package/dist/tools/session-dialog-permission-tools.d.ts +9 -0
- package/dist/tools/session-dialog-permission-tools.js +287 -0
- package/dist/tools/session-lifecycle-tools.d.ts +8 -0
- package/dist/tools/session-lifecycle-tools.js +314 -0
- package/dist/tools/session-notification-device-tools.d.ts +9 -0
- package/dist/tools/session-notification-device-tools.js +156 -0
- package/dist/tools/session-policy-tools.d.ts +16 -0
- package/dist/tools/session-policy-tools.js +22 -0
- package/dist/tools/session-registry.d.ts +28 -0
- package/dist/tools/session-registry.js +427 -0
- package/dist/tools/storage-artifact-har-video-tools.d.ts +8 -0
- package/dist/tools/storage-artifact-har-video-tools.js +311 -0
- package/dist/tools/storage-cache-idb-tools.d.ts +8 -0
- package/dist/tools/storage-cache-idb-tools.js +347 -0
- package/dist/tools/storage-state-cookies-tools.d.ts +8 -0
- package/dist/tools/storage-state-cookies-tools.js +223 -0
- package/dist/tools/storage-tools.d.ts +17 -0
- package/dist/tools/storage-tools.js +25 -0
- package/dist/tools/storage-web-auth-tools.d.ts +10 -0
- package/dist/tools/storage-web-auth-tools.js +230 -0
- package/dist/tools/tool-metadata.d.ts +8 -0
- package/dist/tools/tool-metadata.js +185 -0
- package/dist/util/batch.d.ts +83 -0
- package/dist/util/batch.js +191 -0
- package/dist/util/capabilities.d.ts +504 -0
- package/dist/util/capabilities.js +254 -0
- package/dist/util/config-store.d.ts +103 -0
- package/dist/util/config-store.js +206 -0
- package/dist/util/config.d.ts +11 -0
- package/dist/util/config.js +28 -0
- package/dist/util/credentials.d.ts +136 -0
- package/dist/util/credentials.js +622 -0
- package/dist/util/deadline.d.ts +22 -0
- package/dist/util/deadline.js +62 -0
- package/dist/util/diagnostics.d.ts +161 -0
- package/dist/util/diagnostics.js +579 -0
- package/dist/util/egress-sanitiser.d.ts +29 -0
- package/dist/util/egress-sanitiser.js +52 -0
- package/dist/util/failure.d.ts +8 -0
- package/dist/util/failure.js +50 -0
- package/dist/util/flake-check.d.ts +109 -0
- package/dist/util/flake-check.js +342 -0
- package/dist/util/invariant.d.ts +25 -0
- package/dist/util/invariant.js +66 -0
- package/dist/util/logging.d.ts +6 -0
- package/dist/util/logging.js +12 -0
- package/dist/util/predicates.d.ts +62 -0
- package/dist/util/predicates.js +340 -0
- package/dist/util/secrets.d.ts +104 -0
- package/dist/util/secrets.js +219 -0
- package/dist/util/tokens.d.ts +6 -0
- package/dist/util/tokens.js +24 -0
- package/dist/util/url-sanitizer.d.ts +19 -0
- package/dist/util/url-sanitizer.js +70 -0
- package/dist/util/version.d.ts +2 -0
- package/dist/util/version.js +21 -0
- package/dist/util/workspace.d.ts +7 -0
- package/dist/util/workspace.js +22 -0
- package/package.json +120 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
// Web Workers + Service Workers visibility — capability `read` for listing
|
|
2
|
+
// and reading messages; `action` for sending messages and registering fetch
|
|
3
|
+
// interceptors. Sibling of `ws-interactive.ts` on the worker channel.
|
|
4
|
+
//
|
|
5
|
+
// • `workers_list({type})` — enumerate live workers (Web + SW).
|
|
6
|
+
// • `worker_message_send({workerId, message})` — `postMessage` to a worker.
|
|
7
|
+
// • `worker_messages_read({workerId?})` — drain the FROM-worker ring.
|
|
8
|
+
// • `sw_intercept_fetch({pattern, response})` — fulfil a SW-handled fetch.
|
|
9
|
+
//
|
|
10
|
+
// Two completely different transport stories under one façade:
|
|
11
|
+
//
|
|
12
|
+
// **Web Workers.** No CDP primitive lets us call `postMessage` on a worker we
|
|
13
|
+
// didn't construct. So we install a page-side wrapper of `window.Worker` at
|
|
14
|
+
// document-start (`Page.addInitScript`) — same shape as `ws-interactive.ts`'s
|
|
15
|
+
// `__browxWs`. The wrapper:
|
|
16
|
+
// • Assigns each worker a monotonic id (`ww-1`, `ww-2`, …).
|
|
17
|
+
// • Mirrors every message FROM the worker into a page-side ring
|
|
18
|
+
// (`window.__browxWorkers.drain(id?)` — server reads it via `evaluate`).
|
|
19
|
+
// • Exposes `__browxWorkers.post(id, msg)` which calls the underlying
|
|
20
|
+
// `Worker.prototype.postMessage` — the worker's `onmessage` sees a real
|
|
21
|
+
// event, not a synthetic one.
|
|
22
|
+
// This is the same trade-off `ws-interactive.ts` made: CDP attach-to-worker
|
|
23
|
+
// adds a separate session per worker for a feature (postMessage IPC) that's
|
|
24
|
+
// fundamentally page-side. The in-page proxy keeps the message ring naturally
|
|
25
|
+
// co-located with the IPC surface.
|
|
26
|
+
//
|
|
27
|
+
// **Service Workers.** SWs are independent CDP targets — `addInitScript`
|
|
28
|
+
// doesn't reach them, and the page-side wrapper of `Worker` is a no-op (SWs
|
|
29
|
+
// register via `navigator.serviceWorker.register`, not `new Worker`). So:
|
|
30
|
+
// • Enumerate via CDP `ServiceWorker.enable` + `ServiceWorker.workerVersionUpdated`.
|
|
31
|
+
// • Attach to each SW target via `Target.setAutoAttach({autoAttach:true,
|
|
32
|
+
// waitForDebuggerOnStart:false, flatten:true})`, then on the attached
|
|
33
|
+
// session run `Fetch.enable` with our pattern, and on `Fetch.requestPaused`
|
|
34
|
+
// call `Fetch.fulfillRequest` with the canned response. The intercept fires
|
|
35
|
+
// ONLY when the SW's fetch handler actually runs — i.e. the SW chose to
|
|
36
|
+
// intercept this URL — which is the right semantic.
|
|
37
|
+
// • For postMessage to a SW, the SW target has `Runtime.evaluate` so we
|
|
38
|
+
// dispatch a `MessageEvent` into the SW global; FROM-SW messages come back
|
|
39
|
+
// via a `Runtime.bindingCalled` shuttle installed on the SW session.
|
|
40
|
+
//
|
|
41
|
+
// All four primitives lazily install the page-side wrapper + lazily attach the
|
|
42
|
+
// CDP listeners on first call, so a session that never uses workers pays zero
|
|
43
|
+
// overhead.
|
|
44
|
+
import { globToRegex } from "./ws-interactive.js";
|
|
45
|
+
// ---------------------------------------------------------------------------
|
|
46
|
+
// Page-side wrapper script — wraps `window.Worker` exactly once. Mirrors the
|
|
47
|
+
// shape of `WS_PAGE_SCRIPT` in `ws-interactive.ts`. Browser-only JS, no
|
|
48
|
+
// TS-only syntax — this string is shipped verbatim into the page via
|
|
49
|
+
// `Page.addInitScript`.
|
|
50
|
+
export const WORKERS_PAGE_SCRIPT = `(() => {
|
|
51
|
+
if (window.__browxWorkers) return;
|
|
52
|
+
var NativeWorker = window.Worker;
|
|
53
|
+
if (!NativeWorker) return;
|
|
54
|
+
var nativePost = NativeWorker.prototype.postMessage;
|
|
55
|
+
var workers = new Map(); // wwId -> Worker
|
|
56
|
+
var messages = []; // {workerId, data, at} ring (capped at 500)
|
|
57
|
+
var MAX = 500;
|
|
58
|
+
var nextId = 1;
|
|
59
|
+
|
|
60
|
+
function recordMessage(id, payload) {
|
|
61
|
+
var data;
|
|
62
|
+
try {
|
|
63
|
+
data = typeof payload === "string" ? payload : JSON.stringify(payload);
|
|
64
|
+
} catch (_) {
|
|
65
|
+
data = "[unserialisable]";
|
|
66
|
+
}
|
|
67
|
+
if (data && data.length > 4000) data = data.slice(0, 4000) + "…";
|
|
68
|
+
messages.push({ workerId: id, data: data, at: Date.now() });
|
|
69
|
+
if (messages.length > MAX) messages.splice(0, messages.length - MAX);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function Wrapped(scriptURL, opts) {
|
|
73
|
+
var w = arguments.length > 1 ? new NativeWorker(scriptURL, opts) : new NativeWorker(scriptURL);
|
|
74
|
+
var id = "ww-" + (nextId++);
|
|
75
|
+
workers.set(id, w);
|
|
76
|
+
try { w.__browxId = id; } catch (_) {}
|
|
77
|
+
// Mirror every message-from-worker into the ring. We use addEventListener
|
|
78
|
+
// (not onmessage) so we don't fight with app-side onmessage handlers.
|
|
79
|
+
try {
|
|
80
|
+
w.addEventListener("message", function (ev) { recordMessage(id, ev.data); });
|
|
81
|
+
} catch (_) {}
|
|
82
|
+
return w;
|
|
83
|
+
}
|
|
84
|
+
Wrapped.prototype = NativeWorker.prototype;
|
|
85
|
+
try { Object.defineProperty(Wrapped, "name", { value: "Worker" }); } catch (_) {}
|
|
86
|
+
window.Worker = Wrapped;
|
|
87
|
+
|
|
88
|
+
window.__browxWorkers = {
|
|
89
|
+
list: function () {
|
|
90
|
+
var out = [];
|
|
91
|
+
workers.forEach(function (w, id) {
|
|
92
|
+
// We can't get the scriptURL back from a Worker after construction
|
|
93
|
+
// in all browsers — fall back to the recorded url if we tracked it,
|
|
94
|
+
// else the empty string. (Chromium DOES expose it via internal slot
|
|
95
|
+
// but not via any public API; we track it at construction via the
|
|
96
|
+
// initial scriptURL argument — see __browxWorkers._urls.
|
|
97
|
+
var url = (window.__browxWorkers._urls && window.__browxWorkers._urls.get(id)) || "";
|
|
98
|
+
out.push({ workerId: id, url: url });
|
|
99
|
+
});
|
|
100
|
+
return out;
|
|
101
|
+
},
|
|
102
|
+
_urls: new Map(),
|
|
103
|
+
post: function (id, msg) {
|
|
104
|
+
var w = workers.get(id);
|
|
105
|
+
if (!w) return { ok: false, error: "no worker with id " + id };
|
|
106
|
+
try {
|
|
107
|
+
nativePost.call(w, msg);
|
|
108
|
+
return { ok: true };
|
|
109
|
+
} catch (e) {
|
|
110
|
+
return { ok: false, error: e && e.message ? e.message : String(e) };
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
drain: function (id) {
|
|
114
|
+
var out;
|
|
115
|
+
if (id) {
|
|
116
|
+
out = [];
|
|
117
|
+
var kept = [];
|
|
118
|
+
for (var i = 0; i < messages.length; i++) {
|
|
119
|
+
if (messages[i].workerId === id) out.push(messages[i]);
|
|
120
|
+
else kept.push(messages[i]);
|
|
121
|
+
}
|
|
122
|
+
messages = kept;
|
|
123
|
+
} else {
|
|
124
|
+
out = messages.slice();
|
|
125
|
+
messages.length = 0;
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
},
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
// Track scriptURL at construction. We can't get it post-hoc on most engines.
|
|
132
|
+
var origWrapped = Wrapped;
|
|
133
|
+
window.Worker = function (scriptURL, opts) {
|
|
134
|
+
var w = arguments.length > 1 ? origWrapped(scriptURL, opts) : origWrapped(scriptURL);
|
|
135
|
+
try {
|
|
136
|
+
var id = w.__browxId;
|
|
137
|
+
if (id) {
|
|
138
|
+
var url = "";
|
|
139
|
+
try { url = String(scriptURL && scriptURL.href ? scriptURL.href : scriptURL || ""); } catch (_) {}
|
|
140
|
+
window.__browxWorkers._urls.set(id, url);
|
|
141
|
+
}
|
|
142
|
+
} catch (_) {}
|
|
143
|
+
return w;
|
|
144
|
+
};
|
|
145
|
+
window.Worker.prototype = NativeWorker.prototype;
|
|
146
|
+
try { Object.defineProperty(window.Worker, "name", { value: "Worker" }); } catch (_) {}
|
|
147
|
+
})();`;
|
|
148
|
+
const SW_RING_MAX = 500;
|
|
149
|
+
const SW_PAYLOAD_MAX = 4000;
|
|
150
|
+
export class WorkersRegistry {
|
|
151
|
+
/** SW attachments keyed by CDP sessionId. */
|
|
152
|
+
swAttached = new Map();
|
|
153
|
+
/** Stable monotonic id for the SW listing — `sw-1`, `sw-2`, …. Keyed by
|
|
154
|
+
* CDP sessionId so the id survives status transitions on the same SW. */
|
|
155
|
+
swIdBySession = new Map();
|
|
156
|
+
nextSwId = 1;
|
|
157
|
+
/** Active fetch interceptors. Re-add of the same pattern replaces. */
|
|
158
|
+
fetchInterceptors = new Map();
|
|
159
|
+
/** Server-side ring of FROM-SW messages (we relay these via a CDP
|
|
160
|
+
* `Runtime.bindingCalled` shuttle on each SW session). */
|
|
161
|
+
swMessages = [];
|
|
162
|
+
/** True once the page-side wrapper has been installed. */
|
|
163
|
+
pageInstalled = false;
|
|
164
|
+
/** True once we've called `ServiceWorker.enable` + wired the auto-attach
|
|
165
|
+
* on the top-level CDP session. */
|
|
166
|
+
swEnabled = false;
|
|
167
|
+
/** Detach functions for cleanup. */
|
|
168
|
+
detachers = [];
|
|
169
|
+
/** Install the page-side `Worker` wrapper. Idempotent. Called eagerly at
|
|
170
|
+
* session creation (under capability `read`) so workers opened by the
|
|
171
|
+
* initial document are seen — same posture as `WsInteractiveRegistry`. */
|
|
172
|
+
async installPageWrapper(page) {
|
|
173
|
+
if (this.pageInstalled)
|
|
174
|
+
return;
|
|
175
|
+
this.pageInstalled = true;
|
|
176
|
+
await page.context().addInitScript({ content: WORKERS_PAGE_SCRIPT });
|
|
177
|
+
// re-inject for the current document — addInitScript only fires on
|
|
178
|
+
// future navigations.
|
|
179
|
+
for (const p of page.context().pages()) {
|
|
180
|
+
await p.evaluate(WORKERS_PAGE_SCRIPT).catch(() => undefined);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** Enable the CDP ServiceWorker domain on the session's top-level CDP and
|
|
184
|
+
* wire `Target.setAutoAttach` so newly-registered SWs auto-attach as child
|
|
185
|
+
* sessions. Idempotent. */
|
|
186
|
+
/** Register a CDP event handler + push its detacher onto `this.detachers`.
|
|
187
|
+
* The event name is dynamic here, so the strongly-typed per-event `on`/`off`
|
|
188
|
+
* overloads are bridged through a single untyped seam. */
|
|
189
|
+
onCdp(cdp, event, handler) {
|
|
190
|
+
const c = cdp;
|
|
191
|
+
c.on(event, handler);
|
|
192
|
+
this.detachers.push(() => c.off(event, handler));
|
|
193
|
+
}
|
|
194
|
+
/** `ServiceWorker.workerVersionUpdated` — refresh url/status on the matching
|
|
195
|
+
* attachment(s). */
|
|
196
|
+
registerVersionUpdated(cdp) {
|
|
197
|
+
this.onCdp(cdp, "ServiceWorker.workerVersionUpdated", (raw) => {
|
|
198
|
+
const e = raw;
|
|
199
|
+
for (const v of e.versions ?? []) {
|
|
200
|
+
if (!v.targetId)
|
|
201
|
+
continue;
|
|
202
|
+
for (const att of this.swAttached.values()) {
|
|
203
|
+
if (att.targetId === v.targetId) {
|
|
204
|
+
att.url = v.scriptURL || att.url;
|
|
205
|
+
att.status = v.runningStatus || att.status;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
/** `Target.attachedToTarget` / `detachedFromTarget` — track the SW attachment
|
|
212
|
+
* map, arming any already-armed fetch interceptors on a new SW. */
|
|
213
|
+
registerAttachDetach(cdp) {
|
|
214
|
+
this.onCdp(cdp, "Target.attachedToTarget", (raw) => {
|
|
215
|
+
const e = raw;
|
|
216
|
+
if (e.targetInfo.type !== "service_worker")
|
|
217
|
+
return;
|
|
218
|
+
const att = {
|
|
219
|
+
targetId: e.targetInfo.targetId,
|
|
220
|
+
sessionId: e.sessionId,
|
|
221
|
+
url: e.targetInfo.url,
|
|
222
|
+
status: "running",
|
|
223
|
+
fetchEnabled: false,
|
|
224
|
+
};
|
|
225
|
+
this.swAttached.set(e.sessionId, att);
|
|
226
|
+
this.swIdBySession.set(e.sessionId, `sw-${this.nextSwId++}`);
|
|
227
|
+
if (this.fetchInterceptors.size > 0)
|
|
228
|
+
void this.applyFetchEnable(cdp, att).catch(() => undefined);
|
|
229
|
+
});
|
|
230
|
+
this.onCdp(cdp, "Target.detachedFromTarget", (raw) => {
|
|
231
|
+
const { sessionId } = raw;
|
|
232
|
+
this.swAttached.delete(sessionId);
|
|
233
|
+
this.swIdBySession.delete(sessionId);
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
/** `Fetch.requestPaused` (TOP session; flatten routes child events up by
|
|
237
|
+
* `sessionId`) — fulfill against a matching interceptor, else continue. */
|
|
238
|
+
registerRequestPaused(cdp) {
|
|
239
|
+
this.onCdp(cdp, "Fetch.requestPaused", (raw) => {
|
|
240
|
+
void this.handleRequestPaused(cdp, raw);
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
async handleRequestPaused(cdp, e) {
|
|
244
|
+
let hit;
|
|
245
|
+
for (const ic of this.fetchInterceptors.values()) {
|
|
246
|
+
if (ic.regex.test(e.request.url)) {
|
|
247
|
+
hit = ic;
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
if (!hit) {
|
|
252
|
+
await cdp
|
|
253
|
+
.send("Fetch.continueRequest", {
|
|
254
|
+
requestId: e.requestId,
|
|
255
|
+
...(e.sessionId ? { sessionId: e.sessionId } : {}),
|
|
256
|
+
})
|
|
257
|
+
.catch(() => undefined);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
const r = hit.response;
|
|
261
|
+
const headers = [
|
|
262
|
+
{ name: "content-type", value: r.contentType ?? "application/json" },
|
|
263
|
+
...Object.entries(r.headers ?? {}).map(([name, value]) => ({ name, value })),
|
|
264
|
+
];
|
|
265
|
+
await cdp
|
|
266
|
+
.send("Fetch.fulfillRequest", {
|
|
267
|
+
requestId: e.requestId,
|
|
268
|
+
responseCode: r.status ?? 200,
|
|
269
|
+
responseHeaders: headers,
|
|
270
|
+
body: Buffer.from(r.body ?? "", "utf-8").toString("base64"),
|
|
271
|
+
...(e.sessionId ? { sessionId: e.sessionId } : {}),
|
|
272
|
+
})
|
|
273
|
+
.catch(() => undefined);
|
|
274
|
+
}
|
|
275
|
+
async installSwListener(cdp) {
|
|
276
|
+
if (this.swEnabled)
|
|
277
|
+
return;
|
|
278
|
+
this.swEnabled = true;
|
|
279
|
+
// Enumerate + monitor running versions; auto-attach for a child session per SW.
|
|
280
|
+
await cdp.send("ServiceWorker.enable").catch(() => undefined);
|
|
281
|
+
await cdp
|
|
282
|
+
.send("Target.setAutoAttach", {
|
|
283
|
+
autoAttach: true,
|
|
284
|
+
waitForDebuggerOnStart: false,
|
|
285
|
+
flatten: true,
|
|
286
|
+
})
|
|
287
|
+
.catch(() => undefined);
|
|
288
|
+
this.registerVersionUpdated(cdp);
|
|
289
|
+
this.registerAttachDetach(cdp);
|
|
290
|
+
this.registerRequestPaused(cdp);
|
|
291
|
+
}
|
|
292
|
+
async applyFetchEnable(cdp, att) {
|
|
293
|
+
if (att.fetchEnabled)
|
|
294
|
+
return;
|
|
295
|
+
// CDP send routed to the child session: in flatten mode, the standard
|
|
296
|
+
// CDPSession.send doesn't directly target a child session — but for our
|
|
297
|
+
// workers use case Playwright doesn't expose per-child sessions through
|
|
298
|
+
// the public surface. We rely on the parent CDP and the auto-attach
|
|
299
|
+
// routing the Fetch events up with `sessionId` set.
|
|
300
|
+
// We enable Fetch on the parent so all child Fetch events route up.
|
|
301
|
+
await cdp
|
|
302
|
+
.send("Fetch.enable", {
|
|
303
|
+
patterns: [{ urlPattern: "*", requestStage: "Request" }],
|
|
304
|
+
})
|
|
305
|
+
.catch(() => undefined);
|
|
306
|
+
att.fetchEnabled = true;
|
|
307
|
+
}
|
|
308
|
+
// -------------------------------------------------------------------------
|
|
309
|
+
// Tool surface.
|
|
310
|
+
async list(page, cdp, filter = "all") {
|
|
311
|
+
await this.installPageWrapper(page);
|
|
312
|
+
await this.installSwListener(cdp);
|
|
313
|
+
const out = [];
|
|
314
|
+
if (filter === "all" || filter === "web") {
|
|
315
|
+
try {
|
|
316
|
+
const ws = await page.evaluate(() => {
|
|
317
|
+
const w = globalThis.__browxWorkers;
|
|
318
|
+
return w ? w.list() : [];
|
|
319
|
+
});
|
|
320
|
+
for (const e of ws)
|
|
321
|
+
out.push({ workerId: e.workerId, type: "web", url: e.url });
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
/* page navigation race — empty is fine */
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
if (filter === "all" || filter === "service") {
|
|
328
|
+
for (const [sessionId, att] of this.swAttached) {
|
|
329
|
+
const id = this.swIdBySession.get(sessionId) ?? `sw-${this.nextSwId++}`;
|
|
330
|
+
this.swIdBySession.set(sessionId, id);
|
|
331
|
+
out.push({ workerId: id, type: "service", url: att.url, state: att.status });
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return out;
|
|
335
|
+
}
|
|
336
|
+
async sendMessage(page, cdp, args) {
|
|
337
|
+
if (args.workerId.startsWith("ww-")) {
|
|
338
|
+
await this.installPageWrapper(page);
|
|
339
|
+
const r = await page.evaluate(({ id, msg }) => {
|
|
340
|
+
const w = globalThis.__browxWorkers;
|
|
341
|
+
if (!w)
|
|
342
|
+
return { ok: false, error: "__browxWorkers not installed (init-script race?)" };
|
|
343
|
+
return w.post(id, msg);
|
|
344
|
+
}, { id: args.workerId, msg: args.message });
|
|
345
|
+
return { ...r, workerId: args.workerId };
|
|
346
|
+
}
|
|
347
|
+
if (args.workerId.startsWith("sw-")) {
|
|
348
|
+
await this.installSwListener(cdp);
|
|
349
|
+
// Find the SW attachment for this id.
|
|
350
|
+
const sessionId = [...this.swIdBySession].find(([, id]) => id === args.workerId)?.[0];
|
|
351
|
+
if (!sessionId)
|
|
352
|
+
return {
|
|
353
|
+
ok: false,
|
|
354
|
+
workerId: args.workerId,
|
|
355
|
+
error: `no service worker with id ${args.workerId}`,
|
|
356
|
+
};
|
|
357
|
+
// Dispatch a MessageEvent into the SW global by running JS in the SW
|
|
358
|
+
// context. Playwright doesn't surface child-session sends as a public
|
|
359
|
+
// API; we use the parent CDP's Runtime.evaluate routed via the
|
|
360
|
+
// sessionId field (flatten mode).
|
|
361
|
+
const payload = JSON.stringify(args.message);
|
|
362
|
+
const sendOpts = {
|
|
363
|
+
expression: `self.dispatchEvent(new MessageEvent('message', { data: ${payload} })); true;`,
|
|
364
|
+
returnByValue: true,
|
|
365
|
+
};
|
|
366
|
+
try {
|
|
367
|
+
// `sessionId` is a flatten-mode routing field absent from the generated
|
|
368
|
+
// `evaluateParameters` type; spread it the same way the Fetch handlers
|
|
369
|
+
// above do so the literal isn't excess-property-checked.
|
|
370
|
+
await cdp.send("Runtime.evaluate", { ...sendOpts, ...(sessionId ? { sessionId } : {}) });
|
|
371
|
+
return { ok: true, workerId: args.workerId };
|
|
372
|
+
}
|
|
373
|
+
catch (err) {
|
|
374
|
+
return {
|
|
375
|
+
ok: false,
|
|
376
|
+
workerId: args.workerId,
|
|
377
|
+
error: err instanceof Error ? err.message : String(err),
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
return {
|
|
382
|
+
ok: false,
|
|
383
|
+
workerId: args.workerId,
|
|
384
|
+
error: `unknown workerId prefix (expected ww-* or sw-*): ${args.workerId}`,
|
|
385
|
+
};
|
|
386
|
+
}
|
|
387
|
+
async readMessages(page, args) {
|
|
388
|
+
await this.installPageWrapper(page);
|
|
389
|
+
const out = [];
|
|
390
|
+
// Web Worker messages — drain from the page ring.
|
|
391
|
+
if (!args.workerId || args.workerId.startsWith("ww-")) {
|
|
392
|
+
try {
|
|
393
|
+
const drained = await page.evaluate(({ id }) => {
|
|
394
|
+
const w = globalThis.__browxWorkers;
|
|
395
|
+
if (!w)
|
|
396
|
+
return [];
|
|
397
|
+
return w.drain(id ?? undefined);
|
|
398
|
+
}, { id: args.workerId ?? null });
|
|
399
|
+
for (const m of drained)
|
|
400
|
+
out.push({ workerId: m.workerId, data: m.data, at: m.at });
|
|
401
|
+
}
|
|
402
|
+
catch {
|
|
403
|
+
/* race — empty is fine */
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
// Service Worker messages — drain from the server-side ring.
|
|
407
|
+
if (!args.workerId || args.workerId.startsWith("sw-")) {
|
|
408
|
+
const matching = [];
|
|
409
|
+
const remaining = [];
|
|
410
|
+
for (const m of this.swMessages) {
|
|
411
|
+
if (!args.workerId || m.workerId === args.workerId)
|
|
412
|
+
matching.push(m);
|
|
413
|
+
else
|
|
414
|
+
remaining.push(m);
|
|
415
|
+
}
|
|
416
|
+
this.swMessages = remaining;
|
|
417
|
+
out.push(...matching);
|
|
418
|
+
}
|
|
419
|
+
return out;
|
|
420
|
+
}
|
|
421
|
+
async addFetchIntercept(cdp, spec) {
|
|
422
|
+
await this.installSwListener(cdp);
|
|
423
|
+
const key = spec.pattern;
|
|
424
|
+
this.fetchInterceptors.set(key, {
|
|
425
|
+
pattern: key,
|
|
426
|
+
regex: globToRegex(key),
|
|
427
|
+
response: spec.response,
|
|
428
|
+
});
|
|
429
|
+
// Enable Fetch on every currently-attached SW (and on the parent — we
|
|
430
|
+
// need the parent Fetch.enable so child Fetch events route up).
|
|
431
|
+
await cdp
|
|
432
|
+
.send("Fetch.enable", {
|
|
433
|
+
patterns: [{ urlPattern: "*", requestStage: "Request" }],
|
|
434
|
+
})
|
|
435
|
+
.catch(() => undefined);
|
|
436
|
+
for (const att of this.swAttached.values()) {
|
|
437
|
+
await this.applyFetchEnable(cdp, att).catch(() => undefined);
|
|
438
|
+
}
|
|
439
|
+
return { key, active: this.listFetchIntercepts() };
|
|
440
|
+
}
|
|
441
|
+
async removeFetchIntercept(cdp, sel) {
|
|
442
|
+
await this.installSwListener(cdp);
|
|
443
|
+
let removed;
|
|
444
|
+
if (sel.pattern === undefined) {
|
|
445
|
+
removed = [...this.fetchInterceptors.keys()];
|
|
446
|
+
this.fetchInterceptors.clear();
|
|
447
|
+
}
|
|
448
|
+
else if (this.fetchInterceptors.has(sel.pattern)) {
|
|
449
|
+
removed = [sel.pattern];
|
|
450
|
+
this.fetchInterceptors.delete(sel.pattern);
|
|
451
|
+
}
|
|
452
|
+
else {
|
|
453
|
+
removed = [];
|
|
454
|
+
}
|
|
455
|
+
if (this.fetchInterceptors.size === 0) {
|
|
456
|
+
// Disable Fetch so we don't pause every request for no reason.
|
|
457
|
+
await cdp.send("Fetch.disable").catch(() => undefined);
|
|
458
|
+
for (const att of this.swAttached.values())
|
|
459
|
+
att.fetchEnabled = false;
|
|
460
|
+
}
|
|
461
|
+
return { removed, active: this.listFetchIntercepts() };
|
|
462
|
+
}
|
|
463
|
+
listFetchIntercepts() {
|
|
464
|
+
return [...this.fetchInterceptors.keys()];
|
|
465
|
+
}
|
|
466
|
+
/** Append a FROM-SW message to the server-side ring. Currently unused by
|
|
467
|
+
* the production path (the SW side message-relay is left as a future
|
|
468
|
+
* follow-up — see report); kept for symmetry + future use. */
|
|
469
|
+
recordSwMessage(workerId, data) {
|
|
470
|
+
let trimmed = data;
|
|
471
|
+
if (trimmed.length > SW_PAYLOAD_MAX)
|
|
472
|
+
trimmed = trimmed.slice(0, SW_PAYLOAD_MAX) + "…";
|
|
473
|
+
this.swMessages.push({ workerId, data: trimmed, at: Date.now() });
|
|
474
|
+
if (this.swMessages.length > SW_RING_MAX) {
|
|
475
|
+
this.swMessages.splice(0, this.swMessages.length - SW_RING_MAX);
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
/** Release all CDP listeners. Called from the session teardown. */
|
|
479
|
+
dispose() {
|
|
480
|
+
for (const off of this.detachers) {
|
|
481
|
+
try {
|
|
482
|
+
off();
|
|
483
|
+
}
|
|
484
|
+
catch {
|
|
485
|
+
/* tolerate */
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
this.detachers = [];
|
|
489
|
+
}
|
|
490
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import type { Page } from "playwright-core";
|
|
2
|
+
export declare function globToRegex(pat: string): RegExp;
|
|
3
|
+
export type WsInterceptMode = "drop" | "echo" | "replace";
|
|
4
|
+
export interface WsInterceptSpec {
|
|
5
|
+
/** Glob pattern matched against the WebSocket's `url` at frame time. */
|
|
6
|
+
pattern: string;
|
|
7
|
+
/** `"drop"`, `"echo"`, or `{ data: "<replacement payload>" }`. */
|
|
8
|
+
response: "drop" | "echo" | {
|
|
9
|
+
data: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
/** Per-session interactive-WS registry. Tracks the active interceptors so
|
|
13
|
+
* `unintercept` / `list` can answer locally; the page-side wrapper is the
|
|
14
|
+
* authoritative runtime, but each server-side call mirrors the change
|
|
15
|
+
* into this table before evaluating so a re-`add` of the same pattern
|
|
16
|
+
* cleanly replaces the prior entry on both sides. */
|
|
17
|
+
export declare class WsInteractiveRegistry {
|
|
18
|
+
private interceptors;
|
|
19
|
+
/** Idempotent — installs the init script + (best-effort) re-injects into
|
|
20
|
+
* the current document so the wrapper is live BEFORE `ws_send`
|
|
21
|
+
* / `ws_intercept` is called. Safe to call multiple times: the in-page
|
|
22
|
+
* guard `if (window.__browxWs) return;` short-circuits a re-run, and
|
|
23
|
+
* `addInitScript` accumulates harmlessly across calls.
|
|
24
|
+
*
|
|
25
|
+
* Called lazily by `send`/`intercept` so a session that never uses the
|
|
26
|
+
* interactive primitives pays zero overhead. */
|
|
27
|
+
install(page: Page): Promise<void>;
|
|
28
|
+
/** Send `message` on the page-side WS identified by `wsId`. Returns
|
|
29
|
+
* `{ ok:true, wsId, url, bytes }` on success; `{ ok:false, error }`
|
|
30
|
+
* if the wrapper didn't find the id or the socket isn't OPEN. */
|
|
31
|
+
send(page: Page, args: {
|
|
32
|
+
wsId: string;
|
|
33
|
+
message: string;
|
|
34
|
+
}): Promise<{
|
|
35
|
+
ok: boolean;
|
|
36
|
+
wsId: string;
|
|
37
|
+
url?: string;
|
|
38
|
+
bytes?: number;
|
|
39
|
+
error?: string;
|
|
40
|
+
}>;
|
|
41
|
+
addInterceptor(page: Page, spec: WsInterceptSpec): Promise<{
|
|
42
|
+
key: string;
|
|
43
|
+
active: string[];
|
|
44
|
+
}>;
|
|
45
|
+
removeInterceptor(page: Page, sel: {
|
|
46
|
+
pattern?: string;
|
|
47
|
+
}): Promise<{
|
|
48
|
+
removed: string[];
|
|
49
|
+
active: string[];
|
|
50
|
+
}>;
|
|
51
|
+
/** Server-side mirror of the active patterns — order = insertion. */
|
|
52
|
+
list(): string[];
|
|
53
|
+
/** Read the page-side `__browxWs.list()` registry to surface live WS
|
|
54
|
+
* endpoints + their `wsId`. Best-effort: returns `[]` if the wrapper
|
|
55
|
+
* isn't installed (`install` is the lazy installer; this method is
|
|
56
|
+
* for `ws_send` discoverability and shouldn't itself force install). */
|
|
57
|
+
listSockets(page: Page): Promise<Array<{
|
|
58
|
+
wsId: string;
|
|
59
|
+
url: string;
|
|
60
|
+
readyState: number;
|
|
61
|
+
}>>;
|
|
62
|
+
}
|
|
63
|
+
interface BrowxWsApi {
|
|
64
|
+
send(id: string, msg: string): {
|
|
65
|
+
ok: boolean;
|
|
66
|
+
url?: string;
|
|
67
|
+
bytes?: number;
|
|
68
|
+
error?: string;
|
|
69
|
+
};
|
|
70
|
+
intercept(pattern: string, mode: WsInterceptMode, replacement?: string | null): void;
|
|
71
|
+
unintercept(pattern?: string): void;
|
|
72
|
+
list(): Array<{
|
|
73
|
+
wsId: string;
|
|
74
|
+
url: string;
|
|
75
|
+
readyState: number;
|
|
76
|
+
}>;
|
|
77
|
+
}
|
|
78
|
+
declare global {
|
|
79
|
+
var __browxWs: BrowxWsApi | undefined;
|
|
80
|
+
}
|
|
81
|
+
export declare const WS_PAGE_SCRIPT = "(() => {\n if (window.__browxWs) return;\n var NativeWebSocket = window.WebSocket;\n if (!NativeWebSocket) return;\n var nativeSend = NativeWebSocket.prototype.send;\n var sockets = new Map(); // wsId -> WebSocket\n var nextId = 1;\n var interceptors = []; // { pattern, regex, mode, replacement }\n\n function globToRegex(pat) {\n var out = \"^\";\n for (var i = 0; i < pat.length; i++) {\n var c = pat[i];\n if (c === \"*\") {\n if (pat[i + 1] === \"*\") { out += \".*\"; i++; }\n else { out += \"[^/]*\"; }\n } else if (\"\\\\^$.+?()[]{}|\".indexOf(c) >= 0) {\n out += \"\\\\\" + c;\n } else { out += c; }\n }\n out += \"$\";\n return new RegExp(out);\n }\n\n function matchOne(url) {\n for (var i = 0; i < interceptors.length; i++) {\n if (interceptors[i].regex.test(url)) return interceptors[i];\n }\n return null;\n }\n\n function Wrapped(url, protocols) {\n var sock = arguments.length > 1 ? new NativeWebSocket(url, protocols) : new NativeWebSocket(url);\n var id = \"ws-\" + (nextId++);\n sockets.set(id, sock);\n sock.__browxId = id;\n // Wrap message dispatch. We replace addEventListener(\"message\", \u2026) AND\n // onmessage so both registration paths route through the interceptor.\n var liveListeners = [];\n var origAdd = sock.addEventListener.bind(sock);\n var origRemove = sock.removeEventListener.bind(sock);\n sock.addEventListener = function (type, listener, opts) {\n if (type === \"message\" && typeof listener === \"function\") {\n liveListeners.push(listener);\n return; // we'll dispatch ourselves\n }\n return origAdd(type, listener, opts);\n };\n sock.removeEventListener = function (type, listener, opts) {\n if (type === \"message\" && typeof listener === \"function\") {\n var i = liveListeners.indexOf(listener);\n if (i >= 0) liveListeners.splice(i, 1);\n return;\n }\n return origRemove(type, listener, opts);\n };\n var onmessageFn = null;\n Object.defineProperty(sock, \"onmessage\", {\n configurable: true,\n get: function () { return onmessageFn; },\n set: function (v) { onmessageFn = typeof v === \"function\" ? v : null; },\n });\n function dispatch(payload) {\n var ev = new MessageEvent(\"message\", { data: payload });\n for (var i = 0; i < liveListeners.length; i++) {\n try { liveListeners[i].call(sock, ev); } catch (_) {}\n }\n if (onmessageFn) {\n try { onmessageFn.call(sock, ev); } catch (_) {}\n }\n }\n origAdd(\"message\", function (ev) {\n var hit = matchOne(sock.url || \"\");\n if (!hit) { dispatch(ev.data); return; }\n if (hit.mode === \"drop\") return;\n if (hit.mode === \"echo\") {\n try { nativeSend.call(sock, ev.data); } catch (_) {}\n dispatch(ev.data);\n return;\n }\n // replace\n dispatch(hit.replacement == null ? \"\" : hit.replacement);\n });\n // Expose the id post-construction; the agent reads it via __browxWs.list().\n return sock;\n }\n // Preserve constants + name so feature-detection (`'OPEN' in WebSocket`) keeps working.\n Wrapped.CONNECTING = NativeWebSocket.CONNECTING;\n Wrapped.OPEN = NativeWebSocket.OPEN;\n Wrapped.CLOSING = NativeWebSocket.CLOSING;\n Wrapped.CLOSED = NativeWebSocket.CLOSED;\n Wrapped.prototype = NativeWebSocket.prototype;\n try { Object.defineProperty(Wrapped, \"name\", { value: \"WebSocket\" }); } catch (_) {}\n window.WebSocket = Wrapped;\n\n window.__browxWs = {\n send: function (id, msg) {\n var sock = sockets.get(id);\n if (!sock) return { ok: false, error: \"no socket with id \" + id };\n if (sock.readyState !== 1) return { ok: false, error: \"socket \" + id + \" is not OPEN (readyState=\" + sock.readyState + \")\" };\n try {\n nativeSend.call(sock, msg);\n return { ok: true, url: sock.url || \"\", bytes: typeof msg === \"string\" ? msg.length : 0 };\n } catch (e) {\n return { ok: false, error: e && e.message ? e.message : String(e) };\n }\n },\n intercept: function (pattern, mode, replacement) {\n // Replace any prior interceptor on the same pattern (server-side\n // mirror does the same).\n for (var i = interceptors.length - 1; i >= 0; i--) {\n if (interceptors[i].pattern === pattern) interceptors.splice(i, 1);\n }\n interceptors.push({\n pattern: pattern,\n regex: globToRegex(pattern),\n mode: mode,\n replacement: replacement == null ? null : replacement,\n });\n },\n unintercept: function (pattern) {\n if (pattern === undefined || pattern === null) {\n interceptors.length = 0;\n return;\n }\n for (var i = interceptors.length - 1; i >= 0; i--) {\n if (interceptors[i].pattern === pattern) interceptors.splice(i, 1);\n }\n },\n list: function () {\n var out = [];\n sockets.forEach(function (sock, id) {\n out.push({ wsId: id, url: sock.url || \"\", readyState: sock.readyState });\n });\n return out;\n },\n };\n})();";
|
|
82
|
+
export {};
|