peachsim 0.1.1644 → 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 (608) hide show
  1. package/README.md +12 -0
  2. package/cli/app-catalog.ts +1 -1
  3. package/cli/app-fonts.ts +11 -80
  4. package/cli/app-splash.ts +18 -12
  5. package/cli/bridge-flow-runner.ts +11 -7
  6. package/cli/cloud-client.ts +10 -13
  7. package/cli/command-registry.ts +13 -4
  8. package/cli/commands/box.ts +4 -4
  9. package/cli/commands/control.ts +93 -53
  10. package/cli/commands/coverage-parser.ts +67 -0
  11. package/cli/commands/coverage.ts +550 -0
  12. package/cli/commands/debug.ts +9 -18
  13. package/cli/commands/desktop.ts +19 -7
  14. package/cli/commands/device.ts +14 -9
  15. package/cli/commands/guest-host.ts +6 -10
  16. package/cli/commands/inspect/core.ts +81 -17
  17. package/cli/commands/inspect.ts +13 -8
  18. package/cli/commands/kotlin.ts +2 -2
  19. package/cli/commands/maestro-compare.ts +1 -1
  20. package/cli/commands/platform.ts +20 -11
  21. package/cli/commands/preview.ts +16 -18
  22. package/cli/commands/runtime.ts +3 -2
  23. package/cli/commands/screenshot-layers.ts +1 -1
  24. package/cli/commands/screenshot.ts +1 -1
  25. package/cli/commands/serve.ts +5 -1
  26. package/cli/commands/support.ts +4 -4
  27. package/cli/commands/three-mode.ts +22 -15
  28. package/cli/commands/upload.ts +44 -45
  29. package/cli/current-sim.ts +38 -0
  30. package/cli/desktop-companion.ts +36 -8
  31. package/cli/device-option.ts +1 -1
  32. package/cli/drivers/playwright.ts +1 -0
  33. package/cli/drivers/types.ts +4 -0
  34. package/cli/help-core.ts +1 -1
  35. package/cli/internal-child.ts +2 -1
  36. package/cli/main.ts +9 -3
  37. package/cli/outbound-endpoints.ts +11 -3
  38. package/cli/output-redaction.ts +39 -14
  39. package/cli/remote-simulators.ts +4 -1
  40. package/cli/scene-video.ts +5 -2
  41. package/cli/send-to-box.ts +7 -10
  42. package/cli/telemetry.ts +1 -1
  43. package/cli/ws-bridge.ts +8 -1
  44. package/detox/attempt-events.cjs +3 -1
  45. package/detox/attempt-events.d.cts +1 -1
  46. package/detox/expectations.ts +108 -99
  47. package/detox/frame-offset.d.mts +6 -0
  48. package/detox/frame-offset.mjs +35 -0
  49. package/detox/gestures.ts +6 -18
  50. package/detox/index.ts +169 -101
  51. package/detox/jest-preset.cjs +1 -3
  52. package/detox/jest-transform.cjs +4 -0
  53. package/detox/matchers.ts +3 -0
  54. package/detox/motion-change.cjs +46 -114
  55. package/detox/motion-change.d.cts +5 -27
  56. package/dist-lib/agent-daemon-client.cjs +1 -1
  57. package/dist-lib/agent-events.cjs +1 -1
  58. package/dist-lib/attached-projects.cjs +1 -1
  59. package/dist-lib/auth/shared-session.cjs +1 -1
  60. package/dist-lib/backend-origin.cjs +1 -1
  61. package/dist-lib/beta.cjs +1 -1
  62. package/dist-lib/beta.mjs +1 -1
  63. package/dist-lib/bridge-constants.cjs +1 -1
  64. package/dist-lib/bridge-contract-input.cjs +65 -1
  65. package/dist-lib/bridge-contract-input.mjs +63 -1
  66. package/dist-lib/bridge-contract.cjs +19 -1
  67. package/dist-lib/bridge-contract.mjs +17 -1
  68. package/dist-lib/bundle-channel.cjs +38091 -14846
  69. package/dist-lib/capture-contract.cjs +1 -1
  70. package/dist-lib/capture-contract.mjs +1 -1
  71. package/dist-lib/cloud-contract.cjs +1 -1
  72. package/dist-lib/cloud-contract.mjs +1 -1
  73. package/dist-lib/cloud-test-args.cjs +1 -1
  74. package/dist-lib/cloud-test-args.mjs +1 -1
  75. package/dist-lib/cloud.cjs +1 -1
  76. package/dist-lib/cloud.mjs +1 -1
  77. package/dist-lib/config.cjs +1 -1
  78. package/dist-lib/config.mjs +5 -3
  79. package/dist-lib/detox/index.cjs +1244 -4509
  80. package/dist-lib/detox/jest-preset.cjs +1 -3
  81. package/dist-lib/detox/jest-transform.cjs +4 -0
  82. package/dist-lib/dev-bundle-resolution.cjs +28 -24
  83. package/dist-lib/expo-swift-bundle.cjs +35049 -13125
  84. package/dist-lib/expo-swift-metadata.cjs +1 -1
  85. package/dist-lib/expo-swift-metadata.mjs +1 -1
  86. package/dist-lib/home-paths.cjs +1 -1
  87. package/dist-lib/host/bridge-host.cjs +45112 -63143
  88. package/dist-lib/host/fetch-proxy-handler.cjs +3544 -11
  89. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  90. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  91. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  92. package/dist-lib/host/websocket-proxy.cjs +1 -1
  93. package/dist-lib/index.cjs +1909 -2029
  94. package/dist-lib/jump-to-source-babel.cjs +1 -1
  95. package/dist-lib/jump-to-source-native.cjs +1 -1
  96. package/dist-lib/kotlin-host.cjs +2 -2
  97. package/dist-lib/menu.cjs +1 -1
  98. package/dist-lib/menu.mjs +1 -1
  99. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  100. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  101. package/dist-lib/metro-production-bundle.cjs +1 -1
  102. package/dist-lib/metro-production-bundle.mjs +1 -1
  103. package/dist-lib/metro.cjs +380 -522
  104. package/dist-lib/native-app-identity-project.cjs +39 -252
  105. package/dist-lib/native-app-identity-project.mjs +1174 -11
  106. package/dist-lib/native-app-identity.cjs +8 -3
  107. package/dist-lib/native-app-identity.mjs +8 -3
  108. package/dist-lib/native-firebase-metadata.cjs +1 -1
  109. package/dist-lib/native-firebase-metadata.mjs +1 -1
  110. package/dist-lib/plist.cjs +2 -244
  111. package/dist-lib/plist.mjs +1 -1
  112. package/dist-lib/profiles.cjs +1 -1
  113. package/dist-lib/public-brand.cjs +1 -1
  114. package/dist-lib/public-origins-lib-esm.json +290 -0
  115. package/dist-lib/public-origins-lib-static.json +1 -0
  116. package/dist-lib/public-origins-lib.json +1852 -0
  117. package/dist-lib/react-native-host-modules.cjs +1 -1
  118. package/dist-lib/react-native-host-modules.mjs +1 -1
  119. package/dist-lib/scripts/dev-server-scanner.cjs +14 -253
  120. package/dist-lib/sdk.cjs +83 -16
  121. package/dist-lib/sdk.mjs +81 -15
  122. package/dist-lib/skills.cjs +50546 -75098
  123. package/dist-lib/swift-compile.cjs +25897 -1070
  124. package/dist-lib/swift-compile.mjs +25866 -1033
  125. package/dist-lib/swift-package.cjs +79 -1
  126. package/dist-lib/swift-package.mjs +75 -1
  127. package/dist-lib/swift-submit.cjs +1 -1
  128. package/dist-lib/swift-submit.mjs +1 -1
  129. package/dist-lib/swift-toolchain.cjs +1 -1
  130. package/dist-lib/swift.cjs +1 -1
  131. package/dist-lib/vite-swift.cjs +34273 -12349
  132. package/dist-lib/vite.cjs +373 -298
  133. package/dist-lib/worklet-executable.cjs +1 -1
  134. package/dist-lib/worklet-executable.mjs +1 -1
  135. package/dist-types/packages/peach-compat/src/engine-config.d.ts +2 -0
  136. package/dist-types/packages/peach-compat/src/stubs/form-sheet-spring.d.ts +9 -0
  137. package/dist-types/packages/peach-compat/src/stubs/native-evaluation-lease.d.ts +47 -0
  138. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-cookies.d.ts +113 -0
  139. package/dist-types/packages/peach-compat/src/stubs/native-seams/react-native-gesture-handler.d.ts +154 -0
  140. package/dist-types/packages/peach-compat/src/stubs/screen-transition-math.d.ts +756 -0
  141. package/dist-types/packages/peach-compat/src/stubs/transition-scalar.d.ts +25 -0
  142. package/dist-types/packages/peach-engine/src/billing/plans.d.ts +64 -0
  143. package/dist-types/packages/peach-engine/src/browser-page-target.d.ts +2 -0
  144. package/dist-types/packages/peach-engine/src/bundle-platform-url.d.ts +3 -0
  145. package/dist-types/packages/peach-engine/src/capture/browser-accessibility-host.d.ts +3 -0
  146. package/dist-types/packages/peach-engine/src/capture/browser-composite.d.ts +55 -0
  147. package/dist-types/packages/peach-engine/src/capture/browserAccessibilityContract.d.ts +27 -0
  148. package/dist-types/packages/peach-engine/src/capture/nativeScreenCaptureContract.d.ts +22 -0
  149. package/dist-types/packages/peach-engine/src/cli-companion.d.ts +36 -0
  150. package/dist-types/packages/peach-engine/src/components/native-ui/webview-frame-bridge.d.ts +34 -0
  151. package/dist-types/packages/peach-engine/src/config.d.ts +5 -0
  152. package/dist-types/packages/peach-engine/src/engine/android-stretch-effect.d.ts +57 -0
  153. package/dist-types/packages/peach-engine/src/engine/animated-driven-style.d.ts +47 -0
  154. package/dist-types/packages/peach-engine/src/engine/animated-value.d.ts +5 -0
  155. package/dist-types/packages/peach-engine/src/engine/animated.d.ts +195 -0
  156. package/dist-types/packages/peach-engine/src/engine/animation-clockContract.d.ts +15 -0
  157. package/dist-types/packages/peach-engine/src/engine/animation-graph.d.ts +148 -0
  158. package/dist-types/packages/peach-engine/src/engine/app-catalog-wire.d.ts +10 -0
  159. package/dist-types/packages/peach-engine/src/engine/app-font-registry.d.ts +87 -0
  160. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph-paint.d.ts +7 -0
  161. package/dist-types/packages/peach-engine/src/engine/attributed-paragraph.d.ts +123 -0
  162. package/dist-types/packages/peach-engine/src/engine/audioContract.d.ts +16 -0
  163. package/dist-types/packages/peach-engine/src/engine/canvaskit-api.d.ts +93 -0
  164. package/dist-types/packages/peach-engine/src/engine/canvaskit-renderer.d.ts +216 -0
  165. package/dist-types/packages/peach-engine/src/engine/config-plugin-fonts.d.ts +40 -0
  166. package/dist-types/packages/peach-engine/src/engine/config-plugin-splash.d.ts +25 -0
  167. package/dist-types/packages/peach-engine/src/engine/cull-visibility.d.ts +44 -0
  168. package/dist-types/packages/peach-engine/src/engine/damage-rect.d.ts +19 -0
  169. package/dist-types/packages/peach-engine/src/engine/engine-resource.d.ts +6 -0
  170. package/dist-types/packages/peach-engine/src/engine/expo-manifest.d.ts +5 -0
  171. package/dist-types/packages/peach-engine/src/engine/fiber-debug-metadata.d.ts +30 -0
  172. package/dist-types/packages/peach-engine/src/engine/font-config.d.ts +139 -0
  173. package/dist-types/packages/peach-engine/src/engine/generated/sf-pro-font.d.ts +1 -0
  174. package/dist-types/packages/peach-engine/src/engine/glass-material.d.ts +31 -0
  175. package/dist-types/packages/peach-engine/src/engine/host-composite.d.ts +100 -0
  176. package/dist-types/packages/peach-engine/src/engine/hosted-semantics.d.ts +49 -0
  177. package/dist-types/packages/peach-engine/src/engine/image-audit.d.ts +70 -0
  178. package/dist-types/packages/peach-engine/src/engine/image-loader.d.ts +350 -0
  179. package/dist-types/packages/peach-engine/src/engine/inspect-info.d.ts +27 -0
  180. package/dist-types/packages/peach-engine/src/engine/inspect-outline.d.ts +14 -0
  181. package/dist-types/packages/peach-engine/src/engine/inspect-visibility.d.ts +33 -0
  182. package/dist-types/packages/peach-engine/src/engine/ios-fast-scroll.d.ts +16 -0
  183. package/dist-types/packages/peach-engine/src/engine/layout-sab.d.ts +43 -0
  184. package/dist-types/packages/peach-engine/src/engine/liquid-glass-rect.d.ts +23 -0
  185. package/dist-types/packages/peach-engine/src/engine/liquid-glass-shaders.d.ts +9 -0
  186. package/dist-types/packages/peach-engine/src/engine/liquid-glass.d.ts +283 -0
  187. package/dist-types/packages/peach-engine/src/engine/live-object-counts.d.ts +6 -0
  188. package/dist-types/packages/peach-engine/src/engine/lottie-runtime.d.ts +32 -0
  189. package/dist-types/packages/peach-engine/src/engine/lottie-types.d.ts +138 -0
  190. package/dist-types/packages/peach-engine/src/engine/memory-counts.d.ts +27 -0
  191. package/dist-types/packages/peach-engine/src/engine/metalDirectContract.d.ts +108 -0
  192. package/dist-types/packages/peach-engine/src/engine/metalShaderContract.d.ts +217 -0
  193. package/dist-types/packages/peach-engine/src/engine/native-animation-driver.d.ts +112 -0
  194. package/dist-types/packages/peach-engine/src/engine/native-animation-graph.d.ts +62 -0
  195. package/dist-types/packages/peach-engine/src/engine/native-layout.d.ts +133 -0
  196. package/dist-types/packages/peach-engine/src/engine/native-resources.d.ts +26 -0
  197. package/dist-types/packages/peach-engine/src/engine/nativeReanimatedContract.d.ts +25 -0
  198. package/dist-types/packages/peach-engine/src/engine/nativeReplayContract.d.ts +64 -0
  199. package/dist-types/packages/peach-engine/src/engine/node.d.ts +589 -0
  200. package/dist-types/packages/peach-engine/src/engine/paint-boundary-types.d.ts +112 -0
  201. package/dist-types/packages/peach-engine/src/engine/paint-boundary.d.ts +57 -0
  202. package/dist-types/packages/peach-engine/src/engine/portalContract.d.ts +21 -0
  203. package/dist-types/packages/peach-engine/src/engine/portals.d.ts +20 -0
  204. package/dist-types/packages/peach-engine/src/engine/render-damage.d.ts +107 -0
  205. package/dist-types/packages/peach-engine/src/engine/riveContract.d.ts +420 -0
  206. package/dist-types/packages/peach-engine/src/engine/rn-spring.d.ts +51 -0
  207. package/dist-types/packages/peach-engine/src/engine/scene-table.d.ts +379 -0
  208. package/dist-types/packages/peach-engine/src/engine/scroll-momentum-math.d.ts +152 -0
  209. package/dist-types/packages/peach-engine/src/engine/scroll-pan-contacts.d.ts +10 -0
  210. package/dist-types/packages/peach-engine/src/engine/scroll-platform.d.ts +75 -0
  211. package/dist-types/packages/peach-engine/src/engine/scroll-range.d.ts +14 -0
  212. package/dist-types/packages/peach-engine/src/engine/scroll-velocity.d.ts +14 -0
  213. package/dist-types/packages/peach-engine/src/engine/scroll.d.ts +320 -0
  214. package/dist-types/packages/peach-engine/src/engine/signal.d.ts +7 -0
  215. package/dist-types/packages/peach-engine/src/engine/snapshot-cache-policy.d.ts +6 -0
  216. package/dist-types/packages/peach-engine/src/engine/svg-geometry.d.ts +41 -0
  217. package/dist-types/packages/peach-engine/src/engine/text-attachment-paragraphs.d.ts +10 -0
  218. package/dist-types/packages/peach-engine/src/engine/text-decoration.d.ts +11 -0
  219. package/dist-types/packages/peach-engine/src/engine/text-line-break.d.ts +22 -0
  220. package/dist-types/packages/peach-engine/src/engine/text-paint-receipt.d.ts +98 -0
  221. package/dist-types/packages/peach-engine/src/engine/text-paragraph.d.ts +11 -0
  222. package/dist-types/packages/peach-engine/src/engine/text-paragraphContract.d.ts +34 -0
  223. package/dist-types/packages/peach-engine/src/engine/text-transform.d.ts +1 -0
  224. package/dist-types/packages/peach-engine/src/engine/types.d.ts +657 -0
  225. package/dist-types/packages/peach-engine/src/engine/visible-frame.d.ts +54 -0
  226. package/dist-types/packages/peach-engine/src/engine/webrtcContract.d.ts +74 -0
  227. package/dist-types/packages/peach-engine/src/graphite-stats-fields.d.ts +184 -0
  228. package/dist-types/packages/peach-engine/src/guest-import-meta.d.ts +12 -0
  229. package/dist-types/packages/peach-engine/src/guest-module-overrides.d.ts +7 -0
  230. package/dist-types/packages/peach-engine/src/ios/app-card-types.d.ts +7 -0
  231. package/dist-types/packages/peach-engine/src/ios/apps/canvas-map-data.d.ts +177 -0
  232. package/dist-types/packages/peach-engine/src/ios/aux-home-scene.d.ts +54 -0
  233. package/dist-types/packages/peach-engine/src/ios/chrome-metrics.d.ts +47 -0
  234. package/dist-types/packages/peach-engine/src/ios/constants.d.ts +21 -0
  235. package/dist-types/packages/peach-engine/src/ios/duo-housing.d.ts +37 -0
  236. package/dist-types/packages/peach-engine/src/ios/home/types.d.ts +29 -0
  237. package/dist-types/packages/peach-engine/src/ios/home-app-catalog.d.ts +43 -0
  238. package/dist-types/packages/peach-engine/src/ios/photo-store.d.ts +73 -0
  239. package/dist-types/packages/peach-engine/src/ios/photoLibraryContract.d.ts +166 -0
  240. package/dist-types/packages/peach-engine/src/ios/shell-controller-types.d.ts +21 -0
  241. package/dist-types/packages/peach-engine/src/ios/shell-transition-debug.d.ts +18 -0
  242. package/dist-types/packages/peach-engine/src/metro-asset-path.d.ts +21 -0
  243. package/dist-types/packages/peach-engine/src/metro-fingerprint-registry-client.d.ts +11 -0
  244. package/dist-types/packages/peach-engine/src/metro-fingerprint.d.ts +38 -0
  245. package/dist-types/packages/peach-engine/src/native-preview-bundle.d.ts +44 -0
  246. package/dist-types/packages/peach-engine/src/observability/types.d.ts +74 -0
  247. package/dist-types/packages/peach-engine/src/peach-warm-manifest.d.ts +32 -0
  248. package/dist-types/packages/peach-engine/src/permissions/app-settings-client.d.ts +25 -0
  249. package/dist-types/packages/peach-engine/src/permissions/system-permission-types.d.ts +20 -0
  250. package/dist-types/packages/peach-engine/src/platform/android-back-panel.d.ts +131 -0
  251. package/dist-types/packages/peach-engine/src/platform/android-gesture-exclusion.d.ts +28 -0
  252. package/dist-types/packages/peach-engine/src/platform/android-predictive-back.d.ts +33 -0
  253. package/dist-types/packages/peach-engine/src/platform/system-bars-state.d.ts +14 -0
  254. package/dist-types/packages/peach-engine/src/playwright-sim-host.d.ts +1 -0
  255. package/dist-types/packages/peach-engine/src/preview/bundle-layout.d.ts +8 -0
  256. package/dist-types/packages/peach-engine/src/preview/bundle-variantContract.d.ts +24 -0
  257. package/dist-types/packages/peach-engine/src/preview/capture-bundle.d.ts +26 -0
  258. package/dist-types/packages/peach-engine/src/preview/compress-node.d.ts +2 -0
  259. package/dist-types/packages/peach-engine/src/preview/compress.d.ts +2 -0
  260. package/dist-types/packages/peach-engine/src/preview/presigned-upload.d.ts +60 -0
  261. package/dist-types/packages/peach-engine/src/preview/trace.d.ts +144 -0
  262. package/dist-types/packages/peach-engine/src/preview/upload-protocol.d.ts +152 -0
  263. package/dist-types/packages/peach-engine/src/profiler/animation-recording-loader.d.ts +1 -0
  264. package/dist-types/packages/peach-engine/src/profiler/profile-trace.d.ts +4 -0
  265. package/dist-types/packages/peach-engine/src/react-bridge.d.ts +3 -0
  266. package/dist-types/packages/peach-engine/src/react-native/AppState.d.ts +45 -0
  267. package/dist-types/packages/peach-engine/src/react-native/Appearance.d.ts +34 -0
  268. package/dist-types/packages/peach-engine/src/react-native/framework-colors-data.d.ts +2 -0
  269. package/dist-types/packages/peach-engine/src/react-native/host-services.d.ts +42 -0
  270. package/dist-types/packages/peach-engine/src/react-native/layout-animation.d.ts +22 -0
  271. package/dist-types/packages/peach-engine/src/react-native/platform-colors.d.ts +17 -0
  272. package/dist-types/packages/peach-engine/src/remote-stream/client-config.d.ts +10 -0
  273. package/dist-types/packages/peach-engine/src/remote-stream/cloud-display.d.ts +58 -0
  274. package/dist-types/packages/peach-engine/src/remote-stream/scene-recording.d.ts +45 -0
  275. package/dist-types/packages/peach-engine/src/render-worker/animated-drive-output.d.ts +35 -0
  276. package/dist-types/packages/peach-engine/src/render-worker/app-load.d.ts +16 -0
  277. package/dist-types/packages/peach-engine/src/render-worker/aux-surface-types.d.ts +2 -0
  278. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-shared.d.ts +42 -0
  279. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-webgpu.d.ts +434 -0
  280. package/dist-types/packages/peach-engine/src/render-worker/canvaskit-worker-init.d.ts +12 -0
  281. package/dist-types/packages/peach-engine/src/render-worker/compositor-backend.d.ts +31 -0
  282. package/dist-types/packages/peach-engine/src/render-worker/compositor-gpu.d.ts +202 -0
  283. package/dist-types/packages/peach-engine/src/render-worker/compositor-protocol.d.ts +1945 -0
  284. package/dist-types/packages/peach-engine/src/render-worker/compositor-runtime/scroll-drag-resample.d.ts +44 -0
  285. package/dist-types/packages/peach-engine/src/render-worker/css-keyframes-drive.d.ts +36 -0
  286. package/dist-types/packages/peach-engine/src/render-worker/edit-menu-geometry.d.ts +8 -0
  287. package/dist-types/packages/peach-engine/src/render-worker/engine-resource-relay.d.ts +21 -0
  288. package/dist-types/packages/peach-engine/src/render-worker/expo-widgetContract.d.ts +16 -0
  289. package/dist-types/packages/peach-engine/src/render-worker/gesture-seam-protocol.d.ts +152 -0
  290. package/dist-types/packages/peach-engine/src/render-worker/graph-linked-value.d.ts +29 -0
  291. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler-contract.d.ts +49 -0
  292. package/dist-types/packages/peach-engine/src/render-worker/graphite-pipeline-compiler.d.ts +12 -0
  293. package/dist-types/packages/peach-engine/src/render-worker/host-service-protocol.d.ts +756 -0
  294. package/dist-types/packages/peach-engine/src/render-worker/image-lifecycle-event.d.ts +22 -0
  295. package/dist-types/packages/peach-engine/src/render-worker/image-pixel-contract.d.ts +48 -0
  296. package/dist-types/packages/peach-engine/src/render-worker/live-frame-mirror.d.ts +34 -0
  297. package/dist-types/packages/peach-engine/src/render-worker/map-command-channel.d.ts +189 -0
  298. package/dist-types/packages/peach-engine/src/render-worker/mapNativeContract.d.ts +101 -0
  299. package/dist-types/packages/peach-engine/src/render-worker/native-dynamic-synchronizable.d.ts +22 -0
  300. package/dist-types/packages/peach-engine/src/render-worker/native-menu-gesture.d.ts +9 -0
  301. package/dist-types/packages/peach-engine/src/render-worker/native-ui-commandContract.d.ts +23 -0
  302. package/dist-types/packages/peach-engine/src/render-worker/native-ui-protocol.d.ts +1087 -0
  303. package/dist-types/packages/peach-engine/src/render-worker/native-widgetContract.d.ts +100 -0
  304. package/dist-types/packages/peach-engine/src/render-worker/nativeAnimMirrorContract.d.ts +174 -0
  305. package/dist-types/packages/peach-engine/src/render-worker/nativeSyncReplyContract.d.ts +11 -0
  306. package/dist-types/packages/peach-engine/src/render-worker/one-native-contentContract.d.ts +54 -0
  307. package/dist-types/packages/peach-engine/src/render-worker/pointerSampleContract.d.ts +14 -0
  308. package/dist-types/packages/peach-engine/src/render-worker/protocol.d.ts +880 -0
  309. package/dist-types/packages/peach-engine/src/render-worker/reanimated-css-contract.d.ts +63 -0
  310. package/dist-types/packages/peach-engine/src/render-worker/reanimated-readiness.d.ts +29 -0
  311. package/dist-types/packages/peach-engine/src/render-worker/resilient-frame-clock.d.ts +22 -0
  312. package/dist-types/packages/peach-engine/src/render-worker/retained-app-load.d.ts +20 -0
  313. package/dist-types/packages/peach-engine/src/render-worker/screen-edge-swipe-commit-protocol.d.ts +1 -0
  314. package/dist-types/packages/peach-engine/src/render-worker/screen-form-sheet-commit-protocol.d.ts +26 -0
  315. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror-tenant.d.ts +37 -0
  316. package/dist-types/packages/peach-engine/src/render-worker/scroll-mirror.d.ts +164 -0
  317. package/dist-types/packages/peach-engine/src/render-worker/shell-event-registry.d.ts +119 -0
  318. package/dist-types/packages/peach-engine/src/render-worker/shell-gesture-regions.d.ts +41 -0
  319. package/dist-types/packages/peach-engine/src/render-worker/shell-protocol.d.ts +603 -0
  320. package/dist-types/packages/peach-engine/src/render-worker/shell-scene-schema.d.ts +101 -0
  321. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-inline-sources.d.ts +13 -0
  322. package/dist-types/packages/peach-engine/src/render-worker/shell-tree-wire.d.ts +87 -0
  323. package/dist-types/packages/peach-engine/src/render-worker/test-bridge-protocol.d.ts +47 -0
  324. package/dist-types/packages/peach-engine/src/render-worker/text-inputContract.d.ts +93 -0
  325. package/dist-types/packages/peach-engine/src/render-worker/tree-sync-port.d.ts +102 -0
  326. package/dist-types/packages/peach-engine/src/render-worker/webgpu-frame-transaction.d.ts +292 -0
  327. package/dist-types/packages/peach-engine/src/render-worker/webgpu-readback-scheduler.d.ts +107 -0
  328. package/dist-types/packages/peach-engine/src/render-worker/webview-capture-protocol.d.ts +16 -0
  329. package/dist-types/packages/peach-engine/src/render-worker/worker-input-runtime.d.ts +211 -0
  330. package/dist-types/packages/peach-engine/src/render-worker/worker-storage.d.ts +33 -0
  331. package/dist-types/packages/peach-engine/src/render-worker/worklet-runtime.d.ts +987 -0
  332. package/dist-types/packages/peach-engine/src/render-worker/worklet-sab.d.ts +24 -0
  333. package/dist-types/packages/peach-engine/src/rolldown-bundle-inventory.d.ts +84 -0
  334. package/dist-types/packages/peach-engine/src/rolldown-production-fingerprint.d.ts +31 -0
  335. package/dist-types/packages/peach-engine/src/screenshots/timeline-assets.d.ts +10 -0
  336. package/dist-types/packages/peach-engine/src/screenshots/tokens.d.ts +9 -0
  337. package/dist-types/packages/peach-engine/src/settings/devices.d.ts +70 -0
  338. package/dist-types/packages/peach-engine/src/settings/duo-fold-bus.d.ts +87 -0
  339. package/dist-types/packages/peach-engine/src/settings/interface-rotation.d.ts +30 -0
  340. package/dist-types/packages/peach-engine/src/settings/react-native-configuration.d.ts +12 -0
  341. package/dist-types/packages/peach-engine/src/settings/scene-geometryContract.d.ts +40 -0
  342. package/dist-types/packages/peach-engine/src/settings/store.d.ts +37 -0
  343. package/dist-types/packages/peach-engine/src/shell-events.d.ts +203 -0
  344. package/dist-types/packages/peach-engine/src/shell-intent.d.ts +68 -0
  345. package/dist-types/packages/peach-engine/src/sootsim-event.d.ts +35 -0
  346. package/dist-types/packages/peach-engine/src/top-overlay-state.d.ts +5 -0
  347. package/dist-types/packages/peach-engine/src/web-authentication-automation-host.d.ts +2 -0
  348. package/dist-types/packages/peach-engine/src/webAuthenticationContract.d.ts +34 -0
  349. package/dist-types/packages/peach-engine/src/webview-automation-host.d.ts +180 -0
  350. package/dist-types/packages/peach-engine/src/wireframe-mode.d.ts +16 -0
  351. package/dist-types/packages/peach-globals/src/frameBreakdownContract.d.ts +16 -0
  352. package/dist-types/packages/peach-globals/src/index.d.ts +3311 -0
  353. package/dist-types/packages/peach-globals/src/nativeSurfaceContract.d.ts +76 -0
  354. package/dist-types/packages/peach-globals/src/pointerSourceEventContract.d.ts +8 -0
  355. package/dist-types/packages/peach-globals/src/profileTrace.d.ts +11 -0
  356. package/dist-types/packages/peach-globals/src/profilerContract.d.ts +223 -0
  357. package/dist-types/packages/peach-kit/src/capabilities.d.ts +721 -0
  358. package/dist-types/packages/peach-kit/src/internal.d.ts +4 -0
  359. package/dist-types/packages/peach-kit/src/materials/types.d.ts +27 -0
  360. package/dist-types/packages/peach-kit/src/materials/uikit-blur-material.d.ts +14 -0
  361. package/dist-types/packages/peach-kit/src/navigation-types.d.ts +11 -0
  362. package/dist-types/packages/peach-kit/src/react-bridge.d.ts +53 -0
  363. package/dist-types/packages/peach-kit/src/runtime.d.ts +26 -0
  364. package/dist-types/packages/peach-kit/src/ui/hosting-safe-area.d.ts +24 -0
  365. package/dist-types/packages/peach-kit/src/ui/popover-placement.d.ts +53 -0
  366. package/dist-types/packages/peach-kit/src/ui/presentationContract.d.ts +17 -0
  367. package/kotlin/ComposeSources/PeachComposeHost.kt +1 -1
  368. package/kotlin/JniSources/com/facebook/jni/HybridData.kt +0 -2
  369. package/kotlin/JniSources/dev/peach/jni/NativeBindings.kt +0 -2
  370. package/kotlin/JniTransportSources/dev/peach/jni/integration/JniTransport.kt +0 -2
  371. package/kotlin/README.md +6 -0
  372. package/package.json +22 -2
  373. package/runtime-companion.json +1 -0
  374. package/skills/contrast/SKILL.md +1 -0
  375. package/src/assetCatalogContract.ts +21 -0
  376. package/src/bridge-contract-input.ts +84 -0
  377. package/src/bridge-contract.ts +35 -3
  378. package/src/browser-launch-policy.ts +1 -0
  379. package/src/bundle-channel.mjs +4 -2
  380. package/src/cli-runtime.ts +55 -0
  381. package/src/crash-fingerprint.ts +26 -0
  382. package/src/dev-bundle-resolution.ts +50 -23
  383. package/src/device-catalog.ts +1159 -0
  384. package/src/host/bridge-host.ts +3 -26
  385. package/src/host/browser-pointer.ts +71 -0
  386. package/src/host/dev-server-package-versions.ts +23 -0
  387. package/src/host/fetch-proxy-handler.ts +17 -4
  388. package/src/installed-package-versions.ts +142 -38
  389. package/src/kotlin-host.ts +1 -1
  390. package/src/metro-plugin.ts +4 -4
  391. package/src/metro-project-root.ts +68 -0
  392. package/src/nitro-adapter.lock.json +26 -0
  393. package/src/nitro-adapter.ts +103 -0
  394. package/src/nitro-bundle.ts +24 -10
  395. package/src/nitro-compile.ts +33 -51
  396. package/src/nitro-source.ts +177 -96
  397. package/src/nitroAdapterContract.ts +217 -0
  398. package/src/nitroContract.ts +24 -11
  399. package/src/process-group.ts +41 -34
  400. package/src/react-bridge-importers.ts +28 -0
  401. package/src/reactNativeConfigurationContract.ts +36 -0
  402. package/src/runtime-assets.ts +7 -2
  403. package/src/runtime-delivery.ts +2 -0
  404. package/src/runtimePlatformContract.ts +70 -0
  405. package/src/screenshots/frame-compose.ts +42 -43
  406. package/src/screenshots/org-deck.ts +9 -4
  407. package/src/screenshots/preset-names.ts +29 -0
  408. package/src/screenshots/registry.ts +5 -5
  409. package/src/screenshots/schema.ts +1 -1
  410. package/src/screenshots/screenshotContract.ts +971 -0
  411. package/src/settings-flags.ts +107 -0
  412. package/src/settingsContract.ts +609 -0
  413. package/src/storageSnapshotContract.ts +344 -0
  414. package/src/stub-pattern-matcher.ts +550 -0
  415. package/src/swift-compile.ts +908 -40
  416. package/src/swift-compiler-digest.ts +13 -1
  417. package/src/swift-distribution.lock.json +49 -22
  418. package/src/swift-host.ts +167 -52
  419. package/src/swift-objc-compile.ts +54 -24
  420. package/src/swift-objc-export.ts +532 -0
  421. package/src/swift-objc-import.ts +769 -0
  422. package/src/swift-objc-metadata.ts +285 -10
  423. package/src/swift-objc-sdk.ts +13970 -158
  424. package/src/swift-objc-standin.ts +137 -1
  425. package/src/swift-package.ts +94 -0
  426. package/src/swift-packages.ts +5 -5
  427. package/src/swift-submit.ts +6 -0
  428. package/src/swiftContract.ts +99 -0
  429. package/src/target-matcher.ts +6 -1
  430. package/src/vite-plugin.ts +14 -40
  431. package/src/worker-system-chunks.ts +1 -1
  432. package/src/workerChunkContract.ts +5 -0
  433. package/src/worklets-babel.ts +24 -5
  434. package/src/xcode-project.ts +36 -7
  435. package/src/xcode-target-members.ts +10 -3
  436. package/cli/drivers/playwright-sim-host.ts +0 -825
  437. package/kotlin/fixtures/counter/Counter.d.kt.ts +0 -17
  438. package/kotlin/fixtures/counter/Counter.kt +0 -51
  439. package/kotlin/fixtures/counter/CounterApp.native.tsx +0 -61
  440. package/kotlin/fixtures/counter/CounterApp.tsx +0 -3
  441. package/kotlin/fixtures/counter/CounterScreen.d.kt.ts +0 -8
  442. package/kotlin/fixtures/counter/CounterScreen.kt +0 -56
  443. package/kotlin/fixtures/counter/app/_layout.tsx +0 -4
  444. package/kotlin/fixtures/counter/app/index+spa.tsx +0 -1
  445. package/kotlin/fixtures/counter/app/routes.d.ts +0 -18
  446. package/kotlin/fixtures/counter/package.json +0 -20
  447. package/kotlin/fixtures/counter/tsconfig.json +0 -19
  448. package/kotlin/fixtures/counter/vite.config.ts +0 -20
  449. package/kotlin/fixtures/headless-counter/Headless.kt +0 -234
  450. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +0 -7
  451. package/kotlin/fixtures/import-animation/Animation.kt +0 -80
  452. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +0 -13
  453. package/kotlin/fixtures/import-animation/README.md +0 -24
  454. package/kotlin/fixtures/import-animation/app/_layout.tsx +0 -4
  455. package/kotlin/fixtures/import-animation/app/index+spa.tsx +0 -1
  456. package/kotlin/fixtures/import-animation/app/routes.d.ts +0 -18
  457. package/kotlin/fixtures/import-animation/package.json +0 -23
  458. package/kotlin/fixtures/import-animation/tsconfig.json +0 -20
  459. package/kotlin/fixtures/import-animation/vite.config.ts +0 -20
  460. package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +0 -7
  461. package/kotlin/fixtures/import-drawing/Drawing.kt +0 -101
  462. package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +0 -18
  463. package/kotlin/fixtures/import-drawing/README.md +0 -34
  464. package/kotlin/fixtures/import-drawing/app/_layout.tsx +0 -4
  465. package/kotlin/fixtures/import-drawing/app/index+spa.tsx +0 -1
  466. package/kotlin/fixtures/import-drawing/package.json +0 -23
  467. package/kotlin/fixtures/import-drawing/tsconfig.json +0 -20
  468. package/kotlin/fixtures/import-drawing/vite.config.ts +0 -20
  469. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +0 -7
  470. package/kotlin/fixtures/import-editor/Editor.kt +0 -59
  471. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +0 -23
  472. package/kotlin/fixtures/import-editor/README.md +0 -27
  473. package/kotlin/fixtures/import-editor/app/_layout.tsx +0 -4
  474. package/kotlin/fixtures/import-editor/app/index+spa.tsx +0 -1
  475. package/kotlin/fixtures/import-editor/package.json +0 -23
  476. package/kotlin/fixtures/import-editor/tsconfig.json +0 -20
  477. package/kotlin/fixtures/import-editor/vite.config.ts +0 -20
  478. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +0 -7
  479. package/kotlin/fixtures/import-effects/Effects.kt +0 -87
  480. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +0 -13
  481. package/kotlin/fixtures/import-effects/README.md +0 -19
  482. package/kotlin/fixtures/import-effects/app/_layout.tsx +0 -4
  483. package/kotlin/fixtures/import-effects/app/index+spa.tsx +0 -1
  484. package/kotlin/fixtures/import-effects/package.json +0 -23
  485. package/kotlin/fixtures/import-effects/tsconfig.json +0 -20
  486. package/kotlin/fixtures/import-effects/vite.config.ts +0 -20
  487. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +0 -13
  488. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +0 -7
  489. package/kotlin/fixtures/import-layout/Layout.kt +0 -72
  490. package/kotlin/fixtures/import-layout/README.md +0 -24
  491. package/kotlin/fixtures/import-layout/app/_layout.tsx +0 -4
  492. package/kotlin/fixtures/import-layout/app/index+spa.tsx +0 -1
  493. package/kotlin/fixtures/import-layout/package.json +0 -23
  494. package/kotlin/fixtures/import-layout/tsconfig.json +0 -20
  495. package/kotlin/fixtures/import-layout/vite.config.ts +0 -20
  496. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +0 -18
  497. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +0 -7
  498. package/kotlin/fixtures/import-navigation/Navigation.kt +0 -104
  499. package/kotlin/fixtures/import-navigation/README.md +0 -31
  500. package/kotlin/fixtures/import-navigation/app/_layout.tsx +0 -4
  501. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +0 -1
  502. package/kotlin/fixtures/import-navigation/package.json +0 -23
  503. package/kotlin/fixtures/import-navigation/tsconfig.json +0 -20
  504. package/kotlin/fixtures/import-navigation/vite.config.ts +0 -20
  505. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +0 -29
  506. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +0 -7
  507. package/kotlin/fixtures/import-overlays/Overlays.kt +0 -93
  508. package/kotlin/fixtures/import-overlays/README.md +0 -34
  509. package/kotlin/fixtures/import-overlays/app/_layout.tsx +0 -4
  510. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +0 -1
  511. package/kotlin/fixtures/import-overlays/package.json +0 -23
  512. package/kotlin/fixtures/import-overlays/tsconfig.json +0 -20
  513. package/kotlin/fixtures/import-overlays/vite.config.ts +0 -20
  514. package/kotlin/fixtures/import-resources/ImportResources.native.tsx +0 -18
  515. package/kotlin/fixtures/import-resources/README.md +0 -26
  516. package/kotlin/fixtures/import-resources/Resources.d.kt.ts +0 -6
  517. package/kotlin/fixtures/import-resources/Resources.kt +0 -72
  518. package/kotlin/fixtures/import-resources/app/_layout.tsx +0 -4
  519. package/kotlin/fixtures/import-resources/app/index+spa.tsx +0 -1
  520. package/kotlin/fixtures/import-resources/package.json +0 -23
  521. package/kotlin/fixtures/import-resources/tsconfig.json +0 -20
  522. package/kotlin/fixtures/import-resources/vite.config.ts +0 -20
  523. package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +0 -10
  524. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +0 -13
  525. package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +0 -4
  526. package/kotlin/fixtures/import-scroll/Nested.kt +0 -64
  527. package/kotlin/fixtures/import-scroll/README.md +0 -38
  528. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +0 -7
  529. package/kotlin/fixtures/import-scroll/Scroll.kt +0 -91
  530. package/kotlin/fixtures/import-scroll/app/_layout.tsx +0 -4
  531. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +0 -1
  532. package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +0 -1
  533. package/kotlin/fixtures/import-scroll/package.json +0 -23
  534. package/kotlin/fixtures/import-scroll/tsconfig.json +0 -20
  535. package/kotlin/fixtures/import-scroll/vite.config.ts +0 -20
  536. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +0 -44
  537. package/kotlin/fixtures/import-selection/README.md +0 -32
  538. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +0 -8
  539. package/kotlin/fixtures/import-selection/Selection.kt +0 -78
  540. package/kotlin/fixtures/import-selection/app/_layout.tsx +0 -4
  541. package/kotlin/fixtures/import-selection/app/index+spa.tsx +0 -1
  542. package/kotlin/fixtures/import-selection/package.json +0 -23
  543. package/kotlin/fixtures/import-selection/tsconfig.json +0 -20
  544. package/kotlin/fixtures/import-selection/vite.config.ts +0 -20
  545. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +0 -13
  546. package/kotlin/fixtures/import-surfaces/README.md +0 -22
  547. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +0 -7
  548. package/kotlin/fixtures/import-surfaces/Surfaces.kt +0 -64
  549. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +0 -4
  550. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +0 -1
  551. package/kotlin/fixtures/import-surfaces/package.json +0 -23
  552. package/kotlin/fixtures/import-surfaces/tsconfig.json +0 -20
  553. package/kotlin/fixtures/import-surfaces/vite.config.ts +0 -20
  554. package/kotlin/fixtures/import-values/ImportValues.native.tsx +0 -61
  555. package/kotlin/fixtures/import-values/README.md +0 -28
  556. package/kotlin/fixtures/import-values/Values.d.kt.ts +0 -15
  557. package/kotlin/fixtures/import-values/Values.kt +0 -84
  558. package/kotlin/fixtures/import-values/app/_layout.tsx +0 -4
  559. package/kotlin/fixtures/import-values/app/index+spa.tsx +0 -1
  560. package/kotlin/fixtures/import-values/package.json +0 -23
  561. package/kotlin/fixtures/import-values/tsconfig.json +0 -20
  562. package/kotlin/fixtures/import-values/vite.config.ts +0 -20
  563. package/kotlin/fixtures/kotlin-app/app/build.gradle.kts +0 -30
  564. package/kotlin/fixtures/kotlin-app/app/src/main/AndroidManifest.xml +0 -13
  565. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/MainActivity.kt +0 -60
  566. package/kotlin/fixtures/kotlin-app/app/src/main/java/dev/contrast/kotlinapp/ProbeApplication.kt +0 -18
  567. package/kotlin/fixtures/kotlin-app/build.gradle.kts +0 -5
  568. package/kotlin/fixtures/kotlin-app/gradle.properties +0 -4
  569. package/kotlin/fixtures/kotlin-app/settings.gradle.kts +0 -4
  570. package/kotlin/fixtures/kotlin-app-variants/Anim.kt +0 -62
  571. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +0 -38
  572. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +0 -36
  573. package/kotlin/fixtures/kotlin-app-variants/Bitmaps.kt +0 -50
  574. package/kotlin/fixtures/kotlin-app-variants/Browse.kt +0 -73
  575. package/kotlin/fixtures/kotlin-app-variants/Colors.kt +0 -41
  576. package/kotlin/fixtures/kotlin-app-variants/Controls.kt +0 -62
  577. package/kotlin/fixtures/kotlin-app-variants/Drag.kt +0 -56
  578. package/kotlin/fixtures/kotlin-app-variants/Draw.kt +0 -74
  579. package/kotlin/fixtures/kotlin-app-variants/Drawables.kt +0 -53
  580. package/kotlin/fixtures/kotlin-app-variants/Focus.kt +0 -62
  581. package/kotlin/fixtures/kotlin-app-variants/Form.kt +0 -47
  582. package/kotlin/fixtures/kotlin-app-variants/Icons.kt +0 -59
  583. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +0 -53
  584. package/kotlin/fixtures/kotlin-app-variants/Lists.kt +0 -57
  585. package/kotlin/fixtures/kotlin-app-variants/Nav.kt +0 -47
  586. package/kotlin/fixtures/kotlin-app-variants/Note.kt +0 -40
  587. package/kotlin/fixtures/kotlin-app-variants/Overlays.kt +0 -56
  588. package/kotlin/fixtures/kotlin-app-variants/Pan.kt +0 -38
  589. package/kotlin/fixtures/kotlin-app-variants/Pickers.kt +0 -44
  590. package/kotlin/fixtures/kotlin-app-variants/Press.kt +0 -43
  591. package/kotlin/fixtures/kotlin-app-variants/Scroll.kt +0 -63
  592. package/kotlin/fixtures/kotlin-app-variants/Sheet.kt +0 -43
  593. package/kotlin/fixtures/kotlin-app-variants/Strings.kt +0 -49
  594. package/kotlin/fixtures/kotlin-app-variants/Tabs.kt +0 -47
  595. package/kotlin/fixtures/kotlin-app-variants/TextWidth.kt +0 -45
  596. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +0 -50
  597. package/kotlin/fixtures/kotlin-app-variants/Transition.kt +0 -69
  598. package/kotlin/fixtures/kotlin-app-variants/ViewConfig.kt +0 -22
  599. package/kotlin/fixtures/kotlin-app-variants/Widgets.kt +0 -67
  600. package/kotlin/fixtures/runtime-state/RuntimeState.kt +0 -200
  601. package/kotlin/fork/README.md +0 -97
  602. package/kotlin/fork/build.sh +0 -176
  603. package/kotlin/fork/compose-worker-globals.patch +0 -1247
  604. package/kotlin/fork/fork.json +0 -46
  605. package/kotlin/fork/publish.ts +0 -99
  606. package/kotlin/fork/skia-android-shaping.patch +0 -189
  607. package/kotlin/fork/skiko-local.init.gradle +0 -10
  608. package/kotlin/fork/skiko-worker-clock.patch +0 -122
