peachsim 0.1.2209 → 0.1.2210

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 (102) 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/attached-projects.cjs +1 -1
  4. package/dist-lib/auth/shared-session.cjs +1 -1
  5. package/dist-lib/backend-origin.cjs +1 -1
  6. package/dist-lib/beta.cjs +1 -1
  7. package/dist-lib/beta.mjs +1 -1
  8. package/dist-lib/bridge-constants.cjs +1 -1
  9. package/dist-lib/bridge-contract-input.cjs +1 -1
  10. package/dist-lib/bridge-contract-input.mjs +1 -1
  11. package/dist-lib/bridge-contract.cjs +1 -1
  12. package/dist-lib/bridge-contract.mjs +1 -1
  13. package/dist-lib/bundle-channel.cjs +271 -51
  14. package/dist-lib/capture-contract.cjs +1 -1
  15. package/dist-lib/capture-contract.mjs +1 -1
  16. package/dist-lib/cloud-contract.cjs +1 -1
  17. package/dist-lib/cloud-contract.mjs +1 -1
  18. package/dist-lib/cloud-test-args.cjs +1 -1
  19. package/dist-lib/cloud-test-args.mjs +1 -1
  20. package/dist-lib/cloud.cjs +1 -1
  21. package/dist-lib/cloud.mjs +1 -1
  22. package/dist-lib/config.cjs +1 -1
  23. package/dist-lib/config.mjs +1 -1
  24. package/dist-lib/detox/index.cjs +1 -1
  25. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  26. package/dist-lib/expo-swift-bundle.cjs +270 -50
  27. package/dist-lib/expo-swift-metadata.cjs +1 -1
  28. package/dist-lib/expo-swift-metadata.mjs +1 -1
  29. package/dist-lib/home-paths.cjs +1 -1
  30. package/dist-lib/host/bridge-host.cjs +271 -51
  31. package/dist-lib/host/fetch-proxy-handler.cjs +16 -3
  32. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  33. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  34. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  35. package/dist-lib/host/websocket-proxy.cjs +1 -1
  36. package/dist-lib/index.cjs +16 -3
  37. package/dist-lib/jump-to-source-babel.cjs +1 -1
  38. package/dist-lib/jump-to-source-native.cjs +1 -1
  39. package/dist-lib/kotlin-host.cjs +1 -1
  40. package/dist-lib/menu.cjs +1 -1
  41. package/dist-lib/menu.mjs +1 -1
  42. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  43. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  44. package/dist-lib/metro-production-bundle.cjs +1 -1
  45. package/dist-lib/metro-production-bundle.mjs +1 -1
  46. package/dist-lib/metro.cjs +16 -3
  47. package/dist-lib/native-app-identity-project.cjs +15 -2
  48. package/dist-lib/native-app-identity-project.mjs +15 -2
  49. package/dist-lib/native-app-identity.cjs +1 -1
  50. package/dist-lib/native-app-identity.mjs +1 -1
  51. package/dist-lib/native-firebase-metadata.cjs +1 -1
  52. package/dist-lib/native-firebase-metadata.mjs +1 -1
  53. package/dist-lib/pdfium-raster.cjs +1 -1
  54. package/dist-lib/pdfium-raster.mjs +1 -1
  55. package/dist-lib/plist.cjs +1 -1
  56. package/dist-lib/plist.mjs +1 -1
  57. package/dist-lib/profiles.cjs +1 -1
  58. package/dist-lib/public-brand.cjs +1 -1
  59. package/dist-lib/public-origins-lib-esm.json +24 -24
  60. package/dist-lib/public-origins-lib.json +63 -53
  61. package/dist-lib/react-native-host-modules.cjs +1 -1
  62. package/dist-lib/react-native-host-modules.mjs +1 -1
  63. package/dist-lib/reap-browser.cjs +1 -1
  64. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  65. package/dist-lib/sdk.cjs +1 -1
  66. package/dist-lib/sdk.mjs +1 -1
  67. package/dist-lib/skills.cjs +271 -51
  68. package/dist-lib/swift-compile.cjs +58 -12
  69. package/dist-lib/swift-compile.mjs +57 -12
  70. package/dist-lib/swift-package.cjs +1 -1
  71. package/dist-lib/swift-package.mjs +1 -1
  72. package/dist-lib/swift-submit.cjs +1 -1
  73. package/dist-lib/swift-submit.mjs +1 -1
  74. package/dist-lib/swift-toolchain.cjs +1 -1
  75. package/dist-lib/swift.cjs +1 -1
  76. package/dist-lib/vite-swift.cjs +253 -46
  77. package/dist-lib/vite.cjs +16 -3
  78. package/dist-lib/worklet-executable.cjs +1 -1
  79. package/dist-lib/worklet-executable.mjs +1 -1
  80. package/package.json +1 -1
  81. package/sdk/ios/System/Library/Frameworks/QuartzCore.framework/Headers/CoreAnimation.h +2 -0
  82. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/UIKit.apinotes +21 -0
  83. package/sdk/ios/usr/lib/swift/Combine.swiftmodule/arm64-apple-ios-simulator.swiftinterface +18 -0
  84. package/sdk/ios/usr/lib/swift/Foundation.swiftmodule/arm64-apple-ios-simulator.swiftinterface +1 -0
  85. package/sdk/ios/usr/lib/swift/SwiftUI.swiftmodule/arm64-apple-ios-simulator.swiftinterface +19 -0
  86. package/sdk/ios/usr/lib/swift/SwiftUICore.swiftmodule/arm64-apple-ios-simulator.swiftinterface +4 -0
  87. package/sdk/ios/usr/lib/swift/UIKit.swiftmodule/arm64-apple-ios-simulator.swiftinterface +4 -0
  88. package/sdk/ios/wasm/include/pthread.h +1 -0
  89. package/sdk/ios/wasm/include/signal.h +2 -2
  90. package/sdk/native-hashes.json +3 -3
  91. package/src/native-static-libraries.ts +7 -0
  92. package/src/swift-compile.ts +48 -10
  93. package/src/swift-host.ts +22 -3
  94. package/src/swift-objc-compile.ts +1 -1
  95. package/src/swift-objc-import.ts +32 -2
  96. package/src/swift-objc-standin.ts +1 -1
  97. package/src/swift-packages.ts +53 -28
  98. package/src/swift-pdf-raster.ts +60 -4
  99. package/src/swift-shipped-archives.json +44 -0
  100. package/src/swift-shipped-binaries.ts +12 -0
  101. package/src/swift-standin-emit.ts +9 -3
  102. package/src/swift-standins.ts +75 -8
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peachsim",
3
- "version": "0.1.2209",
3
+ "version": "0.1.2210",
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",
@@ -21,3 +21,5 @@
21
21
  #import <QuartzCore/CATextLayer.h>
