peachsim 0.1.2224 → 0.1.2228

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 (171) hide show
  1. package/cli/bridge-flow-runner.ts +56 -3
  2. package/cli/commands/control.ts +27 -1
  3. package/cli/commands/flow.ts +26 -0
  4. package/cli/commands/package.ts +9 -2
  5. package/cli/drivers/playwright.ts +1 -0
  6. package/cli/drivers/types.ts +3 -0
  7. package/cli/internal-child.ts +4 -2
  8. package/dist-lib/agent-daemon-client.cjs +1 -1
  9. package/dist-lib/agent-events.cjs +1 -1
  10. package/dist-lib/attached-projects.cjs +1 -1
  11. package/dist-lib/auth/shared-session.cjs +1 -1
  12. package/dist-lib/backend-origin.cjs +1 -1
  13. package/dist-lib/beta.cjs +1 -1
  14. package/dist-lib/beta.mjs +1 -1
  15. package/dist-lib/bridge-constants.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.cjs +1 -1
  17. package/dist-lib/bridge-contract-input.mjs +1 -1
  18. package/dist-lib/bridge-contract.cjs +1 -1
  19. package/dist-lib/bridge-contract.mjs +1 -1
  20. package/dist-lib/bundle-channel.cjs +931 -455
  21. package/dist-lib/capture-contract.cjs +1 -1
  22. package/dist-lib/capture-contract.mjs +1 -1
  23. package/dist-lib/cloud-contract.cjs +1 -1
  24. package/dist-lib/cloud-contract.mjs +1 -1
  25. package/dist-lib/cloud-test-args.cjs +1 -1
  26. package/dist-lib/cloud-test-args.mjs +1 -1
  27. package/dist-lib/cloud.cjs +1 -1
  28. package/dist-lib/cloud.mjs +1 -1
  29. package/dist-lib/config.cjs +1 -1
  30. package/dist-lib/config.mjs +1 -1
  31. package/dist-lib/detox/index.cjs +2 -2
  32. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  33. package/dist-lib/expo-swift-bundle.cjs +867 -391
  34. package/dist-lib/expo-swift-metadata.cjs +1 -1
  35. package/dist-lib/expo-swift-metadata.mjs +1 -1
  36. package/dist-lib/home-paths.cjs +1 -1
  37. package/dist-lib/host/bridge-host.cjs +926 -450
  38. package/dist-lib/host/fetch-proxy-handler.cjs +55 -12
  39. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  40. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  41. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  42. package/dist-lib/host/websocket-proxy.cjs +1 -1
  43. package/dist-lib/index.cjs +60 -16
  44. package/dist-lib/jump-to-source-babel.cjs +1 -1
  45. package/dist-lib/jump-to-source-native.cjs +1 -1
  46. package/dist-lib/kotlin-host.cjs +1 -1
  47. package/dist-lib/menu.cjs +1 -1
  48. package/dist-lib/menu.mjs +1 -1
  49. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  50. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  51. package/dist-lib/metro-production-bundle.cjs +11 -4
  52. package/dist-lib/metro-production-bundle.mjs +10 -4
  53. package/dist-lib/metro.cjs +60 -16
  54. package/dist-lib/native-app-identity-project.cjs +53 -9
  55. package/dist-lib/native-app-identity-project.mjs +84 -37
  56. package/dist-lib/native-app-identity.cjs +1 -1
  57. package/dist-lib/native-app-identity.mjs +1 -1
  58. package/dist-lib/native-firebase-metadata.cjs +1 -1
  59. package/dist-lib/native-firebase-metadata.mjs +1 -1
  60. package/dist-lib/pdfium-raster.cjs +1 -1
  61. package/dist-lib/pdfium-raster.mjs +1 -1
  62. package/dist-lib/plist.cjs +1 -1
  63. package/dist-lib/plist.mjs +1 -1
  64. package/dist-lib/profiles.cjs +1 -1
  65. package/dist-lib/public-brand.cjs +1 -1
  66. package/dist-lib/public-origins-lib-esm.json +26 -24
  67. package/dist-lib/public-origins-lib.json +66 -54
  68. package/dist-lib/react-native-host-modules.cjs +1 -1
  69. package/dist-lib/react-native-host-modules.mjs +1 -1
  70. package/dist-lib/reap-browser.cjs +1 -1
  71. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  72. package/dist-lib/sdk.cjs +1 -1
  73. package/dist-lib/sdk.mjs +1 -1
  74. package/dist-lib/skills.cjs +1049 -512
  75. package/dist-lib/swift-compile.cjs +557 -121
  76. package/dist-lib/swift-compile.mjs +693 -258
  77. package/dist-lib/swift-package.cjs +1 -1
  78. package/dist-lib/swift-package.mjs +1 -1
  79. package/dist-lib/swift-submit.cjs +1 -1
  80. package/dist-lib/swift-submit.mjs +1 -1
  81. package/dist-lib/swift-toolchain.cjs +38 -2
  82. package/dist-lib/swift.cjs +1 -1
  83. package/dist-lib/vite-swift.cjs +1726 -1209
  84. package/dist-lib/vite.cjs +55 -12
  85. package/dist-lib/worklet-executable.cjs +1 -1
  86. package/dist-lib/worklet-executable.mjs +1 -1
  87. package/dist-types/packages/peach-engine/src/bundle-parse-receipt.d.ts +17 -0
  88. package/dist-types/packages/peach-engine/src/engine/canvaskit-api.d.ts +2 -1
  89. package/dist-types/packages/peach-engine/src/engine/font-config.d.ts +2 -2
  90. package/dist-types/packages/peach-engine/src/engine/native-layout.d.ts +1 -0
  91. package/dist-types/packages/peach-engine/src/engine/native-paragraph.d.ts +4 -0
  92. package/dist-types/packages/peach-engine/src/engine/node.d.ts +2 -0
  93. package/dist-types/packages/peach-engine/src/engine/scene-table.d.ts +1 -1
  94. package/dist-types/packages/peach-engine/src/engine/types.d.ts +7 -0
  95. package/dist-types/packages/peach-engine/src/engine/yoga-layout.d.ts +2 -0
  96. package/dist-types/packages/peach-engine/src/metro-fingerprint.d.ts +3 -2
  97. package/dist-types/packages/peach-engine/src/preview/preview-room-contract.d.ts +6 -0
  98. package/dist-types/packages/peach-engine/src/render-worker/compositor-protocol.d.ts +1 -0
  99. package/dist-types/packages/peach-engine/src/render-worker/protocol.d.ts +15 -3
  100. package/dist-types/packages/peach-engine/src/rolldown-bundle-inventory.d.ts +0 -5
  101. package/dist-types/packages/peach-kit/src/capabilities.d.ts +2 -0
  102. package/dist-types/packages/peach-kit/src/internal.d.ts +1 -1
  103. package/dist-types/packages/peach-kit/src/ios-tint.d.ts +2 -0
  104. package/kotlin/sdk.tar.gz +0 -0
  105. package/package.json +1 -1
  106. package/runtime-companion.json +1 -1
  107. package/sdk/ios/System/Library/Frameworks/CoreFoundation.framework/Headers/CFCGTypes.h +0 -6
  108. package/sdk/ios/System/Library/Frameworks/Foundation.framework/Headers/NSCharacterSet.h +1 -1
  109. package/sdk/ios/System/Library/Frameworks/Foundation.framework/Headers/NSURL.h +1 -1
  110. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIControl.h +0 -26
  111. package/sdk/ios/System/Library/Frameworks/UIKitTypes.framework/Headers/UIKitTypes.h +27 -0
  112. package/sdk/ios/usr/include/AvailabilityInternal.h +2 -2
  113. package/sdk/ios/usr/include/ObjectiveC.apinotes +380 -7
  114. package/sdk/ios/usr/include/peach/pthread.h +1 -7
  115. package/sdk/ios/wasm/include/TargetConditionals.h +2 -3
  116. package/sdk/ios/wasm/include/__struct_timeval.h +15 -0
  117. package/sdk/ios/wasm/include/__typedef_suseconds_t.h +9 -0
  118. package/sdk/ios/wasm/include/limits.h +1 -1
  119. package/sdk/ios/wasm/include/machine/_types.h +1 -1
  120. package/sdk/ios/wasm/include/machine/limits.h +1 -1
  121. package/sdk/ios/wasm/include/machine/param.h +2 -2
  122. package/sdk/ios/wasm/include/math.h +13 -0
  123. package/sdk/ios/wasm/include/pthread.h +1 -13
  124. package/sdk/ios/wasm/include/sys/resource.h +3 -0
  125. package/sdk/ios/wasm/include/sys/socket.h +0 -10
  126. package/sdk/ios/wasm/include/sys/stat.h +5 -2
  127. package/sdk/ios/wasm/include/sys/time.h +16 -3
  128. package/sdk/ios/wasm/include/sys/types.h +4 -1
  129. package/sdk/ios/wasm/include/time.h +2 -0
  130. package/sdk/ios/wasm/storage-include/TargetConditionals.h +2 -3
  131. package/sdk/native-hashes.json +14 -14
  132. package/src/metro-production-bundle.ts +15 -2
  133. package/src/native-slices.ts +3 -2
  134. package/src/native-static-libraries.ts +23 -23
  135. package/src/native-swift-slices.ts +2 -2
  136. package/src/nitro-adapter.lock.json +288 -288
  137. package/src/nitro-compiler-digest.ts +0 -1
  138. package/src/nitro-dependencies.ts +8 -9
  139. package/src/nitro-superset.lock.json +4 -4
  140. package/src/react-native-core-build.ts +2 -2
  141. package/src/swift-compile.ts +209 -47
  142. package/src/swift-compiler-digest.ts +2 -0
  143. package/src/swift-cxx-standin.ts +1 -1
  144. package/src/swift-darwin-records.ts +4 -4
  145. package/src/swift-distribution-contract.ts +2 -2
  146. package/src/swift-distribution.lock.json +13 -12
  147. package/src/swift-guest-compile.ts +6 -5
  148. package/src/swift-guest-image-ledger.ts +5 -5
  149. package/src/swift-guest-link.ts +1 -1
  150. package/src/swift-guest-linked-spans.ts +7 -4
  151. package/src/swift-guest-manifest.ts +2 -2
  152. package/src/swift-guest-source-inputs.ts +16 -5
  153. package/src/swift-host.ts +10 -5
  154. package/src/swift-icu.ts +1 -1
  155. package/src/swift-objc-compile.ts +9 -4
  156. package/src/swift-objc-standin.ts +1 -4
  157. package/src/swift-package-manifest.ts +5 -1
  158. package/src/swift-packages.ts +2 -2
  159. package/src/swift-shared-sdk.ts +1 -1
  160. package/src/swift-standin-emit.ts +3 -16
  161. package/src/swift-standins.ts +119 -87
  162. package/src/swift-toolchain.ts +37 -1
  163. package/src/swift-uniform-type-constants.ts +1 -1
  164. package/src/swift-wasm-prune.ts +17 -12
  165. package/src/swiftGuestImageContract.ts +4 -4
  166. package/src/swiftNativePinContract.ts +1 -1
  167. package/src/swiftRuntimeProductContract.ts +1 -1
  168. package/src/turbo-runtime.lock.json +28 -28
  169. package/src/wasm-narrow-boundary.ts +296 -0
  170. package/src/wasm-optimize.ts +59 -14
  171. package/src/xcode-project.ts +6 -4
