peachsim 0.1.1406 → 0.1.1465

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 (150) hide show
  1. package/LICENSE +8 -4
  2. package/README.md +22 -2
  3. package/cli/app-fonts.ts +50 -44
  4. package/cli/bin.ts +5 -4
  5. package/cli/bridge-diagnostics.ts +5 -0
  6. package/cli/bridge-flow-runner.ts +21 -13
  7. package/cli/cloud-client.ts +4 -3
  8. package/cli/commands/control.ts +155 -123
  9. package/cli/commands/daemon-mac-app.ts +3 -3
  10. package/cli/commands/daemon.ts +2 -2
  11. package/cli/commands/do-chain.ts +9 -2
  12. package/cli/commands/electron.ts +4 -1
  13. package/cli/commands/inspect/core.ts +1 -1
  14. package/cli/commands/inspect/settle.ts +19 -7
  15. package/cli/commands/inspect/settling.ts +92 -56
  16. package/cli/commands/inspect/wait-idle.ts +21 -9
  17. package/cli/commands/inspect/wait-ready.ts +22 -8
  18. package/cli/commands/inspect.ts +101 -134
  19. package/cli/commands/setup.ts +26 -16
  20. package/cli/commands/upgrade.ts +53 -9
  21. package/cli/desktop-companion.ts +1 -1
  22. package/cli/drivers/playwright-sim-host.ts +32 -13
  23. package/cli/drivers/playwright.ts +3 -3
  24. package/cli/main.ts +14 -5
  25. package/cli/outbound-endpoints.ts +1 -9
  26. package/detox/index.ts +6 -1
  27. package/dist-lib/agent-daemon-client.cjs +1 -1
  28. package/dist-lib/agent-events.cjs +1 -1
  29. package/dist-lib/attached-projects.cjs +1 -1
  30. package/dist-lib/auth/shared-session.cjs +1 -1
  31. package/dist-lib/backend-origin.cjs +1 -1
  32. package/dist-lib/beta.cjs +1 -1
  33. package/dist-lib/beta.mjs +1 -1
  34. package/dist-lib/bridge-constants.cjs +1 -1
  35. package/dist-lib/bridge-contract-input.cjs +1 -1
  36. package/dist-lib/bridge-contract-input.mjs +1 -1
  37. package/dist-lib/bridge-contract.cjs +3 -3
  38. package/dist-lib/bridge-contract.mjs +3 -3
  39. package/dist-lib/bundle-channel.cjs +322 -274
  40. package/dist-lib/capture-contract.cjs +1 -1
  41. package/dist-lib/capture-contract.mjs +1 -1
  42. package/dist-lib/cloud-contract.cjs +1 -1
  43. package/dist-lib/cloud-contract.mjs +1 -1
  44. package/dist-lib/cloud-test-args.cjs +1 -1
  45. package/dist-lib/cloud-test-args.mjs +1 -1
  46. package/dist-lib/cloud.cjs +1 -1
  47. package/dist-lib/cloud.mjs +1 -1
  48. package/dist-lib/config.cjs +1 -1
  49. package/dist-lib/config.mjs +1 -1
  50. package/dist-lib/detox/index.cjs +512 -122
  51. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  52. package/dist-lib/expo-swift-bundle.cjs +69 -33
  53. package/dist-lib/expo-swift-metadata.cjs +1 -1
  54. package/dist-lib/expo-swift-metadata.mjs +1 -1
  55. package/dist-lib/home-paths.cjs +1 -1
  56. package/dist-lib/host/bridge-host.cjs +3650 -3528
  57. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  58. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  59. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  60. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  61. package/dist-lib/host/websocket-proxy.cjs +1 -1
  62. package/dist-lib/index.cjs +327 -123
  63. package/dist-lib/jump-to-source-babel.cjs +1 -1
  64. package/dist-lib/jump-to-source-native.cjs +1 -1
  65. package/dist-lib/kotlin-host.cjs +10 -5
  66. package/dist-lib/menu.cjs +1 -1
  67. package/dist-lib/menu.mjs +1 -1
  68. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  69. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  70. package/dist-lib/metro-production-bundle.cjs +1 -1
  71. package/dist-lib/metro-production-bundle.mjs +1 -1
  72. package/dist-lib/metro.cjs +49 -47
  73. package/dist-lib/native-app-identity-project.cjs +1 -1
  74. package/dist-lib/native-app-identity-project.mjs +1 -1
  75. package/dist-lib/native-app-identity.cjs +1 -1
  76. package/dist-lib/native-app-identity.mjs +1 -1
  77. package/dist-lib/native-firebase-metadata.cjs +1 -1
  78. package/dist-lib/native-firebase-metadata.mjs +1 -1
  79. package/dist-lib/plist.cjs +1 -1
  80. package/dist-lib/plist.mjs +1 -1
  81. package/dist-lib/profiles.cjs +1 -1
  82. package/dist-lib/public-brand.cjs +1 -1
  83. package/dist-lib/react-native-host-modules.cjs +1 -1
  84. package/dist-lib/react-native-host-modules.mjs +1 -1
  85. package/dist-lib/scripts/dev-server-scanner.cjs +23 -17
  86. package/dist-lib/sdk.cjs +99 -61
  87. package/dist-lib/sdk.mjs +97 -61
  88. package/dist-lib/skills.cjs +3347 -3051
  89. package/dist-lib/swift-compile.cjs +26 -12
  90. package/dist-lib/swift-compile.mjs +26 -12
  91. package/dist-lib/swift-package.cjs +1 -1
  92. package/dist-lib/swift-package.mjs +1 -1
  93. package/dist-lib/swift-submit.cjs +2 -2
  94. package/dist-lib/swift-submit.mjs +2 -2
  95. package/dist-lib/swift-toolchain.cjs +1 -1
  96. package/dist-lib/swift.cjs +1 -1
  97. package/dist-lib/vite-swift.cjs +66 -31
  98. package/dist-lib/vite.cjs +1 -1
  99. package/dist-lib/worklet-executable.cjs +5 -1
  100. package/dist-lib/worklet-executable.mjs +5 -1
  101. package/kotlin/AppSources/android/view/Window.kt +2 -0
  102. package/kotlin/AppSources/dev/peach/app/PeachApp.kt +1 -1
  103. package/kotlin/ComposeSources/PeachComposeHost.kt +35 -9
  104. package/kotlin/ExpoComposeSources/dev/peach/expo/PeachExpoCompose.kt +2 -2
  105. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoRuntime.kt +9 -6
  106. package/kotlin/ExpoSources/dev/peach/expo/PeachExpoTypes.kt +4 -4
  107. package/kotlin/ExpoSources/expo/modules/kotlin/modules/Module.kt +2 -2
  108. package/kotlin/ExpoSources/expo/modules/kotlin/viewevent/ViewEvent.kt +22 -8
  109. package/kotlin/ExpoSources/expo/modules/kotlin/views/ExpoView.kt +0 -3
  110. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewDefinitionBuilder.kt +10 -9
  111. package/kotlin/ExpoSources/expo/modules/kotlin/views/ViewProps.kt +6 -5
  112. package/kotlin/fixtures/import-drawing/Drawing.d.kt.ts +7 -0
  113. package/kotlin/fixtures/import-drawing/Drawing.kt +101 -0
  114. package/kotlin/fixtures/import-drawing/ImportDrawing.native.tsx +18 -0
  115. package/kotlin/fixtures/import-drawing/README.md +34 -0
  116. package/kotlin/fixtures/import-drawing/app/_layout.tsx +4 -0
  117. package/kotlin/fixtures/import-drawing/app/index+spa.tsx +1 -0
  118. package/kotlin/fixtures/import-drawing/package.json +23 -0
  119. package/kotlin/fixtures/import-drawing/tsconfig.json +20 -0
  120. package/kotlin/fixtures/import-drawing/vite.config.ts +20 -0
  121. package/kotlin/fixtures/import-scroll/ImportNested.native.tsx +10 -0
  122. package/kotlin/fixtures/import-scroll/Nested.d.kt.ts +4 -0
  123. package/kotlin/fixtures/import-scroll/README.md +15 -0
  124. package/kotlin/fixtures/import-scroll/app/nested+spa.tsx +1 -0
  125. package/kotlin/fixtures/import-values/ImportValues.native.tsx +26 -0
  126. package/kotlin/fixtures/import-values/README.md +6 -1
  127. package/kotlin/fixtures/import-values/Values.d.kt.ts +4 -0
  128. package/kotlin/fixtures/import-values/Values.kt +18 -0
  129. package/kotlin/tools/expo-types.main.kts +17 -5
  130. package/package.json +2 -1
  131. package/scripts/dev-server-scanner.ts +33 -23
  132. package/src/assetCatalogContract.ts +7 -0
  133. package/src/bridge-contract.ts +21 -3
  134. package/src/connect.ts +18 -5
  135. package/src/desktop-host-delivery.ts +33 -3
  136. package/src/expo-swift-host.ts +6 -3
  137. package/src/host/bridge-host.ts +2 -0
  138. package/src/host/fetch-proxy-transport.ts +8 -0
  139. package/src/kotlin-host.ts +11 -5
  140. package/src/native-firebase-config.ts +95 -54
  141. package/src/process-output.ts +16 -0
  142. package/src/sdk.ts +6 -1
  143. package/src/sim-client.ts +6 -1
  144. package/src/swift-compile.ts +36 -15
  145. package/src/swift-distribution.lock.json +8 -8
  146. package/src/swift-standin-emit.ts +10 -1
  147. package/src/swift-standins.ts +21 -7
  148. package/src/swift-submit.ts +6 -1
  149. package/src/worklet-executable.ts +7 -2
  150. /package/kotlin/fixtures/{kotlin-app-variants → import-scroll}/Nested.kt +0 -0
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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;
@@ -753,10 +753,10 @@ var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
753
753
  (module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
754
754
  ).join("");