22
22
  #import <QuartzCore/CATiledLayer.h>
23
23
  #import <QuartzCore/CATransformLayer.h>
24
+ #import <QuartzCore/CAEDRMetadata.h>
25
+ #import <QuartzCore/CAMetalLayer.h>
@@ -1080,6 +1080,27 @@ Classes:
1080
1080
  - Selector: 'imageByRemovingVariant'
1081
1081
  MethodKind: Instance
1082
1082
  SwiftName: 'removingVariant()'
1083
+ - Selector: 'initWithCGImage:scale:orientation:'
1084
+ MethodKind: Instance
1085
+ Availability: nonswift
1086
+ AvailabilityMsg: 'UIKitCore declares the Swift initializer with UIImage.Orientation'
1087
+ - Selector: 'initWithCIImage:scale:orientation:'
1088
+ MethodKind: Instance
1089
+ Availability: nonswift
1090
+ AvailabilityMsg: 'UIKitCore declares the Swift initializer with UIImage.Orientation'
1091
+ - Selector: 'imageWithCGImage:scale:orientation:'
1092
+ MethodKind: Class
1093
+ Availability: nonswift
1094
+ AvailabilityMsg: 'UIKitCore declares the Swift initializer with UIImage.Orientation'
1095
+ - Selector: 'imageWithCIImage:scale:orientation:'
1096
+ MethodKind: Class
1097
+ Availability: nonswift
1098
+ AvailabilityMsg: 'UIKitCore declares the Swift initializer with UIImage.Orientation'
1099
+ Properties:
1100
+ - Name: imageOrientation
1101
+ PropertyKind: Instance
1102
+ Availability: nonswift
1103
+ AvailabilityMsg: 'UIKitCore declares imageOrientation with UIImage.Orientation'
1083
1104
  - Name: UIImageConfiguration
