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
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.939 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! peach v0.1.1399 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
  let __sootsim_import_meta_url = '', __sootsim_import_meta_dirname = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; __sootsim_import_meta_dirname = __dirname; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -1404,21 +1404,367 @@ module.exports = __toCommonJS(vite_plugin_swift_exports);
1404
1404
  var import_node_fs17 = __toESM(require("node:fs"), 1);
1405
1405
  var import_node_path18 = __toESM(require("node:path"), 1);
1406
1406
 
1407
+ // ../sootsim-swift/src/bundleAssets.ts
1408
+ var import_svgpath = __toESM(require("svgpath"), 1);
1409
+
1410
+ // src/swiftContract.ts
1411
+ function isSwiftResourcePath(value) {
1412
+ return typeof value === "string" && value.length <= 4096 && !value.startsWith("/") && !value.includes("\\") && !value.includes("\0") && value.split("/").every((part) => part !== "" && part !== "." && part !== "..");
1413
+ }
1414
+ function isSwiftBundlePath(value) {
1415
+ return typeof value === "string" && (value === "." || isSwiftResourcePath(value) && /\.(bundle|framework)$/.test(value));
1416
+ }
1417
+ function isSwiftResourceBundles(value) {
1418
+ return Array.isArray(value) && value.length <= 128 && value.every(
1419
+ (bundle) => typeof bundle === "object" && bundle !== null && typeof bundle.target === "string" && /^[A-Za-z_][A-Za-z0-9_-]*$/.test(bundle.target) && (bundle.sourcePath === "." || isSwiftResourcePath(bundle.sourcePath)) && isSwiftBundlePath(bundle.path)
1420
+ ) && new Set(value.map((bundle) => bundle.target)).size === value.length && new Set(value.map((bundle) => bundle.path)).size === value.length;
1421
+ }
1422
+ function isSwiftMetalSources(value) {
1423
+ return typeof value === "object" && value !== null && !Array.isArray(value) && Object.entries(value).every(
1424
+ ([file, source]) => file.endsWith(".metal") && isSwiftResourcePath(file) && typeof source === "object" && source !== null && !Array.isArray(source) && "url" in source && typeof source.url === "string" && "sha256" in source && typeof source.sha256 === "string" && /^[a-f0-9]{64}$/.test(source.sha256)
1425
+ );
1426
+ }
1427
+ function isSwiftMetalLibrarySources(value) {
1428
+ return isSwiftMetalSources(value) && Object.values(value).every(
1429
+ (source) => "bundlePath" in source && isSwiftBundlePath(source.bundlePath)
1430
+ );
1431
+ }
1432
+
1433
+ // ../sootsim-swift/src/bundleAssets.ts
1434
+ var RASTER_EXTENSIONS = /* @__PURE__ */ new Set([
1435
+ ".avif",
1436
+ ".bmp",
1437
+ ".gif",
1438
+ ".ico",
1439
+ ".jpeg",
1440
+ ".jpg",
1441
+ ".png",
1442
+ ".webp"
1443
+ ]);
1444
+ function extOf(file) {
1445
+ const dot = file.lastIndexOf(".");
1446
+ return dot < 0 ? "" : file.slice(dot).toLowerCase();
1447
+ }
1448
+ function baseOf(file) {
1449
+ const slash = file.lastIndexOf("/");
1450
+ return slash < 0 ? file : file.slice(slash + 1);
1451
+ }
1452
+ function imagesetFiles(images) {
1453
+ return images.flatMap((image) => {
1454
+ if (typeof image.filename !== "string" || !RASTER_EXTENSIONS.has(extOf(image.filename)) || image.filename.includes("/") || image.filename.includes("\\"))
1455
+ return [];
1456
+ return [
1457
+ {
1458
+ filename: image.filename,
1459
+ scale: image.scale === "2x" ? 2 : image.scale === "3x" ? 3 : 1
1460
+ }
1461
+ ];
1462
+ }).sort((a, b) => a.scale - b.scale);
1463
+ }
1464
+ function flatScale(path18) {
1465
+ const match = /@([23])x\.[^./]+$/.exec(path18);
1466
+ return match ? Number(match[1]) : 1;
1467
+ }
1468
+ function providesNamespace(text3) {
1469
+ if (text3 === null) return false;
1470
+ try {
1471
+ const parsed = JSON.parse(text3);
1472
+ return parsed?.properties?.["provides-namespace"] === true;
1473
+ } catch {
1474
+ return false;
1475
+ }
1476
+ }
1477
+ function catalogEntryName(contentsPath, kind, readText) {
1478
+ const parts = contentsPath.split("/");
1479
+ const leaf2 = parts[parts.length - 2] ?? "";
1480
+ if (!leaf2.endsWith(kind)) return null;
1481
+ const short = leaf2.slice(0, -kind.length) || null;
1482
+ if (short === null) return null;
1483
+ const segments = [short];
1484
+ for (let depth = parts.length - 3; depth >= 0; depth -= 1) {
1485
+ const dir = parts[depth] ?? "";
1486
+ if (dir.endsWith(".xcassets") || dir === "" || dir === "." || dir === "..") break;
1487
+ const folderContents = [...parts.slice(0, depth + 1), "Contents.json"].join("/");
1488
+ if (providesNamespace(readText(folderContents))) segments.unshift(dir);
1489
+ }
1490
+ return segments.join("/");
1491
+ }
1492
+ function isFlatResourceImage(path18) {
1493
+ return path18.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path18));
1494
+ }
1495
+ function enumerateBundleImages(paths, readText, bundleForFile = () => ".") {
1496
+ const table = [];
1497
+ const seen = /* @__PURE__ */ new Map();
1498
+ const namesFor = (file) => {
1499
+ const bundlePath = bundleForFile(file);
1500
+ if (!isSwiftBundlePath(bundlePath))
1501
+ throw new Error(`invalid image bundle ${bundlePath}`);
1502
+ const names = seen.get(bundlePath) ?? /* @__PURE__ */ new Set();
1503
+ seen.set(bundlePath, names);
1504
+ return { bundlePath, names };
1505
+ };
1506
+ const catalogs = paths.filter((path18) => baseOf(path18) === "Contents.json");
1507
+ for (const contentsPath of catalogs) {
1508
+ const name2 = catalogEntryName(contentsPath, ".imageset", readText);
1509
+ if (name2 === null) continue;
1510
+ const { bundlePath, names } = namesFor(contentsPath);
1511
+ if (names.has(name2)) continue;
1512
+ let parsed;
1513
+ try {
1514
+ const text3 = readText(contentsPath);
1515
+ if (text3 === null) continue;
1516
+ parsed = JSON.parse(text3);
1517
+ } catch {
1518
+ continue;
1519
+ }
1520
+ const images = parsed?.images;
1521
+ if (!Array.isArray(images)) continue;
1522
+ const dir = contentsPath.split("/").slice(0, -1).join("/");
1523
+ const variants = imagesetFiles(images);
1524
+ if (variants.length === 0) continue;
1525
+ names.add(name2);
1526
+ for (const variant of variants)
1527
+ table.push({
1528
+ name: name2,
1529
+ file: `${dir}/${variant.filename}`,
1530
+ scale: variant.scale,
1531
+ bundlePath
1532
+ });
1533
+ }
1534
+ for (const path18 of paths) {
1535
+ if (!isFlatResourceImage(path18)) continue;
1536
+ const name2 = baseOf(path18).slice(0, -extOf(path18).length);
1537
+ const { bundlePath, names } = namesFor(path18);
1538
+ if (name2 === "" || names.has(name2)) continue;
1539
+ names.add(name2);
1540
+ table.push({ name: name2, file: path18, scale: flatScale(path18), bundlePath });
1541
+ }
1542
+ return table;
1543
+ }
1544
+ function colorComponent(value) {
1545
+ if (typeof value !== "string") return null;
1546
+ const parsed = value.startsWith("0x") ? Number.parseInt(value.slice(2), 16) / 255 : value.includes(".") ? Number.parseFloat(value) : Number.parseInt(value, 10) / 255;
1547
+ return Number.isFinite(parsed) ? parsed : null;
1548
+ }
1549
+ function colorsetValue(color) {
1550
+ if (typeof color !== "object" || color === null) return null;
1551
+ const reference = Reflect.get(color, "reference");
1552
+ if (typeof reference === "string") {
1553
+ return { system: reference.replace(/Color$/, "") };
1554
+ }
1555
+ const space = Reflect.get(color, "color-space");
1556
+ if (space !== "srgb" && space !== "extended-srgb") return null;
1557
+ const components = Reflect.get(color, "components");
1558
+ if (typeof components !== "object" || components === null) return null;
1559
+ const [red, green, blue, alpha] = ["red", "green", "blue", "alpha"].map(
1560
+ (key2) => colorComponent(Reflect.get(components, key2))
1561
+ );
1562
+ if (red === null || green === null || blue === null || alpha === null) return null;
1563
+ if (![red, green, blue].every((value) => value >= 0 && value <= 1)) return null;
1564
+ const byte = (value) => Math.round(value * 255);
1565
+ return `rgba(${byte(red)}, ${byte(green)}, ${byte(blue)}, ${alpha})`;
1566
+ }
1567
+ function enumerateBundleColors(paths, readText) {
1568
+ const table = {};
1569
+ for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
1570
+ const name2 = catalogEntryName(contentsPath, ".colorset", readText);
1571
+ if (name2 === null || name2 in table) continue;
1572
+ let colors;
1573
+ try {
1574
+ const text3 = readText(contentsPath);
1575
+ if (text3 === null) continue;
1576
+ colors = Reflect.get(JSON.parse(text3), "colors");
1577
+ } catch {
1578
+ continue;
1579
+ }
1580
+ if (!Array.isArray(colors)) continue;
1581
+ let light = null;
1582
+ let dark = null;
1583
+ for (const entry of colors) {
1584
+ if (typeof entry !== "object" || entry === null) continue;
1585
+ const idiom = Reflect.get(entry, "idiom");
1586
+ if (idiom !== "universal" && idiom !== "iphone") continue;
1587
+ const appearances = Reflect.get(entry, "appearances");
1588
+ const list2 = Array.isArray(appearances) ? appearances : [];
1589
+ if (list2.some((item) => Reflect.get(item, "appearance") === "contrast")) continue;
1590
+ const isDark = list2.some(
1591
+ (item) => Reflect.get(item, "appearance") === "luminosity" && Reflect.get(item, "value") === "dark"
1592
+ );
1593
+ if (list2.length > 0 && !isDark) continue;
1594
+ const value = colorsetValue(Reflect.get(entry, "color"));
1595
+ if (value === null) continue;
1596
+ if (isDark) dark = value;
1597
+ else light = value;
1598
+ }
1599
+ if (light === null) continue;
1600
+ if (typeof light === "object") table[name2] = light;
1601
+ else table[name2] = { light, dark: typeof dark === "string" ? dark : light };
1602
+ }
1603
+ return table;
1604
+ }
1605
+ var SYMBOL_CAP_HEIGHT_EM = 1443 / 2048;
1606
+ function axisExtremes(points) {
1607
+ const [a = 0, b = 0, c = 0, d] = points;
1608
+ const out = [a, d ?? c];
1609
+ const within2 = (t) => t > 0 && t < 1;
1610
+ if (d === void 0) {
1611
+ const denom = a - 2 * b + c;
1612
+ const t = denom === 0 ? -1 : (a - b) / denom;
1613
+ if (within2(t)) out.push((1 - t) ** 2 * a + 2 * (1 - t) * t * b + t ** 2 * c);
1614
+ return out;
1615
+ }
1616
+ const qa = 3 * (-a + 3 * b - 3 * c + d);
1617
+ const qb = 6 * (a - 2 * b + c);
1618
+ const qc = 3 * (b - a);
1619
+ const roots = Math.abs(qa) < 1e-12 ? qb === 0 ? [] : [-qc / qb] : (() => {
1620
+ const disc = qb * qb - 4 * qa * qc;
1621
+ if (disc < 0) return [];
1622
+ const root = Math.sqrt(disc);
1623
+ return [(-qb + root) / (2 * qa), (-qb - root) / (2 * qa)];
1624
+ })();
1625
+ for (const t of roots.filter(within2))
1626
+ out.push(
1627
+ (1 - t) ** 3 * a + 3 * (1 - t) ** 2 * t * b + 3 * (1 - t) * t ** 2 * c + t ** 3 * d
1628
+ );
1629
+ return out;
1630
+ }
1631
+ function pathBounds(d) {
1632
+ const xs = [];
1633
+ const ys = [];
1634
+ for (const path18 of d)
1635
+ (0, import_svgpath.default)(path18).abs().unshort().unarc().iterate((segment, _index, x, y) => {
1636
+ const [command, ...args] = segment;
1637
+ if (command === "M" || command === "L") {
1638
+ xs.push(Number(args[0]));
1639
+ ys.push(Number(args[1]));
1640
+ } else if (command === "H") xs.push(Number(args[0]));
1641
+ else if (command === "V") ys.push(Number(args[0]));
1642
+ else if (command === "Q" || command === "C") {
1643
+ const n = args.map(Number);
1644
+ xs.push(...axisExtremes([x, ...n.filter((_, i) => i % 2 === 0)]));
1645
+ ys.push(...axisExtremes([y, ...n.filter((_, i) => i % 2 === 1)]));
1646
+ }
1647
+ });
1648
+ return {
1649
+ minX: Math.min(...xs),
1650
+ maxX: Math.max(...xs),
1651
+ minY: Math.min(...ys),
1652
+ maxY: Math.max(...ys)
1653
+ };
1654
+ }
1655
+ function guide(svg, id, axis) {
1656
+ const line = new RegExp(`<line[^>]*id="${id}"[^>]*>`).exec(svg)?.[0];
1657
+ const value = line === void 0 ? void 0 : new RegExp(`${axis}="([-0-9.]+)"`).exec(line)?.[1];
1658
+ return value === void 0 ? null : Number(value);
1659
+ }
1660
+ function enumerateBundleSymbols(paths, readText, bundleForFile) {
1661
+ const table = {};
1662
+ for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
1663
+ const name2 = catalogEntryName(contentsPath, ".symbolset", readText);
1664
+ if (name2 === null) continue;
1665
+ const bundle = bundleForFile(contentsPath);
1666
+ const key2 = bundle === "." ? name2 : `${bundle}/${name2}`;
1667
+ if (Object.hasOwn(table, key2)) continue;
1668
+ let symbols;
1669
+ try {
1670
+ symbols = Reflect.get(JSON.parse(readText(contentsPath) ?? "null") ?? {}, "symbols");
1671
+ } catch {
1672
+ continue;
1673
+ }
1674
+ const file = Array.isArray(symbols) ? symbols.map((entry) => Reflect.get(entry ?? {}, "filename")).find((f) => typeof f === "string") : void 0;
1675
+ if (typeof file !== "string") continue;
1676
+ if (file.includes("/") || file.includes("\\")) continue;
1677
+ const svg = readText(`${contentsPath.split("/").slice(0, -1).join("/")}/${file}`);
1678
+ if (svg === null) continue;
1679
+ const group = /<g id="Regular-M"[^>]*>([\s\S]*?)<\/g>/.exec(svg)?.[1];
1680
+ const baseline = guide(svg, "Baseline-M", "y1");
1681
+ const capline = guide(svg, "Capline-M", "y1");
1682
+ const left = guide(svg, "left-margin-Regular-M", "x1") ?? guide(svg, "left-margin", "x1");
1683
+ const right = guide(svg, "right-margin-Regular-M", "x1") ?? guide(svg, "right-margin", "x1");
1684
+ if (group === void 0 || baseline === null || capline === null || left === null || right === null)
1685
+ continue;
1686
+ const d = [...group.matchAll(/ d="([^"]+)"/g)].map((match) => match[1] ?? "");
1687
+ if (d.length === 0 || baseline <= capline) continue;
1688
+ const scale = 24 * SYMBOL_CAP_HEIGHT_EM / (baseline - capline);
1689
+ const box = pathBounds(d);
1690
+ const translateX = 12 - (box.minX + box.maxX) * scale / 2;
1691
+ const translateY = 12 - (box.minY + box.maxY) * scale / 2;
1692
+ const advance = Math.round((right - left) * scale * 1e3) / 1e3;
1693
+ const tall = (box.maxY - box.minY) * scale + 0.175 * 24;
1694
+ table[key2] = {
1695
+ viewBox: "0 0 24 24",
1696
+ advance,
1697
+ box: [12 - advance / 2, 12 - tall / 2, advance, tall],
1698
+ layers: d.map((path18) => ({
1699
+ d: (0, import_svgpath.default)(path18).abs().scale(scale).translate(translateX, translateY).round(3).toString()
1700
+ }))
1701
+ };
1702
+ }
1703
+ return table;
1704
+ }
1705
+ var COMPILED_EXTENSIONS = /* @__PURE__ */ new Set([".swift", ".metal", ".storyboard", ".xib"]);
1706
+ var NESTED_BUNDLE_DIR = /\.(?:xcassets|lproj)$/;
1707
+ function isCopiedResource(path18) {
1708
+ const ext = extOf(path18);
1709
+ if (ext === ".json" || ext === ".xcstrings") return true;
1710
+ return !RASTER_EXTENSIONS.has(ext) && !COMPILED_EXTENSIONS.has(ext) && !path18.split("/").some((segment) => NESTED_BUNDLE_DIR.test(segment));
1711
+ }
1712
+ function enumerateBundleResources(paths) {
1713
+ const found = [];
1714
+ const seen = /* @__PURE__ */ new Set();
1715
+ const ordered = [...paths].filter(
1716
+ (path18) => path18.split("/").includes("Resources") && path18.split("/").every((segment) => segment !== "" && segment !== "..") && isCopiedResource(path18)
1717
+ ).sort((a, b) => {
1718
+ const aDepth = a.split("/").length;
1719
+ const bDepth = b.split("/").length;
1720
+ return aDepth - bDepth || (a < b ? -1 : a > b ? 1 : 0);
1721
+ });
1722
+ for (const file of ordered) {
1723
+ const base = baseOf(file);
1724
+ if (seen.has(base)) continue;
1725
+ seen.add(base);
1726
+ found.push({ base, file });
1727
+ }
1728
+ return found;
1729
+ }
1730
+ function resolveSwiftImageResourceUrls(resources, origin) {
1731
+ return Object.fromEntries(
1732
+ Object.entries(resources).map(([bundlePath, images]) => [
1733
+ bundlePath,
1734
+ Object.fromEntries(
1735
+ Object.entries(images).map(([name2, image]) => [
1736
+ name2,
1737
+ image.map((variant) => ({
1738
+ ...variant,
1739
+ uri: new URL(variant.uri, origin).href
1740
+ }))
1741
+ ])
1742
+ )
1743
+ ])
1744
+ );
1745
+ }
1746
+
1407
1747
  // ../sootsim-swift/src/entryModule.ts