@@ -20,8 +20,10 @@ import {
20
20
  } from 'node:fs'
21
21
  import os from 'node:os'
22
22
  import path from 'node:path'
23
+ import yaml from 'yaml'
23
24
  import { admittedMacBuilderSlot } from './admitted-mac-build'
24
25
  import { rnxHomeDir, swiftPackageCacheOptions } from './home-paths'
26
+ import { isRecord } from './is-record'
25
27
  import { terminateProcessGroup } from './process-group'
26
28
  import { swiftCompilerSourceDigest } from './swift-compiler-digest'
27
29
  import { designTimeDiagnostic, designTimeSource } from './swift-design-time'
@@ -31,16 +33,38 @@ import {
31
33
  type SwiftDistributionManifest,
32
34
  } from './swift-distribution-contract'
33
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'
34
40
  import {
41
+ OBJC_RESOURCE_ACCESSOR_BODY,
42
+ OBJC_RESOURCE_ACCESSOR_HEADER,
35
43
  swiftManifestCxxLanguageStandard,
36
44
  swiftManifestTargets,
45
+ swiftObjCResourceAccessor,
46
+ swiftObjCResourceBundleName,
37
47
  swiftPackagePartition,
38
48
  swiftTargetModuleName,
39
49
  type SwiftPackageTarget,
40
50
  } from './swift-package'
