peachsim 0.1.1641 → 0.1.1653

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.
Files changed (618) hide show
  1. package/README.md +12 -0
  2. package/cli/app-bundle-resources.ts +57 -0
  3. package/cli/app-catalog.ts +1 -1
  4. package/cli/app-fonts.ts +11 -80
  5. package/cli/app-splash.ts +18 -12
  6. package/cli/bridge-flow-runner.ts +11 -7
  7. package/cli/cloud-client.ts +10 -13
  8. package/cli/command-registry.ts +13 -4
  9. package/cli/commands/box.ts +4 -4
  10. package/cli/commands/control.ts +105 -53
  11. package/cli/commands/coverage-parser.ts +67 -0
  12. package/cli/commands/coverage.ts +550 -0
  13. package/cli/commands/debug.ts +9 -18
  14. package/cli/commands/desktop.ts +19 -7
  15. package/cli/commands/device.ts +14 -9
  16. package/cli/commands/guest-host.ts +6 -10
  17. package/cli/commands/inspect/core.ts +81 -17
  18. package/cli/commands/inspect.ts +13 -8
  19. package/cli/commands/kotlin.ts +2 -2
  20. package/cli/commands/maestro-compare.ts +1 -1
  21. package/cli/commands/platform.ts +20 -11
  22. package/cli/commands/preview.ts +16 -18
  23. package/cli/commands/runtime.ts +3 -2
  24. package/cli/commands/screenshot-layers.ts +1 -1
  25. package/cli/commands/screenshot.ts +1 -1
  26. package/cli/commands/serve.ts +5 -1
  27. package/cli/commands/support.ts +4 -4
  28. package/cli/commands/three-mode.ts +22 -15
  29. package/cli/commands/upload.ts +44 -45
  30. package/cli/current-sim.ts +38 -0
  31. package/cli/desktop-companion.ts +36 -8
  32. package/cli/device-option.ts +1 -1
  33. package/cli/drivers/playwright.ts +40 -0
  34. package/cli/drivers/types.ts +4 -0
  35. package/cli/help-core.ts +1 -1
  36. package/cli/internal-child.ts +2 -1
  37. package/cli/main.ts +9 -3
  38. package/cli/outbound-endpoints.ts +15 -5
  39. package/cli/output-redaction.ts +39 -14
  40. package/cli/remote-simulators.ts +4 -1
  41. package/cli/scene-video.ts +5 -2
  42. package/cli/send-to-box.ts +7 -10
  43. package/cli/telemetry.ts +1 -1
  44. package/cli/ws-bridge.ts +8 -1
  45. package/detox/attempt-events.cjs +3 -1
  46. package/detox/attempt-events.d.cts +1 -1
  47. package/detox/expectations.ts +108 -99
  48. package/detox/frame-offset.d.mts +6 -0
  49. package/detox/frame-offset.mjs +35 -0
  50. package/detox/gestures.ts +6 -18
  51. package/detox/index.ts +169 -101
  52. package/detox/jest-preset.cjs +1 -3
  53. package/detox/jest-transform.cjs +4 -0
  54. package/detox/matchers.ts +3 -0
  55. package/detox/motion-change.cjs +52 -118
  56. package/detox/motion-change.d.cts +6 -27
  57. package/detox/motion-leg-starts.cjs +20 -0
  58. package/detox/motion-leg-starts.d.cts +8 -0
  59. package/dist-lib/agent-daemon-client.cjs +1 -1
  60. package/dist-lib/agent-events.cjs +1 -1
  61. package/dist-lib/attached-projects.cjs +1 -1
  62. package/dist-lib/auth/shared-session.cjs +1 -1
  63. package/dist-lib/backend-origin.cjs +3 -3
  64. package/dist-lib/beta.cjs +1 -1
  65. package/dist-lib/beta.mjs +1 -1
  66. package/dist-lib/bridge-constants.cjs +1 -1
  67. package/dist-lib/bridge-contract-input.cjs +65 -1
  68. package/dist-lib/bridge-contract-input.mjs +63 -1
  69. package/dist-lib/bridge-contract.cjs +19 -1
  70. package/dist-lib/bridge-contract.mjs +17 -1
  71. package/dist-lib/bundle-channel.cjs +38332 -14940
  72. package/dist-lib/capture-contract.cjs +1 -1
  73. package/dist-lib/capture-contract.mjs +1 -1
  74. package/dist-lib/cloud-contract.cjs +1 -1
  75. package/dist-lib/cloud-contract.mjs +1 -1
  76. package/dist-lib/cloud-test-args.cjs +1 -1
  77. package/dist-lib/cloud-test-args.mjs +1 -1
  78. package/dist-lib/cloud.cjs +1 -1
  79. package/dist-lib/cloud.mjs +1 -1
  80. package/dist-lib/config.cjs +1 -1
  81. package/dist-lib/config.mjs +5 -3
  82. package/dist-lib/detox/index.cjs +1247 -4511
  83. package/dist-lib/detox/jest-preset.cjs +1 -3
  84. package/dist-lib/detox/jest-transform.cjs +4 -0
  85. package/dist-lib/dev-bundle-resolution.cjs +28 -24
  86. package/dist-lib/expo-swift-bundle.cjs +35243 -13172
  87. package/dist-lib/expo-swift-metadata.cjs +1 -1
  88. package/dist-lib/expo-swift-metadata.mjs +1 -1
  89. package/dist-lib/home-paths.cjs +1 -1
  90. package/dist-lib/host/bridge-host.cjs +45285 -63163
  91. package/dist-lib/host/fetch-proxy-handler.cjs +3544 -11
  92. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  93. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  94. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  95. package/dist-lib/host/websocket-proxy.cjs +1 -1
  96. package/dist-lib/index.cjs +1997 -2069
  97. package/dist-lib/jump-to-source-babel.cjs +1 -1
  98. package/dist-lib/jump-to-source-native.cjs +1 -1
  99. package/dist-lib/kotlin-host.cjs +2 -2
  100. package/dist-lib/menu.cjs +14 -6
  101. package/dist-lib/menu.mjs +14 -6
  102. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  103. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  104. package/dist-lib/metro-production-bundle.cjs +1 -1
  105. package/dist-lib/metro-production-bundle.mjs +1 -1
  106. package/dist-lib/metro.cjs +468 -563
  107. package/dist-lib/native-app-identity-project.cjs +128 -292
  108. package/dist-lib/native-app-identity-project.mjs +1262 -51
  109. package/dist-lib/native-app-identity.cjs +8 -3
  110. package/dist-lib/native-app-identity.mjs +8 -3
  111. package/dist-lib/native-firebase-metadata.cjs +1 -1
  112. package/dist-lib/native-firebase-metadata.mjs +1 -1
  113. package/dist-lib/plist.cjs +2 -244
  114. package/dist-lib/plist.mjs +1 -1
  115. package/dist-lib/profiles.cjs +1 -1
  116. package/dist-lib/public-brand.cjs +1 -1
  117. package/dist-lib/public-origins-lib-esm.json +290 -0
  118. package/dist-lib/public-origins-lib-static.json +1 -0
  119. package/dist-lib/public-origins-lib.json +1852 -0
  120. package/dist-lib/react-native-host-modules.cjs +1 -1
  121. package/dist-lib/react-native-host-modules.mjs +1 -1
  122. package/dist-lib/scripts/dev-server-scanner.cjs +14 -253
  123. package/dist-lib/sdk.cjs +84 -16
  124. package/dist-lib/sdk.mjs +82 -15
  125. package/dist-lib/skills.cjs +51248 -75450
  126. package/dist-lib/swift-compile.cjs +26154 -1245
  127. package/dist-lib/swift-compile.mjs +26151 -1230
  128. package/dist-lib/swift-package.cjs +79 -1
  129. package/dist-lib/swift-package.mjs +75 -1
  130. package/dist-lib/swift-submit.cjs +1 -1
  131. package/dist-lib/swift-submit.mjs +1 -1
  132. package/dist-lib/swift-toolchain.cjs +1 -1
  133. package/dist-lib/swift.cjs +1 -1
  134. package/dist-lib/vite-swift.cjs +34394 -12323
  135. package/dist-lib/vite.cjs +373 -298
  136. package/dist-lib/worklet-executable.cjs +1 -1
  137. package/dist-lib/worklet-executable.mjs +1 -1
  138. package/dist-types/packages/peach-compat/src/engine-config.d.ts +2 -0
  139. package/dist-types/packages/peach-compat/src/stubs/form-sheet-spring.d.ts +9 -0
  140. package/dist-types/packages/peach-compat/src/stubs/native-evaluation-lease.d.ts +47 -0
  141. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-cookies.d.ts +113 -0
  142. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-gesture-handler.d.ts +154 -0
  143. package/dist-types/packages/peach-compat/src/stubs/screen-transition-math.d.ts +756 -0
  144. package/dist-types/packages/peach-compat/src/stubs/transition-scalar.d.ts +25 -0
  145. package/dist-types/packages/peach-engine/src/billing/plans.d.ts +64 -0
  146. package/dist-types/packages/peach-engine/src/browser-page-target.d.ts +2 -0
  147. package/dist-types/packages/peach-engine/src/bundle-platform-url.d.ts +3 -0
  148. package/dist-types/packages/peach-engine/src/capture/browser-accessibility-host.d.ts +3 -0
  149. package/dist-types/packages/peach-engine/src/capture/browser-composite.d.ts +55 -0
  150. package/dist-types/packages/peach-engine/src/capture/browserAccessibilityContract.d.ts +27 -0
  151. package/dist-types/packages/peach-engine/src/capture/nativeScreenCaptureContract.d.ts +22 -0
  152. package/dist-types/packages/peach-engine/src/cli-companion.d.ts +36 -0
  153. package/dist-types/packages/peach-engine/src/components/native-ui/webview-frame-bridge.d.ts +34 -0
  154. package/dist-types/packages/peach-engine/src/config.d.ts +5 -0
  155. package/dist-types/packages/peach-engine/src/engine/android-stretch-effect.d.ts +57 -0
  156. package/dist-types/packages/peach-engine/src/engine/animated-driven-style.d.ts +47 -0
  157. package/dist-types/packages/peach-engine/src/engine/animated-value.d.ts +5 -0
  158. package/dist-types/packages/peach-engine/src/engine/animated.d.ts +195 -0
  159. package/dist-types/packages/peach-engine/src/engine/animation-clockContract.d.ts +15 -0
  160. package/dist-types/packages/peach-engine/src/engine/animation-graph.d.ts +148 -0
  161. package/dist-types/packages/peach-engine/src/engine/app-catalog-wire.d.ts +10 -0
  162. package/dist-types/packages/peach-engine/src/engine/app-font-registry.d.ts +87 -0
  163. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph-paint.d.ts +7 -0
  164. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph.d.ts +123 -0
  165. package/dist-types/packages/peach-engine/src/engine/audioContract.d.ts +16 -0
  166. package/dist-types/packages/peach-engine/src/engine/canvaskit-api.d.ts +93 -0
  167. package/dist-types/packages/peach-engine/src/engine/canvaskit-renderer.d.ts +216 -0
  168. package/dist-types/packages/peach-engine/src/engine/config-plugin-fonts.d.ts +40 -0
  169. package/dist-types/packages/peach-engine/src/engine/config-plugin-splash.d.ts +25 -0
  170. package/dist-types/packages/peach-engine/src/engine/cull-visibility.d.ts +44 -0
  171. package/dist-types/packages/peach-engine/src/engine/damage-rect.d.ts +19 -0
  172. package/dist-types/packages/peach-engine/src/engine/engine-resource.d.ts +6 -0
  173. package/dist-types/packages/peach-engine/src/engine/expo-manifest.d.ts +5 -0
  174. package/dist-types/packages/peach-engine/src/engine/fiber-debug-metadata.d.ts +30 -0
  175. package/dist-types/packages/peach-engine/src/engine/font-config.d.ts +139 -0
  176. package/dist-types/packages/peach-engine/src/engine/generated/sf-pro-font.d.ts +1 -0
  177. package/dist-types/packages/peach-engine/src/engine/glass-material.d.ts +31 -0
  178. package/dist-types/packages/peach-engine/src/engine/host-composite.d.ts +100 -0
  179. package/dist-types/packages/peach-engine/src/engine/hosted-semantics.d.ts +49 -0
  180. package/dist-types/packages/peach-engine/src/engine/image-audit.d.ts +70 -0
  181. package/dist-types/packages/peach-engine/src/engine/image-loader.d.ts +350 -0
  182. package/dist-types/packages/peach-engine/src/engine/inspect-info.d.ts +27 -0
  183. package/dist-types/packages/peach-engine/src/engine/inspect-outline.d.ts +14 -0
  184. package/dist-types/packages/peach-engine/src/engine/inspect-visibility.d.ts +33 -0
  185. package/dist-types/packages/peach-engine/src/engine/ios-fast-scroll.d.ts +16 -0
  186. package/dist-types/packages/peach-engine/src/engine/layout-sab.d.ts +43 -0
  187. package/dist-types/packages/peach-engine/src/engine/liquid-glass-rect.d.ts +23 -0
  188. package/dist-types/packages/peach-engine/src/engine/liquid-glass-shaders.d.ts +9 -0
  189. package/dist-types/packages/peach-engine/src/engine/liquid-glass.d.ts +283 -0
  190. package/dist-types/packages/peach-engine/src/engine/live-object-counts.d.ts +6 -0
  191. package/dist-types/packages/peach-engine/src/engine/lottie-runtime.d.ts +32 -0
  192. package/dist-types/packages/peach-engine/src/engine/lottie-types.d.ts +138 -0
  193. package/dist-types/packages/peach-engine/src/engine/memory-counts.d.ts +27 -0
  194. package/dist-types/packages/peach-engine/src/engine/metalDirectContract.d.ts +108 -0
  195. package/dist-types/packages/peach-engine/src/engine/metalShaderContract.d.ts +217 -0
  196. package/dist-types/packages/peach-engine/src/engine/native-animation-driver.d.ts +112 -0
  197. package/dist-types/packages/peach-engine/src/engine/native-animation-graph.d.ts +62 -0
  198. package/dist-types/packages/peach-engine/src/engine/native-layout.d.ts +133 -0
  199. package/dist-types/packages/peach-engine/src/engine/native-resources.d.ts +26 -0
  200. package/dist-types/packages/peach-engine/src/engine/nativeReanimatedContract.d.ts +25 -0
  201. package/dist-types/packages/peach-engine/src/engine/nativeReplayContract.d.ts +64 -0
  202. package/dist-types/packages/peach-engine/src/engine/node.d.ts +589 -0
  203. package/dist-types/packages/peach-engine/src/engine/paint-boundary-types.d.ts +112 -0
  204. package/dist-types/packages/peach-engine/src/engine/paint-boundary.d.ts +57 -0
  205. package/dist-types/packages/peach-engine/src/engine/portalContract.d.ts +21 -0
  206. package/dist-types/packages/peach-engine/src/engine/portals.d.ts +20 -0
  207. package/dist-types/packages/peach-engine/src/engine/render-damage.d.ts +107 -0
  208. package/dist-types/packages/peach-engine/src/engine/riveContract.d.ts +420 -0
  209. package/dist-types/packages/peach-engine/src/engine/rn-spring.d.ts +51 -0
  210. package/dist-types/packages/peach-engine/src/engine/scene-table.d.ts +379 -0
  211. package/dist-types/packages/peach-engine/src/engine/scroll-momentum-math.d.ts +152 -0
  212. package/dist-types/packages/peach-engine/src/engine/scroll-pan-contacts.d.ts +10 -0
  213. package/dist-types/packages/peach-engine/src/engine/scroll-platform.d.ts +75 -0
  214. package/dist-types/packages/peach-engine/src/engine/scroll-range.d.ts +14 -0
  215. package/dist-types/packages/peach-engine/src/engine/scroll-velocity.d.ts +14 -0
  216. package/dist-types/packages/peach-engine/src/engine/scroll.d.ts +320 -0
  217. package/dist-types/packages/peach-engine/src/engine/signal.d.ts +7 -0
  218. package/dist-types/packages/peach-engine/src/engine/snapshot-cache-policy.d.ts +6 -0
  219. package/dist-types/packages/peach-engine/src/engine/svg-geometry.d.ts +41 -0
  220. package/dist-types/packages/peach-engine/src/engine/text-attachment-paragraphs.d.ts +10 -0
  221. package/dist-types/packages/peach-engine/src/engine/text-decoration.d.ts +11 -0
  222. package/dist-types/packages/peach-engine/src/engine/text-line-break.d.ts +22 -0
  223. package/dist-types/packages/peach-engine/src/engine/text-paint-receipt.d.ts +98 -0
  224. package/dist-types/packages/peach-engine/src/engine/text-paragraph.d.ts +11 -0
  225. package/dist-types/packages/peach-engine/src/engine/text-paragraphContract.d.ts +34 -0
  226. package/dist-types/packages/peach-engine/src/engine/text-transform.d.ts +1 -0
  227. package/dist-types/packages/peach-engine/src/engine/types.d.ts +657 -0
  228. package/dist-types/packages/peach-engine/src/engine/visible-frame.d.ts +54 -0
  229. package/dist-types/packages/peach-engine/src/engine/webrtcContract.d.ts +74 -0
  230. package/dist-types/packages/peach-engine/src/graphite-stats-fields.d.ts +184 -0
  231. package/dist-types/packages/peach-engine/src/guest-import-meta.d.ts +12 -0
  232. package/dist-types/packages/peach-engine/src/guest-module-overrides.d.ts +7 -0
  233. package/dist-types/packages/peach-engine/src/ios/app-card-types.d.ts +7 -0
  234. package/dist-types/packages/peach-engine/src/ios/apps/canvas-map-data.d.ts +177 -0
  235. package/dist-types/packages/peach-engine/src/ios/aux-home-scene.d.ts +54 -0
  236. package/dist-types/packages/peach-engine/src/ios/chrome-metrics.d.ts +47 -0
  237. package/dist-types/packages/peach-engine/src/ios/constants.d.ts +21 -0
  238. package/dist-types/packages/peach-engine/src/ios/duo-housing.d.ts +37 -0
  239. package/dist-types/packages/peach-engine/src/ios/home/types.d.ts +29 -0
  240. package/dist-types/packages/peach-engine/src/ios/home-app-catalog.d.ts +43 -0
  241. package/dist-types/packages/peach-engine/src/ios/photo-store.d.ts +73 -0
  242. package/dist-types/packages/peach-engine/src/ios/photoLibraryContract.d.ts +166 -0
  243. package/dist-types/packages/peach-engine/src/ios/shell-controller-types.d.ts +21 -0
  244. package/dist-types/packages/peach-engine/src/ios/shell-transition-debug.d.ts +18 -0
  245. package/dist-types/packages/peach-engine/src/metro-asset-path.d.ts +21 -0
  246. package/dist-types/packages/peach-engine/src/metro-fingerprint-registry-client.d.ts +11 -0
  247. package/dist-types/packages/peach-engine/src/metro-fingerprint.d.ts +38 -0
  248. package/dist-types/packages/peach-engine/src/native-preview-bundle.d.ts +44 -0
  249. package/dist-types/packages/peach-engine/src/observability/types.d.ts +74 -0
  250. package/dist-types/packages/peach-engine/src/peach-warm-manifest.d.ts +32 -0
  251. package/dist-types/packages/peach-engine/src/permissions/app-settings-client.d.ts +25 -0
  252. package/dist-types/packages/peach-engine/src/permissions/system-permission-types.d.ts +20 -0
  253. package/dist-types/packages/peach-engine/src/platform/android-back-panel.d.ts +131 -0
  254. package/dist-types/packages/peach-engine/src/platform/android-gesture-exclusion.d.ts +28 -0
  255. package/dist-types/packages/peach-engine/src/platform/android-predictive-back.d.ts +33 -0
  256. package/dist-types/packages/peach-engine/src/platform/system-bars-state.d.ts +14 -0
  257. package/dist-types/packages/peach-engine/src/playwright-sim-host.d.ts +1 -0
  258. package/dist-types/packages/peach-engine/src/preview/bundle-layout.d.ts +8 -0
  259. package/dist-types/packages/peach-engine/src/preview/bundle-variantContract.d.ts +24 -0
  260. package/dist-types/packages/peach-engine/src/preview/capture-bundle.d.ts +26 -0
  261. package/dist-types/packages/peach-engine/src/preview/compress-node.d.ts +2 -0
  262. package/dist-types/packages/peach-engine/src/preview/compress.d.ts +2 -0
  263. package/dist-types/packages/peach-engine/src/preview/presigned-upload.d.ts +60 -0
  264. package/dist-types/packages/peach-engine/src/preview/trace.d.ts +144 -0
  265. package/dist-types/packages/peach-engine/src/preview/upload-protocol.d.ts +152 -0
  266. package/dist-types/packages/peach-engine/src/profiler/animation-recording-loader.d.ts +1 -0
  267. package/dist-types/packages/peach-engine/src/profiler/profile-trace.d.ts +4 -0
  268. package/dist-types/packages/peach-engine/src/react-bridge.d.ts +3 -0
  269. package/dist-types/packages/peach-engine/src/react-native/AppState.d.ts +45 -0
  270. package/dist-types/packages/peach-engine/src/react-native/Appearance.d.ts +34 -0
  271. package/dist-types/packages/peach-engine/src/react-native/framework-colors-data.d.ts +2 -0
  272. package/dist-types/packages/peach-engine/src/react-native/host-services.d.ts +42 -0
  273. package/dist-types/packages/peach-engine/src/react-native/layout-animation.d.ts +22 -0
  274. package/dist-types/packages/peach-engine/src/react-native/platform-colors.d.ts +17 -0
  275. package/dist-types/packages/peach-engine/src/remote-stream/client-config.d.ts +10 -0
  276. package/dist-types/packages/peach-engine/src/remote-stream/cloud-display.d.ts +58 -0
  277. package/dist-types/packages/peach-engine/src/remote-stream/scene-recording.d.ts +45 -0
  278. package/dist-types/packages/peach-engine/src/render-worker/animated-drive-output.d.ts +35 -0
  279. package/dist-types/packages/peach-engine/src/render-worker/app-load.d.ts +16 -0
  280. package/dist-types/packages/peach-engine/src/render-worker/aux-surface-types.d.ts +2 -0
  281. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-shared.d.ts +42 -0
  282. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-webgpu.d.ts +434 -0
  283. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-worker-init.d.ts +12 -0
  284. package/dist-types/packages/peach-engine/src/render-worker/compositor-backend.d.ts +31 -0
  285. package/dist-types/packages/peach-engine/src/render-worker/compositor-gpu.d.ts +202 -0
  286. package/dist-types/packages/peach-engine/src/render-worker/compositor-protocol.d.ts +1945 -0
  287. package/dist-types/packages/peach-engine/src/render-worker/compositor-runtime/scroll-drag-resample.d.ts +44 -0
  288. package/dist-types/packages/peach-engine/src/render-worker/css-keyframes-drive.d.ts +36 -0
  289. package/dist-types/packages/peach-engine/src/render-worker/edit-menu-geometry.d.ts +8 -0
  290. package/dist-types/packages/peach-engine/src/render-worker/engine-resource-relay.d.ts +21 -0
  291. package/dist-types/packages/peach-engine/src/render-worker/expo-widgetContract.d.ts +16 -0
  292. package/dist-types/packages/peach-engine/src/render-worker/gesture-seam-protocol.d.ts +152 -0
  293. package/dist-types/packages/peach-engine/src/render-worker/graph-linked-value.d.ts +29 -0
  294. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler-contract.d.ts +49 -0
  295. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler.d.ts +12 -0
  296. package/dist-types/packages/peach-engine/src/render-worker/host-service-protocol.d.ts +756 -0
  297. package/dist-types/packages/peach-engine/src/render-worker/image-lifecycle-event.d.ts +22 -0
  298. package/dist-types/packages/peach-engine/src/render-worker/image-pixel-contract.d.ts +48 -0
  299. package/dist-types/packages/peach-engine/src/render-worker/live-frame-mirror.d.ts +34 -0
  300. package/dist-types/packages/peach-engine/src/render-worker/map-command-channel.d.ts +189 -0
  301. package/dist-types/packages/peach-engine/src/render-worker/mapNativeContract.d.ts +101 -0
  302. package/dist-types/packages/peach-engine/src/render-worker/native-dynamic-synchronizable.d.ts +22 -0
  303. package/dist-types/packages/peach-engine/src/render-worker/native-menu-gesture.d.ts +9 -0
  304. package/dist-types/packages/peach-engine/src/render-worker/native-ui-commandContract.d.ts +23 -0
  305. package/dist-types/packages/peach-engine/src/render-worker/native-ui-protocol.d.ts +1087 -0
  306. package/dist-types/packages/peach-engine/src/render-worker/native-widgetContract.d.ts +100 -0
  307. package/dist-types/packages/peach-engine/src/render-worker/nativeAnimMirrorContract.d.ts +174 -0
  308. package/dist-types/packages/peach-engine/src/render-worker/nativeSyncReplyContract.d.ts +11 -0
  309. package/dist-types/packages/peach-engine/src/render-worker/one-native-contentContract.d.ts +54 -0
  310. package/dist-types/packages/peach-engine/src/render-worker/pointerSampleContract.d.ts +14 -0
  311. package/dist-types/packages/peach-engine/src/render-worker/protocol.d.ts +880 -0
  312. package/dist-types/packages/peach-engine/src/render-worker/reanimated-css-contract.d.ts +63 -0
  313. package/dist-types/packages/peach-engine/src/render-worker/reanimated-readiness.d.ts +29 -0
  314. package/dist-types/packages/peach-engine/src/render-worker/resilient-frame-clock.d.ts +22 -0
  315. package/dist-types/packages/peach-engine/src/render-worker/retained-app-load.d.ts +20 -0
  316. package/dist-types/packages/peach-engine/src/render-worker/screen-edge-swipe-commit-protocol.d.ts +1 -0
  317. package/dist-types/packages/peach-engine/src/render-worker/screen-form-sheet-commit-protocol.d.ts +26 -0
  318. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror-tenant.d.ts +37 -0
  319. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror.d.ts +164 -0
  320. package/dist-types/packages/peach-engine/src/render-worker/shell-event-registry.d.ts +119 -0
  321. package/dist-types/packages/peach-engine/src/render-worker/shell-gesture-regions.d.ts +41 -0
  322. package/dist-types/packages/peach-engine/src/render-worker/shell-protocol.d.ts +603 -0
  323. package/dist-types/packages/peach-engine/src/render-worker/shell-scene-schema.d.ts +101 -0
  324. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-inline-sources.d.ts +13 -0
  325. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-wire.d.ts +87 -0
  326. package/dist-types/packages/peach-engine/src/render-worker/test-bridge-protocol.d.ts +47 -0
  327. package/dist-types/packages/peach-engine/src/render-worker/text-inputContract.d.ts +93 -0
  328. package/dist-types/packages/peach-engine/src/render-worker/tree-sync-port.d.ts +102 -0
  329. package/dist-types/packages/peach-engine/src/render-worker/webgpu-frame-transaction.d.ts +292 -0
  330. package/dist-types/packages/peach-engine/src/render-worker/webgpu-readback-scheduler.d.ts +107 -0
  331. package/dist-types/packages/peach-engine/src/render-worker/webview-capture-protocol.d.ts +16 -0
  332. package/dist-types/packages/peach-engine/src/render-worker/worker-input-runtime.d.ts +211 -0
  333. package/dist-types/packages/peach-engine/src/render-worker/worker-storage.d.ts +33 -0
  334. package/dist-types/packages/peach-engine/src/render-worker/worklet-runtime.d.ts +987 -0
  335. package/dist-types/packages/peach-engine/src/render-worker/worklet-sab.d.ts +24 -0
  336. package/dist-types/packages/peach-engine/src/rolldown-bundle-inventory.d.ts +84 -0
  337. package/dist-types/packages/peach-engine/src/rolldown-production-fingerprint.d.ts +31 -0
  338. package/dist-types/packages/peach-engine/src/screenshots/timeline-assets.d.ts +10 -0
  339. package/dist-types/packages/peach-engine/src/screenshots/tokens.d.ts +9 -0
  340. package/dist-types/packages/peach-engine/src/settings/devices.d.ts +70 -0
  341. package/dist-types/packages/peach-engine/src/settings/duo-fold-bus.d.ts +87 -0
  342. package/dist-types/packages/peach-engine/src/settings/interface-rotation.d.ts +30 -0
  343. package/dist-types/packages/peach-engine/src/settings/react-native-configuration.d.ts +12 -0
  344. package/dist-types/packages/peach-engine/src/settings/scene-geometryContract.d.ts +40 -0
  345. package/dist-types/packages/peach-engine/src/settings/store.d.ts +37 -0
  346. package/dist-types/packages/peach-engine/src/shell-events.d.ts +203 -0
  347. package/dist-types/packages/peach-engine/src/shell-intent.d.ts +68 -0
  348. package/dist-types/packages/peach-engine/src/sootsim-event.d.ts +35 -0
  349. package/dist-types/packages/peach-engine/src/top-overlay-state.d.ts +5 -0
  350. package/dist-types/packages/peach-engine/src/web-authentication-automation-host.d.ts +2 -0
  351. package/dist-types/packages/peach-engine/src/webAuthenticationContract.d.ts +34 -0
  352. package/dist-types/packages/peach-engine/src/webview-automation-host.d.ts +180 -0
  353. package/dist-types/packages/peach-engine/src/wireframe-mode.d.ts +16 -0
  354. package/dist-types/packages/peach-globals/src/frameBreakdownContract.d.ts +16 -0
  355. package/dist-types/packages/peach-globals/src/index.d.ts +3311 -0
  356. package/dist-types/packages/peach-globals/src/nativeSurfaceContract.d.ts +76 -0
  357. package/dist-types/packages/peach-globals/src/pointerSourceEventContract.d.ts +8 -0
  358. package/dist-types/packages/peach-globals/src/profileTrace.d.ts +11 -0
  359. package/dist-types/packages/peach-globals/src/profilerContract.d.ts +223 -0
  360. package/dist-types/packages/peach-kit/src/capabilities.d.ts +721 -0
  361. package/dist-types/packages/peach-kit/src/internal.d.ts +4 -0
  362. package/dist-types/packages/peach-kit/src/materials/types.d.ts +27 -0
  363. package/dist-types/packages/peach-kit/src/materials/uikit-blur-material.d.ts +14 -0
  364. package/dist-types/packages/peach-kit/src/navigation-types.d.ts +11 -0
  365. package/dist-types/packages/peach-kit/src/react-bridge.d.ts +53 -0
  366. package/dist-types/packages/peach-kit/src/runtime.d.ts +26 -0
  367. package/dist-types/packages/peach-kit/src/ui/hosting-safe-area.d.ts +24 -0
  368. package/dist-types/packages/peach-kit/src/ui/popover-placement.d.ts +53 -0
  369. package/dist-types/packages/peach-kit/src/ui/presentationContract.d.ts +17 -0
  370. package/kotlin/ComposeSources/PeachComposeHost.kt +1 -1
  371. package/kotlin/JniSources/com/facebook/jni/HybridData.kt +0 -2
  372. package/kotlin/JniSources/dev/peach/jni/NativeBindings.kt +0 -2
  373. package/kotlin/JniTransportSources/dev/peach/jni/integration/JniTransport.kt +0 -2
  374. package/kotlin/README.md +6 -0
  375. package/package.json +22 -2
  376. package/runtime-companion.json +1 -0
  377. package/skills/contrast/SKILL.md +1 -0
  378. package/src/appBundleResourcesContract.ts +51 -0
  379. package/src/assetCatalogContract.ts +21 -0
  380. package/src/backend-origin.ts +3 -1
  381. package/src/bridge-contract-input.ts +84 -0
  382. package/src/bridge-contract.ts +35 -3
  383. package/src/browser-launch-policy.ts +1 -0
  384. package/src/bundle-channel.mjs +4 -2
  385. package/src/cli-runtime.ts +55 -0
  386. package/src/crash-fingerprint.ts +26 -0
  387. package/src/dev-bundle-resolution.ts +50 -23
  388. package/src/device-catalog.ts +1159 -0
  389. package/src/host/bridge-host.ts +20 -37
  390. package/src/host/browser-pointer.ts +71 -0
  391. package/src/host/dev-server-package-versions.ts +23 -0
  392. package/src/host/fetch-proxy-handler.ts +17 -4
  393. package/src/host/staged-host-files.ts +28 -4
  394. package/src/installed-package-versions.ts +142 -38
  395. package/src/kotlin-host.ts +1 -1
  396. package/src/launchMetadataContract.ts +1 -0
  397. package/src/menu.ts +12 -4
  398. package/src/metro-plugin.ts +4 -4
  399. package/src/metro-project-root.ts +68 -0
  400. package/src/native-app-identity-project.ts +47 -38
  401. package/src/nitro-adapter.lock.json +26 -0
  402. package/src/nitro-adapter.ts +103 -0
  403. package/src/nitro-bundle.ts +24 -10
  404. package/src/nitro-compile.ts +33 -51
  405. package/src/nitro-source.ts +177 -96
  406. package/src/nitroAdapterContract.ts +217 -0
  407. package/src/nitroContract.ts +24 -11
  408. package/src/process-group.ts +41 -34
  409. package/src/react-bridge-importers.ts +28 -0
  410. package/src/reactNativeConfigurationContract.ts +36 -0
  411. package/src/runtime-assets.ts +7 -2
  412. package/src/runtime-delivery.ts +8 -7
  413. package/src/runtimePlatformContract.ts +70 -0
  414. package/src/screenshots/frame-compose.ts +42 -43
  415. package/src/screenshots/org-deck.ts +9 -4
  416. package/src/screenshots/preset-names.ts +29 -0
  417. package/src/screenshots/registry.ts +5 -5
  418. package/src/screenshots/schema.ts +1 -1
  419. package/src/screenshots/screenshotContract.ts +971 -0
  420. package/src/settings-flags.ts +107 -0
  421. package/src/settingsContract.ts +609 -0
  422. package/src/storageSnapshotContract.ts +344 -0
  423. package/src/stub-pattern-matcher.ts +550 -0
  424. package/src/swift-compile.ts +926 -47
  425. package/src/swift-compiler-digest.ts +17 -3
  426. package/src/swift-distribution.lock.json +49 -22
  427. package/src/swift-host.ts +167 -52
  428. package/src/swift-objc-compile.ts +86 -26
  429. package/src/swift-objc-export.ts +532 -0
  430. package/src/swift-objc-import.ts +769 -0
  431. package/src/swift-objc-metadata.ts +285 -10
  432. package/src/swift-objc-sdk.ts +13970 -158
  433. package/src/swift-objc-standin.ts +137 -1
  434. package/src/swift-package.ts +94 -0
  435. package/src/swift-packages.ts +5 -5
  436. package/src/swift-root-lock.ts +241 -92
  437. package/src/swift-submit.ts +6 -0
  438. package/src/swiftContract.ts +99 -0
  439. package/src/target-matcher.ts +6 -1
  440. package/src/vite-plugin.ts +14 -40
  441. package/src/worker-system-chunks.ts +1 -1
  442. package/src/workerChunkContract.ts +5 -0
  443. package/src/worklets-babel.ts +24 -5
  444. package/src/xcode-project.ts +103 -11
  445. package/src/xcode-target-members.ts +10 -3
  446. package/cli/drivers/playwright-sim-host.ts +0 -825
  447. package/kotlin/fixtures/counter/Counter.d.kt.ts +0 -17
  448. package/kotlin/fixtures/counter/Counter.kt +0 -51
  449. package/kotlin/fixtures/counter/CounterApp.native.tsx +0 -61
  450. package/kotlin/fixtures/counter/CounterApp.tsx +0 -3
  451. package/kotlin/fixtures/counter/CounterScreen.d.kt.ts +0 -8
  452. package/kotlin/fixtures/counter/CounterScreen.kt +0 -56
  453. package/kotlin/fixtures/counter/app/_layout.tsx +0 -4
  454. package/kotlin/fixtures/counter/app/index+spa.tsx +0 -1
  455. package/kotlin/fixtures/counter/app/routes.d.ts +0 -18
  456. package/kotlin/fixtures/counter/package.json +0 -20
  457. package/kotlin/fixtures/counter/tsconfig.json +0 -19
  458. package/kotlin/fixtures/counter/vite.config.ts +0 -20
  459. package/kotlin/fixtures/headless-counter/Headless.kt +0 -234
  460. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +0 -7
  461. package/kotlin/fixtures/import-animation/Animation.kt +0 -80
  462. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +0 -13
  463. package/kotlin/fixtures/import-animation/README.md +0 -24
  464. package/kotlin/fixtures/import-animation/app/_layout.tsx +0 -4
  465. package/kotlin/fixtures/import-animation/app/index+spa.tsx +0 -1
  466. package/kotlin/fixtures/import-animation/app/routes.d.ts +0 -18
  467. package/kotlin/fixtures/import-animation/package.json +0 -23
  468. package/kotlin/fixtures/import-animation/tsconfig.json +0 -20
  469. package/kotlin/fixtures/import-animation/vite.config.ts +0 -20
  470. package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +0 -7
  471. package/kotlin/fixtures/import-drawing/Drawing.kt +0 -101
  472. package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +0 -18
  473. package/kotlin/fixtures/import-drawing/README.md +0 -34
  474. package/kotlin/fixtures/import-drawing/app/_layout.tsx +0 -4
  475. package/kotlin/fixtures/import-drawing/app/index+spa.tsx +0 -1
  476. package/kotlin/fixtures/import-drawing/package.json +0 -23
  477. package/kotlin/fixtures/import-drawing/tsconfig.json +0 -20
  478. package/kotlin/fixtures/import-drawing/vite.config.ts +0 -20
  479. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +0 -7
  480. package/kotlin/fixtures/import-editor/Editor.kt +0 -59
  481. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +0 -23
  482. package/kotlin/fixtures/import-editor/README.md +0 -27
  483. package/kotlin/fixtures/import-editor/app/_layout.tsx +0 -4
  484. package/kotlin/fixtures/import-editor/app/index+spa.tsx +0 -1
  485. package/kotlin/fixtures/import-editor/package.json +0 -23
  486. package/kotlin/fixtures/import-editor/tsconfig.json +0 -20
  487. package/kotlin/fixtures/import-editor/vite.config.ts +0 -20
  488. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +0 -7
  489. package/kotlin/fixtures/import-effects/Effects.kt +0 -87
  490. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +0 -13
  491. package/kotlin/fixtures/import-effects/README.md +0 -19
  492. package/kotlin/fixtures/import-effects/app/_layout.tsx +0 -4
  493. package/kotlin/fixtures/import-effects/app/index+spa.tsx +0 -1
  494. package/kotlin/fixtures/import-effects/package.json +0 -23
  495. package/kotlin/fixtures/import-effects/tsconfig.json +0 -20
  496. package/kotlin/fixtures/import-effects/vite.config.ts +0 -20
  497. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +0 -13
  498. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +0 -7
  499. package/kotlin/fixtures/import-layout/Layout.kt +0 -72
  500. package/kotlin/fixtures/import-layout/README.md +0 -24
  501. package/kotlin/fixtures/import-layout/app/_layout.tsx +0 -4
  502. package/kotlin/fixtures/import-layout/app/index+spa.tsx +0 -1
  503. package/kotlin/fixtures/import-layout/package.json +0 -23
  504. package/kotlin/fixtures/import-layout/tsconfig.json +0 -20
  505. package/kotlin/fixtures/import-layout/vite.config.ts +0 -20
  506. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +0 -18
  507. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +0 -7
  508. package/kotlin/fixtures/import-navigation/Navigation.kt +0 -104
  509. package/kotlin/fixtures/import-navigation/README.md +0 -31
  510. package/kotlin/fixtures/import-navigation/app/_layout.tsx +0 -4
  511. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +0 -1
  512. package/kotlin/fixtures/import-navigation/package.json +0 -23
  513. package/kotlin/fixtures/import-navigation/tsconfig.json +0 -20
  514. package/kotlin/fixtures/import-navigation/vite.config.ts +0 -20
  515. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +0 -29
  516. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +0 -7
  517. package/kotlin/fixtures/import-overlays/Overlays.kt +0 -93
  518. package/kotlin/fixtures/import-overlays/README.md +0 -34
  519. package/kotlin/fixtures/import-overlays/app/_layout.tsx +0 -4
  520. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +0 -1
  521. package/kotlin/fixtures/import-overlays/package.json +0 -23
  522. package/kotlin/fixtures/import-overlays/tsconfig.json +0 -20
  523. package/kotlin/fixtures/import-overlays/vite.config.ts +0 -20
  524. package/kotlin/fixtures/import-resources/ImportResources.native.tsx +0 -18
  525. package/kotlin/fixtures/import-resources/README.md +0 -26
  526. package/kotlin/fixtures/import-resources/Resources.d.kt.ts +0 -6
  527. package/kotlin/fixtures/import-resources/Resources.kt +0 -72
  528. package/kotlin/fixtures/import-resources/app/_layout.tsx +0 -4
  529. package/kotlin/fixtures/import-resources/app/index+spa.tsx +0 -1
  530. package/kotlin/fixtures/import-resources/package.json +0 -23
  531. package/kotlin/fixtures/import-resources/tsconfig.json +0 -20
  532. package/kotlin/fixtures/import-resources/vite.config.ts +0 -20
  533. package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +0 -10
  534. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +0 -13
  535. package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +0 -4
  536. package/kotlin/fixtures/import-scroll/Nested.kt +0 -64
  537. package/kotlin/fixtures/import-scroll/README.md +0 -38
  538. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +0 -7
  539. package/kotlin/fixtures/import-scroll/Scroll.kt +0 -91
  540. package/kotlin/fixtures/import-scroll/app/_layout.tsx +0 -4
  541. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +0 -1
  542. package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +0 -1
  543. package/kotlin/fixtures/import-scroll/package.json +0 -23
  544. package/kotlin/fixtures/import-scroll/tsconfig.json +0 -20
  545. package/kotlin/fixtures/import-scroll/vite.config.ts +0 -20
  546. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +0 -44
  547. package/kotlin/fixtures/import-selection/README.md +0 -32
  548. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +0 -8
  549. package/kotlin/fixtures/import-selection/Selection.kt +0 -78
  550. package/kotlin/fixtures/import-selection/app/_layout.tsx +0 -4
  551. package/kotlin/fixtures/import-selection/app/index+spa.tsx +0 -1
  552. package/kotlin/fixtures/import-selection/package.json +0 -23
  553. package/kotlin/fixtures/import-selection/tsconfig.json +0 -20
  554. package/kotlin/fixtures/import-selection/vite.config.ts +0 -20
  555. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +0 -13
  556. package/kotlin/fixtures/import-surfaces/README.md +0 -22
  557. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +0 -7
  558. package/kotlin/fixtures/import-surfaces/Surfaces.kt +0 -64
  559. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +0 -4
  560. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +0 -1
  561. package/kotlin/fixtures/import-surfaces/package.json +0 -23
  562. package/kotlin/fixtures/import-surfaces/tsconfig.json +0 -20
  563. package/kotlin/fixtures/import-surfaces/vite.config.ts +0 -20
  564. package/kotlin/fixtures/import-values/ImportValues.native.tsx +0 -61
  565. package/kotlin/fixtures/import-values/README.md +0 -28
  566. package/kotlin/fixtures/import-values/Values.d.kt.ts +0 -15
  567. package/kotlin/fixtures/import-values/Values.kt +0 -84
  568. package/kotlin/fixtures/import-values/app/_layout.tsx +0 -4
  569. package/kotlin/fixtures/import-values/app/index+spa.tsx +0 -1
  570. package/kotlin/fixtures/import-values/package.json +0 -23
  571. package/kotlin/fixtures/import-values/tsconfig.json +0 -20
  572. package/kotlin/fixtures/import-values/vite.config.ts +0 -20
  573. package/kotlin/fixtures/kotlin-app/app/build.gradle.kts +0 -30
  574. package/kotlin/fixtures/kotlin-app/app/src/main/AndroidManifest.xml +0 -13
  575. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/MainActivity.kt +0 -60
  576. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/ProbeApplication.kt +0 -18
  577. package/kotlin/fixtures/kotlin-app/build.gradle.kts +0 -5
  578. package/kotlin/fixtures/kotlin-app/gradle.properties +0 -4
  579. package/kotlin/fixtures/kotlin-app/settings.gradle.kts +0 -4
  580. package/kotlin/fixtures/kotlin-app-variants/Anim.kt +0 -62
  581. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +0 -38
  582. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +0 -36
  583. package/kotlin/fixtures/kotlin-app-variants/Bitmaps.kt +0 -50
  584. package/kotlin/fixtures/kotlin-app-variants/Browse.kt +0 -73
  585. package/kotlin/fixtures/kotlin-app-variants/Colors.kt +0 -41
  586. package/kotlin/fixtures/kotlin-app-variants/Controls.kt +0 -62
  587. package/kotlin/fixtures/kotlin-app-variants/Drag.kt +0 -56
  588. package/kotlin/fixtures/kotlin-app-variants/Draw.kt +0 -74
  589. package/kotlin/fixtures/kotlin-app-variants/Drawables.kt +0 -53
  590. package/kotlin/fixtures/kotlin-app-variants/Focus.kt +0 -62
  591. package/kotlin/fixtures/kotlin-app-variants/Form.kt +0 -47
  592. package/kotlin/fixtures/kotlin-app-variants/Icons.kt +0 -59
  593. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +0 -53
  594. package/kotlin/fixtures/kotlin-app-variants/Lists.kt +0 -57
  595. package/kotlin/fixtures/kotlin-app-variants/Nav.kt +0 -47
  596. package/kotlin/fixtures/kotlin-app-variants/Note.kt +0 -40
  597. package/kotlin/fixtures/kotlin-app-variants/Overlays.kt +0 -56
  598. package/kotlin/fixtures/kotlin-app-variants/Pan.kt +0 -38
  599. package/kotlin/fixtures/kotlin-app-variants/Pickers.kt +0 -44
  600. package/kotlin/fixtures/kotlin-app-variants/Press.kt +0 -43
  601. package/kotlin/fixtures/kotlin-app-variants/Scroll.kt +0 -63
  602. package/kotlin/fixtures/kotlin-app-variants/Sheet.kt +0 -43
  603. package/kotlin/fixtures/kotlin-app-variants/Strings.kt +0 -49
  604. package/kotlin/fixtures/kotlin-app-variants/Tabs.kt +0 -47
  605. package/kotlin/fixtures/kotlin-app-variants/TextWidth.kt +0 -45
  606. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +0 -50
  607. package/kotlin/fixtures/kotlin-app-variants/Transition.kt +0 -69
  608. package/kotlin/fixtures/kotlin-app-variants/ViewConfig.kt +0 -22
  609. package/kotlin/fixtures/kotlin-app-variants/Widgets.kt +0 -67
  610. package/kotlin/fixtures/runtime-state/RuntimeState.kt +0 -200
  611. package/kotlin/fork/README.md +0 -97
  612. package/kotlin/fork/build.sh +0 -176
  613. package/kotlin/fork/compose-worker-globals.patch +0 -1247
  614. package/kotlin/fork/fork.json +0 -46
  615. package/kotlin/fork/publish.ts +0 -99
  616. package/kotlin/fork/skia-android-shaping.patch +0 -189
  617. package/kotlin/fork/skiko-local.init.gradle +0 -10
  618. package/kotlin/fork/skiko-worker-clock.patch +0 -122