755
755
  var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
756
- var MULTI_MANIFEST_VERSION = 18;
756
+ var MULTI_MANIFEST_VERSION = 19;
757
757
  function swiftArtifactHash(input, release, moduleRoot) {
758
758
  const hash = (0, import_node_crypto2.createHash)("sha256");
759
- hash.update(`swift-compile/v23
759
+ hash.update(`swift-compile/v24
760
760
  ${release}
761
761
  `);
762
762
  if (input.oneModule) hash.update("one-module\n");
@@ -828,11 +828,24 @@ function emitSwiftPackageManifest(args) {
828
828
  reachedFrameworks.add("SpriteKit");
829
829
  reachedFrameworks.add("PeachBox2D");
830
830
  }
831
- const distributionObjects = distribution?.objects.filter(
832
- (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
833
- (name) => !object.startsWith(`lib/${name}-`) || reachedFrameworks.has(name)
834
- )
835
- );
831
+ const distributionLink = args.distributionLink;
832
+ if (distribution && !distributionLink)
833
+ throw new Error(
834
+ "swift-compile: distribution linking requires its object response file"
835
+ );
836
+ if (distribution && distributionLink) {
837
+ const objects = distribution.objects.filter(
838
+ (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
839
+ (name) => !object.startsWith(`lib/${name}-`) || reachedFrameworks.has(name)
840
+ )
841
+ );
842
+ distributionLink.files.set(
843
+ distributionLink.path,
844
+ objects.map(
845
+ (object) => `"${import_node_path2.default.join(moduleRoot, object).replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`
846
+ ).join("\n") + "\n"
847
+ );
848
+ }
836
849
  const executable = targets.find((target) => target.executable);