41
51
  import { withSwiftRootLock, type SwiftRootLease } from './swift-root-lock'
42
- import { swiftEnvironment, swiftSdkOptions, type SwiftWasmSdk } from './swift-toolchain'
43
- import { isSwiftResourceBundles } from './swiftContract'
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'
44
68
  import type { SwiftImageUpload } from './swift-submit'
45
69
  import type { SwiftResourceBundle } from './swiftContract'
46
70
 
@@ -59,7 +83,7 @@ async function runCompiler(
59
83
  options: ExecFileOptions & { signal?: AbortSignal; lease?: SwiftRootLease },
60
84
  stream: boolean | RegExp = false,
61
85
  quiet?: RegExp,
62
- ): Promise<void> {
86
+ ): Promise<string> {
63
87
  const { signal } = options
64
88
  signal?.throwIfAborted()
65
89
  const launch = {
@@ -73,7 +97,7 @@ async function runCompiler(
73
97
  : spawn(command, args, launch)
74
98
  let stopping: Promise<void> | undefined
75
99
  try {
76
- await new Promise<void>((resolve, reject) => {
100
+ return await new Promise<string>((resolve, reject) => {
77
101
  let failure: Error | undefined
78
102
  let timeout: ReturnType<typeof setTimeout> | undefined
79
103
  const chunks: Record<'stdout' | 'stderr', Buffer[]> = { stdout: [], stderr: [] }
@@ -129,7 +153,7 @@ async function runCompiler(
129
153
  for (const name of ['stdout', 'stderr'] as const)
130
154
  for (const line of Buffer.concat(chunks[name]).toString().split('\n'))
131
155
  if (line && !quiet.test(line)) process[name].write(`${line}\n`)
132
- resolve()
156
+ resolve(Buffer.concat(chunks.stdout).toString())
133
157
  }
134
158
  })
135
159
  if (options.timeout)
@@ -144,7 +168,7 @@ async function runCompiler(
144
168
  }
145
169
  }
146
170
 
147
- const WASM_TRIPLE = 'wasm32-unknown-wasip1'
171
+ export const WASM_TRIPLE = 'wasm32-unknown-wasip1'
148
172
 
149
173
  // swiftpm's step counter, echoed while a build runs; its diagnostics print
150
174
  // once, with the failure.
@@ -161,6 +185,8 @@ const BUILD_JOBS = String(
161
185
 
162
186
  export interface SwiftCompileInput {
163
187
  files: Record<string, string>
188
+ objcPeerStartup?: SwiftObjCPeerStartup
189
+ nativeTargets?: SwiftNativeTarget[]
164
190
  metalSources?: Record<string, string>
165
191
  resources?: Record<string, string>
166
192
  /** project-relative resource paths retained before the bundle namespace flattens. */
@@ -838,6 +864,8 @@ export function swiftArtifactHash(
838
864
  [...(input.resourceBundles ?? [])].sort((a, b) => a.target.localeCompare(b.target)),
839
865
  ),
840
866
  )
867
+ hash.update(JSON.stringify(input.nativeTargets ?? []))
868
+ hash.update(JSON.stringify(input.objcPeerStartup ?? null))
841
869
  for (const target of Object.keys(input.libraries ?? {}).sort()) {
842
870
  hash.update(`library\n${target}\n`)
843
871
  hash.update(
@@ -864,9 +892,13 @@ export function swiftArtifactHash(
864
892
  interface SwiftNativeTargetPlan {
865
893
  path: string
866
894
  includeDirectory: string
895
+ sources: string[]
867
896
  // units that consume a swift-generated header: excluded from the original
868
897
  // target and compiled by the downstream implementation target.
869
898
  lateSources: string[]
899
+ mixed?: boolean
900
+ exclude?: string[]
901
+ groups?: { name: string; sources: string[]; flags: string[]; cxxFlags: string[] }[]
870
902
  late?: { name: string; producers: string[] }
871
903
  }
872
904
 
@@ -875,6 +907,7 @@ export function emitSwiftPackageManifest(args: {
875
907
  cxxLanguageStandard?: string
876
908
  native?: Map<string, SwiftNativeTargetPlan>
877
909
  headerDirectory?: string
910
+ objcExports?: { modules: Set<string>; flags: string[] }
878
911
  siblings: Map<string, string[]>
879
912
  moduleRoot: string
880
913
  oneModule?: boolean
@@ -953,6 +986,9 @@ export function emitSwiftPackageManifest(args: {
953
986
  ? ' .defaultIsolation(MainActor.self),'
954
987
  : ''
955
988
  const interoperability = target.cxxInterop ? ' .interoperabilityMode(.Cxx),' : ''
989
+ const exports = args.objcExports?.modules.has(target.name)
990
+ ? ' .enableExperimentalFeature("Extern"),'
991
+ : ''
956
992
  const defines = (target.defines ?? [])
957
993
  .map((name) => ` .define(${JSON.stringify(name)}),`)
958
994
  .join('')
@@ -969,8 +1005,9 @@ export function emitSwiftPackageManifest(args: {
969
1005
  ? `, "-I", ${JSON.stringify(path.join(moduleRoot, 'modules'))}`
970
1006
  : ''
971
1007
  const native = args.native?.get(target.name)
1008
+ const clang = native && !native.mixed
972
1009
  const nativeImports = (siblings.get(target.name) ?? [])
973
- .filter((name) => args.native?.has(name))
1010
+ .filter((name) => args.native?.has(name) && !args.native.get(name)?.mixed)
974
1011
  .map(
975
1012
  (name) =>
976
1013
  `, "-Xfrontend", "-import-module", "-Xfrontend", ${JSON.stringify(swiftTargetModuleName(name))}`,
@@ -981,30 +1018,54 @@ export function emitSwiftPackageManifest(args: {
981
1018
  [...(args.native?.values() ?? [])].some((value) =>
982
1019
  value.late?.producers.includes(target.name),
983
1020
  )
984
- ? `, "-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`))}`
985
1022
  : ''
986
- 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}])]`
987
1024
  const deps = [
988
- ...(target.executable
989
- ? [...(args.native?.values() ?? [])].flatMap((value) =>
990
- 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),
991
1059
  )
992
- : []),
993
- ...(distribution || (native && !target.executable)
994
- ? []
995
- : [
996
- '.product(name: "SwiftUI", package: "sootsim-swift")',
997
- ...(oneModule ? [ONE_PRODUCT] : []),
998
- ...(spriteKit ? [SPRITEKIT_PRODUCT] : []),
999
- ]),
1000
- ...(siblings.get(target.name) ?? []).flatMap((dependency) =>
1001
- OPTIONAL_FRAMEWORKS.has(dependency) &&
1002
- !targets.some((candidate) => candidate.name === dependency)
1003
- ? distribution
1004
1060
  ? []
1005
- : [`.product(name: "${dependency}", package: "sootsim-swift")`]
1006
- : [`"${dependency}"`],
1007
- ),
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
+ ]),
1008
1069
  ].join(', ')
1009
1070
  const library =
1010
1071
  distribution && distributionLink
@@ -1027,7 +1088,7 @@ export function emitSwiftPackageManifest(args: {
1027
1088
  linkerSettings: [
1028
1089
  ${linkedLibraries.map((setting) => `${setting},`).join('\n ')}
1029
1090
  .unsafeFlags([
1030
- ${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},
1031
1092
  ]),
1032
1093
  .unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
1033
1094
  ]`
@@ -1040,10 +1101,12 @@ export function emitSwiftPackageManifest(args: {
1040
1101
  ` name: "${target.name}",`,
1041
1102
  ` dependencies: [${deps}],`,
1042
1103
  ` path: "${target.path}",`,
1043
- ...(native ? [` exclude: ${JSON.stringify(native.lateSources)},`] : []),
1104
+ ...(native
1105
+ ? [` exclude: ${JSON.stringify(native.exclude ?? native.lateSources)},`]
1106
+ : []),
1044
1107
  // the native backend supplies dependency module maps without their
1045
1108
  // compiled modules. textual c++ includes keep those dependencies usable.
1046
- ` ${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}`,
1047
1110
  ` ),`,
1048
1111
  ].join('\n')
1049
1112
  }
@@ -1060,16 +1123,40 @@ export function emitSwiftPackageManifest(args: {
1060
1123
  ` dependencies: [${distribution ? '' : `.package(path: "${moduleRoot}")`}],`,
1061
1124
  ' targets: [',
1062
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
+ : []),
1063
1136
  ...[...(args.native?.entries() ?? [])].flatMap(([name, native]) =>
1064
1137
  native.late
1065
- ? [
1066
- ` .target(name: ${JSON.stringify(native.late.name)},`,
1067
- ` 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])},`,
1068
1150
  ` path: ${JSON.stringify(native.path)},`,
1069
- ` sources: ${JSON.stringify(native.lateSources)},`,
1151
+ ` sources: ${JSON.stringify(group.sources)},`,
1070
1152
  ` publicHeadersPath: "include",`,
1071
- ` cxxSettings: [.unsafeFlags(["-fno-cxx-modules", "-I", ${JSON.stringify(native.includeDirectory)}, "-I", ${JSON.stringify(args.headerDirectory)}])]),`,
1072
- ]
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
+ ])
1073
1160
  : [],
1074
1161
  ),
1075
1162
  args.cxxLanguageStandard
@@ -2314,6 +2401,68 @@ const SDK_OBJC_OPTIONAL: Record<
2314
2401
  ][]
2315
2402
  }
2316
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
+ },
2317
2466
  WKWebExtensionWindow: {
2318
2467
  callers: true,
2319
2468
  mainActor: true,
@@ -5521,6 +5670,87 @@ export function swiftApplicationEntry(file: string, source: string): boolean {
5521
5670
  return false
5522
5671
  }
5523
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
+
5524
5754
  // the offsets of the lines that begin in code, and of every `@`, `#`,
5525
5755
  // `class`, `extension` and `override` keyword that stands in code (an interpolation's code included), from a scan of Swift's
5526
5756
  // lexical contexts: nested block comments, line comments, string literals (single and
@@ -5695,7 +5925,14 @@ export function writeSwiftProject(
5695
5925
  layout: SwiftProjectLayout,
5696
5926
  input: SwiftCompileInput,
5697
5927
  moduleRoot: string,
5698
- ): 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')
5699
5936
  if (
5700
5937
  input.resourceBundles !== undefined &&
5701
5938
  !isSwiftResourceBundles(input.resourceBundles)
@@ -5723,7 +5960,54 @@ export function writeSwiftProject(
5723
5960
  : compileTargets(input)
5724
5961
  const files = new Map<string, string | Buffer>()
5725
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
+ }
5726
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
+ }
5727
6011
  // declarations are imported before swift can emit the header that native
5728
6012
  // implementations consume. give those implementations a downstream target.
5729
6013
  for (const target of targets) {
@@ -5739,9 +6023,232 @@ export function writeSwiftProject(
5739
6023
  file.startsWith(`${candidate.path}/`),
5740
6024
  ),
5741
6025
  )
5742
- if (entries.some(([file]) => file.endsWith('.swift'))) continue
5743
6026
  const units = entries.filter(([file]) => /\.(?:c|cc|cpp|cxx|m|mm)$/.test(file))
5744
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
+ }
5745
6252
  const includes = `${prefix}include/`
5746
6253
  const consumers = new Map<string, Set<string>>()
5747
6254
  const reverse = new Map<string, string[]>()
@@ -5749,7 +6256,9 @@ export function writeSwiftProject(
5749
6256
  const producers = new Set<string>()
5750
6257
  // a block-commented include is not an edge.
5751
6258
  const source = contents.replace(/\/\*[\s\S]*?\*\//g, '')
5752
- 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
+ )) {
5753
6262
  const include = match[1]!
5754
6263
  const producer = /(?:^|\/)([^/]+)-Swift\.h$/.exec(include)?.[1]
5755
6264
  if (producer && targets.some((value) => value.name === producer))
@@ -5778,6 +6287,7 @@ export function writeSwiftProject(
5778
6287
  native.set(target.name, {
5779
6288
  path: target.path,
5780
6289
  includeDirectory: path.join(layout.root, includes),
6290
+ sources: units.map(([file]) => file.slice(prefix.length)),
5781
6291
  lateSources: late.map(([file]) => file.slice(prefix.length)),
5782
6292
  ...(late.length > 0
5783
6293
  ? {
@@ -5851,6 +6361,247 @@ export function writeSwiftProject(
5851
6361
  ),
5852
6362
  targets,
5853
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
+ }
5854
6605
  if (targets.length === 0) {
5855
6606
  for (const [file, contents] of Object.entries(input.files)) {
5856
6607
  if (file === 'Package.swift') continue
@@ -5922,6 +6673,7 @@ export function writeSwiftProject(
5922
6673
  emitSwiftPackageManifest({
5923
6674
  targets,
5924
6675
  native,
6676
+ objcExports,
5925
6677
  headerDirectory: native.size > 0 ? headerDirectory : undefined,
5926
6678
  cxxLanguageStandard: swiftManifestCxxLanguageStandard(
5927
6679
  input.files['Package.swift'] ?? '',
@@ -5967,7 +6719,42 @@ export function writeSwiftProject(
5967
6719
  ].join('\n'),
5968
6720
  )
5969
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)
5970
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
+ }
5971
6758
  }
5972
6759
 
5973
6760
  function streamText(value: unknown): string {
@@ -6260,7 +7047,7 @@ export function compileSwiftProjectUnit(
6260
7047
  report('reusing verified disk artifact')
6261
7048
  return retain(root, built)
6262
7049
  }
6263
- writeSwiftProject(layout, input, moduleRoot)
7050
+ const preparation = writeSwiftProject(layout, input, moduleRoot)
6264
7051
  const swift = path.join(options.toolchainBin, 'swift')
6265
7052
  if (!existsSync(swift)) {
6266
7053
  throw new Error(
@@ -6328,6 +7115,87 @@ export function compileSwiftProjectUnit(
6328
7115
  }
6329
7116
  report('compiling and linking Swift modules')
6330
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
+ }
6331
7199
  await runCompiler(
6332
7200
  swift,
6333
7201
  buildArgs,