peachsim 0.1.939 → 0.1.1399

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 (396) hide show
  1. package/README.md +28 -22
  2. package/cli/app-catalog.ts +29 -14
  3. package/cli/app-fonts.ts +5 -3
  4. package/cli/bridge-flow-runner.ts +40 -29
  5. package/cli/cloud-client.ts +57 -21
  6. package/cli/cloud-test-tunnel.ts +12 -18
  7. package/cli/commands/agent.ts +1 -1
  8. package/cli/commands/app-fonts.ts +3 -3
  9. package/cli/commands/assert.ts +8 -8
  10. package/cli/commands/auth.ts +8 -3
  11. package/cli/commands/box/bundle-plane.ts +13 -1
  12. package/cli/commands/box.ts +16 -5
  13. package/cli/commands/compat.ts +1 -1
  14. package/cli/commands/config.ts +2 -2
  15. package/cli/commands/control.ts +125 -71
  16. package/cli/commands/cpu-profile.ts +45 -1
  17. package/cli/commands/daemon.ts +131 -33
  18. package/cli/commands/debug.ts +24 -17
  19. package/cli/commands/desktop.ts +7 -1
  20. package/cli/commands/detect.ts +101 -0
  21. package/cli/commands/detox.ts +6 -6
  22. package/cli/commands/device.ts +12 -12
  23. package/cli/commands/electron.ts +32 -14
  24. package/cli/commands/flow.ts +49 -41
  25. package/cli/commands/guest-host.ts +39 -1
  26. package/cli/commands/inspect/core.ts +14 -8
  27. package/cli/commands/inspect/list.ts +1 -1
  28. package/cli/commands/inspect/settle.ts +5 -3
  29. package/cli/commands/inspect/settling.ts +229 -44
  30. package/cli/commands/inspect/wait-idle.ts +3 -2
  31. package/cli/commands/inspect.ts +105 -93
  32. package/cli/commands/install-cli.ts +36 -15
  33. package/cli/commands/install-desktop.ts +68 -195
  34. package/cli/commands/kotlin.ts +6 -5
  35. package/cli/commands/login.ts +5 -5
  36. package/cli/commands/maestro-compare.ts +554 -0
  37. package/cli/commands/maestro-generate.ts +6 -3
  38. package/cli/commands/maestro.ts +22 -0
  39. package/cli/commands/mode.ts +2 -2
  40. package/cli/commands/no-bridge-hint.ts +6 -2
  41. package/cli/commands/platform.ts +35 -6
  42. package/cli/commands/preview.ts +6 -0
  43. package/cli/commands/project-report.ts +10 -12
  44. package/cli/commands/record.ts +37 -37
  45. package/cli/commands/runtime.ts +9 -9
  46. package/cli/commands/screenshot-layers.ts +4 -4
  47. package/cli/commands/screenshot-mode.ts +2 -2
  48. package/cli/commands/screenshot.ts +8 -8
  49. package/cli/commands/screenshots-capture.ts +2 -2
  50. package/cli/commands/serve.ts +9 -12
  51. package/cli/commands/setup.ts +29 -14
  52. package/cli/commands/shell-boolean-mode.ts +2 -2
  53. package/cli/commands/show-touches-mode.ts +2 -2
  54. package/cli/commands/skills.ts +11 -11
  55. package/cli/commands/swift.ts +29 -11
  56. package/cli/commands/telemetry.ts +2 -2
  57. package/cli/commands/test.ts +5 -0
  58. package/cli/commands/three-mode.ts +3 -3
  59. package/cli/commands/timeline.ts +4 -4
  60. package/cli/commands/upgrade.ts +2 -2
  61. package/cli/commands/upload.ts +15 -15
  62. package/cli/commands/what-happened.ts +2 -2
  63. package/cli/current-sim.ts +6 -3
  64. package/cli/desktop-companion.ts +55 -149
  65. package/cli/dev-build-freshness.ts +2 -2
  66. package/cli/drivers/desktop.ts +17 -9
  67. package/cli/drivers/electron.ts +1 -2
  68. package/cli/drivers/playwright-sim-host.ts +11 -2
  69. package/cli/drivers/playwright.ts +35 -2
  70. package/cli/drivers/types.ts +8 -0
  71. package/cli/maestro-compare.ts +670 -0
  72. package/cli/outbound-endpoints.ts +46 -8
  73. package/cli/recording-access.ts +6 -6
  74. package/cli/run-registry.ts +1 -1
  75. package/cli/runtime-compat.ts +5 -1
  76. package/cli/send-to-box.ts +3 -3
  77. package/cli/shell-init.ts +2 -1
  78. package/cli/ws-bridge.ts +9 -5
  79. package/detox/element-types.ts +1 -0
  80. package/detox/gestures.ts +3 -3
  81. package/detox/index.ts +67 -38
  82. package/detox/navigation-lifecycle.ts +9 -6
  83. package/detox/proof-frame.cjs +6 -4
  84. package/dist-lib/agent-daemon-client.cjs +1 -1
  85. package/dist-lib/agent-events.cjs +1 -1
  86. package/dist-lib/attached-projects.cjs +1 -1
  87. package/dist-lib/auth/shared-session.cjs +1 -1
  88. package/dist-lib/backend-origin.cjs +1 -1
  89. package/dist-lib/beta.cjs +1 -1
  90. package/dist-lib/beta.mjs +1 -1
  91. package/dist-lib/bridge-constants.cjs +1 -1
  92. package/dist-lib/bridge-contract-input.cjs +42 -17
  93. package/dist-lib/bridge-contract-input.mjs +41 -16
  94. package/dist-lib/bridge-contract.cjs +1 -4
  95. package/dist-lib/bridge-contract.mjs +1 -3
  96. package/dist-lib/bundle-channel.cjs +2918 -550
  97. package/dist-lib/capture-contract.cjs +65 -24
  98. package/dist-lib/capture-contract.mjs +63 -24
  99. package/dist-lib/cloud-contract.cjs +2 -2
  100. package/dist-lib/cloud-contract.mjs +2 -2
  101. package/dist-lib/cloud-test-args.cjs +1 -1
  102. package/dist-lib/cloud-test-args.mjs +1 -1
  103. package/dist-lib/cloud.cjs +3 -3
  104. package/dist-lib/cloud.mjs +3 -3
  105. package/dist-lib/config.cjs +15 -5
  106. package/dist-lib/config.mjs +154 -0
  107. package/dist-lib/detox/index.cjs +495 -139
  108. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  109. package/dist-lib/expo-swift-bundle.cjs +1168 -238
  110. package/dist-lib/expo-swift-metadata.cjs +34 -23
  111. package/dist-lib/expo-swift-metadata.mjs +32 -23
  112. package/dist-lib/home-paths.cjs +2 -2
  113. package/dist-lib/host/bridge-host.cjs +2938 -654
  114. package/dist-lib/host/fetch-proxy-handler.cjs +14 -1
  115. package/dist-lib/host/fetch-proxy-overrides.cjs +7 -1
  116. package/dist-lib/host/fetch-proxy-overrides.mjs +5 -1
  117. package/dist-lib/host/replacement-module-handler.cjs +2 -2
  118. package/dist-lib/host/websocket-proxy.cjs +1 -1
  119. package/dist-lib/index.cjs +999 -353
  120. package/dist-lib/jump-to-source-babel.cjs +1 -1
  121. package/dist-lib/jump-to-source-native.cjs +1 -1
  122. package/dist-lib/kotlin-host.cjs +332 -19
  123. package/dist-lib/menu.cjs +1 -1
  124. package/dist-lib/menu.mjs +1 -1
  125. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  126. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  127. package/dist-lib/metro-production-bundle.cjs +7 -7
  128. package/dist-lib/metro-production-bundle.mjs +5 -5
  129. package/dist-lib/metro.cjs +688 -250
  130. package/dist-lib/native-app-identity-project.cjs +2647 -0
  131. package/dist-lib/native-app-identity-project.mjs +1257 -0
  132. package/dist-lib/native-app-identity.cjs +325 -25
  133. package/dist-lib/native-app-identity.mjs +323 -25
  134. package/dist-lib/native-firebase-metadata.cjs +1 -1
  135. package/dist-lib/native-firebase-metadata.mjs +1 -1
  136. package/dist-lib/plist.cjs +1 -1
  137. package/dist-lib/plist.mjs +1 -1
  138. package/dist-lib/profiles.cjs +1 -1
  139. package/dist-lib/public-brand.cjs +1 -1
  140. package/dist-lib/react-native-host-modules.cjs +5 -1
  141. package/dist-lib/react-native-host-modules.mjs +5 -1
  142. package/dist-lib/scripts/dev-server-scanner.cjs +57 -32
  143. package/dist-lib/sdk.cjs +231 -51
  144. package/dist-lib/sdk.mjs +231 -51
  145. package/dist-lib/skills.cjs +4107 -1374
  146. package/dist-lib/swift-compile.cjs +290 -30
  147. package/dist-lib/swift-compile.mjs +290 -30
  148. package/dist-lib/swift-package.cjs +143 -12
  149. package/dist-lib/swift-package.mjs +137 -11
  150. package/dist-lib/swift-submit.cjs +47 -5
  151. package/dist-lib/swift-submit.mjs +42 -5
  152. package/dist-lib/swift-toolchain.cjs +7 -2
  153. package/dist-lib/swift.cjs +1 -1
  154. package/dist-lib/vite-swift.cjs +1392 -458
  155. package/dist-lib/vite.cjs +13 -17
  156. package/dist-lib/worklet-executable.cjs +248 -33
  157. package/dist-lib/worklet-executable.mjs +248 -33
  158. package/install.sh +10 -1
  159. package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Resources.kt +9 -9
  160. package/kotlin/AndroidViewSources/android/graphics/Canvas.kt +20 -0
  161. package/kotlin/AndroidViewSources/android/view/View.kt +211 -0
  162. package/kotlin/AndroidViewSources/android/widget/FrameLayout.kt +61 -0
  163. package/kotlin/AndroidViewSources/android/widget/LinearLayout.kt +49 -0
  164. package/kotlin/AppSources/android/view/Window.kt +36 -0
  165. package/kotlin/AppSources/android/view/WindowInsets.kt +9 -0
  166. package/kotlin/AppSources/android/view/WindowInsetsController.kt +5 -0
  167. package/kotlin/AppSources/android/window/OnBackInvokedDispatcher.kt +48 -0
  168. package/kotlin/AppSources/androidx/activity/OnBackPressedDispatcher.kt +20 -5
  169. package/kotlin/AppSources/androidx/compose/foundation/layout/WindowInsets.kt +15 -0
  170. package/kotlin/AppSources/androidx/compose/ui/platform/ComposeView.kt +2 -1
  171. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +42 -50
  172. package/kotlin/ComposeSources/PeachComposeHost.kt +200 -84
  173. package/kotlin/ExpoComposeSources/PeachAndroidView.kt +87 -0
  174. package/kotlin/ExpoComposeSources/PeachExpoViewMount.kt +24 -0
  175. package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +28 -0
  176. package/kotlin/ExpoComposeSources/expo/modules/kotlin/views/ExpoComposeView.kt +70 -0
  177. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +513 -0
  178. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +173 -0
  179. package/kotlin/ExpoSources/expo/modules/kotlin/AppContext.kt +20 -0
  180. package/kotlin/ExpoSources/expo/modules/kotlin/Promise.kt +19 -0
  181. package/kotlin/ExpoSources/expo/modules/kotlin/classcomponent/ClassComponentBuilder.kt +198 -0
  182. package/kotlin/ExpoSources/expo/modules/kotlin/exception/CodedException.kt +126 -0
  183. package/kotlin/ExpoSources/expo/modules/kotlin/functions/Functions.kt +132 -0
  184. package/kotlin/ExpoSources/expo/modules/kotlin/jni/JavaScriptTypedArray.kt +81 -0
  185. package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +98 -0
  186. package/kotlin/ExpoSources/expo/modules/kotlin/objects/ObjectDefinitionBuilder.kt +236 -0
  187. package/kotlin/ExpoSources/expo/modules/kotlin/records/Record.kt +12 -0
  188. package/kotlin/ExpoSources/expo/modules/kotlin/runtime/Runtime.kt +9 -0
  189. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObject.kt +50 -0
  190. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedObjectRegistry.kt +57 -0
  191. package/kotlin/ExpoSources/expo/modules/kotlin/sharedobjects/SharedRef.kt +19 -0
  192. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/ConcreteTypedArrays.kt +158 -0
  193. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/GenericTypedArray.kt +8 -0
  194. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArray.kt +29 -0
  195. package/kotlin/ExpoSources/expo/modules/kotlin/typedarray/TypedArrayIterator.kt +9 -0
  196. package/kotlin/ExpoSources/expo/modules/kotlin/types/AnyType.kt +155 -0
  197. package/kotlin/ExpoSources/expo/modules/kotlin/types/Either.kt +91 -0
  198. package/kotlin/ExpoSources/expo/modules/kotlin/types/Enumerable.kt +6 -0
  199. package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +54 -0
  200. package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +23 -0
  201. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +71 -0
  202. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +35 -0
  203. package/kotlin/README.md +13 -3
  204. package/kotlin/Sources/android/os/Build.kt +17 -0
  205. package/kotlin/Sources/android/os/Handler.kt +35 -0
  206. package/kotlin/Sources/android/os/Looper.kt +17 -0
  207. package/kotlin/Sources/android/os/MessageQueue.kt +56 -0
  208. package/kotlin/Sources/android/os/SystemClock.kt +14 -0
  209. package/kotlin/Sources/android/util/Log.kt +64 -0
  210. package/kotlin/Sources/java/security/MessageDigest.kt +114 -0
  211. package/kotlin/Sources/kotlin/text/StringFormat.kt +9 -0
  212. package/kotlin/Sources/org/json/JSON.kt +44 -0
  213. package/kotlin/fixtures/counter/Counter.d.kt.ts +1 -0
  214. package/kotlin/fixtures/counter/Counter.kt +10 -3
  215. package/kotlin/fixtures/counter/CounterApp.native.tsx +1 -1
  216. package/kotlin/fixtures/counter/vite.config.ts +2 -2
  217. package/kotlin/fixtures/headless-counter/Headless.kt +7 -6
  218. package/kotlin/fixtures/import-animation/Animation.d.kt.ts +7 -0
  219. package/kotlin/fixtures/import-animation/Animation.kt +80 -0
  220. package/kotlin/fixtures/import-animation/ImportAnimation.native.tsx +13 -0
  221. package/kotlin/fixtures/import-animation/README.md +24 -0
  222. package/kotlin/fixtures/import-animation/app/_layout.tsx +4 -0
  223. package/kotlin/fixtures/import-animation/app/index+spa.tsx +1 -0
  224. package/kotlin/fixtures/import-animation/app/routes.d.ts +18 -0
  225. package/kotlin/fixtures/import-animation/package.json +23 -0
  226. package/kotlin/fixtures/import-animation/tsconfig.json +20 -0
  227. package/kotlin/fixtures/import-animation/vite.config.ts +20 -0
  228. package/kotlin/fixtures/import-editor/Editor.d.kt.ts +7 -0
  229. package/kotlin/fixtures/import-editor/Editor.kt +59 -0
  230. package/kotlin/fixtures/import-editor/ImportEditor.native.tsx +23 -0
  231. package/kotlin/fixtures/import-editor/README.md +27 -0
  232. package/kotlin/fixtures/import-editor/app/_layout.tsx +4 -0
  233. package/kotlin/fixtures/import-editor/app/index+spa.tsx +1 -0
  234. package/kotlin/fixtures/import-editor/package.json +23 -0
  235. package/kotlin/fixtures/import-editor/tsconfig.json +20 -0
  236. package/kotlin/fixtures/import-editor/vite.config.ts +20 -0
  237. package/kotlin/fixtures/import-effects/Effects.d.kt.ts +7 -0
  238. package/kotlin/fixtures/import-effects/Effects.kt +87 -0
  239. package/kotlin/fixtures/import-effects/ImportEffects.native.tsx +13 -0
  240. package/kotlin/fixtures/import-effects/README.md +19 -0
  241. package/kotlin/fixtures/import-effects/app/_layout.tsx +4 -0
  242. package/kotlin/fixtures/import-effects/app/index+spa.tsx +1 -0
  243. package/kotlin/fixtures/import-effects/package.json +23 -0
  244. package/kotlin/fixtures/import-effects/tsconfig.json +20 -0
  245. package/kotlin/fixtures/import-effects/vite.config.ts +20 -0
  246. package/kotlin/fixtures/import-layout/ImportLayout.native.tsx +13 -0
  247. package/kotlin/fixtures/import-layout/Layout.d.kt.ts +7 -0
  248. package/kotlin/fixtures/import-layout/Layout.kt +72 -0
  249. package/kotlin/fixtures/import-layout/README.md +24 -0
  250. package/kotlin/fixtures/import-layout/app/_layout.tsx +4 -0
  251. package/kotlin/fixtures/import-layout/app/index+spa.tsx +1 -0
  252. package/kotlin/fixtures/import-layout/package.json +23 -0
  253. package/kotlin/fixtures/import-layout/tsconfig.json +20 -0
  254. package/kotlin/fixtures/import-layout/vite.config.ts +20 -0
  255. package/kotlin/fixtures/import-navigation/ImportNavigation.native.tsx +18 -0
  256. package/kotlin/fixtures/import-navigation/Navigation.d.kt.ts +7 -0
  257. package/kotlin/fixtures/import-navigation/Navigation.kt +104 -0
  258. package/kotlin/fixtures/import-navigation/README.md +31 -0
  259. package/kotlin/fixtures/import-navigation/app/_layout.tsx +4 -0
  260. package/kotlin/fixtures/import-navigation/app/index+spa.tsx +1 -0
  261. package/kotlin/fixtures/import-navigation/package.json +23 -0
  262. package/kotlin/fixtures/import-navigation/tsconfig.json +20 -0
  263. package/kotlin/fixtures/import-navigation/vite.config.ts +20 -0
  264. package/kotlin/fixtures/import-overlays/ImportOverlays.native.tsx +29 -0
  265. package/kotlin/fixtures/import-overlays/Overlays.d.kt.ts +7 -0
  266. package/kotlin/fixtures/import-overlays/Overlays.kt +93 -0
  267. package/kotlin/fixtures/import-overlays/README.md +34 -0
  268. package/kotlin/fixtures/import-overlays/app/_layout.tsx +4 -0
  269. package/kotlin/fixtures/import-overlays/app/index+spa.tsx +1 -0
  270. package/kotlin/fixtures/import-overlays/package.json +23 -0
  271. package/kotlin/fixtures/import-overlays/tsconfig.json +20 -0
  272. package/kotlin/fixtures/import-overlays/vite.config.ts +20 -0
  273. package/kotlin/fixtures/import-scroll/ImportScroll.native.tsx +13 -0
  274. package/kotlin/fixtures/import-scroll/README.md +23 -0
  275. package/kotlin/fixtures/import-scroll/Scroll.d.kt.ts +7 -0
  276. package/kotlin/fixtures/import-scroll/Scroll.kt +91 -0
  277. package/kotlin/fixtures/import-scroll/app/_layout.tsx +4 -0
  278. package/kotlin/fixtures/import-scroll/app/index+spa.tsx +1 -0
  279. package/kotlin/fixtures/import-scroll/package.json +23 -0
  280. package/kotlin/fixtures/import-scroll/tsconfig.json +20 -0
  281. package/kotlin/fixtures/import-scroll/vite.config.ts +20 -0
  282. package/kotlin/fixtures/import-selection/ImportSelection.native.tsx +44 -0
  283. package/kotlin/fixtures/import-selection/README.md +32 -0
  284. package/kotlin/fixtures/import-selection/Selection.d.kt.ts +8 -0
  285. package/kotlin/fixtures/import-selection/Selection.kt +78 -0
  286. package/kotlin/fixtures/import-selection/app/_layout.tsx +4 -0
  287. package/kotlin/fixtures/import-selection/app/index+spa.tsx +1 -0
  288. package/kotlin/fixtures/import-selection/package.json +23 -0
  289. package/kotlin/fixtures/import-selection/tsconfig.json +20 -0
  290. package/kotlin/fixtures/import-selection/vite.config.ts +20 -0
  291. package/kotlin/fixtures/import-surfaces/ImportSurfaces.native.tsx +13 -0
  292. package/kotlin/fixtures/import-surfaces/README.md +22 -0
  293. package/kotlin/fixtures/import-surfaces/Surfaces.d.kt.ts +7 -0
  294. package/kotlin/fixtures/import-surfaces/Surfaces.kt +64 -0
  295. package/kotlin/fixtures/import-surfaces/app/_layout.tsx +4 -0
  296. package/kotlin/fixtures/import-surfaces/app/index+spa.tsx +1 -0
  297. package/kotlin/fixtures/import-surfaces/package.json +23 -0
  298. package/kotlin/fixtures/import-surfaces/tsconfig.json +20 -0
  299. package/kotlin/fixtures/import-surfaces/vite.config.ts +20 -0
  300. package/kotlin/fixtures/import-values/ImportValues.native.tsx +35 -0
  301. package/kotlin/fixtures/import-values/README.md +23 -0
  302. package/kotlin/fixtures/import-values/Values.d.kt.ts +11 -0
  303. package/kotlin/fixtures/import-values/Values.kt +66 -0
  304. package/kotlin/fixtures/import-values/app/_layout.tsx +4 -0
  305. package/kotlin/fixtures/import-values/app/index+spa.tsx +1 -0
  306. package/kotlin/fixtures/import-values/package.json +23 -0
  307. package/kotlin/fixtures/import-values/tsconfig.json +20 -0
  308. package/kotlin/fixtures/import-values/vite.config.ts +20 -0
  309. package/kotlin/fixtures/kotlin-app-variants/BarBehavior.kt +38 -0
  310. package/kotlin/fixtures/kotlin-app-variants/BarVisibility.kt +36 -0
  311. package/kotlin/fixtures/kotlin-app-variants/Ime.kt +3 -1
  312. package/kotlin/fixtures/kotlin-app-variants/TransientInsets.kt +50 -0
  313. package/kotlin/fork/NOTICE +6 -1
  314. package/kotlin/fork/README.md +15 -7
  315. package/kotlin/fork/build.sh +2 -0
  316. package/kotlin/fork/compose-worker-globals.patch +186 -4
  317. package/kotlin/fork/fork.json +2 -2
  318. package/kotlin/fork/skiko-worker-clock.patch +12 -0
  319. package/kotlin/toolchain.json +12 -12
  320. package/kotlin/tools/expo-types.main.kts +115 -0
  321. package/package.json +17 -23
  322. package/scripts/dev-server-scanner.ts +92 -66
  323. package/skills/contrast/SKILL.md +2 -2
  324. package/skills/peach-debug/SKILL.md +1 -1
  325. package/skills/peach-perf/SKILL.md +1 -1
  326. package/skills/peach-setup/SKILL.md +2 -1
  327. package/skills/peach-test/SKILL.md +8 -0
  328. package/src/assetCatalogContract.ts +43 -1
  329. package/src/bridge-contract-input.ts +46 -19
  330. package/src/bridge-contract.ts +0 -1
  331. package/src/bundle-channel.mjs +197 -84
  332. package/src/bundleGlobalFooter.ts +38 -0
  333. package/src/capture-contract.ts +107 -33
  334. package/src/cloud-contract.ts +5 -1
  335. package/src/cloud.ts +5 -2
  336. package/src/config.ts +22 -3
  337. package/src/configured-bundle-producer.ts +1 -1
  338. package/src/desktop-host-delivery.ts +95 -1
  339. package/src/expo-kotlin-bundle.ts +29 -0
  340. package/src/expo-kotlin-host.ts +201 -0
  341. package/src/expo-swift-host.ts +96 -76
  342. package/src/expoKotlinContract.ts +70 -0
  343. package/src/expoSwiftContract.ts +4 -25
  344. package/src/home-paths.ts +7 -4
  345. package/src/host/bridge-host.ts +23 -3
  346. package/src/host/fetch-proxy-handler.ts +13 -0
  347. package/src/host/fetch-proxy-overrides.ts +11 -0
  348. package/src/host/replacement-module-handler.ts +5 -2
  349. package/src/index.ts +3 -1
  350. package/src/kotlin-host.ts +463 -19
  351. package/src/metro-plugin.ts +56 -28
  352. package/src/metro-production-bundle.ts +2 -2
  353. package/src/native-app-identity-project.ts +190 -0
  354. package/src/native-app-identity.ts +398 -34
  355. package/src/native-firebase-config.ts +69 -15
  356. package/src/native-seam-manifest.ts +6 -0
  357. package/src/one-widget-discovery.ts +2 -1
  358. package/src/openstep-plist.ts +107 -0
  359. package/src/react-native-host-modules.ts +4 -0
  360. package/src/runtime-assets.ts +2 -2
  361. package/src/sim-client.ts +2 -2
  362. package/src/swift-binary-modules.ts +3 -1
  363. package/src/swift-compile.ts +286 -38
  364. package/src/swift-distribution-contract.ts +4 -0
  365. package/src/swift-distribution.lock.json +123 -12
  366. package/src/swift-distribution.ts +7 -3
  367. package/src/swift-host.ts +298 -83
  368. package/src/swift-package-manifest.ts +29 -2
  369. package/src/swift-package.ts +180 -10
  370. package/src/swift-packages.ts +4 -0
  371. package/src/swift-standin-emit.ts +4 -1
  372. package/src/swift-standins.ts +274 -15
  373. package/src/swift-submit.ts +62 -7
  374. package/src/swift-toolchain.ts +6 -1
  375. package/src/swiftContract.ts +126 -3
  376. package/src/vite-plugin-one.ts +13 -16
  377. package/src/vite-plugin-swift.ts +4 -5
  378. package/src/vite-plugin.ts +360 -144
  379. package/src/vite.d.ts +1 -1
  380. package/src/worker-system-chunks.ts +221 -0
  381. package/src/worklet-executable.ts +348 -38
  382. package/src/worklets-babel.ts +1 -1
  383. package/src/xcode-project.ts +243 -127
  384. package/dist-lib/agent-identity.cjs +0 -39
  385. package/dist-lib/agent-sessions.cjs +0 -760
  386. package/dist-lib/cli-constants.cjs +0 -32
  387. package/dist-lib/render-mode.cjs +0 -44
  388. package/kotlin/AppSources/android/view/View.kt +0 -74
  389. package/kotlin/AppSources/android/widget/FrameLayout.kt +0 -6
  390. package/src/render-mode.ts +0 -15
  391. /package/kotlin/{AppSources → AndroidViewSources}/android/content/Context.kt +0 -0
  392. /package/kotlin/{AppSources → AndroidViewSources}/android/content/res/Configuration.kt +0 -0
  393. /package/kotlin/{AppSources → AndroidViewSources}/android/graphics/Color.kt +0 -0
  394. /package/kotlin/{AppSources → AndroidViewSources}/android/util/DisplayMetrics.kt +0 -0
  395. /package/kotlin/{AppSources → AndroidViewSources}/dev/peach/app/JavaFormat.kt +0 -0
  396. /package/kotlin/{AppSources → Sources}/java/lang/Runnable.kt +0 -0