837
850
  if (!executable) throw new Error("swift-compile: no executable target to emit");
838
851
  const stanza = (target) => {
@@ -861,10 +874,7 @@ function emitSwiftPackageManifest(args) {
861
874
  (dependency) => OPTIONAL_FRAMEWORKS.has(dependency) && !targets.some((candidate) => candidate.name === dependency) ? distribution ? [] : [`.product(name: "${dependency}", package: "sootsim-swift")`] : [`"${dependency}"`]
862
875
  )
863
876
  ].join(", ");
864
- const library = distribution ? [
865
- ...(distributionObjects ?? []).map((object) => import_node_path2.default.join(moduleRoot, object)),
866
- ...distribution.link
867
- ].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
877
+ const library = distribution && distributionLink ? ["-Xlinker", `@${distributionLink.path}`, ...distribution.link].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
868
878
  const kind = target.executable ? ".executableTarget" : ".target";
869
879
  const link = target.executable ? `,
870
880
  linkerSettings: [
@@ -2237,6 +2247,10 @@ function writeSwiftProject(layout, input, moduleRoot) {
2237
2247
  oneModule: input.oneModule,
2238
2248
  spriteKit: importsSpriteKit(input.files),
2239
2249
  distribution: distribution ?? void 0,
2250
+ distributionLink: {
2251
+ path: import_node_path2.default.join(layout.root, ".peach-distribution-objects.rsp"),
2252
+ files
2253
+ },
2240
2254
  libraries
2241
2255
  }) + moduleFiles
2242
2256
  );
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-compile.ts
4
4
  import { execFile as execFile2, execFileSync } from "node:child_process";
@@ -699,10 +699,10 @@ var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
699
699
  (module) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module}"`
700
700
  ).join("");
701
701
  var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
702
- var MULTI_MANIFEST_VERSION = 18;
702
+ var MULTI_MANIFEST_VERSION = 19;
703
703
  function swiftArtifactHash(input, release, moduleRoot) {
704
704
  const hash = createHash2("sha256");
705
- hash.update(`swift-compile/v23
705
+ hash.update(`swift-compile/v24
706
706
  ${release}
707
707
  `);
708
708
  if (input.oneModule) hash.update("one-module\n");
@@ -774,11 +774,24 @@ function emitSwiftPackageManifest(args) {
774
774
  reachedFrameworks.add("SpriteKit");
775
775
  reachedFrameworks.add("PeachBox2D");
776
776
  }
777
- const distributionObjects = distribution?.objects.filter(
778
- (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
779
- (name) => !object.startsWith(`lib/${name}-`) || reachedFrameworks.has(name)
780
- )
781
- );
777
+ const distributionLink = args.distributionLink;
778
+ if (distribution && !distributionLink)
779
+ throw new Error(
780
+ "swift-compile: distribution linking requires its object response file"
781
+ );
782
+ if (distribution && distributionLink) {
783
+ const objects = distribution.objects.filter(
784
+ (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
785
+ (name) => !object.startsWith(`lib/${name}-`) || reachedFrameworks.has(name)
786
+ )
787
+ );
788
+ distributionLink.files.set(
789
+ distributionLink.path,
790
+ objects.map(
791
+ (object) => `"${path2.join(moduleRoot, object).replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`
792
+ ).join("\n") + "\n"
793
+ );
794
+ }
782
795
  const executable = targets.find((target) => target.executable);
783
796
  if (!executable) throw new Error("swift-compile: no executable target to emit");
784
797
  const stanza = (target) => {
@@ -807,10 +820,7 @@ function emitSwiftPackageManifest(args) {
807
820
  (dependency) => OPTIONAL_FRAMEWORKS.has(dependency) && !targets.some((candidate) => candidate.name === dependency) ? distribution ? [] : [`.product(name: "${dependency}", package: "sootsim-swift")`] : [`"${dependency}"`]
808
821
  )
809
822
  ].join(", ");