@@ -504,7 +504,7 @@ export function linkGuestImages(
504
504
  fs.writeFileSync(irPath, ledger.llvmIR)
505
505
  execFileSync(
506
506
  clang,
507
- ['--target=wasm32-unknown-wasip1', '-c', irPath, '-o', ledgerObject],
507
+ ['--target=wasm64-unknown-wasip1', '-c', irPath, '-o', ledgerObject],
508
508
  { stdio: 'pipe' },
509
509
  )
510
510
  linkedOwners.set(ledgerObject, options.ledgerDataImage)
@@ -29,6 +29,9 @@ function number(bytes: Uint8Array, start: number): [number, number] {
29
29
  }
30
30
  }
31
31
 
32
+ // the linked module places segments with i64.const and the lowered one with i32.const.
33
+ const constant = (opcode: number | undefined) => opcode === 0x41 || opcode === 0x42
34
+
32
35
  function signedAddress(bytes: Uint8Array, start: number): [number, number] {
33
36
  const [value, end] = number(bytes, start)
34
37
  const bits = (end - start) * 7
@@ -84,7 +87,7 @@ function layout(bytes: Uint8Array): WasmLayout {
84
87
  }
85
88
  const limits = () => {
86
89
  const flags = read()
87
- if (flags & ~3) throw new Error('unsupported wasm limits')
90
+ if (flags & ~7) throw new Error('unsupported wasm limits')
88
91
  const minimum = read()
89
92
  if (flags & 1) read()
90
93
  return minimum
@@ -123,7 +126,7 @@ function layout(bytes: Uint8Array): WasmLayout {
123
126
  if (read() !== 1 || memoryPages !== undefined)
124
127
  throw new Error('unsupported wasm memories')
125
128
  const flags = read()
126
- if (flags & ~3) throw new Error('unsupported wasm memory limits')
129
+ if (flags & ~7) throw new Error('unsupported wasm memory limits')
127
130
  memoryPages = read()
128
131
  if (flags & 1) read()
129
132
  if (pos !== memory[1]) throw new Error('invalid wasm memory section')
@@ -160,7 +163,7 @@ function layout(bytes: Uint8Array): WasmLayout {
160
163
  if (flags !== 0 && flags !== 2)
161
164
  throw new Error(`unsupported wasm element segment ${flags}`)
162
165
  if (flags === 2 && read() !== 0) throw new Error('unsupported wasm table index')
163
- if (bytes[pos++] !== 0x41) throw new Error('nonconstant wasm table offset')
166
+ if (!constant(bytes[pos++])) throw new Error('nonconstant wasm table offset')
164
167
  let base: number
165
168
  ;[base, pos] = signedAddress(bytes, pos)
166
169
  if (bytes[pos++] !== 0x0b) throw new Error('invalid wasm table offset')
@@ -191,7 +194,7 @@ function layout(bytes: Uint8Array): WasmLayout {
191
194
  if (flags !== 0 && flags !== 2)
192
195
  throw new Error(`unsupported wasm data segment ${flags}`)
193
196
  if (flags === 2 && read() !== 0) throw new Error('unsupported wasm memory index')
194
- if (bytes[pos++] !== 0x41) throw new Error('nonconstant wasm data offset')
197
+ if (!constant(bytes[pos++])) throw new Error('nonconstant wasm data offset')
195
198
  let address: number
196
199
  ;[address, pos] = signedAddress(bytes, pos)
197
200
  if (bytes[pos++] !== 0x0b) throw new Error('invalid wasm data offset')
@@ -90,8 +90,8 @@ export function createGuestImageManifest(
90
90
  image: GuestManifestImage,
91
91
  ): SwiftGuestImageManifest {
92
92
  const target = {
93
- triple: 'wasm32-unknown-wasip1',
94
- pointerWidth: 32,
93
+ triple: 'wasm64-unknown-wasip1',
94
+ pointerWidth: 64,
95
95
  byteOrder: 'little',
96
96
  cpuType: -1,
97
97
  cpuSubtype: 0,
@@ -1,6 +1,6 @@
1
1
  import { execFileSync } from 'node:child_process'
2
2
  import { createHash } from 'node:crypto'
3
- import { readFileSync, realpathSync, writeFileSync } from 'node:fs'
3
+ import { mkdirSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
4
4
  import path from 'node:path'
5
5
  import { libraryArchiveTarget, type GuestSourceArtifact } from './swift-guest-source-plan'
6
6
  import { frameworkRuntimeProductId } from './swift-runtime-products'
@@ -42,6 +42,10 @@ export function clangIrLinkOptions(ir: string): string[] {
42
42
  return result
43
43
  }
44
44
 
45
+ // the C compiler a package build runs: the toolchain clang, named for the
46
+ // target whose <target>.build directory receives the object
47
+ export const CLANG_TARGET_MODULE_WRAPPER = '.peach-clang'
48
+
45
49
  /** Replay only selected source-owned Clang commands to retain their IR link options. */
46
50
  export function sourceGuestClangLinkOptions(options: {
47
51
  buildDirectory: string
@@ -97,15 +101,22 @@ export function sourceGuestClangLinkOptions(options: {
97
101
  throw new Error(`unsupported source object producer ${file}`)
98
102
  continue
99
103
  }
104
+ const compiler = command.args[0] ? realpathSync(command.args[0]) : ''
100
105
  if (
101
106
  command.tool !== 'clang' ||
102
- !command.args.length ||
103
- realpathSync(command.args[0]!) !==
104
- realpathSync(path.join(options.toolchainBin, 'clang'))
107
+ (compiler !== realpathSync(path.join(options.toolchainBin, 'clang')) &&
108
+ compiler !==
109
+ realpathSync(path.join(options.buildDirectory, CLANG_TARGET_MODULE_WRAPPER)))
105
110
  )
106
111
  throw new Error(`unsupported source object producer ${file}`)
107
112
  const args = command.args.slice(1).filter((arg) => arg !== '-c')
108
- const output = path.join(options.directory, `clang-link-${index}.ll`)
113
+ // the replay keeps the object's <target>.build directory name
114
+ const outputDirectory = path.join(
115
+ options.directory,
116
+ path.basename(path.dirname(file)),
117
+ )
118
+ mkdirSync(outputDirectory, { recursive: true })
119
+ const output = path.join(outputDirectory, `clang-link-${index}.ll`)
109
120
  for (const flag of ['-o', '-MF']) {
110
121
  const index = args.lastIndexOf(flag)
111
122
  if (index < 0 || index + 1 >= args.length)
package/src/swift-host.ts CHANGED
@@ -1171,16 +1171,21 @@ async function buildXcodeLayout(root: string): Promise<XcodeLayout | null> {
1171
1171
  )
1172
1172
  .map((feature) => feature.name),
1173
1173
  // the flat build gives every module one package; swiftpm names each
1174
- // module for its own package, which `@retroactive` and `package` read
1175
- swiftFlags: ['-package-name', swiftPackageIdentity(target.packageDir)].concat(
1176
- target.packageSwiftFlags
1174
+ // module for its own package, which `@retroactive` and `package` read.
1175
+ // xcode and swiftpm build a debug package testable, so sources may
1176
+ // `@testable import` it
1177
+ swiftFlags: [
1178
+ '-package-name',
1179
+ swiftPackageIdentity(target.packageDir),
1180
+ ...(packageConfiguration === 'debug' ? ['-enable-testing'] : []),
1181
+ ...target.packageSwiftFlags
1177
1182
  .filter(
1178
1183
  (setting) =>
1179
1184
  setting.configuration === null ||
1180
1185
  setting.configuration === packageConfiguration,
1181
1186
  )
1182
1187
  .flatMap((setting) => setting.flags),
1183
- ),
1188
+ ],
1184
1189
  linkedLibraries: target.packageLibraries
1185
1190
  .filter(
1186
1191
  (library) =>
@@ -1666,7 +1671,7 @@ function xcodeManifest(layout: XcodeLayout): string {
1666
1671
  return [
1667
1672
  '// swift-tools-version: 6.2',
1668
1673
  'import PackageDescription',
1669
- `let package = Package(name: "app", ${layout.app.iosDeploymentTarget ? `platforms: [.iOS(${JSON.stringify(layout.app.iosDeploymentTarget)})], ` : ''}dependencies: [${[...nativePaths].map(([name, directory]) => `.package(name: ${JSON.stringify(name)}, path: ${JSON.stringify(directory)})`).join(', ')}], targets: [`,
1674
+ `let package = Package(name: "app", platforms: [.iOS(${JSON.stringify(layout.app.iosDeploymentTarget)})], dependencies: [${[...nativePaths].map(([name, directory]) => `.package(name: ${JSON.stringify(name)}, path: ${JSON.stringify(directory)})`).join(', ')}], targets: [`,
1670
1675
  ` .executableTarget(name: "${layout.app.moduleName}", dependencies: [${[...appProducts, ...layout.targets.map((target) => JSON.stringify(target.name)), ...sdkProducts].join(', ')}], path: "${XCODE_APP_DIR}", ${appSettings}),`,
1671
1676
  ...layout.targets.map((target) =>
1672
1677
  target.systemLibrary
package/src/swift-icu.ts CHANGED
@@ -141,7 +141,7 @@ async function load(toolchainBin: string, sdk: string): Promise<Buffer> {
141
141
  ...swiftSdkOptions(),
142
142
  '--show-configuration',
143
143
  sdk,
144
- 'wasm32-unknown-wasip1',
144
+ 'wasm64-unknown-wasip1',
145
145
  ],
146
146
  { env: swiftEnvironment() },
147
147
  )
@@ -5,7 +5,7 @@ import path from 'node:path'
5
5
  import { mapLimit } from '../../../src/helpers/mapLimit.ts'
6
6
  import { cacheDir } from './home-paths'
7
7
  import { isRecord } from './is-record'
8
- import { DOUBLE_CONVERSION_WASM32_BACKPORT } from './nitro-dependencies'
8
+ import { DOUBLE_CONVERSION_WASM64_BACKPORT } from './nitro-dependencies'
9
9
  import {
10
10
  swiftBuildJobs,
11
11
  swiftSdkPaths,
@@ -320,7 +320,7 @@ function* xcodeObjCInputSteps(
320
320
  )
321
321
  // the pod's own double-conversion utils.h takes the approved backport by
322
322
  // its exact original bytes; the file on disk stays unchanged.
323
- const backport = DOUBLE_CONVERSION_WASM32_BACKPORT
323
+ const backport = DOUBLE_CONVERSION_WASM64_BACKPORT
324
324
  if (
325
325
  path.basename(file) !== 'utils.h' ||
326
326
  createHash('sha256').update(bytes).digest('hex') !== backport.originalSha256
@@ -713,6 +713,11 @@ function* xcodeObjCInputSteps(
713
713
  }
714
714
  for (const reference of references) {
715
715
  if (++workCount % 64 === 0) yield
716
+ if (
717
+ path.isAbsolute(reference.name) &&
718
+ /\.sdk\/(?:System|Developer)\/Library\/Frameworks\//.test(reference.name)
719
+ )
720
+ continue
716
721
  // only the first quoted lookup depends on the including file. after a
717
722
  // local miss, every includer shares the target's ordered search paths.
718
723
  if (reference.quoted && !reference.next) {
@@ -1120,7 +1125,7 @@ export function prepareXcodeSwiftProducts(
1120
1125
  ? ['-merge-modules', '-emit-module']
1121
1126
  : ['-emit-object', '-whole-module-optimization', '-parse-as-library']),
1122
1127
  '-target',
1123
- 'wasm32-unknown-wasip1',
1128
+ 'wasm64-unknown-wasip1',
1124
1129
  '-sdk',
1125
1130
  sdk.sysroot,
1126
1131
  '-resource-dir',
@@ -1547,7 +1552,7 @@ export async function prepareXcodeObjCImplementations(
1547
1552
  (!cxx ||
1548
1553
  flags.lastIndexOf('-fno-cxx-modules') <= flags.lastIndexOf('-fcxx-modules'))
1549
1554
  const args = [
1550
- '--target=wasm32-unknown-wasip1',
1555
+ '--target=wasm64-unknown-wasip1',
1551
1556
  `--sysroot=${sdk.sysroot}`,
1552
1557
  '-fwasm-exceptions',
1553
1558
  '-fexceptions',
@@ -303,14 +303,11 @@ export function objcSdkIntakeFlags(
303
303
  return [
304
304
  ...swiftObjCPlatformFlags(toolchainBin, minimum),
305
305
  // AvailabilityInternal.h derives these through __is_target_os(ios), which
306
- // is false for wasm32. the maximum is the sdk the headers come from, as
306
+ // is false for wasm64. the maximum is the sdk the headers come from, as
307
307
  // xcode defines it, so `#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_26_0`
308
308
  // sources see the members the sdk declares instead of a 17.0 default.
309
309
  `-D__IPHONE_OS_VERSION_MIN_REQUIRED=${minimum}`,
310
310
  `-D__IPHONE_OS_VERSION_MAX_ALLOWED=__IPHONE_${NATIVE_GRAPH_SDK_VERSION.replace('.', '_')}`,
311
- // apple's build setting for a 32-bit target to keep NSInteger and
312
- // NSUInteger long, the nominal types they have on arm64.
313
- '-DNS_BUILD_32_LIKE_64=1',
314
311
  // the installed libc's default feature set otherwise defines
315
312
  // _XOPEN_SOURCE, which darwin's sys/cdefs.h turns into a strict posix
316
313
  // level; iOS compiles at darwin's full level with neither defined.
@@ -513,7 +513,11 @@ export function swiftPackageManifest(
513
513
  ? '5'
514
514
  : (string(record(raw.toolsVersion)._version) ?? 'unknown')
515
515
  let mainActorIsolation = false
516
- const defines: SwiftManifestSetting[] = []
516
+ // swiftpm defines each enabled trait as a condition in every swift target
517
+ const defines: SwiftManifestSetting[] = [...traits].map((name) => ({
518
+ name,
519
+ configuration: null,
520
+ }))
517
521
  const libraries: SwiftManifestSetting[] = []
518
522
  const frameworks: SwiftManifestSetting[] = []
519
523
  const experimentalFeatures: SwiftManifestSetting[] = []
@@ -116,7 +116,7 @@ export interface SwiftPackageBinary {
116
116
  reached: boolean
117
117
  /** a source Objective-C target: public headers relative to dir. */
118
118
  publicHeaders?: string
119
- /** sources, relative to the package, with no wasm32 lowering that keep a
119
+ /** sources, relative to the package, with no wasm lowering that keep a
120
120
  * source target from compiling; its public headers stand in for it. */
121
121
  unloweredSources?: string[]
122
122
  /** dependency module public headers, relative to dir. */
@@ -693,7 +693,7 @@ export function resolveSwiftPackages(options: {
693
693
  : target.type !== 'regular' && target.type !== 'system'
694
694
  ? `${name} is a ${target.type} target`
695
695
  : unlowerable.length > 0
696
- ? `${name} has native sources with no wasm32 lowering: ${unlowerable.map((file) => path.relative(pkg.manifest.dir, file)).join(', ')}${gap ? `; ${gap}` : ''}`
696
+ ? `${name} has native sources with no wasm lowering: ${unlowerable.map((file) => path.relative(pkg.manifest.dir, file)).join(', ')}${gap ? `; ${gap}` : ''}`
697
697
  : null
698
698
  // every dependency resolves, so a failing one never hides the rest
699
699
  // of the closure from the compile or from the report
@@ -277,7 +277,7 @@ export function swiftSharedSdkViewOptions(
277
277
  ...swiftSdkOptions(),
278
278
  '--show-configuration',
279
279
  sdk,
280
- 'wasm32-unknown-wasip1',
280
+ 'wasm64-unknown-wasip1',
281
281
  ],
282
282
  { encoding: 'utf8', env: swiftEnvironment(), stdio: ['ignore', 'pipe', 'pipe'] },
283
283
  )
@@ -1529,6 +1529,7 @@ export function emitSwiftStandin(
1529
1529
  ].includes(name)
1530
1530
  ) &&
1531
1531
  !(name === nsObjectProtocol && externalRoot(id) === nsObject) &&
1532
+ !options.unconformed?.get(path)?.has(name.split(/::|\./).pop()!) &&
1532
1533
  !options.unconformed?.get(path)?.has(name),
1533
1534
  ),
1534
1535
  ].filter((name, at, all) => all.indexOf(name) === at)
@@ -1703,8 +1704,7 @@ export function emitSwiftStandin(
1703
1704
  synthesizedEquality(member, list))
1704
1705
  )
1705
1706
  continue
1706
- const header = values.get(member.identifier.precise)
1707
- const value = header === undefined ? undefined : atWidth(header, raw)
1707
+ const value = values.get(member.identifier.precise)
1708
1708
  if (value !== undefined && member.kind.identifier === 'swift.type.property') {
1709
1709
  emit(
1710
1710
  `${inner}public static let ${tick(leaf(member))} = ${shape.name}(rawValue: ${value})`,
@@ -1763,8 +1763,7 @@ export function emitSwiftStandin(
1763
1763
  )
1764
1764
  const seenValues = new Map<string, string>()
1765
1765
  for (const member of cases) {
1766
- const header = values.get(member.identifier.precise)
1767
- const value = header === undefined ? undefined : atWidth(header, raw)
1766
+ const value = values.get(member.identifier.precise)
1768
1767
  // objective-c aliases a value under a second name; swift spells
1769
1768
  // the alias as a static member of the first case.
1770
1769
  if (value !== undefined && seenValues.has(value)) {
@@ -1976,18 +1975,6 @@ export function emitSwiftStandin(
1976
1975
  }
1977
1976
  return null
1978
1977
  }
1979
- // header values are clang's for 64-bit iOS. NSUIntegerMax, NSIntegerMax
1980
- // and NSIntegerMin are the platform-width type's own extremes, which on
1981
- // wasm32 are the 32-bit ones.
1982
- const atWidth = (value: string, raw: string | null) =>
1983
- (raw === 'UInt' || raw === 'Swift.UInt') && value === '18446744073709551615'
1984
- ? '4294967295'
1985
- : (raw === 'Int' || raw === 'Swift.Int') && value === '9223372036854775807'
1986
- ? '2147483647'
1987
- : (raw === 'Int' || raw === 'Swift.Int') && value === '-9223372036854775808'
1988
- ? '-2147483648'
1989
- : value
1990
-
1991
1978
  const emitGlobal = scoped((symbol: GraphSymbol) => {
1992
1979
  const path = pathOf(symbol)
1993
1980
  const kind = symbol.kind.identifier
@@ -13,12 +13,14 @@ import { execFileSync, spawn, spawnSync } from 'node:child_process'
13
13
  import { createHash } from 'node:crypto'
14
14
  import fs from 'node:fs'
15
15
  import path from 'node:path'
16
+ import { PEACH_FORKED_SCRIPT_ENV } from './forked-script-contract'
16
17
  import { cacheDir as peachCacheDir } from './home-paths'
17
18
  import { isRecord } from './is-record'
18
19
  import { fetchNativeEntry, nativeEntryKey } from './native-prebuilt'
19
20
  import { nativeSliceEntry, NATIVE_SLICE_RECIPES } from './native-slices'
20
21
  import { nativeStaticLibrary, nativeStaticLibraryRecipe } from './native-static-libraries'
21
22
  import { nativeSwiftSlice } from './native-swift-slices'
23
+ import { tryAcquireNumberedLock } from './numbered-lock'
22
24
  import { outputLockStdio } from './output-lock-stdio'
23
25
  import {
24
26
  FOUNDATION_IMPLICIT_MODULES,
@@ -35,6 +37,7 @@ import {
35
37
  swiftSdkPaths,
36
38
  } from './swift-compile'
37
39
  import { emitCxxStandin } from './swift-cxx-standin'
40
+ import { swiftModuleToolchain } from './swift-distribution'
38
41
  import {
39
42
  iosSdkId,
40
43
  WASI_EMULATION,
@@ -74,7 +77,7 @@ import {
74
77
  } from './swift-toolchain'
75
78
  import { simulatorNativeLibrary } from './swift-xcframework'
76
79
 
77
- const TRIPLE = 'wasm32-unknown-wasip1'
80
+ const TRIPLE = 'wasm64-unknown-wasip1'
78
81
  // every stand-in artifact and temporary workspace belongs to peach.
79
82
  const cacheDir = path.join(peachCacheDir(), 'swift-standins')
80
83
  export interface SwiftStandin {
@@ -1700,6 +1703,14 @@ function graphStandin(
1700
1703
  unconformed.set(owner, new Set([...(unconformed.get(owner) ?? []), conformance]))
1701
1704
  continue
1702
1705
  }
1706
+ // a superclass another module declares already brings this conformance
1707
+ const redundant = /^redundant conformance of '\w+' to protocol '(\w+)'$/.exec(
1708
+ match[3]!,
1709
+ )?.[1]
1710
+ if (owner && redundant) {
1711
+ unconformed.set(owner, new Set([...(unconformed.get(owner) ?? []), redundant]))
1712
+ continue
1713
+ }
1703
1714
  if (owner && swiftPaths.has(owner))
1704
1715
  throw new Error(
1705
1716
  `Swift declaration ${module}.${owner} does not typecheck: ${match[3]}`,
@@ -2175,7 +2186,7 @@ async function cxxStandin(
2175
2186
  }
2176
2187
  }
2177
2188
 
2178
- export const RUST_TARGET = 'wasm32-wasip1'
2189
+ export const RUST_TARGET = 'wasm64-wasip1'
2179
2190
  // directories a crate search never enters: build output and installed deps
2180
2191
  const UNSEARCHED = new Set([
2181
2192
  'node_modules',
@@ -2233,9 +2244,7 @@ export function crateFor(root: string, name: string): string | null {
2233
2244
  */
2234
2245
  export const RUST_TOOLCHAIN = '1.94.0'
2235
2246
 
2236
- // the directories a crate's build reads: the workspace that owns its Cargo.lock
2237
- // plus every path dependency that lies outside it.
2238
- function crateSourceRoots(manifest: string): string[] {
2247
+ function crateWorkspace(manifest: string): string {
2239
2248
  let workspace = path.dirname(manifest)
2240
2249
  while (!fs.existsSync(path.join(workspace, 'Cargo.lock'))) {
2241
2250
  const parent = path.dirname(workspace)
@@ -2243,7 +2252,15 @@ function crateSourceRoots(manifest: string): string[] {
2243
2252
  throw new Error(`${manifest} has no Cargo.lock; the build runs --locked`)
2244
2253
  workspace = parent
2245
2254
  }
2246
- const roots = [workspace]
2255
+ return workspace
2256
+ }
2257
+
2258
+ function crateSourceRoots(manifest: string, searchRoot: string): string[] {
2259
+ const workspace = crateWorkspace(manifest)
2260
+ const root = path.resolve(searchRoot)
2261
+ const roots = path.relative(root, workspace).startsWith('..')
2262
+ ? [root, workspace]
2263
+ : [root]
2247
2264
  const inside = (dir: string) =>
2248
2265
  roots.some((root) => !path.relative(root, dir).startsWith('..'))
2249
2266
  const manifests = (dir: string): string[] =>
@@ -2269,7 +2286,7 @@ function crateSourceRoots(manifest: string): string[] {
2269
2286
 
2270
2287
  // a digest of every file under the roots a crate builds from, build output and
2271
2288
  // installed dependencies aside.
2272
- function crateSourceDigest(manifest: string): string {
2289
+ function crateSourceDigest(manifest: string, searchRoot: string): string {
2273
2290
  const hash = createHash('sha256')
2274
2291
  const walk = (dir: string, root: string) => {
2275
2292
  for (const entry of fs
@@ -2285,7 +2302,7 @@ function crateSourceDigest(manifest: string): string {
2285
2302
  }
2286
2303
  }
2287
2304
  }
2288
- for (const root of crateSourceRoots(manifest)) {
2305
+ for (const root of crateSourceRoots(manifest, searchRoot)) {
2289
2306
  hash.update(`root\0`)
2290
2307
  walk(root, root)
2291
2308
  }
@@ -2293,14 +2310,20 @@ function crateSourceDigest(manifest: string): string {
2293
2310
  }
2294
2311
 
2295
2312
  /** the registry entry a crate's static library lives under. */
2296
- export function rustCrateEntry(manifest: string, library: string) {
2313
+ export function rustCrateEntry(
2314
+ manifest: string,
2315
+ library: string,
2316
+ moduleRoot: string,
2317
+ searchRoot: string,
2318
+ ) {
2297
2319
  const inputs = {
2298
2320
  crate: library,
2299
- source: crateSourceDigest(manifest),
2321
+ source: crateSourceDigest(manifest, searchRoot),
2300
2322
  target: RUST_TARGET,
2301
- build: 'release locked',
2323
+ build: 'release locked panic=abort',
2324
+ compiler: swiftModuleToolchain(moduleRoot).release,
2325
+ sdk: swiftModuleSdk(moduleRoot).wasmSdkChecksum,
2302
2326
  rust: RUST_TOOLCHAIN,
2303
- rustflags: process.env.RUSTFLAGS ?? '',
2304
2327
  }
2305
2328
  return { name: library, inputs, key: nativeEntryKey(inputs) }
2306
2329
  }
@@ -2308,7 +2331,7 @@ export function rustCrateEntry(manifest: string, library: string) {
2308
2331
  /**
2309
2332
  * the WebAssembly static library a c stand-in links in place of its traps,
2310
2333
  * or null when it has none. a build the developer supplies in the
2311
- * xcframework (`wasm32-wasip1/lib<name>.a`) wins; otherwise the crate under
2334
+ * xcframework (`wasm64-wasip1/lib<name>.a`) wins; otherwise the crate under
2312
2335
  * `searchRoot` that builds the slice's library comes from the registry when
2313
2336
  * it holds that crate's source and toolchain, else compiles with the
2314
2337
  * developer's cargo with the registry's pinned toolchain. peach ships no rust compiler.
@@ -2353,10 +2376,11 @@ export function standinLibrary(
2353
2376
  }
2354
2377
  const manifest = crateFor(searchRoot, path.basename(library, '.a').replace(/^lib/, ''))
2355
2378
  if (!manifest) return null
2356
- const entry = rustCrateEntry(manifest, library)
2379
+ if (!toolchain) throw new Error('Rust native libraries need the Swift SDK')
2380
+ const entry = rustCrateEntry(manifest, library, toolchain.moduleRoot, searchRoot)
2357
2381
  const prebuilt = fetchNativeEntry('rust', entry.name, entry.key)
2358
2382
  if (prebuilt) return path.join(prebuilt, library)
2359
- return buildRustCrate(manifest, library, searchRoot)
2383
+ return buildRustCrate(manifest, library, searchRoot, toolchain.moduleRoot, entry)
2360
2384
  }
2361
2385
 
2362
2386
  /** compiles a crate with the same rust standard library as registry archives. */
@@ -2364,87 +2388,95 @@ export function buildRustCrate(
2364
2388
  manifest: string,
2365
2389
  library: string,
2366
2390
  searchRoot: string,
2391
+ moduleRoot: string,
2392
+ entry = rustCrateEntry(manifest, library, moduleRoot, searchRoot),
2367
2393
  ): string {
2368
- const crate = path.relative(searchRoot, path.dirname(manifest))
2369
- // rustup installs the pinned toolchain and its wasm target, and is a no-op
2370
- // when both are present. a cargo without rustup has to carry them itself.
2371
- const rustup = spawnSync(
2372
- // runner-toolchain-platform: darwin
2373
- 'rustup',
2374
- [
2375
- 'toolchain',
2376
- 'install',
2377
- RUST_TOOLCHAIN,
2378
- '--profile',
2379
- 'minimal',
2380
- '--target',
2381
- RUST_TARGET,
2382
- '--no-self-update',
2383
- ],
2384
- { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] },
2385
- )
2386
- if (!rustup.error && rustup.status !== 0)
2387
- throw new Error(
2388
- `rustup could not install Rust ${RUST_TOOLCHAIN} with ${RUST_TARGET} for ${crate}: ${failure(rustup)}`,
2394
+ const compiler = swiftModuleToolchain(moduleRoot)
2395
+ const sdk = swiftModuleSdk(moduleRoot)
2396
+ const sdkRoot = path.dirname(swiftSdkPaths(moduleRoot, compiler.toolchainBin).sysroot)
2397
+ const runner = path.join(sdkRoot, 'rust/scripts/build-rust-wasm64.mjs')
2398
+ const work = path.join(cacheDir, 'rust', entry.key)
2399
+ const release = tryAcquireNumberedLock(work + '.lock', manifest)
2400
+ if (!release) throw new Error('Rust native build already running: ' + manifest)
2401
+ try {
2402
+ const roots = crateSourceRoots(manifest, searchRoot)
2403
+ let common = roots[0]!
2404
+ while (
2405
+ roots.some((root) => {
2406
+ const relative = path.relative(common, root)
2407
+ return relative === '..' || relative.startsWith('..' + path.sep)
2408
+ })
2389
2409
  )
2390
- const result = spawnSync(
2391
- // runner-toolchain-platform: darwin
2392
- 'cargo',
2393
- [
2394
- 'build',
2395
- '--release',
2396
- '--locked',
2397
- '--target',
2398
- RUST_TARGET,
2399
- '--message-format=json-render-diagnostics',
2400
- '--manifest-path',
2401
- manifest,
2402
- '--target-dir',
2403
- path.join(cacheDir, 'cargo', key(manifest)),
2404
- ],
2405
- {
2406
- encoding: 'utf8',
2407
- env: {
2408
- ...process.env,
2409
- RUSTUP_TOOLCHAIN: RUST_TOOLCHAIN,
2410
- CARGO_HOME: path.join(cacheDir, 'cargo-home'),
2411
- },
2412
- maxBuffer: 256 * 1024 * 1024,
2413
- stdio: ['ignore', 'pipe', 'pipe'],
2414
- },
2415
- )
2416
- if (result.error)
2417
- throw new Error(
2418
- `${crate} is a rust crate and cargo is not installed; install rust (https://rustup.rs), then run again`,
2410
+ common = path.dirname(common)
2411
+ const source = path.join(work, 'source')
2412
+ fs.rmSync(source, { recursive: true, force: true })
2413
+ for (const root of roots)
2414
+ fs.cpSync(root, path.join(source, path.relative(common, root)), {
2415
+ recursive: true,
2416
+ filter: (file) => !UNSEARCHED.has(path.basename(file)),
2417
+ })
2418
+ const privateManifest = path.join(source, path.relative(common, manifest))
2419
+ const lock = path.join(
2420
+ source,
2421
+ path.relative(common, crateWorkspace(manifest)),
2422
+ 'Cargo.lock',
2419
2423
  )
2420
- if (result.status !== 0) {
2421
- if (
2422
- /target may not be installed|can't find crate for `(core|std)`/.test(result.stderr)
2424
+ const result = spawnSync(
2425
+ process.execPath,
2426
+ [
2427
+ runner,
2428
+ '--bin',
2429
+ compiler.toolchainBin,
2430
+ '--sdk',
2431
+ sdkRoot,
2432
+ '--sdk-checksum',
2433
+ sdk.wasmSdkChecksum,
2434
+ '--work',
2435
+ path.join(work, 'toolchain'),
2436
+ '--manifest',
2437
+ privateManifest,
2438
+ '--lock',
2439
+ lock,
2440
+ '--panic',
2441
+ 'abort',
2442
+ '--cargo-arg=--locked',
2443
+ '--cargo-arg=--jobs',
2444
+ '--cargo-arg=' + (process.env.TM_EXEC_CPU_CORES ?? '1'),
2445
+ ],
2446
+ {
2447
+ encoding: 'utf8',
2448
+ env: { ...swiftEnvironment(), [PEACH_FORKED_SCRIPT_ENV]: '1' },
2449
+ maxBuffer: 256 * 1024 * 1024,
2450
+ stdio: ['ignore', 'pipe', 'pipe'],
2451
+ },
2423
2452
  )
2453
+ if (result.error) throw result.error
2454
+ if (result.status !== 0)
2424
2455
  throw new Error(
2425
- `${crate} builds for ${RUST_TARGET}, which Rust ${RUST_TOOLCHAIN} lacks; run \`rustup target add --toolchain ${RUST_TOOLCHAIN} ${RUST_TARGET}\`, then run again`,
2456
+ `Rust wasm64 could not build ${path.relative(searchRoot, manifest)}: ${failure(result)}`,
2426
2457
  )
2458
+ for (const line of result.stdout.split('\n')) {
2459
+ if (!line.startsWith('{')) continue
2460
+ const message: unknown = JSON.parse(line)
2461
+ if (
2462
+ !message ||
2463
+ typeof message !== 'object' ||
2464
+ !('filenames' in message) ||
2465
+ !Array.isArray(message.filenames)
2466
+ )
2467
+ continue
2468
+ const archive = message.filenames.find(
2469
+ (file): file is string =>
2470
+ typeof file === 'string' && path.basename(file) === library,
2471
+ )
2472
+ if (archive) return archive
2473
+ }
2427
2474
  throw new Error(
2428
- `cargo could not build ${crate} for ${RUST_TARGET}: ${failure(result)}`,
2429
- )
2430
- }
2431
- for (const line of result.stdout.split('\n')) {
2432
- if (!line.startsWith('{')) continue
2433
- const message: unknown = JSON.parse(line)
2434
- if (
2435
- !message ||
2436
- typeof message !== 'object' ||
2437
- !('filenames' in message) ||
2438
- !Array.isArray(message.filenames)
2475
+ `cargo built ${manifest} for ${RUST_TARGET} but reported no ${library}`,
2439
2476
  )
2440
- continue
2441
- const archive = message.filenames.find(
2442
- (file): file is string =>
2443
- typeof file === 'string' && path.basename(file) === library,
2444
- )
2445
- if (archive) return archive
2477
+ } finally {
2478
+ release()
2446
2479
  }
2447
- throw new Error(`cargo built ${crate} for ${RUST_TARGET} but reported no ${library}`)
2448
2480
  }
2449
2481
 
2450
2482
  // source preflight admits the complete closure once, including ignored local