peachsim 0.1.673 → 0.1.674

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 (71) hide show
  1. package/dist-lib/agent-daemon-client.cjs +1 -1
  2. package/dist-lib/agent-events.cjs +1 -1
  3. package/dist-lib/agent-identity.cjs +1 -1
  4. package/dist-lib/agent-sessions.cjs +1 -1
  5. package/dist-lib/attached-projects.cjs +1 -1
  6. package/dist-lib/auth/shared-session.cjs +1 -1
  7. package/dist-lib/backend-origin.cjs +1 -1
  8. package/dist-lib/beta.cjs +1 -1
  9. package/dist-lib/beta.mjs +1 -1
  10. package/dist-lib/bridge-constants.cjs +1 -1
  11. package/dist-lib/bridge-contract-input.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.mjs +1 -1
  13. package/dist-lib/bridge-contract.cjs +1 -1
  14. package/dist-lib/bridge-contract.mjs +1 -1
  15. package/dist-lib/capture-contract.cjs +1 -1
  16. package/dist-lib/capture-contract.mjs +1 -1
  17. package/dist-lib/cli-constants.cjs +1 -1
  18. package/dist-lib/cloud-contract.cjs +1 -1
  19. package/dist-lib/cloud-contract.mjs +1 -1
  20. package/dist-lib/cloud-test-args.cjs +1 -1
  21. package/dist-lib/cloud-test-args.mjs +1 -1
  22. package/dist-lib/cloud.cjs +1 -1
  23. package/dist-lib/cloud.mjs +1 -1
  24. package/dist-lib/config.cjs +1 -1
  25. package/dist-lib/detox/index.cjs +1 -1
  26. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  27. package/dist-lib/home-paths.cjs +1 -1
  28. package/dist-lib/host/bridge-host.cjs +257 -236
  29. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  30. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  31. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  32. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  33. package/dist-lib/host/websocket-proxy.cjs +1 -1
  34. package/dist-lib/index.cjs +1 -1
  35. package/dist-lib/jump-to-source-babel.cjs +1 -1
  36. package/dist-lib/jump-to-source-native.cjs +1 -1
  37. package/dist-lib/kotlin-host.cjs +1 -1
  38. package/dist-lib/menu.cjs +1 -1
  39. package/dist-lib/menu.mjs +1 -1
  40. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  41. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  42. package/dist-lib/metro-production-bundle.cjs +1 -1
  43. package/dist-lib/metro-production-bundle.mjs +1 -1
  44. package/dist-lib/metro.cjs +1 -1
  45. package/dist-lib/native-app-identity.cjs +1 -1
  46. package/dist-lib/native-app-identity.mjs +1 -1
  47. package/dist-lib/native-firebase-metadata.cjs +1 -1
  48. package/dist-lib/native-firebase-metadata.mjs +1 -1
  49. package/dist-lib/plist.cjs +1 -1
  50. package/dist-lib/plist.mjs +1 -1
  51. package/dist-lib/profiles.cjs +1 -1
  52. package/dist-lib/public-brand.cjs +1 -1
  53. package/dist-lib/react-native-host-modules.cjs +1 -1
  54. package/dist-lib/react-native-host-modules.mjs +1 -1
  55. package/dist-lib/render-mode.cjs +1 -1
  56. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  57. package/dist-lib/sdk.cjs +1 -1
  58. package/dist-lib/sdk.mjs +1 -1
  59. package/dist-lib/skills.cjs +434 -406
  60. package/dist-lib/swift-compile.cjs +21 -7
  61. package/dist-lib/swift-compile.mjs +21 -7
  62. package/dist-lib/swift-package.cjs +1 -1
  63. package/dist-lib/swift-package.mjs +1 -1
  64. package/dist-lib/swift-submit.cjs +1 -1
  65. package/dist-lib/swift-submit.mjs +1 -1
  66. package/dist-lib/swift.cjs +1 -1
  67. package/dist-lib/vite-swift.cjs +109 -88
  68. package/dist-lib/vite.cjs +1 -1
  69. package/package.json +1 -1
  70. package/src/swift-compile.ts +31 -10
  71. package/src/swift-host.ts +2 -4
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.673 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.674 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
@@ -46,7 +46,7 @@ __export(vite_plugin_swift_exports, {
46
46
  });
47
47
  module.exports = __toCommonJS(vite_plugin_swift_exports);
48
48
  var import_node_fs5 = __toESM(require("node:fs"), 1);
49
- var import_node_path6 = __toESM(require("node:path"), 1);
49
+ var import_node_path7 = __toESM(require("node:path"), 1);
50
50
 
51
51
  // ../sootsim-swift/src/entryModule.ts