810
- const library = distribution ? [
811
- ...(distributionObjects ?? []).map((object) => path2.join(moduleRoot, object)),
812
- ...distribution.link
813
- ].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
823
+ const library = distribution && distributionLink ? ["-Xlinker", `@${distributionLink.path}`, ...distribution.link].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
814
824
  const kind = target.executable ? ".executableTarget" : ".target";
815
825
  const link = target.executable ? `,
816
826
  linkerSettings: [
@@ -2183,6 +2193,10 @@ function writeSwiftProject(layout, input, moduleRoot) {
2183
2193
  oneModule: input.oneModule,
2184
2194
  spriteKit: importsSpriteKit(input.files),
2185
2195
  distribution: distribution ?? void 0,
2196
+ distributionLink: {
2197
+ path: path2.join(layout.root, ".peach-distribution-objects.rsp"),
2198
+ files
2199
+ },
2186
2200
  libraries
2187
2201
  }) + moduleFiles
2188
2202
  );
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swift-package.ts
4
4
  function isSwiftManifestFile(file) {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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 __defProp = Object.defineProperty;
@@ -77,7 +77,7 @@ var MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024;
77
77
  var MAX_SWIFT_COMPILE_IMAGES = 128;
78
78
  var MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
79
79
  var MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
80
- var SWIFT_HOST_ABI = 41;
80
+ var SWIFT_HOST_ABI = 45;
81
81
  var POLL_INTERVAL_MS = 1500;
82
82
  function swiftNativeEntry(native, file) {
83
83
  return {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/swiftContract.ts
4
4
  function isSwiftResourcePath(value) {
@@ -33,7 +33,7 @@ var MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024;
33
33
  var MAX_SWIFT_COMPILE_IMAGES = 128;
34
34
  var MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
35
35
  var MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
36
- var SWIFT_HOST_ABI = 41;
36
+ var SWIFT_HOST_ABI = 45;
37
37
  var POLL_INTERVAL_MS = 1500;
38
38
  function swiftNativeEntry(native, file) {
39
39
  return {
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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 __defProp = Object.defineProperty;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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;
@@ -61,9 +61,9 @@ var require_parse = __commonJS({
61
61
  doc.documentElement.nodeName === "plist",
62
62
  "malformed document. First element should be <plist>"
63
63
  );
64
- var plist2 = parsePlistXML(doc.documentElement);
65
- if (plist2.length == 1) plist2 = plist2[0];
66
- return plist2;
64
+ var plist3 = parsePlistXML(doc.documentElement);
65
+ if (plist3.length == 1) plist3 = plist3[0];
66
+ return plist3;
67
67
  }
68
68
  function parsePlistXML(node) {
69
69
  var i, new_obj, key2, val, new_arr, res, counter, type;
@@ -1705,6 +1705,7 @@ function enumerateBundleSymbols(paths, readText, bundleForFile) {
1705
1705
  var COMPILED_EXTENSIONS = /* @__PURE__ */ new Set([".swift", ".metal", ".storyboard", ".xib"]);
1706
1706
  var NESTED_BUNDLE_DIR = /\.(?:xcassets|lproj)$/;
1707
1707
  function isCopiedResource(path18) {
1708
+ if (path18.split("/").some((segment) => segment.endsWith(".atlasc"))) return true;
1708
1709
  const ext = extOf(path18);
1709
1710
  if (ext === ".json" || ext === ".xcstrings") return true;
1710
1711
  return !RASTER_EXTENSIONS.has(ext) && !COMPILED_EXTENSIONS.has(ext) && !path18.split("/").some((segment) => NESTED_BUNDLE_DIR.test(segment));
@@ -1720,7 +1721,9 @@ function enumerateBundleResources(paths) {
1720
1721
  return aDepth - bDepth || (a < b ? -1 : a > b ? 1 : 0);
1721
1722
  });
1722
1723
  for (const file of ordered) {
1723
- const base = baseOf(file);
1724
+ const parts = file.split("/");
1725
+ const atlas = parts.findIndex((part) => part.endsWith(".atlasc"));
1726
+ const base = atlas < 0 ? baseOf(file) : parts.slice(atlas).join("/");
1724
1727
  if (seen.has(base)) continue;
1725
1728
  seen.add(base);
1726
1729
  found.push({ base, file });
@@ -2527,10 +2530,10 @@ var FOUNDATION_IMPLICIT_FLAGS = FOUNDATION_IMPLICIT_MODULES.map(
2527
2530
  (module2) => `, "-Xfrontend", "-import-module", "-Xfrontend", "${module2}"`
2528
2531
  ).join("");
2529
2532
  var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"';
2530
- var MULTI_MANIFEST_VERSION = 18;
2533
+ var MULTI_MANIFEST_VERSION = 19;
2531
2534
  function swiftArtifactHash(input, release, moduleRoot) {
2532
2535
  const hash = (0, import_node_crypto2.createHash)("sha256");
2533
- hash.update(`swift-compile/v23
2536
+ hash.update(`swift-compile/v24
2534
2537
  ${release}
2535
2538
  `);
2536
2539
  if (input.oneModule) hash.update("one-module\n");