1408
1748
  function nativeExportLines(args, commonjs) {
1409
1749
  const native = args.native;
1410
1750
  if (!native) return [];
1411
- return Object.entries(native.modules).map(([name2, methods]) => {
1412
- const calls = methods.map(
1413
- (method) => `${method}: (...args) => callSwiftModule(options, ${JSON.stringify(`${native.packageId}.${name2}`)}, ${JSON.stringify(method)}, args, ${JSON.stringify(native.contractHash)})`
1414
- ).join(", ");
1415
- return commonjs ? `module.exports.${name2} = Object.freeze({ ${calls} })` : `export const ${name2} = Object.freeze({ ${calls} })`;
1416
- });
1751
+ return [
1752
+ ...Object.entries(native.modules).map(([name2, methods]) => {
1753
+ const calls = methods.map(
1754
+ (method) => `${method}: (...args) => callSwiftModule(options, ${JSON.stringify(`${native.packageId}.${name2}`)}, ${JSON.stringify(method)}, args, ${JSON.stringify(native.contractHash)})`
1755
+ ).join(", ");
1756
+ return commonjs ? `module.exports.${name2} = Object.freeze({ ${calls} })` : `export const ${name2} = Object.freeze({ ${calls} })`;
1757
+ }),
1758
+ ...native.views.map((view) => {
1759
+ const value = `createSwiftEntry({ ...options, rootId: options.rootId + ${JSON.stringify("/")} + ${JSON.stringify(view)}, view: ${JSON.stringify(view)}, contractHash: ${JSON.stringify(native.contractHash)} })`;
1760
+ return commonjs ? `module.exports.${view} = ${value}` : `export const ${view} = ${value}`;
1761
+ })
1762
+ ];
1417
1763
  }
1418
1764
  function swiftEntryModuleEsm(args) {
1419
1765
  return [
1420
1766
  `import { createSwiftEntry, callSwiftModule } from 'peachsim/swift'`,
1421
- `const options = ${JSON.stringify({ url: args.url, hash: args.hash, icuUrl: args.icuUrl, rootId: args.rootId, resources: args.resources, bundleFiles: args.bundleFiles, colors: args.colors, symbols: args.symbols })}`,
1767
+ `const options = ${JSON.stringify({ url: args.url, hash: args.hash, icuUrl: args.icuUrl, rootId: args.rootId, resources: args.resources, bundleFiles: args.bundleFiles, colors: args.colors, symbols: args.symbols, metalSources: args.metalSources })}`,
1422
1768
  ...!args.native || args.native.defaultView ? ["export default createSwiftEntry(options)"] : [],
1423
1769
  ...nativeExportLines(args, false),
1424
1770
  ""
@@ -1473,7 +1819,7 @@ function parseSwiftDistributionManifest(value) {
1473
1819
  };
1474
1820
  }
1475
1821
  function parseSwiftDistributionLock(value) {
1476
- if (!isRecord(value) || typeof value.id !== "string" || !/^[a-f0-9]{16}$/.test(value.id) || typeof value.release !== "string" || typeof value.wasmSdkId !== "string" || typeof value.wasmSdkUrl !== "string" || typeof value.wasmSdkChecksum !== "string" || typeof value.source !== "string" || !isRecord(value.hosts)) {
1822
+ if (!isRecord(value) || typeof value.id !== "string" || !/^[a-f0-9]{16}$/.test(value.id) || typeof value.release !== "string" || typeof value.wasmSdkId !== "string" || typeof value.wasmSdkUrl !== "string" || typeof value.wasmSdkChecksum !== "string" || typeof value.source !== "string" || !isStrings(value.targets) || !isRecord(value.hosts)) {
1477
1823
  throw new Error("invalid Swift distribution lock");
1478
1824
  }
1479
1825
  const hosts = value.hosts;
@@ -1491,6 +1837,7 @@ function parseSwiftDistributionLock(value) {
1491
1837
  wasmSdkUrl: value.wasmSdkUrl,
1492
1838
  wasmSdkChecksum: value.wasmSdkChecksum,
1493
1839
  source: value.source,
1840
+ targets: value.targets,
1494
1841
  hosts: {
1495
1842
  "darwin-arm64": entry("darwin-arm64"),
1496
1843
  "linux-x64": entry("linux-x64"),
@@ -1622,7 +1969,10 @@ var MANIFEST_DECLARATIONS = [
1622
1969
  function manifestCalls(manifest, kinds) {
1623
1970
  const code = manifest.replace(/\/\*[\s\S]*?\*\//g, "").replace(/(^|[^:"])\/\/[^\n]*/g, "$1");
1624
1971
  const calls = [];
1625
- const pattern = new RegExp(`\\.(${MANIFEST_DECLARATIONS.join("|")})\\s*\\(`, "g");
1972
+ const pattern = new RegExp(
1973
+ `(?:\\.(${MANIFEST_DECLARATIONS.join("|")})|\\b(Package))\\s*\\(`,
1974
+ "g"
1975
+ );
1626
1976
  let match;
1627
1977
  while ((match = pattern.exec(code)) !== null) {
1628
1978
  let depth = 1;
@@ -1652,22 +2002,59 @@ function manifestCalls(manifest, kinds) {
1652
2002
  }
1653
2003
  i++;
1654
2004
  }
1655
- if (kinds.includes(match[1]))
1656
- calls.push({ kind: match[1], flat, call: code.slice(start, i) });
2005
+ const kind = match[1] ?? match[2];
2006
+ if (kinds.includes(kind)) calls.push({ kind, flat, call: code.slice(start, i) });
2007
+ else if (kind === "Package") {
2008
+ calls.push(...manifestCalls(code.slice(start, i - 1), kinds));
2009
+ }
1657
2010
  pattern.lastIndex = i;
1658
2011
  }
1659
2012
  return calls;
1660
2013
  }
2014
+ function splitManifestArguments(source) {
2015
+ const arguments_ = [];
2016
+ let start = 0;
2017
+ let parentheses = 0;
2018
+ let brackets = 0;
2019
+ let braces = 0;
2020
+ let inString = false;
2021
+ let escaped = false;
2022
+ for (let index = 0; index < source.length; index++) {
2023
+ const character = source[index];
2024
+ if (inString) {
2025
+ if (escaped) escaped = false;
2026
+ else if (character === "\\") escaped = true;
2027
+ else if (character === '"') inString = false;
2028
+ } else if (character === '"') inString = true;
2029
+ else if (character === "(") parentheses++;
2030
+ else if (character === ")") parentheses--;
2031
+ else if (character === "[") brackets++;
2032
+ else if (character === "]") brackets--;
2033
+ else if (character === "{") braces++;
2034
+ else if (character === "}") braces--;
2035
+ else if (character === "," && parentheses === 0 && brackets === 0 && braces === 0) {
2036
+ arguments_.push(source.slice(start, index).trim());
2037
+ start = index + 1;
2038
+ }
2039
+ }
2040
+ const final = source.slice(start).trim();
2041
+ if (final) arguments_.push(final);
2042
+ return arguments_;
2043
+ }
1661
2044
  function swiftPackageIdentity(url) {
1662
2045
  return (url.split("/").pop() ?? url).replace(/\.git$/, "").toLowerCase();
1663
2046
  }
1664
2047
  function swiftManifestTargets(manifest, resourcePaths = []) {
1665
2048
  const implicitResources = swiftImplicitResourcePaths(resourcePaths);
1666
2049
  const targets = [];
1667
- for (const { kind, flat, call } of manifestCalls(manifest, [
1668
- "executableTarget",
1669
- "target"
1670
- ])) {
2050
+ const declarations = manifestCalls(manifest, ["executableTarget", "target"]);
2051
+ const targetNames = new Set(
2052
+ declarations.flatMap(({ flat }) => {
2053
+ const name2 = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1];
2054
+ return name2 ? [name2] : [];
2055
+ })
2056
+ );
2057
+ for (const { kind, flat, call } of declarations) {
1671
2058
  const executable = kind === "executableTarget";
1672
2059
  const name2 = /\bname\s*:\s*"([^"]+)"/.exec(flat)?.[1];
1673
2060
  if (!name2) continue;
@@ -1677,6 +2064,12 @@ function swiftManifestTargets(manifest, resourcePaths = []) {
1677
2064
  /\.swiftLanguageMode\(\s*\.v(\d+)\s*\)/.exec(call)?.[1] ?? "5"
1678
2065
  );
1679
2066
  const mainActorIsolation = /\.defaultIsolation\(\s*MainActor\.self\s*\)/.test(call);
2067
+ const cxxInterop = /\.interoperabilityMode\(\s*\.Cxx\s*\)/.test(
2068
+ call.replace(/"(?:\\.|[^"\\])*"/g, "")
2069
+ );
2070
+ const defines = [
2071
+ ...call.matchAll(/\.define\(\s*"([A-Za-z_][A-Za-z0-9_]*)"\s*\)/g)
2072
+ ].map((match) => match[1]);
1680
2073
  const excluded = [
1681
2074
  ...(/\bexclude\s*:\s*\[([^\]]*)\]/.exec(flat)?.[1] ?? "").matchAll(/"([^"]+)"/g)
1682
2075
  ].map((match) => match[1].replace(/^\.\//, "").replace(/\/+$/, ""));
@@ -1690,20 +2083,95 @@ function swiftManifestTargets(manifest, resourcePaths = []) {
1690
2083
  return false;
1691
2084
  return true;
1692
2085
  });
2086
+ const targetArguments = splitManifestArguments(call.slice(0, -1));
2087
+ const dependencyArgument = targetArguments.find(
2088
+ (argument) => /^dependencies\s*:/.test(argument)
2089
+ );
2090
+ const dependencyList = dependencyArgument?.replace(/^dependencies\s*:\s*/, "").trim();
2091
+ const dependencyNames = /* @__PURE__ */ new Set();
2092
+ if (dependencyList?.startsWith("[") && dependencyList.endsWith("]")) {
2093
+ for (const dependency of splitManifestArguments(dependencyList.slice(1, -1))) {
2094
+ const dependencyName = /^"([^"]+)"$/.exec(dependency)?.[1] ?? /^\.(?:target|byName)\s*\(\s*name\s*:\s*"([^"]+)"/.exec(dependency)?.[1];
2095
+ if (dependencyName && targetNames.has(dependencyName))
2096
+ dependencyNames.add(dependencyName);
2097
+ }
2098
+ }
2099
+ const dependencies = [...dependencyNames].map((name3) => ({
2100
+ kind: "target",
2101
+ name: name3
2102
+ }));
1693
2103
  targets.push({
1694
2104
  name: name2,
1695
2105
  path: targetPath,
1696
2106
  executable,
1697
2107
  languageMode,
1698
2108
  mainActorIsolation,
1699
- resources
2109
+ ...cxxInterop ? { cxxInterop: true } : {},
2110
+ ...defines.length === 0 ? {} : { defines },
2111
+ resources,
2112
+ ...dependencies.length === 0 ? {} : { dependencies },
2113
+ ...excluded.length === 0 ? {} : { exclude: excluded }
1700
2114
  });
1701
2115
  }
1702
2116
  return targets;
1703
2117
  }
2118
+ function swiftManifestCxxLanguageStandard(manifest) {
2119
+ const declaration = manifestCalls(manifest, ["Package"])[0];
2120
+ if (!declaration) return void 0;
2121
+ const code = declaration.flat.replace(/"(?:\\.|[^"\\])*"/g, "");
2122
+ return /\bcxxLanguageStandard\s*:\s*\.(\w+)/.exec(code)?.[1];
2123
+ }
2124
+ function swiftResourceBundles(files2, resourcePaths = []) {
2125
+ const manifest = files2["Package.swift"] ?? "";
2126
+ const targets = swiftManifestTargets(manifest, resourcePaths).filter(
2127
+ (target) => target.resources
2128
+ );
2129
+ if (targets.length === 0) return [];
2130
+ const declaration = manifestCalls(manifest, ["Package"])[0];
2131
+ const packageName = declaration && /\bname\s*:\s*"([^"/\\]+)"/.exec(declaration.flat)?.[1];
2132
+ if (!packageName)
2133
+ throw new Error("swift resource bundles require the original package name");
2134
+ return targets.map((target) => ({
2135
+ target: target.name,
2136
+ sourcePath: target.path,
2137
+ path: `${packageName}_${target.name}.bundle`
2138
+ }));
2139
+ }
2140
+ function swiftResourceBundleForFile(bundles, file) {
2141
+ let owner;
2142
+ for (const bundle of bundles) {
2143
+ const prefix = bundle.sourcePath === "." ? "" : `${bundle.sourcePath}/`;
2144
+ if (file.startsWith(prefix) && (!owner || bundle.sourcePath.length > owner.sourcePath.length))
2145
+ owner = bundle;
2146
+ }
2147
+ return owner;
2148
+ }
2149
+ function swiftResourceBundleInfoPlist(bundle) {
2150
+ const name2 = bundle.path.split("/").pop().replace(/\.(bundle|framework)$/, "");
2151
+ const escaped = name2.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
2152
+ return `<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"><plist version="1.0"><dict><key>CFBundleName</key><string>${escaped}</string><key>CFBundlePackageType</key><string>${bundle.path.endsWith(".framework") ? "FMWK" : "BNDL"}</string></dict></plist>`;
2153
+ }
2154
+ function swiftMetalSourceFiles(files2) {
2155
+ const sources = Object.entries(files2).filter(([file]) => file.endsWith(".metal"));
2156
+ if (sources.length === 0) return {};
2157
+ const targets = swiftManifestTargets(files2["Package.swift"] ?? "");
2158
+ return Object.fromEntries(
2159
+ sources.filter(([file]) => {
2160
+ if (targets.length === 0) return true;
2161
+ return targets.some((target) => {
2162
+ const prefix = target.path === "." ? "" : `${target.path}/`;
2163
+ if (!file.startsWith(prefix)) return false;
2164
+ const relative = file.slice(prefix.length);
2165
+ return !(target.exclude ?? []).some(
2166
+ (excluded) => relative === excluded || relative.startsWith(`${excluded}/`)
2167
+ );
2168
+ });
2169
+ })
2170
+ );
2171
+ }
1704
2172
  function swiftPackagePartition(manifest, resourcePaths = []) {
1705
2173
  const targets = swiftManifestTargets(manifest, resourcePaths);
1706
- return targets.length === 1 && targets[0].executable && targets[0].path === "." ? [] : targets;
2174
+ return targets.length === 1 && targets[0].executable && targets[0].path === "." && targets[0].languageMode === 5 && !targets[0].mainActorIsolation && !targets[0].defines?.length && !targets[0].cxxInterop && !swiftManifestCxxLanguageStandard(manifest) ? [] : targets;
1707
2175
  }
1708
2176
 
1709
2177
  // src/swift-compile.ts
