peachsim 0.1.1620 → 0.1.1635

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 (185) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +45 -6
  3. package/cli/app-config.ts +4 -1
  4. package/cli/app-fonts.ts +39 -18
  5. package/cli/app-stubs.ts +224 -9
  6. package/cli/bridge-flow-runner.ts +248 -156
  7. package/cli/cloud-client.ts +68 -57
  8. package/cli/command-registry.ts +1 -0
  9. package/cli/commands/box/search-command.ts +3 -2
  10. package/cli/commands/box.ts +10 -29
  11. package/cli/commands/control.ts +391 -92
  12. package/cli/commands/doctor.ts +17 -184
  13. package/cli/commands/flow.ts +79 -11
  14. package/cli/commands/inspect/core.ts +10 -5
  15. package/cli/commands/inspect/settling.ts +71 -22
  16. package/cli/commands/inspect/wait-ready.ts +12 -0
  17. package/cli/commands/inspect.ts +26 -3
  18. package/cli/commands/install-desktop.ts +1 -0
  19. package/cli/commands/maestro-compare.ts +105 -67
  20. package/cli/commands/maestro.ts +9 -1
  21. package/cli/commands/platform.ts +71 -36
  22. package/cli/commands/record.ts +21 -1
  23. package/cli/commands/screenshot.ts +23 -1
  24. package/cli/commands/serve.ts +7 -2
  25. package/cli/commands/setup.ts +19 -42
  26. package/cli/commands/swift.ts +5 -0
  27. package/cli/commands/upload.ts +51 -8
  28. package/cli/desktop-companion.ts +102 -17
  29. package/cli/dev-build-freshness.ts +37 -2
  30. package/cli/drivers/desktop.ts +14 -1
  31. package/cli/drivers/playwright-sim-host.ts +44 -8
  32. package/cli/drivers/playwright.ts +9 -8
  33. package/cli/drivers/types.ts +5 -0
  34. package/cli/maestro-accessibility.ts +53 -0
  35. package/cli/maestro-compare.ts +108 -12
  36. package/cli/main.ts +2 -1
  37. package/cli/outbound-endpoints.ts +35 -6
  38. package/cli/parent-pid.ts +0 -9
  39. package/cli/pause-aware-timeout.ts +102 -0
  40. package/cli/remote-simulators.ts +112 -0
  41. package/cli/remoteSimulatorContract.ts +21 -0
  42. package/cli/scene-video.ts +89 -0
  43. package/cli/ws-bridge.ts +23 -14
  44. package/detox/attempt-events.cjs +4 -0
  45. package/detox/expectations.ts +5 -1
  46. package/detox/index.ts +241 -181
  47. package/detox/motion-change.cjs +73 -0
  48. package/detox/motion-change.d.cts +21 -0
  49. package/detox/navigation-lifecycle.ts +22 -4
  50. package/dist-lib/agent-daemon-client.cjs +3 -2
  51. package/dist-lib/agent-events.cjs +1 -1
  52. package/dist-lib/attached-projects.cjs +1 -1
  53. package/dist-lib/auth/shared-session.cjs +3 -2
  54. package/dist-lib/backend-origin.cjs +1 -1
  55. package/dist-lib/beta.cjs +1 -1
  56. package/dist-lib/beta.mjs +1 -1
  57. package/dist-lib/bridge-constants.cjs +13 -1
  58. package/dist-lib/bridge-contract-input.cjs +1 -1
  59. package/dist-lib/bridge-contract-input.mjs +1 -1
  60. package/dist-lib/bridge-contract.cjs +14 -8
  61. package/dist-lib/bridge-contract.mjs +13 -7
  62. package/dist-lib/bundle-channel.cjs +10480 -7962
  63. package/dist-lib/capture-contract.cjs +1 -1
  64. package/dist-lib/capture-contract.mjs +1 -1
  65. package/dist-lib/cloud-contract.cjs +1 -1
  66. package/dist-lib/cloud-contract.mjs +1 -1
  67. package/dist-lib/cloud-test-args.cjs +1 -1
  68. package/dist-lib/cloud-test-args.mjs +1 -1
  69. package/dist-lib/cloud.cjs +3 -2
  70. package/dist-lib/cloud.mjs +3 -2
  71. package/dist-lib/config.cjs +10 -6
  72. package/dist-lib/config.mjs +10 -6
  73. package/dist-lib/detox/index.cjs +1854 -966
  74. package/dist-lib/dev-bundle-resolution.cjs +64 -24
  75. package/dist-lib/expo-swift-bundle.cjs +8715 -6271
  76. package/dist-lib/expo-swift-metadata.cjs +7 -4
  77. package/dist-lib/expo-swift-metadata.mjs +7 -4
  78. package/dist-lib/home-paths.cjs +32 -3
  79. package/dist-lib/host/bridge-host.cjs +10135 -7060
  80. package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
  81. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  82. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  83. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  84. package/dist-lib/host/websocket-proxy.cjs +1 -1
  85. package/dist-lib/index.cjs +1843 -408
  86. package/dist-lib/jump-to-source-babel.cjs +1 -1
  87. package/dist-lib/jump-to-source-native.cjs +1 -1
  88. package/dist-lib/kotlin-host.cjs +1 -1
  89. package/dist-lib/menu.cjs +3 -2
  90. package/dist-lib/menu.mjs +3 -2
  91. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  92. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  93. package/dist-lib/metro-production-bundle.cjs +5 -4
  94. package/dist-lib/metro-production-bundle.mjs +5 -4
  95. package/dist-lib/metro.cjs +1182 -418
  96. package/dist-lib/native-app-identity-project.cjs +782 -23
  97. package/dist-lib/native-app-identity-project.mjs +781 -23
  98. package/dist-lib/native-app-identity.cjs +276 -9
  99. package/dist-lib/native-app-identity.mjs +273 -8
  100. package/dist-lib/native-firebase-metadata.cjs +5 -4
  101. package/dist-lib/native-firebase-metadata.mjs +5 -4
  102. package/dist-lib/plist.cjs +1 -1
  103. package/dist-lib/plist.mjs +1 -1
  104. package/dist-lib/profiles.cjs +1 -1
  105. package/dist-lib/public-brand.cjs +3 -2
  106. package/dist-lib/react-native-host-modules.cjs +8 -1
  107. package/dist-lib/react-native-host-modules.mjs +8 -1
  108. package/dist-lib/scripts/dev-server-scanner.cjs +106 -28
  109. package/dist-lib/sdk.cjs +115 -34
  110. package/dist-lib/sdk.mjs +115 -33
  111. package/dist-lib/skills.cjs +15274 -9904
  112. package/dist-lib/swift-compile.cjs +1165 -173
  113. package/dist-lib/swift-compile.mjs +1212 -203
  114. package/dist-lib/swift-package.cjs +12 -3
  115. package/dist-lib/swift-package.mjs +12 -3
  116. package/dist-lib/swift-submit.cjs +7 -1
  117. package/dist-lib/swift-submit.mjs +5 -1
  118. package/dist-lib/swift-toolchain.cjs +133 -18
  119. package/dist-lib/swift.cjs +1 -1
  120. package/dist-lib/vite-swift.cjs +2648 -862
  121. package/dist-lib/vite.cjs +70 -14
  122. package/dist-lib/worklet-executable.cjs +25 -2
  123. package/dist-lib/worklet-executable.mjs +25 -2
  124. package/kotlin/AppSources/dev/peach/app/PeachDrawable.kt +21 -14
  125. package/kotlin/Sources/androidx/annotation/DrawableRes.kt +14 -0
  126. package/package.json +2 -2
  127. package/scripts/dev-server-scanner.ts +35 -14
  128. package/skills/peach-perf/SKILL.md +11 -5
  129. package/skills/peach-setup/SKILL.md +16 -19
  130. package/src/admitted-mac-build.ts +34 -8
  131. package/src/android-app-identity.ts +146 -0
  132. package/src/android-autolinking.ts +75 -0
  133. package/src/android-string-value.ts +36 -0
  134. package/src/android-strings.ts +5 -36
  135. package/src/androidAutolinkingContract.ts +40 -0
  136. package/src/bridge-constants.ts +11 -0
  137. package/src/bridge-contract.ts +22 -34
  138. package/src/bundleGlobalFooter.ts +26 -7
  139. package/src/codex-client.ts +3 -2
  140. package/src/config.ts +15 -0
  141. package/src/desktop-host-delivery.ts +5 -1
  142. package/src/dev-bundle-resolution.ts +60 -26
  143. package/src/expo-kotlin-host.ts +6 -36
  144. package/src/expo-manifest-body.ts +13 -0
  145. package/src/expo-swift-bundle.ts +17 -12
  146. package/src/expo-swift-host.ts +640 -192
  147. package/src/expo-swift-ready.ts +78 -0
  148. package/src/expoSwiftContract.ts +19 -0
  149. package/src/home-paths.ts +48 -2
  150. package/src/host/bridge-host.ts +12 -57
  151. package/src/host/staged-host-files.ts +29 -2
  152. package/src/installed-package-versions.ts +54 -14
  153. package/src/launchMetadataContract.ts +24 -0
  154. package/src/metro-plugin.ts +37 -42
  155. package/src/native-app-identity-project.ts +142 -5
  156. package/src/native-app-identity.ts +176 -11
  157. package/src/native-firebase-config.ts +209 -13
  158. package/src/nitro-compile.ts +2 -5
  159. package/src/nitro-source.ts +147 -63
  160. package/src/process-group.ts +114 -61
  161. package/src/process-output.ts +0 -9
  162. package/src/public-brand.ts +1 -0
  163. package/src/react-native-bridge-modules.ts +416 -0
  164. package/src/react-native-host-modules.ts +7 -0
  165. package/src/sim-client.ts +6 -4
  166. package/src/swift-binary-modules.ts +2 -2
  167. package/src/swift-compile.ts +1007 -108
  168. package/src/swift-compiler-digest.ts +14 -0
  169. package/src/swift-distribution.lock.json +40 -12
  170. package/src/swift-distribution.ts +61 -9
  171. package/src/swift-host.ts +149 -56
  172. package/src/swift-icu.ts +14 -6
  173. package/src/swift-objc-sdk.ts +133 -10
  174. package/src/swift-objc-standin.ts +38 -3
  175. package/src/swift-package-manifest.ts +21 -6
  176. package/src/swift-package.ts +15 -1
  177. package/src/swift-packages.ts +119 -60
  178. package/src/swift-standin-emit.ts +57 -9
  179. package/src/swift-standins.ts +185 -25
  180. package/src/swift-submit.ts +10 -0
  181. package/src/swift-toolchain.ts +149 -23
  182. package/src/vite-plugin.ts +20 -20
  183. package/src/worklet-executable.ts +30 -3
  184. package/src/worklets-babel.ts +35 -14
  185. package/src/xcode-project.ts +10 -0