@@ -2602,11 +2605,24 @@ function emitSwiftPackageManifest(args) {
2602
2605
  reachedFrameworks.add("SpriteKit");
2603
2606
  reachedFrameworks.add("PeachBox2D");
2604
2607
  }
2605
- const distributionObjects = distribution?.objects.filter(
2606
- (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
2607
- (name2) => !object.startsWith(`lib/${name2}-`) || reachedFrameworks.has(name2)
2608
- )
2609
- );
2608
+ const distributionLink = args.distributionLink;
2609
+ if (distribution && !distributionLink)
2610
+ throw new Error(
2611
+ "swift-compile: distribution linking requires its object response file"
2612
+ );
2613
+ if (distribution && distributionLink) {
2614
+ const objects = distribution.objects.filter(
2615
+ (object) => [...OPTIONAL_FRAMEWORKS, "SpriteKit", "PeachBox2D"].every(
2616
+ (name2) => !object.startsWith(`lib/${name2}-`) || reachedFrameworks.has(name2)
2617
+ )
2618
+ );
2619
+ distributionLink.files.set(
2620
+ distributionLink.path,
2621
+ objects.map(
2622
+ (object) => `"${import_node_path2.default.join(moduleRoot, object).replaceAll("\\", "\\\\").replaceAll('"', '\\"')}"`
2623
+ ).join("\n") + "\n"
2624
+ );
2625
+ }
2610
2626
  const executable = targets.find((target) => target.executable);
2611
2627
  if (!executable) throw new Error("swift-compile: no executable target to emit");
2612
2628
  const stanza = (target) => {
@@ -2635,10 +2651,7 @@ function emitSwiftPackageManifest(args) {
2635
2651
  (dependency) => OPTIONAL_FRAMEWORKS.has(dependency) && !targets.some((candidate) => candidate.name === dependency) ? distribution ? [] : [`.product(name: "${dependency}", package: "sootsim-swift")`] : [`"${dependency}"`]
2636
2652
  )
2637
2653
  ].join(", ");
2638
- const library = distribution ? [
2639
- ...(distributionObjects ?? []).map((object) => import_node_path2.default.join(moduleRoot, object)),
2640
- ...distribution.link
2641
- ].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
2654
+ const library = distribution && distributionLink ? ["-Xlinker", `@${distributionLink.path}`, ...distribution.link].map((flag) => `, ${JSON.stringify(flag)}`).join("") : "";
2642
2655
  const kind = target.executable ? ".executableTarget" : ".target";
