peachsim 0.1.2209 → 0.1.2213

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 (141) hide show
  1. package/cli/command-registry.ts +1 -0
  2. package/cli/commands/inspect/settling.ts +1 -1
  3. package/cli/commands/map.ts +576 -0
  4. package/cli/commands/runtime.ts +1 -1
  5. package/cli/main.ts +6 -0
  6. package/cli/outbound-endpoints.ts +11 -0
  7. package/dist-lib/agent-daemon-client.cjs +1 -1
  8. package/dist-lib/agent-events.cjs +1 -1
  9. package/dist-lib/attached-projects.cjs +1 -1
  10. package/dist-lib/auth/shared-session.cjs +1 -1
  11. package/dist-lib/backend-origin.cjs +1 -1
  12. package/dist-lib/beta.cjs +1 -1
  13. package/dist-lib/beta.mjs +1 -1
  14. package/dist-lib/bridge-constants.cjs +1 -1
  15. package/dist-lib/bridge-contract-input.cjs +1 -1
  16. package/dist-lib/bridge-contract-input.mjs +1 -1
  17. package/dist-lib/bridge-contract.cjs +1 -1
  18. package/dist-lib/bridge-contract.mjs +1 -1
  19. package/dist-lib/bundle-channel.cjs +282 -53
  20. package/dist-lib/capture-contract.cjs +1 -1
  21. package/dist-lib/capture-contract.mjs +1 -1
  22. package/dist-lib/cloud-contract.cjs +1 -1
  23. package/dist-lib/cloud-contract.mjs +1 -1
  24. package/dist-lib/cloud-test-args.cjs +1 -1
  25. package/dist-lib/cloud-test-args.mjs +1 -1
  26. package/dist-lib/cloud.cjs +1 -1
  27. package/dist-lib/cloud.mjs +1 -1
  28. package/dist-lib/config.cjs +1 -1
  29. package/dist-lib/config.mjs +1 -1
  30. package/dist-lib/detox/index.cjs +6 -3
  31. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  32. package/dist-lib/expo-swift-bundle.cjs +280 -51
  33. package/dist-lib/expo-swift-metadata.cjs +1 -1
  34. package/dist-lib/expo-swift-metadata.mjs +1 -1
  35. package/dist-lib/home-paths.cjs +1 -1
  36. package/dist-lib/host/bridge-host.cjs +1264 -856
  37. package/dist-lib/host/fetch-proxy-handler.cjs +21 -5
  38. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  39. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  40. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  41. package/dist-lib/host/websocket-proxy.cjs +1 -1
  42. package/dist-lib/index.cjs +1966 -752
  43. package/dist-lib/jump-to-source-babel.cjs +1 -1
  44. package/dist-lib/jump-to-source-native.cjs +1 -1
  45. package/dist-lib/kotlin-host.cjs +1 -1
  46. package/dist-lib/menu.cjs +1 -1
  47. package/dist-lib/menu.mjs +1 -1
  48. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  49. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  50. package/dist-lib/metro-production-bundle.cjs +1 -1
  51. package/dist-lib/metro-production-bundle.mjs +1 -1
  52. package/dist-lib/metro.cjs +1806 -593
  53. package/dist-lib/native-app-identity-project.cjs +19 -3
  54. package/dist-lib/native-app-identity-project.mjs +19 -3
  55. package/dist-lib/native-app-identity.cjs +1 -1
  56. package/dist-lib/native-app-identity.mjs +1 -1
  57. package/dist-lib/native-firebase-metadata.cjs +1 -1
  58. package/dist-lib/native-firebase-metadata.mjs +1 -1
  59. package/dist-lib/pdfium-raster.cjs +1 -1
  60. package/dist-lib/pdfium-raster.mjs +1 -1
  61. package/dist-lib/plist.cjs +1 -1
  62. package/dist-lib/plist.mjs +1 -1
  63. package/dist-lib/profiles.cjs +1 -1
  64. package/dist-lib/public-brand.cjs +1 -1
  65. package/dist-lib/public-origins-lib-esm.json +25 -24
  66. package/dist-lib/public-origins-lib.json +83 -53
  67. package/dist-lib/react-native-host-modules.cjs +1 -1
  68. package/dist-lib/react-native-host-modules.mjs +1 -1
  69. package/dist-lib/reap-browser.cjs +1 -1
  70. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  71. package/dist-lib/sdk.cjs +2 -2
  72. package/dist-lib/sdk.mjs +2 -2
  73. package/dist-lib/skills.cjs +1800 -1334
  74. package/dist-lib/swift-compile.cjs +58 -12
  75. package/dist-lib/swift-compile.mjs +57 -12
  76. package/dist-lib/swift-package.cjs +1 -1
  77. package/dist-lib/swift-package.mjs +1 -1
  78. package/dist-lib/swift-submit.cjs +1 -1
  79. package/dist-lib/swift-submit.mjs +1 -1
  80. package/dist-lib/swift-toolchain.cjs +1 -1
  81. package/dist-lib/swift.cjs +1 -1
  82. package/dist-lib/vite-swift.cjs +257 -47
  83. package/dist-lib/vite.cjs +1530 -303
  84. package/dist-lib/worklet-executable.cjs +1 -1
  85. package/dist-lib/worklet-executable.mjs +1 -1
  86. package/dist-types/packages/peach-engine/src/engine/font-config.d.ts +1 -1
  87. package/dist-types/packages/peach-engine/src/engine/node.d.ts +1 -0
  88. package/kotlin/sdk.tar.gz +0 -0
  89. package/package.json +1 -1
  90. package/runtime-companion.json +1 -1
  91. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/CoreData.apinotes +35 -0
  92. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/CoreData.h +8 -0
  93. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSAttributeDescription.h +30 -0
  94. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSEntityDescription.h +14 -0
  95. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSExpressionDescription.h +10 -0
  96. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSFetchIndexDescription.h +13 -0
  97. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSFetchIndexElementDescription.h +18 -0
  98. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSManagedObject.h +11 -0
  99. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectContext.h +19 -0
  100. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectID.h +2 -0
  101. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectModel.h +3 -0
  102. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSMergePolicy.h +17 -0
  103. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSPersistentStore.h +8 -0
  104. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSPersistentStoreCoordinator.h +6 -0
  105. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSPropertyDescription.h +13 -0
  106. package/sdk/ios/System/Library/Frameworks/CoreData.framework/Headers/NSRelationshipDescription.h +21 -0
  107. package/sdk/ios/System/Library/Frameworks/QuartzCore.framework/Headers/CoreAnimation.h +2 -0
  108. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIImage.h +1 -10
  109. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIKit.apinotes +21 -0
  110. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UINibLoading.h +1 -1
  111. package/sdk/ios/System/Library/Frameworks/UIKitTypes.framework/Headers/UIKitTypes.h +11 -0
  112. package/sdk/ios/usr/lib/swift/Combine.swiftmodule/arm64-apple-ios-simulator.swiftinterface +18 -0
  113. package/sdk/ios/usr/lib/swift/Foundation.swiftmodule/arm64-apple-ios-simulator.swiftinterface +1 -0
  114. package/sdk/ios/usr/lib/swift/SwiftUI.swiftmodule/arm64-apple-ios-simulator.swiftinterface +19 -0
  115. package/sdk/ios/usr/lib/swift/SwiftUICore.swiftmodule/arm64-apple-ios-simulator.swiftinterface +4 -0
  116. package/sdk/ios/usr/lib/swift/UIKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +4 -0
  117. package/sdk/ios/wasm/include/pthread.h +1 -0
  118. package/sdk/ios/wasm/include/signal.h +2 -2
  119. package/sdk/native-hashes.json +3 -3
  120. package/skills/contrast/SKILL.md +1 -0
  121. package/src/home-paths.ts +1 -1
  122. package/src/host/bridge-host.ts +101 -97
  123. package/src/metro-plugin.ts +4 -1
  124. package/src/native-static-libraries.ts +7 -0
  125. package/src/react-native-coverage/native-source-ranges-file.ts +1 -1
  126. package/src/runtime-assets.ts +0 -1
  127. package/src/runtime-delivery.ts +1 -1
  128. package/src/runtime-packs.ts +212 -0
  129. package/src/swift-compile.ts +48 -10
  130. package/src/swift-host.ts +22 -3
  131. package/src/swift-objc-compile.ts +1 -1
  132. package/src/swift-objc-import.ts +32 -2
  133. package/src/swift-objc-standin.ts +1 -1
  134. package/src/swift-packages.ts +53 -28
  135. package/src/swift-pdf-raster.ts +60 -4
  136. package/src/swift-shipped-archives.json +44 -0
  137. package/src/swift-shipped-binaries.ts +12 -0
  138. package/src/swift-standin-config.ts +4 -2
  139. package/src/swift-standin-emit.ts +9 -3
  140. package/src/swift-standins.ts +75 -8
  141. package/src/vite-plugin-one.ts +4 -1