@@ -1,825 +0,0 @@
1
- import {
2
- acquireChromiumAdmission,
3
- readChromiumQueue,
4
- } from '../../../../scripts/lib/chromium-admission'
5
- // the detached browser host, as CJS source.
6
- //
7
- // it resolves playwright from the absolute path the driver hands it, launches
8
- // Chrome for Testing, opens the target url, then keeps itself (and therefore
9
- // the browser) alive until the page asks it to close (`peach close`, or the
10
- // bridge reclaiming an idle sim for a queued chromium launch),
11
- // the browser disconnects, or its owning session exits. all inputs arrive
12
- // through the environment.
13
- //
14
- // it stays a source string rather than a module of its own: playwright is
15
- // resolved from the user's project at runtime and is not a dependency here, so
16
- // there are no types for any of this, and a typed rewrite would be `unknown`
17
- // casts end to end. cli/internal-child.ts runs it through node:vm with a real
18
- // require, in a child process the CLI spawns as itself.
19
- import {
20
- chromeDisabledFeaturesSwitch,
21
- LINUX_CHROME_SCOPE_ENV,
22
- softwareChromeLaunchOptions,
23
- } from '../../../../scripts/lib/reap-browser'
24
- import { createBrowserPageTargetReader } from '../../../peach-engine/src/browser-page-target'
25
- import { captureBrowserAccessibility } from '../../../peach-engine/src/capture/browser-accessibility-host'
26
- import {
27
- readBrowserCompositeCaptureRequest,
28
- resolveBrowserCompositeCdpClip,
29
- } from '../../../peach-engine/src/capture/browser-composite'
30
- import { WEBVIEW_HOST_BOOTSTRAP_SOURCE } from '../../../peach-engine/src/components/native-ui/webview-frame-bridge'
31
- import { createBrowserPointerDispatcher } from '../../../peach-engine/src/render-worker/browser-pointer'
32
- import { automateWebAuthenticationSessions } from '../../../peach-engine/src/web-authentication-automation-host'
33
- import {
34
- automateWebViewFrames,
35
- WEBVIEW_HOST_BINDING,
36
- WEBVIEW_INSTANCE_ATTRIBUTE,
37
- WEBVIEW_SCHEME_NAVIGATION_EVENT,
38
- WEBVIEW_NETWORK_NAVIGATION_EVENT,
39
- WEBVIEW_LOAD_EVENT,
40
- webViewAutomationHelpersSource,
41
- } from '../../../peach-engine/src/webview-automation-host'
42
- import { DISPOSABLE_BROWSER_CACHE_DIR_NAMES } from '../../src/browser-cache'
43
- import { listProcessChildren } from '../../src/process-group'
44
-
45
- // a person's tap on the device canvas is a trusted input, which gives the page
46
- // the user activation browsers require before media plays with sound, and an
47
- // AVAudioPlayer started from that tap sounds. the driver's taps are dispatched
48
- // inside the page and never activate it, so without this an app's play() is
49
- // refused where the same tap by a person plays (RAN:
50
- // scripts/debug/audiotap-probe.ts). ios needs no gesture for audio at all.
51
- // every proof that drives media in chromium launches with this one policy.
52
- export const DRIVER_AUTOPLAY_POLICY = '--autoplay-policy=no-user-gesture-required'
53
-
54
- export const PLAYWRIGHT_SIM_HOST = `
55
- const modulePath = process.env.SOOTSIM_PW_MODULE;
56
- const executablePath = process.env.SOOTSIM_PW_EXECUTABLE;
57
- // the shared libraries this host lacks, from peach's bundle. only the browser
58
- // gets them on its library path: the bundled builds are older than the system's.
59
- const libraryPath = process.env.SOOTSIM_PW_LIBRARY_PATH;
60
- if (!executablePath) throw new Error('SOOTSIM_PW_EXECUTABLE is not set');
61
- const url = process.env.SOOTSIM_PW_URL;
62
- // the WS bridge port the sim page must register with, injected below as
63
- // window.__sootsimBridgePort so the page skips its shell-port heuristic (which
64
- // assumes the default offset and breaks when the dev bridge drifted).
65
- const bridgePort = process.env.SOOTSIM_PW_BRIDGE_PORT || '';
66
- const fetchProxySpki = process.env.PEACH_PW_FETCH_PROXY_SPKI || '';
67
- const headless = process.env.SOOTSIM_PW_HEADLESS === '1';
68
- const callerUserDataDir = process.env.SOOTSIM_PW_USERDATADIR || '';
69
- // pid of the session that launched us (its topmost non-init ancestor). when
70
- // that process exits we tear Chrome down — see startOwnerWatch below. it is a
71
- // required lifetime bound: an invalid value aborts before Chrome launches.
72
- // SOOTSIM_PW_OWNER_POLL_MS is a test-only override of the 5s poll interval;
73
- // production never sets it.
74
- const ownerPid = Number(process.env.SOOTSIM_PW_OWNER_PID || 0);
75
- // the open command waiting for this host to connect; it may queue for the
76
- // browser slot and then be killed by its own caller's budget.
77
- const launcherPid = Number(process.env.SOOTSIM_PW_LAUNCHER_PID || 0);
78
- const ownerPollMs = Number(process.env.SOOTSIM_PW_OWNER_POLL_MS || 5000);
79
- // optional CDP port — exposes Chrome's remote-debugging endpoint so a
80
- // bridge-driven sim can also be cpu-profiled (peach perf cpu --cdp-port).
81
- // playwright keeps its own pipe connection; the port is an additional endpoint.
82
- const cdpPort = process.env.SOOTSIM_PW_CDP_PORT || '';
83
- // the native desktop host's standalone command (a JSON array). it attaches to
84
- // this headless browser over CDP, composites the sim, and presents page frames
85
- // only when a capture asks (specs/peach-desktop-host/headless.md).
86
- const hostCommand = process.env.PEACH_PW_HOST_COMMAND ? JSON.parse(process.env.PEACH_PW_HOST_COMMAND) : null;
87
- if (hostCommand && (!headless || !cdpPort)) {
88
- throw new Error('[playwright-driver] the desktop host attaches only to a headless browser with a CDP port');
89
- }
90
- // extra chromium launch args, space-separated. a linux GPU runner injects
91
- // '--use-angle=vulkan --enable-features=Vulkan' here so chrome binds the
92
- // real GPU instead of silently falling back to swiftshader software
93
- // rendering (which pegs cores and produces ~1fps canvas capture).
94
- const extraChromeArgs = (process.env.SOOTSIM_PW_CHROME_ARGS || '')
95
- .split(' ')
96
- .filter(Boolean);
97
- // A Mac always has a GPU, so a local macOS drive that lands on Playwright's
98
- // software renderer is a misconfiguration that pegs every core: it fails
99
- // closed unless the hardware-backed test browser is proven after launch. CI
100
- // and Linux or Windows hosts, which are often GPU-less servers, use the
101
- // bundled browser and render in software when no GPU is present.
102
- const hardwareGpuRequired =
103
- process.platform === 'darwin' && process.env.CI !== '1' && process.env.CI !== 'true';
104
- const softwareRendererPattern = /swiftshader|software(?: rasterizer)?|llvmpipe|lavapipe|softpipe/i;
105
- // page viewport as '<w>x<h>'. the caller sizes it from the device profile;
106
- // the fallback is phone-shaped because the page hosts a phone sim — the
107
- // playwright default (1280x720 desktop) letterboxes the device frame.
108
- const viewportSpec = /^(\\d+)x(\\d+)$/.exec(process.env.SOOTSIM_PW_VIEWPORT || '');
109
- const viewport = viewportSpec
110
- ? { width: Number(viewportSpec[1]), height: Number(viewportSpec[2]) }
111
- : { width: 600, height: 900 };
112
- // host display pixels per css pixel; default to a retina Mac browser's 2.
113
- // medium renders at 2 and high at device native, independently of browser DPR.
114
- // low follows measured on-screen density, capped at device native.
115
- // SOOTSIM_PW_DSF changes browser DPR, not the selected render resolution.
116
- const deviceScaleFactor = Number(process.env.SOOTSIM_PW_DSF || 2);
117
- const closeTimeoutMs = Number(process.env.SOOTSIM_PW_CLOSE_TIMEOUT_MS || 2500);
118
- const connectAckFile = process.env.SOOTSIM_PW_CONNECTED_ACK_FILE || '';
119
- const admittedFile = process.env.SOOTSIM_PW_ADMITTED_FILE || '';
120
- const completionFile = process.env.PEACH_PW_COMPLETION_FILE || '';
121
- const disposableBrowserCacheDirs = new Set(${JSON.stringify(
122
- DISPOSABLE_BROWSER_CACHE_DIR_NAMES,
123
- )});
124
- const { existsSync, mkdtempSync, readdirSync, readFileSync, rmSync, unlinkSync, writeFileSync } = require('fs');
125
- const { execSync, spawn, spawnSync } = require('child_process');
126
- const listProcessChildren = ${listProcessChildren.toString()};
127
- const { tmpdir } = require('os');
128
- const { join } = require('path');
129
- const createBrowserPointerDispatcher = ${createBrowserPointerDispatcher.toString()};
130
- const captureBrowserAccessibility = ${captureBrowserAccessibility.toString()};
131
- const automateWebViewFrames = ${automateWebViewFrames.toString()};
132
- const automateWebAuthenticationSessions = ${automateWebAuthenticationSessions.toString()};
133
- const webViewAutomationHelpers = ${webViewAutomationHelpersSource()};
134
- const readBrowserCompositeCaptureRequest = ${readBrowserCompositeCaptureRequest.toString()};
135
- const resolveBrowserCompositeCdpClip = ${resolveBrowserCompositeCdpClip.toString()};
136
- const acquireChromiumAdmission = ${acquireChromiumAdmission.toString()};
137
- const readChromiumQueue = ${readChromiumQueue.toString()};
138
- // chrome tree reaper — playwright's browser.close() and even SIGKILLing the
139
- // root chrome process do NOT reliably take down the helper tree (gpu, renderer,
140
- // network/storage utilities). they reparent to launchd/init and survive, each
141
- // one busy enough to peg CPU at 100%+. close() only reaches the root.
142
- //
143
- // the prior approach was \`pgrep -f ms-playwright/[c]hromium\`. it never matched
144
- // system Chrome, so the reaper was a no-op in the common case and every
145
- // aborted/closed \`peach open\` leaked a renderer + gpu helper burning 100%+
146
- // CPU until manually killed (multiple incidents 2026-06).
147
- //
148
- // a named profile can already belong to another host. its path finds browser
149
- // candidates; the unique launch environment proves which ones we may reap,
150
- // including helpers reparented after the browser root exits.
151
- const reapEnabled = process.platform !== 'win32';
152
- let profileDir = callerUserDataDir;
153
- let ephemeralProfile = false;
154
- if (!profileDir) {
155
- profileDir = mkdtempSync(join(tmpdir(), 'peach-playwright-host-'));
156
- ephemeralProfile = true;
157
- }
158
- // browser HTTP caches are acceleration data, not profile identity. give each
159
- // host a bounded temporary cache so persistent named profiles retain cookies
160
- // and storage without multiplying a private cache for every profile.
161
- const diskCacheDir = mkdtempSync(join(tmpdir(), 'peach-playwright-cache-'));
162
- let profileLaunched = false;
163
- // [pid, command line] for every process on the profile. linux reads /proc,
164
- // since minimal and rootless images ship no ps.
165
- const profileProcesses = () => {
166
- if (!reapEnabled) return [];
167
- try {
168
- // match the whole --user-data-dir argument: a pattern search also found
169
- // browsers whose profile path merely starts with this one.
170
- const flag = ' --user-data-dir=' + profileDir + ' ';
171
- const rows = process.platform === 'linux'
172
- ? readdirSync('/proc').filter((name) => /^\\d+$/.test(name)).map((name) => {
173
- let command = '';
174
- // a process can exit between the listing and this read
175
- try { command = readFileSync('/proc/' + name + '/cmdline', 'utf8').split('\\0').join(' ').trim(); } catch {}
176
- return [Number(name), command];
177
- })
178
- : execSync('ps -axo pid=,command=', {
179
- stdio: ['ignore', 'pipe', 'ignore'],
180
- maxBuffer: Infinity,
181
- })
182
- .toString().split('\\n').map((line) => line.trim().match(/^(\\d+)\\s+(.*)$/))
183
- .filter(Boolean).map((row) => [Number(row[1]), row[2]]);
184
- return rows.filter(([pid, command]) => pid && pid !== process.pid && (' ' + command + ' ').includes(flag));
185
- } catch (error) {
186
- throw new Error('[playwright-driver] cannot establish browser profile ownership: ' + String(error));
187
- }
188
- };
189
- const chromePidsByProfile = () => profileProcesses().map(([pid]) => pid);
190
- const chromeCommandsByProfile = () => profileProcesses().map(([, command]) => command);
191
- const assertNoUnsafeSwiftShaderFlag = () => {
192
- if (!hardwareGpuRequired) return;
193
- const unsafe = chromeCommandsByProfile().find((command) =>
194
- command.includes('--enable-unsafe-swiftshader') ||
195
- /--use-angle=(?:swiftshader|swiftshader-webgl)(?:\\s|$)/i.test(command)
196
- );
197
- if (unsafe) {
198
- throw new Error(
199
- '[playwright-driver] refused software-rendering Chrome: launched process contains a SwiftShader flag'
200
- );
201
- }
202
- };
203
- const killTree = (pid) => {
204
- let kids = [];
205
- try {
206
- kids = listProcessChildren([pid]);
207
- } catch {}
208
- for (const k of kids) killTree(k);
209
- try { process.kill(pid, 'SIGKILL'); } catch {}
210
- };
211
- const reapChrome = () => {
212
- try {
213
- for (const pid of chromePidsByProfile()) {
214
- let owned = false;
215
- if (process.platform === 'linux') {
216
- try {
217
- owned = readFileSync('/proc/' + pid + '/environ', 'utf8').split('\\0')
218
- .includes('PEACH_PW_BROWSER_OWNER=' + diskCacheDir);
219
- } catch {}
220
- } else {
221
- const plain = spawnSync('ps', ['-o', 'command=', '-p', String(pid)], { encoding: 'utf8' });
222
- const withEnv = spawnSync('ps', ['eww', '-o', 'command=', '-p', String(pid)], { encoding: 'utf8' });
223
- const argv = (plain.stdout || '').trimEnd();
224
- const full = (withEnv.stdout || '').trimEnd();
225
- owned = plain.status === 0 && withEnv.status === 0 && full.startsWith(argv) &&
226
- (full.slice(argv.length) + ' ').includes(' PEACH_PW_BROWSER_OWNER=' + diskCacheDir + ' ');
227
- }
228
- if (owned) killTree(pid);
229
- }
230
- } catch (error) {
231
- process.stderr.write('[playwright-driver] browser teardown refused: ' + String(error) + '\\n');
232
- }
233
- };
234
- const removeDisposableCaches = (root) => {
235
- let children = [];
236
- try { children = readdirSync(root, { withFileTypes: true }); } catch { return; }
237
- for (const child of children) {
238
- if (!child.isDirectory() || child.isSymbolicLink()) continue;
239
- const childPath = join(root, child.name);
240
- if (disposableBrowserCacheDirs.has(child.name)) {
241
- try { rmSync(childPath, { recursive: true, force: true }); } catch {}
242
- continue;
243
- }
244
- removeDisposableCaches(childPath);
245
- }
246
- };
247
- // chrome treats a SingletonLock whose recorded hostname differs from the
248
- // current one as held by another machine, and macOS renames the host with the
249
- // network, so a lock left by a killed host blocks every relaunch of a named
250
- // profile. no process runs this profile here, so its lock files are stale.
251
- const clearStaleSingletonLock = () => {
252
- if (chromePidsByProfile().length > 0) return;
253
- for (const name of ['SingletonLock', 'SingletonSocket', 'SingletonCookie']) {
254
- try { rmSync(join(profileDir, name), { force: true }); } catch {}
255
- }
256
- };
257
- const cleanupProfile = () => {
258
- try { rmSync(diskCacheDir, { recursive: true, force: true }); } catch {}
259
- if (ephemeralProfile) {
260
- try { rmSync(profileDir, { recursive: true, force: true }); } catch {}
261
- return;
262
- }
263
- if (profileLaunched) removeDisposableCaches(profileDir);
264
- };
265
- (async () => {
266
- const pw = require(modulePath);
267
- let context;
268
- let keepAlive = null;
269
- let connectTimer = null;
270
- let connectAckPoll = null;
271
- let ownerWatch = null;
272
- let connected = false;
273
- let shuttingDown = false;
274
- let desktopHost = null;
275
- // the host runs the tenant's workers in its realms, where the browser cannot see them; it
276
- // evaluates there over node ipc and answers each realm's value as it settles, null where one
277
- // throws. only that page's target is inspected; the first value that is not null answers,
278
- // or null once no realm in that page is pending
279
- const hostEvaluations = new Map();
280
- let hostEvaluation = 0;
281
- const readPageTarget = (${createBrowserPageTargetReader.toString()})();
282
- const hostRealms = (page) => ({
283
- evaluate: async (fn, args) => {
284
- const targetId = await readPageTarget(page);
285
- return new Promise((resolve) => {
286
- const id = ++hostEvaluation;
287
- hostEvaluations.set(id, resolve);
288
- desktopHost.send({ t: 'evaluate', id, targetId, expression: '(' + fn + ')(' + JSON.stringify(args) + ')' });
289
- });
290
- },
291
- });
292
- const stopDesktopHost = async () => {
293
- if (!desktopHost || desktopHost.exitCode !== null || desktopHost.signalCode !== null) return;
294
- const exited = new Promise((resolve) => desktopHost.once('exit', resolve));
295
- desktopHost.kill('SIGTERM');
296
- await exited;
297
- };
298
- // the host's ready line follows its CDP auto-attach registration, so every
299
- // page this browser opens afterwards is composited by it
300
- const startDesktopHost = async () => {
301
- // the persistent context's token changes on relaunch; its stores belong to the browser profile.
302
- const profileSession = await context.newCDPSession(context.pages()[0]);
303
- let profileContext;
304
- try {
305
- const { targetInfo } = await profileSession.send('Target.getTargetInfo');
306
- profileContext = targetInfo.browserContextId;
307
- if (!profileContext) throw new Error('[playwright-driver] persistent browser context has no identity');
308
- } finally {
309
- await profileSession.detach();
310
- }
311
- desktopHost = spawn(
312
- hostCommand[0],
313
- [...hostCommand.slice(1), '--port', '0', '--browser', 'http://127.0.0.1:' + cdpPort, '--headless',
314
- '--profile', join(profileDir, 'peach-node'), '--profile-context', profileContext],
315
- { stdio: ['ignore', 'ignore', 'pipe', 'ipc'] },
316
- );
317
- desktopHost.on('message', (m) => {
318
- if (m.value === null && m.pending > 0) return;
319
- hostEvaluations.get(m.id)?.(m.value);
320
- hostEvaluations.delete(m.id);
321
- });
322
- let log = '';
323
- const hostUrl = await new Promise((resolve, reject) => {
324
- const timer = setTimeout(() => reject(new Error('[playwright-driver] desktop host did not start within 30s: ' + log)), 30000);
325
- desktopHost.once('error', (error) => { clearTimeout(timer); reject(error); });
326
- desktopHost.once('exit', (code) => { clearTimeout(timer); reject(new Error('[playwright-driver] desktop host exited during startup (' + code + '): ' + log)); });
327
- desktopHost.stderr.on('data', (data) => {
328
- process.stderr.write(data);
329
- if (log.length < 65536) log += String(data);
330
- const ready = /peach host on (http:\\/\\/127\\.0\\.0\\.1:\\d+\\/)/.exec(log);
331
- if (ready) { clearTimeout(timer); resolve(ready[1]); }
332
- });
333
- });
334
- desktopHost.removeAllListeners('exit');
335
- desktopHost.once('exit', (code) => {
336
- process.stderr.write('[playwright-driver] desktop host exited (' + code + ')\\n');
337
- void shutdown(3);
338
- });
339
- process.stderr.write('[playwright-driver] desktop host attached on ' + hostUrl + '\\n');
340
- };
341
- const clearConnectTimer = () => {
342
- if (connectTimer) {
343
- clearTimeout(connectTimer);
344
- connectTimer = null;
345
- }
346
- if (connectAckPoll) {
347
- clearInterval(connectAckPoll);
348
- connectAckPoll = null;
349
- }
350
- };
351
- const markConnected = () => {
352
- connected = true;
353
- clearConnectTimer();
354
- };
355
- const ackFileExists = () => {
356
- if (!connectAckFile) return false;
357
- try { return existsSync(connectAckFile); } catch { return false; }
358
- };
359
- const bounded = async (label, work, timeoutMs) => {
360
- let timer = null;
361
- try {
362
- const timeout = new Promise((resolve) => {
363
- timer = setTimeout(() => resolve({ timedOut: true }), timeoutMs);
364
- });
365
- if (typeof timer.unref === 'function') timer.unref();
366
- const result = await Promise.race([
367
- Promise.resolve().then(work).then(
368
- () => ({ timedOut: false }),
369
- (error) => ({ timedOut: false, error }),
370
- ),
371
- timeout,
372
- ]);
373
- if (result && result.timedOut) {
374
- process.stderr.write('[shutdown-timeout] ' + label + ' exceeded ' + timeoutMs + 'ms\\n');
375
- return false;
376
- }
377
- if (result && result.error) {
378
- process.stderr.write('[shutdown-error] ' + label + ': ' + String((result.error && result.error.message) || result.error) + '\\n');
379
- return false;
380
- }
381
- return true;
382
- } finally {
383
- if (timer) clearTimeout(timer);
384
- }
385
- };
386
- const browserProcess = () => {
387
- if (context && typeof context.browser === 'function') {
388
- try {
389
- const b = context.browser();
390
- if (b && typeof b.process === 'function') return b.process();
391
- } catch {}
392
- }
393
- return null;
394
- };
395
- const processIsAlive = (proc) => {
396
- if (!proc || !proc.pid) return false;
397
- try {
398
- process.kill(proc.pid, 0);
399
- return true;
400
- } catch (err) {
401
- return err && err.code === 'EPERM';
402
- }
403
- };
404
- const terminateBrowserProcess = async () => {
405
- const proc = browserProcess();
406
- if (!proc || !proc.pid || !processIsAlive(proc)) return;
407
- try { proc.kill('SIGTERM'); } catch {}
408
- await bounded('browser process exit after SIGTERM', async () => {
409
- while (processIsAlive(proc)) {
410
- await new Promise((resolve) => setTimeout(resolve, 50));
411
- }
412
- }, 600);
413
- if (!processIsAlive(proc)) return;
414
- try { proc.kill('SIGKILL'); } catch {}
415
- };
416
- const shutdown = async (code = 0) => {
417
- if (shuttingDown) return;
418
- shuttingDown = true;
419
- clearConnectTimer();
420
- if (keepAlive) clearInterval(keepAlive);
421
- if (ownerWatch) clearInterval(ownerWatch);
422
- const timeoutMs = Number.isFinite(closeTimeoutMs) && closeTimeoutMs > 0 ? closeTimeoutMs : 2500;
423
- if (desktopHost) desktopHost.removeAllListeners('exit');
424
- await bounded('desktop host stop', stopDesktopHost, timeoutMs);
425
- if (context) await bounded('context.close', () => context.close(), timeoutMs);
426
- await terminateBrowserProcess();
427
- // close() can leave reparented helpers; reap only this launch's browser
428
- // and helpers, even if another host now uses the same named profile.
429
- reapChrome();
430
- cleanupProfile();
431
- if (connectAckFile) {
432
- try { unlinkSync(connectAckFile); } catch {}
433
- }
434
- if (admittedFile) {
435
- try { unlinkSync(admittedFile); } catch {}
436
- }
437
- process.exit(code);
438
- };
439
- process.once('SIGTERM', () => { void shutdown(0); });
440
- process.once('SIGINT', () => { void shutdown(0); });
441
- // the launch-failure path at the bottom of this script exits without going
442
- // through shutdown(); the exit hook (sync sweep) still reaps the tree.
443
- process.on('exit', (code) => {
444
- if (desktopHost && desktopHost.exitCode === null) desktopHost.kill('SIGKILL');
445
- reapChrome();
446
- cleanupProfile();
447
- if (completionFile) {
448
- try {
449
- writeFileSync(completionFile, JSON.stringify({ code, pid: process.pid, completedAt: Date.now() }) + '\\n');
450
- } catch (error) {
451
- process.stderr.write('[completion-error] ' + String(error) + '\\n');
452
- }
453
- }
454
- });
455
- // owner-liveness watchdog — the load-bearing fix for leaked Chrome hosts.
456
- // we are spawned detached + unref'd so \`peach open\` returns immediately,
457
- // which means nothing in the OS process tree ties Chrome's lifetime to the
458
- // session that asked for it. once the sim connects, the connect-timeout
459
- // safety net is cleared, so absent an explicit \`peach close\` (or the
460
- // daemon's idle reaper closing the sim socket) the host would hold Chrome
461
- // open forever after its owner exits. poll the owning session's pid and tear
462
- // down when it's gone. ESRCH (kill throws) = owner exited; EPERM = alive but
463
- // not signalable by us, which still counts as alive.
464
- const startOwnerWatch = () => {
465
- if (!Number.isInteger(ownerPid) || ownerPid < 1) {
466
- throw new Error('[playwright-driver] missing valid owning process; refusing unsupervised browser host');
467
- }
468
- const intervalMs = Number.isFinite(ownerPollMs) && ownerPollMs > 0 ? ownerPollMs : 5000;
469
- const gone = (pid) => {
470
- try {
471
- process.kill(pid, 0);
472
- return false;
473
- } catch (err) {
474
- return !(err && err.code === 'EPERM');
475
- }
476
- };
477
- ownerWatch = setInterval(() => {
478
- if (gone(ownerPid)) {
479
- process.stderr.write('[owner-gone] owning process ' + ownerPid + ' exited; closing playwright host\\n');
480
- void shutdown(0);
481
- return;
482
- }
483
- // until the sim connects, the open command is the only one waiting for
484
- // it; once that command is gone nobody receives the sim.
485
- if (!connected && !ackFileExists() && Number.isInteger(launcherPid) && launcherPid > 1 && gone(launcherPid)) {
486
- process.stderr.write('[launcher-gone] open command ' + launcherPid + ' exited before the sim connected; closing playwright host\\n');
487
- void shutdown(2);
488
- }
489
- }, intervalMs);
490
- if (typeof ownerWatch.unref === 'function') ownerWatch.unref();
491
- };
492
- startOwnerWatch();
493
- // Local rendering uses Playwright's full Chrome for Testing app. On macOS its
494
- // com.google.chrome.for.testing identity cannot intercept open/quit events for
495
- // the user's com.google.Chrome browser. CI and non-Mac hosts use
496
- // chromium_headless_shell; local Mac rendering fails closed because that
497
- // shell has no GPU and silently chooses SwiftShader. NOTE: this is NOT enough to make \`peach perf cpu\`
498
- // work — that profiles the tenant *worker*, and the JS Self-Profiler API
499
- // cannot be constructed in a dedicated worker (see
500
- // worker-handlers/cpu-profile.ts). cpu-profile needs a CDP-based profiler
501
- // instead.
502
- if (
503
- hardwareGpuRequired &&
504
- extraChromeArgs.some((arg) =>
505
- arg === '--enable-unsafe-swiftshader' ||
506
- /^--use-angle=(?:swiftshader|swiftshader-webgl)$/i.test(arg)
507
- )
508
- ) {
509
- throw new Error('[playwright-driver] refused SwiftShader launch arguments');
510
- }
511
- // one browser path per environment: the full, separately identified test app
512
- // on a local Mac; the bundled chromium everywhere else. never launch a
513
- // branded user browser.
514
- const channelsToTry = hardwareGpuRequired ? ['chromium'] : [null];
515
- const launchWith = async (channel) => {
516
- const opts = channel
517
- ? { headless, channel, viewport, deviceScaleFactor }
518
- : { headless, viewport, deviceScaleFactor };
519
- opts.env = { ...process.env, PEACH_PW_BROWSER_OWNER: diskCacheDir };
520
- opts.executablePath = executablePath;
521
- if (libraryPath) {
522
- opts.env = {
523
- ...opts.env,
524
- LD_LIBRARY_PATH: [libraryPath, process.env.LD_LIBRARY_PATH].filter(Boolean).join(':'),
525
- };
526
- }
527
- // keep the browser main process with its children in the caller's cgroup.
528
- // otherwise chromium moves only main into a systemd app scope over dbus.
529
- if (process.platform === 'linux') {
530
- opts.env = { ...process.env, ...opts.env, ...${JSON.stringify(LINUX_CHROME_SCOPE_ENV)} };
531
- }
532
- // playwright injects --force-color-profile=srgb by default, which reads
533
- // visibly washed-out next to a normal chrome window on a wide-gamut mac
534
- // display. strip it so driver-launched sims color-match the user's own
535
- // browser (real incident 2026-07-09: "low res and whitewashed" sim).
536
- opts.ignoreDefaultArgs = ['--force-color-profile=srgb'];
537
- // headless chromium backgrounds/occludes the renderer and throttles rAF +
538
- // timers to ~1fps, which silently starves combined/video frame capture
539
- // (was 47 frames over 63s -> frozen-looking mp4). keep the render loop at
540
- // full rate so the recorder captures real motion. document.hidden stays
541
- // false in headless, so assertTabVisibleForCapture never caught this — it
542
- // has to be fixed at the launch flags.
543
- opts.args = [
544
- '--disk-cache-dir=' + diskCacheDir,
545
- '--disk-cache-size=67108864',
546
- '--disable-background-timer-throttling',
547
- '--disable-backgrounding-occluded-windows',
548
- '--disable-renderer-backgrounding',
549
- ${JSON.stringify(DRIVER_AUTOPLAY_POLICY)},
550
- ];
551
- if (channel) {
552
- // the full test browser can bind the real platform GPU — force the native
553
- // ANGLE backend and strip playwright's --enable-unsafe-swiftshader
554
- // default arg. without both, headless chrome silently falls back to
555
- // swiftshader software rendering for the CanvasKit/WebGL canvas and
556
- // pegs every core. SOOTSIM_PW_CHROME_ARGS is appended later, so an
557
- // env-injected --use-angle=... still overrides (last flag wins).
558
- const angle = process.platform === 'darwin' ? 'metal'
559
- : process.platform === 'linux' ? 'vulkan' : 'default';
560
- opts.args.unshift(
561
- '--use-angle=' + angle,
562
- '--enable-gpu',
563
- '--enable-gpu-rasterization',
564
- '--enable-zero-copy',
565
- '--ignore-gpu-blocklist',
566
- '--enable-unsafe-webgpu',
567
- );
568
- opts.ignoreDefaultArgs.push('--enable-unsafe-swiftshader');
569
- } else if (hostCommand) {
570
- // the attached desktop host draws every surface on its own device, so the
571
- // page composites only dom and the frames a capture presents: chromium's
572
- // software compositor does that without a gpu process emulated on the cpu
573
- opts.args.push('--disable-gpu');
574
- } else {
575
- // the shared software launch owns the webgpu canvas backing and watchdog
576
- // flags too; an adapter alone does not prove a canvas can present.
577
- opts.args.push(...${JSON.stringify(softwareChromeLaunchOptions({}).args)});
578
- }
579
- opts.args.push(${JSON.stringify(chromeDisabledFeaturesSwitch())});
580
- if (fetchProxySpki) opts.args.push('--ignore-certificate-errors-spki-list=' + fetchProxySpki);
581
- if (cdpPort) opts.args.push('--remote-debugging-port=' + cdpPort);
582
- if (extraChromeArgs.length) opts.args.push(...extraChromeArgs);
583
- // headed: size the OS window to the (phone-shaped) viewport too, plus
584
- // room for chrome's own toolbar, so the window isn't desktop-shaped
585
- // around a letterboxed page.
586
- if (!headless) opts.args.push('--window-size=' + viewport.width + ',' + (viewport.height + 88));
587
- const launched = await pw.chromium.launchPersistentContext(profileDir, opts);
588
- profileLaunched = true;
589
- return launched;
590
- };
591
- // the host-wide chromium slot is held for this host's life; its exit frees it
592
- await acquireChromiumAdmission({
593
- fs: require('fs'),
594
- os: require('os'),
595
- path: require('path'),
596
- childProcess: require('child_process'),
597
- label: 'peach sim host ' + profileDir,
598
- readQueue: readChromiumQueue,
599
- });
600
- // the launcher's connect wait starts here: time queued for the slot is not
601
- // time the sim had to connect.
602
- if (admittedFile) {
603
- try { writeFileSync(admittedFile, JSON.stringify({ admittedAt: Date.now(), pid: process.pid }) + '\\n'); } catch {}
604
- }
605
- clearStaleSingletonLock();
606
- let launchErr = null;
607
- let launchedChannel = null;
608
- for (const channel of channelsToTry) {
609
- try {
610
- context = await launchWith(channel);
611
- launchedChannel = channel || 'chromium';
612
- launchErr = null;
613
- break;
614
- } catch (err) {
615
- launchErr = err;
616
- const msg = err && err.message ? String(err.message) : '';
617
- const isMissingChannel =
618
- /not found at/i.test(msg) ||
619
- /not installed/i.test(msg) ||
620
- /Chromium distribution/i.test(msg);
621
- if (!isMissingChannel) throw err; // unexpected failure: bubble up
622
- if (channel) {
623
- const next = hardwareGpuRequired
624
- ? '; bundled Chromium is disabled for local GPU work\\n'
625
- : ', falling back to bundled chromium\\n';
626
- process.stderr.write('[playwright-driver] channel "' + channel + '" not available' + next);
627
- }
628
- }
629
- }
630
- if (launchErr) throw launchErr;
631
- if (launchedChannel) {
632
- process.stderr.write('[playwright-driver] launched ' + launchedChannel + '\\n');
633
- }
634
- if (hostCommand) await startDesktopHost();
635
- // grant camera up front so the sim's Camera app reaches the host webcam
636
- // through getUserMedia, mirroring a real iOS simulator where the camera just
637
- // works. without this the unhandled chrome permission prompt auto-denies and
638
- // CameraApp renders its "Camera Access Required" placeholder.
639
- // location does NOT follow the same rule: a real iOS simulator never reads
640
- // the host Mac's real position, it reports a simulated device location
641
- // (simctl location / engine/geolocation-source.ts). granting chrome's
642
- // geolocation here would leak the operator's real position into the tenant
643
- // and its backend, so host-service-main.ts never reaches navigator.geolocation.
644
- await context.grantPermissions(['camera']);
645
- const hostMeta = {
646
- sootsimHostDriver: 'playwright',
647
- peachRenderer: hostCommand ? 'native' : 'chromium',
648
- peachHostExecutable: hostCommand ? hostCommand[0] : null,
649
- sootsimHostPid: process.pid,
650
- sootsimHostOwnerPid: ownerPid,
651
- sootsimHostStartedAt: Date.now(),
652
- };
653
- // inject the resolved bridge port (numeric literal) BEFORE the page runs, so
654
- // the shell/engine talk to the daemon this driver owns. addInitScript runs
655
- // ahead of every page script, and the vite dev plugin only fills the value in
656
- // when it is still unset, so this one wins. plain assignment, NOT
657
- // defineProperty: other injectors also assign to it, and a non-writable
658
- // property would throw at that assignment and crash boot.
659
- const bridgePortInject = bridgePort
660
- ? 'window.__sootsimBridgePort = ' + Number(bridgePort) + ';'
661
- : '';
662
- await context.addInitScript({
663
- content: 'Object.defineProperty(window, "__sootsimHostMeta", { value: ' + JSON.stringify(hostMeta) + ', configurable: true });' + bridgePortInject,
664
- });
665
- // react-native-webview's frames: the bridge at document start of every
666
- // document, CSP-proof injection, source.headers, no framing refusals and
667
- // app-scheme navigations, as a WKWebView gives its page.
668
- const webViewTimingName = 'peachwv' + require('crypto').randomBytes(12).toString('hex');
669
- await automateWebViewFrames(
670
- context,
671
- {
672
- hostBinding: ${JSON.stringify(WEBVIEW_HOST_BINDING)},
673
- instanceAttribute: ${JSON.stringify(WEBVIEW_INSTANCE_ATTRIBUTE)},
674
- schemeNavigationEvent: ${JSON.stringify(WEBVIEW_SCHEME_NAVIGATION_EVENT)},
675
- networkNavigationEvent: ${JSON.stringify(WEBVIEW_NETWORK_NAVIGATION_EVENT)},
676
- loadEvent: ${JSON.stringify(WEBVIEW_LOAD_EVENT)},
677
- configTimingName: webViewTimingName,
678
- bootstrapSource: '(' + ${JSON.stringify(WEBVIEW_HOST_BOOTSTRAP_SOURCE)} + ')(' + JSON.stringify(webViewTimingName) + ');',
679
- },
680
- webViewAutomationHelpers,
681
- hostCommand ? (page) => [hostRealms(page)] : (page) => page.workers(),
682
- );
683
- await context.exposeBinding('__sootsimHostClose', async () => {
684
- await shutdown(0);
685
- });
686
- const pointerHosts = new WeakMap();
687
- await context.exposeBinding('__peachHostAccessibility', (source, instanceIds) =>
688
- captureBrowserAccessibility(source.page, instanceIds));
689
- await context.exposeBinding('__sootsimHostPointer', async (source, value) => {
690
- let pending = pointerHosts.get(source.page);
691
- if (!pending) {
692
- pending = source.page.context().newCDPSession(source.page).then(session =>
693
- createBrowserPointerDispatcher((method, params) => session.send(method, params)));
694
- pointerHosts.set(source.page, pending);
695
- }
696
- await (await pending)(value);
697
- });
698
- await context.exposeBinding('__sootsimHostCapture', async (source, value) => {
699
- const request = readBrowserCompositeCaptureRequest(value);
700
- // a headless desktop host presents page frames only for a capture
701
- if (desktopHost) await source.page.evaluate(() => window.__peachNative.prepareCapture());
702
- const session = await source.page.context().newCDPSession(source.page);
703
- try {
704
- const { clip, originX, originY } = resolveBrowserCompositeCdpClip(
705
- request,
706
- await session.send('Page.getLayoutMetrics'),
707
- );
708
- const result = await session.send('Page.captureScreenshot', {
709
- format: 'png',
710
- fromSurface: true,
711
- captureBeyondViewport: true,
712
- clip,
713
- });
714
- return { dataUrl: 'data:image/png;base64,' + result.data, originX, originY };
715
- } finally {
716
- await session.detach();
717
- }
718
- });
719
- const connectTimeoutMs = Number(process.env.SOOTSIM_PW_CONNECT_TIMEOUT_MS || 120000);
720
- if (connectAckFile) {
721
- connectAckPoll = setInterval(() => {
722
- if (ackFileExists()) markConnected();
723
- }, 500);
724
- if (typeof connectAckPoll.unref === 'function') connectAckPoll.unref();
725
- }
726
- connectTimer = setTimeout(() => {
727
- if (ackFileExists()) {
728
- markConnected();
729
- return;
730
- }
731
- if (connected) return;
732
- process.stderr.write('[connect-timeout] sim did not register with the bridge within ' + connectTimeoutMs + 'ms; closing playwright host\\n');
733
- void shutdown(2);
734
- }, Number.isFinite(connectTimeoutMs) && connectTimeoutMs > 0 ? connectTimeoutMs : 120000);
735
- if (typeof connectTimer.unref === 'function') connectTimer.unref();
736
- const page = await context.newPage();
737
- await automateWebAuthenticationSessions(context, '__peachWebAuthenticationHost', page, !headless);
738
- if (hardwareGpuRequired) {
739
- assertNoUnsafeSwiftShaderFlag();
740
- const gpu = await page.evaluate(() => {
741
- const canvas = document.createElement('canvas');
742
- const gl =
743
- canvas.getContext('webgl2', { powerPreference: 'high-performance' }) ||
744
- canvas.getContext('webgl', { powerPreference: 'high-performance' });
745
- if (!gl) return { renderer: null, vendor: null };
746
- const info = gl.getExtension('WEBGL_debug_renderer_info');
747
- return {
748
- renderer: info ? String(gl.getParameter(info.UNMASKED_RENDERER_WEBGL)) : null,
749
- vendor: info ? String(gl.getParameter(info.UNMASKED_VENDOR_WEBGL)) : null,
750
- };
751
- });
752
- if (!gpu.renderer) {
753
- throw new Error(
754
- '[playwright-driver] could not prove a hardware WebGL renderer; refusing local render-heavy launch'
755
- );
756
- }
757
- if (softwareRendererPattern.test(gpu.renderer)) {
758
- throw new Error('[playwright-driver] refused software WebGL renderer: ' + gpu.renderer);
759
- }
760
- assertNoUnsafeSwiftShaderFlag();
761
- process.stderr.write(
762
- '[playwright-driver] hardware WebGL renderer: ' + gpu.renderer +
763
- (gpu.vendor ? ' (' + gpu.vendor + ')' : '') + '\\n'
764
- );
765
- }
766
- // surface page-side failures (engine boot crash, failed WS registration)
767
- // to stderr so a sim that never connects produces a real diagnostic
768
- // instead of a silent "timed out waiting for opened sim to connect".
769
- page.on('pageerror', (e) => {
770
- process.stderr.write('[pageerror] ' + ((e && e.stack) || e) + '\\n');
771
- });
772
- page.on('console', (m) => {
773
- if (m.type() === 'error') {
774
- process.stderr.write('[console.error] ' + m.text() + '\\n');
775
- if (hostCommand && m.text().includes('[compositor] worker lost:')) void shutdown(1);
776
- }
777
- });
778
- // a crashed renderer never runs the page's bridge close path, so nothing
779
- // would ever close this host.
780
- page.on('crash', () => {
781
- process.stderr.write('[page] renderer crashed; closing playwright host\\n');
782
- void shutdown(1);
783
- });
784
- try {
785
- await page.goto(url, { waitUntil: 'domcontentloaded', timeout: 60000 });
786
- } catch (err) {
787
- const message = String((err && err.message) || err);
788
- process.stderr.write('[goto] ' + message + '\\n');
789
- // nothing serves this url: the page is a dead error document that can
790
- // never register, and nothing re-navigates — waiting out the connect
791
- // timeout burns 125s proving it (peach test on an unserved shell). exit
792
- // now so the caller fails fast. a goto TIMEOUT keeps waiting (a
793
- // slow-but-alive server may still finish loading the page); only
794
- // connection-level failures, where no server exists at all, are fatal.
795
- if (/ERR_CONNECTION_REFUSED|ERR_ADDRESS_UNREACHABLE|ERR_NAME_NOT_RESOLVED/.test(message)) {
796
- process.stderr.write('[unserved] nothing serves ' + url + '; closing playwright host\\n');
797
- void shutdown(3);
798
- }
799
- }
800
- keepAlive = setInterval(() => {}, 1 << 30);
801
- // browser disconnect (e.g. user killed chrome from outside) → tear down.
802
- // we are persistent-only now, so .browser() is the only handle to it.
803
- try {
804
- const b = context.browser && context.browser();
805
- if (b && typeof b.on === 'function') b.on('disconnected', () => { void shutdown(0); });
806
- } catch {}
807
- context.on('close', () => { void shutdown(0); });
808
- page.on('close', () => { void shutdown(0); });
809
- })().catch((err) => {
810
- const detail = String((err && err.stack) || err);
811
- process.stderr.write(detail + '\\n');
812
- // chrome's own error ("Missing X server") says what is wrong on a linux
813
- // box with no display, not what to do about it.
814
- if (
815
- process.platform === 'linux' &&
816
- !headless &&
817
- !process.env.DISPLAY &&
818
- !process.env.WAYLAND_DISPLAY &&
819
- /missing x server|cannot open display|x server|x11/i.test(detail)
820
- ) {
821
- process.stderr.write('hint: linux without DISPLAY/WAYLAND_DISPLAY — rerun without --headed (or add --headless) to run playwright headless.\\n');
822
- }
823
- process.exit(1);
824
- });
825
- `