@@ -16,7 +16,9 @@ import {
16
16
  import os from 'node:os'
17
17
  import path from 'node:path'
18
18
  import { admittedMacBuilderSlot } from './admitted-mac-build'
19
+ import { rnxHomeDir, swiftPackageCacheOptions } from './home-paths'
19
20
  import { terminateProcessGroup } from './process-group'
21
+ import { swiftCompilerSourceDigest } from './swift-compiler-digest'
20
22
  import { designTimeDiagnostic, designTimeSource } from './swift-design-time'
21
23
  import {
22
24
  parseSwiftDistributionManifest,
@@ -31,9 +33,9 @@ import {
31
33
  swiftTargetModuleName,
32
34
  type SwiftPackageTarget,
33
35
  } from './swift-package'
36
+ import { swiftSdkOptions, type SwiftWasmSdk } from './swift-toolchain'
34
37
  import { isSwiftResourceBundles } from './swiftContract'
35
38
  import type { SwiftImageUpload } from './swift-submit'
36
- import type { SwiftWasmSdk } from './swift-toolchain'
37
39
  import type { SwiftResourceBundle } from './swiftContract'
38
40
 
39
41
  export { swiftIcuAsset, type SwiftIcuAsset }
@@ -377,7 +379,8 @@ export function withNativeSourceGlue(
377
379
  const OPTIONAL_FRAMEWORK_DEPENDENCIES: Record<string, string[]> = {
378
380
  GameplayKit: [],
379
381
  simd: [],
380
- GLKit: [],
382
+ ModelIO: ['simd'],
383
+ GLKit: ['ModelIO'],
381
384
  Accelerate: [],
382
385
  CryptoKit: [],
383
386
  CommonCrypto: [],
@@ -391,7 +394,7 @@ const OPTIONAL_FRAMEWORK_DEPENDENCIES: Record<string, string[]> = {
391
394
  Statsig: [],
392
395
  TOCropViewController: [],
393
396
  RiveRuntime: ['MetalKit'],
394
- MetalKit: [],
397
+ MetalKit: ['ModelIO'],
395
398
  DatadogCore: [],
396
399
  DatadogLogs: ['DatadogCore'],
397
400
  DatadogRUM: ['DatadogCore'],
@@ -553,12 +556,19 @@ export function swiftSdkPaths(
553
556
  toolchainBin: string,
554
557
  ): { sysroot: string; resources: string } {
555
558
  const sdk = swiftModuleSdk(moduleRoot).wasmSdkId
556
- const key = `${toolchainBin}\0${sdk}`
559
+ const key = JSON.stringify([toolchainBin, sdk, swiftSdkOptions()])
557
560
  const cached = sdkPaths.get(key)
558
561
  if (cached) return cached
559
562
  const configuration = execFileSync(
560
563
  path.join(toolchainBin, 'swift'),
561
- ['sdk', 'configure', '--show-configuration', sdk, 'wasm32-unknown-wasip1'],
564
+ [
565
+ 'sdk',
566
+ 'configure',
567
+ ...swiftSdkOptions(),
568
+ '--show-configuration',
569
+ sdk,
570
+ 'wasm32-unknown-wasip1',
571
+ ],
562
572
  { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] },
563
573
  )
564
574
  const field = (name: string) => {
@@ -585,7 +595,7 @@ export function swiftAvailableModules(
585
595
  toolchainBin: string,
586
596
  ): Set<string> {
587
597
  const sdk = swiftModuleSdk(moduleRoot).wasmSdkId
588
- const key = `${moduleRoot}\0${sdk}`
598
+ const key = JSON.stringify([moduleRoot, sdk, swiftSdkOptions()])
589
599
  const cached = availableModules.get(key)
590
600
  if (cached) return cached
591
601
  const modules = new Set(swiftPeachModules(moduleRoot))
@@ -711,7 +721,14 @@ const EXECUTABLE_LINK_FLAGS = ` "-Xclang-linker", "-O0",
711
721
  const REACTOR_FLAG = '"-Xclang-linker", "-mexec-model=reactor",\n'
712
722
 
713
723
  /** bump with any change to the emitted multi-target manifest text. */
714
- export const MULTI_MANIFEST_VERSION = 38
724
+ export const MULTI_MANIFEST_VERSION = 39
725
+
726
+ // build-cli replaces this in every bundle; source runs read the files directly.
727
+ declare const __SWIFT_COMPILER_DIGEST__: string | undefined
728
+ const compilerSourceDigest =
729
+ typeof __SWIFT_COMPILER_DIGEST__ === 'string'
730
+ ? __SWIFT_COMPILER_DIGEST__
731
+ : swiftCompilerSourceDigest(import.meta.dirname)
715
732
 
716
733
  export function swiftArtifactHash(
717
734
  input: SwiftCompileInput,
@@ -719,54 +736,8 @@ export function swiftArtifactHash(
719
736
  moduleRoot: string,
720
737
  ): string {
721
738
  const hash = createHash('sha256')
722
- // v47: target ownership honors exclusions before lowering manifest-named files
723
- // v46: view builder literals compile as design-time lookups
724
- // v45: the link runs no wasm-opt pass, whatever the compiling machine has
725
- // v44: fixed-signature optional type methods retain metatype dispatch
726
- // v43: optional type-property witnesses preserve class getter dispatch
727
- // v42: the source-checkout template route takes the same executable stack layout
728
- // v41: executable stack size and layout match the native main-thread budget
729
- // v40: generic classes expose fixed-signature optional SDK witnesses
730
- // v39: target source files named Package.swift lower with their owning module
731
- // v38: dependency manifests stay intact and backend threads match build jobs
732
- // v37: optional requirement calls lower trailing closures without parentheses
733
- // v36: javascript dialog witnesses preserve typed main actor completions
734
- // v35: input-suggestion witnesses keep UIKit payload and optional results
735
- // v34: typed async SDK witnesses keep imported names and completion results
736
- // v33: Foundation-qualified authentication types use their networking owner
737
- // v32: extension override slots resolve across each target's files
738
- // v31: the text, table, scroll, collection and flow layout delegates'
739
- // witnesses gain selector records, and their optional calls lower to
740
- // selector sends
741
- // v30: async methods answer their completion handler selector, async
742
- // optional requirements get members, and non-escaping closures reach sends
743
- // v29: the SDK's delegate protocols' witnesses gain selector records, and
744
- // optional calls reach a requirement by its labels and witnesses by types
745
- // v28: AnyClass method calls and IMP casts lower to selector sends
746
- // v27: @objc protocols' optional requirements lower to selector sends
747
- // v26: an @objc protocol is class-bound, #keyPath lowers to its string,
748
- // and an override lifted from an extension keeps the extension's access
749
- // v25: every Clang submodule import names its framework module
750
- // v24: distribution objects use an ordered linker response file
751
- // v22: Foundation sources see Darwin, which carries the libc and Mach
752
- // v21: Foundation sources see the ObservableObject and Published aliases
753
- // v20: supplied table editing and swipe methods preserve objective-c selectors
754
- // v18: NSValue(time:) constructs NSStructBox through NSValue.boxedTime
755
- // v17: AVAsset(url:) constructs AVURLAsset for the class cluster
756
- // v16: overrides of @objc extension members rename to __peach_ovr_
757
- // v15: Foundation-only sources see the platform libc (WASILibc, including
758
- // math round) and its pthread mutexes (wasi_pthread)
759
- // v14: AnyObject doubleValue lowers to the typed _objcNumber getter
760
- // v13: implicit target resources synthesize Bundle.module
761
- // v12: overrides in an extension of a same-file class lift into the class
762
- // v10: Foundation-only sources see Dispatch queues
763
- // v9: table cell and header footer view initializers compile required
764
- // v8: optional framework products and distribution objects link on import
765
- // v7: runtime class lookup uses the same objc class registry as messages
766
- // v6: app and scene delegate classes compile final
767
- // (v5: a target declaring resources gets SwiftPM's Bundle.module accessor;
768
- // v4: sources compile through swiftSourceAsIOS)
769
- hash.update(`swift-compile/v47\n${release}\n`)
739
+ hash.update(`swift-compile\n${release}\n`)
740
+ hash.update(compilerSourceDigest)
770
741
  if (input.oneModule) hash.update('one-module\n')
771
742
  hash.update(swiftModuleDigest(moduleRoot))
772
743
  for (const file of Object.keys(input.files).sort()) {
@@ -855,19 +826,18 @@ export function emitSwiftPackageManifest(args: {
855
826
  libraries?: Map<string, string>
856
827
  }): string {
857
828
  const { targets, siblings, moduleRoot, oneModule, spriteKit, distribution } = args
858
- const reachedFrameworks = new Set(
859
- [...siblings.values()]
860
- .flat()
861
- .filter(
862
- (name) =>
863
- OPTIONAL_FRAMEWORKS.has(name) &&
864
- !targets.some((target) => target.name === name),
865
- )
866
- .flatMap((name) => [name, ...(OPTIONAL_FRAMEWORK_DEPENDENCIES[name] ?? [])]),
867
- )
829
+ const reachedFrameworks = new Set<string>()
830
+ const reach = (name: string) => {
831
+ if (reachedFrameworks.has(name)) return
832
+ reachedFrameworks.add(name)
833
+ for (const dependency of OPTIONAL_FRAMEWORK_DEPENDENCIES[name] ?? [])
834
+ reach(dependency)
835
+ }
836
+ for (const name of [...siblings.values()].flat())
837
+ if (OPTIONAL_FRAMEWORKS.has(name) && !targets.some((target) => target.name === name))
838
+ reach(name)
868
839
  if (spriteKit) {
869
- reachedFrameworks.add('SpriteKit')
870
- reachedFrameworks.add('PeachBox2D')
840
+ for (const name of ['SpriteKit', 'PeachBox2D', 'simd', 'GLKit']) reach(name)
871
841
  }
872
842
  // the distribution builder names each object lib/<target>-<file>.o.
873
843
  // preserve link order while leaving unreached optional module objects out.
@@ -914,6 +884,10 @@ export function emitSwiftPackageManifest(args: {
914
884
  // each target compiles in the language mode and default isolation its
915
885
  // author declared, the way xcode builds the same package.
916
886
  const stanza = (target: SwiftPackageTarget): string => {
887
+ // system modules keep their upstream module map and resolve headers and
888
+ // libraries from the wasm SDK, never the build host's pkg-config paths.
889
+ if (target.systemLibrary)
890
+ return ` .systemLibrary(name: ${JSON.stringify(target.name)}, path: ${JSON.stringify(target.path)}),`
917
891
  const isolation = target.mainActorIsolation
918
892
  ? ' .defaultIsolation(MainActor.self),'
919
893
  : ''
@@ -977,17 +951,27 @@ export function emitSwiftPackageManifest(args: {
977
951
  .join('')
978
952
  : ''
979
953
  const kind = target.executable ? '.executableTarget' : '.target'
954
+ const linkedLibraries = (target.linkedLibraries ?? []).map(
955
+ (name) => `.linkedLibrary(${JSON.stringify(name)})`,
956
+ )
957
+ const librarySettings = [
958
+ ...linkedLibraries,
959
+ ...(args.libraries?.has(target.name)
960
+ ? [`.unsafeFlags([${JSON.stringify(args.libraries.get(target.name))}])`]
961
+ : []),
962
+ ]
980
963
  const link = target.executable
981
964
  ? `,
982
965
  linkerSettings: [
966
+ ${linkedLibraries.map((setting) => `${setting},`).join('\n ')}
983
967
  .unsafeFlags([
984
968
  ${REACTOR_FLAG}${EXECUTABLE_LINK_FLAGS} "-Xlinker", "--export-if-defined=__main_argc_argv"${library},
985
969
  ]),
986
970
  .unsafeFlags(["-Xlinker", "--strip-all"], .when(configuration: .release)),
987
971
  ]`
988
- : args.libraries?.has(target.name)
972
+ : librarySettings.length > 0
989
973
  ? `,
990
- linkerSettings: [.unsafeFlags([${JSON.stringify(args.libraries.get(target.name))}])]`
974
+ linkerSettings: [${librarySettings.join(', ')}]`
991
975
  : ''
992
976
  return [
993
977
  ` ${kind}(`,
@@ -1062,7 +1046,8 @@ export function syncSwiftTree(base: string, files: Map<string, string | Buffer>)
1062
1046
  }
1063
1047
 
1064
1048
  // the app runs as iOS, but it compiles for wasm, where `os(iOS)` is false and
1065
- // every iOS branch of the app would compile out. a condition line names iOS
1049
+ // every iOS branch of the app would compile out. peach is the iOS simulator,
1050
+ // so `targetEnvironment(simulator)` holds too. a condition line names iOS
1066
1051
  // as `true` padded to the same length, so diagnostics keep their columns;
1067
1052
  // os(WASI) still holds for code written for wasm. only `#if` and `#elseif`
1068
1053
  // lines that begin in code change: a line inside a string literal or a block
@@ -1076,7 +1061,7 @@ export function syncSwiftTree(base: string, files: Map<string, string | Buffer>)
1076
1061
  // explicit `@objc(name:)` on a member, whose name becomes a string argument,
1077
1062
  // and a delegate class that becomes final (below).
1078
1063
  const DIRECTIVE = /^[ \t]*#(?:if|elseif)\b/
1079
- const OS_IOS = /\bos\(\s*iOS\s*\)/g
1064
+ const OS_IOS = /\b(?:os\(\s*iOS\s*\)|targetEnvironment\(\s*simulator\s*\))/g
1080
1065
  const OBJC_ATTRIBUTE = /^@(?:objcMembers\b|objc\b(?:(\s*)\(([^()]*)\))?|IBAction\b)/
1081
1066
  const SELECTOR = /^#selector\b/
1082
1067
  const PROTOCOL_NAME = /^\s+[A-Za-z_]\w*(\s*:)?/
@@ -1606,12 +1591,73 @@ function compiledSwiftSources(
1606
1591
  const sources = lifted.map(([, contents]) => contents)
1607
1592
  const extensions = objcExtensionMemberIndex(sources)
1608
1593
  const objc = objcIndex(sources)
1594
+ const rooted = objcRootedClasses(sources)
1609
1595
  for (const [file, contents] of lifted)
1610
- compiled.set(file, swiftSourceAsIOS(contents, extensions, objc))
1596
+ compiled.set(
1597
+ file,
1598
+ hideObjCClassesFromCxx(swiftSourceAsIOS(contents, extensions, objc), rooted),
1599
+ )
1611
1600
  }
1612
1601
  return compiled
1613
1602
  }
1614
1603
 
1604
+ // an Apple framework protocol a class may list first, which is no superclass
1605
+ const APPLE_PROTOCOL =
1606
+ /^NS(?:Mutable)?Copying$|^NS(?:Secure)?Coding$|^NSLocking$|^NSFastEnumeration$|^NSObjectProtocol$|(?:Delegate|DataSource)$/
1607
+
1608
+ // the module's classes whose superclass chain, through the classes `sources`
1609
+ // declare, reaches an Apple framework class: Objective-C classes on iOS
1610
+ function objcRootedClasses(sources: string[]): Set<string> {
1611
+ const bases = new Map<string, string>()
1612
+ for (const source of sources)
1613
+ for (const match of swiftCodeMask(source).matchAll(
1614
+ /\bclass\s+(?!(?:func|var|let|subscript)\b)([A-Za-z_]\w*)\s*(?:<[^>{]*>)?\s*:\s*(?:[A-Za-z_]\w*\.)*([A-Za-z_]\w*)/g,
1615
+ ))
1616
+ bases.set(match[1]!, match[2]!)
1617
+ const rooted = new Set<string>()
1618
+ for (const name of bases.keys()) {
1619
+ const seen = new Set([name])
1620
+ let base = bases.get(name)!
1621
+ while (bases.has(base) && !seen.has(base)) {
1622
+ seen.add(base)
1623
+ base = bases.get(base)!
1624
+ }
1625
+ if (
1626
+ !bases.has(base) &&
1627
+ APPLE_CLASS.test(base) &&
1628
+ !APPLE_PROTOCOL.test(base) &&
1629
+ !(base in SDK_OBJC_OPTIONAL)
1630
+ )
1631
+ rooted.add(name)
1632
+ }
1633
+ return rooted
1634
+ }
1635
+
1636
+ // the header swift emits on iOS keeps an Objective-C class out of its C++
1637
+ // section. here its root is a swift class from a module with no C++ header,
1638
+ // so C++ that includes the header fails on the undeclared base. a top-level
1639
+ // class in `rooted` gains @_expose(!Cxx) in front of its declaration,
1640
+ // shifting that one line's columns. swift rejects the attribute in a local
1641
+ // scope, so a nested class keeps its exposure.
1642
+ function hideObjCClassesFromCxx(source: string, rooted: Set<string>): string {
1643
+ if (rooted.size === 0) return source
1644
+ const code = swiftCodeMask(source)
1645
+ const starts: number[] = []
1646
+ let depth = 0
1647
+ for (const match of code.matchAll(
1648
+ /[{}]|\bclass\s+(?!(?:func|var|let|subscript)\b)([A-Za-z_]\w*)/g,
1649
+ )) {
1650
+ if (match[0] === '{') depth++
1651
+ else if (match[0] === '}') depth--
1652
+ else if (depth === 0 && rooted.has(match[1]!))
1653
+ starts.push(declarationStart(code, match.index, 0))
1654
+ }
1655
+ let out = source
1656
+ for (const at of starts.reverse())
1657
+ out = `${out.slice(0, at)}@_expose(!Cxx) ${out.slice(at)}`
1658
+ return out
1659
+ }
1660
+
1615
1661
  // wasm Swift has no ObjC runtime, so a member read on AnyObject never
1616
1662
  // resolves: `value of type 'AnyObject' has no member 'doubleValue'`. native
1617
1663
  // code that bridges dictionary values through AnyObject to reach NSNumber's
@@ -3602,6 +3648,8 @@ export type ObjCIndex = {
3602
3648
  // each @objc type method's selector to its result type, null when two
3603
3649
  // declarations disagree
3604
3650
  typeMethods: Map<string, string | null>
3651
+ // NSObject and protocols constrained to it without a Swift init requirement
3652
+ nsObjectTypes: Set<string>
3605
3653
  }
3606
3654
 
3607
3655
  // the @objc type methods `source` declares, by selector, into `found`
@@ -3739,15 +3787,43 @@ export function objcIndex(sources: string[]): ObjCIndex {
3739
3787
  /\b(?:var|let)\s+([A-Za-z_]\w*)/g,
3740
3788
  ))
3741
3789
  variables.add(declared[1]!)
3742
- const parents = requirements.size
3743
- ? inheritedTypes(sources)
3744
- : new Map<string, Set<string>>()
3790
+ const parents = inheritedTypes(sources)
3745
3791
  for (const [protocol, inherited] of sdkParents)
3746
3792
  parents.set(protocol, new Set([...(parents.get(protocol) ?? []), ...inherited]))
3747
3793
  const conformers = requirements.size
3748
3794
  ? conformingTypes(parents, new Set(requirements.keys()))
3749
3795
  : new Map<string, Set<string>>()
3750
- return { requirements, conformers, callable, variables, aliases, typeMethods }
3796
+ const protocols = new Set<string>()
3797
+ const initializers = new Set<string>()
3798
+ for (const source of sources) {
3799
+ if (!/\bprotocol\b/.test(source)) continue
3800
+ const code = swiftCodeMask(source)
3801
+ const braces = [...code.matchAll(/[{}]/g)].map((match) => match.index)
3802
+ for (const protocol of code.matchAll(/\bprotocol\s+([A-Za-z_]\w*)[^{}]*\{/g)) {
3803
+ const name = protocol[1]!
3804
+ protocols.add(name)
3805
+ const open = protocol.index + protocol[0].length - 1
3806
+ if (
3807
+ /\binit\s*[?!]?\s*\(/.test(code.slice(open + 1, closingBrace(code, braces, open)))
3808
+ )
3809
+ initializers.add(name)
3810
+ }
3811
+ }
3812
+ const rooted = conformingTypes(parents, new Set(['NSObject']))
3813
+ const initialized = conformingTypes(parents, initializers)
3814
+ const nsObjectTypes = new Set([
3815
+ 'NSObject',
3816
+ ...[...protocols].filter((name) => rooted.has(name) && !initialized.has(name)),
3817
+ ])
3818
+ return {
3819
+ requirements,
3820
+ conformers,
3821
+ callable,
3822
+ variables,
3823
+ aliases,
3824
+ typeMethods,
3825
+ nsObjectTypes,
3826
+ }
3751
3827
  }
3752
3828
 
3753
3829
  // the non-generic file-scope typealiases `sources` declare, each resolved
@@ -4117,7 +4193,7 @@ const IMP_CONVENTION = /@convention\(c\)(?=\s*\(\s*AnyObject\s*,\s*Selector\b)/g
4117
4193
 
4118
4194
  function lowerObjCRuntimeCalls(source: string, index: ObjCIndex): string {
4119
4195
  const casts = source.includes('@convention(c)')
4120
- const classes = /\b(?:AnyClass|AnyObject)\b/.test(source)
4196
+ const classes = /\b(?:AnyClass|AnyObject)\b|\.\s*init\s*\(/.test(source)
4121
4197
  if (!casts && !classes) return source
4122
4198
  const code = swiftCodeMask(source)
4123
4199
  const edits: [number, number, string][] = []
@@ -4148,15 +4224,33 @@ function lowerObjCRuntimeCalls(source: string, index: ObjCIndex): string {
4148
4224
  }
4149
4225
  }
4150
4226
  if (classes) {
4151
- // every declaration of a name, typed or not; a receiver is an AnyClass
4152
- // or AnyObject only where its innermost declaration in scope says so
4227
+ // every declaration of a name, typed or not; a receiver's innermost
4228
+ // declaration in scope determines its runtime operation
4153
4229
  const declarations = new Map<string, { at: number; type: string }[]>()
4154
4230
  for (const declared of code.matchAll(
4155
- /(?:\b(?:let|var)\s+|[(,]\s*(?:[A-Za-z_]\w*\s+)?)([A-Za-z_]\w*)\s*:\s*(?:([A-Z]\w*(?:\.\w+)*)\s*([?!])?|[[(])|\b(?:let|var|for)\s+([A-Za-z_]\w*)\b(?!\s*:)|[{,]\s*([A-Za-z_]\w*)\s+in\b/g,
4231
+ /(?:\b(?:let|var)\s+|[(,]\s*(?:[A-Za-z_]\w*\s+)?)([A-Za-z_]\w*)\s*:\s*(?:(?:any\s+)?([A-Z]\w*(?:\.\w+)*)\s*([?!])?|[[(])|\b(?:let|var|for)\s+([A-Za-z_]\w*)\b(?!\s*:)|[{,]\s*([A-Za-z_]\w*)\s+in\b/g,
4156
4232
  )) {
4157
4233
  const name = declared[1] ?? declared[4] ?? declared[5]!
4158
4234
  const list = declarations.get(name) ?? []
4159
- list.push({ at: declared.index, type: declared[3] ? '' : (declared[2] ?? '') })
4235
+ let type = declared[3] ? '' : (declared[2] ?? '')
4236
+ if (!type && declared[4]) {
4237
+ // NSClassFromString's checked cast establishes the metatype of a
4238
+ // successful conditional binding, including a guard's remaining body.
4239
+ const lookup = /^\s*=\s*NSClassFromString\s*\(/.exec(
4240
+ code.slice(declared.index + declared[0].length),
4241
+ )
4242
+ if (lookup) {
4243
+ const open = declared.index + declared[0].length + lookup[0].length - 1
4244
+ type =
4245
+ /^\s*as\?\s*([A-Za-z_]\w*(?:\.\w+)*\.Type)\b/.exec(
4246
+ code.slice(closingParen(code, open) + 1),
4247
+ )?.[1] ?? ''
4248
+ }
4249
+ }
4250
+ const resolved = type.endsWith('.Type')
4251
+ ? `${resolveAliases(type.slice(0, -5), index.aliases)}.Type`
4252
+ : resolveAliases(type, index.aliases)
4253
+ list.push({ at: declared.index, type: resolved })
4160
4254
  declarations.set(name, list)
4161
4255
  }
4162
4256
  // a tuple or enum pattern (`let (a, b)`, `case let .some(a)`) binds
@@ -4174,7 +4268,7 @@ function lowerObjCRuntimeCalls(source: string, index: ObjCIndex): string {
4174
4268
  }
4175
4269
  for (const list of declarations.values()) list.sort((a, b) => a.at - b.at)
4176
4270
  const braces = [...code.matchAll(/[{}]/g)].map((match) => match.index)
4177
- const receives = (name: string, at: number, type: string): boolean => {
4271
+ const receiverType = (name: string, at: number): string | undefined => {
4178
4272
  let innermost: { from: number; type: string } | undefined
4179
4273
  for (const declared of declarations.get(name) ?? []) {
4180
4274
  if (declared.at > at) break
@@ -4182,22 +4276,40 @@ function lowerObjCRuntimeCalls(source: string, index: ObjCIndex): string {
4182
4276
  if (at > from && at < to && (!innermost || from >= innermost.from))
4183
4277
  innermost = { from, type: declared.type }
4184
4278
  }
4185
- return innermost?.type === type
4279
+ return innermost?.type
4186
4280
  }
4187
4281
  let reached = -1
4188
4282
  for (const call of code.matchAll(
4189
4283
  /(?<![\w.])((?:type\s*\(\s*of\s*:\s*([A-Za-z_]\w*)\s*\))|[A-Za-z_]\w*)\s*\.\s*([A-Za-z_]\w*)\s*\(/g,
4190
4284
  )) {
4191
- if (
4192
- call.index < reached ||
4193
- !(call[2]
4194
- ? receives(call[2], call.index, 'AnyObject')
4195
- : receives(call[1]!, call.index, 'AnyClass'))
4196
- )
4197
- continue
4285
+ if (call.index < reached) continue
4286
+ const type = receiverType(call[2] ?? call[1]!, call.index)
4287
+ const constructed = call[2] ? type : type?.replace(/\.Type$/, '')
4288
+ const constructs =
4289
+ call[3] === 'init' &&
4290
+ constructed &&
4291
+ (call[2] || type?.endsWith('.Type')) &&
4292
+ index.nsObjectTypes.has(constructed.replace(/^Foundation\./, ''))
4293
+ if (!constructs && type !== (call[2] ? 'AnyObject' : 'AnyClass')) continue
4198
4294
  const open = call.index + call[0].length - 1
4199
4295
  const shut = closingParen(code, open)
4200
4296
  const passed = callArguments(source, code, open, shut)
4297
+ if (constructs && passed.length === 0) {
4298
+ // a class-constrained protocol metatype otherwise erases a generic
4299
+ // initializer result to NSObject, losing its protocol requirements.
4300
+ const result =
4301
+ constructed.replace(/^Foundation\./, '') === 'NSObject'
4302
+ ? constructed
4303
+ : `any ${constructed}`
4304
+ edits.push([
4305
+ call.index,
4306
+ shut + 1 - call.index,
4307
+ `_objcNSObjectDefaultInit(${call[1]}, returning: (${result}).self)`,
4308
+ ])
4309
+ reached = shut + 1
4310
+ continue
4311
+ }
4312
+ if (type !== (call[2] ? 'AnyObject' : 'AnyClass')) continue
4201
4313
  const selector = objcSelectorName(
4202
4314
  call[3]!,
4203
4315
  passed.map(({ label }) => label),
@@ -4229,7 +4341,7 @@ function lowerObjCRuntimeCalls(source: string, index: ObjCIndex): string {
4229
4341
  // char outside code (comments, strings, regex literals) reads as a space,
4230
4342
  // so an identifier that survives is code. newlines stay, keeping every
4231
4343
  // offset valid in both views.
4232
- function swiftCodeMask(source: string): string {
4344
+ export function swiftCodeMask(source: string): string {
4233
4345
  const chars = source.split('')
4234
4346
  const blank = (from: number, to: number): void => {
4235
4347
  for (let i = Math.max(0, from); i < Math.min(to, chars.length); i++)
@@ -4344,6 +4456,710 @@ function swiftCodeMask(source: string): string {
4344
4456
  return chars.join('')
4345
4457
  }
4346
4458
 
4459
+ // darwin declares these in Foundation; the guest networking module owns them.
4460
+ const FOUNDATION_NETWORKING_TYPES = new Set([
4461
+ 'CachedURLResponse',
4462
+ 'HTTPCookieStorage',
4463
+ 'HTTPURLResponse',
4464
+ 'NSMutableURLRequest',
4465
+ 'NSURLConnection',
4466
+ 'NSURLConnectionDataDelegate',
4467
+ 'NSURLConnectionDelegate',
4468
+ 'NSURLConnectionDownloadDelegate',
4469
+ 'URLAuthenticationChallenge',
4470
+ 'URLAuthenticationChallengeSender',
4471
+ 'URLCache',
4472
+ 'URLCredential',
4473
+ 'URLCredentialStorage',
4474
+ 'URLProtectionSpace',
4475
+ 'URLProtocol',
4476
+ 'URLProtocolClient',
4477
+ 'URLRequest',
4478
+ 'URLResponse',
4479
+ 'URLSession',
4480
+ 'URLSessionConfiguration',
4481
+ 'URLSessionDataDelegate',
4482
+ 'URLSessionDataTask',
4483
+ 'URLSessionDelegate',
4484
+ 'URLSessionDownloadDelegate',
4485
+ 'URLSessionDownloadTask',
4486
+ 'URLSessionStreamDelegate',
4487
+ 'URLSessionStreamTask',
4488
+ 'URLSessionTask',
4489
+ 'URLSessionTaskDelegate',
4490
+ 'URLSessionTaskMetrics',
4491
+ 'URLSessionTaskTransactionMetrics',
4492
+ 'URLSessionUploadTask',
4493
+ 'URLSessionWebSocketDelegate',
4494
+ 'URLSessionWebSocketTask',
4495
+ ])
4496
+
4497
+ // Foundation overlay declarations live in the shared guest overlay module.
4498
+ const FOUNDATION_OVERLAY_TYPES = new Set([
4499
+ 'AsyncCharacterSequence',
4500
+ 'AsyncLineSequence',
4501
+ 'AsyncUnicodeScalarSequence',
4502
+ 'BlockOperation',
4503
+ 'DateComponentsFormatter',
4504
+ 'ErrorUserInfoKey',
4505
+ 'FileWrapper',
4506
+ 'HTTPCookie',
4507
+ 'HTTPCookiePropertyKey',
4508
+ 'HTTPCookieStringPolicy',
4509
+ 'InlinePresentationIntent',
4510
+ 'ListFormatter',
4511
+ 'LocalizedStringResource',
4512
+ 'MachError',
4513
+ 'MeasurementFormatUnitUsage',
4514
+ 'MeasurementFormatter',
4515
+ 'MessagePort',
4516
+ 'NSAssertionHandler',
4517
+ 'NSAttributedStringFormattingContextKey',
4518
+ 'NSBundleResourceRequest',
4519
+ 'NSCollectionChangeType',
4520
+ 'NSConditionLock',
4521
+ 'NSDataDetector',
4522
+ 'NSException',
4523
+ 'NSExtensionContext',
4524
+ 'NSExtensionItem',
4525
+ 'NSExtensionRequestHandling',
4526
+ 'NSFastEnumerationIterator',
4527
+ 'NSFastEnumerationState',
4528
+ 'NSFileAccessIntent',
4529
+ 'NSFileCoordinator',
4530
+ 'NSFileManagerResumeSyncBehavior',
4531
+ 'NSFileManagerSupportedSyncControls',
4532
+ 'NSFileManagerUploadLocalVersionConflictPolicy',
4533
+ 'NSFileProviderService',
4534
+ 'NSFileProviderServiceName',
4535
+ 'NSFileSecurity',
4536
+ 'NSFileVersion',
4537
+ 'NSGrammaticalCase',
4538
+ 'NSGrammaticalDefiniteness',
4539
+ 'NSGrammaticalDetermination',
4540
+ 'NSGrammaticalGender',
4541
+ 'NSGrammaticalNumber',
4542
+ 'NSGrammaticalPartOfSpeech',
4543
+ 'NSGrammaticalPerson',
4544
+ 'NSGrammaticalPronounType',
4545
+ 'NSHashEnumerator',
4546
+ 'NSHashTable',
4547
+ 'NSHashTableCallBacks',
4548
+ 'NSItemProvider',
4549
+ 'NSItemProviderFileOptions',
4550
+ 'NSItemProviderRepresentationVisibility',
4551
+ 'NSKeyValueOperator',
4552
+ 'NSKeyValueSetMutationKind',
4553
+ 'NSKeyValueSharedObservers',
4554
+ 'NSLinguisticTag',
4555
+ 'NSLinguisticTagScheme',
4556
+ 'NSLinguisticTagger',
4557
+ 'NSLinguisticTaggerUnit',
4558
+ 'NSMachPort',
4559
+ 'NSMapEnumerator',
4560
+ 'NSMapTable',
4561
+ 'NSMapTableKeyCallBacks',
4562
+ 'NSMapTableValueCallBacks',
4563
+ 'NSMetadataItem',
4564
+ 'NSMetadataQuery',
4565
+ 'NSMetadataQueryAttributeValueTuple',
4566
+ 'NSMetadataQueryDelegate',
4567
+ 'NSMetadataQueryResultGroup',
4568
+ 'NSOrderedCollectionChange',
4569
+ 'NSOrderedCollectionDifference',
4570
+ 'NSOrderedCollectionDifferenceCalculationOptions',
4571
+ 'NSPointerArray',
4572
+ 'NSPointerFunctions',
4573
+ 'NSPredicateValidating',
4574
+ 'NSProxy',
4575
+ 'NSPurgeableData',
4576
+ 'NSSecureUnarchiveFromDataTransformer',
4577
+ 'NSSwappedDouble',
4578
+ 'NSSwappedFloat',
4579
+ 'NSURLRequest',
4580
+ 'NSUbiquitousKeyValueStore',
4581
+ 'NSUserActivity',
4582
+ 'NSUserActivityDelegate',
4583
+ 'NSValueTransformerName',
4584
+ 'NSXPCCoder',
4585
+ 'NSXPCConnection',
4586
+ 'NSXPCInterface',
4587
+ 'NSXPCListener',
4588
+ 'NSXPCListenerDelegate',
4589
+ 'NSXPCListenerEndpoint',
4590
+ 'NetService',
4591
+ 'NetServiceBrowser',
4592
+ 'NetServiceBrowserDelegate',
4593
+ 'NetServiceDelegate',
4594
+ 'NotificationQueue',
4595
+ 'Operation',
4596
+ 'OperationQueue',
4597
+ 'PredicateCodableConfiguration',
4598
+ 'PresentationIntent',
4599
+ 'Progress',
4600
+ 'ProgressKind',
4601
+ 'ProgressUserInfoKey',
4602
+ 'RelativeDateTimeFormatter',
4603
+ 'SocketPort',
4604
+ 'StringEncodingDetectionOptionsKey',
4605
+ 'TermOfAddress',
4606
+ 'URLFileProtection',
4607
+ 'URLResource',
4608
+ 'URLThumbnailDictionaryItem',
4609
+ 'URLUbiquitousItemDownloadingStatus',
4610
+ 'URLUbiquitousSharedItemPermissions',
4611
+ 'URLUbiquitousSharedItemRole',
4612
+ 'UndoManager',
4613
+ 'ValueTransformer',
4614
+ 'XMLParser',
4615
+ 'XMLParserDelegate',
4616
+ ])
4617
+
4618
+ // existing overlay globals retain their declaration and runtime owner.
4619
+ const FOUNDATION_OVERLAY_GLOBALS = new Set([
4620
+ 'CFBridgingRetain',
4621
+ 'NSASCIIStringEncoding',
4622
+ 'NSAllHashTableObjects',
4623
+ 'NSAllMapTableKeys',
4624
+ 'NSAllMapTableValues',
4625
+ 'NSAllocateMemoryPages',
4626
+ 'NSAssertionHandlerKey',
4627
+ 'NSBuddhistCalendar',
4628
+ 'NSBundleErrorMaximum',
4629
+ 'NSBundleErrorMinimum',
4630
+ 'NSBundleExecutableArchitectureARM64',
4631
+ 'NSBundleExecutableArchitectureI386',
4632
+ 'NSBundleExecutableArchitecturePPC',
4633
+ 'NSBundleExecutableArchitecturePPC64',
4634
+ 'NSBundleExecutableArchitectureX86_64',
4635
+ 'NSBundleOnDemandResourceExceededMaximumSizeError',
4636
+ 'NSBundleOnDemandResourceInvalidTagError',
4637
+ 'NSBundleOnDemandResourceOutOfSpaceError',
4638
+ 'NSBundleResourceRequestLoadingPriorityUrgent',
4639
+ 'NSChineseCalendar',
4640
+ 'NSCloudSharingConflictError',
4641
+ 'NSCloudSharingErrorMaximum',
4642
+ 'NSCloudSharingErrorMinimum',
4643
+ 'NSCloudSharingNetworkFailureError',
4644
+ 'NSCloudSharingNoPermissionError',
4645
+ 'NSCloudSharingOtherError',
4646
+ 'NSCloudSharingQuotaExceededError',
4647
+ 'NSCloudSharingTooManyParticipantsError',
4648
+ 'NSCoderErrorMaximum',
4649
+ 'NSCoderErrorMinimum',
4650
+ 'NSCoderInvalidValueError',
4651
+ 'NSCompareHashTables',
4652
+ 'NSCompareMapTables',
4653
+ 'NSCompressionErrorMaximum',
4654
+ 'NSCompressionErrorMinimum',
4655
+ 'NSCompressionFailedError',
4656
+ 'NSConvertHostDoubleToSwapped',
4657
+ 'NSConvertHostFloatToSwapped',
4658
+ 'NSConvertSwappedDoubleToHost',
4659
+ 'NSConvertSwappedFloatToHost',
4660
+ 'NSCopyMemoryPages',
4661
+ 'NSCountHashTable',
4662
+ 'NSCountMapTable',
4663
+ 'NSCreateHashTable',
4664
+ 'NSCreateMapTable',
4665
+ 'NSDeallocateMemoryPages',
4666
+ 'NSDecompressionFailedError',
4667
+ 'NSEndHashTableEnumeration',
4668
+ 'NSEndMapTableEnumeration',
4669
+ 'NSEnumerateHashTable',
4670
+ 'NSEnumerateMapTable',
4671
+ 'NSExecutableErrorMaximum',
4672
+ 'NSExecutableErrorMinimum',
4673
+ 'NSExtensionItemAttachmentsKey',
4674
+ 'NSExtensionItemAttributedContentTextKey',
4675
+ 'NSExtensionItemAttributedTitleKey',
4676
+ 'NSExtensionItemsAndErrorsKey',
4677
+ 'NSExtensionJavaScriptFinalizeArgumentKey',
4678
+ 'NSExtensionJavaScriptPreprocessingResultsKey',
4679
+ 'NSFileErrorMaximum',
4680
+ 'NSFileErrorMinimum',
4681
+ 'NSFormattingErrorMaximum',
4682
+ 'NSFormattingErrorMinimum',
4683
+ 'NSFoundationVersionNumber',
4684
+ 'NSFoundationVersionNumber10_0',
4685
+ 'NSFoundationVersionNumber10_1',
4686
+ 'NSFoundationVersionNumber10_10',
4687
+ 'NSFoundationVersionNumber10_10_1',
4688
+ 'NSFoundationVersionNumber10_10_2',
4689
+ 'NSFoundationVersionNumber10_10_3',
4690
+ 'NSFoundationVersionNumber10_10_4',
4691
+ 'NSFoundationVersionNumber10_10_5',
4692
+ 'NSFoundationVersionNumber10_10_Max',
4693
+ 'NSFoundationVersionNumber10_11',
4694
+ 'NSFoundationVersionNumber10_11_1',
4695
+ 'NSFoundationVersionNumber10_11_2',
4696
+ 'NSFoundationVersionNumber10_11_3',
4697
+ 'NSFoundationVersionNumber10_11_4',
4698
+ 'NSFoundationVersionNumber10_11_Max',
4699
+ 'NSFoundationVersionNumber10_1_1',
4700
+ 'NSFoundationVersionNumber10_1_2',
4701
+ 'NSFoundationVersionNumber10_1_3',
4702
+ 'NSFoundationVersionNumber10_1_4',
4703
+ 'NSFoundationVersionNumber10_2',
4704
+ 'NSFoundationVersionNumber10_2_1',
4705
+ 'NSFoundationVersionNumber10_2_2',
4706
+ 'NSFoundationVersionNumber10_2_3',
4707
+ 'NSFoundationVersionNumber10_2_4',
4708
+ 'NSFoundationVersionNumber10_2_5',
4709
+ 'NSFoundationVersionNumber10_2_6',
4710
+ 'NSFoundationVersionNumber10_2_7',
4711
+ 'NSFoundationVersionNumber10_2_8',
4712
+ 'NSFoundationVersionNumber10_3',
4713
+ 'NSFoundationVersionNumber10_3_1',
4714
+ 'NSFoundationVersionNumber10_3_2',
4715
+ 'NSFoundationVersionNumber10_3_3',
4716
+ 'NSFoundationVersionNumber10_3_4',
4717
+ 'NSFoundationVersionNumber10_3_5',
4718
+ 'NSFoundationVersionNumber10_3_6',
4719
+ 'NSFoundationVersionNumber10_3_7',
4720
+ 'NSFoundationVersionNumber10_3_8',
4721
+ 'NSFoundationVersionNumber10_3_9',
4722
+ 'NSFoundationVersionNumber10_4',
4723
+ 'NSFoundationVersionNumber10_4_1',
4724
+ 'NSFoundationVersionNumber10_4_10',
4725
+ 'NSFoundationVersionNumber10_4_11',
4726
+ 'NSFoundationVersionNumber10_4_2',
4727
+ 'NSFoundationVersionNumber10_4_3',
4728
+ 'NSFoundationVersionNumber10_4_4_Intel',
4729
+ 'NSFoundationVersionNumber10_4_4_PowerPC',
4730
+ 'NSFoundationVersionNumber10_4_5',
4731
+ 'NSFoundationVersionNumber10_4_6',
4732
+ 'NSFoundationVersionNumber10_4_7',
4733
+ 'NSFoundationVersionNumber10_4_8',
4734
+ 'NSFoundationVersionNumber10_4_9',
4735
+ 'NSFoundationVersionNumber10_5',
4736
+ 'NSFoundationVersionNumber10_5_1',
4737
+ 'NSFoundationVersionNumber10_5_2',
4738
+ 'NSFoundationVersionNumber10_5_3',
4739
+ 'NSFoundationVersionNumber10_5_4',
4740
+ 'NSFoundationVersionNumber10_5_5',
4741
+ 'NSFoundationVersionNumber10_5_6',
4742
+ 'NSFoundationVersionNumber10_5_7',
4743
+ 'NSFoundationVersionNumber10_5_8',
4744
+ 'NSFoundationVersionNumber10_6',
4745
+ 'NSFoundationVersionNumber10_6_1',
4746
+ 'NSFoundationVersionNumber10_6_2',
4747
+ 'NSFoundationVersionNumber10_6_3',
4748
+ 'NSFoundationVersionNumber10_6_4',
4749
+ 'NSFoundationVersionNumber10_6_5',
4750
+ 'NSFoundationVersionNumber10_6_6',
4751
+ 'NSFoundationVersionNumber10_6_7',
4752
+ 'NSFoundationVersionNumber10_6_8',
4753
+ 'NSFoundationVersionNumber10_7',
4754
+ 'NSFoundationVersionNumber10_7_1',
4755
+ 'NSFoundationVersionNumber10_7_2',
4756
+ 'NSFoundationVersionNumber10_7_3',
4757
+ 'NSFoundationVersionNumber10_7_4',
4758
+ 'NSFoundationVersionNumber10_8',
4759
+ 'NSFoundationVersionNumber10_8_1',
4760
+ 'NSFoundationVersionNumber10_8_2',
4761
+ 'NSFoundationVersionNumber10_8_3',
4762
+ 'NSFoundationVersionNumber10_8_4',
4763
+ 'NSFoundationVersionNumber10_9',
4764
+ 'NSFoundationVersionNumber10_9_1',
4765
+ 'NSFoundationVersionNumber10_9_2',
4766
+ 'NSFoundationVersionNumber_iOS_4_0',
4767
+ 'NSFoundationVersionNumber_iOS_4_1',
4768
+ 'NSFoundationVersionNumber_iOS_4_2',
4769
+ 'NSFoundationVersionNumber_iOS_4_3',
4770
+ 'NSFoundationVersionNumber_iOS_5_0',
4771
+ 'NSFoundationVersionNumber_iOS_5_1',
4772
+ 'NSFoundationVersionNumber_iOS_6_0',
4773
+ 'NSFoundationVersionNumber_iOS_6_1',
4774
+ 'NSFoundationVersionNumber_iOS_7_0',
4775
+ 'NSFoundationVersionNumber_iOS_7_1',
4776
+ 'NSFoundationVersionNumber_iOS_8_0',
4777
+ 'NSFoundationVersionNumber_iOS_8_1',
4778
+ 'NSFoundationVersionNumber_iOS_8_2',
4779
+ 'NSFoundationVersionNumber_iOS_8_3',
4780
+ 'NSFoundationVersionNumber_iOS_8_4',
4781
+ 'NSFoundationVersionNumber_iOS_8_x_Max',
4782
+ 'NSFoundationVersionNumber_iOS_9_0',
4783
+ 'NSFoundationVersionNumber_iOS_9_1',
4784
+ 'NSFoundationVersionNumber_iOS_9_2',
4785
+ 'NSFoundationVersionNumber_iOS_9_3',
4786
+ 'NSFoundationVersionNumber_iOS_9_4',
4787
+ 'NSFoundationVersionNumber_iOS_9_x_Max',
4788
+ 'NSFoundationVersionNumber_iPhoneOS_2_0',
4789
+ 'NSFoundationVersionNumber_iPhoneOS_2_1',
4790
+ 'NSFoundationVersionNumber_iPhoneOS_2_2',
4791
+ 'NSFoundationVersionNumber_iPhoneOS_3_0',
4792
+ 'NSFoundationVersionNumber_iPhoneOS_3_1',
4793
+ 'NSFoundationVersionNumber_iPhoneOS_3_2',
4794
+ 'NSFoundationVersionWithFileManagerResourceForkSupport',
4795
+ 'NSFreeHashTable',
4796
+ 'NSFreeMapTable',
4797
+ 'NSGetUncaughtExceptionHandler',
4798
+ 'NSGregorianCalendar',
4799
+ 'NSHPUXOperatingSystem',
4800
+ 'NSHashGet',
4801
+ 'NSHashInsert',
4802
+ 'NSHashInsertIfAbsent',
4803
+ 'NSHashInsertKnownAbsent',
4804
+ 'NSHashRemove',
4805
+ 'NSHashTableCopyIn',
4806
+ 'NSHashTableObjectPointerPersonality',
4807
+ 'NSHashTableStrongMemory',
4808
+ 'NSHashTableWeakMemory',
4809
+ 'NSHebrewCalendar',
4810
+ 'NSHostByteOrder',
4811
+ 'NSISO2022JPStringEncoding',
4812
+ 'NSISO8601Calendar',
4813
+ 'NSISOLatin1StringEncoding',
4814
+ 'NSISOLatin2StringEncoding',
4815
+ 'NSIndianCalendar',
4816
+ 'NSIslamicCalendar',
4817
+ 'NSIslamicCivilCalendar',
4818
+ 'NSItemProviderPreferredImageSizeKey',
4819
+ 'NSJapaneseCalendar',
4820
+ 'NSJapaneseEUCStringEncoding',
4821
+ 'NSLoadedClasses',
4822
+ 'NSLocalizedFailureErrorKey',
4823
+ 'NSLogPageSize',
4824
+ 'NSMACHOperatingSystem',
4825
+ 'NSMacOSRomanStringEncoding',
4826
+ 'NSMapGet',
4827
+ 'NSMapInsert',
4828
+ 'NSMapInsertIfAbsent',
4829
+ 'NSMapInsertKnownAbsent',
4830
+ 'NSMapMember',
4831
+ 'NSMapRemove',
4832
+ 'NSMapTableCopyIn',
4833
+ 'NSMapTableObjectPointerPersonality',
4834
+ 'NSMapTableStrongMemory',
4835
+ 'NSMapTableWeakMemory',
4836
+ 'NSMetadataItemContentTypeKey',
4837
+ 'NSMetadataItemContentTypeTreeKey',
4838
+ 'NSMetadataItemDisplayNameKey',
4839
+ 'NSMetadataItemFSContentChangeDateKey',
4840
+ 'NSMetadataItemFSCreationDateKey',
4841
+ 'NSMetadataItemFSNameKey',
4842
+ 'NSMetadataItemFSSizeKey',
4843
+ 'NSMetadataItemIsUbiquitousKey',
4844
+ 'NSMetadataItemPathKey',
4845
+ 'NSMetadataItemURLKey',
4846
+ 'NSMetadataQueryAccessibleUbiquitousExternalDocumentsScope',
4847
+ 'NSMetadataQueryResultContentRelevanceAttribute',
4848
+ 'NSMetadataQueryUbiquitousDataScope',
4849
+ 'NSMetadataQueryUbiquitousDocumentsScope',
4850
+ 'NSMetadataQueryUpdateAddedItemsKey',
4851
+ 'NSMetadataQueryUpdateChangedItemsKey',
4852
+ 'NSMetadataQueryUpdateRemovedItemsKey',
4853
+ 'NSMetadataUbiquitousItemContainerDisplayNameKey',
4854
+ 'NSMetadataUbiquitousItemDownloadRequestedKey',
4855
+ 'NSMetadataUbiquitousItemDownloadingErrorKey',
4856
+ 'NSMetadataUbiquitousItemDownloadingStatusCurrent',
4857
+ 'NSMetadataUbiquitousItemDownloadingStatusDownloaded',
4858
+ 'NSMetadataUbiquitousItemDownloadingStatusKey',
4859
+ 'NSMetadataUbiquitousItemDownloadingStatusNotDownloaded',
4860
+ 'NSMetadataUbiquitousItemHasUnresolvedConflictsKey',
4861
+ 'NSMetadataUbiquitousItemIsDownloadingKey',
4862
+ 'NSMetadataUbiquitousItemIsExternalDocumentKey',
4863
+ 'NSMetadataUbiquitousItemIsSharedKey',
4864
+ 'NSMetadataUbiquitousItemIsUploadedKey',
4865
+ 'NSMetadataUbiquitousItemIsUploadingKey',
4866
+ 'NSMetadataUbiquitousItemPercentDownloadedKey',
4867
+ 'NSMetadataUbiquitousItemPercentUploadedKey',
4868
+ 'NSMetadataUbiquitousItemURLInLocalContainerKey',
4869
+ 'NSMetadataUbiquitousItemUploadingErrorKey',
4870
+ 'NSMetadataUbiquitousSharedItemCurrentUserPermissionsKey',
4871
+ 'NSMetadataUbiquitousSharedItemCurrentUserRoleKey',
4872
+ 'NSMetadataUbiquitousSharedItemMostRecentEditorNameComponentsKey',
4873
+ 'NSMetadataUbiquitousSharedItemOwnerNameComponentsKey',
4874
+ 'NSMetadataUbiquitousSharedItemPermissionsReadOnly',
4875
+ 'NSMetadataUbiquitousSharedItemPermissionsReadWrite',
4876
+ 'NSMetadataUbiquitousSharedItemRoleOwner',
4877
+ 'NSMetadataUbiquitousSharedItemRoleParticipant',
4878
+ 'NSMultipleUnderlyingErrorsKey',
4879
+ 'NSNEXTSTEPStringEncoding',
4880
+ 'NSNextHashEnumeratorItem',
4881
+ 'NSNextMapEnumeratorPair',
4882
+ 'NSNonLossyASCIIStringEncoding',
4883
+ 'NSNonOwnedPointerHashCallBacks',
4884
+ 'NSNonOwnedPointerMapKeyCallBacks',
4885
+ 'NSNonOwnedPointerMapValueCallBacks',
4886
+ 'NSNonOwnedPointerOrNullMapKeyCallBacks',
4887
+ 'NSNonRetainedObjectHashCallBacks',
4888
+ 'NSNonRetainedObjectMapKeyCallBacks',
4889
+ 'NSNonRetainedObjectMapValueCallBacks',
4890
+ 'NSOSF1OperatingSystem',
4891
+ 'NSObjectHashCallBacks',
4892
+ 'NSObjectMapKeyCallBacks',
4893
+ 'NSObjectMapValueCallBacks',
4894
+ 'NSOpenStepRootDirectory',
4895
+ 'NSOpenStepUnicodeReservedBase',
4896
+ 'NSOwnedObjectIdentityHashCallBacks',
4897
+ 'NSOwnedPointerHashCallBacks',
4898
+ 'NSOwnedPointerMapKeyCallBacks',
4899
+ 'NSOwnedPointerMapValueCallBacks',
4900
+ 'NSPersianCalendar',
4901
+ 'NSPointerToStructHashCallBacks',
4902
+ 'NSPropertyListErrorMaximum',
4903
+ 'NSPropertyListErrorMinimum',
4904
+ 'NSProprietaryStringEncoding',
4905
+ 'NSProtocolFromString',
4906
+ 'NSRepublicOfChinaCalendar',
4907
+ 'NSResetHashTable',
4908
+ 'NSResetMapTable',
4909
+ 'NSShiftJISStringEncoding',
4910
+ 'NSSolarisOperatingSystem',
4911
+ 'NSStringFromHashTable',
4912
+ 'NSStringFromMapTable',
4913
+ 'NSStringFromProtocol',
4914
+ 'NSSunOSOperatingSystem',
4915
+ 'NSSwapBigDoubleToHost',
4916
+ 'NSSwapBigFloatToHost',
4917
+ 'NSSwapBigIntToHost',
4918
+ 'NSSwapBigLongLongToHost',
4919
+ 'NSSwapBigLongToHost',
4920
+ 'NSSwapBigShortToHost',
4921
+ 'NSSwapDouble',
4922
+ 'NSSwapFloat',
4923
+ 'NSSwapHostDoubleToBig',
4924
+ 'NSSwapHostDoubleToLittle',
4925
+ 'NSSwapHostFloatToBig',
4926
+ 'NSSwapHostFloatToLittle',
4927
+ 'NSSwapHostIntToBig',
4928
+ 'NSSwapHostIntToLittle',
4929
+ 'NSSwapHostLongLongToBig',
4930
+ 'NSSwapHostLongLongToLittle',
4931
+ 'NSSwapHostLongToBig',
4932
+ 'NSSwapHostLongToLittle',
4933
+ 'NSSwapHostShortToBig',
4934
+ 'NSSwapHostShortToLittle',
4935
+ 'NSSwapInt',
4936
+ 'NSSwapLittleDoubleToHost',
4937
+ 'NSSwapLittleFloatToHost',
4938
+ 'NSSwapLittleIntToHost',
4939
+ 'NSSwapLittleLongLongToHost',
4940
+ 'NSSwapLittleLongToHost',
4941
+ 'NSSwapLittleShortToHost',
4942
+ 'NSSwapLong',
4943
+ 'NSSwapLongLong',
4944
+ 'NSSwapShort',
4945
+ 'NSSymbolStringEncoding',
4946
+ 'NSTextCheckingAllCustomTypes',
4947
+ 'NSTextCheckingAllSystemTypes',
4948
+ 'NSTextCheckingAllTypes',
4949
+ 'NSURLAuthenticationMethodHTMLForm',
4950
+ 'NSURLAuthenticationMethodNTLM',
4951
+ 'NSURLAuthenticationMethodNegotiate',
4952
+ 'NSURLCredentialStorageRemoveSynchronizableCredentials',
4953
+ 'NSURLErrorFileOutsideSafeArea',
4954
+ 'NSURLFileScheme',
4955
+ 'NSURLProtectionSpaceFTP',
4956
+ 'NSURLProtectionSpaceFTPProxy',
4957
+ 'NSURLProtectionSpaceHTTP',
4958
+ 'NSURLProtectionSpaceHTTPProxy',
4959
+ 'NSURLProtectionSpaceHTTPS',
4960
+ 'NSURLProtectionSpaceHTTPSProxy',
4961
+ 'NSURLProtectionSpaceSOCKSProxy',
4962
+ 'NSURLSessionDownloadTaskResumeData',
4963
+ 'NSURLSessionTransferSizeUnknown',
4964
+ 'NSURLSessionUploadTaskResumeData',
4965
+ 'NSUTF16BigEndianStringEncoding',
4966
+ 'NSUTF16LittleEndianStringEncoding',
4967
+ 'NSUTF16StringEncoding',
4968
+ 'NSUTF32BigEndianStringEncoding',
4969
+ 'NSUTF32LittleEndianStringEncoding',
4970
+ 'NSUTF32StringEncoding',
4971
+ 'NSUTF8StringEncoding',
4972
+ 'NSUbiquitousFileErrorMaximum',
4973
+ 'NSUbiquitousFileErrorMinimum',
4974
+ 'NSUbiquitousKeyValueStoreAccountChange',
4975
+ 'NSUbiquitousKeyValueStoreChangeReasonKey',
4976
+ 'NSUbiquitousKeyValueStoreChangedKeysKey',
4977
+ 'NSUbiquitousKeyValueStoreInitialSyncChange',
4978
+ 'NSUbiquitousKeyValueStoreQuotaViolationChange',
4979
+ 'NSUbiquitousKeyValueStoreServerChange',
4980
+ 'NSUndefinedDateComponent',
4981
+ 'NSUndoCloseGroupingRunLoopOrdering',
4982
+ 'NSUndoManagerGroupIsDiscardableKey',
4983
+ 'NSUnicodeStringEncoding',
4984
+ 'NSUserActivityErrorMaximum',
4985
+ 'NSUserActivityErrorMinimum',
4986
+ 'NSUserActivityTypeBrowsingWeb',
4987
+ 'NSValidationErrorMaximum',
4988
+ 'NSValidationErrorMinimum',
4989
+ 'NSWindows95OperatingSystem',
4990
+ 'NSWindowsCP1250StringEncoding',
4991
+ 'NSWindowsCP1251StringEncoding',
4992
+ 'NSWindowsCP1252StringEncoding',
4993
+ 'NSWindowsCP1253StringEncoding',
4994
+ 'NSWindowsCP1254StringEncoding',
4995
+ 'NSWindowsNTOperatingSystem',
4996
+ 'NSWrapCalendarComponents',
4997
+ 'NSXPCConnectionCodeSigningRequirementFailure',
4998
+ 'NSXPCConnectionErrorMaximum',
4999
+ 'NSXPCConnectionErrorMinimum',
5000
+ 'NS_BigEndian',
5001
+ 'NS_LittleEndian',
5002
+ 'NS_UnknownByteOrder',
5003
+ 'kCFStringEncodingASCII',
5004
+ ])
5005
+
5006
+ const CORE_FOUNDATION_OVERLAY_GLOBALS = new Set([
5007
+ 'kCFCoreFoundationVersionNumber10_0',
5008
+ 'kCFCoreFoundationVersionNumber10_0_3',
5009
+ 'kCFCoreFoundationVersionNumber10_1',
5010
+ 'kCFCoreFoundationVersionNumber10_10',
5011
+ 'kCFCoreFoundationVersionNumber10_10_1',
5012
+ 'kCFCoreFoundationVersionNumber10_10_2',
5013
+ 'kCFCoreFoundationVersionNumber10_10_3',
5014
+ 'kCFCoreFoundationVersionNumber10_10_4',
5015
+ 'kCFCoreFoundationVersionNumber10_10_5',
5016
+ 'kCFCoreFoundationVersionNumber10_10_Max',
5017
+ 'kCFCoreFoundationVersionNumber10_11',
5018
+ 'kCFCoreFoundationVersionNumber10_11_1',
5019
+ 'kCFCoreFoundationVersionNumber10_11_2',
5020
+ 'kCFCoreFoundationVersionNumber10_11_3',
5021
+ 'kCFCoreFoundationVersionNumber10_11_4',
5022
+ 'kCFCoreFoundationVersionNumber10_11_Max',
5023
+ 'kCFCoreFoundationVersionNumber10_1_1',
5024
+ 'kCFCoreFoundationVersionNumber10_1_2',
5025
+ 'kCFCoreFoundationVersionNumber10_1_3',
5026
+ 'kCFCoreFoundationVersionNumber10_1_4',
5027
+ 'kCFCoreFoundationVersionNumber10_2',
5028
+ 'kCFCoreFoundationVersionNumber10_2_1',
5029
+ 'kCFCoreFoundationVersionNumber10_2_2',
5030
+ 'kCFCoreFoundationVersionNumber10_2_3',
5031
+ 'kCFCoreFoundationVersionNumber10_2_4',
5032
+ 'kCFCoreFoundationVersionNumber10_2_5',
5033
+ 'kCFCoreFoundationVersionNumber10_2_6',
5034
+ 'kCFCoreFoundationVersionNumber10_2_7',
5035
+ 'kCFCoreFoundationVersionNumber10_2_8',
5036
+ 'kCFCoreFoundationVersionNumber10_3',
5037
+ 'kCFCoreFoundationVersionNumber10_3_1',
5038
+ 'kCFCoreFoundationVersionNumber10_3_2',
5039
+ 'kCFCoreFoundationVersionNumber10_3_3',
5040
+ 'kCFCoreFoundationVersionNumber10_3_4',
5041
+ 'kCFCoreFoundationVersionNumber10_3_5',
5042
+ 'kCFCoreFoundationVersionNumber10_3_6',
5043
+ 'kCFCoreFoundationVersionNumber10_3_7',
5044
+ 'kCFCoreFoundationVersionNumber10_3_8',
5045
+ 'kCFCoreFoundationVersionNumber10_3_9',
5046
+ 'kCFCoreFoundationVersionNumber10_4',
5047
+ 'kCFCoreFoundationVersionNumber10_4_1',
5048
+ 'kCFCoreFoundationVersionNumber10_4_10',
5049
+ 'kCFCoreFoundationVersionNumber10_4_11',
5050
+ 'kCFCoreFoundationVersionNumber10_4_2',
5051
+ 'kCFCoreFoundationVersionNumber10_4_3',
5052
+ 'kCFCoreFoundationVersionNumber10_4_4_Intel',
5053
+ 'kCFCoreFoundationVersionNumber10_4_4_PowerPC',
5054
+ 'kCFCoreFoundationVersionNumber10_4_5_Intel',
5055
+ 'kCFCoreFoundationVersionNumber10_4_5_PowerPC',
5056
+ 'kCFCoreFoundationVersionNumber10_4_6_Intel',
5057
+ 'kCFCoreFoundationVersionNumber10_4_6_PowerPC',
5058
+ 'kCFCoreFoundationVersionNumber10_4_7',
5059
+ 'kCFCoreFoundationVersionNumber10_4_8',
5060
+ 'kCFCoreFoundationVersionNumber10_4_9',
5061
+ 'kCFCoreFoundationVersionNumber10_5',
5062
+ 'kCFCoreFoundationVersionNumber10_5_1',
5063
+ 'kCFCoreFoundationVersionNumber10_5_2',
5064
+ 'kCFCoreFoundationVersionNumber10_5_3',
5065
+ 'kCFCoreFoundationVersionNumber10_5_4',
5066
+ 'kCFCoreFoundationVersionNumber10_5_5',
5067
+ 'kCFCoreFoundationVersionNumber10_5_6',
5068
+ 'kCFCoreFoundationVersionNumber10_5_7',
5069
+ 'kCFCoreFoundationVersionNumber10_5_8',
5070
+ 'kCFCoreFoundationVersionNumber10_6',
5071
+ 'kCFCoreFoundationVersionNumber10_6_1',
5072
+ 'kCFCoreFoundationVersionNumber10_6_2',
5073
+ 'kCFCoreFoundationVersionNumber10_6_3',
5074
+ 'kCFCoreFoundationVersionNumber10_6_4',
5075
+ 'kCFCoreFoundationVersionNumber10_6_5',
5076
+ 'kCFCoreFoundationVersionNumber10_6_6',
5077
+ 'kCFCoreFoundationVersionNumber10_6_7',
5078
+ 'kCFCoreFoundationVersionNumber10_6_8',
5079
+ 'kCFCoreFoundationVersionNumber10_7',
5080
+ 'kCFCoreFoundationVersionNumber10_7_1',
5081
+ 'kCFCoreFoundationVersionNumber10_7_2',
5082
+ 'kCFCoreFoundationVersionNumber10_7_3',
5083
+ 'kCFCoreFoundationVersionNumber10_7_4',
5084
+ 'kCFCoreFoundationVersionNumber10_7_5',
5085
+ 'kCFCoreFoundationVersionNumber10_8',
5086
+ 'kCFCoreFoundationVersionNumber10_8_1',
5087
+ 'kCFCoreFoundationVersionNumber10_8_2',
5088
+ 'kCFCoreFoundationVersionNumber10_8_3',
5089
+ 'kCFCoreFoundationVersionNumber10_8_4',
5090
+ 'kCFCoreFoundationVersionNumber10_9',
5091
+ 'kCFCoreFoundationVersionNumber10_9_1',
5092
+ 'kCFCoreFoundationVersionNumber10_9_2',
5093
+ 'kCFCoreFoundationVersionNumber_iOS_4_0',
5094
+ 'kCFCoreFoundationVersionNumber_iOS_4_1',
5095
+ 'kCFCoreFoundationVersionNumber_iOS_4_2',
5096
+ 'kCFCoreFoundationVersionNumber_iOS_4_3',
5097
+ 'kCFCoreFoundationVersionNumber_iOS_5_0',
5098
+ 'kCFCoreFoundationVersionNumber_iOS_5_1',
5099
+ 'kCFCoreFoundationVersionNumber_iOS_6_0',
5100
+ 'kCFCoreFoundationVersionNumber_iOS_6_1',
5101
+ 'kCFCoreFoundationVersionNumber_iOS_7_0',
5102
+ 'kCFCoreFoundationVersionNumber_iOS_7_1',
5103
+ 'kCFCoreFoundationVersionNumber_iOS_8_0',
5104
+ 'kCFCoreFoundationVersionNumber_iOS_8_1',
5105
+ 'kCFCoreFoundationVersionNumber_iOS_8_2',
5106
+ 'kCFCoreFoundationVersionNumber_iOS_8_3',
5107
+ 'kCFCoreFoundationVersionNumber_iOS_8_4',
5108
+ 'kCFCoreFoundationVersionNumber_iOS_8_x_Max',
5109
+ 'kCFCoreFoundationVersionNumber_iOS_9_0',
5110
+ 'kCFCoreFoundationVersionNumber_iOS_9_1',
5111
+ 'kCFCoreFoundationVersionNumber_iOS_9_2',
5112
+ 'kCFCoreFoundationVersionNumber_iOS_9_3',
5113
+ 'kCFCoreFoundationVersionNumber_iOS_9_4',
5114
+ 'kCFCoreFoundationVersionNumber_iOS_9_x_Max',
5115
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_2_0',
5116
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_2_1',
5117
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_2_2',
5118
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_3_0',
5119
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_3_1',
5120
+ 'kCFCoreFoundationVersionNumber_iPhoneOS_3_2',
5121
+ ])
5122
+
5123
+ // the Darwin CoreFoundation overlay exposes Foundation's geometry identities.
5124
+ const CORE_FOUNDATION_GEOMETRY_TYPES = new Set([
5125
+ 'CGFloat',
5126
+ 'CGPoint',
5127
+ 'CGSize',
5128
+ 'CGRect',
5129
+ 'CGRectEdge',
5130
+ ])
5131
+
5132
+ const CORE_FOUNDATION_GRAPHICS_TYPES = new Set([
5133
+ 'CGAffineTransform',
5134
+ 'CGAffineTransformComponents',
5135
+ 'CGVector',
5136
+ ])
5137
+
5138
+ // scoped imports select native CF handles over overlay bridge aliases without
5139
+ // rewriting references or changing the overlay's measured storage contracts.
5140
+ const CORE_FOUNDATION_HANDLE_IMPORTS = [
5141
+ 'CFAllocator',
5142
+ 'CFArray',
5143
+ 'CFAttributedString',
5144
+ 'CFBoolean',
5145
+ 'CFData',
5146
+ 'CFDate',
5147
+ 'CFDictionary',
5148
+ 'CFError',
5149
+ 'CFMutableData',
5150
+ 'CFNumber',
5151
+ 'CFSet',
5152
+ 'CFString',
5153
+ 'CFURL',
5154
+ ]
5155
+ .map((name) => `import class CoreFoundation.${name}`)
5156
+ .concat([
5157
+ 'import typealias CoreFoundation.CFPropertyList',
5158
+ 'import typealias CoreFoundation.CFTypeRef',
5159
+ 'import CoreGraphics',
5160
+ ])
5161
+ .join('; ')
5162
+
4347
5163
  export function swiftSourceAsIOS(
4348
5164
  original: string,
4349
5165
  extraObjCExtensions?: Map<string, Set<string>>,
@@ -4409,25 +5225,80 @@ export function swiftSourceAsIOS(
4409
5225
  if (imported) {
4410
5226
  out +=
4411
5227
  conditioned.slice(copied, at) + `import ${imported[1]}`.padEnd(imported[0].length)
5228
+ if (imported[1] === 'CoreFoundation') out += `; ${CORE_FOUNDATION_HANDLE_IMPORTS}`
4412
5229
  copied = at + imported[0].length
4413
5230
  continue
4414
5231
  }
5232
+ const coreFoundationImport = /^import\s+CoreFoundation\b/.exec(rest)
5233
+ if (coreFoundationImport) {
5234
+ out +=
5235
+ conditioned.slice(copied, at) +
5236
+ coreFoundationImport[0] +
5237
+ `; ${CORE_FOUNDATION_HANDLE_IMPORTS}`
5238
+ copied = at + coreFoundationImport[0].length
5239
+ continue
5240
+ }
4415
5241
  if (/^NSClassFromString\b/.test(rest)) {
4416
5242
  out += conditioned.slice(copied, at) + '_peachClassFromString'
4417
5243
  copied = at + 'NSClassFromString'.length
4418
5244
  continue
4419
5245
  }
4420
- // darwin exports these types from Foundation; wasm leaves unavailable
4421
- // aliases there and their implementation lives in networking.
4422
- if (
4423
- /^Foundation\s*\.\s*(?:HTTPURLResponse|URLAuthenticationChallenge|URLAuthenticationChallengeSender|URLCredential|URLProtectionSpace|URLRequest|URLResponse|URLSession)\b/.test(
4424
- rest,
5246
+ // darwin exposes these names through Foundation; the guest keeps networking
5247
+ // and overlay declarations in their owning modules.
5248
+ const foundationMember =
5249
+ /^Foundation\s*\.\s*(?:`([A-Za-z_]\w*)`|([A-Za-z_]\w*)\b)/.exec(rest)
5250
+ const foundationName = foundationMember?.[1] ?? foundationMember?.[2]
5251
+ let foundationOwner: string | undefined
5252
+ if (foundationName !== undefined) {
5253
+ if (
5254
+ foundationName === 'NSClassFromString' ||
5255
+ foundationName === 'NSKeyValueChange' ||
5256
+ foundationName === 'NSKeyValueObservedChange' ||
5257
+ foundationName === 'NSKeyValueObservation'
4425
5258
  )
4426
- ) {
4427
- out += conditioned.slice(copied, at) + 'FoundationNetworking'
5259
+ foundationOwner = 'PeachObjC'
5260
+ else if (foundationName === 'DispatchData') foundationOwner = 'Dispatch'
5261
+ else if (FOUNDATION_NETWORKING_TYPES.has(foundationName))
5262
+ foundationOwner = 'FoundationNetworking'
5263
+ else if (
5264
+ FOUNDATION_OVERLAY_TYPES.has(foundationName) ||
5265
+ FOUNDATION_OVERLAY_GLOBALS.has(foundationName) ||
5266
+ CORE_FOUNDATION_OVERLAY_GLOBALS.has(foundationName)
5267
+ )
5268
+ foundationOwner = 'PeachFoundation'
5269
+ }
5270
+ if (foundationOwner !== undefined) {
5271
+ out += conditioned.slice(copied, at) + foundationOwner
4428
5272
  copied = at + 'Foundation'.length
4429
5273
  continue
4430
5274
  }
5275
+ const coreFoundationMember =
5276
+ /^CoreFoundation\s*\.\s*(?:`([A-Za-z_]\w*)`|([A-Za-z_]\w*)\b)/.exec(rest)
5277
+ const coreFoundationName = coreFoundationMember?.[1] ?? coreFoundationMember?.[2]
5278
+ if (
5279
+ coreFoundationName !== undefined &&
5280
+ CORE_FOUNDATION_OVERLAY_GLOBALS.has(coreFoundationName)
5281
+ ) {
5282
+ out += conditioned.slice(copied, at) + 'PeachFoundation'
5283
+ copied = at + 'CoreFoundation'.length
5284
+ continue
5285
+ }
5286
+ if (
5287
+ coreFoundationName !== undefined &&
5288
+ CORE_FOUNDATION_GEOMETRY_TYPES.has(coreFoundationName)
5289
+ ) {
5290
+ out += conditioned.slice(copied, at) + 'Foundation'
5291
+ copied = at + 'CoreFoundation'.length
5292
+ continue
5293
+ }
5294
+ if (
5295
+ coreFoundationName !== undefined &&
5296
+ CORE_FOUNDATION_GRAPHICS_TYPES.has(coreFoundationName)
5297
+ ) {
5298
+ out += conditioned.slice(copied, at) + 'CoreGraphics'
5299
+ copied = at + 'CoreFoundation'.length
5300
+ continue
5301
+ }
4431
5302
  if (rest.startsWith('class')) {
4432
5303
  const declared = CLASS_BASE.exec(rest)
4433
5304
  if (declared && reusableViews.has(declared[2]!.split('.').pop()!)) {
@@ -4693,7 +5564,9 @@ function swiftCodeScan(source: string): {
4693
5564
  ? 'NSClassFromString'
4694
5565
  : source.startsWith('Foundation', i)
4695
5566
  ? 'Foundation'
4696
- : null
5567
+ : source.startsWith('CoreFoundation', i)
5568
+ ? 'CoreFoundation'
5569
+ : null
4697
5570
  if (
4698
5571
  keyword &&
4699
5572
  !/[\w$]/.test(source[i - 1] ?? '') &&
@@ -5219,18 +6092,29 @@ export function compileSwiftProjectUnit(
5219
6092
  multi: compileTargets(input).length > 0,
5220
6093
  }
5221
6094
  const hash = swiftArtifactHash(input, options.release, moduleRoot)
6095
+ const sharedRoot = path.join(rnxHomeDir(), 'cache', 'swift-projects', hash)
6096
+ const report = (message: string) =>
6097
+ console.error(`[swift-project ${hash.slice(0, 16)}] ${message}`)
6098
+ report('checking verified artifacts')
5222
6099
  return serialize(
5223
6100
  root,
5224
6101
  async () => {
5225
6102
  // reuse one verified result across server restarts before admission or
5226
6103
  // swiftpm. the address covers sources, framework inputs and toolchain.
5227
6104
  const retained = retainedArtifacts.get(root)?.find((old) => old.hash === hash)
5228
- if (retained) return retain(root, retained)
5229
- const cached = readCompiledArtifact(path.join(root, 'artifact'), hash)
5230
- if (cached) return retain(root, cached)
5231
- // an admitted mac slot already holds the build lock and the pinned
5232
- // toolchain, so it compiles here. a bare CONTRAST_REMOTE_BUILD value is
5233
- // only an inherited marker and still dispatches through admission.
6105
+ if (retained) {
6106
+ report('reusing memory artifact')
6107
+ return retain(root, retained)
6108
+ }
6109
+ const cached = readCompiledArtifact(path.join(sharedRoot, 'artifact'), hash)
6110
+ const previous = cached ?? readCompiledArtifact(path.join(root, 'artifact'), hash)
6111
+ if (previous) {
6112
+ if (!cached) saveCompiledArtifact(sharedRoot, previous)
6113
+ report('reusing verified disk artifact')
6114
+ return retain(root, previous)
6115
+ }
6116
+ // a mac builder with a live destination grant compiles here. inherited
6117
+ // transport markers alone still dispatch through admission.
5234
6118
  if (
5235
6119
  process.platform === 'darwin' &&
5236
6120
  process.env.TM_SESSION &&
@@ -5249,11 +6133,18 @@ export function compileSwiftProjectUnit(
5249
6133
  hash,
5250
6134
  release: options.release,
5251
6135
  timeoutMs: options.timeoutMs,
5252
- buildKey: createHash('sha256').update(root).digest('hex').slice(0, 32),
6136
+ // the builder's swiftpm tree holds the sootsim-swift objects, which
6137
+ // depend on the toolchain and sdk and not on the caller's checkout
6138
+ // path, so every caller shares one warm tree per toolchain.
6139
+ buildKey: createHash('sha256')
6140
+ .update(`${options.release}\0${swiftModuleSdk(moduleRoot).wasmSdkId}`)
6141
+ .digest('hex')
6142
+ .slice(0, 32),
5253
6143
  }),
5254
6144
  )
5255
6145
  try {
5256
6146
  const repo = path.resolve(moduleRoot, '../..')
6147
+ report('requesting builder admission or cached result')
5257
6148
  await runCompiler(
5258
6149
  'bun',
5259
6150
  [
@@ -5282,6 +6173,8 @@ export function compileSwiftProjectUnit(
5282
6173
  )
5283
6174
  }
5284
6175
  saveCompiledArtifact(root, artifact)
6176
+ saveCompiledArtifact(sharedRoot, artifact)
6177
+ report('builder artifact verified')
5285
6178
  return retain(root, artifact)
5286
6179
  } finally {
5287
6180
  rmSync(requestRoot, { recursive: true, force: true })
@@ -5294,6 +6187,7 @@ export function compileSwiftProjectUnit(
5294
6187
  `swift-compile: no swift.org toolchain at ${options.toolchainBin}; install ${options.release} and its matching wasm sdk`,
5295
6188
  )
5296
6189
  }
6190
+ report('preparing compiler plugins')
5297
6191
  const macroPlugins = await ensureMacroPlugins(
5298
6192
  moduleRoot,
5299
6193
  options.toolchainBin,
@@ -5306,12 +6200,14 @@ export function compileSwiftProjectUnit(
5306
6200
  const icu = swiftIcuAsset(options.toolchainBin, sdk)
5307
6201
  const buildArgs = [
5308
6202
  'build',
6203
+ ...swiftPackageCacheOptions(),
5309
6204
  '--build-system',
5310
6205
  'native',
5311
6206
  '-j',
5312
6207
  BUILD_JOBS,
5313
6208
  '--package-path',
5314
6209
  root,
6210
+ ...swiftSdkOptions(),
5315
6211
  '--swift-sdk',
5316
6212
  sdk,
5317
6213
  '-c',
@@ -5349,8 +6245,9 @@ export function compileSwiftProjectUnit(
5349
6245
  timeout: options.timeoutMs,
5350
6246
  signal: options.signal,
5351
6247
  }
6248
+ report('compiling and linking Swift modules')
5352
6249
  try {
5353
- await runCompiler(swift, buildArgs, buildOptions)
6250
+ await runCompiler(swift, buildArgs, buildOptions, true)
5354
6251
  } catch (error) {
5355
6252
  const output = outputOf(error)
5356
6253
  const moduleCache = path.join(
@@ -5366,7 +6263,7 @@ export function compileSwiftProjectUnit(
5366
6263
  ) {
5367
6264
  rmSync(moduleCache, { recursive: true, force: true })
5368
6265
  try {
5369
- await runCompiler(swift, buildArgs, buildOptions)
6266
+ await runCompiler(swift, buildArgs, buildOptions, true)
5370
6267
  } catch (retryError) {
5371
6268
  throw new Error(
5372
6269
  projectDiagnostic(outputOf(retryError), layout, input.files),
@@ -5387,6 +6284,8 @@ export function compileSwiftProjectUnit(
5387
6284
  icu: await icu,
5388
6285
  }
5389
6286
  saveCompiledArtifact(root, artifact)
6287
+ saveCompiledArtifact(sharedRoot, artifact)
6288
+ report('compiled artifact verified')
5390
6289
  return retain(root, artifact)
5391
6290
  },
5392
6291
  options.signal,