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,4 +1,9 @@
1
- import { spawn, execFileSync, type ExecFileOptions } from 'node:child_process'
1
+ import {
2
+ spawn,
3
+ execFileSync,
4
+ type ExecFileOptions,
5
+ type SpawnOptions,
6
+ } from 'node:child_process'
2
7
  import { createHash } from 'node:crypto'
3
8
  import {
4
9
  cpSync,
@@ -15,8 +20,10 @@ import {
15
20
  } from 'node:fs'
16
21
  import os from 'node:os'
17
22
  import path from 'node:path'
23
+ import yaml from 'yaml'
18
24
  import { admittedMacBuilderSlot } from './admitted-mac-build'
19
25
  import { rnxHomeDir, swiftPackageCacheOptions } from './home-paths'
26
+ import { isRecord } from './is-record'
20
27
  import { terminateProcessGroup } from './process-group'
21
28
  import { swiftCompilerSourceDigest } from './swift-compiler-digest'
22
29
  import { designTimeDiagnostic, designTimeSource } from './swift-design-time'
@@ -26,16 +33,38 @@ import {
26
33
  type SwiftDistributionManifest,
27
34
  } from './swift-distribution-contract'
28
35
  import { swiftIcuAsset, type SwiftIcuAsset } from './swift-icu'
36
+ import { swiftObjCExports } from './swift-objc-export'
37
+ import { swiftObjCImports, swiftObjCPrivateImports } from './swift-objc-import'
38
+ import { validateObjcPeerStartupLibraries } from './swift-objc-metadata'
39
+ import { materializeObjcSdk, objcView } from './swift-objc-standin'
29
40
  import {
41
+ OBJC_RESOURCE_ACCESSOR_BODY,
42
+ OBJC_RESOURCE_ACCESSOR_HEADER,
30
43
  swiftManifestCxxLanguageStandard,
31
44
  swiftManifestTargets,
45
+ swiftObjCResourceAccessor,
46
+ swiftObjCResourceBundleName,
32
47
  swiftPackagePartition,
33
48
  swiftTargetModuleName,
34
49
  type SwiftPackageTarget,
35
50
  } from './swift-package'
36
- import { withSwiftRootLock } from './swift-root-lock'
37
- import { swiftEnvironment, swiftSdkOptions, type SwiftWasmSdk } from './swift-toolchain'
38
- import { isSwiftResourceBundles } from './swiftContract'
51
+ import { withSwiftRootLock, type SwiftRootLease } from './swift-root-lock'
52
+ import {
53
+ swiftEnvironment,
54
+ swiftSdkOptions,
55
+ swiftToolchain,
56
+ type SwiftWasmSdk,
57
+ } from './swift-toolchain'
58
+ import {
59
+ isSwiftNativeTargets,
60
+ isSwiftObjCPeerStartup,
61
+ isSwiftResourceBundles,
62
+ SWIFT_NATIVE_INPUT_ROOT,
63
+ SWIFT_NATIVE_SDK_INCLUDE,
64
+ type SwiftNativeTarget,
65
+ type SwiftObjCPeerStartup,
66
+ type SwiftProjectPreparation,
67
+ } from './swiftContract'
39
68
  import type { SwiftImageUpload } from './swift-submit'
40
69
  import type { SwiftResourceBundle } from './swiftContract'
41
70
 
@@ -43,27 +72,32 @@ export { swiftIcuAsset, type SwiftIcuAsset }
43
72
 
44
73
  // compiler drivers own descendants such as admission and swiftpm workers.
45
74
  // cancellation waits for their pipes to close before releasing the build root.
75
+ // a `lease` records the group under the root's lock, so the root stays held
76
+ // while the compiler lives even if this process does not.
46
77
  // `stream` echoes the output as it arrives: all of it, or only matching lines.
47
78
  // a successful run then echoes the rest minus lines matching `quiet`, its
48
79
  // warnings; a failed run's output goes to the caller's one diagnostic.
49
80
  async function runCompiler(
50
81
  command: string,
51
82
  args: string[],
52
- options: ExecFileOptions & { signal?: AbortSignal },
83
+ options: ExecFileOptions & { signal?: AbortSignal; lease?: SwiftRootLease },
53
84
  stream: boolean | RegExp = false,
54
85
  quiet?: RegExp,
55
- ): Promise<void> {
86
+ ): Promise<string> {
56
87
  const { signal } = options
57
88
  signal?.throwIfAborted()
58
- const child = spawn(command, args, {
89
+ const launch = {
59
90
  cwd: options.cwd,
60
91
  env: swiftEnvironment(options.env),
61
92
  detached: true,
62
- stdio: ['ignore', 'pipe', 'pipe'],
63
- })
93
+ stdio: ['ignore', 'pipe', 'pipe'] as ['ignore', 'pipe', 'pipe'],
94
+ } satisfies SpawnOptions
95
+ const child = options.lease
96
+ ? options.lease.spawn(command, args, launch)
97
+ : spawn(command, args, launch)
64
98
  let stopping: Promise<void> | undefined
65
99
  try {
66
- await new Promise<void>((resolve, reject) => {
100
+ return await new Promise<string>((resolve, reject) => {
67
101
  let failure: Error | undefined
68
102
  let timeout: ReturnType<typeof setTimeout> | undefined
69
103
  const chunks: Record<'stdout' | 'stderr', Buffer[]> = { stdout: [], stderr: [] }
@@ -119,7 +153,7 @@ async function runCompiler(
119
153
  for (const name of ['stdout', 'stderr'] as const)
120
154
  for (const line of Buffer.concat(chunks[name]).toString().split('\n'))
121
155
  if (line && !quiet.test(line)) process[name].write(`${line}\n`)
122
- resolve()
156
+ resolve(Buffer.concat(chunks.stdout).toString())
123
157
  }
124
158
  })
125
159
  if (options.timeout)
@@ -134,7 +168,7 @@ async function runCompiler(
134
168
  }
135
169
  }
136
170
 
137
- const WASM_TRIPLE = 'wasm32-unknown-wasip1'
171
+ export const WASM_TRIPLE = 'wasm32-unknown-wasip1'
138
172
 
139
173
  // swiftpm's step counter, echoed while a build runs; its diagnostics print
140
174
  // once, with the failure.
@@ -151,6 +185,8 @@ const BUILD_JOBS = String(
151
185
 
152
186
  export interface SwiftCompileInput {
153
187
  files: Record<string, string>
188
+ objcPeerStartup?: SwiftObjCPeerStartup
189
+ nativeTargets?: SwiftNativeTarget[]
154
190
  metalSources?: Record<string, string>
155
191
  resources?: Record<string, string>
156
192
  /** project-relative resource paths retained before the bundle namespace flattens. */
@@ -828,6 +864,8 @@ export function swiftArtifactHash(
828
864
  [...(input.resourceBundles ?? [])].sort((a, b) => a.target.localeCompare(b.target)),
829
865
  ),
830
866
  )
867
+ hash.update(JSON.stringify(input.nativeTargets ?? []))
868
+ hash.update(JSON.stringify(input.objcPeerStartup ?? null))
831
869
  for (const target of Object.keys(input.libraries ?? {}).sort()) {
832
870
  hash.update(`library\n${target}\n`)
833
871
  hash.update(
@@ -854,9 +892,13 @@ export function swiftArtifactHash(
854
892
  interface SwiftNativeTargetPlan {
855
893
  path: string
856
894
  includeDirectory: string
895
+ sources: string[]
857
896
  // units that consume a swift-generated header: excluded from the original
858
897
  // target and compiled by the downstream implementation target.
859
898
  lateSources: string[]
899
+ mixed?: boolean
900
+ exclude?: string[]
901
+ groups?: { name: string; sources: string[]; flags: string[]; cxxFlags: string[] }[]
860
902
  late?: { name: string; producers: string[] }
861
903
  }
862
904
 
@@ -865,6 +907,7 @@ export function emitSwiftPackageManifest(args: {
865
907
  cxxLanguageStandard?: string
866
908
  native?: Map<string, SwiftNativeTargetPlan>
867
909
  headerDirectory?: string
910
+ objcExports?: { modules: Set<string>; flags: string[] }
868
911
  siblings: Map<string, string[]>
869
912
  moduleRoot: string
870
913
  oneModule?: boolean
@@ -943,6 +986,9 @@ export function emitSwiftPackageManifest(args: {
943
986
  ? ' .defaultIsolation(MainActor.self),'
944
987
  : ''
945
988
  const interoperability = target.cxxInterop ? ' .interoperabilityMode(.Cxx),' : ''
989
+ const exports = args.objcExports?.modules.has(target.name)
990
+ ? ' .enableExperimentalFeature("Extern"),'
991
+ : ''
946
992
  const defines = (target.defines ?? [])
947
993
  .map((name) => ` .define(${JSON.stringify(name)}),`)
948
994
  .join('')
@@ -959,8 +1005,9 @@ export function emitSwiftPackageManifest(args: {
959
1005
  ? `, "-I", ${JSON.stringify(path.join(moduleRoot, 'modules'))}`
960
1006
  : ''
961
1007
  const native = args.native?.get(target.name)
1008
+ const clang = native && !native.mixed
962
1009
  const nativeImports = (siblings.get(target.name) ?? [])
963
- .filter((name) => args.native?.has(name))
1010
+ .filter((name) => args.native?.has(name) && !args.native.get(name)?.mixed)
964
1011
  .map(
965
1012
  (name) =>
966
1013
  `, "-Xfrontend", "-import-module", "-Xfrontend", ${JSON.stringify(swiftTargetModuleName(name))}`,
@@ -971,30 +1018,54 @@ export function emitSwiftPackageManifest(args: {
971
1018
  [...(args.native?.values() ?? [])].some((value) =>
972
1019
  value.late?.producers.includes(target.name),
973
1020
  )
974
- ? `, "-emit-objc-header-path", ${JSON.stringify(path.join(args.headerDirectory, `${target.name}-Swift.h`))}`
1021
+ ? `, "-emit-objc-header-path", ${JSON.stringify(path.join(args.headerDirectory, `${target.name}-${args.objcExports?.modules.has(target.name) ? 'Cxx' : 'Swift'}.h`))}`
975
1022
  : ''
976
- const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation}${interoperability}${defines} .unsafeFlags(["-Osize", "-Xfrontend", "-enable-cross-import-overlays"${overlayFlags}${FOUNDATION_IMPLICIT_FLAGS}${oneModule ? ONE_IMPLICIT_FLAGS : ''}${imports}${nativeImports}${header}])]`
1023
+ const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation}${interoperability}${defines}${exports} .unsafeFlags(["-Osize", "-Xfrontend", "-enable-cross-import-overlays"${overlayFlags}${FOUNDATION_IMPLICIT_FLAGS}${oneModule ? ONE_IMPLICIT_FLAGS : ''}${imports}${nativeImports}${header}])]`
977
1024
  const deps = [
978
- ...(target.executable
979
- ? [...(args.native?.values() ?? [])].flatMap((value) =>
980
- value.late ? [JSON.stringify(value.late.name)] : [],
1025
+ ...new Set([
1026
+ ...(target.executable
1027
+ ? [
1028
+ ...new Set([
1029
+ ...(args.objcExports?.modules ?? []),
1030
+ ...[...(args.native?.values() ?? [])].flatMap(
1031
+ (value) => value.late?.producers ?? [],
1032
+ ),
1033
+ ]),
1034
+ ]
1035
+ .filter((name) => name !== target.name)
1036
+ .map((name) => JSON.stringify(name))
1037
+ : []),
1038
+ ...(target.executable && args.objcExports ? ['"PeachSwiftObjCExports"'] : []),
1039
+ ...(target.executable
1040
+ ? [...(args.native?.values() ?? [])].flatMap((value) =>
1041
+ value.late
1042
+ ? (value.groups ?? [{ name: value.late.name }]).map((group) =>
1043
+ JSON.stringify(group.name),
1044
+ )
1045
+ : [],
1046
+ )
1047
+ : []),
1048
+ ...(distribution || (clang && !target.executable)
1049
+ ? []
1050
+ : [
1051
+ '.product(name: "SwiftUI", package: "sootsim-swift")',
1052
+ ...(oneModule ? [ONE_PRODUCT] : []),
1053
+ ...(spriteKit ? [SPRITEKIT_PRODUCT] : []),
1054
+ ]),
1055
+ ...(siblings.get(target.name) ?? []).flatMap((dependency) =>
1056
+ clang &&
1057
+ [...(args.native?.values() ?? [])].some((value) =>
1058
+ value.late?.producers.includes(dependency),
981
1059
  )
982
- : []),
983
- ...(distribution || (native && !target.executable)
984
- ? []
985
- : [
986
- '.product(name: "SwiftUI", package: "sootsim-swift")',
987
- ...(oneModule ? [ONE_PRODUCT] : []),
988
- ...(spriteKit ? [SPRITEKIT_PRODUCT] : []),
989
- ]),
990
- ...(siblings.get(target.name) ?? []).flatMap((dependency) =>
991
- OPTIONAL_FRAMEWORKS.has(dependency) &&
992
- !targets.some((candidate) => candidate.name === dependency)
993
- ? distribution
994
1060
  ? []
995
- : [`.product(name: "${dependency}", package: "sootsim-swift")`]
996
- : [`"${dependency}"`],
997
- ),
1061
+ : OPTIONAL_FRAMEWORKS.has(dependency) &&
1062
+ !targets.some((candidate) => candidate.name === dependency)
1063
+ ? distribution
1064
+ ? []
1065
+ : [`.product(name: "${dependency}", package: "sootsim-swift")`]
1066
+ : [`"${dependency}"`],
1067
+ ),
1068
+ ]),
998
1069
  ].join(', ')
999
1070
  const library =
1000
1071
  distribution && distributionLink
@@ -1017,7 +1088,7 @@ export function emitSwiftPackageManifest(args: {
1017
1088
  linkerSettings: [
1018
1089
  ${linkedLibraries.map((setting) => `${setting},`).join('\n ')}
1019
1090
  .unsafeFlags([
1020
- ${REACTOR_FLAG}${EXECUTABLE_LINK_FLAGS} "-Xlinker", "--export-if-defined=__main_argc_argv"${library},
1091
+ ${REACTOR_FLAG}${EXECUTABLE_LINK_FLAGS} "-Xlinker", "--export-if-defined=__main_argc_argv"${args.objcExports ? ', "-Xlinker", "--fatal-warnings"' : ''}${library},
1021
1092
  ]),
1022
1093
  .unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
1023
1094
  ]`
@@ -1030,10 +1101,12 @@ export function emitSwiftPackageManifest(args: {
1030
1101
  ` name: "${target.name}",`,
1031
1102
  ` dependencies: [${deps}],`,
1032
1103
  ` path: "${target.path}",`,
1033
- ...(native ? [` exclude: ${JSON.stringify(native.lateSources)},`] : []),
1104
+ ...(native
1105
+ ? [` exclude: ${JSON.stringify(native.exclude ?? native.lateSources)},`]
1106
+ : []),
1034
1107
  // the native backend supplies dependency module maps without their
1035
1108
  // compiled modules. textual c++ includes keep those dependencies usable.
1036
- ` ${native ? `cxxSettings: [${defines} .unsafeFlags(["-fno-cxx-modules"])]` : swiftSettings}${link}`,
1109
+ ` ${clang ? `${args.objcExports ? `cSettings: [.unsafeFlags(${JSON.stringify(args.objcExports.flags)})], ` : ''}cxxSettings: [${defines} .unsafeFlags(["-fno-cxx-modules"])]` : swiftSettings}${link}`,
1037
1110
  ` ),`,
1038
1111
  ].join('\n')
1039
1112
  }
@@ -1050,16 +1123,40 @@ export function emitSwiftPackageManifest(args: {
1050
1123
  ` dependencies: [${distribution ? '' : `.package(path: "${moduleRoot}")`}],`,
1051
1124
  ' targets: [',
1052
1125
  ...targets.map(stanza),
1126
+ ...(args.objcExports
1127
+ ? [
1128
+ ' .target(name: "PeachSwiftObjCExports",',
1129
+ ' dependencies: [],',
1130
+ ' path: "PeachObjCExports",',
1131
+ ` sources: ${JSON.stringify(['root.m', ...[...args.objcExports.modules].map((name) => `${name}.m`)])},`,
1132
+ ' publicHeadersPath: "include",',
1133
+ ` cSettings: [.unsafeFlags(${JSON.stringify([...args.objcExports.flags.filter((flag) => flag !== '-fobjc-arc'), '-fno-objc-arc', '-Xclang', '-disable-objc-default-synthesize-properties'])})]),`,
1134
+ ]
1135
+ : []),
1053
1136
  ...[...(args.native?.entries() ?? [])].flatMap(([name, native]) =>
1054
1137
  native.late
1055
- ? [
1056
- ` .target(name: ${JSON.stringify(native.late.name)},`,
1057
- ` dependencies: ${JSON.stringify([name, ...native.late.producers])},`,
1138
+ ? (
1139
+ native.groups ?? [
1140
+ {
1141
+ name: native.late.name,
1142
+ sources: native.lateSources,
1143
+ flags: [],
1144
+ cxxFlags: [],
1145
+ },
1146
+ ]
1147
+ ).flatMap((group) => [
1148
+ ` .target(name: ${JSON.stringify(group.name)},`,
1149
+ ` dependencies: ${JSON.stringify(args.native?.get(name)?.mixed ? [] : [name])},`,
1058
1150
  ` path: ${JSON.stringify(native.path)},`,
1059
- ` sources: ${JSON.stringify(native.lateSources)},`,
1151
+ ` sources: ${JSON.stringify(group.sources)},`,
1060
1152
  ` publicHeadersPath: "include",`,
1061
- ` cxxSettings: [.unsafeFlags(["-fno-cxx-modules", "-I", ${JSON.stringify(native.includeDirectory)}, "-I", ${JSON.stringify(args.headerDirectory)}])]),`,
1062
- ]
1153
+ ...(args.objcExports
1154
+ ? [
1155
+ ` cSettings: [.unsafeFlags(${JSON.stringify([...args.objcExports.flags, ...group.flags])})],`,
1156
+ ]
1157
+ : []),
1158
+ ` cxxSettings: [.unsafeFlags(${JSON.stringify(['-fno-cxx-modules', '-I', native.includeDirectory, '-I', args.headerDirectory, ...group.cxxFlags])})]),`,
1159
+ ])
1063
1160
  : [],
1064
1161
  ),
1065
1162
  args.cxxLanguageStandard
@@ -2304,6 +2401,68 @@ const SDK_OBJC_OPTIONAL: Record<
2304
2401
  ][]
2305
2402
  }
2306
2403
  > = {
2404
+ UIAdaptivePresentationControllerDelegate: {
2405
+ mainActor: true,
2406
+ parents: [],
2407
+ requirements: [
2408
+ [
2409
+ 'presentationControllerShouldDismiss(_:)',
2410
+ 'presentationControllerShouldDismiss:',
2411
+ 'UIPresentationController->Bool',
2412
+ ],
2413
+ [
2414
+ 'presentationControllerWillDismiss(_:)',
2415
+ 'presentationControllerWillDismiss:',
2416
+ 'UIPresentationController->Void',
2417
+ ],
2418
+ [
2419
+ 'presentationControllerDidDismiss(_:)',
2420
+ 'presentationControllerDidDismiss:',
2421
+ 'UIPresentationController->Void',
2422
+ ],
2423
+ [
2424
+ 'presentationControllerDidAttemptToDismiss(_:)',
2425
+ 'presentationControllerDidAttemptToDismiss:',
2426
+ 'UIPresentationController->Void',
2427
+ ],
2428
+ [
2429
+ 'adaptivePresentationStyle(for:)',
2430
+ 'adaptivePresentationStyleForPresentationController:',
2431
+ 'UIPresentationController->UIModalPresentationStyle',
2432
+ ],
2433
+ [
2434
+ 'adaptivePresentationStyle(for:traitCollection:)',
2435
+ 'adaptivePresentationStyleForPresentationController:traitCollection:',
2436
+ 'UIPresentationController,UITraitCollection->UIModalPresentationStyle',
2437
+ ],
2438
+ [
2439
+ 'presentationController(_:willPresentWithAdaptiveStyle:transitionCoordinator:)',
2440
+ 'presentationController:willPresentWithAdaptiveStyle:transitionCoordinator:',
2441
+ 'UIPresentationController,UIModalPresentationStyle,(UIViewControllerTransitionCoordinator)?->Void',
2442
+ ],
2443
+ ],
2444
+ },
2445
+ UIPopoverPresentationControllerDelegate: {
2446
+ mainActor: true,
2447
+ parents: ['UIAdaptivePresentationControllerDelegate'],
2448
+ requirements: [
2449
+ [
2450
+ 'popoverPresentationControllerShouldDismissPopover(_:)',
2451
+ 'popoverPresentationControllerShouldDismissPopover:',
2452
+ 'UIPopoverPresentationController->Bool',
2453
+ ],
2454
+ [
2455
+ 'popoverPresentationControllerDidDismissPopover(_:)',
2456
+ 'popoverPresentationControllerDidDismissPopover:',
2457
+ 'UIPopoverPresentationController->Void',
2458
+ ],
2459
+ [
2460
+ 'prepareForPopoverPresentation(_:)',
2461
+ 'prepareForPopoverPresentation:',
2462
+ 'UIPopoverPresentationController->Void',
2463
+ ],
2464
+ ],
2465
+ },
2307
2466
  WKWebExtensionWindow: {
2308
2467
  callers: true,
2309
2468
  mainActor: true,
@@ -5511,6 +5670,87 @@ export function swiftApplicationEntry(file: string, source: string): boolean {
5511
5670
  return false
5512
5671
  }
5513
5672
 
5673
+ // swift's executable entry runs after the reactor's _initialize has completed.
5674
+ // global swift values remain lazy; native application initializers need separate
5675
+ // object evidence and are refused here rather than running the registry early.
5676
+ function installObjcPeerStartup(
5677
+ input: SwiftCompileInput,
5678
+ targets: SwiftPackageTarget[],
5679
+ compiled: Map<string, string>,
5680
+ ): void {
5681
+ const startup = input.objcPeerStartup
5682
+ if (!startup) return
5683
+ function fail(detail: string): never {
5684
+ throw new Error(`Objective-C peer startup: ${detail}`)
5685
+ }
5686
+ if (
5687
+ (input.nativeTargets?.length ?? 0) > 0 ||
5688
+ Object.keys(input.files).some((file) => /\.(?:c|cc|cpp|cxx|m|mm)$/.test(file))
5689
+ )
5690
+ fail('original native source targets require constructor provenance before admission')
5691
+ validateObjcPeerStartupLibraries(input.libraries ?? {})
5692
+ const executables = targets.filter((target) => target.executable)
5693
+ if (executables.length !== 1)
5694
+ fail('requires one executable application entry; library startup is unqualified')
5695
+ const target = executables[0]!
5696
+ const prefix = target.path === '.' ? '' : `${target.path}/`
5697
+ const belongs = (file: string): boolean =>
5698
+ file.startsWith(prefix) &&
5699
+ !targets.some(
5700
+ (other) =>
5701
+ other !== target &&
5702
+ other.path !== '.' &&
5703
+ other.path.startsWith(prefix) &&
5704
+ file.startsWith(`${other.path}/`),
5705
+ )
5706
+ if (
5707
+ !belongs(input.entry) ||
5708
+ !belongs(startup.registration) ||
5709
+ !compiled.has(startup.registration) ||
5710
+ startup.registration === input.entry
5711
+ )
5712
+ fail('generated registration and entry must belong to the same executable target')
5713
+ for (const [file, source] of compiled) {
5714
+ if (/@_(?:section|used)\b/.test(swiftCodeMask(source)))
5715
+ fail(`${file} contains unqualified pre-main Swift storage`)
5716
+ }
5717
+ const entries = [...compiled].filter(
5718
+ ([file, source]) => belongs(file) && /@main\b/.test(swiftCodeMask(source)),
5719
+ )
5720
+ if (entries.length === 0) {
5721
+ const source = compiled.get(input.entry)
5722
+ if (path.basename(input.entry) !== 'main.swift' || source === undefined)
5723
+ fail('requires main.swift or a supported @main App/UIApplicationDelegate entry')
5724
+ compiled.set(input.entry, `_peachRegisterObjcPeers()\n${source}`)
5725
+ return
5726
+ }
5727
+ if (entries.length !== 1 || entries[0]![0] !== input.entry)
5728
+ fail('requires the exact single @main application entry')
5729
+ const [file, source] = entries[0]!
5730
+ const code = swiftCodeMask(source)
5731
+ const attribute = /@main\b/.exec(code)!
5732
+ const nominal = /\b(?:struct|class|enum)\s+([A-Za-z_]\w*)[^{}]*\{/.exec(
5733
+ code.slice(attribute.index),
5734
+ )
5735
+ if (
5736
+ !nominal ||
5737
+ /\bstatic\s+func\s+main\s*\([^)]*\)[^{]*\b(?:async|throws|rethrows)\b/.test(code)
5738
+ )
5739
+ fail('generic, async or throwing application entries are unqualified')
5740
+ if (/\b(?:struct|class|enum)\s+\w+\s*</.test(nominal[0]))
5741
+ fail('generic application entries are unqualified')
5742
+ const generated = `${prefix}PeachObjCPeerStartup.generated.swift`
5743
+ if (compiled.has(generated)) fail('generated entry conflicts with application sources')
5744
+ compiled.set(
5745
+ file,
5746
+ source.slice(0, attribute.index) + ' ' + source.slice(attribute.index + 5),
5747
+ )
5748
+ compiled.set(
5749
+ generated,
5750
+ `@main struct __PeachObjCPeerStartupEntry {\n @MainActor static func main() {\n _peachRegisterObjcPeers()\n ${nominal[1]}.main()\n }\n}\n`,
5751
+ )
5752
+ }
5753
+
5514
5754
  // the offsets of the lines that begin in code, and of every `@`, `#`,
5515
5755
  // `class`, `extension` and `override` keyword that stands in code (an interpolation's code included), from a scan of Swift's
5516
5756
  // lexical contexts: nested block comments, line comments, string literals (single and
@@ -5685,7 +5925,14 @@ export function writeSwiftProject(
5685
5925
  layout: SwiftProjectLayout,
5686
5926
  input: SwiftCompileInput,
5687
5927
  moduleRoot: string,
5688
- ): void {
5928
+ ): SwiftProjectPreparation {
5929
+ if (
5930
+ input.objcPeerStartup !== undefined &&
5931
+ !isSwiftObjCPeerStartup(input.objcPeerStartup)
5932
+ )
5933
+ throw new Error('swift compile input has invalid Objective-C peer startup metadata')
5934
+ if (input.nativeTargets !== undefined && !isSwiftNativeTargets(input.nativeTargets))
5935
+ throw new Error('swift compile input has invalid original clang target inputs')
5689
5936
  if (
5690
5937
  input.resourceBundles !== undefined &&
5691
5938
  !isSwiftResourceBundles(input.resourceBundles)
@@ -5713,7 +5960,54 @@ export function writeSwiftProject(
5713
5960
  : compileTargets(input)
5714
5961
  const files = new Map<string, string | Buffer>()
5715
5962
  const native = new Map<string, SwiftNativeTargetPlan>()
5963
+ const bySourcePath = [...targets].sort(
5964
+ (left, right) => right.path.length - left.path.length,
5965
+ )
5966
+ const swiftTargets = new Set<string>()
5967
+ for (const file of Object.keys(input.files)) {
5968
+ if (!file.endsWith('.swift')) continue
5969
+ const target = bySourcePath.find(
5970
+ (candidate) => candidate.path === '.' || file.startsWith(`${candidate.path}/`),
5971
+ )
5972
+ if (target) swiftTargets.add(target.name)
5973
+ }
5716
5974
  const headerDirectory = path.join(layout.root, '.build', 'peach-cxx-headers')
5975
+ const headerModuleDirectory = path.join(
5976
+ layout.root,
5977
+ '.build',
5978
+ 'peach-objc-export-modules',
5979
+ )
5980
+ const imports = new Map<
5981
+ string,
5982
+ {
5983
+ view: ReturnType<typeof objcView>
5984
+ classes: string[]
5985
+ headers: string[]
5986
+ foreignTypes: Map<string, string>
5987
+ }
5988
+ >()
5989
+ // headers keep their original project paths. product headers additionally
5990
+ // occupy the same Module/Header.h namespace that xcode publishes.
5991
+ for (const settings of input.nativeTargets ?? []) {
5992
+ for (const file of settings.headers) {
5993
+ const contents = input.files[file]
5994
+ if (contents === undefined)
5995
+ throw new Error(`missing original Objective-C header ${file}`)
5996
+ const destination = path.join(layout.root, file)
5997
+ mkdirSync(path.dirname(destination), { recursive: true })
5998
+ writeFileSync(destination, contents)
5999
+ files.set(destination, contents)
6000
+ }
6001
+ for (const header of settings.publicHeaders) {
6002
+ const destination = path.join(headerDirectory, settings.name, path.basename(header))
6003
+ if (files.has(destination))
6004
+ throw new Error(`duplicate product header ${destination}`)
6005
+ const contents = `#import ${JSON.stringify(path.join(layout.root, header))}\n`
6006
+ files.set(destination, contents)
6007
+ mkdirSync(path.dirname(destination), { recursive: true })
6008
+ writeFileSync(destination, contents)
6009
+ }
6010
+ }
5717
6011
  // declarations are imported before swift can emit the header that native
5718
6012
  // implementations consume. give those implementations a downstream target.
5719
6013
  for (const target of targets) {
@@ -5729,9 +6023,232 @@ export function writeSwiftProject(
5729
6023
  file.startsWith(`${candidate.path}/`),
5730
6024
  ),
5731
6025
  )
5732
- if (entries.some(([file]) => file.endsWith('.swift'))) continue
5733
6026
  const units = entries.filter(([file]) => /\.(?:c|cc|cpp|cxx|m|mm)$/.test(file))
5734
6027
  if (units.length === 0) continue
6028
+ const settings = input.nativeTargets?.find((value) => value.name === target.name)
6029
+ if (
6030
+ entries.some(([file]) => file.endsWith('.swift')) ||
6031
+ (settings && units.some(([file]) => /\.mm?$/.test(file)))
6032
+ ) {
6033
+ if (!settings)
6034
+ throw new Error(
6035
+ `mixed target ${target.name} requires its original native target settings; SwiftPM does not compile mixed source targets`,
6036
+ )
6037
+ const headers = settings.headers
6038
+ const roots = settings.bridgingHeader
6039
+ ? [settings.bridgingHeader]
6040
+ : settings.publicHeaders
6041
+ if (!roots.length)
6042
+ throw new Error(`mixed target ${target.name} has no original declaration headers`)
6043
+ for (const file of headers) {
6044
+ const destination = path.join(layout.root, file)
6045
+ mkdirSync(path.dirname(destination), { recursive: true })
6046
+ writeFileSync(destination, input.files[file]!)
6047
+ }
6048
+ const search = [
6049
+ ...new Set([
6050
+ ...(settings?.headerSearchPaths ?? []),
6051
+ ...headers.map((file) => path.posix.dirname(file)),
6052
+ ]),
6053
+ ].flatMap((dir) => ['-I', path.join(layout.root, dir)])
6054
+ const pin: { release: string } =
6055
+ distribution ??
6056
+ JSON.parse(readFileSync(path.join(moduleRoot, 'toolchain.json'), 'utf8'))
6057
+ const release = pin.release
6058
+ const toolchainBin = swiftToolchain(release, swiftModuleSdk(moduleRoot))
6059
+ const sdkHeaders = materializeObjcSdk(
6060
+ path.join(layout.root, '.build', 'peach-objc-sdk'),
6061
+ )
6062
+ const stageFlags = (flags: readonly string[], sdkInclude: string) =>
6063
+ flags.map((flag) =>
6064
+ flag
6065
+ .replaceAll(SWIFT_NATIVE_INPUT_ROOT, layout.root)
6066
+ .replaceAll(SWIFT_NATIVE_SDK_INCLUDE, sdkInclude),
6067
+ )
6068
+ const originalFlags = [
6069
+ ...(settings?.flags ?? []),
6070
+ ...search,
6071
+ ...(settings?.frameworkSearchPaths ?? []).flatMap((dir) => [
6072
+ '-F',
6073
+ path.join(layout.root, dir),
6074
+ ]),
6075
+ '-I',
6076
+ headerDirectory,
6077
+ ]
6078
+ const flags = stageFlags(
6079
+ originalFlags,
6080
+ path.join(swiftSdkPaths(moduleRoot, toolchainBin).sysroot, 'include'),
6081
+ )
6082
+ const prefixHeader = settings?.prefixHeader
6083
+ ? ['-include', path.join(layout.root, settings.prefixHeader)]
6084
+ : []
6085
+ // swiftpm gives a native resource target's units an accessor header and
6086
+ // one more unit defining it. the swift accessor below stays for swift.
6087
+ const bundleName = entries.some(([file]) => file.endsWith('.swift'))
6088
+ ? undefined
6089
+ : swiftObjCResourceBundleName({
6090
+ target: target.name,
6091
+ path: target.path,
6092
+ resources:
6093
+ resourceTargets.find((candidate) => candidate.name === target.name)
6094
+ ?.resources ?? false,
6095
+ usesBundleMacro: entries.some(
6096
+ ([file, contents]) =>
6097
+ /\.(?:c|cc|cpp|cxx|m|mm|h|hpp|hh|hxx)$/.test(file) &&
6098
+ /\bSWIFTPM_MODULE_BUNDLE\b/.test(contents),
6099
+ ),
6100
+ bundles: input.resourceBundles,
6101
+ })
6102
+ const accessor =
6103
+ bundleName === undefined ? undefined : swiftObjCResourceAccessor(bundleName)
6104
+ const accessorHeader = path.join(
6105
+ layout.root,
6106
+ target.path,
6107
+ OBJC_RESOURCE_ACCESSOR_HEADER,
6108
+ )
6109
+ const accessorUnit = `${prefix}${OBJC_RESOURCE_ACCESSOR_BODY}`
6110
+ if (
6111
+ accessor &&
6112
+ (input.files[accessorUnit] !== undefined ||
6113
+ input.files[`${prefix}${OBJC_RESOURCE_ACCESSOR_HEADER}`] !== undefined)
6114
+ )
6115
+ throw new Error(`target ${target.name} already contains its resource accessor`)
6116
+ const nativeUnits: [string, string][] = accessor
6117
+ ? [...units, [accessorUnit, accessor.body]]
6118
+ : units
6119
+ const accessorFlags = accessor ? ['-include', accessorHeader] : []
6120
+ if (accessor) {
6121
+ files.set(accessorHeader, accessor.header)
6122
+ files.set(path.join(layout.root, accessorUnit), accessor.body)
6123
+ }
6124
+ const sourceHeaders = path.join(
6125
+ layout.root,
6126
+ '.build',
6127
+ 'peach-objc-originals',
6128
+ target.name,
6129
+ )
6130
+ mkdirSync(sourceHeaders, { recursive: true })
6131
+ const modulemap = path.join(sourceHeaders, 'module.modulemap')
6132
+ writeFileSync(
6133
+ modulemap,
6134
+ `module ${swiftTargetModuleName(target.name)} {\n${roots.map((file) => `header ${JSON.stringify(path.join(layout.root, file))}`).join('\n')}\nexport *\n}\n`,
6135
+ )
6136
+ const view = objcView(
6137
+ { module: swiftTargetModuleName(target.name), headers: sourceHeaders, modulemap },
6138
+ toolchainBin,
6139
+ path.join(moduleRoot, 'ios-simulator-stdlib'),
6140
+ path.join(layout.root, '.build', 'peach-objc-sdk'),
6141
+ path.join(layout.root, '.build', 'peach-objc-imports', target.name),
6142
+ {
6143
+ flags: stageFlags(originalFlags, path.join(sdkHeaders, 'usr/include')),
6144
+ target: `arm64-apple-ios${settings?.deploymentTarget ?? '16.0'}-simulator`,
6145
+ },
6146
+ )
6147
+ const defined = new Set<string>()
6148
+ const declarations = (node: unknown): void => {
6149
+ if (!node || typeof node !== 'object') return
6150
+ const name: unknown = Reflect.get(node, 'name')
6151
+ if (
6152
+ Reflect.get(node, 'kind') === 'ObjCInterfaceDecl' &&
6153
+ Reflect.get(node, 'super') &&
6154
+ typeof name === 'string'
6155
+ )
6156
+ defined.add(name)
6157
+ const children: unknown = Reflect.get(node, 'inner')
6158
+ if (Array.isArray(children)) for (const child of children) declarations(child)
6159
+ }
6160
+ declarations(view.clangAST)
6161
+ const foreignTypes = new Map<string, string>()
6162
+ for (const graph of view.graphs)
6163
+ for (const symbol of graph.symbols) {
6164
+ const nativeName = /^c:objc\(cs\)(\w+)$/.exec(symbol.identifier.precise)?.[1]
6165
+ if (nativeName && defined.has(nativeName))
6166
+ foreignTypes.set(symbol.pathComponents[0]!, nativeName)
6167
+ }
6168
+ imports.set(target.name, {
6169
+ view,
6170
+ classes: [...foreignTypes.values()],
6171
+ headers: roots.map((file) => path.join(layout.root, file)),
6172
+ foreignTypes,
6173
+ })
6174
+ const thunk = 'PeachObjCImports.generated.m'
6175
+ const groups = new Map<
6176
+ string,
6177
+ { name: string; sources: string[]; flags: string[]; cxxFlags: string[] }
6178
+ >()
6179
+ for (const [file] of nativeUnits) {
6180
+ const origin = settings?.sourceDirectories[file]
6181
+ if (origin) mkdirSync(path.join(layout.root, origin), { recursive: true })
6182
+ const perFile = [
6183
+ ...(origin ? ['-iquote', path.join(layout.root, origin)] : []),
6184
+ ...stageFlags(
6185
+ settings?.fileFlags[file] ?? [],
6186
+ path.join(swiftSdkPaths(moduleRoot, toolchainBin).sysroot, 'include'),
6187
+ ),
6188
+ ]
6189
+ const cxx = /\.(?:cc|cpp|cxx|mm)$/.test(file)
6190
+ const identity = createHash('sha256')
6191
+ .update(JSON.stringify([cxx, perFile]))
6192
+ .digest('hex')
6193
+ .slice(0, 12)
6194
+ const group = groups.get(identity) ?? {
6195
+ name: `${target.name}SwiftImplementation_${identity}`,
6196
+ sources: [],
6197
+ flags: [...flags, ...prefixHeader, ...accessorFlags, ...perFile],
6198
+ cxxFlags: [
6199
+ ...flags,
6200
+ ...prefixHeader,
6201
+ ...accessorFlags,
6202
+ ...stageFlags(
6203
+ cxx ? settings.cxxFlags : [],
6204
+ path.join(swiftSdkPaths(moduleRoot, toolchainBin).sysroot, 'include'),
6205
+ ),
6206
+ ...perFile,
6207
+ ],
6208
+ }
6209
+ group.sources.push(file.slice(prefix.length))
6210
+ groups.set(identity, group)
6211
+ }
6212
+ groups.set('imports', {
6213
+ name: `${target.name}ObjCImports`,
6214
+ sources: [thunk],
6215
+ flags: [...flags, '-fobjc-arc'],
6216
+ cxxFlags: [...flags, '-fobjc-arc'],
6217
+ })
6218
+ const include = path.join(layout.root, target.path, 'include')
6219
+ files.set(
6220
+ path.join(include, 'module.modulemap'),
6221
+ `module ${target.name}ImplementationDeclarations { export * }\n`,
6222
+ )
6223
+ native.set(target.name, {
6224
+ mixed: true,
6225
+ path: target.path,
6226
+ includeDirectory: include,
6227
+ sources: nativeUnits.map(([file]) => file.slice(prefix.length)),
6228
+ lateSources: [...nativeUnits.map(([file]) => file.slice(prefix.length)), thunk],
6229
+ exclude: [
6230
+ ...entries
6231
+ .filter(([file]) => !file.endsWith('.swift') && !file.endsWith('.metal'))
6232
+ .map(([file]) => file.slice(prefix.length)),
6233
+ ...(accessor
6234
+ ? [OBJC_RESOURCE_ACCESSOR_HEADER, OBJC_RESOURCE_ACCESSOR_BODY]
6235
+ : []),
6236
+ thunk,
6237
+ 'include',
6238
+ ],
6239
+ groups: [...groups.values()],
6240
+ late: {
6241
+ name: `${target.name}SwiftImplementation`,
6242
+ producers: [
6243
+ target.name,
6244
+ ...(target.dependencies ?? [])
6245
+ .filter((dependency) => swiftTargets.has(dependency.name))
6246
+ .map((dependency) => dependency.name),
6247
+ ],
6248
+ },
6249
+ })
6250
+ continue
6251
+ }
5735
6252
  const includes = `${prefix}include/`
5736
6253
  const consumers = new Map<string, Set<string>>()
5737
6254
  const reverse = new Map<string, string[]>()
@@ -5739,7 +6256,9 @@ export function writeSwiftProject(
5739
6256
  const producers = new Set<string>()
5740
6257
  // a block-commented include is not an edge.
5741
6258
  const source = contents.replace(/\/\*[\s\S]*?\*\//g, '')
5742
- for (const match of source.matchAll(/^\s*#\s*include\s*[<"]([^>"]+)[>"]/gm)) {
6259
+ for (const match of source.matchAll(
6260
+ /^\s*#\s*(?:include|import)\s*[<"]([^>"]+)[>"]/gm,
6261
+ )) {
5743
6262
  const include = match[1]!
5744
6263
  const producer = /(?:^|\/)([^/]+)-Swift\.h$/.exec(include)?.[1]
5745
6264
  if (producer && targets.some((value) => value.name === producer))
@@ -5768,6 +6287,7 @@ export function writeSwiftProject(
5768
6287
  native.set(target.name, {
5769
6288
  path: target.path,
5770
6289
  includeDirectory: path.join(layout.root, includes),
6290
+ sources: units.map(([file]) => file.slice(prefix.length)),
5771
6291
  lateSources: late.map(([file]) => file.slice(prefix.length)),
5772
6292
  ...(late.length > 0
5773
6293
  ? {
@@ -5841,6 +6361,247 @@ export function writeSwiftProject(
5841
6361
  ),
5842
6362
  targets,
5843
6363
  )
6364
+ installObjcPeerStartup(
6365
+ input,
6366
+ layout.multi ? targets : targets.map((target) => ({ ...target, path: '.' })),
6367
+ compiled,
6368
+ )
6369
+ // an application's swift module must precede its native implementations.
6370
+ // the tiny executable calls the original typed entry after both are linked.
6371
+ for (const target of [...targets]) {
6372
+ if (
6373
+ !target.executable ||
6374
+ ![...native.values()].some((value) => value.late?.producers.includes(target.name))
6375
+ )
6376
+ continue
6377
+ const prefix = target.path === '.' ? '' : `${target.path}/`
6378
+ const entries = [...compiled].filter(
6379
+ ([file]) =>
6380
+ file.startsWith(prefix) &&
6381
+ !targets.some(
6382
+ (candidate) =>
6383
+ candidate.name !== target.name &&
6384
+ candidate.path !== '.' &&
6385
+ candidate.path.startsWith(prefix) &&
6386
+ file.startsWith(`${candidate.path}/`),
6387
+ ),
6388
+ )
6389
+ const mains = entries.flatMap(([file, source]) => {
6390
+ const match = /@main\b[\s\S]*?\b(?:struct|class|enum)\s+([A-Za-z_]\w*)/.exec(
6391
+ swiftCodeMask(source),
6392
+ )
6393
+ return match ? [{ file, source, match }] : []
6394
+ })
6395
+ if (mains.length !== 1)
6396
+ throw new Error(
6397
+ `mixed executable ${target.name} requires one typed Swift application entry`,
6398
+ )
6399
+ const main = mains[0]!
6400
+ compiled.set(
6401
+ main.file,
6402
+ main.source.slice(0, main.match.index) +
6403
+ ' ' +
6404
+ main.source.slice(main.match.index + 5) +
6405
+ `\n@MainActor public func __peachRunApplication() { ${main.match[1]}.main() }\n`,
6406
+ )
6407
+ const name = `${target.name}Executable`
6408
+ if (targets.some((candidate) => candidate.name === name))
6409
+ throw new Error(`mixed application executable target conflicts with ${name}`)
6410
+ target.executable = false
6411
+ targets.push({
6412
+ ...target,
6413
+ name,
6414
+ path: `PeachApplication/${name}`,
6415
+ executable: true,
6416
+ resources: false,
6417
+ dependencies: [{ kind: 'target', name: target.name }],
6418
+ exclude: [],
6419
+ })
6420
+ files.set(
6421
+ path.join(layout.root, `PeachApplication/${name}/Entry.swift`),
6422
+ `import ${swiftTargetModuleName(target.name)}\n@main struct __PeachApplicationEntry { @MainActor static func main() { __peachRunApplication() } }\n`,
6423
+ )
6424
+ }
6425
+ // genuine objective-c consumers receive declarations and implementations from
6426
+ // one typed export plan. the swift compiler emits their C function prototypes.
6427
+ const objcProducers = new Set<string>()
6428
+ for (const name of imports.keys()) objcProducers.add(name)
6429
+ for (const [name, plan] of native) {
6430
+ if (!plan.late) continue
6431
+ if (plan.lateSources.some((file) => /\.mm?$/.test(file)))
6432
+ for (const producer of plan.late.producers) objcProducers.add(producer)
6433
+ }
6434
+ const objcModules = new Set<string>()
6435
+ const registrations: string[] = []
6436
+ const registeredClasses = new Set<string>(['NSObject'])
6437
+ let rootOwner: string | undefined
6438
+ for (const name of objcProducers) {
6439
+ const target = targets.find((value) => value.name === name)!
6440
+ const prefix = target.path === '.' ? '' : `${target.path}/`
6441
+ const exported = swiftObjCExports({
6442
+ module: swiftTargetModuleName(name),
6443
+ sources: Object.entries(input.files).filter(
6444
+ ([file]) =>
6445
+ file.startsWith(prefix) &&
6446
+ file.endsWith('.swift') &&
6447
+ !targets.some(
6448
+ (candidate) =>
6449
+ candidate.name !== name &&
6450
+ candidate.path !== '.' &&
6451
+ candidate.path.startsWith(prefix) &&
6452
+ file.startsWith(`${candidate.path}/`),
6453
+ ) &&
6454
+ !target.exclude?.some(
6455
+ (excluded) =>
6456
+ file.slice(prefix.length) === excluded ||
6457
+ file.slice(prefix.length).startsWith(`${excluded}/`),
6458
+ ),
6459
+ ),
6460
+ mask: swiftCodeMask,
6461
+ declarationStart,
6462
+ selector: objcSelectorName,
6463
+ foreignTypes: imports.get(name)?.foreignTypes,
6464
+ })
6465
+ const original = imports.get(name)
6466
+ if (!exported && !original) continue
6467
+ objcModules.add(name)
6468
+ rootOwner ??= exported
6469
+ ? [...exported.swift.keys()][0]
6470
+ : `${prefix}PeachObjCImports.generated.swift`
6471
+ files.set(
6472
+ path.join(headerDirectory, `${name}-Swift.h`),
6473
+ exported?.header ?? '#pragma once\n',
6474
+ )
6475
+ files.set(
6476
+ path.join(headerDirectory, name, `${name}-Swift.h`),
6477
+ `#include "../${name}-Swift.h"\n`,
6478
+ )
6479
+ files.set(
6480
+ path.join(headerModuleDirectory, name, 'module.modulemap'),
6481
+ `module ${swiftTargetModuleName(name)} {\n${[
6482
+ path.join(headerDirectory, `${name}-Swift.h`),
6483
+ ...(
6484
+ input.nativeTargets?.find((target) => target.name === name)?.publicHeaders ?? []
6485
+ ).map((header) => path.join(layout.root, header)),
6486
+ ]
6487
+ .map((header) => ` header ${JSON.stringify(header)}`)
6488
+ .join('\n')}\n export *\n}\n`,
6489
+ )
6490
+ files.set(
6491
+ path.join(layout.root, 'PeachObjCExports', `${name}.m`),
6492
+ exported?.implementation ?? `#include "${name}-Cxx.h"\n`,
6493
+ )
6494
+ if (exported) registrations.push(exported.registration)
6495
+ for (const type of exported?.types.values() ?? []) registeredClasses.add(type)
6496
+ for (const type of original?.classes ?? []) registeredClasses.add(type)
6497
+ for (const [file, text] of exported?.swift ?? [])
6498
+ compiled.set(file, compiled.get(file)! + text)
6499
+ if (original) {
6500
+ const generated = swiftObjCImports(original.view.graphs, {
6501
+ module: swiftTargetModuleName(name),
6502
+ headers: original.headers,
6503
+ classes: original.classes,
6504
+ clangAST: original.view.clangAST,
6505
+ peerTypes: exported?.types,
6506
+ })
6507
+ const register = `_peach_objc_imports_${swiftTargetModuleName(name)}`
6508
+ files.set(
6509
+ path.join(layout.root, target.path, 'PeachObjCImports.generated.swift'),
6510
+ generated.swift +
6511
+ generated.registration +
6512
+ `\n@_cdecl("${register}") public func __peachRegisterOriginalObjC() { ${generated.registerFunction}() }\n`,
6513
+ )
6514
+ files.set(
6515
+ path.join(layout.root, target.path, 'PeachObjCImports.generated.m'),
6516
+ generated.objc,
6517
+ )
6518
+ registrations.push(`${register}();`)
6519
+ }
6520
+ }
6521
+ let objcExports: { modules: Set<string>; flags: string[] } | undefined
6522
+ if (rootOwner && input.objcPeerStartup)
6523
+ throw new Error(
6524
+ 'Objective-C peer startup: joining framework metadata with source exports requires one qualified root registration',
6525
+ )
6526
+ if (rootOwner) {
6527
+ if (
6528
+ targets.some((target) => target.name === 'PeachSwiftObjCExports') ||
6529
+ Object.keys(input.files).some((file) => file.startsWith('PeachObjCExports/'))
6530
+ )
6531
+ throw new Error(
6532
+ 'Swift Objective-C export target conflicts with application sources',
6533
+ )
6534
+ const ownerFile = path.join(layout.root, rootOwner)
6535
+ const ownerSource = compiled.get(rootOwner) ?? files.get(ownerFile)
6536
+ if (typeof ownerSource !== 'string')
6537
+ throw new Error('Objective-C root registration has no owning Swift source')
6538
+ files.set(
6539
+ ownerFile,
6540
+ ownerSource +
6541
+ `
6542
+ @_extern(c, "_peach_objc_register_all_exports") private func __peachRegisterAllExports()
6543
+ private let __peachExportRegistration: Void = { __peachRegisterAllExports() }()
6544
+ @_cdecl("_peach_objc_ensure_exports")
6545
+ public func __peachEnsureExportRegistration() { _ = __peachExportRegistration }
6546
+ @_cdecl("_peach_objc_export_root")
6547
+ public func __peachObjcExportRoot() { _objcRegisterPeerClass(NSObject.self, nativeName: "NSObject") }
6548
+ `,
6549
+ )
6550
+ if (compiled.has(rootOwner)) compiled.set(rootOwner, files.get(ownerFile)!.toString())
6551
+ files.set(
6552
+ path.join(layout.root, 'PeachObjCExports', 'include', 'module.modulemap'),
6553
+ 'module PeachSwiftObjCExports { export * }\n',
6554
+ )
6555
+ files.set(
6556
+ path.join(layout.root, 'PeachObjCExports', 'root.m'),
6557
+ [
6558
+ '#import <Foundation/Foundation.h>',
6559
+ 'extern void _peach_objc_ensure_exports(void);',
6560
+ 'extern void *_peach_objc_allocate_foreign(void *);',
6561
+ '@implementation NSObject',
6562
+ '+ (void)initialize { _peach_objc_ensure_exports(); }',
6563
+ '+ (instancetype)alloc { return (__bridge id)_peach_objc_allocate_foreign((__bridge void *)self); }',
6564
+ '+ (instancetype)new { return [[self alloc] init]; }',
6565
+ '- (instancetype)init { return self; }',
6566
+ '@end',
6567
+ 'extern void _peach_objc_export_root(void);',
6568
+ ...registrations.flatMap((text) =>
6569
+ [...text.matchAll(/(\w+)\(\);/g)].map(
6570
+ (match) => `extern void ${match[1]}(void);`,
6571
+ ),
6572
+ ),
6573
+ 'extern void _peach_objc_register_private_implementations(void);',
6574
+ 'void _peach_objc_register_all_exports(void) {',
6575
+ '_peach_objc_export_root();',
6576
+ ...registrations,
6577
+ '_peach_objc_register_private_implementations();',
6578
+ '}',
6579
+ '',
6580
+ ].join('\n'),
6581
+ )
6582
+ const headers = materializeObjcSdk(path.join(layout.root, '.build', 'peach-objc-sdk'))
6583
+ objcExports = {
6584
+ modules: objcModules,
6585
+ flags: [
6586
+ '-fobjc-runtime=gnustep-2.2',
6587
+ '-fobjc-exceptions',
6588
+ '-fexceptions',
6589
+ '-fwasm-exceptions',
6590
+ '-fobjc-arc',
6591
+ '-fblocks',
6592
+ '-F',
6593
+ path.join(headers, 'System/Library/Frameworks'),
6594
+ '-idirafter',
6595
+ path.join(headers, 'usr/include'),
6596
+ '-I',
6597
+ headerDirectory,
6598
+ ...[...objcModules].map(
6599
+ (name) =>
6600
+ `-fmodule-map-file=${path.join(headerModuleDirectory, name, 'module.modulemap')}`,
6601
+ ),
6602
+ ],
6603
+ }
6604
+ }
5844
6605
  if (targets.length === 0) {
5845
6606
  for (const [file, contents] of Object.entries(input.files)) {
5846
6607
  if (file === 'Package.swift') continue
@@ -5912,6 +6673,7 @@ export function writeSwiftProject(
5912
6673
  emitSwiftPackageManifest({
5913
6674
  targets,
5914
6675
  native,
6676
+ objcExports,
5915
6677
  headerDirectory: native.size > 0 ? headerDirectory : undefined,
5916
6678
  cxxLanguageStandard: swiftManifestCxxLanguageStandard(
5917
6679
  input.files['Package.swift'] ?? '',
@@ -5957,7 +6719,42 @@ export function writeSwiftProject(
5957
6719
  ].join('\n'),
5958
6720
  )
5959
6721
  }
6722
+ for (const [file, source] of compiled)
6723
+ if (!Object.hasOwn(input.files, file))
6724
+ files.set(path.join(layout.multi ? layout.root : layout.sources, file), source)
5960
6725
  syncSwiftTree(layout.root, files)
6726
+ const producers = [
6727
+ ...new Set([
6728
+ ...objcProducers,
6729
+ ...[...native.values()].flatMap((value) => value.late?.producers ?? []),
6730
+ ]),
6731
+ ]
6732
+ const dependencies = swiftTargetDependencies(input.files, targets)
6733
+ const included = new Set<string>()
6734
+ const include = (name: string): void => {
6735
+ if (included.has(name)) return
6736
+ included.add(name)
6737
+ for (const dependency of dependencies.get(name) ?? []) include(dependency)
6738
+ }
6739
+ for (const producer of producers)
6740
+ for (const dependency of dependencies.get(producer) ?? []) include(dependency)
6741
+ // building a producer also emits its dependency producers' headers.
6742
+ return {
6743
+ headerProducers: producers.filter((name) => !included.has(name)),
6744
+ ...(rootOwner && objcExports
6745
+ ? {
6746
+ objcImplementations: {
6747
+ owner: path.join(layout.root, rootOwner),
6748
+ registeredClasses: [...registeredClasses],
6749
+ units: [...native.values()].flatMap((value) =>
6750
+ value.sources
6751
+ .filter((file) => /\.mm?$/.test(file))
6752
+ .map((file) => path.join(layout.root, value.path, file)),
6753
+ ),
6754
+ },
6755
+ }
6756
+ : {}),
6757
+ }
5961
6758
  }
5962
6759
 
5963
6760
  function streamText(value: unknown): string {
@@ -6242,7 +7039,7 @@ export function compileSwiftProjectUnit(
6242
7039
  // using it, so one process writes, builds and reads them at a time.
6243
7040
  return withSwiftRootLock(
6244
7041
  root,
6245
- async () => {
7042
+ async (lease) => {
6246
7043
  // a process that held the root while this one waited may have built
6247
7044
  // this exact address.
6248
7045
  const built = readCompiledArtifact(path.join(sharedRoot, 'artifact'), hash)
@@ -6250,7 +7047,7 @@ export function compileSwiftProjectUnit(
6250
7047
  report('reusing verified disk artifact')
6251
7048
  return retain(root, built)
6252
7049
  }
6253
- writeSwiftProject(layout, input, moduleRoot)
7050
+ const preparation = writeSwiftProject(layout, input, moduleRoot)
6254
7051
  const swift = path.join(options.toolchainBin, 'swift')
6255
7052
  if (!existsSync(swift)) {
6256
7053
  throw new Error(
@@ -6314,9 +7111,91 @@ export function compileSwiftProjectUnit(
6314
7111
  maxBuffer: 64 * 1024 * 1024,
6315
7112
  timeout: options.timeoutMs,
6316
7113
  signal: options.signal,
7114
+ lease,
6317
7115
  }
6318
7116
  report('compiling and linking Swift modules')
6319
7117
  try {
7118
+ // clang consumes the real emitted headers after swift finishes.
7119
+ // swiftpm's transitive swift module maps are not C declarations:
7120
+ // importing them would shadow SDK modules such as ObjectiveC.
7121
+ for (const producer of preparation.headerProducers) {
7122
+ await runCompiler(
7123
+ swift,
7124
+ [...buildArgs, '--target', producer],
7125
+ buildOptions,
7126
+ SWIFTPM_PROGRESS,
7127
+ SWIFTPM_NOISE,
7128
+ )
7129
+ }
7130
+ if (preparation.objcImplementations) {
7131
+ const plan = preparation.objcImplementations
7132
+ // the producer build writes the complete native build graph. use
7133
+ // its exact per-unit clang argv, including swiftpm's settings.
7134
+ const manifest: unknown = yaml.parse(
7135
+ readFileSync(path.join(root, '.build', 'release.yaml'), 'utf8'),
7136
+ )
7137
+ if (!isRecord(manifest) || !isRecord(manifest.commands))
7138
+ throw new Error('missing SwiftPM native compiler commands')
7139
+ const commands = new Map<string, string[]>()
7140
+ const selected = new Set(plan.units)
7141
+ for (const command of Object.values(manifest.commands)) {
7142
+ if (
7143
+ !isRecord(command) ||
7144
+ command.tool !== 'clang' ||
7145
+ !Array.isArray(command.inputs)
7146
+ )
7147
+ continue
7148
+ for (const file of command.inputs) {
7149
+ if (typeof file !== 'string' || !selected.has(file)) continue
7150
+ if (
7151
+ commands.has(file) ||
7152
+ !Array.isArray(command.args) ||
7153
+ !command.args.length ||
7154
+ !command.args.every((arg: unknown) => typeof arg === 'string')
7155
+ )
7156
+ throw new Error(`invalid SwiftPM compiler command for ${file}`)
7157
+ commands.set(file, command.args)
7158
+ }
7159
+ }
7160
+ async function* implementationASTs(): AsyncGenerator<string> {
7161
+ for (const file of plan.units) {
7162
+ const command = commands.get(file)
7163
+ if (!command)
7164
+ throw new Error(`missing SwiftPM compiler command for ${file}`)
7165
+ // change only the action and its output side effects. language,
7166
+ // SDK, defines, includes and original source identity stay exact.
7167
+ const args: string[] = []
7168
+ for (let index = 1; index < command.length; index++) {
7169
+ const arg = command[index]!
7170
+ if (
7171
+ ['-o', '-MF', '-MT', '-MQ', '-serialize-diagnostics'].includes(arg)
7172
+ )
7173
+ index++
7174
+ else if (!['-c', '-MD', '-MMD'].includes(arg)) args.push(arg)
7175
+ }
7176
+ try {
7177
+ yield await runCompiler(
7178
+ command[0]!,
7179
+ [...args, '-fsyntax-only', '-Xclang', '-ast-dump'],
7180
+ { ...buildOptions, cwd: root, maxBuffer: 256 * 1024 * 1024 },
7181
+ )
7182
+ } catch (error) {
7183
+ const diagnostic =
7184
+ error && typeof error === 'object'
7185
+ ? streamText(Reflect.get(error, 'stderr'))
7186
+ : ''
7187
+ throw new Error(
7188
+ `original Objective-C implementation AST failed for ${file}: ${diagnostic || String(error)}`,
7189
+ )
7190
+ }
7191
+ }
7192
+ }
7193
+ const adapter = await swiftObjCPrivateImports(
7194
+ implementationASTs(),
7195
+ plan.registeredClasses,
7196
+ )
7197
+ writeFileSync(plan.owner, readFileSync(plan.owner, 'utf8') + adapter)
7198
+ }
6320
7199
  await runCompiler(
6321
7200
  swift,
6322
7201
  buildArgs,