@@ -432,7 +432,7 @@ function* xcodeObjCInputSteps(
432
432
  if (
433
433
  !binary.reached ||
434
434
  binary.publicHeaders === undefined ||
435
- binary.assemblySources !== undefined
435
+ binary.unloweredSources !== undefined
436
436
  )
437
437
  continue
438
438
  const manifest = swiftPackageManifest(binary.dir)
@@ -24,12 +24,42 @@ export function swiftClangImporterFlags(flags: readonly string[]): string[] {
24
24
  )
25
25
  }
26
26
 
27
+ // swift names a header's submodule as `import Module.Header`, which xcode
28
+ // infers for every header of a framework. a header an app source imports that
29
+ // way becomes its own submodule, visible with the module; the rest stay in it.
30
+ const SWIFT_SUBMODULE_IMPORT =
31
+ /^[ \t]*(?:@\w+(?:\([^)]*\))?[ \t]+)*import[ \t]+([A-Za-z_]\w*)\.([A-Za-z_]\w*)[ \t]*(?:\/\/.*)?$/gm
32
+
33
+ export function swiftSubmoduleImports(
34
+ sources: Iterable<string>,
35
+ ): Map<string, Set<string>> {
36
+ const imports = new Map<string, Set<string>>()
37
+ for (const source of sources)
38
+ for (const [, module, submodule] of source.matchAll(SWIFT_SUBMODULE_IMPORT)) {
39
+ const names = imports.get(module!) ?? new Set<string>()
40
+ names.add(submodule!)
41
+ imports.set(module!, names)
42
+ }
43
+ return imports
44
+ }
45
+
27
46
  // swiftpm synthesizes a module map for public headers when the package provides
28
47
  // none. original xcode and package module maps retain their own contents.