52
52
  function nativeExportLines(args, commonjs) {
@@ -351,7 +351,7 @@ var ONE_IMPLICIT_FLAGS = ', "-Xfrontend", "-import-module", "-Xfrontend", "One"'
351
351
  var MULTI_MANIFEST_VERSION = 6;
352
352
  function swiftArtifactHash(input, release, moduleRoot) {
353
353
  const hash = (0, import_node_crypto2.createHash)("sha256");
354
- hash.update(`swift-compile/v6
354
+ hash.update(`swift-compile/v7
355
355
  ${release}
356
356
  `);
357
357
  if (input.oneModule) hash.update("one-module\n");
@@ -469,6 +469,17 @@ function swiftSourceAsIOS(source) {
469
469
  let copied = 0;
470
470
  for (const at of tokens) {
471
471
  const rest = conditioned.slice(at, at + 400);
472
+ const imported = /^import\s+CoreImage\.CIFilterBuiltins\b/.exec(rest);
473
+ if (imported) {
474
+ out += conditioned.slice(copied, at) + "import CoreImage".padEnd(imported[0].length);
475
+ copied = at + imported[0].length;
476
+ continue;
477
+ }
478
+ if (/^NSClassFromString\b/.test(rest)) {
479
+ out += conditioned.slice(copied, at) + "_peachClassFromString";
480
+ copied = at + "NSClassFromString".length;
481
+ continue;
482
+ }
472
483
  if (rest.startsWith("class")) {
473
484
  const modifiers = conditioned.slice(conditioned.lastIndexOf("\n", at - 1) + 1, at);
474
485
  if (DELEGATE_CLASS.test(rest) && !/\b(?:final|open)\b/.test(modifiers)) {
@@ -569,12 +580,15 @@ function swiftCodeScan(source) {
569
580
  if (top.parens === 0 && stack.length > 1) stack.pop();
570
581
  else top.parens--;
571
582
  i++;
572
- } else if (source.startsWith("class", i) && !/[\w$]/.test(source[i - 1] ?? "") && !/[\w$]/.test(source[i + 5] ?? "")) {
573
- tokens.push(i);
574
- i += 5;
575
583
  } else {
576
- if (char === "@") tokens.push(i);
577
- i++;
584
+ const keyword = source.startsWith("class", i) ? "class" : source.startsWith("import", i) ? "import" : source.startsWith("NSClassFromString", i) ? "NSClassFromString" : null;
585
+ if (keyword && !/[\w$]/.test(source[i - 1] ?? "") && !/[\w$]/.test(source[i + keyword.length] ?? "")) {
586
+ tokens.push(i);
587
+ i += keyword.length;
588
+ } else {
589
+ if (char === "@") tokens.push(i);
590
+ i++;
591
+ }
578
592
  }
579
593
  }
580
594
  return { lineStarts: starts, tokens };
@@ -745,8 +759,18 @@ function compileSwiftProjectUnit(input, options) {
745
759
  // src/swift-host.ts
746
760
  var import_node_crypto3 = require("node:crypto");
747
761
  var import_node_fs4 = __toESM(require("node:fs"), 1);
748
- var import_node_os3 = __toESM(require("node:os"), 1);
749
- var import_node_path5 = __toESM(require("node:path"), 1);
762
+ var import_node_os4 = __toESM(require("node:os"), 1);
763
+ var import_node_path6 = __toESM(require("node:path"), 1);
764
+
765
+ // ../../src/compile/swiftToolchain.ts
766
+ var import_node_os2 = __toESM(require("node:os"), 1);
767
+ var import_node_path3 = __toESM(require("node:path"), 1);
768
+ function swiftToolchainBin(release) {
769
+ return process.platform === "darwin" ? import_node_path3.default.join(
770
+ import_node_os2.default.homedir(),
771
+ `Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`
772
+ ) : import_node_path3.default.join(process.env.CONTRAST_SWIFT_TOOLCHAINS ?? "/opt/swift", release, "usr/bin");
773
+ }
750
774
 
751
775
  // ../sootsim-swift/src/bundleAssets.ts
752
776
  var import_svgpath = __toESM(require("svgpath"), 1);
@@ -780,8 +804,8 @@ function pickImagesetFile(images) {
780
804
  scale: pick.scale === "2x" ? 2 : pick.scale === "3x" ? 3 : 1
781
805
  };
782
806
  }
783
- function flatScale(path6) {
784
- const match = /@([23])x\.[^./]+$/.exec(path6);
807
+ function flatScale(path7) {
808
+ const match = /@([23])x\.[^./]+$/.exec(path7);
785
809
  return match ? Number(match[1]) : 1;
786
810
  }
787
811
  function providesNamespace(text) {
@@ -808,13 +832,13 @@ function catalogEntryName(contentsPath, kind, readText) {
808
832
  }
809
833
  return segments.join("/");
810
834
  }
811
- function isFlatResourceImage(path6) {
812
- return path6.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path6));
835
+ function isFlatResourceImage(path7) {
836
+ return path7.split("/").includes("Resources") && RASTER_EXTENSIONS.has(extOf(path7));
813
837
  }
814
838
  function enumerateBundleImages(paths, readText) {
815
839
  const table = [];
816
840
  const seen = /* @__PURE__ */ new Set();
817
- const catalogs = paths.filter((path6) => baseOf(path6) === "Contents.json");
841
+ const catalogs = paths.filter((path7) => baseOf(path7) === "Contents.json");
818
842
  for (const contentsPath of catalogs) {
819
843
  const name = catalogEntryName(contentsPath, ".imageset", readText);
820
844
  if (name === null || seen.has(name)) continue;
@@ -835,12 +859,12 @@ function enumerateBundleImages(paths, readText) {
835
859
  seen.add(name);
836
860
  table.push({ name, file: `${dir}/${pick.filename}`, scale: pick.scale });
837
861
  }
838
- for (const path6 of paths) {
839
- if (!isFlatResourceImage(path6)) continue;
840
- const name = baseOf(path6).slice(0, -extOf(path6).length);
862
+ for (const path7 of paths) {
863
+ if (!isFlatResourceImage(path7)) continue;
864
+ const name = baseOf(path7).slice(0, -extOf(path7).length);
841
865
  if (name === "" || seen.has(name)) continue;
842
866
  seen.add(name);
843
- table.push({ name, file: path6, scale: flatScale(path6) });
867
+ table.push({ name, file: path7, scale: flatScale(path7) });
844
868
  }
845
869
  return table;
846
870
  }
@@ -869,7 +893,7 @@ function colorsetValue(color) {
869
893
  }
870
894
  function enumerateBundleColors(paths, readText) {
871
895
  const table = {};
872
- for (const contentsPath of paths.filter((path6) => baseOf(path6) === "Contents.json")) {
896
+ for (const contentsPath of paths.filter((path7) => baseOf(path7) === "Contents.json")) {
873
897
  const name = catalogEntryName(contentsPath, ".colorset", readText);
874
898
  if (name === null || name in table) continue;
875
899
  let colors;
@@ -934,8 +958,8 @@ function axisExtremes(points) {
934
958
  function pathBounds(d) {
935
959
  const xs = [];
936
960
  const ys = [];
937
- for (const path6 of d)
938
- (0, import_svgpath.default)(path6).abs().unshort().unarc().iterate((segment, _index, x, y) => {
961
+ for (const path7 of d)
962
+ (0, import_svgpath.default)(path7).abs().unshort().unarc().iterate((segment, _index, x, y) => {
939
963
  const [command, ...args] = segment;
940
964
  if (command === "M" || command === "L") {
941
965
  xs.push(Number(args[0]));
@@ -962,7 +986,7 @@ function guide(svg, id, axis) {
962
986
  }
963
987
  function enumerateBundleSymbols(paths, readText) {
964
988
  const table = {};
965
- for (const contentsPath of paths.filter((path6) => baseOf(path6) === "Contents.json")) {
989
+ for (const contentsPath of paths.filter((path7) => baseOf(path7) === "Contents.json")) {
966
990
  const name = catalogEntryName(contentsPath, ".symbolset", readText);
967
991
  if (name === null || name in table) continue;
968
992
  let symbols;
@@ -995,8 +1019,8 @@ function enumerateBundleSymbols(paths, readText) {
995
1019
  viewBox: "0 0 24 24",
996
1020
  advance,
997
1021
  box: [12 - advance / 2, 12 - tall / 2, advance, tall],
998
- layers: d.map((path6) => ({
999
- d: (0, import_svgpath.default)(path6).abs().scale(scale).translate(translateX, translateY).round(3).toString()
1022
+ layers: d.map((path7) => ({
1023
+ d: (0, import_svgpath.default)(path7).abs().scale(scale).translate(translateX, translateY).round(3).toString()
1000
1024
  }))
1001
1025
  };
1002
1026
  }
@@ -1006,7 +1030,7 @@ function enumerateBundleJson(paths) {
1006
1030
  const found = [];
1007
1031
  const seen = /* @__PURE__ */ new Set();
1008
1032
  const ordered = [...paths].filter(
1009
- (path6) => path6.split("/").includes("Resources") && path6.split("/").every((segment) => segment !== "" && segment !== "..") && (extOf(path6) === ".json" || extOf(path6) === ".xcstrings")
1033
+ (path7) => path7.split("/").includes("Resources") && path7.split("/").every((segment) => segment !== "" && segment !== "..") && (extOf(path7) === ".json" || extOf(path7) === ".xcstrings")
1010
1034
  ).sort((a, b) => {
1011
1035
  const aDepth = a.split("/").length;
1012
1036
  const bDepth = b.split("/").length;
@@ -1023,22 +1047,22 @@ function enumerateBundleJson(paths) {
1023
1047
 
1024
1048
  // src/auth/shared-session.ts
1025
1049
  var import_node_fs3 = require("node:fs");
1026
- var import_node_path4 = require("node:path");
1050
+ var import_node_path5 = require("node:path");
1027
1051
 
1028
1052
  // src/home-paths.ts
1029
- var import_node_os2 = require("node:os");
1030
- var import_node_path3 = __toESM(require("node:path"), 1);
1053
+ var import_node_os3 = require("node:os");
1054
+ var import_node_path4 = __toESM(require("node:path"), 1);
1031
1055
  var PEACH_HOME_ENV = "PEACH_HOME";
1032
1056
  function rnxHomeDir() {
1033
1057
  const override = process.env[PEACH_HOME_ENV];
1034
- if (override && override.length > 0) return import_node_path3.default.resolve(override);
1035
- return import_node_path3.default.join((0, import_node_os2.homedir)(), ".peach");
1058
+ if (override && override.length > 0) return import_node_path4.default.resolve(override);
1059
+ return import_node_path4.default.join((0, import_node_os3.homedir)(), ".peach");
1036
1060
  }
1037
1061
  function electronDir() {
1038
- return import_node_path3.default.join(rnxHomeDir(), "electron");
1062
+ return import_node_path4.default.join(rnxHomeDir(), "electron");
1039
1063
  }
1040
1064
  function electronUserDataDir() {
1041
- return import_node_path3.default.join(electronDir(), "userData");
1065
+ return import_node_path4.default.join(electronDir(), "userData");
1042
1066
  }
1043
1067
  var DAEMON_LOCKFILE_MAX_BYTES = 16 * 1024;
1044
1068
 
@@ -1055,14 +1079,14 @@ var DEFAULT_ORIGIN = "https://contrast.dev";
1055
1079
  function getBaseDir() {
1056
1080
  const explicit = process.env[SESSION_FILE_ENV];
1057
1081
  if (explicit?.trim()) {
1058
- return (0, import_node_path4.dirname)((0, import_node_path4.resolve)(explicit));
1082
+ return (0, import_node_path5.dirname)((0, import_node_path5.resolve)(explicit));
1059
1083
  }
1060
1084
  return electronUserDataDir();
1061
1085
  }
1062
1086
  function getSharedDesktopAuthFilePath() {
1063
1087
  const explicit = process.env[SESSION_FILE_ENV];
1064
- if (explicit?.trim()) return (0, import_node_path4.resolve)(explicit);
1065
- return (0, import_node_path4.join)(getBaseDir(), "desktop-auth.json");
1088
+ if (explicit?.trim()) return (0, import_node_path5.resolve)(explicit);
1089
+ return (0, import_node_path5.join)(getBaseDir(), "desktop-auth.json");
1066
1090
  }
1067
1091
  function normalizeUser(input) {
1068
1092
  if (!input || typeof input !== "object") return null;
@@ -1372,17 +1396,17 @@ var SKIP_SOURCE_DIRS = /* @__PURE__ */ new Set([
1372
1396
  var NATIVE_DESCRIPTOR = ".one-native-source.json";
1373
1397
  var NATIVE_GLUE = ".one-native-source.swift.txt";
1374
1398
  function swiftPackageId(packagePath) {
1375
- return import_node_path5.default.basename(packagePath).replace(/[^A-Za-z0-9_]/g, "_").replace(/^(\d)/, "_$1");
1399
+ return import_node_path6.default.basename(packagePath).replace(/[^A-Za-z0-9_]/g, "_").replace(/^(\d)/, "_$1");
1376
1400
  }
1377
1401
  function nativeSourceDescriptor(packagePath) {
1378
1402
  packagePath = import_node_fs4.default.realpathSync(packagePath);
1379
- const file = import_node_path5.default.join(packagePath, NATIVE_DESCRIPTOR);
1403
+ const file = import_node_path6.default.join(packagePath, NATIVE_DESCRIPTOR);
1380
1404
  if (!import_node_fs4.default.existsSync(file)) return null;
1381
1405
  const value = JSON.parse(
1382
1406
  readPackageFile(packagePath, file, MAX_SWIFT_COMPILE_SOURCE_BYTES).toString("utf8")
1383
1407
  );
1384
1408
  const invalid = () => new Error(`${file}: invalid One native source descriptor; run one typegen`);
1385
- if (!value || typeof value !== "object" || Reflect.get(value, "generatedBy") !== "one typegen" || !import_node_fs4.default.existsSync(import_node_path5.default.join(packagePath, NATIVE_GLUE))) {
1409
+ if (!value || typeof value !== "object" || Reflect.get(value, "generatedBy") !== "one typegen" || !import_node_fs4.default.existsSync(import_node_path6.default.join(packagePath, NATIVE_GLUE))) {
1386
1410
  throw invalid();
1387
1411
  }
1388
1412
  if (!isSwiftNativeModules(value) || value.packageId !== swiftPackageId(packagePath)) {
@@ -1392,7 +1416,7 @@ function nativeSourceDescriptor(packagePath) {
1392
1416
  }
1393
1417
  function nativeSourceFiles(packagePath) {
1394
1418
  packagePath = import_node_fs4.default.realpathSync(packagePath);
1395
- return [NATIVE_DESCRIPTOR, NATIVE_GLUE].map((name) => import_node_path5.default.join(packagePath, name)).filter((file) => import_node_fs4.default.existsSync(file));
1419
+ return [NATIVE_DESCRIPTOR, NATIVE_GLUE].map((name) => import_node_path6.default.join(packagePath, name)).filter((file) => import_node_fs4.default.existsSync(file));
1396
1420
  }
1397
1421
  var projects = /* @__PURE__ */ new Map();
1398
1422
  function projectFor(packagePath, hosted) {
@@ -1423,15 +1447,15 @@ function packageFiles(root) {
1423
1447
  for (const entry of import_node_fs4.default.readdirSync(dir, { withFileTypes: true }).sort((left, right) => left.name.localeCompare(right.name))) {
1424
1448
  if (entry.name.startsWith(".") && entry.name !== NATIVE_DESCRIPTOR && entry.name !== NATIVE_GLUE || SKIP_SOURCE_DIRS.has(entry.name))
1425
1449
  continue;
1426
- const full = import_node_path5.default.join(dir, entry.name);
1450
+ const full = import_node_path6.default.join(dir, entry.name);
1427
1451
  if (entry.isSymbolicLink()) throw new Error(`swift input is a symlink: ${full}`);
1428
1452
  const real = import_node_fs4.default.realpathSync(full);
1429
- const relative = import_node_path5.default.relative(canonicalRoot, real);
1430
- if (relative.startsWith(`..${import_node_path5.default.sep}`) || relative === ".." || import_node_path5.default.isAbsolute(relative)) {
1453
+ const relative = import_node_path6.default.relative(canonicalRoot, real);
1454
+ if (relative.startsWith(`..${import_node_path6.default.sep}`) || relative === ".." || import_node_path6.default.isAbsolute(relative)) {
1431
1455
  throw new Error(`swift input escapes the selected package: ${full}`);
1432
1456
  }
1433
1457
  if (entry.isDirectory()) {
1434
- if (import_node_fs4.default.existsSync(import_node_path5.default.join(full, "Package.swift"))) continue;
1458
+ if (import_node_fs4.default.existsSync(import_node_path6.default.join(full, "Package.swift"))) continue;
1435
1459
  walk(full);
1436
1460
  } else if (entry.isFile()) {
1437
1461
  found.push(full);
@@ -1444,16 +1468,16 @@ function packageFiles(root) {
1444
1468
  }
1445
1469
  function readPackageFile(root, file, maxBytes) {
1446
1470
  const canonicalRoot = import_node_fs4.default.realpathSync(root);
1447
- const relative = import_node_path5.default.relative(canonicalRoot, import_node_fs4.default.realpathSync(file));
1448
- if (relative === ".." || relative.startsWith(`..${import_node_path5.default.sep}`) || import_node_path5.default.isAbsolute(relative)) {
1471
+ const relative = import_node_path6.default.relative(canonicalRoot, import_node_fs4.default.realpathSync(file));
1472
+ if (relative === ".." || relative.startsWith(`..${import_node_path6.default.sep}`) || import_node_path6.default.isAbsolute(relative)) {
1449
1473
  throw new Error(`swift input escapes the selected package: ${file}`);
1450
1474
  }
1451
- let ancestor = import_node_path5.default.resolve(file);
1475
+ let ancestor = import_node_path6.default.resolve(file);
1452
1476
  while (ancestor !== canonicalRoot) {
1453
1477
  if (import_node_fs4.default.lstatSync(ancestor).isSymbolicLink()) {
1454
1478
  throw new Error(`swift input is a symlink: ${ancestor}`);
1455
1479
  }
1456
- const parent = import_node_path5.default.dirname(ancestor);
1480
+ const parent = import_node_path6.default.dirname(ancestor);
1457
1481
  if (parent === ancestor)
1458
1482
  throw new Error(`swift input escapes the selected package: ${file}`);
1459
1483
  ancestor = parent;
@@ -1506,7 +1530,7 @@ var RESOURCE_CONTENT_TYPES = {
1506
1530
  function buildSwiftResourceTable(project, baseUrl) {
1507
1531
  const absolute = resourceCandidateFiles(project.packagePath);
1508
1532
  const relative = absolute.map(
1509
- (file) => import_node_path5.default.relative(project.packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep)
1533
+ (file) => import_node_path6.default.relative(project.packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep)
1510
1534
  );
1511
1535
  const byRelative = new Map(absolute.map((file, index) => [relative[index], file]));
1512
1536
  const readContents = (candidate) => {
@@ -1540,10 +1564,10 @@ function buildSwiftResourceTable(project, baseUrl) {
1540
1564
  );
1541
1565
  imageBytes += bytes.length;
1542
1566
  const hash = (0, import_node_crypto3.createHash)("sha256").update(bytes).digest("hex").slice(0, 16);
1543
- const ext = import_node_path5.default.posix.extname(file).toLowerCase();
1567
+ const ext = import_node_path6.default.posix.extname(file).toLowerCase();
1544
1568
  table[name] = { uri: `${baseUrl}${RESOURCE_PATH}${hash}${ext}`, scale };
1545
1569
  images[name] = {
1546
- file: import_node_path5.default.posix.basename(file),
1570
+ file: import_node_path6.default.posix.basename(file),
1547
1571
  data: bytes.toString("base64")
1548
1572
  };
1549
1573
  watched.push(file);
@@ -1572,14 +1596,14 @@ var BUNDLE_MAX_TOTAL_BYTES = MAX_SWIFT_COMPILE_RESOURCE_TOTAL_BYTES;
1572
1596
  function buildSwiftBundleFiles(packagePath) {
1573
1597
  packagePath = import_node_fs4.default.realpathSync(packagePath);
1574
1598
  const relative = resourceCandidateFiles(packagePath).map(
1575
- (file) => import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep)
1599
+ (file) => import_node_path6.default.relative(packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep)
1576
1600
  );
1577
1601
  const files = {};
1578
1602
  const watched = [];
1579
1603
  let total = 0;
1580
1604
  for (const { base, file } of enumerateBundleJson(relative)) {
1581
1605
  watched.push(file);
1582
- const disk = import_node_path5.default.join(packagePath, ...file.split("/"));
1606
+ const disk = import_node_path6.default.join(packagePath, ...file.split("/"));
1583
1607
  if (Object.keys(files).length >= BUNDLE_MAX_FILES || total + import_node_fs4.default.statSync(disk).size > BUNDLE_MAX_TOTAL_BYTES) {
1584
1608
  throw new Error(
1585
1609
  `swift bundle pack exceeds ${BUNDLE_MAX_FILES} files / ${BUNDLE_MAX_TOTAL_BYTES} bytes`
@@ -1600,7 +1624,7 @@ function linkedModuleRoots(packagePath) {
1600
1624
  try {
1601
1625
  manifest = readPackageFile(
1602
1626
  packagePath,
1603
- import_node_path5.default.join(packagePath, "Package.swift"),
1627
+ import_node_path6.default.join(packagePath, "Package.swift"),
1604
1628
  MAX_SWIFT_COMPILE_SOURCE_BYTES
1605
1629
  ).toString("utf8");
1606
1630
  } catch {
@@ -1609,8 +1633,8 @@ function linkedModuleRoots(packagePath) {
1609
1633
  const roots = /* @__PURE__ */ new Set();
1610
1634
  const dependency = /\.package\(\s*path:\s*"([^"]+)"\s*\)/g;
1611
1635
  for (const match of manifest.replace(/^\s*\/\/.*$/gm, "").matchAll(dependency)) {
1612
- const root = import_node_path5.default.resolve(packagePath, match[1]);
1613
- if (import_node_fs4.default.existsSync(import_node_path5.default.join(root, "Package.swift"))) roots.add(root);
1636
+ const root = import_node_path6.default.resolve(packagePath, match[1]);
1637
+ if (import_node_fs4.default.existsSync(import_node_path6.default.join(root, "Package.swift"))) roots.add(root);
1614
1638
  }
1615
1639
  return [...roots].sort();
1616
1640
  }
@@ -1619,25 +1643,25 @@ function sourceStamp(packagePath, moduleRootOverride, hosted = false) {
1619
1643
  hash.update(packagePath);
1620
1644
  const projectInputs = new Set(packageFiles(packagePath));
1621
1645
  for (const file of [...projectInputs].sort()) {
1622
- hash.update(import_node_path5.default.relative(packagePath, file));
1646
+ hash.update(import_node_path6.default.relative(packagePath, file));
1623
1647
  const stat = import_node_fs4.default.statSync(file);
1624
1648
  hash.update(`${stat.mtimeMs}/${stat.ctimeMs}/${stat.size}`);
1625
1649
  }
1626
1650
  const moduleRoot = hosted ? void 0 : moduleRootOverride ?? linkedModuleRoots(packagePath).find(
1627
- (root) => import_node_fs4.default.existsSync(import_node_path5.default.join(root, "toolchain.json"))
1651
+ (root) => import_node_fs4.default.existsSync(import_node_path6.default.join(root, "toolchain.json"))
1628
1652
  );
1629
1653
  if (moduleRoot) {
1630
1654
  hash.update(moduleRoot);
1631
1655
  for (const relative of swiftModuleInputFiles(moduleRoot)) {
1632
1656
  hash.update(relative);
1633
- hash.update(String(import_node_fs4.default.statSync(import_node_path5.default.join(moduleRoot, relative)).mtimeMs));
1657
+ hash.update(String(import_node_fs4.default.statSync(import_node_path6.default.join(moduleRoot, relative)).mtimeMs));
1634
1658
  }
1635
1659
  }
1636
1660
  return hash.digest("hex").slice(0, 16);
1637
1661
  }
1638
1662
  function entryRootId(packagePath, file) {
1639
- const relative = import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep);
1640
- return `${import_node_path5.default.basename(packagePath)}${import_node_path5.default.posix.sep}${relative}`;
1663
+ const relative = import_node_path6.default.relative(packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep);
1664
+ return `${import_node_path6.default.basename(packagePath)}${import_node_path6.default.posix.sep}${relative}`;
1641
1665
  }
1642
1666
  function icuUrl(origin, artifact) {
1643
1667
  return "url" in artifact.icu ? artifact.icu.url : `${origin}${ICU_PATH}${artifact.icu.sha256}`;
@@ -1652,7 +1676,7 @@ function packageSources(packagePath) {
1652
1676
  throw new Error("swift source byte cap exceeded");
1653
1677
  const files = {};
1654
1678
  for (const file of sources) {
1655
- const relative = import_node_path5.default.relative(packagePath, file).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep);
1679
+ const relative = import_node_path6.default.relative(packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep);
1656
1680
  files[relative] = readPackageFile(
1657
1681
  packagePath,
1658
1682
  file,
@@ -1672,7 +1696,7 @@ function packageSnapshot(project) {
1672
1696
  ...native ? {
1673
1697
  glue: readPackageFile(
1674
1698
  project.packagePath,
1675
- import_node_path5.default.join(project.packagePath, NATIVE_GLUE),
1699
+ import_node_path6.default.join(project.packagePath, NATIVE_GLUE),
1676
1700
  MAX_SWIFT_COMPILE_SOURCE_BYTES
1677
1701
  ).toString("utf8")
1678
1702
  } : {}
@@ -1710,7 +1734,7 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
1710
1734
  package: content
1711
1735
  };
1712
1736
  const moduleRoot = moduleRootOverride ?? linkedModuleRoots(packagePath).find(
1713
- (root) => import_node_fs4.default.existsSync(import_node_path5.default.join(root, "toolchain.json"))
1737
+ (root) => import_node_fs4.default.existsSync(import_node_path6.default.join(root, "toolchain.json"))
1714
1738
  );
1715
1739
  if (!moduleRoot)
1716
1740
  return {
@@ -1729,10 +1753,10 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
1729
1753
  // server and a capture, or two checkouts) build each other's sources. so
1730
1754
  // each app and module checkout gets its own root, which keeps the same
1731
1755
  // app's incremental build across restarts.
1732
- buildRoot: process.env.CONTRAST_SWIFT_BUILD_ROOT ?? import_node_path5.default.join(
1733
- import_node_os3.default.tmpdir(),
1756
+ buildRoot: process.env.CONTRAST_SWIFT_BUILD_ROOT ?? import_node_path6.default.join(
1757
+ import_node_os4.default.tmpdir(),
1734
1758
  "contrast-swift-build",
1735
- (0, import_node_crypto3.createHash)("sha256").update(`${moduleRoot}\0${import_node_path5.default.resolve(packagePath)}`).digest("hex").slice(0, 16)
1759
+ (0, import_node_crypto3.createHash)("sha256").update(`${moduleRoot}\0${import_node_path6.default.resolve(packagePath)}`).digest("hex").slice(0, 16)
1736
1760
  ),
1737
1761
  moduleRoot,
1738
1762
  ...toolchain
@@ -1740,24 +1764,21 @@ async function compile(packagePath, entry, stamp, moduleRootOverride, hosted, sn
1740
1764
  return { ...artifact, stamp, package: content };
1741
1765
  }
1742
1766
  function localSwiftToolchain(moduleRoot) {
1743
- const manifest = import_node_path5.default.join(moduleRoot, "toolchain.json");
1767
+ const manifest = import_node_path6.default.join(moduleRoot, "toolchain.json");
1744
1768
  if (!import_node_fs4.default.existsSync(manifest)) return null;
1745
1769
  const toolchain = JSON.parse(import_node_fs4.default.readFileSync(manifest, "utf8"));
1746
1770
  const release = toolchain && typeof toolchain === "object" ? Reflect.get(toolchain, "release") : void 0;
1747
1771
  if (typeof release !== "string") {
1748
1772
  throw new Error(`swift toolchain manifest at ${moduleRoot} has no release`);
1749
1773
  }
1750
- const toolchainBin = import_node_path5.default.join(
1751
- import_node_os3.default.homedir(),
1752
- `Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`
1753
- );
1754
- return import_node_fs4.default.existsSync(import_node_path5.default.join(toolchainBin, "swift")) ? { release, toolchainBin } : null;
1774
+ const toolchainBin = swiftToolchainBin(release);
1775
+ return import_node_fs4.default.existsSync(import_node_path6.default.join(toolchainBin, "swift")) ? { release, toolchainBin } : null;
1755
1776
  }
1756
1777
  async function compileRemote(packagePath, entry, snapshot, hosted) {
1757
1778
  const auth = hosted ? null : resolveCliAuth();
1758
1779
  if (!hosted && (!auth || auth.kind === "github")) {
1759
1780
  throw new Error(
1760
- `compiling ${import_node_path5.default.basename(packagePath)} for Peach needs \`peach login\` or PEACH_API_KEY: this peachsim has no local SwiftUI module, so Contrast compiles it`
1781
+ `compiling ${import_node_path6.default.basename(packagePath)} for Peach needs \`peach login\` or PEACH_API_KEY: this peachsim has no local SwiftUI module, so Contrast compiles it`
1761
1782
  );
1762
1783
  }
1763
1784
  const origin = hosted?.origin ?? resolveContrastBackendOrigin(auth?.kind === "session" ? auth.origin : null);
@@ -1787,7 +1808,7 @@ async function compileRemote(packagePath, entry, snapshot, hosted) {
1787
1808
  );
1788
1809
  if (descriptor && address.native?.hash !== descriptor.hash) {
1789
1810
  throw new Error(
1790
- `${import_node_path5.default.basename(packagePath)}: Contrast compiled native contract ${address.native?.hash ?? "none"} but one typegen wrote ${descriptor.hash}; the app's One and the compile host's differ, or the compile host is older than this peachsim`
1811
+ `${import_node_path6.default.basename(packagePath)}: Contrast compiled native contract ${address.native?.hash ?? "none"} but one typegen wrote ${descriptor.hash}; the app's One and the compile host's differ, or the compile host is older than this peachsim`
1791
1812
  );
1792
1813
  }
1793
1814
  const response = await fetch(address.url, { signal });
@@ -1862,11 +1883,11 @@ function artifactFor(project, entry, moduleRoot) {
1862
1883
  function swiftPackageWatchFiles(packagePath, moduleRoot) {
1863
1884
  packagePath = import_node_fs4.default.realpathSync(packagePath);
1864
1885
  return [
1865
- import_node_path5.default.join(packagePath, "Package.swift"),
1886
+ import_node_path6.default.join(packagePath, "Package.swift"),
1866
1887
  ...sourceFiles(packagePath),
1867
1888
  ...nativeSourceFiles(packagePath),
1868
1889
  ...resourceCandidateFiles(packagePath),
1869
- ...moduleRoot ? swiftModuleInputFiles(moduleRoot).map((file) => import_node_path5.default.join(moduleRoot, file)) : []
1890
+ ...moduleRoot ? swiftModuleInputFiles(moduleRoot).map((file) => import_node_path6.default.join(moduleRoot, file)) : []
1870
1891
  ];
1871
1892
  }
1872
1893
  async function swiftPackageMetadata(packagePath, packageName, moduleRoot, origin, hosted) {
@@ -1883,7 +1904,7 @@ async function swiftPackageMetadata(packagePath, packageName, moduleRoot, origin
1883
1904
  );
1884
1905
  }
1885
1906
  const project = projectFor(packagePath, hosted);
1886
- const entry = mains.length === 1 ? import_node_path5.default.relative(packagePath, mains[0]).split(import_node_path5.default.sep).join(import_node_path5.default.posix.sep) : Object.entries(native?.files ?? {}).find(
1907
+ const entry = mains.length === 1 ? import_node_path6.default.relative(packagePath, mains[0]).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep) : Object.entries(native?.files ?? {}).find(
1887
1908
  ([_file, names]) => names.length > 0
1888
1909
  )?.[0];
1889
1910
  if (!entry) throw new Error(`swift package ${packageName} has no native module source`);
@@ -1972,12 +1993,12 @@ function artifactUrl(project, artifact) {
1972
1993
  return `${serverOrigin()}${ARTIFACT_PATH2}${artifact.hash}.wasm`;
1973
1994
  }
1974
1995
  function packageFor(file) {
1975
- let dir = import_node_path6.default.dirname(file);
1996
+ let dir = import_node_path7.default.dirname(file);
1976
1997
  const stop = devServer?.config.root;
1977
1998
  for (; ; ) {
1978
- if (import_node_fs5.default.existsSync(import_node_path6.default.join(dir, "Package.swift"))) return dir;
1979
- if (stop !== void 0 && dir === stop || import_node_path6.default.dirname(dir) === dir) break;
1980
- dir = import_node_path6.default.dirname(dir);
1999
+ if (import_node_fs5.default.existsSync(import_node_path7.default.join(dir, "Package.swift"))) return dir;
2000
+ if (stop !== void 0 && dir === stop || import_node_path7.default.dirname(dir) === dir) break;
2001
+ dir = import_node_path7.default.dirname(dir);
1981
2002
  }
1982
2003
  throw new Error(
1983
2004
  `no Package.swift above ${file}${stop === void 0 ? "" : ` (searched up to ${stop})`}; a .swift import needs a swiftpm package like the one in packages/sootsim-swift/example`
@@ -1998,7 +2019,7 @@ function swiftPlugin(options = {}) {
1998
2019
  if (!resolved) throw new Error(`cannot resolve swift source ${source}`);
1999
2020
  let id = resolved.id;
2000
2021
  if (importer && (source.startsWith("./") || source.startsWith("../"))) {
2001
- const raw2 = import_node_path6.default.resolve(import_node_path6.default.dirname(importer.split("?")[0] ?? importer), source);
2022
+ const raw2 = import_node_path7.default.resolve(import_node_path7.default.dirname(importer.split("?")[0] ?? importer), source);
2002
2023
  try {
2003
2024
  if (import_node_fs5.default.realpathSync(raw2) === import_node_fs5.default.realpathSync(resolved.id)) id = raw2;
2004
2025
  } catch {
@@ -2012,19 +2033,19 @@ function swiftPlugin(options = {}) {
2012
2033
  if (!import_node_fs5.default.existsSync(file)) throw new Error(`swift source ${file} no longer exists`);
2013
2034
  const packagePath = options.packagePath ?? packageFor(file);
2014
2035
  const project = projectFor(packagePath);
2015
- const entry = import_node_path6.default.relative(packagePath, file).split(import_node_path6.default.sep).join(import_node_path6.default.posix.sep);
2036
+ const entry = import_node_path7.default.relative(packagePath, file).split(import_node_path7.default.sep).join(import_node_path7.default.posix.sep);
2016
2037
  for (const source of [
2017
2038
  ...sourceFiles(packagePath),
2018
2039
  ...nativeSourceFiles(packagePath)
2019
2040
  ])
2020
2041
  this.addWatchFile(source);
2021
- this.addWatchFile(import_node_path6.default.join(packagePath, "Package.swift"));
2042
+ this.addWatchFile(import_node_path7.default.join(packagePath, "Package.swift"));
2022
2043
  const moduleRoot = linkedModuleRoots(packagePath).find(
2023
- (root) => import_node_fs5.default.existsSync(import_node_path6.default.join(root, "toolchain.json"))
2044
+ (root) => import_node_fs5.default.existsSync(import_node_path7.default.join(root, "toolchain.json"))
2024
2045
  );
2025
2046
  if (moduleRoot)
2026
2047
  for (const relative of swiftModuleInputFiles(moduleRoot))
2027
- this.addWatchFile(import_node_path6.default.join(moduleRoot, relative));
2048
+ this.addWatchFile(import_node_path7.default.join(moduleRoot, relative));
2028
2049
  let artifact;
2029
2050
  try {
2030
2051
  artifact = await artifactFor(project, entry);
@@ -2043,7 +2064,7 @@ function swiftPlugin(options = {}) {
2043
2064
  ...artifact.package.resources.watched,
2044
2065
  ...artifact.package.bundleFiles.watched
2045
2066
  ])
2046
- this.addWatchFile(import_node_path6.default.join(packagePath, ...watched.split(import_node_path6.default.posix.sep)));
2067
+ this.addWatchFile(import_node_path7.default.join(packagePath, ...watched.split(import_node_path7.default.posix.sep)));
2047
2068
  const colors = artifact.package.resources.colors;
2048
2069
  const symbols = artifact.package.resources.symbols;
2049
2070
  const bundleFiles = artifact.package.bundleFiles.files;
package/dist-lib/vite.cjs CHANGED
@@ -1,4 +1,4 @@
1
- /*! rnx v0.1.673 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
1
+ /*! rnx v0.1.674 | (c) 2026 Tamagui LLC | Proprietary — see LICENSE */
2
2
  let __sootsim_import_meta_url = ''; try { __sootsim_import_meta_url = require('url').pathToFileURL(__filename).href; } catch {}
3
3
  "use strict";
4
4
  var __create = Object.create;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.673",
3
+ "version": "0.1.674",
4
4
  "description": "Vite and Metro plugins, testing drivers, and SDK exports for peach.",
5
5
  "author": "Tamagui LLC",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -229,10 +229,11 @@ export function swiftArtifactHash(
229
229
  moduleRoot: string,
230
230
  ): string {
231
231
  const hash = createHash('sha256')
232
+ // v7: runtime class lookup uses the same objc class registry as messages
232
233
  // v6: app and scene delegate classes compile final
233
234
  // (v5: a target declaring resources gets SwiftPM's Bundle.module accessor;
234
235
  // v4: sources compile through swiftSourceAsIOS)
235
- hash.update(`swift-compile/v6\n${release}\n`)
236
+ hash.update(`swift-compile/v7\n${release}\n`)
236
237
  if (input.oneModule) hash.update('one-module\n')
237
238
  hash.update(linkedModuleDigest(moduleRoot))
238
239
  for (const file of Object.keys(input.files).sort()) {
@@ -392,6 +393,17 @@ export function swiftSourceAsIOS(source: string): string {
392
393
  let copied = 0
393
394
  for (const at of tokens) {
394
395
  const rest = conditioned.slice(at, at + 400)
396
+ const imported = /^import\s+CoreImage\.CIFilterBuiltins\b/.exec(rest)
397
+ if (imported) {
398
+ out += conditioned.slice(copied, at) + 'import CoreImage'.padEnd(imported[0].length)
399
+ copied = at + imported[0].length
400
+ continue
401
+ }
402
+ if (/^NSClassFromString\b/.test(rest)) {
403
+ out += conditioned.slice(copied, at) + '_peachClassFromString'
404
+ copied = at + 'NSClassFromString'.length
405
+ continue
406
+ }
395
407
  if (rest.startsWith('class')) {
396
408
  const modifiers = conditioned.slice(conditioned.lastIndexOf('\n', at - 1) + 1, at)
397
409
  if (DELEGATE_CLASS.test(rest) && !/\b(?:final|open)\b/.test(modifiers)) {
@@ -504,16 +516,25 @@ function swiftCodeScan(source: string): { lineStarts: Set<number>; tokens: numbe
504
516
  if (top.parens === 0 && stack.length > 1) stack.pop()
505
517
  else top.parens--
506
518
  i++
507
- } else if (
508
- source.startsWith('class', i) &&
509
- !/[\w$]/.test(source[i - 1] ?? '') &&
510
- !/[\w$]/.test(source[i + 5] ?? '')
511
- ) {
512
- tokens.push(i)
513
- i += 5
514
519
  } else {
515
- if (char === '@') tokens.push(i)
516
- i++
520
+ const keyword = source.startsWith('class', i)
521
+ ? 'class'
522
+ : source.startsWith('import', i)
523
+ ? 'import'
524
+ : source.startsWith('NSClassFromString', i)
525
+ ? 'NSClassFromString'
526
+ : null
527
+ if (
528
+ keyword &&
529
+ !/[\w$]/.test(source[i - 1] ?? '') &&
530
+ !/[\w$]/.test(source[i + keyword.length] ?? '')
531
+ ) {
532
+ tokens.push(i)
533
+ i += keyword.length
534
+ } else {
535
+ if (char === '@') tokens.push(i)
536
+ i++
537
+ }
517
538
  }
518
539
  }
519
540
  return { lineStarts: starts, tokens }
package/src/swift-host.ts CHANGED
@@ -5,6 +5,7 @@ import { createHash } from 'node:crypto'
5
5
  import fs from 'node:fs'
6
6
  import os from 'node:os'
7
7
  import path from 'node:path'
8
+ import { swiftToolchainBin } from '../../../src/compile/swiftToolchain'
8
9
  import {
9
10
  enumerateBundleColors,
10
11
  enumerateBundleSymbols,
@@ -642,10 +643,7 @@ export function localSwiftToolchain(
642
643
  if (typeof release !== 'string') {
643
644
  throw new Error(`swift toolchain manifest at ${moduleRoot} has no release`)
644
645
  }
645
- const toolchainBin = path.join(
646
- os.homedir(),
647
- `Library/Developer/Toolchains/${release}.xctoolchain/usr/bin`,
648
- )
646
+ const toolchainBin = swiftToolchainBin(release)
649
647
  return fs.existsSync(path.join(toolchainBin, 'swift'))
650
648
  ? { release, toolchainBin }
651
649
  : null