package/src/swift-host.ts CHANGED
@@ -8,7 +8,8 @@ import {
8
8
  enumerateBundleColors,
9
9
  enumerateBundleSymbols,
10
10
  enumerateBundleImages,
11
- enumerateBundleJson,
11
+ enumerateBundleResources,
12
+ resolveSwiftImageResourceUrls,
12
13
  } from '../../sootsim-swift/src/bundleAssets'
13
14
  import { authHeaderValue, resolveCliAuth } from '../cli/auth'
14
15
  import { resolveContrastBackendOrigin } from './backend-origin'
@@ -25,7 +26,15 @@ import {
25
26
  swiftApplicationEntry,
26
27
  } from './swift-compile'
27
28
  import { swiftDistributionRoot, swiftModuleToolchain } from './swift-distribution'
28
- import { swiftImplicitResourcePaths, type SwiftPackageTarget } from './swift-package'
29
+ import {
30
+ swiftImplicitResourcePaths,
31
+ swiftMetalSourceFiles,
32
+ swiftResourceBundles,
33
+ swiftResourceBundleForFile,
34
+ swiftResourceBundleInfoPlist,
35
+ type SwiftPackageTarget,
36
+ } from './swift-package'
37
+ import { swiftPackageManifest } from './swift-package-manifest'
29
38
  import {
30
39
  REMOTE_CHECKOUTS,
31
40
  resolveSwiftPackages,
@@ -36,6 +45,7 @@ import {
36
45
  import { readPackageFile } from './swift-source-file'
37
46
  import {
38
47
  standinGenerationInputs,
48
+ standinLibrary,
39
49
  swiftStandins,
40
50
  type SwiftStandin,
41
51
  } from './swift-standins'
@@ -45,6 +55,9 @@ import {
45
55
  MAX_SWIFT_COMPILE_RESOURCES,
46
56
  MAX_SWIFT_COMPILE_RESOURCE_BYTES,
47
57
  MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES,
58
+ MAX_SWIFT_COMPILE_METAL_FILES,
59
+ MAX_SWIFT_COMPILE_METAL_BYTES,
60
+ MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES,
48
61
  MAX_SWIFT_COMPILE_IMAGES,
49
62
  MAX_SWIFT_COMPILE_IMAGE_BYTES,
50
63
  MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES,
@@ -64,9 +77,10 @@ import type { SwiftEntryModuleArgs } from '../../sootsim-swift/src/entryModule'
64
77
  import type {
65
78
  AppCatalogColor,
66
79
  SfSymbolVector,
67
- SwiftImageSource,
80
+ SwiftImageResources,
68
81
  } from './assetCatalogContract'
69
82
  import type { SwiftCompileInput, SwiftIcuAsset } from './swift-compile'
83
+ import type { SwiftMetalLibrarySource, SwiftResourceBundle } from './swiftContract'
70
84
  import type { ServerResponse } from 'node:http'
71
85
 
72
86
  const ARTIFACT_PATH = '/__peach/swift/'
@@ -135,7 +149,7 @@ export interface SwiftArtifact {
135
149
  // rather than from whichever of them ran first.
136
150
  stamp: string
137
151
  package: {
138
- resources: Omit<SwiftResourceTable, 'images'>
152
+ resources: Omit<SwiftResourceTable, 'images' | 'metalUploads'>
139
153
  bundleFiles: SwiftBundlePack
140
154
  native: SwiftNativeModules | null
141
155
  }
@@ -194,6 +208,8 @@ export function projectFor(
194
208
  interface XcodeProjectEntry {
195
209
  xcodeproj: string
196
210
  target?: string
211
+ /** the build configuration a selected scheme runs; xcode's default otherwise. */
212
+ configuration?: string
197
213
  /** peach's own modules: a remote product named one links it, never its source. */
198
214
  provided: ReadonlySet<string> | null
199
215
  /** the module root a local compile links, which builds binary stand-ins. */
@@ -220,12 +236,14 @@ export function openXcodeProject(
220
236
  xcodeproj: string,
221
237
  target: string | undefined,
222
238
  moduleRoot: string | undefined,
239
+ configuration?: string,
223
240
  ): string {
224
- const app = readXcodeAppTarget(xcodeproj, target)
241
+ const app = readXcodeAppTarget(xcodeproj, target, configuration)
225
242
  const root = app.rootDir
226
243
  xcodeProjects.set(root, {
227
244
  xcodeproj,
228
245
  target: app.name,
246
+ configuration: app.configuration,
229
247
  provided: moduleRoot ? new Set(swiftPeachModules(moduleRoot)) : null,
230
248
  moduleRoot: moduleRoot ?? null,
231
249
  })
@@ -240,6 +258,7 @@ function swiftPackages(
240
258
  packages: SwiftPackages
241
259
  standins: SwiftStandin[]
242
260
  projectGaps: Map<string, string>
261
+ binaries: SwiftPackageBinary[]
243
262
  } {
244
263
  const stamp = (file: string | null) =>
245
264
  file && fs.existsSync(file) ? fs.statSync(file).mtimeMs : 0
@@ -328,7 +347,7 @@ function swiftPackages(
328
347
  cached.standinKey = generation
329
348
  }
330
349
  }
331
- return cached
350
+ return { ...cached, binaries: reached }
332
351
  }
333
352
 
334
353
  // the app target's sources compile as one executable target under this
@@ -361,24 +380,50 @@ interface XcodeLayout {
361
380
  targets: (SwiftPackageTarget & { exclude: string[] })[]
362
381
  packages: SwiftPackages
363
382
  standins: SwiftStandin[]
383
+ /** the binary targets the stand-ins come from. */
384
+ binaries: SwiftPackageBinary[]
364
385
  /** why a framework the project vendors got no stand-in, by name. */
365
386
  projectGaps: Map<string, string>
366
387
  /** the input directory each app and framework source compiles under. */
367
388
  targetDirs: Map<string, string>
389
+ resourceBundles: SwiftResourceBundle[]
368
390
  files: string[]
369
391
  }
370
392
 
371
393
  function xcodeLayout(root: string): XcodeLayout | null {
372
394
  const registered = xcodeProjects.get(root)
373
395
  if (!registered) return null
374
- const app = readXcodeAppTarget(registered.xcodeproj, registered.target)
375
- const files = new Set([...app.projectFiles, ...app.sources, ...app.resources])
396
+ const app = readXcodeAppTarget(
397
+ registered.xcodeproj,
398
+ registered.target,
399
+ registered.configuration,
400
+ )
401
+ const appSources = app.allSources.filter(
402
+ (file) => file.endsWith('.swift') || file.endsWith('.metal'),
403
+ )
404
+ const files = new Set([...app.projectFiles, ...appSources, ...app.resources])
376
405
  if (app.infoPlistFile) files.add(app.infoPlistFile)
377
- const targetDirs = new Map(app.sources.map((file) => [file, XCODE_APP_DIR]))
406
+ const targetDirs = new Map(
407
+ [...appSources, ...app.resources].map((file) => [file, XCODE_APP_DIR]),
408
+ )
409
+ const resourceBundles: SwiftResourceBundle[] = [
410
+ { target: app.moduleName, sourcePath: XCODE_APP_DIR, path: '.' },
411
+ ]
378
412
  const targets: XcodeLayout['targets'] = []
379
413
  for (const framework of app.frameworks) {
380
414
  const dir = path.posix.join(XCODE_FRAMEWORKS_DIR, framework.moduleName)
381
- for (const file of framework.sources) {
415
+ resourceBundles.push({
416
+ target: framework.moduleName,
417
+ sourcePath: dir,
418
+ path: `Frameworks/${framework.moduleName}.framework`,
419
+ })
420
+ for (const file of framework.allSources) {
421
+ if (!file.endsWith('.swift') && !file.endsWith('.metal')) continue
422
+ if (targetDirs.has(file)) continue
423
+ targetDirs.set(file, dir)
424
+ files.add(file)
425
+ }
426
+ for (const file of framework.resources) {
382
427
  if (targetDirs.has(file)) continue
383
428
  targetDirs.set(file, dir)
384
429
  files.add(file)
@@ -391,9 +436,10 @@ function xcodeLayout(root: string): XcodeLayout | null {
391
436
  exclude: [],
392
437
  languageMode: framework.languageMode,
393
438
  mainActorIsolation: framework.mainActorIsolation,
439
+ defines: framework.defines,
394
440
  })
395
441
  }
396
- const { packages, standins, projectGaps } = swiftPackages(registered, app)
442
+ const { packages, standins, projectGaps, binaries } = swiftPackages(registered, app)
397
443
  for (const standin of standins)
398
444
  targets.push({
399
445
  name: standin.module,
@@ -404,6 +450,9 @@ function xcodeLayout(root: string): XcodeLayout | null {
404
450
  languageMode: 5,
405
451
  mainActorIsolation: false,
406
452
  })
453
+ // xcode builds packages in swiftpm's debug configuration for Debug, which
454
+ // defines DEBUG, and in release for any other, as its package compiles show
455
+ const packageConfiguration = app.configuration === 'Debug' ? 'debug' : 'release'
407
456
  for (const target of packages.targets) {
408
457
  const relative = path.relative(
409
458
  target.remote ? path.join(root, REMOTE_CHECKOUTS) : root,
@@ -420,7 +469,24 @@ function xcodeLayout(root: string): XcodeLayout | null {
420
469
  ...target,
421
470
  path: target.remote ? path.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
422
471
  exclude: [],
472
+ defines: [
473
+ ...(packageConfiguration === 'debug' ? ['DEBUG'] : []),
474
+ ...target.packageDefines
475
+ .filter(
476
+ (define) =>
477
+ define.configuration === null ||
478
+ define.configuration === packageConfiguration,
479
+ )
480
+ .map((define) => define.name),
481
+ ],
423
482
  })
483
+ if (target.resources) {
484
+ resourceBundles.push({
485
+ target: target.name,
486
+ sourcePath: target.remote ? path.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
487
+ path: `${swiftPackageManifest(target.packageDir).name}_${target.name}.bundle`,
488
+ })
489
+ }
424
490
  if (!target.remote) files.add(path.join(target.packageDir, 'Package.swift'))
425
491
  for (const file of target.files) files.add(file)
426
492
  }
@@ -436,8 +502,10 @@ function xcodeLayout(root: string): XcodeLayout | null {
436
502
  targets,
437
503
  packages,
438
504
  standins,
505
+ binaries,
439
506
  projectGaps,
440
507
  targetDirs,
508
+ resourceBundles,
441
509
  files: [...files].sort(),
442
510
  }
443
511
  }
@@ -445,16 +513,24 @@ function xcodeLayout(root: string): XcodeLayout | null {
445
513
  // the manifest the compile reads for an xcode app: the app target and each
446
514
  // framework and package target, in the forms swiftManifestTargets scans.
447
515
  function xcodeManifest(layout: XcodeLayout): string {
448
- const settings = (mode: number, mainActor: boolean) =>
449
- `swiftSettings: [.swiftLanguageMode(.v${mode})${mainActor ? ', .defaultIsolation(MainActor.self)' : ''}]`
516
+ const settings = (target: {
517
+ languageMode: number
518
+ mainActorIsolation: boolean
519
+ defines?: string[]
520
+ }) =>
521
+ `swiftSettings: [${[
522
+ `.swiftLanguageMode(.v${target.languageMode})`,
523
+ ...(target.mainActorIsolation ? ['.defaultIsolation(MainActor.self)'] : []),
524
+ ...(target.defines ?? []).map((name) => `.define(${JSON.stringify(name)})`),
525
+ ].join(', ')}]`
450
526
  return [
451
527
  '// swift-tools-version: 6.2',
452
528
  'import PackageDescription',
453
529
  'let package = Package(name: "app", targets: [',
454
- ` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app.languageMode, layout.app.mainActorIsolation)}),`,
530
+ ` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app)}),`,
455
531
  ...layout.targets.map(
456
532
  (target) =>
457
- ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ''}${target.resources ? 'resources: [], ' : ''}${settings(target.languageMode, target.mainActorIsolation)}),`,
533
+ ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ''}${target.resources ? 'resources: [], ' : ''}${settings(target)}),`,
458
534
  ),
459
535
  '])',
460
536
  '',
@@ -511,10 +587,12 @@ export function sourceFiles(root: string): string[] {
511
587
  return packageFiles(root).filter((file) => file.endsWith('.swift'))
512
588
  }
513
589
 
590
+ // project files and the xcconfigs their settings read are build inputs, never resources
514
591
  function resourceCandidateFiles(root: string): string[] {
515
592
  return packageFiles(root).filter(
516
593
  (file) =>
517
594
  !file.endsWith('.swift') &&
595
+ !file.endsWith('.xcconfig') &&
518
596
  !['project.pbxproj', 'project.xcproj'].includes(path.basename(file)),
519
597
  )
520
598
  }
@@ -526,7 +604,11 @@ export function swiftProjectAppInfo(packagePath: string): {
526
604
  } {
527
605
  const registered = xcodeProjects.get(packagePath)
528
606
  const app = registered
529
- ? readXcodeAppTarget(registered.xcodeproj, registered.target)
607
+ ? readXcodeAppTarget(
608
+ registered.xcodeproj,
609
+ registered.target,
610
+ registered.configuration,
611
+ )
530
612
  : null
531
613
  const files = app?.resources ?? resourceCandidateFiles(packagePath)
532
614
  const catalogs = files.filter(
@@ -616,10 +698,12 @@ const RESOURCE_CONTENT_TYPES: Record<string, string> = {
616
698
  }
617
699
 
618
700
  export interface SwiftResourceTable {
619
- /** bundle asset name to its absolute serving url and scale. */
620
- table: Record<string, SwiftImageSource>
701
+ /** each bundle's asset names to their serving urls and scales. */
702
+ table: SwiftImageResources
621
703
  /** the same rasters as compile-address inputs. */
622
704
  images: Record<string, SwiftImageUpload>
705
+ metalSources: Record<string, SwiftMetalLibrarySource>
706
+ metalUploads: Record<string, string>
623
707
  /** asset-catalog color name to its value. */
624
708
  colors: Record<string, AppCatalogColor>
625
709
  symbols: Record<string, SfSymbolVector>
@@ -634,6 +718,7 @@ export interface SwiftResourceTable {
634
718
  export function buildSwiftResourceTable(
635
719
  project: SwiftProject,
636
720
  baseUrl: string,
721
+ inputs: Record<string, string>,
637
722
  ): SwiftResourceTable {
638
723
  const limits = inputLimits(Boolean(project.hosted))
639
724
  const absolute = resourceCandidateFiles(project.packagePath)
@@ -650,15 +735,77 @@ export function buildSwiftResourceTable(
650
735
  'utf8',
651
736
  )
652
737
  }
653
- const found = enumerateBundleImages(relative, readContents)
654
- const colors = enumerateBundleColors(relative, readContents)
655
- const symbols = enumerateBundleSymbols(relative, readContents)
656
- const table: Record<string, SwiftImageSource> = {}
738
+ const layout = xcodeLayout(project.packagePath)
739
+ const bundles = layout?.resourceBundles ?? swiftResourceBundles(inputs, relative)
740
+ const catalogFiles = relative.filter((file) => {
741
+ const disk = byRelative.get(file)
742
+ return !disk || !layout?.targetDirs.get(disk)?.startsWith(`${XCODE_FRAMEWORKS_DIR}/`)
743
+ })
744
+ const found = enumerateBundleImages(relative, readContents, (file) => {
745
+ const disk = byRelative.get(file)
746
+ if (!disk) throw new Error(`image source ${file} has no input file`)
747
+ const key = layout ? xcodeInputKey(layout, disk, file) : file
748
+ return swiftResourceBundleForFile(bundles, key)?.path ?? '.'
749
+ })
750
+ const colors = enumerateBundleColors(catalogFiles, readContents)
751
+ const symbols = enumerateBundleSymbols(catalogFiles, readContents, (file) => {
752
+ const disk = byRelative.get(file)
753
+ if (!disk) throw new Error(`symbol source ${file} has no input file`)
754
+ const key = layout ? xcodeInputKey(layout, disk, file) : file
755
+ return swiftResourceBundleForFile(bundles, key)?.path ?? '.'
756
+ })
757
+ const table: SwiftImageResources = Object.create(null)
657
758
  const images: Record<string, SwiftImageUpload> = {}
759
+ const metalSources: Record<string, SwiftMetalLibrarySource> = {}
760
+ const metalUploads: Record<string, string> = {}
658
761
  const watched: string[] = []
659
762
  const registered = new Map<string, { bytes: Buffer; contentType: string }>()
763
+ const shaderFiles = relative.filter((file) => file.endsWith('.metal'))
764
+ const metalCandidates: Record<string, string> = {}
765
+ if (inputs['Package.swift'] !== undefined)
766
+ metalCandidates['Package.swift'] = inputs['Package.swift']
767
+ const metalInputs = new Map<string, { file: string; disk: string }>()
768
+ for (const file of shaderFiles) {
769
+ const disk = byRelative.get(file)
770
+ if (!disk) throw new Error(`metal source ${file} has no input file`)
771
+ const key = layout ? xcodeInputKey(layout, disk, file) : file
772
+ metalCandidates[key] = ''
773
+ metalInputs.set(key, { file, disk })
774
+ }
775
+ const metalFiles = Object.keys(swiftMetalSourceFiles(metalCandidates))
776
+ if (metalFiles.length > MAX_SWIFT_COMPILE_METAL_FILES)
777
+ throw new Error('metal source pack exceeds the compile service file cap')
778
+ let metalBytes = 0
779
+ for (const key of metalFiles) {
780
+ const input = metalInputs.get(key)
781
+ if (!input) throw new Error(`metal source ${key} has no input file`)
782
+ const { file, disk } = input
783
+ const bytes = readPackageFile(
784
+ project.packagePath,
785
+ disk,
786
+ MAX_SWIFT_COMPILE_METAL_BYTES,
787
+ )
788
+ metalBytes += bytes.length
789
+ if (metalBytes > MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES)
790
+ throw new Error('metal source pack exceeds the compile service caps')
791
+ const source = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(
792
+ bytes,
793
+ )
794
+ const sha256 = createHash('sha256').update(bytes).digest('hex')
795
+ const bundle = swiftResourceBundleForFile(bundles, key)
796
+ if (!bundle && inputs['Package.swift'])
797
+ throw new Error(`metal source ${key} has no resource target bundle`)
798
+ metalSources[key] = {
799
+ sha256,
800
+ url: `${baseUrl}${RESOURCE_PATH}${sha256}.metal`,
801
+ bundlePath: bundle?.path ?? '.',
802
+ }
803
+ metalUploads[key] = source
804
+ watched.push(file)
805
+ registered.set(`${sha256}.metal`, { bytes, contentType: 'text/plain; charset=utf-8' })
806
+ }
660
807
  let imageBytes = 0
661
- for (const { name, file, scale } of found) {
808
+ for (const { name, file, scale, bundlePath } of found) {
662
809
  const disk = byRelative.get(file)
663
810
  if (!disk) continue
664
811
  if (
@@ -671,8 +818,12 @@ export function buildSwiftResourceTable(
671
818
  imageBytes += bytes.length
672
819
  const hash = createHash('sha256').update(bytes).digest('hex').slice(0, 16)
673
820
  const ext = path.posix.extname(file).toLowerCase()
674
- table[name] = { uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale }
675
- images[name] = {
821
+ const bundle = table[bundlePath] ?? Object.create(null)
822
+ const variants = (bundle[name] ??= [])
823
+ variants.push({ uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale })
824
+ table[bundlePath] = bundle
825
+ const key = layout ? xcodeInputKey(layout, disk, file) : file
826
+ images[key] = {
676
827
  file: path.posix.basename(file),
677
828
  data: bytes.toString('base64'),
678
829
  }
@@ -700,19 +851,17 @@ export function buildSwiftResourceTable(
700
851
  project.resourcesPrevious = project.resourceFiles
701
852
  project.resourceFiles = registered
702
853
  }
703
- return { table, images, colors, symbols, watched }
854
+ return { table, images, metalSources, metalUploads, colors, symbols, watched }
704
855
  }
705
856
 
706
- // the /res pack: every Resources/ json in the package, basename-keyed and
707
- // base64, riding the entry module so the mount serves it without a fetch.
708
- // the namespace is flat like the bundle the wasm side reads: shallower
709
- // paths pack first (the Resources root is the bundle root) with a lexical
710
- // tiebreak, and the first spelling of a basename wins a collision. data json
857
+ // copied resources ride the entry module as base64 in their target bundle.
858
+ // each bundle keeps the existing shallow-first basename collision rule.
711
859
  // bundle caps match the hosted compiler; oversized input refuses before reading.
712
860
 
713
861
  export interface SwiftBundlePack {
714
- /** basename to base64 bytes for the mount's /res. */
862
+ /** bundle-relative path to base64 bytes for the mount's /res. */
715
863
  files: Record<string, string>
864
+ bundles: SwiftResourceBundle[]
716
865
  /** project-relative json files this load's pack covers (for watching). */
717
866
  watched: string[]
718
867
  }
@@ -720,6 +869,7 @@ export interface SwiftBundlePack {
720
869
  export function buildSwiftBundleFiles(
721
870
  packagePath: string,
722
871
  hosted: boolean,
872
+ inputs?: Record<string, string>,
723
873
  ): SwiftBundlePack {
724
874
  packagePath = fs.realpathSync(packagePath)
725
875
  const limits = inputLimits(hosted)
@@ -733,33 +883,57 @@ export function buildSwiftBundleFiles(
733
883
  const watched: string[] = []
734
884
  let total = 0
735
885
  const xcode = xcodeLayout(packagePath)
886
+ const bundles =
887
+ xcode?.resourceBundles ??
888
+ swiftResourceBundles(inputs ?? packageSources(packagePath), relative)
889
+ const addFile = (key: string, bytes: Buffer) => {
890
+ if (
891
+ Object.keys(files).length >= limits.resources ||
892
+ bytes.length > limits.resourceBytes ||
893
+ total + bytes.length > limits.resourceTotalBytes
894
+ )
895
+ throw new Error(
896
+ `swift bundle pack exceeds ${limits.resources} files / ${limits.resourceTotalBytes} bytes`,
897
+ )
898
+ files[key] = bytes.toString('base64')
899
+ total += bytes.length
900
+ }
736
901
  if (xcode) {
737
902
  const bytes = Buffer.from(xcode.app.infoPlist)
738
903
  if (bytes.length > limits.resourceBytes || bytes.length > limits.resourceTotalBytes)
739
904
  throw new Error('swift launch Info.plist exceeds bundle resource limits')
740
- files['Info.plist'] = bytes.toString('base64')
741
- total += bytes.length
905
+ addFile('Info.plist', bytes)
742
906
  if (xcode.app.infoPlistFile)
743
907
  watched.push(
744
908
  path.relative(packagePath, xcode.app.infoPlistFile).split(path.sep).join('/'),
745
909
  )
746
910
  }
747
- for (const { base, file } of enumerateBundleJson(relative)) {
748
- watched.push(file)
911
+ const groups = new Map<string, string[]>()
912
+ for (const file of relative) {
749
913
  const disk = path.join(packagePath, ...file.split('/'))
750
- if (
751
- Object.keys(files).length >= limits.resources ||
752
- total + fs.statSync(disk).size > limits.resourceTotalBytes
753
- ) {
754
- throw new Error(
755
- `swift bundle pack exceeds ${limits.resources} files / ${limits.resourceTotalBytes} bytes`,
756
- )
914
+ const key = xcode ? xcodeInputKey(xcode, disk, file) : file
915
+ const bundle = swiftResourceBundleForFile(bundles, key)
916
+ const bundlePath = bundle?.path ?? '.'
917
+ const group = groups.get(bundlePath) ?? []
918
+ group.push(file)
919
+ groups.set(bundlePath, group)
920
+ }
921
+ for (const bundle of bundles) {
922
+ if (bundle.path === '.') continue
923
+ addFile(
924
+ `${bundle.path}/Info.plist`,
925
+ Buffer.from(swiftResourceBundleInfoPlist(bundle)),
926
+ )
927
+ }
928
+ for (const [bundlePath, paths] of groups) {
929
+ for (const { base, file } of enumerateBundleResources(paths)) {
930
+ watched.push(file)
931
+ const disk = path.join(packagePath, ...file.split('/'))
932
+ const bytes = readPackageFile(packagePath, disk, limits.resourceBytes)
933
+ addFile(bundlePath === '.' ? base : `${bundlePath}/${base}`, bytes)
757
934
  }
758
- const bytes = readPackageFile(packagePath, disk, limits.resourceBytes)
759
- files[base] = bytes.toString('base64')
760
- total += bytes.length
761
935
  }
762
- return { files, watched }
936
+ return { files, bundles, watched }
763
937
  }
764
938
 
765
939
  // the middleware's lookup, exported for the producer's own proof: a hit is
@@ -848,7 +1022,29 @@ export function icuUrl(origin: string, artifact: SwiftArtifact): string {
848
1022
  : `${origin}${ICU_PATH}${artifact.icu.sha256}`
849
1023
  }
850
1024
 
851
- function packageSources(packagePath: string): Record<string, string> {
1025
+ // a c stand-in whose framework has a WebAssembly build links that library,
1026
+ // keyed by the stand-in target it links into; its own source then defines
1027
+ // nothing, so the library's functions run instead of the traps. one library
1028
+ // links once, through the first module its framework ships.
1029
+ function standinLibraries(layout: XcodeLayout): Map<string, SwiftStandin[]> {
1030
+ const linked = new Map<string, SwiftStandin[]>()
1031
+ for (const binary of layout.binaries) {
1032
+ const modules = layout.standins.filter(
1033
+ (standin) =>
1034
+ standin.target === binary.target && `${standin.module}.c` in standin.files,
1035
+ )
1036
+ if (modules.length === 0) continue
1037
+ const library = standinLibrary(binary, layout.app.rootDir)
1038
+ if (!library) continue
1039
+ linked.set(library, modules)
1040
+ }
1041
+ return linked
1042
+ }
1043
+
1044
+ function packageSources(
1045
+ packagePath: string,
1046
+ linked: ReadonlySet<SwiftStandin> = new Set(),
1047
+ ): Record<string, string> {
852
1048
  const xcode = xcodeLayout(packagePath)
853
1049
  const files: Record<string, string> = {}
854
1050
  for (const file of sourceFiles(packagePath)) {
@@ -864,7 +1060,10 @@ function packageSources(packagePath: string): Record<string, string> {
864
1060
  files['Package.swift'] = xcodeManifest(xcode)
865
1061
  for (const standin of xcode.standins)
866
1062
  for (const [file, text] of Object.entries(standin.files))
867
- files[path.posix.join(XCODE_STANDINS_DIR, standin.module, file)] = text
1063
+ files[path.posix.join(XCODE_STANDINS_DIR, standin.module, file)] =
1064
+ linked.has(standin) && file === `${standin.module}.c`
1065
+ ? `// ${standin.target}'s WebAssembly library defines ${standin.module}'s functions.\n`
1066
+ : text
868
1067
  }
869
1068
  return files
870
1069
  }
@@ -877,11 +1076,13 @@ interface SwiftPackageSnapshot {
877
1076
  bundleFiles: SwiftBundlePack
878
1077
  native: SwiftNativeModules | null
879
1078
  glue?: string
1079
+ libraries?: Record<string, string>
880
1080
  }
881
1081
 
882
1082
  function packageSnapshot(project: SwiftProject, entry: string): SwiftPackageSnapshot {
883
- const files = packageSources(project.packagePath)
884
1083
  const layout = xcodeLayout(project.packagePath)
1084
+ const linked = layout ? standinLibraries(layout) : new Map<string, SwiftStandin[]>()
1085
+ const files = packageSources(project.packagePath, new Set([...linked.values()].flat()))
885
1086
  const native = nativeSourceDescriptor(project.packagePath)
886
1087
  return {
887
1088
  files,
@@ -889,13 +1090,33 @@ function packageSnapshot(project: SwiftProject, entry: string): SwiftPackageSnap
889
1090
  ? xcodeInputKey(layout, path.resolve(project.packagePath, entry), entry)
890
1091
  : entry,
891
1092
  resourcePaths: swiftImplicitResourcePaths(
892
- resourceCandidateFiles(project.packagePath).map((file) =>
893
- path.relative(project.packagePath, file).split(path.sep).join(path.posix.sep),
894
- ),
1093
+ resourceCandidateFiles(project.packagePath).map((file) => {
1094
+ const relative = path
1095
+ .relative(project.packagePath, file)
1096
+ .split(path.sep)
1097
+ .join(path.posix.sep)
1098
+ return layout && file.endsWith('.metal')
1099
+ ? xcodeInputKey(layout, file, relative)
1100
+ : relative
1101
+ }),
1102
+ ),
1103
+ resources: buildSwiftResourceTable(project, '', files),
1104
+ bundleFiles: buildSwiftBundleFiles(
1105
+ project.packagePath,
1106
+ Boolean(project.hosted),
1107
+ files,
895
1108
  ),
896
- resources: buildSwiftResourceTable(project, ''),
897
- bundleFiles: buildSwiftBundleFiles(project.packagePath, Boolean(project.hosted)),
898
1109
  native,
1110
+ ...(linked.size > 0
1111
+ ? {
1112
+ libraries: Object.fromEntries(
1113
+ [...linked].map(([library, [first]]) => [
1114
+ first!.module,
1115
+ fs.readFileSync(library).toString('base64'),
1116
+ ]),
1117
+ ),
1118
+ }
1119
+ : {}),
899
1120
  ...(native
900
1121
  ? {
901
1122
  glue: readPackageFile(
@@ -911,11 +1132,14 @@ function packageSnapshot(project: SwiftProject, entry: string): SwiftPackageSnap
911
1132
  function snapshotCompileInput(snapshot: SwiftPackageSnapshot): SwiftCompileInput {
912
1133
  const input: SwiftCompileInput = {
913
1134
  files: snapshot.files,
1135
+ metalSources: snapshot.resources.metalUploads,
914
1136
  resourcePaths: snapshot.resourcePaths,
1137
+ resourceBundles: snapshot.bundleFiles.bundles,
915
1138
  resources: snapshot.bundleFiles.files,
916
1139
  images: snapshot.resources.images,
917
1140
  entry: snapshot.entry,
918
1141
  oneModule: true,
1142
+ ...(snapshot.libraries ? { libraries: snapshot.libraries } : {}),
919
1143
  }
920
1144
  return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input
921
1145
  }
@@ -935,6 +1159,7 @@ async function compile(
935
1159
  table: snapshot.resources.table,
936
1160
  colors: snapshot.resources.colors,
937
1161
  symbols: snapshot.resources.symbols,
1162
+ metalSources: snapshot.resources.metalSources,
938
1163
  watched: snapshot.resources.watched,
939
1164
  }
940
1165
  const content = {
@@ -1066,15 +1291,6 @@ export function swiftApiGapReport(output: string): string | null {
1066
1291
  ].join('\n')
1067
1292
  }
1068
1293
 
1069
- // the platform modules peach decided not to provide (plans/partners/triumph/
1070
- // arcade-gaps.md, report 2): a shipped Darwin module would flip every
1071
- // `canImport(Darwin)` branch in every dependency.
1072
- const UNPROVIDED_PLATFORM_MODULES: Record<string, string> = {
1073
- Darwin:
1074
- 'Peach compiles for WebAssembly, which has no Darwin; C library names come through Foundation',
1075
- MachO: 'Peach compiles for WebAssembly, which has no Mach-O images',
1076
- }
1077
-
1078
1294
  // the frameworks the iOS simulator SDK ships, so a report can say which
1079
1295
  // missing modules are Apple's on any host, linux included. regenerated by
1080
1296
  // scripts/ios-sdk-frameworks.ts.
@@ -1099,21 +1315,14 @@ async function missingModulesMessage(
1099
1315
  ] as const
1100
1316
  }),
1101
1317
  ...[...missing.keys()].flatMap((name) =>
1102
- UNPROVIDED_PLATFORM_MODULES[name]
1318
+ IOS_SDK_FRAMEWORKS.has(name)
1103
1319
  ? [
1104
1320
  [
1105
1321
  name,
1106
- { source: 'the iOS SDK', reason: UNPROVIDED_PLATFORM_MODULES[name]! },
1322
+ { source: 'the iOS SDK', reason: 'a framework Peach does not provide' },
1107
1323
  ] as const,
1108
1324
  ]
1109
- : IOS_SDK_FRAMEWORKS.has(name)
1110
- ? [
1111
- [
1112
- name,
1113
- { source: 'the iOS SDK', reason: 'a framework Peach does not provide' },
1114
- ] as const,
1115
- ]
1116
- : [],
1325
+ : [],
1117
1326
  ),
1118
1327
  ...(layout?.packages.modules ?? []),
1119
1328
  ...(layout?.packages.unavailable ?? []),
@@ -1123,9 +1332,7 @@ async function missingModulesMessage(
1123
1332
  // such as FirebaseCore ships inside _FirebaseCore with no target of its
1124
1333
  // own. the archives are read only for a module the sdk does not explain.
1125
1334
  const packaged = new Set(
1126
- [...missing.keys()].filter(
1127
- (name) => !UNPROVIDED_PLATFORM_MODULES[name] && !IOS_SDK_FRAMEWORKS.has(name),
1128
- ),
1335
+ [...missing.keys()].filter((name) => !IOS_SDK_FRAMEWORKS.has(name)),
1129
1336
  )
1130
1337
  if (packaged.size > 0)
1131
1338
  await Promise.all(
@@ -1209,7 +1416,9 @@ async function compileRemote(
1209
1416
  submit,
1210
1417
  {
1211
1418
  files: snapshot.files,
1419
+ metalSources: snapshot.resources.metalUploads,
1212
1420
  resourcePaths: snapshot.resourcePaths,
1421
+ resourceBundles: snapshot.bundleFiles.bundles,
1213
1422
  resources: snapshot.bundleFiles.files,
1214
1423
  images: snapshot.resources.images,
1215
1424
  entry: snapshot.entry,
@@ -1361,13 +1570,18 @@ export async function swiftPackageMetadata(
1361
1570
  hash: artifact.hash,
1362
1571
  icuUrl: icuUrl(origin, artifact),
1363
1572
  rootId: `${packageName}/${entry}`,
1364
- resources: Object.fromEntries(
1365
- Object.entries(resources.table).map(([name, image]) => [
1366
- name,
1367
- { ...image, uri: `${origin}${image.uri}` },
1368
- ]),
1369
- ),
1573
+ resources: resolveSwiftImageResourceUrls(resources.table, origin),
1370
1574
  bundleFiles: bundleFiles.files,
1575
+ ...(Object.keys(resources.metalSources).length === 0
1576
+ ? {}
1577
+ : {
1578
+ metalSources: Object.fromEntries(
1579
+ Object.entries(resources.metalSources).map(([file, source]) => [
1580
+ file,
1581
+ { ...source, url: `${origin}${source.url}` },
1582
+ ]),
1583
+ ),
1584
+ }),
1371
1585
  colors: resources.colors,
1372
1586
  symbols: resources.symbols,
1373
1587
  native: artifact.package.native
@@ -1375,6 +1589,7 @@ export async function swiftPackageMetadata(
1375
1589
  packageId: artifact.package.native.packageId,
1376
1590
  contractHash: artifact.package.native.hash,
1377
1591
  modules: artifact.package.native.modules,
1592
+ views: Object.keys(artifact.package.native.views),
1378
1593
  defaultView: mains.length === 1,
1379
1594
  }
1380
1595
  : undefined,