@@ -1736,6 +2204,7 @@ function swiftModuleInputFiles(root) {
1736
2204
  "Package.swift",
1737
2205
  "scripts/contrast-app-Package.swift",
1738
2206
  "scripts/build-distribution.ts",
2207
+ "scripts/distribution-clang.ts",
1739
2208
  "scripts/build-distribution-plugins.sh",
1740
2209
  "scripts/build-preview-plugin.sh",
1741
2210
  "toolchain.json"
@@ -1760,6 +2229,10 @@ function swiftMacroPlugins(moduleRoot) {
1760
2229
  stale: false
1761
2230
  };
1762
2231
  const dir = import_node_path2.default.join(moduleRoot, ".build/host/RnxPreviewMacros");
2232
+ const release = JSON.parse(
2233
+ (0, import_node_fs2.readFileSync)(import_node_path2.default.join(moduleRoot, "toolchain.json"), "utf8")
2234
+ ).release;
2235
+ const compilerStamp = import_node_path2.default.join(dir, "compiler-release");
1763
2236
  const ext = process.platform === "darwin" ? "dylib" : "so";
1764
2237
  const plugins = [
1765
2238
  {
@@ -1773,12 +2246,12 @@ function swiftMacroPlugins(moduleRoot) {
1773
2246
  ];
1774
2247
  return {
1775
2248
  libraries: plugins.map(({ library }) => library),
1776
- stale: plugins.some(
2249
+ stale: !(0, import_node_fs2.existsSync)(compilerStamp) || (0, import_node_fs2.readFileSync)(compilerStamp, "utf8").trim() !== release || plugins.some(
1777
2250
  ({ library, source }) => !(0, import_node_fs2.existsSync)(library) || (0, import_node_fs2.statSync)(source).mtimeMs > (0, import_node_fs2.statSync)(library).mtimeMs
1778
2251
  )
1779
2252
  };
1780
2253
  }
1781
- async function ensureMacroPlugins(moduleRoot, toolchainBin) {
2254
+ async function ensureMacroPlugins(moduleRoot, toolchainBin, release) {
1782
2255
  const { libraries, stale } = swiftMacroPlugins(moduleRoot);
1783
2256
  if (stale) {
1784
2257
  await run2("sh", [
@@ -1786,6 +2259,11 @@ async function ensureMacroPlugins(moduleRoot, toolchainBin) {
1786
2259
  toolchainBin,
1787
2260
  libraries[0]
1788
2261
  ]);
2262
+ (0, import_node_fs2.writeFileSync)(
2263
+ import_node_path2.default.join(import_node_path2.default.dirname(libraries[0]), "compiler-release"),
2264
+ `${release}
2265
+ `
2266
+ );
1789
2267
  }
1790
2268
  return libraries;
1791
2269
  }
@@ -1847,6 +2325,7 @@ var OPTIONAL_FRAMEWORK_DEPENDENCIES = {
1847
2325
  TikTokBusinessSDK: [],
1848
2326
  nSure: [],
1849
2327
  Statsig: [],
2328
+ TOCropViewController: [],
1850
2329
  RiveRuntime: ["MetalKit"],
1851
2330
  MetalKit: [],
1852
2331
  DatadogCore: [],
@@ -1861,6 +2340,7 @@ var OPTIONAL_FRAMEWORK_DEPENDENCIES = {
1861
2340
  Intercom: [],
1862
2341
  FirebaseCore: [],
1863
2342
  FirebaseSharedSwift: ["FirebaseCore"],
2343
+ FirebaseRemoteConfig: ["FirebaseCore", "FirebaseSharedSwift"],
1864
2344
  FirebaseFirestoreInternal: ["FirebaseCore"],
1865
2345
  FirebaseAnalytics: ["FirebaseCore"],
1866
2346
  FirebaseAppCheck: ["FirebaseCore"],
@@ -1868,6 +2348,7 @@ var OPTIONAL_FRAMEWORK_DEPENDENCIES = {
1868
2348
  FirebaseCrashlytics: ["FirebaseCore"],
1869
2349
  FirebaseFirestore: ["FirebaseCore", "FirebaseSharedSwift", "FirebaseFirestoreInternal"],
1870
2350
  FirebaseStorage: ["FirebaseCore"],
2351
+ GoogleMobileAds: [],
1871
2352
  FBAudienceNetwork: []
1872
2353
  };
1873
2354
  var OPTIONAL_FRAMEWORKS = new Set(Object.keys(OPTIONAL_FRAMEWORK_DEPENDENCIES));
@@ -2011,7 +2492,11 @@ function swiftTargetDependencies(files2, targets) {
2011
2492
  const siblings = /* @__PURE__ */ new Map();
2012
2493
  for (const target of targets) {
2013
2494
  const prefix = target.path === "." ? "" : `${target.path}/`;
2014
- const deps = /* @__PURE__ */ new Set();
2495
+ const deps = new Set(
2496
+ (target.dependencies ?? []).flatMap(
2497
+ (dependency) => dependency.kind === "target" && dependency.name !== target.name && names.has(dependency.name) ? [dependency.name] : []
2498
+ )
2499
+ );
2015
2500
  for (const [file, contents] of Object.entries(files2)) {
2016
2501
  if (file === "Package.swift" || !file.startsWith(prefix)) continue;
2017
2502
  if (targets.some(
@@ -2035,17 +2520,17 @@ var FOUNDATION_IMPLICIT_MODULES = [
2035
2520
  "PeachObjC",
2036
2521
  "Dispatch",
2037
2522
  "FoundationNetworking",
2038
- "WASILibc",
2039
- "wasi_pthread"
2523
+ "PeachFoundationCombine",
2524
+ "Darwin"
2040
2525
  ];
2041
2526
  var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
2042
2527
  (module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
2043
2528
  ).join("");
2044
2529
  var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
2045
- var MULTI_MANIFEST_VERSION = 12;
2530
+ var MULTI_MANIFEST_VERSION = 18;
2046
2531
  function swiftArtifactHash(input, release, moduleRoot) {
2047
2532
  const hash = (0, import_node_crypto2.createHash)("sha256");
2048
- hash.update(`swift-compile/v20
2533
+ hash.update(`swift-compile/v23
2049
2534
  ${release}
2050
2535
  `);
2051
2536
  if (input.oneModule) hash.update("one-module\n");
@@ -2054,6 +2539,13 @@ ${release}
2054
2539
  hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
2055
2540
  hash.update((0, import_node_crypto2.createHash)("sha256").update(input.files[file]).digest());
2056
2541
  }
2542
+ for (const file of Object.keys(input.metalSources ?? {}).sort()) {
2543
+ hash.update("metal-source\n");
2544
+ hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
2545
+ hash.update(
2546
+ (0, import_node_crypto2.createHash)("sha256").update(input.metalSources?.[file] ?? "").digest()
2547
+ );
2548
+ }
2057
2549
  for (const base of Object.keys(input.resources ?? {}).sort()) {
2058
2550
  hash.update((0, import_node_crypto2.createHash)("sha256").update(base).digest());
2059
2551
  hash.update(
@@ -2071,6 +2563,19 @@ ${release}
2071
2563
  hash.update("resource-path\n");
2072
2564
  hash.update((0, import_node_crypto2.createHash)("sha256").update(file).digest());
2073
2565
  }
2566
+ hash.update(
2567
+ JSON.stringify(
2568
+ [...input.resourceBundles ?? []].sort((a, b) => a.target.localeCompare(b.target))
2569
+ )
2570
+ );
2571
+ for (const target of Object.keys(input.libraries ?? {}).sort()) {
2572
+ hash.update(`library
2573
+ ${target}
2574
+ `);
2575
+ hash.update(
2576
+ (0, import_node_crypto2.createHash)("sha256").update(input.libraries?.[target] ?? "").digest()
2577
+ );
2578
+ }
2074
2579
  const targets = compileTargets(input);
2075
2580
  if (targets.length > 0) {
2076
2581
  hash.update(`swift-multi/v${MULTI_MANIFEST_VERSION}
@@ -2106,10 +2611,22 @@ function emitSwiftPackageManifest(args) {
2106
2611
  if (!executable) throw new Error("swift-compile: no executable target to emit");
2107
2612
  const stanza = (target) => {
2108
2613
  const isolation = target.mainActorIsolation ? " .defaultIsolation(MainActor.self)," : "";
2614
+ const interoperability = target.cxxInterop ? " .interoperabilityMode(.Cxx)," : "";
2615
+ const defines = (target.defines ?? []).map((name2) => ` .define(${JSON.stringify(name2)}),`).join("");
2109
2616
  const imports = distribution ? `, "-I", ${JSON.stringify(import_node_path2.default.join(moduleRoot, "modules"))}` : "";
2110
- const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation} .unsafeFlags(["-Osize"${FOUNDATION_IMPLICIT_FLAGS}${oneModule ? ONE_IMPLICIT_FLAGS : ""}${imports}])]`;
2617
+ const native = args.native?.get(target.name);
2618
+ const nativeImports = (siblings.get(target.name) ?? []).filter((name2) => args.native?.has(name2)).map(
2619
+ (name2) => `, "-Xfrontend", "-import-module", "-Xfrontend", ${JSON.stringify(name2)}`
2620
+ ).join("");
2621
+ const header = args.headerDirectory && [...args.native?.values() ?? []].some(
2622
+ (value) => value.late.producers.includes(target.name)
2623
+ ) ? `, "-emit-objc-header-path", ${JSON.stringify(import_node_path2.default.join(args.headerDirectory, `${target.name}-Swift.h`))}` : "";
2624
+ const swiftSettings = `swiftSettings: [.swiftLanguageMode(.v${target.languageMode}),${isolation}${interoperability}${defines} .unsafeFlags(["-Osize"${FOUNDATION_IMPLICIT_FLAGS}${oneModule ? ONE_IMPLICIT_FLAGS : ""}${imports}${nativeImports}${header}])]`;
2111
2625
  const deps = [
2112
- ...distribution ? [] : [
2626
+ ...target.executable ? [...args.native?.values() ?? []].map(
2627
+ (value) => JSON.stringify(value.late.name)
2628
+ ) : [],
2629
+ ...distribution || native ? [] : [
2113
2630
  '.product(name: "SwiftUI", package: "sootsim-swift")',
2114
2631
  ...oneModule ? [ONE_PRODUCT] : [],
2115
2632
  ...spriteKit ? [SPRITEKIT_PRODUCT] : []
@@ -2130,13 +2647,15 @@ function emitSwiftPackageManifest(args) {
2130
2647
  "-Xlinker", "--export-if-defined=__main_argc_argv"${library},
2131
2648
  ]),
2132
2649
  .unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
2133
- ]` : "";
2650
+ ]` : args.libraries?.has(target.name) ? `,
2651
+ linkerSettings: [.unsafeFlags([${JSON.stringify(args.libraries.get(target.name))}])]` : "";
2134
2652
  return [
2135
2653
  ` ${kind}(`,
2136
2654
  ` name: "${target.name}",`,
2137
2655
  ` dependencies: [${deps}],`,
2138
2656
  ` path: "${target.path}",`,
2139
- ` ${swiftSettings}${link}`,
2657
+ ...native ? [` exclude: ${JSON.stringify(native.lateSources)},`] : [],
2658
+ ` ${native ? "cxxSettings: []" : swiftSettings}${link}`,
2140
2659
  ` ),`
2141
2660
  ].join("\n");
2142
2661
  };
@@ -2151,7 +2670,16 @@ function emitSwiftPackageManifest(args) {
2151
2670
  ` dependencies: [${distribution ? "" : `.package(path: "${moduleRoot}")`}],`,
2152
2671
  " targets: [",
2153
2672
  ...targets.map(stanza),
2154
- " ]",
2673
+ ...[...args.native?.entries() ?? []].flatMap(([name2, native]) => [
2674
+ ` .target(name: ${JSON.stringify(native.late.name)},`,
2675
+ ` dependencies: ${JSON.stringify([name2, ...native.late.producers])},`,
2676
+ ` path: ${JSON.stringify(native.path)},`,
2677
+ ` sources: ${JSON.stringify(native.lateSources)},`,
2678
+ ` publicHeadersPath: "include",`,
2679
+ ` cxxSettings: [.unsafeFlags(["-fno-cxx-modules", "-I", ${JSON.stringify(native.includeDirectory)}, "-I", ${JSON.stringify(args.headerDirectory)}])]),`
2680
+ ]),
2681
+ args.cxxLanguageStandard ? ` ],
2682
+ cxxLanguageStandard: .${args.cxxLanguageStandard}` : " ]",
2155
2683
  ")",
2156
2684
  ""
2157
2685
  ].join("\n");
@@ -2168,9 +2696,10 @@ function syncSwiftTree(base, files2) {
2168
2696
  };
2169
2697
  walk2(base);
2170
2698
  for (const [full, contents] of files2) {
2171
- if ((0, import_node_fs2.existsSync)(full) && (0, import_node_fs2.readFileSync)(full, "utf8") === contents) continue;
2699
+ if ((0, import_node_fs2.existsSync)(full) && (typeof contents === "string" ? (0, import_node_fs2.readFileSync)(full, "utf8") === contents : (0, import_node_fs2.readFileSync)(full).equals(contents)))
2700
+ continue;
2172
2701
  (0, import_node_fs2.mkdirSync)(import_node_path2.default.dirname(full), { recursive: true });
2173
- (0, import_node_fs2.writeFileSync)(full, contents, "utf8");
2702
+ (0, import_node_fs2.writeFileSync)(full, contents);
2174
2703
  }
2175
2704
  }
2176
2705
  var DIRECTIVE = /^[ \t]*#(?:if|elseif)\b/;
@@ -3206,6 +3735,8 @@ function swiftCodeScan(source) {
3206
3735
  }
3207
3736
  var compiledSource = (file, contents, extraObjCExtensions, tableConformances) => file.endsWith(".swift") ? swiftSourceAsIOS(contents, extraObjCExtensions, tableConformances) : contents;
3208
3737
  function writeSwiftProject(layout, input, moduleRoot) {
3738
+ if (input.resourceBundles !== void 0 && !isSwiftResourceBundles(input.resourceBundles))
3739
+ throw new Error("swift compile input has invalid target bundle assignments");
3209
3740
  const resourceTargets = swiftManifestTargets(
3210
3741
  input.files["Package.swift"] ?? "",
3211
3742
  input.resourcePaths
@@ -3222,6 +3753,80 @@ function writeSwiftProject(layout, input, moduleRoot) {
3222
3753
  }
3223
3754
  ] : compileTargets(input);
3224
3755
  const files2 = /* @__PURE__ */ new Map();
3756
+ const native = /* @__PURE__ */ new Map();
3757
+ const headerDirectory = import_node_path2.default.join(layout.root, ".build", "peach-cxx-headers");
3758
+ for (const target of targets) {
3759
+ const prefix = target.path === "." ? "" : `${target.path}/`;
3760
+ const entries = Object.entries(input.files).filter(
3761
+ ([file]) => file.startsWith(prefix) && !targets.some(
3762
+ (candidate) => candidate.name !== target.name && candidate.path !== "." && candidate.path.startsWith(prefix) && file.startsWith(`${candidate.path}/`)
3763
+ )
3764
+ );
3765
+ if (entries.some(([file]) => file.endsWith(".swift"))) continue;
3766
+ const units = entries.filter(([file]) => /\.(?:c|cc|cpp|cxx|m|mm)$/.test(file));
3767
+ if (units.length === 0) continue;
3768
+ const includes = `${prefix}include/`;
3769
+ const consumers = /* @__PURE__ */ new Map();
3770
+ const reverse = /* @__PURE__ */ new Map();
3771
+ for (const [file, contents] of entries) {
3772
+ const producers = /* @__PURE__ */ new Set();
3773
+ const source = contents.replace(/\/\*[\s\S]*?\*\//g, "");
3774
+ for (const match of source.matchAll(/^\s*#\s*include\s*[<"]([^>"]+)[>"]/gm)) {
3775
+ const include = match[1];
3776
+ const producer = /(?:^|\/)([^/]+)-Swift\.h$/.exec(include)?.[1];
3777
+ if (producer && targets.some((value) => value.name === producer))
3778
+ producers.add(producer);
3779
+ const local = [
3780
+ import_node_path2.default.posix.join(import_node_path2.default.posix.dirname(file), include),
3781
+ `${includes}${include}`
3782
+ ].find((candidate) => input.files[candidate] !== void 0);
3783
+ if (local) {
3784
+ reverse.set(local, [...reverse.get(local) ?? [], file]);
3785
+ }
3786
+ }
3787
+ consumers.set(file, producers);
3788
+ }
3789
+ const queue = [...consumers.keys()].filter((file) => consumers.get(file).size > 0);
3790
+ for (let index = 0; index < queue.length; index++) {
3791
+ const file = queue[index];
3792
+ for (const parent of reverse.get(file) ?? []) {
3793
+ const inherited = consumers.get(parent);
3794
+ const before = inherited.size;
3795
+ for (const producer of consumers.get(file)) inherited.add(producer);
3796
+ if (before !== inherited.size) queue.push(parent);
3797
+ }
3798
+ }
3799
+ const late = units.filter(([file]) => consumers.get(file).size > 0);
3800
+ if (late.length === 0) continue;
3801
+ native.set(target.name, {
3802
+ path: target.path,
3803
+ includeDirectory: import_node_path2.default.join(layout.root, includes),
3804
+ lateSources: late.map(([file]) => file.slice(prefix.length)),
3805
+ late: {
3806
+ name: `${target.name}SwiftImplementation`,
3807
+ producers: [
3808
+ ...new Set(late.flatMap(([file]) => [...consumers.get(file)]))
3809
+ ].sort()
3810
+ }
3811
+ });
3812
+ if (input.files[`${includes}module.modulemap`] !== void 0) continue;
3813
+ const roots = entries.filter(
3814
+ ([file]) => file.startsWith(includes) && /\.(?:h|hpp|hh|hxx)$/.test(file) && consumers.get(file).size === 0
3815
+ );
3816
+ files2.set(
3817
+ import_node_path2.default.join(layout.root, includes, "module.modulemap"),
3818
+ [
3819
+ `module ${target.name} {`,
3820
+ ...roots.map(
3821
+ ([file]) => ` header ${JSON.stringify(file.slice(includes.length))}`
3822
+ ),
3823
+ " export *",
3824
+ "}",
3825
+ ""
3826
+ ].join("\n")
3827
+ );
3828
+ }
3829
+ if (native.size > 0) (0, import_node_fs2.mkdirSync)(headerDirectory, { recursive: true });
3225
3830
  const modulePlan = (0, import_node_crypto2.createHash)("sha256").update(
3226
3831
  swiftModuleInputFiles(moduleRoot).join("\n")
3227
3832
  );
@@ -3230,7 +3835,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
3230
3835
  }
3231
3836
  const resourcePlan = (0, import_node_crypto2.createHash)("sha256").update(
3232
3837
  JSON.stringify(
3233
- resourceTargets.filter((target) => target.resources).map((target) => [target.name, target.path])
3838
+ resourceTargets.filter((target) => target.resources).map((target) => [
3839
+ target.name,
3840
+ target.path,
3841
+ input.resourceBundles?.find((bundle) => bundle.target === target.name)?.path
3842
+ ])
3234
3843
  )
3235
3844
  ).digest("hex").slice(0, 16);
3236
3845
  const moduleFiles = `
@@ -3290,6 +3899,12 @@ function writeSwiftProject(layout, input, moduleRoot) {
3290
3899
  files2.set(import_node_path2.default.join(layout.root, "Package.swift"), manifest + moduleFiles);
3291
3900
  } else {
3292
3901
  const base = layout.multi ? layout.root : layout.sources;
3902
+ const libraries = /* @__PURE__ */ new Map();
3903
+ for (const [target, data] of Object.entries(input.libraries ?? {})) {
3904
+ const file = import_node_path2.default.join(layout.root, ".peach-libraries", `lib${target}.a`);
3905
+ files2.set(file, Buffer.from(data, "base64"));
3906
+ libraries.set(target, file);
3907
+ }
3293
3908
  for (const [file, contents] of Object.entries(input.files)) {
3294
3909
  if (file === "Package.swift") continue;
3295
3910
  files2.set(
@@ -3301,6 +3916,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
3301
3916
  import_node_path2.default.join(layout.root, "Package.swift"),
3302
3917
  emitSwiftPackageManifest({
3303
3918
  targets,
3919
+ native,
3920
+ headerDirectory: native.size > 0 ? headerDirectory : void 0,
3921
+ cxxLanguageStandard: swiftManifestCxxLanguageStandard(
3922
+ input.files["Package.swift"] ?? ""
3923
+ ),
3304
3924
  siblings: swiftTargetDependencies(
3305
3925
  input.files,
3306
3926
  layout.multi ? targets : targets.map((target) => ({ ...target, path: "." }))
@@ -3308,12 +3928,20 @@ function writeSwiftProject(layout, input, moduleRoot) {
3308
3928
  moduleRoot,
3309
3929
  oneModule: input.oneModule,
3310
3930
  spriteKit: importsSpriteKit(input.files),
3311
- distribution: distribution ?? void 0
3931
+ distribution: distribution ?? void 0,
3932
+ libraries
3312
3933
  }) + moduleFiles
3313
3934
  );
3314
3935
  }
3315
3936
  for (const target of resourceTargets) {
3316
3937
  if (!target.resources) continue;
3938
+ const bundle = input.resourceBundles?.find(
3939
+ (candidate) => candidate.target === target.name
3940
+ );
3941
+ if (!bundle || bundle.sourcePath !== target.path)
3942
+ throw new Error(
3943
+ `swift resource target ${target.name} has no matching bundle assignment`
3944
+ );
3317
3945
  const directory = layout.multi ? import_node_path2.default.join(layout.root, target.path) : layout.sources;
3318
3946
  files2.set(
3319
3947
  import_node_path2.default.join(directory, "ResourceBundleAccessor.generated.swift"),
@@ -3321,7 +3949,11 @@ function writeSwiftProject(layout, input, moduleRoot) {
3321
3949
  "import Foundation",
3322
3950
  "",
3323
3951
  "extension Foundation.Bundle {",
3324
- " static let module: Bundle = Bundle.main",
3952
+ bundle.path === "." ? " static let module: Bundle = Bundle.main" : ` static let module: Bundle = {
3953
+ let url = Bundle.main.bundleURL.appendingPathComponent(${JSON.stringify(bundle.path)})
3954
+ guard let bundle = Bundle(url: url) else { fatalError("resource bundle is missing: ${bundle.target}") }
3955
+ return bundle
3956
+ }()`,
3325
3957
  "}",
3326
3958
  ""
3327
3959
  ].join("\n")
@@ -3389,7 +4021,7 @@ function compileSwiftProjectUnit(input, options) {
3389
4021
  };
3390
4022
  const hash = swiftArtifactHash(input, options.release, moduleRoot);
3391
4023
  return serialize(root, async () => {
3392
- if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && process.env.CONTRAST_HEAVY_ADMITTED !== "1" && moduleRoot === import_node_path2.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
4024
+ if (process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && moduleRoot === import_node_path2.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(moduleRoot)) {
3393
4025
  const requestRoot = (0, import_node_fs2.mkdtempSync)(import_node_path2.default.join(root, ".builder-request-"));
3394
4026
  const output = import_node_path2.default.join(requestRoot, "output");
3395
4027
  const request = import_node_path2.default.join(requestRoot, "request.json");
@@ -3414,7 +4046,11 @@ function compileSwiftProjectUnit(input, options) {
3414
4046
  "--output",
3415
4047
  output
3416
4048
  ],
3417
- { cwd: repo, timeout: options.timeoutMs, maxBuffer: 64 * 1024 * 1024 }
4049
+ {
4050
+ cwd: repo,
4051
+ timeout: options.timeoutMs,
4052
+ maxBuffer: 64 * 1024 * 1024
4053
+ }
3418
4054
  );
3419
4055
  pending.child.stdout?.on("data", (bytes2) => process.stdout.write(bytes2));
3420
4056
  pending.child.stderr?.on("data", (bytes2) => process.stderr.write(bytes2));
@@ -3446,7 +4082,11 @@ function compileSwiftProjectUnit(input, options) {
3446
4082
  `swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`
3447
4083
  );
3448
4084
  }
3449
- const macroPlugins = await ensureMacroPlugins(moduleRoot, options.toolchainBin);
4085
+ const macroPlugins = await ensureMacroPlugins(
4086
+ moduleRoot,
4087
+ options.toolchainBin,
4088
+ options.release
4089
+ );
3450
4090
  const sdk = swiftModuleSdk(moduleRoot).wasmSdkId;
3451
4091
  const icu = swiftIcuAsset(options.toolchainBin, sdk);
3452
4092
  try {
@@ -3454,6 +4094,8 @@ function compileSwiftProjectUnit(input, options) {
3454
4094
  swift,
3455
4095
  [
3456
4096
  "build",
4097
+ "--build-system",
4098
+ "native",
3457
4099
  "-j",
3458
4100
  BUILD_JOBS,
3459
4101
  "--package-path",
@@ -3483,302 +4125,29 @@ function compileSwiftProjectUnit(input, options) {
3483
4125
  ].filter(Boolean).join(":")
3484
4126
  } : {}
3485
4127
  },
3486
- maxBuffer: 64 * 1024 * 1024,
3487
- timeout: options.timeoutMs
3488
- }
3489
- );
3490
- } catch (error) {
3491
- throw new Error(projectDiagnostic(outputOf(error), layout), {
3492
- cause: error
3493
- });
3494
- }
3495
- return {
3496
- hash,
3497
- bytes: (0, import_node_fs2.readFileSync)(builtArtifact(layout)),
3498
- icu: await icu
3499
- };
3500
- });
3501
- }
3502
-
3503
- // src/swift-host.ts
3504
- var import_node_crypto7 = require("node:crypto");
3505
- var import_node_fs14 = __toESM(require("node:fs"), 1);
3506
- var import_node_os8 = __toESM(require("node:os"), 1);
3507
- var import_node_path15 = __toESM(require("node:path"), 1);
3508
-
3509
- // ../sootsim-swift/src/bundleAssets.ts
3510
- var import_svgpath = __toESM(require("svgpath"), 1);
3511
- var RASTER_EXTENSIONS = /* @__PURE__ */ new Set([
3512
- ".avif",
3513
- ".bmp",
3514
- ".gif",
3515
- ".ico",
3516
- ".jpeg",
3517
- ".jpg",
3518
- ".png",
3519
- ".webp"
3520
- ]);
3521
- function extOf(file) {
3522
- const dot = file.lastIndexOf(".");
3523
- return dot < 0 ? "" : file.slice(dot).toLowerCase();
3524
- }
3525
- function baseOf(file) {
3526
- const slash = file.lastIndexOf("/");
3527
- return slash < 0 ? file : file.slice(slash + 1);
3528
- }
3529
- function pickImagesetFile(images) {
3530
- const rasters = images.filter(
3531
- (image) => typeof image.filename === "string" && RASTER_EXTENSIONS.has(extOf(image.filename))
3532
- );
3533
- if (rasters.length === 0) return null;
3534
- const rank = (scale) => scale === "2x" ? 0 : scale === "3x" ? 1 : scale === "1x" ? 2 : 3;
3535
- const pick = [...rasters].sort((a, b) => rank(a.scale) - rank(b.scale))[0];
3536
- return {
3537
- filename: pick.filename,
3538
- scale: pick.scale === "2x" ? 2 : pick.scale === "3x" ? 3 : 1
3539
- };
3540
- }
3541
- function flatScale(path18) {
3542
- const match = /@([23])x\.[^./]+$/.exec(path18);
3543
- return match ? Number(match[1]) : 1;
3544
- }
3545
- function providesNamespace(text3) {
3546
- if (text3 === null) return false;
3547
- try {
3548
- const parsed = JSON.parse(text3);
3549
- return parsed?.properties?.["provides-namespace"] === true;
3550
- } catch {
3551
- return false;
3552
- }
3553
- }
3554
- function catalogEntryName(contentsPath, kind, readText) {
3555
- const parts = contentsPath.split("/");
3556
- const leaf2 = parts[parts.length - 2] ?? "";
3557
- if (!leaf2.endsWith(kind)) return null;
3558
- const short = leaf2.slice(0, -kind.length) || null;
3559
- if (short === null) return null;
3560
- const segments = [short];
3561
- for (let depth = parts.length - 3; depth >= 0; depth -= 1) {
3562
- const dir = parts[depth] ?? "";
3563
- if (dir.endsWith(".xcassets") || dir === "" || dir === "." || dir === "..") break;
3564
- const folderContents = [...parts.slice(0, depth + 1), "Contents.json"].join("/");
3565
- if (providesNamespace(readText(folderContents))) segments.unshift(dir);
3566
- }
3567
- return segments.join("/");
3568
- }
3569
- function isFlatResourceImage(path18) {
3570
- return path18.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path18));
3571
- }
3572
- function enumerateBundleImages(paths, readText) {
3573
- const table = [];
3574
- const seen = /* @__PURE__ */ new Set();
3575
- const catalogs = paths.filter((path18) => baseOf(path18) === "Contents.json");
3576
- for (const contentsPath of catalogs) {
3577
- const name2 = catalogEntryName(contentsPath, ".imageset", readText);
3578
- if (name2 === null || seen.has(name2)) continue;
3579
- let parsed;
3580
- try {
3581
- const text3 = readText(contentsPath);
3582
- if (text3 === null) continue;
3583
- parsed = JSON.parse(text3);
3584
- } catch {
3585
- continue;
3586
- }
3587
- const images = parsed?.images;
3588
- if (!Array.isArray(images)) continue;
3589
- const dir = contentsPath.split("/").slice(0, -1).join("/");
3590
- const pick = pickImagesetFile(images);
3591
- if (pick === null || pick.filename.includes("/") || pick.filename.includes("\\"))
3592
- continue;
3593
- seen.add(name2);
3594
- table.push({ name: name2, file: `${dir}/${pick.filename}`, scale: pick.scale });
3595
- }
3596
- for (const path18 of paths) {
3597
- if (!isFlatResourceImage(path18)) continue;
3598
- const name2 = baseOf(path18).slice(0, -extOf(path18).length);
3599
- if (name2 === "" || seen.has(name2)) continue;
3600
- seen.add(name2);
3601
- table.push({ name: name2, file: path18, scale: flatScale(path18) });
3602
- }
3603
- return table;
3604
- }
3605
- function colorComponent(value) {
3606
- if (typeof value !== "string") return null;
3607
- const parsed = value.startsWith("0x") ? Number.parseInt(value.slice(2), 16) / 255 : value.includes(".") ? Number.parseFloat(value) : Number.parseInt(value, 10) / 255;
3608
- return Number.isFinite(parsed) ? parsed : null;
3609
- }
3610
- function colorsetValue(color) {
3611
- if (typeof color !== "object" || color === null) return null;
3612
- const reference = Reflect.get(color, "reference");
3613
- if (typeof reference === "string") {
3614
- return { system: reference.replace(/Color$/, "") };
3615
- }
3616
- const space = Reflect.get(color, "color-space");
3617
- if (space !== "srgb" && space !== "extended-srgb") return null;
3618
- const components = Reflect.get(color, "components");
3619
- if (typeof components !== "object" || components === null) return null;
3620
- const [red, green, blue, alpha] = ["red", "green", "blue", "alpha"].map(
3621
- (key2) => colorComponent(Reflect.get(components, key2))
3622
- );
3623
- if (red === null || green === null || blue === null || alpha === null) return null;
3624
- if (![red, green, blue].every((value) => value >= 0 && value <= 1)) return null;
3625
- const byte = (value) => Math.round(value * 255);
3626
- return `rgba(${byte(red)}, ${byte(green)}, ${byte(blue)}, ${alpha})`;
3627
- }
3628
- function enumerateBundleColors(paths, readText) {
3629
- const table = {};
3630
- for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
3631
- const name2 = catalogEntryName(contentsPath, ".colorset", readText);
3632
- if (name2 === null || name2 in table) continue;
3633
- let colors;
3634
- try {
3635
- const text3 = readText(contentsPath);
3636
- if (text3 === null) continue;
3637
- colors = Reflect.get(JSON.parse(text3), "colors");
3638
- } catch {
3639
- continue;
3640
- }
3641
- if (!Array.isArray(colors)) continue;
3642
- let light = null;
3643
- let dark = null;
3644
- for (const entry of colors) {
3645
- if (typeof entry !== "object" || entry === null) continue;
3646
- const idiom = Reflect.get(entry, "idiom");
3647
- if (idiom !== "universal" && idiom !== "iphone") continue;
3648
- const appearances = Reflect.get(entry, "appearances");
3649
- const list2 = Array.isArray(appearances) ? appearances : [];
3650
- if (list2.some((item) => Reflect.get(item, "appearance") === "contrast")) continue;
3651
- const isDark = list2.some(
3652
- (item) => Reflect.get(item, "appearance") === "luminosity" && Reflect.get(item, "value") === "dark"
3653
- );
3654
- if (list2.length > 0 && !isDark) continue;
3655
- const value = colorsetValue(Reflect.get(entry, "color"));
3656
- if (value === null) continue;
3657
- if (isDark) dark = value;
3658
- else light = value;
3659
- }
3660
- if (light === null) continue;
3661
- if (typeof light === "object") table[name2] = light;
3662
- else table[name2] = { light, dark: typeof dark === "string" ? dark : light };
3663
- }
3664
- return table;
3665
- }
3666
- var SYMBOL_CAP_HEIGHT_EM = 1443 / 2048;
3667
- function axisExtremes(points) {
3668
- const [a = 0, b = 0, c = 0, d] = points;
3669
- const out = [a, d ?? c];
3670
- const within2 = (t) => t > 0 && t < 1;
3671
- if (d === void 0) {
3672
- const denom = a - 2 * b + c;
3673
- const t = denom === 0 ? -1 : (a - b) / denom;
3674
- if (within2(t)) out.push((1 - t) ** 2 * a + 2 * (1 - t) * t * b + t ** 2 * c);
3675
- return out;
3676
- }
3677
- const qa = 3 * (-a + 3 * b - 3 * c + d);
3678
- const qb = 6 * (a - 2 * b + c);
3679
- const qc = 3 * (b - a);
3680
- const roots = Math.abs(qa) < 1e-12 ? qb === 0 ? [] : [-qc / qb] : (() => {
3681
- const disc = qb * qb - 4 * qa * qc;
3682
- if (disc < 0) return [];
3683
- const root = Math.sqrt(disc);
3684
- return [(-qb + root) / (2 * qa), (-qb - root) / (2 * qa)];
3685
- })();
3686
- for (const t of roots.filter(within2))
3687
- out.push(
3688
- (1 - t) ** 3 * a + 3 * (1 - t) ** 2 * t * b + 3 * (1 - t) * t ** 2 * c + t ** 3 * d
3689
- );
3690
- return out;
3691
- }
3692
- function pathBounds(d) {
3693
- const xs = [];
3694
- const ys = [];
3695
- for (const path18 of d)
3696
- (0, import_svgpath.default)(path18).abs().unshort().unarc().iterate((segment, _index, x, y) => {
3697
- const [command, ...args] = segment;
3698
- if (command === "M" || command === "L") {
3699
- xs.push(Number(args[0]));
3700
- ys.push(Number(args[1]));
3701
- } else if (command === "H") xs.push(Number(args[0]));
3702
- else if (command === "V") ys.push(Number(args[0]));
3703
- else if (command === "Q" || command === "C") {
3704
- const n = args.map(Number);
3705
- xs.push(...axisExtremes([x, ...n.filter((_, i) => i % 2 === 0)]));
3706
- ys.push(...axisExtremes([y, ...n.filter((_, i) => i % 2 === 1)]));
3707
- }
3708
- });
3709
- return {
3710
- minX: Math.min(...xs),
3711
- maxX: Math.max(...xs),
3712
- minY: Math.min(...ys),
3713
- maxY: Math.max(...ys)
3714
- };
3715
- }
3716
- function guide(svg, id, axis) {
3717
- const line = new RegExp(`<line[^>]*id="${id}"[^>]*>`).exec(svg)?.[0];
3718
- const value = line === void 0 ? void 0 : new RegExp(`${axis}="([-0-9.]+)"`).exec(line)?.[1];
3719
- return value === void 0 ? null : Number(value);
3720
- }
3721
- function enumerateBundleSymbols(paths, readText) {
3722
- const table = {};
3723
- for (const contentsPath of paths.filter((path18) => baseOf(path18) === "Contents.json")) {
3724
- const name2 = catalogEntryName(contentsPath, ".symbolset", readText);
3725
- if (name2 === null || name2 in table) continue;
3726
- let symbols;
3727
- try {
3728
- symbols = Reflect.get(JSON.parse(readText(contentsPath) ?? "null") ?? {}, "symbols");
3729
- } catch {
3730
- continue;
3731
- }
3732
- const file = Array.isArray(symbols) ? symbols.map((entry) => Reflect.get(entry ?? {}, "filename")).find((f) => typeof f === "string") : void 0;
3733
- if (typeof file !== "string") continue;
3734
- if (file.includes("/") || file.includes("\\")) continue;
3735
- const svg = readText(`${contentsPath.split("/").slice(0, -1).join("/")}/${file}`);
3736
- if (svg === null) continue;
3737
- const group = /<g id="Regular-M"[^>]*>([\s\S]*?)<\/g>/.exec(svg)?.[1];
3738
- const baseline = guide(svg, "Baseline-M", "y1");
3739
- const capline = guide(svg, "Capline-M", "y1");
3740
- const left = guide(svg, "left-margin-Regular-M", "x1") ?? guide(svg, "left-margin", "x1");
3741
- const right = guide(svg, "right-margin-Regular-M", "x1") ?? guide(svg, "right-margin", "x1");
3742
- if (group === void 0 || baseline === null || capline === null || left === null || right === null)
3743
- continue;
3744
- const d = [...group.matchAll(/ d="([^"]+)"/g)].map((match) => match[1] ?? "");
3745
- if (d.length === 0 || baseline <= capline) continue;
3746
- const scale = 24 * SYMBOL_CAP_HEIGHT_EM / (baseline - capline);
3747
- const box = pathBounds(d);
3748
- const translateX = 12 - (box.minX + box.maxX) * scale / 2;
3749
- const translateY = 12 - (box.minY + box.maxY) * scale / 2;
3750
- const advance = Math.round((right - left) * scale * 1e3) / 1e3;
3751
- const tall = (box.maxY - box.minY) * scale + 0.175 * 24;
3752
- table[name2] = {
3753
- viewBox: "0 0 24 24",
3754
- advance,
3755
- box: [12 - advance / 2, 12 - tall / 2, advance, tall],
3756
- layers: d.map((path18) => ({
3757
- d: (0, import_svgpath.default)(path18).abs().scale(scale).translate(translateX, translateY).round(3).toString()
3758
- }))
4128
+ maxBuffer: 64 * 1024 * 1024,
4129
+ timeout: options.timeoutMs
4130
+ }
4131
+ );
4132
+ } catch (error) {
4133
+ throw new Error(projectDiagnostic(outputOf(error), layout), {
4134
+ cause: error
4135
+ });
4136
+ }
4137
+ return {
4138
+ hash,
4139
+ bytes: (0, import_node_fs2.readFileSync)(builtArtifact(layout)),
4140
+ icu: await icu
3759
4141
  };
3760
- }
3761
- return table;
3762
- }
3763
- function enumerateBundleJson(paths) {
3764
- const found = [];
3765
- const seen = /* @__PURE__ */ new Set();
3766
- const ordered = [...paths].filter(
3767
- (path18) => path18.split("/").includes("Resources") && path18.split("/").every((segment) => segment !== "" && segment !== "..") && (extOf(path18) === ".json" || extOf(path18) === ".xcstrings")
3768
- ).sort((a, b) => {
3769
- const aDepth = a.split("/").length;
3770
- const bDepth = b.split("/").length;
3771
- return aDepth - bDepth || (a < b ? -1 : a > b ? 1 : 0);
3772
4142
  });
3773
- for (const file of ordered) {
3774
- const base = baseOf(file);
3775
- if (seen.has(base)) continue;
3776
- seen.add(base);
3777
- found.push({ base, file });
3778
- }
3779
- return found;
3780
4143
  }
3781
4144
 
4145
+ // src/swift-host.ts
4146
+ var import_node_crypto7 = require("node:crypto");
4147
+ var import_node_fs14 = __toESM(require("node:fs"), 1);
4148
+ var import_node_os8 = __toESM(require("node:os"), 1);
4149
+ var import_node_path15 = __toESM(require("node:path"), 1);
4150
+
3782
4151
  // src/auth/shared-session.ts
3783
4152
  var import_node_fs3 = require("node:fs");
3784
4153
  var import_node_path4 = require("node:path");
@@ -4286,7 +4655,7 @@ function frameworkModules(paths) {
4286
4655
  }
4287
4656
  async function range(url, spec) {
4288
4657
  const response = await fetch(url, {
4289
- headers: { range: `bytes=${spec}` },
4658
+ headers: { range: `bytes=${spec}`, "accept-encoding": "identity" },
4290
4659
  signal: AbortSignal.timeout(2e4)
4291
4660
  });
4292
4661
  const match = /^bytes (\d+)-\d+\/(\d+)$/.exec(
@@ -4467,24 +4836,135 @@ function runExtractor(command, args) {
4467
4836
 
4468
4837
  // src/swift-distribution.lock.json
4469
4838
  var swift_distribution_lock_default = {
4470
- id: "dd4939815d74c469",
4471
- release: "swift-6.3-RELEASE",
4472
- wasmSdkId: "swift-6.3-RELEASE_wasm-peach-41921598-peach-edd95e37",
4473
- wasmSdkUrl: "https://r2.rnxsim.com/swift-wasm-sdk/swift-6.3-RELEASE_wasm-peach-41921598-peach-edd95e37.artifactbundle.tar.gz",
4474
- wasmSdkChecksum: "e8b76a6b78c21e9e16a6943a691ea001aeb0a18518d775a26130520303eb5c6d",
4475
- source: "65037f7f51d461fcf993549d206b3a5dfaa1f58f",
4839
+ id: "3246f7e5ccb24952",
4840
+ release: "swift-6.4.0-RELEASE",
4841
+ wasmSdkId: "swift-6.4.0-RELEASE_wasm-peach-e4629014",
4842
+ wasmSdkUrl: "https://r2.sootsim.com/swift-wasm-sdk/swift-6.4.0-RELEASE_wasm-peach-e4629014.artifactbundle.tar.gz",
4843
+ wasmSdkChecksum: "522f3ff98e951872d64751376d45e36394e572ec2aa4e0a52fb0027824bf41f6",
4844
+ source: "a1e87668019272a329f6d9fada213573e3c5107f",
4845
+ targets: [
4846
+ "ExpoModulesCore",
4847
+ "PeachJSON",
4848
+ "PeachFoundation",
4849
+ "FoundationNetworking",
4850
+ "DeveloperToolsSupport",
4851
+ "SwiftUI",
4852
+ "Dispatch",
4853
+ "Darwin",
4854
+ "MachO",
4855
+ "ObjectiveC",
4856
+ "PeachObjC",
4857
+ "UIKitCore",
4858
+ "PeachICU",
4859
+ "CoreImage",
4860
+ "QuartzCore",
4861
+ "CoreGraphics",
4862
+ "AppTrackingTransparency",
4863
+ "StoreKit",
4864
+ "WeatherKit",
4865
+ "DeviceCheck",
4866
+ "PassKit",
4867
+ "Translation",
4868
+ "CoreSpotlight",
4869
+ "CoreVideo",
4870
+ "CoreMedia",
4871
+ "VideoToolbox",
4872
+ "AdSupport",
4873
+ "BackgroundTasks",
4874
+ "LocalAuthentication",
4875
+ "CoreMotion",
4876
+ "MessageUI",
4877
+ "GameController",
4878
+ "MetricKit",
4879
+ "Metal",
4880
+ "AuthenticationServices",
4881
+ "os",
4882
+ "Charts",
4883
+ "Symbols",
4884
+ "UniformTypeIdentifiers",
4885
+ "WidgetKit",
4886
+ "ActivityKit",
4887
+ "SwiftData",
4888
+ "UIKit",
4889
+ "Combine",
4890
+ "PeachFoundationCombine",
4891
+ "AppIntents",
4892
+ "PhotosUI",
4893
+ "AVFoundation",
4894
+ "AVFAudio",
4895
+ "UserNotifications",
4896
+ "Network",
4897
+ "OSLog",
4898
+ "Security",
4899
+ "Accelerate",
4900
+ "CoreText",
4901
+ "CommonCrypto",
4902
+ "PeachCodec",
4903
+ "Compression",
4904
+ "zlib",
4905
+ "CryptoKit",
4906
+ "TikTokBusinessSDK",
4907
+ "nSure",
4908
+ "Statsig",
4909
+ "TOCropViewController",
4910
+ "RiveRuntime",
4911
+ "MetalKit",
4912
+ "DatadogCore",
4913
+ "DatadogLogs",
4914
+ "DatadogRUM",
4915
+ "DatadogTrace",
4916
+ "AppLovinSDK",
4917
+ "GoogleMobileAds",
4918
+ "AppsFlyerLib",
4919
+ "FBSDKCoreKit",
4920
+ "FBAEMKit",
4921
+ "FBSDKCoreKit_Basics",
4922
+ "FirebaseCore",
4923
+ "FirebaseSharedSwift",
4924
+ "FirebaseRemoteConfig",
4925
+ "FirebaseFirestoreInternal",
4926
+ "FirebaseAnalytics",
4927
+ "FirebaseAppCheck",
4928
+ "FirebaseAuth",
4929
+ "FirebaseCrashlytics",
4930
+ "FirebaseFirestore",
4931
+ "FirebaseStorage",
4932
+ "Intercom",
4933
+ "FBAudienceNetwork",
4934
+ "NaturalLanguage",
4935
+ "AVKit",
4936
+ "SafariServices",
4937
+ "QuickLook",
4938
+ "CoreHaptics",
4939
+ "WebKit",
4940
+ "Photos",
4941
+ "LinkPresentation",
4942
+ "FoundationModels",
4943
+ "CoreTransferable",
4944
+ "AudioToolbox",
4945
+ "Intents",
4946
+ "MobileCoreServices",
4947
+ "ImageIO",
4948
+ "CoreLocationEnums",
4949
+ "CoreLocation",
4950
+ "MapKit",
4951
+ "One",
4952
+ "GameplayKit",
4953
+ "SpriteKit",
4954
+ "PeachBox2D"
4955
+ ],
4476
4956
  hosts: {
4477
4957
  "darwin-arm64": {
4478
- sha256: "d15d78a731a2613ab34d199f45aec8d4a6046ce54155f321ea67f9f7476e5dfd",
4479
- size: 47319022
4958
+ sha256: "fb5a3e9db1eae670b5ba84432345e52de8b55b5fdf0e468ff95dfa25a62a6968",
4959
+ size: 55050821
4480
4960
  },
4481
4961
  "linux-x64": {
4482
- sha256: "0bcedbd713a5682041638fb99204b20b62437636302359f9a60fa2cb103acbf2",
4483
- size: 47324525
4962
+ sha256: "46a0eae68905751ee7c6536e79f626bc71d9d5a22cf9a76ce12b8d6c3aa34293",
4963
+ size: 55056198
4484
4964
  },
4485
4965
  "linux-arm64": {
4486
- sha256: "dfb7d0abf23a5c006ad81b06d4263b01f903220d5b15717d5c224f959c0e422f",
4487
- size: 47323454
4966
+ sha256: "ea6453b55ff428d4d152d829731504400d49969ab0750264a931eaf0d7659122",
4967
+ size: 55055213
4488
4968
  }
4489
4969
  }
4490
4970
  };
@@ -4494,6 +4974,9 @@ var import_node_child_process4 = require("node:child_process");
4494
4974
  var import_node_fs6 = __toESM(require("node:fs"), 1);
4495
4975
  var import_node_os5 = __toESM(require("node:os"), 1);
4496
4976
  var import_node_path7 = __toESM(require("node:path"), 1);
4977
+ function swiftCompilerRelease(release) {
4978
+ return release.replace(/^swift-(\d+\.\d+)\.0-RELEASE$/, "swift-$1-RELEASE");
4979
+ }
4497
4980
  function swiftToolchainBin(release) {
4498
4981
  if (process.platform === "darwin") {
4499
4982
  const dirs = [import_node_os5.default.homedir(), "/"].map(
@@ -4518,7 +5001,7 @@ function swiftToolchain(release, sdk) {
4518
5001
  encoding: "utf8",
4519
5002
  stdio: ["ignore", "pipe", "pipe"]
4520
5003
  }) : "";
4521
- if (!version.includes(`(${release})`)) {
5004
+ if (!version.includes(`(${swiftCompilerRelease(release)})`)) {
4522
5005
  const found = version ? `found ${version.split("\n")[0]?.trim()} at ${swift}` : process.platform === "darwin" ? `found no ${release}.xctoolchain in ~/Library/Developer/Toolchains or /Library/Developer/Toolchains` : "found no swift on PATH";
4523
5006
  throw new Error(
4524
5007
  `peach compiles Swift with the swift.org toolchain ${release} and its wasm SDK; ${found}.
@@ -4615,11 +5098,6 @@ function swiftModuleToolchain(root) {
4615
5098
  };
4616
5099
  }
4617
5100
 
4618
- // src/swift-packages.ts
4619
- var import_node_child_process6 = require("node:child_process");
4620
- var import_node_fs9 = __toESM(require("node:fs"), 1);
4621
- var import_node_path10 = __toESM(require("node:path"), 1);
4622
-
4623
5101
  // src/swift-package-manifest.ts
4624
5102
  var import_node_child_process5 = require("node:child_process");
4625
5103
  var import_node_crypto5 = require("node:crypto");
@@ -4740,10 +5218,10 @@ function swiftPackageManifest(dir) {
4740
5218
  }
4741
5219
  const products = /* @__PURE__ */ new Map();
4742
5220
  for (const product of array(raw2.products)) {
4743
- const { name: name2, targets: targets2, type } = record(product);
4744
- if (!string(name2) || !("library" in record(type))) continue;
5221
+ const { name: name3, targets: targets2, type } = record(product);
5222
+ if (!string(name3) || !("library" in record(type))) continue;
4745
5223
  products.set(
4746
- string(name2),
5224
+ string(name3),
4747
5225
  array(targets2).flatMap((target) => string(target) ?? [])
4748
5226
  );
4749
5227
  }
@@ -4751,12 +5229,12 @@ function swiftPackageManifest(dir) {
4751
5229
  const names = new Set(array(raw2.targets).map((target) => string(record(target).name)));
4752
5230
  for (const entry of array(raw2.targets)) {
4753
5231
  const target = record(entry);
4754
- const name2 = string(target.name);
5232
+ const name3 = string(target.name);
4755
5233
  const kind = string(target.type);
4756
- if (!name2 || !isTargetType(kind)) continue;
5234
+ if (!name3 || !isTargetType(kind)) continue;
4757
5235
  const declared = string(target.path);
4758
5236
  const roots = kind === "test" ? ["Tests"] : ["Sources", "Source", "src", "srcs"];
4759
- const targetDir = declared ? import_node_path9.default.resolve(dir, declared) : roots.map((root) => import_node_path9.default.join(dir, root, name2)).find((candidate) => import_node_fs8.default.existsSync(candidate)) ?? import_node_path9.default.join(dir, roots[0], name2);
5237
+ const targetDir = declared ? import_node_path9.default.resolve(dir, declared) : roots.map((root) => import_node_path9.default.join(dir, root, name3)).find((candidate) => import_node_fs8.default.existsSync(candidate)) ?? import_node_path9.default.join(dir, roots[0], name3);
4760
5238
  const dependencies = [];
4761
5239
  for (const dependency of array(target.dependencies)) {
4762
5240
  const { target: local, product, byName } = record(dependency);
@@ -4781,16 +5259,26 @@ function swiftPackageManifest(dir) {
4781
5259
  }
4782
5260
  let languageMode = packageMode;
4783
5261
  let mainActorIsolation = false;
5262
+ const defines = [];
4784
5263
  for (const setting of array(target.settings)) {
4785
- const settingKind = record(record(setting).kind);
5264
+ const { kind: rawKind, tool, condition } = record(setting);
5265
+ const settingKind = record(rawKind);
4786
5266
  const mode = string(record(settingKind.swiftLanguageMode)._0);
4787
5267
  if (mode)
4788
5268
  languageMode = Math.max(5, Number(/^(\d+)/.exec(mode)?.[1] ?? languageMode));
4789
5269
  if (string(record(settingKind.defaultIsolation)._0) === "MainActor")
4790
5270
  mainActorIsolation = true;
5271
+ const define = string(record(settingKind.define)._0);
5272
+ if (define && string(tool) === "swift" && /^[A-Za-z_][A-Za-z0-9_]*$/.test(define) && linksOnIOS(condition, traits)) {
5273
+ const config = string(record(condition).config);
5274
+ defines.push({
5275
+ name: define,
5276
+ configuration: config === "debug" || config === "release" ? config : null
5277
+ });
5278
+ }
4791
5279
  }
4792
- targets.set(name2, {
4793
- name: name2,
5280
+ targets.set(name3, {
5281
+ name: name3,
4794
5282
  type: kind,
4795
5283
  dir: targetDir,
4796
5284
  sources: target.sources == null ? null : array(target.sources).flatMap((file) => string(file) ?? []),
@@ -4798,12 +5286,15 @@ function swiftPackageManifest(dir) {
4798
5286
  dependencies,
4799
5287
  languageMode,
4800
5288
  mainActorIsolation,
5289
+ defines,
4801
5290
  declaresResources: array(target.resources).length > 0,
4802
5291
  url: string(target.url) ?? null,
4803
5292
  checksum: string(target.checksum) ?? null
4804
5293
  });
4805
5294
  }
4806
- const manifest = { dir, products, targets, packages };
5295
+ const name2 = string(raw2.name);
5296
+ if (!name2) throw new Error(`swiftpm returned no package name for ${dir}`);
5297
+ const manifest = { name: name2, dir, products, targets, packages };
4807
5298
  evaluated.set(key2, manifest);
4808
5299
  return manifest;
4809
5300
  }
@@ -4832,6 +5323,9 @@ function swiftTargetFiles(manifest, target) {
4832
5323
  }
4833
5324
 
4834
5325
  // src/swift-packages.ts
5326
+ var import_node_child_process6 = require("node:child_process");
5327
+ var import_node_fs9 = __toESM(require("node:fs"), 1);
5328
+ var import_node_path10 = __toESM(require("node:path"), 1);
4835
5329
  var REMOTE_CHECKOUTS = import_node_path10.default.join(".build", "peach", "checkouts");
4836
5330
  var C_FAMILY = /\.(c|cc|cpp|cxx|m|mm|s|S)$/;
4837
5331
  var BINARY = "is a binary framework";
@@ -4950,6 +5444,7 @@ function resolveSwiftPackages(options) {
4950
5444
  files: files2,
4951
5445
  packageDir: pkg.manifest.dir,
4952
5446
  remote: pkg.remote,
5447
+ packageDefines: target.defines,
4953
5448
  executable: false,
4954
5449
  languageMode: target.languageMode,
4955
5450
  mainActorIsolation: target.mainActorIsolation,
@@ -5144,6 +5639,7 @@ function getCliVersion() {
5144
5639
 
5145
5640
  // src/swift-standin-emit.ts
5146
5641
  var STANDIN_EMIT_VERSION = "5";
5642
+ var STANDIN_IMPORTS = ["Foundation", "UIKit"];
5147
5643
  var TYPE_KINDS = /* @__PURE__ */ new Set([
5148
5644
  "swift.class",
5149
5645
  "swift.struct",
@@ -5764,7 +6260,7 @@ function emitSwiftStandin(graphs, options) {
5764
6260
  else emitMember(member, " ", { openOwner: false, inClass: false });
5765
6261
  emit(`}`);
5766
6262
  }
5767
- const imports = ["Foundation", "UIKit", ...options.imports ?? []];
6263
+ const imports = [...STANDIN_IMPORTS, ...options.imports ?? []];
5768
6264
  const banner = [
5769
6265
  `// stand-in for the binary ${options.module} module, generated from ${options.source}.`,
5770
6266
  `// do not hand-edit: every body traps because the vendor binary cannot run`,
@@ -5965,6 +6461,8 @@ function xcframework(binary) {
5965
6461
  var files = (dir, test) => import_node_fs12.default.existsSync(dir) ? import_node_fs12.default.readdirSync(dir, { recursive: true, encoding: "utf8" }).filter((file) => test(import_node_path12.default.basename(file))).sort() : [];
5966
6462
  function surfaces(xcframeworkDir) {
5967
6463
  const slice = import_node_fs12.default.readdirSync(xcframeworkDir).filter((name2) => /^ios-.+-simulator$/.test(name2)).sort()[0];
6464
+ if (!slice && xcframeworkDir.endsWith(".framework"))
6465
+ throw new Error("a plain .framework has no .xcframework simulator slice");
5968
6466
  if (!slice) throw new Error("it has no iOS simulator slice");
5969
6467
  const root = import_node_path12.default.join(xcframeworkDir, slice);
5970
6468
  const found = [];
@@ -6007,6 +6505,9 @@ function peachModuleDirs(toolchain, imports) {
6007
6505
  const { moduleRoot, toolchainBin } = toolchain;
6008
6506
  if (swiftDistributionAt(moduleRoot)) return [import_node_path12.default.join(moduleRoot, "modules")];
6009
6507
  const peach = new Set(swiftPeachModules(moduleRoot));
6508
+ const targets = [.../* @__PURE__ */ new Set([...STANDIN_IMPORTS, ...imports])].filter(
6509
+ (name2) => peach.has(name2)
6510
+ );
6010
6511
  const plugins = swiftMacroPlugins(moduleRoot);
6011
6512
  if (plugins.stale)
6012
6513
  exec("sh", [
@@ -6014,11 +6515,15 @@ function peachModuleDirs(toolchain, imports) {
6014
6515
  toolchainBin,
6015
6516
  plugins.libraries[0]
6016
6517
  ]);
6017
- for (const target of imports.filter((name2) => peach.has(name2)))
6518
+ for (const target of targets)
6018
6519
  exec(
6019
6520
  import_node_path12.default.join(toolchainBin, "swift"),
6020
6521
  [
6021
6522
  "build",
6523
+ "--build-system",
6524
+ "native",
6525
+ "-j",
6526
+ "4",
6022
6527
  "--swift-sdk",
6023
6528
  swiftModuleSdk(moduleRoot).wasmSdkId,
6024
6529
  "-c",
@@ -6045,7 +6550,12 @@ function peachModuleDirs(toolchain, imports) {
6045
6550
  ];
6046
6551
  }
6047
6552
  function swiftInterfaceForWasm(text3) {
6048
- return text3.replace(
6553
+ const rooted = text3.replace(
6554
+ /\bObjectiveC(\.|::)(NSObject|NSObjectProtocol)\b/g,
6555
+ "Foundation$1$2"
6556
+ );
6557
+ const foundation = rooted !== text3 && !/^import[ \t]+Foundation\b/m.test(rooted) ? rooted.replace(/^(?=import[ \t])/m, "import Foundation\n") : rooted;
6558
+ return foundation.replace(
6049
6559
  /^(\/\/ swift-module-flags:.*)$/m,
6050
6560
  (flags) => flags.replace(/-target \S+/, `-target ${TRIPLE}`).replace(/\s-enable-objc-interop\b/, "").replace(/\s-target-variant \S+/, "")
6051
6561
  ).replace(
@@ -6364,6 +6874,167 @@ ${roots.map((file) => ` header "${file}"
6364
6874
  }
6365
6875
  };
6366
6876
  }
6877
+ var RUST_TARGET = "wasm32-wasip1";
6878
+ var UNSEARCHED = /* @__PURE__ */ new Set([
6879
+ "node_modules",
6880
+ "Pods",
6881
+ "target",
6882
+ ".build",
6883
+ ".git",
6884
+ "DerivedData"
6885
+ ]);
6886
+ function crateFor(root, name2) {
6887
+ const walk2 = (dir, depth) => {
6888
+ const manifest = import_node_path12.default.join(dir, "Cargo.toml");
6889
+ if (import_node_fs12.default.existsSync(manifest)) {
6890
+ const text3 = import_node_fs12.default.readFileSync(manifest, "utf8");
6891
+ const section = (title) => new RegExp(`^\\[${title}\\]\\s*$([\\s\\S]*?)(?=^\\[|(?![\\s\\S]))`, "m").exec(
6892
+ text3
6893
+ )?.[1] ?? "";
6894
+ const field = (body, key2) => new RegExp(`^${key2}\\s*=\\s*"([^"]+)"`, "m").exec(body)?.[1];
6895
+ const lib = section("lib");
6896
+ const crate = field(lib, "name") ?? field(section("package"), "name")?.replaceAll("-", "_");
6897
+ if (crate === name2) {
6898
+ if (!/crate-type\s*=\s*\[[^\]]*"staticlib"/.test(lib))
6899
+ throw new Error(
6900
+ `${import_node_path12.default.relative(root, manifest)} builds lib${name2} without crate-type "staticlib"`
6901
+ );
6902
+ return manifest;
6903
+ }
6904
+ }
6905
+ if (depth === 0) return null;
6906
+ for (const entry of import_node_fs12.default.readdirSync(dir, { withFileTypes: true })) {
6907
+ if (!entry.isDirectory() || UNSEARCHED.has(entry.name) || entry.name.endsWith(".xcframework"))
6908
+ continue;
6909
+ const found = walk2(import_node_path12.default.join(dir, entry.name), depth - 1);
6910
+ if (found) return found;
6911
+ }
6912
+ return null;
6913
+ };
6914
+ return walk2(root, 4);
6915
+ }
6916
+ function standinLibrary(binary, searchRoot) {
6917
+ const dir = xcframework(binary).dir;
6918
+ const slice = import_node_fs12.default.readdirSync(dir).filter((name2) => /^ios-.+-simulator$/.test(name2)).sort()[0];
6919
+ const library = slice ? import_node_fs12.default.readdirSync(import_node_path12.default.join(dir, slice)).find((name2) => /^lib.+\.a$/.test(name2)) : void 0;
6920
+ const supplied = import_node_path12.default.join(dir, RUST_TARGET);
6921
+ if (import_node_fs12.default.existsSync(supplied)) {
6922
+ const found = import_node_fs12.default.readdirSync(supplied).filter((name2) => name2.endsWith(".a"));
6923
+ const chosen = library && found.includes(library) ? library : found.length === 1 ? found[0] : null;
6924
+ if (!chosen)
6925
+ throw new Error(
6926
+ `${import_node_path12.default.relative(searchRoot, supplied)} holds no single static library${library ? ` named ${library}` : ""}`
6927
+ );
6928
+ return import_node_path12.default.join(supplied, chosen);
6929
+ }
6930
+ if (!library) return null;
6931
+ const manifest = crateFor(searchRoot, library.slice("lib".length, -".a".length));
6932
+ if (!manifest) return null;
6933
+ const result = (0, import_node_child_process7.spawnSync)(
6934
+ "cargo",
6935
+ [
6936
+ "build",
6937
+ "--release",
6938
+ "--target",
6939
+ RUST_TARGET,
6940
+ "--message-format=json-render-diagnostics",
6941
+ "--manifest-path",
6942
+ manifest
6943
+ ],
6944
+ {
6945
+ encoding: "utf8",
6946
+ maxBuffer: 256 * 1024 * 1024,
6947
+ stdio: ["ignore", "pipe", "pipe"]
6948
+ }
6949
+ );
6950
+ const crate = import_node_path12.default.relative(searchRoot, import_node_path12.default.dirname(manifest));
6951
+ if (result.error)
6952
+ throw new Error(
6953
+ `${crate} is a rust crate and cargo is not installed; install rust (https://rustup.rs), then run again`
6954
+ );
6955
+ if (result.status !== 0) {
6956
+ if (/target may not be installed|can't find crate for `(core|std)`/.test(result.stderr))
6957
+ throw new Error(
6958
+ `${crate} builds for ${RUST_TARGET}, which this rust lacks; run \`rustup target add ${RUST_TARGET}\`, then run again`
6959
+ );
6960
+ throw new Error(
6961
+ `cargo could not build ${crate} for ${RUST_TARGET}: ${failure(result)}`
6962
+ );
6963
+ }
6964
+ for (const line of result.stdout.split("\n")) {
6965
+ if (!line.startsWith("{")) continue;
6966
+ const message = JSON.parse(line);
6967
+ if (!message || typeof message !== "object" || !("filenames" in message) || !Array.isArray(message.filenames))
6968
+ continue;
6969
+ const archive = message.filenames.find(
6970
+ (file) => typeof file === "string" && import_node_path12.default.basename(file) === library
6971
+ );
6972
+ if (archive) return archive;
6973
+ }
6974
+ throw new Error(`cargo built ${crate} for ${RUST_TARGET} but reported no ${library}`);
6975
+ }
6976
+ function sourceBinaryStandins(binary, toolchain, provided) {
6977
+ const repo = import_node_path12.default.resolve(toolchain.moduleRoot, "../..");
6978
+ const work = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os7.default.tmpdir(), "peach-standin-request-"));
6979
+ try {
6980
+ const artifact = xcframework(binary);
6981
+ const local = { ...binary, dir: artifact.dir, url: null, checksum: null };
6982
+ const generation = standinGenerationInputs([local], toolchain);
6983
+ const request = import_node_path12.default.join(work, "request.json");
6984
+ const delivery = import_node_path12.default.join(work, "delivery");
6985
+ import_node_fs12.default.writeFileSync(
6986
+ request,
6987
+ JSON.stringify({
6988
+ binary: local,
6989
+ provided: [...provided],
6990
+ generation,
6991
+ release: toolchain.release,
6992
+ callerToolchainBin: toolchain.toolchainBin
6993
+ })
6994
+ );
6995
+ (0, import_node_child_process7.execFileSync)(
6996
+ "bash",
6997
+ [
6998
+ import_node_path12.default.join(repo, "scripts/build/remote.sh"),
6999
+ // a deadline makes a busy pool wait for a slot; without one it refuses
7000
+ // at once and the app reads as missing a module
7001
+ "--timeout",
7002
+ "1800",
7003
+ "--delivery-dir",
7004
+ delivery,
7005
+ "--toolchain",
7006
+ "packages/sootsim-swift/toolchain.json",
7007
+ "--input",
7008
+ request,
7009
+ "--input",
7010
+ artifact.dir,
7011
+ "bun",
7012
+ "scripts/build/swift-standins.ts",
7013
+ "--request",
7014
+ ".remote-inputs/request.json",
7015
+ "--artifact",
7016
+ `.remote-inputs/${import_node_path12.default.basename(artifact.dir)}`,
7017
+ "--output",
7018
+ ".remote-out/standins.json"
7019
+ ],
7020
+ { cwd: repo, stdio: "inherit" }
7021
+ );
7022
+ const receipt = JSON.parse(
7023
+ import_node_fs12.default.readFileSync(import_node_path12.default.join(delivery, "standins.json"), "utf8")
7024
+ );
7025
+ if (!receipt || typeof receipt !== "object" || !("generation" in receipt) || receipt.generation !== generation || !("result" in receipt))
7026
+ throw new Error("Swift stand-in builder source differs from the caller");
7027
+ const result = receipt.result;
7028
+ if (typeof result === "string") return result;
7029
+ if (!Array.isArray(result) || !result.every(
7030
+ (item) => item && typeof item === "object" && typeof item.module === "string" && typeof item.target === "string" && item.target === binary.target && item.files && typeof item.files === "object" && !Array.isArray(item.files) && Object.values(item.files).every((text3) => typeof text3 === "string")
7031
+ ))
7032
+ throw new Error("invalid Swift stand-in builder result");
7033
+ return result;
7034
+ } finally {
7035
+ import_node_fs12.default.rmSync(work, { recursive: true, force: true });
7036
+ }
7037
+ }
6367
7038
  var built = /* @__PURE__ */ new Map();
6368
7039
  function standinGenerationInputs(binaries, toolchain) {
6369
7040
  const { moduleRoot, toolchainBin, release } = toolchain;
@@ -6440,7 +7111,7 @@ function binaryStandins(binary, toolchain, provided) {
6440
7111
  const work = import_node_fs12.default.mkdtempSync(import_node_path12.default.join(import_node_os7.default.tmpdir(), "peach-standin-"));
6441
7112
  let result;
6442
7113
  try {
6443
- result = found.map((surface) => {
7114
+ result = process.platform === "darwin" && process.env.TM_SESSION && process.env.CI !== "true" && toolchain.moduleRoot === import_node_path12.default.resolve(__sootsim_import_meta_dirname, "../../sootsim-swift") && !swiftDistributionAt(toolchain.moduleRoot) ? sourceBinaryStandins(binary, toolchain, provided) : found.map((surface) => {
6444
7115
  const dir = import_node_path12.default.join(work, surface.module);
6445
7116
  try {
6446
7117
  return surface.kind === "swift" ? swiftStandin(surface, binary, toolchain, dir) : cStandin(surface, binary, toolchain, dir);
@@ -6450,6 +7121,7 @@ function binaryStandins(binary, toolchain, provided) {
6450
7121
  );
6451
7122
  }
6452
7123
  });
7124
+ if (typeof result === "string") return result;
6453
7125
  import_node_fs12.default.mkdirSync(import_node_path12.default.dirname(cached2), { recursive: true });
6454
7126
  import_node_fs12.default.writeFileSync(cached2, JSON.stringify(result));
6455
7127
  built.set(id, result);
@@ -6478,18 +7150,22 @@ var MAX_SWIFT_COMPILE_SOURCE_BYTES = 2 * 1024 * 1024;
6478
7150
  var MAX_SWIFT_COMPILE_RESOURCES = 128;
6479
7151
  var MAX_SWIFT_COMPILE_RESOURCE_BYTES = 2 * 1024 * 1024;
6480
7152
  var MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES = 8 * 1024 * 1024;
7153
+ var MAX_SWIFT_COMPILE_METAL_FILES = 128;
7154
+ var MAX_SWIFT_COMPILE_METAL_BYTES = 2 * 1024 * 1024;
7155
+ var MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024;
6481
7156
  var MAX_SWIFT_COMPILE_IMAGES = 128;
6482
7157
  var MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
6483
7158
  var MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
6484
- var SWIFT_HOST_ABI = 24;
7159
+ var SWIFT_HOST_ABI = 41;
6485
7160
  var POLL_INTERVAL_MS = 1500;
6486
7161
  function swiftNativeEntry(native, file) {
6487
7162
  return {
6488
7163
  packageId: native.packageId,
6489
7164
  contractHash: native.hash,
6490
7165
  modules: Object.fromEntries(
6491
- (native.files[file] ?? []).map((name2) => [name2, native.modules[name2] ?? []])
7166
+ (native.files[file] ?? []).filter((name2) => Object.hasOwn(native.modules, name2)).map((name2) => [name2, native.modules[name2]])
6492
7167
  ),
7168
+ views: (native.files[file] ?? []).filter((name2) => Object.hasOwn(native.views, name2)),
6493
7169
  defaultView: native.defaultViewFiles.includes(file)
6494
7170
  };
6495
7171
  }
@@ -6536,7 +7212,11 @@ function isRecord2(value) {
6536
7212
  return typeof value === "object" && value !== null && !Array.isArray(value);
6537
7213
  }
6538
7214
  function isSwiftNativeModules(value) {
6539
- return isRecord2(value) && typeof value.packageId === "string" && typeof value.hash === "string" && isRecord2(value.files) && isRecord2(value.modules) && [...Object.values(value.files), ...Object.values(value.modules)].every(
7215
+ return isRecord2(value) && typeof value.packageId === "string" && typeof value.hash === "string" && isRecord2(value.files) && isRecord2(value.modules) && isRecord2(value.views) && [
7216
+ ...Object.values(value.files),
7217
+ ...Object.values(value.modules),
7218
+ ...Object.values(value.views)
7219
+ ].every(
6540
7220
  (names) => Array.isArray(names) && names.every((name2) => typeof name2 === "string")
6541
7221
  ) && Array.isArray(value.defaultViewFiles) && value.defaultViewFiles.every((file) => typeof file === "string");
6542
7222
  }
@@ -6544,7 +7224,7 @@ function isSwiftCompileOutcome(value) {
6544
7224
  if (!isRecord2(value)) return false;
6545
7225
  switch (value.status) {
6546
7226
  case "published":
6547
- return typeof value.artifactUrl === "string" && typeof value.icuUrl === "string" && typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash) && (value.imageUrls === void 0 || isRecord2(value.imageUrls) && Object.values(value.imageUrls).every((url) => typeof url === "string")) && (value.native === void 0 || isSwiftNativeModules(value.native));
7227
+ return typeof value.artifactUrl === "string" && typeof value.icuUrl === "string" && typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash) && (value.imageUrls === void 0 || isRecord2(value.imageUrls) && Object.values(value.imageUrls).every((url) => typeof url === "string")) && (value.metalSources === void 0 || isSwiftMetalLibrarySources(value.metalSources)) && (value.native === void 0 || isSwiftNativeModules(value.native));
6548
7228
  case "compiling":
6549
7229
  return typeof value.hash === "string" && /^[a-f0-9]{64}$/.test(value.hash);
6550
7230
  case "refused":
@@ -6579,6 +7259,14 @@ async function compileSwiftProject(submit, work, origin, signal) {
6579
7259
  hash: outcome.hash,
6580
7260
  icuUrl: compileAssetUrl(outcome.icuUrl, origin),
6581
7261
  ...outcome.imageUrls === void 0 ? {} : { imageUrls: resolveImageUrls(outcome.imageUrls, origin) },
7262
+ ...outcome.metalSources === void 0 ? {} : {
7263
+ metalSources: Object.fromEntries(
7264
+ Object.entries(outcome.metalSources).map(([file, source]) => [
7265
+ file,
7266
+ { ...source, url: compileAssetUrl(source.url, origin) }
7267
+ ])
7268
+ )
7269
+ },
6582
7270
  ...outcome.native === void 0 ? {} : { native: outcome.native }
6583
7271
  };
6584
7272
  case "compiling":
@@ -6945,7 +7633,10 @@ function isJsonObject(value) {
6945
7633
  return typeof value === "object" && value !== null && !Array.isArray(value);
6946
7634
  }
6947
7635
 
6948
- // src/xcode-project.ts
7636
+ // src/openstep-plist.ts
7637
+ var isDict = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7638
+ var str = (value) => typeof value === "string" ? value : void 0;
7639
+ var list = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
6949
7640
  function parseOpenStepPlist(text3) {
6950
7641
  let i = 0;
6951
7642
  const fail = (message) => {
@@ -7003,6 +7694,7 @@ function parseOpenStepPlist(text3) {
7003
7694
  if (typeof key2 !== "string") fail("dictionary key is not a string");
7004
7695
  skip();
7005
7696
  if (text3[i++] !== "=") fail("expected =");
7697
+ if (Object.hasOwn(dict, key2)) fail(`duplicate key ${key2}`);
7006
7698
  dict[key2] = value();
7007
7699
  skip();
7008
7700
  if (text3[i++] !== ";") fail("expected ;");
@@ -7035,9 +7727,8 @@ function parseOpenStepPlist(text3) {
7035
7727
  if (i !== text3.length) fail("trailing content");
7036
7728
  return root;
7037
7729
  }
7038
- var isDict = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7039
- var str = (value) => typeof value === "string" ? value : void 0;
7040
- var list = (value) => Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
7730
+
7731
+ // src/xcode-project.ts
7041
7732
  var APPLICATION = "com.apple.product-type.application";
7042
7733
  var MODULE_PRODUCTS = /* @__PURE__ */ new Set([
7043
7734
  "com.apple.product-type.framework",
@@ -7064,9 +7755,9 @@ function walkFiles(dir) {
7064
7755
  return out;
7065
7756
  }
7066
7757
  var isDirectory = (dir) => import_node_fs13.default.existsSync(dir) && import_node_fs13.default.statSync(dir).isDirectory();
7067
- function readXcconfig(file, seen = /* @__PURE__ */ new Set()) {
7068
- if (seen.has(file) || !import_node_fs13.default.existsSync(file)) return {};
7069
- seen.add(file);
7758
+ function readXcconfig(file, read) {
7759
+ if (read.includes(file) || !import_node_fs13.default.existsSync(file)) return {};
7760
+ read.push(file);
7070
7761
  const settings = {};
7071
7762
  for (const raw2 of import_node_fs13.default.readFileSync(file, "utf8").split("\n")) {
7072
7763
  const line = raw2.replace(/\/\/.*$/, "").trim();
@@ -7074,7 +7765,7 @@ function readXcconfig(file, seen = /* @__PURE__ */ new Set()) {
7074
7765
  if (include) {
7075
7766
  Object.assign(
7076
7767
  settings,
7077
- readXcconfig(import_node_path14.default.resolve(import_node_path14.default.dirname(file), include[1]), seen)
7768
+ readXcconfig(import_node_path14.default.resolve(import_node_path14.default.dirname(file), include[1]), read)
7078
7769
  );
7079
7770
  continue;
7080
7771
  }
@@ -7155,7 +7846,7 @@ function workspaceReferences(workspace) {
7155
7846
  function enclosingXcodeWorkspace(xcodeproj) {
7156
7847
  const project = import_node_fs13.default.realpathSync(xcodeproj);
7157
7848
  for (let dir = import_node_path14.default.dirname(project); ; dir = import_node_path14.default.dirname(dir)) {
7158
- for (const name2 of import_node_fs13.default.readdirSync(dir)) {
7849
+ for (const name2 of import_node_fs13.default.readdirSync(dir).sort()) {
7159
7850
  if (!name2.endsWith(".xcworkspace")) continue;
7160
7851
  const workspace = import_node_path14.default.join(dir, name2);
7161
7852
  if (!import_node_fs13.default.existsSync(import_node_path14.default.join(workspace, "contents.xcworkspacedata"))) continue;
@@ -7237,17 +7928,30 @@ function loadProject(xcodeproj) {
7237
7928
  loaded.set(projectFile, { mtimeMs, project: result });
7238
7929
  return result;
7239
7930
  }
7240
- function targetSettings(ref, builtins) {
7931
+ function defaultConfiguration(project) {
7932
+ const configList = project.object(str(project.project.buildConfigurationList));
7933
+ const names = list(configList?.buildConfigurations).flatMap(
7934
+ (id) => str(project.object(id)?.name) ?? []
7935
+ );
7936
+ return names.includes("Debug") ? "Debug" : str(configList?.defaultConfigurationName) ?? names[0] ?? "Debug";
7937
+ }
7938
+ function targetSettings(ref, configuration, builtins) {
7241
7939
  const { project, target } = ref;
7940
+ const xcconfigs = [];
7242
7941
  const level = (listId) => {
7243
- const configs2 = list(project.object(listId)?.buildConfigurations).map(project.object);
7244
- const config = configs2.find((entry) => entry?.name === "Debug") ?? configs2.find(Boolean);
7942
+ const configList = project.object(listId);
7943
+ const configs2 = list(configList?.buildConfigurations).map(project.object);
7944
+ const config = configs2.find((entry) => entry?.name === configuration) ?? configs2.find((entry) => entry?.name === str(configList?.defaultConfigurationName));
7245
7945
  if (!config) return [];
7246
- const name2 = str(config.name) ?? "Debug";
7946
+ const name2 = str(config.name) ?? configuration;
7247
7947
  const base = str(config.baseConfigurationReference);
7248
7948
  const own = isDict(config.buildSettings) ? config.buildSettings : {};
7949
+ const baseFile = base ? project.resolvePath(base) : null;
7950
+ const read = [];
7951
+ const fromFile = baseFile ? readXcconfig(baseFile, read) : {};
7952
+ xcconfigs.push(...read);
7249
7953
  return [
7250
- applyConditions(base ? readXcconfig(project.resolvePath(base) ?? "") : {}, name2),
7954
+ applyConditions(fromFile, name2),
7251
7955
  applyConditions(
7252
7956
  Object.fromEntries(
7253
7957
  Object.entries(own).flatMap(
@@ -7259,7 +7963,7 @@ function targetSettings(ref, builtins) {
7259
7963
  ];
7260
7964
  };
7261
7965
  const levels = [
7262
- builtins,
7966
+ { ...builtins, CONFIGURATION: configuration },
7263
7967
  ...level(str(project.project.buildConfigurationList)),
7264
7968
  ...level(str(target.buildConfigurationList))
7265
7969
  ];
@@ -7298,9 +8002,30 @@ function targetSettings(ref, builtins) {
7298
8002
  };
7299
8003
  return {
7300
8004
  get: (key2) => valueAt(key2, levels.length - 1),
7301
- keys: new Set(levels.flatMap((values) => Object.keys(values)))
8005
+ keys: new Set(levels.flatMap((values) => Object.keys(values))),
8006
+ xcconfigs
7302
8007
  };
7303
8008
  }
8009
+ function settingList(value) {
8010
+ const items2 = [];
8011
+ for (const [, quoted, plain] of value.matchAll(
8012
+ /"((?:\\.|[^"\\])*)"|((?:\\.|[^\s"])+)/g
8013
+ ))
8014
+ items2.push((quoted ?? plain).replace(/\\(.)/g, "$1"));
8015
+ return items2;
8016
+ }
8017
+ function compilationConditions(settings) {
8018
+ const flags = settingList(settings("OTHER_SWIFT_FLAGS"));
8019
+ const defined = flags.flatMap(
8020
+ (flag, index) => flag === "-D" ? flags[index + 1] ?? [] : flag.startsWith("-D") ? flag.slice(2) : []
8021
+ );
8022
+ return [
8023
+ .../* @__PURE__ */ new Set([
8024
+ ...settingList(settings("SWIFT_ACTIVE_COMPILATION_CONDITIONS")),
8025
+ ...defined
8026
+ ])
8027
+ ];
8028
+ }
7304
8029
  function expand(value, lookup) {
7305
8030
  return value.replace(
7306
8031
  /\$(?:\(([A-Za-z_][A-Za-z0-9_]*)((?::[^)]*)?)\)|\{([A-Za-z_][A-Za-z0-9_]*)((?::[^}]*)?)\}|([A-Za-z_][A-Za-z0-9_]*))/g,
@@ -7311,8 +8036,9 @@ function expand(value, lookup) {
7311
8036
  }
7312
8037
  );
7313
8038
  }
7314
- function targetMembers(ref) {
8039
+ function targetMembers(ref, settings, options = {}) {
7315
8040
  const { project, target, id: targetId } = ref;
8041
+ const targetName = str(target.name) ?? targetId;
7316
8042
  const sources = /* @__PURE__ */ new Set();
7317
8043
  const allSources = /* @__PURE__ */ new Set();
7318
8044
  const resources = /* @__PURE__ */ new Set();
@@ -7333,6 +8059,29 @@ function targetMembers(ref) {
7333
8059
  const resolved = project.resolvePath(refId);
7334
8060
  return resolved ? [resolved] : [];
7335
8061
  };
8062
+ const scriptForOutput = /* @__PURE__ */ new Map();
8063
+ const noteScriptOutput = (raw2, script) => {
8064
+ const expanded = expand(raw2, settings);
8065
+ if (!expanded.endsWith(".swift")) return;
8066
+ const absolute = import_node_path14.default.isAbsolute(expanded) ? import_node_path14.default.normalize(expanded) : import_node_path14.default.resolve(project.projectDir, expanded);
8067
+ if (!scriptForOutput.has(absolute)) scriptForOutput.set(absolute, script);
8068
+ };
8069
+ for (const phaseId of list(target.buildPhases)) {
8070
+ const phase = project.object(phaseId);
8071
+ if (phase?.isa !== "PBXShellScriptBuildPhase") continue;
8072
+ const script = str(phase.name) ?? phaseId;
8073
+ for (const raw2 of list(phase.outputPaths)) noteScriptOutput(raw2, script);
8074
+ for (const listPath of list(phase.outputFileListPaths)) {
8075
+ const expandedList = expand(listPath, settings);
8076
+ const absoluteList = import_node_path14.default.isAbsolute(expandedList) ? expandedList : import_node_path14.default.resolve(project.projectDir, expandedList);
8077
+ if (!import_node_fs13.default.existsSync(absoluteList)) continue;
8078
+ for (const line of import_node_fs13.default.readFileSync(absoluteList, "utf8").split("\n")) {
8079
+ const trimmed = line.trim();
8080
+ if (trimmed === "" || trimmed.startsWith("#")) continue;
8081
+ noteScriptOutput(trimmed, script);
8082
+ }
8083
+ }
8084
+ }
7336
8085
  for (const phaseId of list(target.buildPhases)) {
7337
8086
  const phase = project.object(phaseId);
7338
8087
  if (phase?.isa !== "PBXSourcesBuildPhase" && phase?.isa !== "PBXResourcesBuildPhase")
@@ -7340,13 +8089,30 @@ function targetMembers(ref) {
7340
8089
  for (const buildFileId of list(phase.files)) {
7341
8090
  for (const file of fileRefPaths(str(project.object(buildFileId)?.fileRef) ?? "")) {
7342
8091
  if (phase.isa === "PBXSourcesBuildPhase") {
7343
- if (!import_node_fs13.default.existsSync(file)) continue;
8092
+ if (!import_node_fs13.default.existsSync(file)) {
8093
+ if (options.requireSources === false) continue;
8094
+ const script = scriptForOutput.get(import_node_path14.default.normalize(file));
8095
+ throw new Error(
8096
+ script ? `${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)` : `${targetName}: missing source ${file}`
8097
+ );
8098
+ }
7344
8099
  allSources.add(file);
7345
8100
  if (file.endsWith(".swift")) sources.add(file);
7346
8101
  } else if (phase.isa === "PBXResourcesBuildPhase") addResource(file);
7347
8102
  }
7348
8103
  }
7349
8104
  }
8105
+ for (const [file, script] of scriptForOutput) {
8106
+ if (sources.has(file) || allSources.has(file)) continue;
8107
+ if (!import_node_fs13.default.existsSync(file)) {
8108
+ if (options.requireSources === false) continue;
8109
+ throw new Error(
8110
+ `${targetName}: missing generated source ${file} (Run Script "${script}" declares it in outputPaths; run the script or check in its output)`
8111
+ );
8112
+ }
8113
+ allSources.add(file);
8114
+ sources.add(file);
8115
+ }
7350
8116
  const addSynchronized = (folder, relative) => {
7351
8117
  const file = import_node_path14.default.join(folder, relative);
7352
8118
  if (NEVER_MEMBER.test(relative)) return;
@@ -7446,7 +8212,7 @@ function nativeTargets(project) {
7446
8212
  }
7447
8213
  return refs;
7448
8214
  }
7449
- function readXcodeAppTarget(input, targetName) {
8215
+ function readXcodeAppTarget(input, targetName, configurationName, options = {}) {
7450
8216
  const xcodeprojOrWorkspace = import_node_fs13.default.realpathSync(input);
7451
8217
  const workspace = xcodeprojOrWorkspace.endsWith(".xcworkspace") ? xcodeprojOrWorkspace : null;
7452
8218
  const { listed, projects: projects2, projectAt } = workspaceProjects(xcodeprojOrWorkspace);
@@ -7461,6 +8227,7 @@ function readXcodeAppTarget(input, targetName) {
7461
8227
  );
7462
8228
  }
7463
8229
  const app = named[0];
8230
+ const configuration = configurationName ?? defaultConfiguration(app.project);
7464
8231
  const byProduct = /* @__PURE__ */ new Map();
7465
8232
  for (const ref of allTargets) {
7466
8233
  const product = ref.project.object(str(ref.target.productReference));
@@ -7511,9 +8278,14 @@ function readXcodeAppTarget(input, targetName) {
7511
8278
  order.push(ref);
7512
8279
  };
7513
8280
  visit(app);
8281
+ const xcconfigs = /* @__PURE__ */ new Set();
7514
8282
  const moduleTarget = (ref) => {
7515
8283
  const name2 = str(ref.target.name) ?? ref.id;
7516
- const { get: settings2, keys } = targetSettings(ref, {
8284
+ const {
8285
+ get: settings2,
8286
+ keys,
8287
+ xcconfigs: read
8288
+ } = targetSettings(ref, configuration, {
7517
8289
  TARGET_NAME: name2,
7518
8290
  PROJECT_NAME: import_node_path14.default.basename(ref.project.xcodeproj, ".xcodeproj"),
7519
8291
  SRCROOT: ref.project.projectDir,
@@ -7521,6 +8293,7 @@ function readXcodeAppTarget(input, targetName) {
7521
8293
  PROJECT_DIR: ref.project.projectDir,
7522
8294
  DEVELOPMENT_LANGUAGE: str(ref.project.project.developmentRegion) ?? "en"
7523
8295
  });
8296
+ for (const file of read) xcconfigs.add(file);
7524
8297
  const swiftVersion = Number.parseFloat(settings2("SWIFT_VERSION") || "5");
7525
8298
  return {
7526
8299
  settings: settings2,
@@ -7528,9 +8301,10 @@ function readXcodeAppTarget(input, targetName) {
7528
8301
  module: {
7529
8302
  name: name2,
7530
8303
  moduleName: applyOperator(settings2("PRODUCT_MODULE_NAME"), "c99extidentifier"),
7531
- ...targetMembers(ref),
8304
+ ...targetMembers(ref, settings2, options),
7532
8305
  languageMode: swiftVersion >= 6 ? 6 : 5,
7533
- mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor"
8306
+ mainActorIsolation: settings2("SWIFT_DEFAULT_ACTOR_ISOLATION") === "MainActor",
8307
+ defines: compilationConditions(settings2)
7534
8308
  }
7535
8309
  };
7536
8310
  };
@@ -7636,7 +8410,9 @@ function readXcodeAppTarget(input, targetName) {
7636
8410
  )
7637
8411
  ].map((dir) => import_node_fs13.default.realpathSync(dir))
7638
8412
  ),
7639
- projectFiles: [...new Set(used.map((project) => project.projectFile))].sort(),
8413
+ projectFiles: [
8414
+ .../* @__PURE__ */ new Set([...used.map((project) => project.projectFile), ...xcconfigs])
8415
+ ].sort(),
7640
8416
  appIconName: settings("ASSETCATALOG_COMPILER_APPICON_NAME"),
7641
8417
  infoPlist: import_plist.default.build(info),
7642
8418
  infoPlistFile,
@@ -7647,7 +8423,9 @@ function readXcodeAppTarget(input, targetName) {
7647
8423
  ].sort(),
7648
8424
  binaryFrameworks: [...binaryFrameworks].map(([name2, file]) => ({ name: name2, path: file })).sort((left, right) => left.name.localeCompare(right.name)),
7649
8425
  packageResolved: import_node_fs13.default.existsSync(resolvedFile) ? resolvedFile : null,
7650
- appTargets: appTargetNames
8426
+ appTargets: appTargetNames,
8427
+ configuration,
8428
+ settings
7651
8429
  };
7652
8430
  }
7653
8431
 
@@ -7788,7 +8566,7 @@ function swiftPackages(entry, app) {
7788
8566
  cached2.standinKey = generation;
7789
8567
  }
7790
8568
  }
7791
- return cached2;
8569
+ return { ...cached2, binaries: reached };
7792
8570
  }
7793
8571
  var XCODE_APP_DIR = "__app__";
7794
8572
  var XCODE_FRAMEWORKS_DIR = "__frameworks__";
@@ -7803,14 +8581,37 @@ function xcodeInputKey(layout, file, relative) {
7803
8581
  function xcodeLayout(root) {
7804
8582
  const registered = xcodeProjects.get(root);
7805
8583
  if (!registered) return null;
7806
- const app = readXcodeAppTarget(registered.xcodeproj, registered.target);
7807
- const files2 = /* @__PURE__ */ new Set([...app.projectFiles, ...app.sources, ...app.resources]);
8584
+ const app = readXcodeAppTarget(
8585
+ registered.xcodeproj,
8586
+ registered.target,
8587
+ registered.configuration
8588
+ );
8589
+ const appSources = app.allSources.filter(
8590
+ (file) => file.endsWith(".swift") || file.endsWith(".metal")
8591
+ );
8592
+ const files2 = /* @__PURE__ */ new Set([...app.projectFiles, ...appSources, ...app.resources]);
7808
8593
  if (app.infoPlistFile) files2.add(app.infoPlistFile);
7809
- const targetDirs = new Map(app.sources.map((file) => [file, XCODE_APP_DIR]));
8594
+ const targetDirs = new Map(
8595
+ [...appSources, ...app.resources].map((file) => [file, XCODE_APP_DIR])
8596
+ );
8597
+ const resourceBundles = [
8598
+ { target: app.moduleName, sourcePath: XCODE_APP_DIR, path: "." }
8599
+ ];
7810
8600
  const targets = [];
7811
8601
  for (const framework of app.frameworks) {
7812
8602
  const dir = import_node_path15.default.posix.join(XCODE_FRAMEWORKS_DIR, framework.moduleName);
7813
- for (const file of framework.sources) {
8603
+ resourceBundles.push({
8604
+ target: framework.moduleName,
8605
+ sourcePath: dir,
8606
+ path: `Frameworks/${framework.moduleName}.framework`
8607
+ });
8608
+ for (const file of framework.allSources) {
8609
+ if (!file.endsWith(".swift") && !file.endsWith(".metal")) continue;
8610
+ if (targetDirs.has(file)) continue;
8611
+ targetDirs.set(file, dir);
8612
+ files2.add(file);
8613
+ }
8614
+ for (const file of framework.resources) {
7814
8615
  if (targetDirs.has(file)) continue;
7815
8616
  targetDirs.set(file, dir);
7816
8617
  files2.add(file);
@@ -7822,10 +8623,11 @@ function xcodeLayout(root) {
7822
8623
  resources: false,
7823
8624
  exclude: [],
7824
8625
  languageMode: framework.languageMode,
7825
- mainActorIsolation: framework.mainActorIsolation
8626
+ mainActorIsolation: framework.mainActorIsolation,
8627
+ defines: framework.defines
7826
8628
  });
7827
8629
  }
7828
- const { packages, standins, projectGaps } = swiftPackages(registered, app);
8630
+ const { packages, standins, projectGaps, binaries } = swiftPackages(registered, app);
7829
8631
  for (const standin of standins)
7830
8632
  targets.push({
7831
8633
  name: standin.module,
@@ -7836,6 +8638,7 @@ function xcodeLayout(root) {
7836
8638
  languageMode: 5,
7837
8639
  mainActorIsolation: false
7838
8640
  });
8641
+ const packageConfiguration = app.configuration === "Debug" ? "debug" : "release";
7839
8642
  for (const target of packages.targets) {
7840
8643
  const relative = import_node_path15.default.relative(
7841
8644
  target.remote ? import_node_path15.default.join(root, REMOTE_CHECKOUTS) : root,
@@ -7847,8 +8650,21 @@ function xcodeLayout(root) {
7847
8650
  targets.push({
7848
8651
  ...target,
7849
8652
  path: target.remote ? import_node_path15.default.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
7850
- exclude: []
8653
+ exclude: [],
8654
+ defines: [
8655
+ ...packageConfiguration === "debug" ? ["DEBUG"] : [],
8656
+ ...target.packageDefines.filter(
8657
+ (define) => define.configuration === null || define.configuration === packageConfiguration
8658
+ ).map((define) => define.name)
8659
+ ]
7851
8660
  });
8661
+ if (target.resources) {
8662
+ resourceBundles.push({
8663
+ target: target.name,
8664
+ sourcePath: target.remote ? import_node_path15.default.posix.join(XCODE_PACKAGES_DIR, posix) : posix,
8665
+ path: `${swiftPackageManifest(target.packageDir).name}_${target.name}.bundle`
8666
+ });
8667
+ }
7852
8668
  if (!target.remote) files2.add(import_node_path15.default.join(target.packageDir, "Package.swift"));
7853
8669
  for (const file of target.files) files2.add(file);
7854
8670
  }
@@ -7860,20 +8676,26 @@ function xcodeLayout(root) {
7860
8676
  targets,
7861
8677
  packages,
7862
8678
  standins,
8679
+ binaries,
7863
8680
  projectGaps,
7864
8681
  targetDirs,
8682
+ resourceBundles,
7865
8683
  files: [...files2].sort()
7866
8684
  };
7867
8685
  }
7868
8686
  function xcodeManifest(layout) {
7869
- const settings = (mode, mainActor) => `swiftSettings: [.swiftLanguageMode(.v${mode})${mainActor ? ", .defaultIsolation(MainActor.self)" : ""}]`;
8687
+ const settings = (target) => `swiftSettings: [${[
8688
+ `.swiftLanguageMode(.v${target.languageMode})`,
8689
+ ...target.mainActorIsolation ? [".defaultIsolation(MainActor.self)"] : [],
8690
+ ...(target.defines ?? []).map((name2) => `.define(${JSON.stringify(name2)})`)
8691
+ ].join(", ")}]`;
7870
8692
  return [
7871
8693
  "// swift-tools-version: 6.2",
7872
8694
  "import PackageDescription",
7873
8695
  'let package = Package(name: "app", targets: [',
7874
- ` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app.languageMode, layout.app.mainActorIsolation)}),`,
8696
+ ` .executableTarget(name: "${layout.app.moduleName}", path: "${XCODE_APP_DIR}", ${settings(layout.app)}),`,
7875
8697
  ...layout.targets.map(
7876
- (target) => ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ""}${target.resources ? "resources: [], " : ""}${settings(target.languageMode, target.mainActorIsolation)}),`
8698
+ (target) => ` .target(name: "${target.name}", path: "${target.path}", ${target.exclude.length > 0 ? `exclude: ${JSON.stringify(target.exclude)}, ` : ""}${target.resources ? "resources: [], " : ""}${settings(target)}),`
7877
8699
  ),
7878
8700
  "])",
7879
8701
  ""
@@ -7914,7 +8736,7 @@ function sourceFiles(root) {
7914
8736
  }
7915
8737
  function resourceCandidateFiles(root) {
7916
8738
  return packageFiles(root).filter(
7917
- (file) => !file.endsWith(".swift") && !["project.pbxproj", "project.xcproj"].includes(import_node_path15.default.basename(file))
8739
+ (file) => !file.endsWith(".swift") && !file.endsWith(".xcconfig") && !["project.pbxproj", "project.xcproj"].includes(import_node_path15.default.basename(file))
7918
8740
  );
7919
8741
  }
7920
8742
  var HOSTED_LIMITS = {
@@ -7944,7 +8766,7 @@ var RESOURCE_CONTENT_TYPES = {
7944
8766
  ".png": "image/png",
7945
8767
  ".webp": "image/webp"
7946
8768
  };
7947
- function buildSwiftResourceTable(project, baseUrl) {
8769
+ function buildSwiftResourceTable(project, baseUrl, inputs) {
7948
8770
  const limits = inputLimits(Boolean(project.hosted));
7949
8771
  const absolute = resourceCandidateFiles(project.packagePath);
7950
8772
  const relative = absolute.map(
@@ -7959,15 +8781,77 @@ function buildSwiftResourceTable(project, baseUrl) {
7959
8781
  "utf8"
7960
8782
  );
7961
8783
  };
7962
- const found = enumerateBundleImages(relative, readContents);
7963
- const colors = enumerateBundleColors(relative, readContents);
7964
- const symbols = enumerateBundleSymbols(relative, readContents);
7965
- const table = {};
8784
+ const layout = xcodeLayout(project.packagePath);
8785
+ const bundles = layout?.resourceBundles ?? swiftResourceBundles(inputs, relative);
8786
+ const catalogFiles = relative.filter((file) => {
8787
+ const disk = byRelative.get(file);
8788
+ return !disk || !layout?.targetDirs.get(disk)?.startsWith(`${XCODE_FRAMEWORKS_DIR}/`);
8789
+ });
8790
+ const found = enumerateBundleImages(relative, readContents, (file) => {
8791
+ const disk = byRelative.get(file);
8792
+ if (!disk) throw new Error(`image source ${file} has no input file`);
8793
+ const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
8794
+ return swiftResourceBundleForFile(bundles, key2)?.path ?? ".";
8795
+ });
8796
+ const colors = enumerateBundleColors(catalogFiles, readContents);
8797
+ const symbols = enumerateBundleSymbols(catalogFiles, readContents, (file) => {
8798
+ const disk = byRelative.get(file);
8799
+ if (!disk) throw new Error(`symbol source ${file} has no input file`);
8800
+ const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
8801
+ return swiftResourceBundleForFile(bundles, key2)?.path ?? ".";
8802
+ });
8803
+ const table = /* @__PURE__ */ Object.create(null);
7966
8804
  const images = {};
8805
+ const metalSources = {};
8806
+ const metalUploads = {};
7967
8807
  const watched = [];
7968
8808
  const registered = /* @__PURE__ */ new Map();
8809
+ const shaderFiles = relative.filter((file) => file.endsWith(".metal"));
8810
+ const metalCandidates = {};
8811
+ if (inputs["Package.swift"] !== void 0)
8812
+ metalCandidates["Package.swift"] = inputs["Package.swift"];
8813
+ const metalInputs = /* @__PURE__ */ new Map();
8814
+ for (const file of shaderFiles) {
8815
+ const disk = byRelative.get(file);
8816
+ if (!disk) throw new Error(`metal source ${file} has no input file`);
8817
+ const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
8818
+ metalCandidates[key2] = "";
8819
+ metalInputs.set(key2, { file, disk });
8820
+ }
8821
+ const metalFiles = Object.keys(swiftMetalSourceFiles(metalCandidates));
8822
+ if (metalFiles.length > MAX_SWIFT_COMPILE_METAL_FILES)
8823
+ throw new Error("metal source pack exceeds the compile service file cap");
8824
+ let metalBytes = 0;
8825
+ for (const key2 of metalFiles) {
8826
+ const input = metalInputs.get(key2);
8827
+ if (!input) throw new Error(`metal source ${key2} has no input file`);
8828
+ const { file, disk } = input;
8829
+ const bytes = readPackageFile(
8830
+ project.packagePath,
8831
+ disk,
8832
+ MAX_SWIFT_COMPILE_METAL_BYTES
8833
+ );
8834
+ metalBytes += bytes.length;
8835
+ if (metalBytes > MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES)
8836
+ throw new Error("metal source pack exceeds the compile service caps");
8837
+ const source = new TextDecoder("utf-8", { fatal: true, ignoreBOM: true }).decode(
8838
+ bytes
8839
+ );
8840
+ const sha256 = (0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex");
8841
+ const bundle = swiftResourceBundleForFile(bundles, key2);
8842
+ if (!bundle && inputs["Package.swift"])
8843
+ throw new Error(`metal source ${key2} has no resource target bundle`);
8844
+ metalSources[key2] = {
8845
+ sha256,
8846
+ url: `${baseUrl}${RESOURCE_PATH}${sha256}.metal`,
8847
+ bundlePath: bundle?.path ?? "."
8848
+ };
8849
+ metalUploads[key2] = source;
8850
+ watched.push(file);
8851
+ registered.set(`${sha256}.metal`, { bytes, contentType: "text/plain; charset=utf-8" });
8852
+ }
7969
8853
  let imageBytes = 0;
7970
- for (const { name: name2, file, scale } of found) {
8854
+ for (const { name: name2, file, scale, bundlePath } of found) {
7971
8855
  const disk = byRelative.get(file);
7972
8856
  if (!disk) continue;
7973
8857
  if (Object.keys(images).length >= limits.images || imageBytes + import_node_fs14.default.statSync(disk).size > limits.imageTotalBytes) {
@@ -7977,8 +8861,12 @@ function buildSwiftResourceTable(project, baseUrl) {
7977
8861
  imageBytes += bytes.length;
7978
8862
  const hash = (0, import_node_crypto7.createHash)("sha256").update(bytes).digest("hex").slice(0, 16);
7979
8863
  const ext = import_node_path15.default.posix.extname(file).toLowerCase();
7980
- table[name2] = { uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale };
7981
- images[name2] = {
8864
+ const bundle = table[bundlePath] ?? /* @__PURE__ */ Object.create(null);
8865
+ const variants = bundle[name2] ??= [];
8866
+ variants.push({ uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale });
8867
+ table[bundlePath] = bundle;
8868
+ const key2 = layout ? xcodeInputKey(layout, disk, file) : file;
8869
+ images[key2] = {
7982
8870
  file: import_node_path15.default.posix.basename(file),
7983
8871
  data: bytes.toString("base64")
7984
8872
  };
@@ -8000,9 +8888,9 @@ function buildSwiftResourceTable(project, baseUrl) {
8000
8888
  project.resourcesPrevious = project.resourceFiles;
8001
8889
  project.resourceFiles = registered;
8002
8890
  }
8003
- return { table, images, colors, symbols, watched };
8891
+ return { table, images, metalSources, metalUploads, colors, symbols, watched };
8004
8892
  }
8005
- function buildSwiftBundleFiles(packagePath, hosted) {
8893
+ function buildSwiftBundleFiles(packagePath, hosted, inputs) {
8006
8894
  packagePath = import_node_fs14.default.realpathSync(packagePath);
8007
8895
  const limits = inputLimits(hosted);
8008
8896
  const relative = resourceCandidateFiles(packagePath).map(
@@ -8012,30 +8900,51 @@ function buildSwiftBundleFiles(packagePath, hosted) {
8012
8900
  const watched = [];
8013
8901
  let total = 0;
8014
8902
  const xcode = xcodeLayout(packagePath);
8903
+ const bundles = xcode?.resourceBundles ?? swiftResourceBundles(inputs ?? packageSources(packagePath), relative);
8904
+ const addFile = (key2, bytes) => {
8905
+ if (Object.keys(files2).length >= limits.resources || bytes.length > limits.resourceBytes || total + bytes.length > limits.resourceTotalBytes)
8906
+ throw new Error(
8907
+ `swift bundle pack exceeds ${limits.resources} files / ${limits.resourceTotalBytes} bytes`
8908
+ );
8909
+ files2[key2] = bytes.toString("base64");
8910
+ total += bytes.length;
8911
+ };
8015
8912
  if (xcode) {
8016
8913
  const bytes = Buffer.from(xcode.app.infoPlist);
8017
8914
  if (bytes.length > limits.resourceBytes || bytes.length > limits.resourceTotalBytes)
8018
8915
  throw new Error("swift launch Info.plist exceeds bundle resource limits");
8019
- files2["Info.plist"] = bytes.toString("base64");
8020
- total += bytes.length;
8916
+ addFile("Info.plist", bytes);
8021
8917
  if (xcode.app.infoPlistFile)
8022
8918
  watched.push(
8023
8919
  import_node_path15.default.relative(packagePath, xcode.app.infoPlistFile).split(import_node_path15.default.sep).join("/")
8024
8920
  );
8025
8921
  }
8026
- for (const { base, file } of enumerateBundleJson(relative)) {
8027
- watched.push(file);
8922
+ const groups = /* @__PURE__ */ new Map();
8923
+ for (const file of relative) {
8028
8924
  const disk = import_node_path15.default.join(packagePath, ...file.split("/"));
8029
- if (Object.keys(files2).length >= limits.resources || total + import_node_fs14.default.statSync(disk).size > limits.resourceTotalBytes) {
8030
- throw new Error(
8031
- `swift bundle pack exceeds ${limits.resources} files / ${limits.resourceTotalBytes} bytes`
8032
- );
8925
+ const key2 = xcode ? xcodeInputKey(xcode, disk, file) : file;
8926
+ const bundle = swiftResourceBundleForFile(bundles, key2);
8927
+ const bundlePath = bundle?.path ?? ".";
8928
+ const group = groups.get(bundlePath) ?? [];
8929
+ group.push(file);
8930
+ groups.set(bundlePath, group);
8931
+ }
8932
+ for (const bundle of bundles) {
8933
+ if (bundle.path === ".") continue;
8934
+ addFile(
8935
+ `${bundle.path}/Info.plist`,
8936
+ Buffer.from(swiftResourceBundleInfoPlist(bundle))
8937
+ );
8938
+ }
8939
+ for (const [bundlePath, paths] of groups) {
8940
+ for (const { base, file } of enumerateBundleResources(paths)) {
8941
+ watched.push(file);
8942
+ const disk = import_node_path15.default.join(packagePath, ...file.split("/"));
8943
+ const bytes = readPackageFile(packagePath, disk, limits.resourceBytes);
8944
+ addFile(bundlePath === "." ? base : `${bundlePath}/${base}`, bytes);
8033
8945
  }
8034
- const bytes = readPackageFile(packagePath, disk, limits.resourceBytes);
8035
- files2[base] = bytes.toString("base64");
8036
- total += bytes.length;
8037
8946
  }
8038
- return { files: files2, watched };
8947
+ return { files: files2, bundles, watched };
8039
8948
  }
8040
8949
  function serveSwiftResource(project, key2) {
8041
8950
  return project.resourceFiles.get(key2) ?? project.resourcesPrevious.get(key2) ?? null;
@@ -8088,7 +8997,20 @@ function entryRootId(packagePath, file) {
8088
8997
  function icuUrl(origin, artifact) {
8089
8998
  return "url" in artifact.icu ? artifact.icu.url : `${origin}${ICU_PATH}${artifact.icu.sha256}`;
8090
8999
  }
8091
- function packageSources(packagePath) {
9000
+ function standinLibraries(layout) {
9001
+ const linked = /* @__PURE__ */ new Map();
9002
+ for (const binary of layout.binaries) {
9003
+ const modules = layout.standins.filter(
9004
+ (standin) => standin.target === binary.target && `${standin.module}.c` in standin.files
9005
+ );
9006
+ if (modules.length === 0) continue;
9007
+ const library = standinLibrary(binary, layout.app.rootDir);
9008
+ if (!library) continue;
9009
+ linked.set(library, modules);
9010
+ }
9011
+ return linked;
9012
+ }
9013
+ function packageSources(packagePath, linked = /* @__PURE__ */ new Set()) {
8092
9014
  const xcode = xcodeLayout(packagePath);
8093
9015
  const files2 = {};
8094
9016
  for (const file of sourceFiles(packagePath)) {
@@ -8104,25 +9026,40 @@ function packageSources(packagePath) {
8104
9026
  files2["Package.swift"] = xcodeManifest(xcode);
8105
9027
  for (const standin of xcode.standins)
8106
9028
  for (const [file, text3] of Object.entries(standin.files))
8107
- files2[import_node_path15.default.posix.join(XCODE_STANDINS_DIR, standin.module, file)] = text3;
9029
+ files2[import_node_path15.default.posix.join(XCODE_STANDINS_DIR, standin.module, file)] = linked.has(standin) && file === `${standin.module}.c` ? `// ${standin.target}'s WebAssembly library defines ${standin.module}'s functions.
9030
+ ` : text3;
8108
9031
  }
8109
9032
  return files2;
8110
9033
  }
8111
9034
  function packageSnapshot(project, entry) {
8112
- const files2 = packageSources(project.packagePath);
8113
9035
  const layout = xcodeLayout(project.packagePath);
9036
+ const linked = layout ? standinLibraries(layout) : /* @__PURE__ */ new Map();
9037
+ const files2 = packageSources(project.packagePath, new Set([...linked.values()].flat()));
8114
9038
  const native = nativeSourceDescriptor(project.packagePath);
8115
9039
  return {
8116
9040
  files: files2,
8117
9041
  entry: layout ? xcodeInputKey(layout, import_node_path15.default.resolve(project.packagePath, entry), entry) : entry,
8118
9042
  resourcePaths: swiftImplicitResourcePaths(
8119
- resourceCandidateFiles(project.packagePath).map(
8120
- (file) => import_node_path15.default.relative(project.packagePath, file).split(import_node_path15.default.sep).join(import_node_path15.default.posix.sep)
8121
- )
9043
+ resourceCandidateFiles(project.packagePath).map((file) => {
9044
+ const relative = import_node_path15.default.relative(project.packagePath, file).split(import_node_path15.default.sep).join(import_node_path15.default.posix.sep);
9045
+ return layout && file.endsWith(".metal") ? xcodeInputKey(layout, file, relative) : relative;
9046
+ })
9047
+ ),
9048
+ resources: buildSwiftResourceTable(project, "", files2),
9049
+ bundleFiles: buildSwiftBundleFiles(
9050
+ project.packagePath,
9051
+ Boolean(project.hosted),
9052
+ files2
8122
9053
  ),
8123
- resources: buildSwiftResourceTable(project, ""),
8124
- bundleFiles: buildSwiftBundleFiles(project.packagePath, Boolean(project.hosted)),
8125
9054
  native,
9055
+ ...linked.size > 0 ? {
9056
+ libraries: Object.fromEntries(
9057
+ [...linked].map(([library, [first]]) => [
9058
+ first.module,
9059
+ import_node_fs14.default.readFileSync(library).toString("base64")
9060
+ ])
9061
+ )
9062
+ } : {},
8126
9063
  ...native ? {
8127
9064
  glue: readPackageFile(
8128
9065
  project.packagePath,
@@ -8135,11 +9072,14 @@ function packageSnapshot(project, entry) {
8135
9072
  function snapshotCompileInput(snapshot) {
8136
9073
  const input = {
8137
9074
  files: snapshot.files,
9075
+ metalSources: snapshot.resources.metalUploads,
8138
9076
  resourcePaths: snapshot.resourcePaths,
9077
+ resourceBundles: snapshot.bundleFiles.bundles,
8139
9078
  resources: snapshot.bundleFiles.files,
8140
9079
  images: snapshot.resources.images,
8141
9080
  entry: snapshot.entry,
8142
- oneModule: true
9081
+ oneModule: true,
9082
+ ...snapshot.libraries ? { libraries: snapshot.libraries } : {}
8143
9083
  };
8144
9084
  return snapshot.glue ? withNativeSourceGlue(input, snapshot.glue) : input;
8145
9085
  }
@@ -8151,6 +9091,7 @@ async function compile(packagePath, stamp, moduleRootOverride, hosted, snapshot)
8151
9091
  table: snapshot.resources.table,
8152
9092
  colors: snapshot.resources.colors,
8153
9093
  symbols: snapshot.resources.symbols,
9094
+ metalSources: snapshot.resources.metalSources,
8154
9095
  watched: snapshot.resources.watched
8155
9096
  };
8156
9097
  const content = {
@@ -8258,10 +9199,6 @@ function swiftApiGapReport(output) {
8258
9199
  ...other.size > 0 ? ["other errors, often caused by the ones above:", ...rows(other)] : []
8259
9200
  ].join("\n");
8260
9201
  }
8261
- var UNPROVIDED_PLATFORM_MODULES = {
8262
- Darwin: "Peach compiles for WebAssembly, which has no Darwin; C library names come through Foundation",
8263
- MachO: "Peach compiles for WebAssembly, which has no Mach-O images"
8264
- };
8265
9202
  var IOS_SDK_FRAMEWORKS = new Set(ios_sdk_frameworks_default.frameworks);
8266
9203
  async function missingModulesMessage(packagePath, missing) {
8267
9204
  const layout = xcodeLayout(packagePath);
@@ -8277,12 +9214,7 @@ async function missingModulesMessage(packagePath, missing) {
8277
9214
  ];
8278
9215
  }),
8279
9216
  ...[...missing.keys()].flatMap(
8280
- (name2) => UNPROVIDED_PLATFORM_MODULES[name2] ? [
8281
- [
8282
- name2,
8283
- { source: "the iOS SDK", reason: UNPROVIDED_PLATFORM_MODULES[name2] }
8284
- ]
8285
- ] : IOS_SDK_FRAMEWORKS.has(name2) ? [
9217
+ (name2) => IOS_SDK_FRAMEWORKS.has(name2) ? [
8286
9218
  [
8287
9219
  name2,
8288
9220
  { source: "the iOS SDK", reason: "a framework Peach does not provide" }
@@ -8293,9 +9225,7 @@ async function missingModulesMessage(packagePath, missing) {
8293
9225
  ...layout?.packages.unavailable ?? []
8294
9226
  ]);
8295
9227
  const packaged = new Set(
8296
- [...missing.keys()].filter(
8297
- (name2) => !UNPROVIDED_PLATFORM_MODULES[name2] && !IOS_SDK_FRAMEWORKS.has(name2)
8298
- )
9228
+ [...missing.keys()].filter((name2) => !IOS_SDK_FRAMEWORKS.has(name2))
8299
9229
  );
8300
9230
  if (packaged.size > 0)
8301
9231
  await Promise.all(
@@ -8354,7 +9284,9 @@ async function compileRemote(packagePath, snapshot, hosted) {
8354
9284
  submit,
8355
9285
  {
8356
9286
  files: snapshot.files,
9287
+ metalSources: snapshot.resources.metalUploads,
8357
9288
  resourcePaths: snapshot.resourcePaths,
9289
+ resourceBundles: snapshot.bundleFiles.bundles,
8358
9290
  resources: snapshot.bundleFiles.files,
8359
9291
  images: snapshot.resources.images,
8360
9292
  entry: snapshot.entry,
@@ -8473,19 +9405,23 @@ async function swiftPackageMetadata(packagePath, packageName, moduleRoot, origin
8473
9405
  hash: artifact.hash,
8474
9406
  icuUrl: icuUrl(origin, artifact),
8475
9407
  rootId: `${packageName}/${entry}`,
8476
- resources: Object.fromEntries(
8477
- Object.entries(resources.table).map(([name2, image]) => [
8478
- name2,
8479
- { ...image, uri: `${origin}${image.uri}` }
8480
- ])
8481
- ),
9408
+ resources: resolveSwiftImageResourceUrls(resources.table, origin),
8482
9409
  bundleFiles: bundleFiles.files,
9410
+ ...Object.keys(resources.metalSources).length === 0 ? {} : {
9411
+ metalSources: Object.fromEntries(
9412
+ Object.entries(resources.metalSources).map(([file, source]) => [
9413
+ file,
9414
+ { ...source, url: `${origin}${source.url}` }
9415
+ ])
9416
+ )
9417
+ },
8483
9418
  colors: resources.colors,
8484
9419
  symbols: resources.symbols,
8485
9420
  native: artifact.package.native ? {
8486
9421
  packageId: artifact.package.native.packageId,
8487
9422
  contractHash: artifact.package.native.hash,
8488
9423
  modules: artifact.package.native.modules,
9424
+ views: Object.keys(artifact.package.native.views),
8489
9425
  defaultView: mains.length === 1
8490
9426
  } : void 0
8491
9427
  };
@@ -8801,11 +9737,9 @@ function swiftPlugin(options = {}) {
8801
9737
  this.warn(error instanceof Error ? error.message : String(error));
8802
9738
  artifact = project.artifact;
8803
9739
  }
8804
- const resources = Object.fromEntries(
8805
- Object.entries(artifact.package.resources.table).map(([name2, image]) => [
8806
- name2,
8807
- { ...image, uri: `${serverOrigin()}${image.uri}` }
8808
- ])
9740
+ const resources = resolveSwiftImageResourceUrls(
9741
+ artifact.package.resources.table,
9742
+ serverOrigin()
8809
9743
  );
8810
9744
  for (const watched of [
8811
9745
  ...artifact.package.resources.watched,