1084
1105
  - Name: UIImageSymbolConfiguration
1085
1106
  Methods:
@@ -0,0 +1,18 @@
1
+ // swift-interface-format-version: 1.0
2
+ // swift-module-flags: -target arm64-apple-ios16.0-simulator -enable-objc-interop -enable-library-evolution -module-name Combine
3
+ import Swift
4
+ import _Concurrency
5
+ public protocol Publisher {
6
+ associatedtype Output
7
+ associatedtype Failure : Swift.Error
8
+ }
9
+ final public class ObservableObjectPublisher : Combine.Publisher {
10
+ public typealias Output = Swift.Void
11
+ public typealias Failure = Swift.Never
12
+ public init()
13
+ public func send()
14
+ }
15
+ public protocol ObservableObject : AnyObject {
16
+ associatedtype ObjectWillChangePublisher : Combine.Publisher = Combine.ObservableObjectPublisher where Self.ObjectWillChangePublisher.Failure == Swift.Never
17
+ var objectWillChange: Self.ObjectWillChangePublisher { get }
18
+ }
@@ -3,6 +3,7 @@
3
3
  @_exported import Foundation
4
4
  @_exported import ObjectiveC
5
5
  @_exported import CoreGraphics
6
+ @_exported import Combine
6
7
  import Swift
7
8
  import _Concurrency