2643
2656
  const link = target.executable ? `,
2644
2657
  linkerSettings: [
@@ -3929,6 +3942,10 @@ function writeSwiftProject(layout, input, moduleRoot) {
3929
3942
  oneModule: input.oneModule,
3930
3943
  spriteKit: importsSpriteKit(input.files),
3931
3944
  distribution: distribution ?? void 0,
3945
+ distributionLink: {
3946
+ path: import_node_path2.default.join(layout.root, ".peach-distribution-objects.rsp"),
3947
+ files: files2
3948
+ },
3932
3949
  libraries
3933
3950
  }) + moduleFiles
3934
3951
  );
@@ -4836,12 +4853,12 @@ function runExtractor(command, args) {
4836
4853
 
4837
4854
  // src/swift-distribution.lock.json
4838
4855
  var swift_distribution_lock_default = {
4839
- id: "3246f7e5ccb24952",
4856
+ id: "c60899948fe25af8",
4840
4857
  release: "swift-6.4.0-RELEASE",
4841
4858
  wasmSdkId: "swift-6.4.0-RELEASE_wasm-peach-e4629014",
4842
4859
  wasmSdkUrl: "https://r2.sootsim.com/swift-wasm-sdk/swift-6.4.0-RELEASE_wasm-peach-e4629014.artifactbundle.tar.gz",
4843
4860
  wasmSdkChecksum: "522f3ff98e951872d64751376d45e36394e572ec2aa4e0a52fb0027824bf41f6",
4844
- source: "a1e87668019272a329f6d9fada213573e3c5107f",
4861
+ source: "22d7666f9c66ec4b558db482661d440e581d84ff",
4845
4862
  targets: [
4846
4863
  "ExpoModulesCore",
4847
4864
  "PeachJSON",
@@ -4955,16 +4972,16 @@ var swift_distribution_lock_default = {
4955
4972
  ],
4956
4973
  hosts: {
4957
4974
  "darwin-arm64": {
4958
- sha256: "fb5a3e9db1eae670b5ba84432345e52de8b55b5fdf0e468ff95dfa25a62a6968",
4959
- size: 55050821
4975
+ sha256: "4661b87b8d627792bd28ef41d856bc9abcc913eb816efa448075d48e88abe823",
4976
+ size: 55595616
4960
4977
  },
4961
4978
  "linux-x64": {
4962
- sha256: "46a0eae68905751ee7c6536e79f626bc71d9d5a22cf9a76ce12b8d6c3aa34293",
4963
- size: 55056198
4979
+ sha256: "85dc5fc24acd33568f5ddccb3d69905c638162f5d5d767eefbbc16f9a4cca845",
4980
+ size: 55601101
4964
4981
  },
4965
4982
  "linux-arm64": {
4966
- sha256: "ea6453b55ff428d4d152d829731504400d49969ab0750264a931eaf0d7659122",
4967
- size: 55055213
4983
+ sha256: "009f687e2f5a03cf2af277638861543aead3ad907136c2de8e48a6a702040182",
4984
+ size: 55600268
4968
4985
  }
4969
4986
  }
4970
4987
  };
@@ -5637,6 +5654,12 @@ function getCliVersion() {
5637
5654
  return cached;
5638
5655
  }
5639
5656
 
5657
+ // src/plist.ts
5658
+ var import_plist = __toESM(require_plist(), 1);
5659
+ function parsePlistSource(source) {
5660
+ return import_plist.default.parse(source);
5661
+ }
5662
+
5640
5663
  // src/swift-standin-emit.ts
5641
5664
  var STANDIN_EMIT_VERSION = "5";
5642
5665
  var STANDIN_IMPORTS = ["Foundation", "UIKit"];
@@ -6218,7 +6241,12 @@ function emitSwiftStandin(graphs, options) {
6218
6241
  if (fix && !/^(?:prefix|infix|postfix)\b/.test(spelled))
6219
6242
  spelled = `${fix} ${spelled}`;
6220
6243
  }
6221
- emit(`${attrs}public ${spelled} { ${trap(path18)} }`);
6244
+ const measured = behavior.get(path18);
6245
+ if (measured) used.add(path18);
6246
+ const overloadBody = /\basync\b/.test(spelled) ? measured?.asyncBody : /\bResult</.test(spelled) ? measured?.resultBody : void 0;
6247
+ emit(
6248
+ `${attrs}public ${spelled} { ${overloadBody ?? measured?.body ?? trap(path18)} }`
6249
+ );
6222
6250
  } else if (kind === "swift.var") {
6223
6251
  const parsed = splitAccessors(text(symbol).replace(/^let /, "var "));
6224
6252
  const measured = behavior.get(path18);
@@ -6913,10 +6941,17 @@ function crateFor(root, name2) {
6913
6941
  };
6914
6942
  return walk2(root, 4);
6915
6943
  }
6944
+ function simulatorLibraryName(dir) {
6945
+ const info = parsePlistSource(import_node_fs12.default.readFileSync(import_node_path12.default.join(dir, "Info.plist"), "utf8"));
6946
+ const libraries = info && typeof info === "object" ? Reflect.get(info, "AvailableLibraries") : void 0;
6947
+ if (!Array.isArray(libraries)) return void 0;
6948
+ return libraries.filter(
6949
+ (entry) => typeof entry === "object" && entry !== null && Reflect.get(entry, "SupportedPlatform") === "ios" && Reflect.get(entry, "SupportedPlatformVariant") === "simulator"
6950
+ ).map((entry) => Reflect.get(entry, "LibraryPath")).find((name2) => typeof name2 === "string" && /^lib.+\.a$/.test(name2));
6951
+ }
6916
6952
  function standinLibrary(binary, searchRoot) {
6917
6953
  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;
6954
+ const library = simulatorLibraryName(dir);
6920
6955
  const supplied = import_node_path12.default.join(dir, RUST_TARGET);
6921
6956
  if (import_node_fs12.default.existsSync(supplied)) {
6922
6957
  const found = import_node_fs12.default.readdirSync(supplied).filter((name2) => name2.endsWith(".a"));
@@ -7156,7 +7191,7 @@ var MAX_SWIFT_COMPILE_METAL_TOTAL_BYTES = 8 * 1024 * 1024;
7156
7191
  var MAX_SWIFT_COMPILE_IMAGES = 128;
7157
7192
  var MAX_SWIFT_COMPILE_IMAGE_BYTES = 4 * 1024 * 1024;
7158
7193
  var MAX_SWIFT_COMPILE_IMAGE_TOTAL_BYTES = 16 * 1024 * 1024;
7159
- var SWIFT_HOST_ABI = 41;
7194
+ var SWIFT_HOST_ABI = 45;
7160
7195
  var POLL_INTERVAL_MS = 1500;
7161
7196
  function swiftNativeEntry(native, file) {
7162
7197
  return {
@@ -7298,7 +7333,7 @@ async function compileSwiftProject(submit, work, origin, signal) {
7298
7333
  // src/xcode-project.ts
7299
7334
  var import_node_fs13 = __toESM(require("node:fs"), 1);
7300
7335
  var import_node_path14 = __toESM(require("node:path"), 1);
7301
- var import_plist = __toESM(require_plist(), 1);
7336
+ var import_plist3 = __toESM(require_plist(), 1);
7302
7337
 
7303
7338
  // src/xcode-json-project.ts
7304
7339
  var import_node_path13 = __toESM(require("node:path"), 1);
@@ -8321,7 +8356,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
8321
8356
  return value;
8322
8357
  };
8323
8358
  const infoPlistFile = settings("INFOPLIST_FILE") ? import_node_path14.default.resolve(app.project.projectDir, settings("INFOPLIST_FILE")) : null;
8324
- const sourceInfo = infoPlistFile ? import_plist.default.parse(import_node_fs13.default.readFileSync(infoPlistFile, "utf8")) : {};
8359
+ const sourceInfo = infoPlistFile ? import_plist3.default.parse(import_node_fs13.default.readFileSync(infoPlistFile, "utf8")) : {};
8325
8360
  if (!sourceInfo || typeof sourceInfo !== "object" || Array.isArray(sourceInfo) || sourceInfo instanceof Date || Buffer.isBuffer(sourceInfo)) {
8326
8361
  throw new Error(`${module2.name} Info.plist must contain a dictionary`);
8327
8362
  }
@@ -8414,7 +8449,7 @@ function readXcodeAppTarget(input, targetName, configurationName, options = {})
8414
8449
  .../* @__PURE__ */ new Set([...used.map((project) => project.projectFile), ...xcconfigs])
8415
8450
  ].sort(),
8416
8451
  appIconName: settings("ASSETCATALOG_COMPILER_APPICON_NAME"),
8417
- infoPlist: import_plist.default.build(info),
8452
+ infoPlist: import_plist3.default.build(info),
8418
8453
  infoPlistFile,
8419
8454
  frameworks,
8420
8455
  linkedProducts,
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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;
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (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 __defProp = Object.defineProperty;
@@ -254,6 +254,10 @@ function resolveProperty(owner, name, collection, depth) {
254
254
  function resolveObject(expression, scope, collection, depth) {
255
255
  if (depth > MAX_RESOLUTION_DEPTH) return void 0;
256
256
  if (expression.type === "ObjectExpression") return { object: expression, scope };
257
+ if (expression.type === "SequenceExpression") {
258
+ const last = childNodes(Reflect.get(expression, "expressions")).at(-1);
259
+ return last && resolveObject(last, scope, collection, depth + 1);
260
+ }
257
261
  if (expression.type === "Identifier") {
258
262
  const name = identifierName(expression);
259
263
  const binding = name === void 0 ? void 0 : lookup(scope, name);
@@ -1,4 +1,4 @@
1
- /*! peach v0.1.1406 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
1
+ /*! peach v0.1.1465 | (c) 2026 Tamagui LLC | Proprietary; see LICENSE */
2
2
 
3
3
  // src/worklet-executable.ts
4
4
  import { parse } from "acorn";
@@ -229,6 +229,10 @@ function resolveProperty(owner, name, collection, depth) {
229
229
  function resolveObject(expression, scope, collection, depth) {
230
230
  if (depth > MAX_RESOLUTION_DEPTH) return void 0;
231
231
  if (expression.type === "ObjectExpression") return { object: expression, scope };
232
+ if (expression.type === "SequenceExpression") {
233
+ const last = childNodes(Reflect.get(expression, "expressions")).at(-1);
234
+ return last && resolveObject(last, scope, collection, depth + 1);
235
+ }
232
236
  if (expression.type === "Identifier") {
233
237
  const name = identifierName(expression);
234
238
  const binding = name === void 0 ? void 0 : lookup(scope, name);
@@ -29,6 +29,7 @@ class Window internal constructor(
29
29
  context: Context,
30
30
  theme: WindowTheme,
31
31
  internal val host: PeachWindowHost,
32
+ private val predictiveBackEnabled: Boolean,
32
33
  ) {
33
34
  private companion object { var nextBackGeneration = 0 }
34
35
  private val backGeneration = ++nextBackGeneration
@@ -159,6 +160,7 @@ class Window internal constructor(
159
160
  .put("systemBarsBehavior", insetsController.systemBarsBehavior)
160
161
  .put("backCallbacks", backDispatcher.registrations())
161
162
  .put("backGeneration", backGeneration)
163
+ .put("predictiveBackEnabled", predictiveBackEnabled)
162
164
 
163
165
  // Activity.setContentView(View) fills the content parent
164
166
  internal fun setContentView(view: View, params: ViewGroup.LayoutParams) {
@@ -195,7 +195,7 @@ private fun launchActivity(app: AppProcess, lastNonConfigurationInstance: Any?):
195
195
  // the theme the activity is created under: a relaunch after a night
196
196
  // change takes the other one
197
197
  val theme = if (processResources.configuration.isNight()) spec.nightWindow else spec.dayWindow
198
- window = Window(activity, theme, host)
198
+ window = Window(activity, theme, host, spec.predictiveBack)
199
199
  activity.attach(
200
200
  app.application,
201
201
  spec.component,
@@ -19,6 +19,8 @@ import androidx.compose.ui.input.key.KeyEventType
19
19
  import androidx.compose.ui.input.pointer.PointerEventType
20
20
  import androidx.compose.ui.input.pointer.PointerType
21
21
  import androidx.compose.ui.layout.Layout
22
+ import androidx.compose.ui.layout.Remeasurement
23
+ import androidx.compose.ui.layout.RemeasurementModifier
22
24
  import androidx.compose.ui.platform.FrameRecomposer
23
25
  import androidx.compose.ui.platform.LocalFontFamilyResolver
24
26
  import androidx.compose.ui.platform.PlatformArchitectureComponentsOwner
@@ -380,7 +382,13 @@ internal class PeachComposeMount(
380
382
  // ComposeView before its parent measures it, the content has none and
381
383
  // lays out nothing until the first arrive
382
384
  var constraints: Constraints? = null
383
- set(value) { if (field != value) { field = value; needsMeasure = true } }
385
+ set(value) {
386
+ if (field != value) {
387
+ field = value
388
+ needsMeasure = true
389
+ rootNeedsMeasure = true
390
+ }
391
+ }
384
392
  private val events = mutableListOf<JSONObject>()
385
393
  // state reported once a frame, read when the frame draws: like the decor,
386
394
  // the device sees the state a frame ends with, not each step to it
@@ -400,6 +408,13 @@ internal class PeachComposeMount(
400
408
  private var needsMeasure = true
401
409
  private var measuredSize = IntSize.Zero
402
410
  private var rootSize = IntSize.Zero
411
+ private var rootNeedsMeasure = true
412
+ private var rootRemeasurement: Remeasurement? = null
413
+ private val rootMeasureModifier = object : RemeasurementModifier {
414
+ override fun onRemeasurementAvailable(remeasurement: Remeasurement) {
415
+ rootRemeasurement = remeasurement
416
+ }
417
+ }
403
418
  private val scene = CanvasLayersComposeScene(
404
419
  recomposer, platform.density, LayoutDirection.Ltr, null, platform,
405
420
  invalidateLayout = { needsMeasure = true; invalidate(true) }, invalidateDraw = { invalidate(false) },
@@ -425,7 +440,7 @@ internal class PeachComposeMount(
425
440
  try {
426
441
  scene.setContent {
427
442
  // the parent measures the imported root; popup windows keep their own minimums.
428
- Layout(content = {
443
+ Layout(modifier = rootMeasureModifier, content = {
429
444
  CompositionLocalProvider(
430
445
  LocalSystemTheme provides if (night) SystemTheme.DARK else SystemTheme.LIGHT,
431
446
  LocalNavigationEventDispatcherOwner provides
@@ -434,13 +449,19 @@ internal class PeachComposeMount(
434
449
  PeachAndroidFonts(fonts, content)
435
450
  }
436
451
  }) { measurables, _ ->
437
- val rootConstraints = checkNotNull(constraints)
438
- val placeables = measurables.map { it.measure(rootConstraints) }
439
- rootSize = IntSize(
440
- rootConstraints.constrainWidth(placeables.maxOfOrNull { it.width } ?: 0),
441
- rootConstraints.constrainHeight(placeables.maxOfOrNull { it.height } ?: 0),
442
- )
443
- layout(rootSize.width, rootSize.height) { placeables.forEach { it.place(0, 0) } }
452
+ val rootConstraints = constraints
453
+ if (rootConstraints == null) {
454
+ // an attached view has no measured children until its parent supplies bounds.
455
+ rootSize = IntSize.Zero
456
+ layout(0, 0) {}
457
+ } else {
458
+ val placeables = measurables.map { it.measure(rootConstraints) }
459
+ rootSize = IntSize(
460
+ rootConstraints.constrainWidth(placeables.maxOfOrNull { it.width } ?: 0),
461
+ rootConstraints.constrainHeight(placeables.maxOfOrNull { it.height } ?: 0),
462
+ )
463
+ layout(rootSize.width, rootSize.height) { placeables.forEach { it.place(0, 0) } }
464
+ }
444
465
  }
445
466
  }
446
467
  } catch (failure: Throwable) {
@@ -470,6 +491,11 @@ internal class PeachComposeMount(
470
491
  }
471
492
 
472
493
  fun measure(): IntSize {
494
+ // host bounds can change while the scene's popup bounds remain the same.
495
+ if (rootNeedsMeasure) {
496
+ rootRemeasurement?.forceRemeasure()
497
+ rootNeedsMeasure = false
498
+ }
473
499
  // intrinsic root constraints can be unbounded; popup windows measure within the laid-out view.
474
500
  scene.measureContent(Constraints(maxWidth = measuredSize.width, maxHeight = measuredSize.height))
475
501
  val measured = rootSize
@@ -2,6 +2,7 @@
2
2
 
3
3
  package dev.peach.expo
4
4
 
5
+ import android.view.View
5
6
  import androidx.compose.runtime.MutableState
6
7
  import expo.modules.kotlin.exception.PropSetException
7
8
  import expo.modules.kotlin.exception.exceptionDecorator
@@ -9,12 +10,11 @@ import expo.modules.kotlin.types.AnyType
9
10
  import expo.modules.kotlin.types.toAnyType
10
11
  import expo.modules.kotlin.views.AnyViewProp
11
12
  import expo.modules.kotlin.views.ExpoComposeView
12
- import expo.modules.kotlin.views.ExpoView
13
13
 
14
14
  // a compose view's MutableState prop: a new value replaces the state's, as
15
15
  // ComposeViewProp sets it, so the content recomposes
16
16
  class ComposeStateProp(name: String, type: AnyType, private val write: (Any, Any?) -> Unit) : AnyViewProp(name, type) {
17
- override fun set(prop: Any?, onView: ExpoView) {
17
+ override fun set(prop: Any?, onView: View) {
18
18
  exceptionDecorator({ PropSetException(name, onView::class, it) }) {
19
19
  val props = (onView as ExpoComposeView<*>).props ?: return
20
20
  write(props, type.convert(prop))