29
- export function swiftObjCModuleMap(module: string, headers: readonly string[]): string {
48
+ export function swiftObjCModuleMap(
49
+ module: string,
50
+ headers: readonly string[],
51
+ submodules: ReadonlySet<string> = new Set(),
52
+ ): string {
53
+ const header = (file: string) => `header ${JSON.stringify(file)}`
54
+ const stem = (file: string) =>
55
+ file.slice(file.lastIndexOf('/') + 1).replace(/\.[^.]*$/, '')
30
56
  return [
31
57
  `module ${module} {`,
32
- ...headers.map((header) => ` header ${JSON.stringify(header)}`),
58
+ ...headers.map((file) =>
59
+ submodules.has(stem(file))
60
+ ? ` module ${stem(file)} { ${header(file)} export * }`
61
+ : ` ${header(file)}`,
62
+ ),
33
63
  ' export *',
34
64
  '}',
35
65
  '',
@@ -348,7 +348,7 @@ export function iosDeploymentMinimum(version: string | null): number | undefined
348
348
  const headerFiles = (dir: string): string[] =>
349
349
  fs
350
350
  .readdirSync(dir, { recursive: true, encoding: 'utf8' })
351
- .filter((file) => file.endsWith('.h'))
351
+ .filter((file) => file.endsWith('.h') || file.endsWith('.hh'))
352
352
  .sort()
353
353
 
354
354
  /**
@@ -19,6 +19,7 @@ import { cacheDir } from './home-paths'
19
19
  import { requireNativeGit } from './native-git'
20
20
  import { tryAcquireNumberedLock } from './numbered-lock'
21
21
  import { preparedSwiftCheckouts, preparedSwiftPin } from './prepared-xcode-phases'
22
+ import { swiftCTakesReturnAddress } from './swift-compile'
22
23
  import {
23
24
  isSwiftNativeTranslationUnit,
24
25
  swiftImplicitResourcePaths,
@@ -36,6 +37,7 @@ import {
36
37
  type SwiftManifestTarget,
37
38
  type SwiftPackageManifest,
38
39
  } from './swift-package-manifest'
40
+ import { shippedBinaryDiffers } from './swift-shipped-binaries'
39
41
  import type { SwiftSourceLinkGraph } from './swiftContract'
40
42
 
41
43
  // which machine a package target is built for
@@ -114,9 +116,9 @@ export interface SwiftPackageBinary {
114
116
  reached: boolean
115
117
  /** a source Objective-C target: public headers relative to dir. */
116
118
  publicHeaders?: string
117
- /** assembly sources, relative to the package, that keep a source target from
118
- * compiling; its public headers stand in for it. */
119
- assemblySources?: string[]
119
+ /** sources, relative to the package, with no wasm32 lowering that keep a
120
+ * source target from compiling; its public headers stand in for it. */
121
+ unloweredSources?: string[]
120
122
  /** dependency module public headers, relative to dir. */
121
123
  headerDependencies?: { module: string; path: string }[]
122
124
  /** xcode modules whose linked package products reach this clang target. */
@@ -159,29 +161,42 @@ export function remoteSwiftCheckouts(root: string): string {
159
161
  // assembly requires its own target lowering; objective-c keeps its original bodies.
160
162
  const UNSUPPORTED_NATIVE = /\.(s|S)$/
161
163
 
162
- // a clang source target whose sources include assembly cannot lower to wasm,
163
- // unless upstream declares wasi-conditioned c settings for it: that is the
164
- // package's own supported portable path (boringssl's guarded assembly with
165
- // OPENSSL_NO_ASM), which compiles with those flags exactly as swiftpm builds
166
- // it. without that signal the target keeps the refusal below. when a refused
167
- // target also ships public headers, those headers stand in for it and every
168
- // declaration they spell traps by name. this is the assembly rule above,
169
- // widened only where the target has a header surface to stand in from.
170
- function assemblySources(
164
+ // a clang source target whose sources include assembly, or take their own
165
+ // return address, cannot lower to wasm, unless upstream declares
166
+ // wasi-conditioned c settings for it: that is the package's own supported
167
+ // portable path (boringssl's guarded assembly with OPENSSL_NO_ASM), which
168
+ // compiles with those flags exactly as swiftpm builds it. without that signal
169
+ // the target keeps the refusal below. when a refused target also ships public
170
+ // headers, those headers stand in for it and every declaration they spell
171
+ // traps by name. this is the assembly rule above, widened only where the
172
+ // target has a header surface to stand in from.
173
+ function unlowerableSources(
174
+ files: readonly string[],
175
+ target: SwiftManifestTarget,
176
+ ): string[] {
177
+ if (target.declaresWasiNativeSettings) return []
178
+ return [
179
+ ...files.filter((file) => UNSUPPORTED_NATIVE.test(file)),
180
+ ...files
181
+ .filter(isSwiftNativeTranslationUnit)
182
+ .filter((file) => swiftCTakesReturnAddress(fs.readFileSync(file, 'utf8'))),
183
+ ]
184
+ }
185
+
186
+ function unloweredSources(
171
187
  files: readonly string[],
172
188
  target: SwiftManifestTarget,
173
189
  ): string[] | null {
174
190
  if (target.type !== 'regular') return null
175
- if (target.declaresWasiNativeSettings) return null
176
- const assembly = files.filter((file) => UNSUPPORTED_NATIVE.test(file))
177
- if (assembly.length === 0) return null
178
191
  if (!files.some(isSwiftNativeTranslationUnit)) return null
192
+ const unlowered = unlowerableSources(files, target)
193
+ if (unlowered.length === 0) return null
179
194
  const headers = path.resolve(target.dir, target.publicHeadersPath)
180
195
  if (
181
196
  !files.some((file) => file.startsWith(`${headers}${path.sep}`) && file.endsWith('.h'))
182
197
  )
183
198
  return null
184
- return assembly
199
+ return unlowered
185
200
  }
186
201
 
187
202
  const BINARY = 'is a binary framework'
@@ -514,6 +529,8 @@ export function resolveSwiftPackages(options: {
514
529
  /** local package directories the workspace or a project references. */
515
530
  localDirs: readonly string[]
516
531
  provided: ReadonlySet<string> | null
532
+ /** binary targets whose stand-in is built; one pinning another archive than peach's shipped module compiles through it. */
533
+ standinTargets?: ReadonlySet<string>
517
534
  /** why a binary target has no stand-in, added to its reason. */
518
535
  binaryGaps?: ReadonlyMap<string, string>
519
536
  /**
@@ -657,9 +674,7 @@ export function resolveSwiftPackages(options: {
657
674
  ? swiftTargetFiles(pkg.manifest, target)
658
675
  : []
659
676
  const gap = options.binaryGaps?.get(name)
660
- const assembly = target.declaresWasiNativeSettings
661
- ? []
662
- : files.filter((file) => UNSUPPORTED_NATIVE.test(file))
677
+ const unlowerable = unlowerableSources(files, target)
663
678
  const placeholder = placeholderPackage(pkg)
664
679
  const ownReason =
665
680
  target.type === 'binary'
@@ -668,8 +683,8 @@ export function resolveSwiftPackages(options: {
668
683
  ? `${name} stands in as a placeholder (${placeholder}), and ${gap}`
669
684
  : target.type !== 'regular' && target.type !== 'system'
670
685
  ? `${name} is a ${target.type} target`
671
- : assembly.length > 0
672
- ? `${name} is an assembly target with no wasm32 lowering: ${assembly.map((file) => path.relative(pkg.manifest.dir, file)).join(', ')}${gap ? `; ${gap}` : ''}`
686
+ : unlowerable.length > 0
687
+ ? `${name} has native sources with no wasm32 lowering: ${unlowerable.map((file) => path.relative(pkg.manifest.dir, file)).join(', ')}${gap ? `; ${gap}` : ''}`
673
688
  : null
674
689
  // every dependency resolves, so a failing one never hides the rest
675
690
  // of the closure from the compile or from the report
@@ -778,9 +793,8 @@ export function resolveSwiftPackages(options: {
778
793
  )
779
794
  )
780
795
  return false
781
- // an assembly target stands in from its public headers, so a stand-in
782
- // peach built for it stays provided instead of compiling its sources
783
- if (providedTargets.has(name) && assemblySources(files, target)) return false
796
+ // a target whose headers stand in for its unlowered sources stays with the stand-in
797
+ if (unloweredSources(files, target)) return false
784
798
  claimed.add(key)
785
799
  providedTargets.delete(name)
786
800
  for (const dependency of target.dependencies) {
@@ -794,6 +808,17 @@ export function resolveSwiftPackages(options: {
794
808
  }
795
809
  const claimProduct = (pkg: LoadedPackage, product: string): void => {
796
810
  const roots = pkg.manifest.products.get(product)?.targets ?? []
811
+ for (const root of roots) {
812
+ const target = pkg.manifest.targets.get(root)
813
+ if (
814
+ target?.type === 'binary' &&
815
+ !options.standinTargets?.has(root) &&
816
+ shippedBinaryDiffers(root, target.checksum)
817
+ ) {
818
+ providedTargets.delete(root)
819
+ providedProducts.delete(product)
820
+ }
821
+ }
797
822
  if (roots.map((name) => claimTarget(pkg, name)).some(Boolean))
798
823
  providedProducts.delete(product)
799
824
  }
@@ -840,7 +865,7 @@ export function resolveSwiftPackages(options: {
840
865
  : []
841
866
  const objc =
842
867
  target.type === 'regular' && files.some((file) => /\.(m|mm)$/.test(file))
843
- const assembly = assemblySources(files, target)
868
+ const unlowered = unloweredSources(files, target)
844
869
  const gap = placeholderPackage(pkg)
845
870
  const sources = files.filter((file) => file.endsWith('.swift'))
846
871
  // swiftpm's release settings, as xcode builds a package for any
@@ -873,7 +898,7 @@ export function resolveSwiftPackages(options: {
873
898
  ],
874
899
  },
875
900
  })
876
- else if (target.type === 'binary' || objc || assembly)
901
+ else if (target.type === 'binary' || objc || unlowered)
877
902
  result.binaries.push({
878
903
  target: name,
879
904
  source: pkg.source,
@@ -889,9 +914,9 @@ export function resolveSwiftPackages(options: {
889
914
  path.join(target.dir, target.publicHeadersPath),
890
915
  ),
891
916
  }),
892
- ...(assembly
917
+ ...(unlowered
893
918
  ? {
894
- assemblySources: assembly.map((file) =>
919
+ unloweredSources: unlowered.map((file) =>
895
920
  path.relative(pkg.manifest.dir, file),
896
921
  ),
897
922
  }
@@ -46,9 +46,9 @@ CGImageDestinationAddImage(dest, image, nil)
46
46
  guard CGImageDestinationFinalize(dest) else { exit(7) }
47
47
  `
48
48
 
49
- function rasterBinary(): string {
50
- const tag = createHash('sha256').update(RASTER_SWIFT).digest('hex').slice(0, 16)
51
- const binary = path.join(cacheDir(), `swift-pdf-raster-${tag}`)
49
+ function rasterBinary(swift = RASTER_SWIFT, name = 'swift-pdf-raster'): string {
50
+ const tag = createHash('sha256').update(swift).digest('hex').slice(0, 16)
51
+ const binary = path.join(cacheDir(), `${name}-${tag}`)
52
52
  try {
53
53
  fs.accessSync(binary, fs.constants.X_OK)
54
54
  return binary
@@ -61,7 +61,7 @@ function rasterBinary(): string {
61
61
  fs.mkdtempSync(path.join(os.tmpdir(), 'swift-pdf-raster-')),
62
62
  'raster.swift',
63
63
  )
64
- fs.writeFileSync(source, RASTER_SWIFT)
64
+ fs.writeFileSync(source, swift)
65
65
  try {
66
66
  // runner-toolchain-platform: darwin
67
67
  execFileSync('xcrun', ['swiftc', '-o', binary, source], { stdio: 'pipe' })
@@ -135,3 +135,59 @@ export function rasterizePdfFile(diskPath: string, pdfSha256: string): { bytes:
135
135
  fs.rmSync(path.dirname(out), { recursive: true, force: true })
136
136
  }
137
137
  }
138
+
139
+ // actool compiles an svg imageset to a vector rendition. the engine decodes
140
+ // rasters only, so an svg imageset travels as its 3x png like a pdf one.
141
+ // AppKit draws svg on macOS; other hosts have no svg renderer here and keep
142
+ // serving the file as it is.
143
+ const RASTER_SVG_SWIFT = `import AppKit
144
+ guard CommandLine.arguments.count == 4 else { exit(1) }
145
+ let input = URL(fileURLWithPath: CommandLine.arguments[1])
146
+ let scale = CGFloat(Double(CommandLine.arguments[2]) ?? 3.0)
147
+ let output = URL(fileURLWithPath: CommandLine.arguments[3])
148
+ guard let image = NSImage(contentsOf: input), image.size.width > 0, image.size.height > 0 else { exit(2) }
149
+ let width = Int(ceil(image.size.width * scale))
150
+ let height = Int(ceil(image.size.height * scale))
151
+ if width > 12000 || height > 12000 { exit(3) }
152
+ guard let rep = NSBitmapImageRep(bitmapDataPlanes: nil, pixelsWide: width, pixelsHigh: height, bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false, colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0) else { exit(4) }
153
+ guard let context = NSGraphicsContext(bitmapImageRep: rep) else { exit(5) }
154
+ NSGraphicsContext.saveGraphicsState()
155
+ NSGraphicsContext.current = context
156
+ context.imageInterpolation = .high
157
+ image.draw(in: NSRect(x: 0, y: 0, width: width, height: height), from: .zero, operation: .copy, fraction: 1)
158
+ NSGraphicsContext.restoreGraphicsState()
159
+ guard let data = rep.representation(using: .png, properties: [:]) else { exit(6) }
160
+ do { try data.write(to: output) } catch { exit(7) }
161
+ `
162
+
163
+ /**
164
+ * the svg file as 3x png bytes, cached by the svg's sha256, or null off macOS.
165
+ * throws when the svg cannot rasterize, like actool failing the build.
166
+ */
167
+ export function rasterizeSvgFile(
168
+ diskPath: string,
169
+ svgSha256: string,
170
+ ): { bytes: Buffer } | null {
171
+ if (process.platform !== 'darwin') return null
172
+ const binary = rasterBinary(RASTER_SVG_SWIFT, 'swift-svg-raster')
173
+ const tag = createHash('sha256').update(RASTER_SVG_SWIFT).digest('hex').slice(0, 16)
174
+ const cached = path.join(cacheDir(), `swift-svg-png-${tag}-${svgSha256}.png`)
175
+ if (fs.existsSync(cached)) return { bytes: fs.readFileSync(cached) }
176
+ const out = path.join(
177
+ fs.mkdtempSync(path.join(os.tmpdir(), 'swift-svg-png-')),
178
+ 'out.png',
179
+ )
180
+ try {
181
+ execFileSync(binary, [diskPath, '3', out], { stdio: 'pipe' })
182
+ const bytes = fs.readFileSync(out)
183
+ fs.mkdirSync(cacheDir(), { recursive: true })
184
+ fs.copyFileSync(out, cached)
185
+ return { bytes: Buffer.from(bytes) }
186
+ } catch (error) {
187
+ throw new Error(
188
+ `swift svg asset ${diskPath} did not rasterize: ${error instanceof Error ? error.message : String(error)}`,
189
+ )
190
+ } finally {
191
+ fs.rmSync(path.dirname(out), { recursive: true, force: true })
192
+ }
193
+ }
@@ -0,0 +1,44 @@
1
+ {
2
+ "AppCheckCore": "a18d4e5aff27ff4b9bce8d6e73e55ccf1d11515311e219aa4473319cdff3187b",
3
+ "AppLovinSDK": "c00f052c4b15766a6a2734e2b3685234e6bd28dbc47fbe7cbc3edbf56f701d5c",
4
+ "AppsFlyerLib": "13bae495e63e22579dd9525a1c9e88d8eedc78b4586979b7e2d492cfd3efbe1f",
5
+ "FBAEMKit": "ceaf685683c6a23ae4893150d0d770aeeaec34811ac8c146b3aa351beade5fa0",
6
+ "FBAudienceNetwork": "4d84bf1e404a83852a93af2ae73e22e45bb2b11e0a9a445c3b461173a5d6aec3",
7
+ "FBLPromises": "3544fb457e7f60c69740cdd26617a75bdd613943e948becca643022c7edd76c0",
8
+ "FBSDKCoreKit": "1577edd62ec0c172928befed3b309dc59ae8915d2aaad091460d9d1be5ddc13d",
9
+ "FBSDKCoreKit_Basics": "c780833f204f9ec6eab70a3758a45c5c78bfb6f4e590289ccf395497f204cac1",
10
+ "FirebaseAnalytics": "e3253a494375c5174d20cb81925e20afa1ff6b1419125cb608d39b092b53ff2a",
11
+ "FirebaseAppCheck": "af82d72727d55d14f65eee96845d4d9495e4e603b4673709d6f3448b9595cc63",
12
+ "FirebaseAppCheckInterop": "7ffd54e6fe187bf8cd714e3d863e0095f7cbbb0fb802adb87a40c552de7cffcc",
13
+ "FirebaseAuth": "fcde09db8d45ffba67802e81c17b8046db6b56568226ace3fca898983b08c968",
14
+ "FirebaseAuthInterop": "e8e6f4fb42b3fa76c2bade7a522ab0f224558d27d2321175c791d307541787a8",
15
+ "FirebaseCore": "30e3505c715e17682c1dc20bb26ba475e99e6981a9a0dba3cf9352eea632fc1d",
16
+ "FirebaseCoreExtension": "e37ce2abcd4c218ab5426da78cbe7ab41f79ee7eba1d02dd4b0cde952ed2c4a0",
17
+ "FirebaseCoreInternal": "72a15c0c63585faf93e9ffa91e8a8c1c50b24749405804ffae19a29ec05b07ab",
18
+ "FirebaseCrashlytics": "e03c71913efd97678b895abb1e968c83e58b3fbd7955a81ec6e6581b95db16e3",
19
+ "FirebaseFirestore": "f7a1bb7fc4a2fb09298b514114d6aaca9a4f00fd8868667524a05bc4563bf1fd",
20
+ "FirebaseFirestoreInternal": "d9595a1784beaf5cd4a8e0dda0f4364ddfa6b536ad60f82746d81d14dce037a3",
21
+ "FirebaseInstallations": "141e313325bab001f2dbb79dc8a433f884f4c4a12a5feb665e6958098d637f7b",
22
+ "FirebaseRemoteConfig": "e0ae6d626a423d535bc67216f9f0cd66f98f1c0fb4b5bf88074d4496733e2db1",
23
+ "FirebaseRemoteConfigInterop": "794f599eb4232058715b606fa671639c8cc5d821655a0f739651d17c5ef65c37",
24
+ "FirebaseSessions": "1781d72e47dac0fc7a532412641021730bd5b659135633cd9ef7b97ccd31b0ce",
25
+ "FirebaseSharedSwift": "8d63b09a517733ef3a58390bf1e8cf054f058bdd618bb4f19a1f4b5a0b4f09e5",
26
+ "FirebaseStorage": "636b33180dd5ad60b4878357691fe6472cf3bd57ec691e9d661c5444f523df66",
27
+ "GTMSessionFetcher": "f58dc2bd9db39defd73f0f67e7a11893a0c6e6f0ba45cd83cf420b2b3c15f1bd",
28
+ "GoogleAdsOnDeviceConversion": "31a5a1f5204f4844a480d3889b6ebe2e69473ef32b868935c51812c0483cb08b",
29
+ "GoogleAppMeasurement": "5741e6334392e0345f1b5896111ffef4d5a78859970f5e197fa0b7d881165305",
30
+ "GoogleAppMeasurementIdentitySupport": "b70cb033eeb002ed1c5a8140953ccb3be0221ca754c05fe450ed9c9c6547f274",
31
+ "GoogleDataTransport": "7d08050419e0906f13039cc4d2dd69be075234c0bf5bbb34df9dd4891e48831d",
32
+ "GoogleMobileAds": "f2c09c60ee331ce029f563304ad73a481d57ace0d4bc11ce33a2bf59497c59bf",
33
+ "GoogleUtilities": "37a9d3d3810dad763a8a79bd4c7cc4c37b386240725aca07f45dba1826676c8c",
34
+ "Intercom": "fc8251f24b305b91f83304d4dffaf1a90c424a7bc37be8b595dd1fc5cff566ea",
35
+ "Promises": "6d8f1a4b3d561d67adfc2026834779b05685d1cdacea6e83c70d0641c39f24de",
36
+ "RecaptchaInterop": "cf5cc62ebc237b34d5267c1190d18f33b424dbc7f81713f127108d0ad8a592cf",
37
+ "RiveRuntime": "72b6ff5c5a1d153c9cdbea9a917c09be557cfcb1fafa02853fa06b0268551710",
38
+ "absl": "fff0388cf074c69a2da4bc197a005da0b8e5c23ebdcfa383600c540a342f9df1",
39
+ "grpc": "918737c9f8f93e14127b3894e31c7a0522475f2247b74f87d8166dff3a6bafb0",
40
+ "grpcpp": "b83f85e0256cf06df00cf0ed728b5c0d68373ca401742877935771447450b90a",
41
+ "leveldb": "5521a6e6e4cd01b2e31b099d4341f1bccae7e8ba43de648b028928573daf8bb4",
42
+ "nanopb": "a7fafe2e4e16d99de4c58f72e22dcc53221885aa6d678d1270123e4b01badfa3",
43
+ "openssl_grpc": "b2aaede82457cdd15915762a4f57b38e28ba0f47b9b48556a7e0c46881973096"
44
+ }
@@ -0,0 +1,12 @@
1
+ import archives from './swift-shipped-archives.json' with { type: 'json' }
2
+
3
+ // the archive checksum of each vendor binary whose surface peach ships as a module
4
+ // (scripts/debug/swift-binary-standin-generate.ts writes the table). a package pinning a
5
+ // different archive gets its own stand-in, since the shipped module declares another version's API.
6
+ const SHIPPED_ARCHIVES = new Map<string, string>(Object.entries(archives))
7
+
8
+ /** true when `target` is a binary peach ships and the app's pinned archive is another one. */
9
+ export function shippedBinaryDiffers(target: string, checksum: string | null): boolean {
10
+ const shipped = SHIPPED_ARCHIVES.get(target)
11
+ return shipped !== undefined && checksum !== null && checksum !== shipped
12
+ }
@@ -48,8 +48,10 @@ export function isSwiftStandinBehavior(value: unknown): value is StandinBehavior
48
48
  const fields = ['members', 'body', 'asyncBody', 'resultBody', 'set', 'stored']
49
49
  return (
50
50
  isRecord(value) &&
51
- Object.entries(value).every(
52
- ([key, entry]) => fields.includes(key) && typeof entry === 'string',
51
+ Object.entries(value).every(([key, entry]) =>
52
+ key === 'builtin'
53
+ ? entry === true
54
+ : fields.includes(key) && typeof entry === 'string',
53
55
  )
54
56
  )
55
57
  }
@@ -178,6 +178,8 @@ export type StandinOptions = {
178
178
  plain?: ReadonlySet<string>
179
179
  /** paths whose type the guest cannot represent in objective-c: emitted without @objc */
180
180
  unobjc?: ReadonlySet<string>
181
+ /** classes whose superclass declares init(coder:) non-failable: the compiler rejected the failable one */
182
+ coderNonfailable?: ReadonlySet<string>
181
183
  /** class path → objective-c protocols the compiler found its witnesses mismatch (nullability a swift protocol checks); the class drops the conformance */
182
184
  unconformed?: ReadonlyMap<string, ReadonlySet<string>>
183
185
  /** paths the compiler says must be marked override */
@@ -1644,7 +1646,7 @@ export function emitSwiftStandin(
1644
1646
  externalRoot(id) !== null
1645
1647
  )
1646
1648
  emit(
1647
- `${inner}public required init?(coder: NSCoder) { ${options.inert ? 'return nil' : trap(`${path}.init(coder:)`)} }`,
1649
+ `${inner}public required init${options.coderNonfailable?.has(path) ? '' : '?'}(coder: NSCoder) { ${options.inert && !options.coderNonfailable?.has(path) ? 'return nil' : trap(`${path}.init(coder:)`)} }`,
1648
1650
  )
1649
1651
  // a designated init drops the inherited required init(), so a
1650
1652
  // subclass restates it
@@ -1890,6 +1892,8 @@ export function emitSwiftStandin(
1890
1892
  .replace(/^(?:weak |unowned )/, '')
1891
1893
  .replace(/^((?:static )?)let /, '$1var ')
1892
1894
  const witness = `${owner}.${leaf(member)}`
1895
+ // a superclass the graph cannot see already declares what the compiler says must override
1896
+ if (options.forcedOverride?.has(witness)) return
1893
1897
  const body = options.inert ? inertBody(member) : trap(witness)
1894
1898
  if (
1895
1899
  member.kind.identifier === 'swift.property' ||
@@ -1899,11 +1903,13 @@ export function emitSwiftStandin(
1899
1903
  const setter = parsed.settable
1900
1904
  ? ` ${parsed.nonmutating ? 'nonmutating ' : ''}set { ${body} }`
1901
1905
  : ''
1902
- emit(
1906
+ emitAt(
1907
+ witness,
1903
1908
  `${indent}${visibility} ${parsed.decl} { get${parsed.effects} { ${body} }${setter} }`,
1904
1909
  )
1905
1910
  } else
1906
- emit(
1911
+ emitAt(
1912
+ witness,
1907
1913
  `${indent}${member.kind.identifier === 'swift.init' ? 'public required ' : visibility + ' '}${stripDefaults(decl)} { ${body} }`,
1908
1914
  )
1909
1915
  }
@@ -1240,7 +1240,7 @@ function interfaceEnumValues(
1240
1240
  const declarations = [
1241
1241
  ...interfaceText.matchAll(
1242
1242
  new RegExp(
1243
- `^([ \\t]*)(?:@[\\w.]+(?:\\([^)]*\\))?\\s+)*(?:nonisolated\\s+)?(?:public|open)\\s+enum\\s+${name}\\s*:\\s*(?:Swift\\.)?U?Int(?:8|16|32|64)?\\b[^{]*\\{[ \\t]*$`,
1243
+ `^([ \\t]*)(?:@[\\w.]+(?:\\([^)]*\\))?\\s+)*(?:nonisolated\\s+)?(?:public|open)\\s+enum\\s+${name}\\s*:\\s*(?:Swift\\.)?(?:U?Int(?:8|16|32|64)?|IntegerLiteralType)\\b[^{]*\\{[ \\t]*$`,
1244
1244
  'gm',
1245
1245
  ),
1246
1246
  ),
@@ -1364,9 +1364,34 @@ function mixedStandin(
1364
1364
  null,
1365
1365
  view.inheritedConformances,
1366
1366
  interfaceProjections(view.graphs, interfaceText),
1367
+ [],
1368
+ externalConformances(surface.module, interfaceText),
1367
1369
  )
1368
1370
  }
1369
1371
 
1372
+ // an outside type's conformance to the module's own protocol (`extension Swift.String : Module.P {}`):
1373
+ // the symbol graph keeps an extension's members and drops the conformance it declares, so the
1374
+ // interface is the only record. a constrained extension stays out. a type of another module is
1375
+ // spelled by its own name, as the emitted members are.
1376
+ function externalConformances(module: string, interfaceText: string): string {
1377
+ const lines = new Set<string>()
1378
+ for (const match of interfaceText.matchAll(
1379
+ /^(?:@\w+\s+)*extension\s+([\w.]+)\s*:\s*([^{\n]+?)\s*\{/gm,
1380
+ )) {
1381
+ const [, extended, conformances] = match
1382
+ if (extended!.startsWith(`${module}.`) || /\bwhere\b/.test(conformances!)) continue
1383
+ const own = conformances!
1384
+ .split(',')
1385
+ .map((name) => name.trim())
1386
+ .filter((name) => name.startsWith(`${module}.`))
1387
+ const type = extended!.startsWith('Swift.')
1388
+ ? extended!
1389
+ : extended!.split('.').slice(1).join('.')
1390
+ if (own.length > 0 && type) lines.add(`extension ${type} : ${own.join(', ')} {}\n`)
1391
+ }
1392
+ return lines.size > 0 ? `\n${[...lines].join('')}` : ''
1393
+ }
1394
+
1370
1395
  // the sdk toolset passes this to every swiftc compile; raw swiftc does not read the toolset,
1371
1396
  // and emitting a module aborts without it when the source reaches the wasm exception model.
1372
1397
  // swift-symbolgraph-extract has no -Xllvm.
@@ -1506,6 +1531,8 @@ function graphStandin(
1506
1531
  inheritedConformances: ReadonlyMap<string, ReadonlySet<string>> = new Map(),
1507
1532
  projections: ReadonlyMap<string, string> = new Map(),
1508
1533
  dependencyGraphs: SymbolGraph[] = [],
1534
+ // declarations the symbol graphs cannot carry, appended after the emitted ones
1535
+ trailer = '',
1509
1536
  ): SwiftStandin {
1510
1537
  const paths = new Set(
1511
1538
  graphs.flatMap((graph) =>
@@ -1556,6 +1583,8 @@ function graphStandin(
1556
1583
  const plain = new Set<string>()
1557
1584
  const unobjc = new Set<string>()
1558
1585
  const trapped = new Set<string>()
1586
+ const forced = new Set<string>()
1587
+ const nonfailable = new Set<string>()
1559
1588
  const unconformed = new Map<string, Set<string>>()
1560
1589
  const objcProtocols = new Set(
1561
1590
  graphs.flatMap((graph) =>
@@ -1575,7 +1604,7 @@ function graphStandin(
1575
1604
  // like a binary framework's.
1576
1605
  const inert =
1577
1606
  binary.placeholder !== undefined ||
1578
- (binary.publicHeaders !== undefined && binary.assemblySources === undefined)
1607
+ (binary.publicHeaders !== undefined && binary.unloweredSources === undefined)
1579
1608
  for (;;) {
1580
1609
  const { source, owners, skipped } = emitSwiftStandin(graphs, {
1581
1610
  module,
@@ -1588,6 +1617,8 @@ function graphStandin(
1588
1617
  unobjc,
1589
1618
  unconformed,
1590
1619
  trapped,
1620
+ forcedOverride: forced,
1621
+ coderNonfailable: nonfailable,
1591
1622
  inert,
1592
1623
  imports: [...(placeholder?.peachImports ?? []), ...imports],
1593
1624
  family: [...imports, ...(placeholder?.peachImports ?? [])],
@@ -1609,7 +1640,7 @@ function graphStandin(
1609
1640
  `Configured Swift behavior ${module}.${entry.path} was not emitted: ${entry.reason}`,
1610
1641
  )
1611
1642
  }
1612
- fs.writeFileSync(file, source)
1643
+ fs.writeFileSync(file, source + trailer)
1613
1644
  const check = spawnSync(
1614
1645
  path.join(toolchain.toolchainBin, 'swiftc'),
1615
1646
  // emitting the module runs the diagnostics a typecheck skips, such as
@@ -1633,10 +1664,17 @@ function graphStandin(
1633
1664
  return {
1634
1665
  module,
1635
1666
  target: binary.target,
1636
- files: { [`${module}.swift`]: source },
1667
+ files: { [`${module}.swift`]: source + trailer },
1637
1668
  ...(imports.length ? { dependencies: imports } : {}),
1638
1669
  }
1639
- const before = omit.size + plain.size + unobjc.size + trapped.size + unconformed.size
1670
+ const before =
1671
+ omit.size +
1672
+ plain.size +
1673
+ unobjc.size +
1674
+ trapped.size +
1675
+ unconformed.size +
1676
+ forced.size +
1677
+ nonfailable.size
1640
1678
  const elsewhere: string[] = []
1641
1679
  for (const match of check.stderr.matchAll(/^(\S+?):(\d+):\d+: error: (.*)$/gm)) {
1642
1680
  const owner = match[1] === file ? owners[Number(match[2]) - 1] : undefined
@@ -1663,15 +1701,44 @@ function graphStandin(
1663
1701
  throw new Error(
1664
1702
  `Configured Swift behavior ${module}.${owner} does not typecheck: ${match[3]}`,
1665
1703
  )
1666
- if (owner && /does not override any|overrides nothing/.test(match[3]!))
1704
+ if (
1705
+ owner &&
1706
+ /does not override any|overrides nothing|does not override a designated initializer/.test(
1707
+ match[3]!,
1708
+ )
1709
+ )
1667
1710
  plain.add(owner)
1711
+ else if (
1712
+ owner &&
1713
+ /failable initializer 'init\(coder:\)' cannot override a non-failable/.test(
1714
+ match[3]!,
1715
+ ) &&
1716
+ !nonfailable.has(owner)
1717
+ )
1718
+ nonfailable.add(owner)
1719
+ // the guest's superclass declares the member the vendor's graph names only as new
1720
+ else if (
1721
+ owner &&
1722
+ /requires an 'override' keyword/.test(match[3]!) &&
1723
+ !forced.has(owner)
1724
+ )
1725
+ forced.add(owner)
1668
1726
  // an inert value the declaration's type cannot build: its body traps
1669
1727
  else if (owner && inert && INERT_VALUE.test(match[3]!) && !trapped.has(owner))
1670
1728
  trapped.add(owner)
1671
1729
  else if (owner) omit.set(owner, `rejected by swiftc: ${match[3]}`)
1672
1730
  else elsewhere.push(match[3]!)
1673
1731
  }
1674
- if (omit.size + plain.size + unobjc.size + trapped.size + unconformed.size === before)
1732
+ if (
1733
+ omit.size +
1734
+ plain.size +
1735
+ unobjc.size +
1736
+ trapped.size +
1737
+ unconformed.size +
1738
+ forced.size +
1739
+ nonfailable.size ===
1740
+ before
1741
+ )
1675
1742
  throw new Error(
1676
1743
  `its generated source does not typecheck: ${elsewhere.slice(0, 3).join('; ') || check.stderr.trim().slice(0, 400)}`,
1677
1744
  )
@@ -2695,7 +2762,7 @@ export function standinGenerationInputs(
2695
2762
  (dependency) =>
2696
2763
  `${swiftTargetModuleName(dependency.module)}\0${treeDigest(path.join(binary.dir, dependency.path))}`,
2697
2764
  ),
2698
- ...(binary.assemblySources ?? []),
2765
+ ...(binary.unloweredSources ?? []),
2699
2766
  ].join('\0')
2700
2767
  : swiftBinaryFramework(binary).digest,
2701
2768
  )
@@ -44,6 +44,7 @@ import {
44
44
  serveRuntimeFile,
45
45
  SOOTSIM_RUNTIME_MISSING_MESSAGE,
46
46
  } from './runtime-assets'
47
+ import { ensureRuntimePackFor } from './runtime-packs'
47
48
  import { SWIFT_HMR_PATH, SWIFT_PACKAGE_PATH } from './swift-submit'
48
49
  import { swiftViteLifetime } from './swift-vite-lifetime'
49
50
  import type { OneWidgetPackage } from './oneWidgetContract'
@@ -595,7 +596,7 @@ export function peachPlugin(options: PeachPluginOptions = {}): Plugin {
595
596
  })
596
597
  })
597
598
 
598
- server.middlewares.use((req, res, next) => {
599
+ server.middlewares.use(async (req, res, next) => {
599
600
  if (serveBrowserProxyRoute(req, res)) return
600
601
  const url = req.url || ''
601
602
  const pathname = url.split('?')[0]
@@ -615,6 +616,8 @@ export function peachPlugin(options: PeachPluginOptions = {}): Plugin {
615
616
  return
616
617
  }
617
618
 
619
+ await ensureRuntimePackFor(runtimeRoot, pathname)
620
+
618
621
  // root-relative runtime assets emitted by the shell and engine vite
619
622
  // builds. only intercept when the asset exists in the active runtime.
620
623
  if (isRootRuntimeAssetPath(pathname)) {