8
9
  public struct URL : Swift.Hashable, Swift.Codable, Swift.Sendable, Swift.CustomStringConvertible {
@@ -23,3 +23,22 @@ extension SwiftUI.UIViewControllerRepresentable {
23
23
  extension SwiftUI.UIViewControllerRepresentable where Self.Coordinator == Swift.Void {
24
24
  @_Concurrency.MainActor @preconcurrency public func makeCoordinator() -> Swift.Void
25
25
  }
26
+ @_Concurrency.MainActor @preconcurrency public protocol UIViewRepresentable : SwiftUICore.View where Self.Body == Swift.Never {
27
+ associatedtype UIViewType : UIKit.UIView
28
+ @_Concurrency.MainActor @preconcurrency func makeUIView(context: Self.Context) -> Self.UIViewType
29
+ @_Concurrency.MainActor @preconcurrency func updateUIView(_ uiView: Self.UIViewType, context: Self.Context)
30
+ @_Concurrency.MainActor @preconcurrency static func dismantleUIView(_ uiView: Self.UIViewType, coordinator: Self.Coordinator)
31
+ associatedtype Coordinator = Swift.Void
32
+ @_Concurrency.MainActor @preconcurrency func makeCoordinator() -> Self.Coordinator
33
+ typealias Context = SwiftUI.UIViewRepresentableContext<Self>
34
+ }
35
+ @_Concurrency.MainActor @preconcurrency public struct UIViewRepresentableContext<Representable> where Representable : SwiftUI.UIViewRepresentable {
36
+ @_Concurrency.MainActor @preconcurrency public let coordinator: Representable.Coordinator
37
+ }
38
+ extension SwiftUI.UIViewRepresentable {
39
+ @_Concurrency.MainActor @preconcurrency public var body: Swift.Never { get }
40
+ @_Concurrency.MainActor @preconcurrency public static func dismantleUIView(_ uiView: Self.UIViewType, coordinator: Self.Coordinator)
41
+ }
42
+ extension SwiftUI.UIViewRepresentable where Self.Coordinator == Swift.Void {
43
+ @_Concurrency.MainActor @preconcurrency public func makeCoordinator() -> Swift.Void
44
+ }
@@ -14,3 +14,7 @@ public struct Binding<Value> {}
14
14
  @resultBuilder public struct ViewBuilder {
15
15
  public static func buildBlock<Content>(_ content: Content) -> Content where Content : SwiftUICore.View
16
16
  }
17
+ public struct AnyView : SwiftUICore.View {
18
+ public typealias Body = Swift.Never
19
+ public var body: Swift.Never { get }
20
+ }
@@ -2,6 +2,7 @@
2
2
  // swift-module-flags: -target arm64-apple-ios16.0-simulator -enable-objc-interop -enable-library-evolution -module-name UIKit
3
3
  @_exported import UIKit
4
4
  import Swift
5
+ import _Concurrency
5
6
  extension UIKit.UIApplication {
6
7
  public typealias State = UIKit.UIApplicationState
7
8
  }
@@ -11,6 +12,9 @@ extension UIKit.UIWindow {
11
12
  extension UIKit.UIDevice {
12
13
  public typealias BatteryState = UIKit.UIDeviceBatteryState
13
14
  }
15
+ extension ObjectiveC.NSObject {
16
+ @objc @_Concurrency.MainActor @preconcurrency dynamic open var accessibilityElements: [Any]? { @objc get @objc set }
17
+ }
14
18
  extension UIKit.NSLayoutConstraint {
15
19
  public typealias Relation = UIKit.NSLayoutRelation
16
20
  public typealias Attribute = UIKit.NSLayoutAttribute
@@ -47,6 +47,7 @@ void *pthread_get_stackaddr_np(pthread_t);
47
47
  int pthread_threadid_np(pthread_t, __uint64_t * _Nullable);
48
48
  struct __darwin_pthread_handler_rec **__peach_darwin_cleanup_stack(void);
49
49
  int pthread_cancel(pthread_t) __asm__("__peach_darwin_pthread_cancel");
50
+ void pthread_exit(void * _Nullable) __attribute__((noreturn)) __asm__("__peach_darwin_pthread_exit");
50
51
  int pthread_setcancelstate(int , int * _Nullable) __asm__("__peach_darwin_pthread_setcancelstate");
51
52
  int pthread_setcanceltype(int , int * _Nullable) __asm__("__peach_darwin_pthread_setcanceltype");
52
53
  void pthread_testcancel(void) __asm__("__peach_darwin_pthread_testcancel");
@@ -1,6 +1,6 @@
1
1
  // darwin's signal.h in place of the installed libc's. functions the installed
2
2
  // libc also defines with its own numbering (raise, bsd_signal, psignal) have
3
- // their own symbols. waiting for a signal needs asynchronous delivery, which
3
+ // their own symbols. waiting for a signal that is not already pending needs asynchronous delivery, which
4
4
  // a wasm instance has no source of.
5
5
  #ifndef _USER_SIGNAL_H
6
6
  #define _USER_SIGNAL_H
@@ -43,7 +43,7 @@ int sigprocmask(int, const sigset_t * __restrict, sigset_t * __restrict);
43
43
  int sigrelse(int);
44
44
  void (* _Nullable sigset(int, void (* _Nullable)(int)))(int);
45
45
  int sigsuspend(const sigset_t *) __PEACH_DARWIN_UNAVAILABLE("Darwin asynchronous signals are not implemented for WebAssembly");
46
- int sigwait(const sigset_t * __restrict, int * __restrict) __PEACH_DARWIN_UNAVAILABLE("Darwin asynchronous signals are not implemented for WebAssembly");
46
+ int sigwait(const sigset_t * __restrict, int * __restrict);
47
47
  #if !defined(_POSIX_C_SOURCE) || _POSIX_C_SOURCE >= 200809L || defined(_DARWIN_C_SOURCE)
48
48
  void psignal(int, const char *) __asm__("__peach_darwin_psignal");
49
49
  #endif
@@ -42,7 +42,7 @@
42
42
  {
43
43
  "path": "wasm/include/machine/limits.h",
44
44
  "nativeSha256": "50345f1ab843fca787a38c552a84177e678d79dab86e714434f94f2546839357",
45
- "sha256": "7c944f43a0de8e3b1b19951650fc8ebb98d373094a5d9258cb0e99a9b723f000",
45
+ "sha256": "f970318bcb9a7e991924f78c075ba48cf99292372088e0adc0daf9018164f839",
46
46
  "change": "one __wasm32__ branch before the native #else: arm/limits.h's selection inline, with arm/_limits.h's __DARWIN_CLK_TCK in place of its include and USE_CLANG_LIMITS fixed at 0",
47
47
  "reason": "the native selection errors on any architecture but i386, x86_64, arm and arm64. wasm32 takes arm's values, as machine/_types.h does. A modules build on iOS takes the integer limits from clang's limits.h, which includes Darwin's; the wasm view finds Darwin's ahead of clang's, whose builtin module would bring the installed libc's limits with it, so the branch always defines them."
48
48
  },
@@ -77,8 +77,8 @@
77
77
  {
78
78
  "path": "System/Library/Frameworks/Foundation.framework/Headers/Foundation.apinotes",
79
79
  "nativeSha256": "025956c54d34391f2c422b736710641a860694436f5b8a34d719ade2d9ed3220",
80
- "sha256": "8dc2bc8008ae1d31401458ec776a9c2f356ff6ffdb890bb409bc79b07318b651",
81
- "change": "hide NSArray arrayWithObjects:count: from Swift, nest FileManager sync control and URLSession delayed request and multipath enums, import networking singleton and selector names, and hide native members whose Swift implementation supplies the existing typed declaration",
80
+ "sha256": "f05f7e0edce96ebd5d6c1c5d816b6d5a1c922a2c969ce971748bb10edd3d3ed5",
81
+ "change": "hide NSArray arrayWithObjects:count: from Swift, nest FileManager sync control and URLSession delayed request and multipath enums, import networking singleton and selector names, hide native members whose Swift implementation supplies the existing typed declaration, and leave unnested the enums of classes Foundation declares in Swift, which declare those nested types themselves",
82
82
  "reason": "the Objective-C header owns the networking classes and categories; their Swift implementation must use the native imported names without the obsolete moved-type aliases or duplicate Swift-owned session classes"
83
83
  },
84
84
  {
@@ -192,6 +192,13 @@ export const NATIVE_STATIC_LIBRARY_RECIPES = [
192
192
  recipe: 'a2642115a5eeb04559c9f1daaa4b4cbe4b1c211533b4cc80cb8339a4477af205',
193
193
  archive: 'libsksg.a',
194
194
  },
195
+ {
196
+ name: 'webgpu_dawn',
197
+ nativeSha256: '95078993275bccc969b1dfa1ad0934cbacc05ae59e8aa2a6cc46ce93e97d4f69',
198
+ upstream: '3d786993a7ded64c4ebb4884b9b079db9ad0e580',
199
+ recipe: 'c55468cc976e837ad894133f2231beb7d1ed64633af7b457b8a2610d7df45994',
200
+ archive: 'libwebgpu_dawn.a',
201
+ },
195
202
  ]
196
203
 
197
204
  export function nativeStaticLibraryEntry(
@@ -62,6 +62,7 @@ import {
62
62
  SWIFT_OBJC_INTEROP_FLAGS,
63
63
  swiftClangImporterFlags,
64
64
  swiftObjCModuleMap,
65
+ swiftSubmoduleImports,
65
66
  } from './swift-objc-import'
66
67
  import { swiftObjCRuntimeFlags } from './swift-objc-runtime'
67
68
  import { iosDeploymentMinimum, objcSdkIntakeFlags } from './swift-objc-standin'
@@ -3832,6 +3833,25 @@ function stripCCode(source: string): string {
3832
3833
  return code
3833
3834
  }
3834
3835
 
3836
+ // whether the unit's code under wasm32 takes its own return address, which
3837
+ // the WebAssembly backend rejects ("hasn't implemented __builtin_return_address"):
3838
+ // native machine code the target has no lowering for, like assembly. branches
3839
+ // the native architecture macros guard are not wasm code.
3840
+ const wasmMacroEnvironment: SwiftCMacroEnvironment = {
3841
+ ...emptyMacroEnvironment,
3842
+ defines: new Map([
3843
+ ['__wasm__', '1'],
3844
+ ['__wasm32__', '1'],
3845
+ ['__wasi__', '1'],
3846
+ ]),
3847
+ }
3848
+ export function swiftCTakesReturnAddress(source: string): boolean {
3849
+ if (!source.includes('__builtin_return_address')) return false
3850
+ return /\b__builtin_return_address\s*\(/.test(
3851
+ cActiveCode(stripCCode(source), wasmMacroEnvironment),
3852
+ )
3853
+ }
3854
+
3835
3855
  // every name the given sources define. order and conditions are not
3836
3856
  // evaluated: a name defined anywhere makes its guards undecided.
3837
3857
  export function swiftCDefinedNames(sources: Iterable<string>): Set<string> {
@@ -4360,6 +4380,11 @@ export function writeSwiftProject(
4360
4380
  clangImportedModules.add(name)
4361
4381
  }
4362
4382
  }
4383
+ const submoduleImports = swiftSubmoduleImports(
4384
+ Object.entries(input.files).flatMap(([file, contents]) =>
4385
+ file.endsWith('.swift') ? [contents] : [],
4386
+ ),
4387
+ )
4363
4388
  const headerDirectory = path.join(layout.root, '.build', 'peach-cxx-headers')
4364
4389
  const flattenedHeaders = new Set<string>()
4365
4390
  // product header aliases belong to this input. keep emitted Swift headers,
@@ -4906,6 +4931,7 @@ export function writeSwiftProject(
4906
4931
  swiftObjCModuleMap(
4907
4932
  swiftTargetModuleName(target.name),
4908
4933
  roots.map((file) => path.join(layout.root, file)),
4934
+ submoduleImports.get(swiftTargetModuleName(target.name)),
4909
4935
  ))
4910
4936
  if (moduleContents === undefined)
4911
4937
  throw new Error('missing original module map ' + modulemap)
@@ -5295,13 +5321,17 @@ export function writeSwiftProject(
5295
5321
  modulemap,
5296
5322
  originalMap
5297
5323
  ? `extern module ${moduleName} ${JSON.stringify(path.join(layout.root, originalMap))}\nmodule ${moduleName}.Swift {\n header ${JSON.stringify(path.join(headerDirectory, name + '-Swift.h'))}\n requires objc\n}\n`
5298
- : swiftObjCModuleMap(moduleName, [
5299
- ...(
5300
- input.nativeTargets?.find((target) => target.name === name)
5301
- ?.publicHeaders ?? []
5302
- ).map((header) => path.join(layout.root, header)),
5303
- path.join(headerDirectory, name + '-Swift.h'),
5304
- ]),
5324
+ : swiftObjCModuleMap(
5325
+ moduleName,
5326
+ [
5327
+ ...(
5328
+ input.nativeTargets?.find((target) => target.name === name)
5329
+ ?.publicHeaders ?? []
5330
+ ).map((header) => path.join(layout.root, header)),
5331
+ path.join(headerDirectory, name + '-Swift.h'),
5332
+ ],
5333
+ submoduleImports.get(moduleName),
5334
+ ),
5305
5335
  )
5306
5336
  nativeHeaderFlags.push('-fmodule-map-file=' + modulemap)
5307
5337
  }
@@ -6588,8 +6618,15 @@ async function buildFrameworkProducts(
6588
6618
  const linked = frameworkLinkClosure(scratch, linkedTargets.targets)
6589
6619
  const objects = linked.objects
6590
6620
  if (linked.modules.has('UniformTypeIdentifiers')) {
6591
- const object = path.join(scratch, 'UniformTypeIdentifiers-NativeConstants.o')
6592
- if (!existsSync(object)) {
6621
+ const constantsDir = path.join(scratch, 'uniform-type-constants')
6622
+ const constantsStamp = path.join(constantsDir, '.complete')
6623
+ const object = path.join(constantsDir, 'UniformTypeIdentifiers-NativeConstants.o')
6624
+ if (
6625
+ !existsSync(constantsStamp) ||
6626
+ readFileSync(constantsStamp, 'utf8') !== args.frameworkKey
6627
+ ) {
6628
+ rmSync(constantsDir, { recursive: true, force: true })
6629
+ mkdirSync(constantsDir)
6593
6630
  const sdkPaths = swiftSdkPaths(args.moduleRoot, args.toolchainBin)
6594
6631
  compileUniformTypeConstants({
6595
6632
  bin: args.toolchainBin,
@@ -6597,8 +6634,9 @@ async function buildFrameworkProducts(
6597
6634
  darwin: sdkPaths.darwin,
6598
6635
  packageRoot: args.moduleRoot,
6599
6636
  minimum: darwinRecordsMinimum(),
6600
- out: scratch,
6637
+ out: constantsDir,
6601
6638
  })
6639
+ writeFileSync(constantsStamp, args.frameworkKey)
6602
6640
  }
6603
6641
  objects.push(object)
6604
6642
  linked.owners.set(object, 'UniformTypeIdentifiers')
package/src/swift-host.ts CHANGED
@@ -83,7 +83,8 @@ import {
83
83
  type SwiftPackageGap,
84
84
  type SwiftPackages,
85
85
  } from './swift-packages'
86
- import { rasterizePdfFile } from './swift-pdf-raster'
86
+ import { rasterizePdfFile, rasterizeSvgFile } from './swift-pdf-raster'
87
+ import { shippedBinaryDiffers } from './swift-shipped-binaries'
87
88
  import {
88
89
  packageInputPath,
89
90
  readPackageFile as readSwiftSourceFile,
@@ -596,7 +597,7 @@ async function swiftPackages(
596
597
  // compiling, or a placeholder package's swift target: each stands in from
597
598
  // its public surface.
598
599
  const standinArtifact = (binary: SwiftPackageBinary) =>
599
- binary.publicHeaders === undefined || binary.assemblySources !== undefined
600
+ binary.publicHeaders === undefined || binary.unloweredSources !== undefined
600
601
  const artifacts = reached.filter(standinArtifact)
601
602
  if (entry.moduleRoot && entry.provided && artifacts.length > 0) {
602
603
  const resolved = swiftModuleToolchain(entry.moduleRoot)
@@ -618,10 +619,16 @@ async function swiftPackages(
618
619
  const cxxArtifacts = reached.filter(standinArtifact)
619
620
  const generation = standinGenerationInputs(cxxArtifacts, toolchain, entry.behavior)
620
621
  if (cached.standinKey !== generation) {
622
+ // an archive other than the one peach ships a module for stands in itself
623
+ const replaced = new Set(
624
+ cxxArtifacts
625
+ .filter((binary) => shippedBinaryDiffers(binary.target, binary.checksum))
626
+ .map((binary) => binary.target),
627
+ )
621
628
  const built = await swiftStandins(
622
629
  cxxArtifacts,
623
630
  toolchain,
624
- entry.provided,
631
+ new Set([...entry.provided].filter((name) => !replaced.has(name))),
625
632
  entry.behavior,
626
633
  )
627
634
  cached.packages = await resolveSwiftPackagesAsync({
@@ -637,6 +644,9 @@ async function swiftPackages(
637
644
  .map((binary) => binary.target)
638
645
  .filter((target) => !built.gaps.has(target)),
639
646
  ]),
647
+ standinTargets: new Set(
648
+ [...replaced].filter((target) => !built.gaps.has(target)),
649
+ ),
640
650
  binaryGaps: built.gaps,
641
651
  owners,
642
652
  })
@@ -1941,6 +1951,15 @@ export function buildSwiftResourceTable(
1941
1951
  throw new Error('swift image pack exceeds the compile service caps')
1942
1952
  }
1943
1953
  bytes = readPackageFile(project.packagePath, disk, limits.imageBytes)
1954
+ const svg =
1955
+ ext === '.svg'
1956
+ ? rasterizeSvgFile(disk, createHash('sha256').update(bytes).digest('hex'))
1957
+ : null
1958
+ if (svg) {
1959
+ bytes = svg.bytes
1960
+ ext = '.png'
1961
+ uploadName = `${path.posix.basename(file, path.posix.extname(file))}.png`
1962
+ }
1944
1963
  }
1945
1964
  if (imageBytes + bytes.length > limits.imageTotalBytes) {
1946
1965
  throw new Error('swift image pack exceeds the compile service caps')
@@ -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
  }