peachsim 0.1.2219 → 0.1.2221

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 (93) hide show
  1. package/cli/commands/flow.ts +4 -0
  2. package/cli/commands/inspect.ts +4 -4
  3. package/cli/maestro-compare.ts +37 -26
  4. package/dist-lib/agent-daemon-client.cjs +1 -1
  5. package/dist-lib/agent-events.cjs +1 -1
  6. package/dist-lib/attached-projects.cjs +1 -1
  7. package/dist-lib/auth/shared-session.cjs +1 -1
  8. package/dist-lib/backend-origin.cjs +1 -1
  9. package/dist-lib/beta.cjs +1 -1
  10. package/dist-lib/beta.mjs +1 -1
  11. package/dist-lib/bridge-constants.cjs +1 -1
  12. package/dist-lib/bridge-contract-input.cjs +1 -1
  13. package/dist-lib/bridge-contract-input.mjs +1 -1
  14. package/dist-lib/bridge-contract.cjs +1 -1
  15. package/dist-lib/bridge-contract.mjs +1 -1
  16. package/dist-lib/bundle-channel.cjs +117 -36
  17. package/dist-lib/capture-contract.cjs +1 -1
  18. package/dist-lib/capture-contract.mjs +1 -1
  19. package/dist-lib/cloud-contract.cjs +1 -1
  20. package/dist-lib/cloud-contract.mjs +1 -1
  21. package/dist-lib/cloud-test-args.cjs +1 -1
  22. package/dist-lib/cloud-test-args.mjs +1 -1
  23. package/dist-lib/cloud.cjs +1 -1
  24. package/dist-lib/cloud.mjs +1 -1
  25. package/dist-lib/config.cjs +1 -1
  26. package/dist-lib/config.mjs +1 -1
  27. package/dist-lib/detox/index.cjs +1 -1
  28. package/dist-lib/dev-bundle-resolution.cjs +1 -1
  29. package/dist-lib/expo-swift-bundle.cjs +114 -33
  30. package/dist-lib/expo-swift-metadata.cjs +1 -1
  31. package/dist-lib/expo-swift-metadata.mjs +1 -1
  32. package/dist-lib/home-paths.cjs +1 -1
  33. package/dist-lib/host/bridge-host.cjs +115 -34
  34. package/dist-lib/host/fetch-proxy-handler.cjs +3 -3
  35. package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
  36. package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
  37. package/dist-lib/host/replacement-module-handler.cjs +1 -1
  38. package/dist-lib/host/websocket-proxy.cjs +1 -1
  39. package/dist-lib/index.cjs +3 -3
  40. package/dist-lib/jump-to-source-babel.cjs +1 -1
  41. package/dist-lib/jump-to-source-native.cjs +1 -1
  42. package/dist-lib/kotlin-host.cjs +1 -1
  43. package/dist-lib/menu.cjs +1 -1
  44. package/dist-lib/menu.mjs +1 -1
  45. package/dist-lib/metro-fingerprint-registry.cjs +1 -1
  46. package/dist-lib/metro-fingerprint-registry.mjs +1 -1
  47. package/dist-lib/metro-production-bundle.cjs +1 -1
  48. package/dist-lib/metro-production-bundle.mjs +1 -1
  49. package/dist-lib/metro.cjs +3 -3
  50. package/dist-lib/native-app-identity-project.cjs +2 -2
  51. package/dist-lib/native-app-identity-project.mjs +2 -2
  52. package/dist-lib/native-app-identity.cjs +1 -1
  53. package/dist-lib/native-app-identity.mjs +1 -1
  54. package/dist-lib/native-firebase-metadata.cjs +1 -1
  55. package/dist-lib/native-firebase-metadata.mjs +1 -1
  56. package/dist-lib/pdfium-raster.cjs +1 -1
  57. package/dist-lib/pdfium-raster.mjs +1 -1
  58. package/dist-lib/plist.cjs +1 -1
  59. package/dist-lib/plist.mjs +1 -1
  60. package/dist-lib/profiles.cjs +1 -1
  61. package/dist-lib/public-brand.cjs +1 -1
  62. package/dist-lib/public-origins-lib-esm.json +24 -24
  63. package/dist-lib/public-origins-lib.json +53 -53
  64. package/dist-lib/react-native-host-modules.cjs +1 -1
  65. package/dist-lib/react-native-host-modules.mjs +1 -1
  66. package/dist-lib/reap-browser.cjs +1 -1
  67. package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
  68. package/dist-lib/sdk.cjs +1 -1
  69. package/dist-lib/sdk.mjs +1 -1
  70. package/dist-lib/skills.cjs +115 -34
  71. package/dist-lib/swift-compile.cjs +39 -21
  72. package/dist-lib/swift-compile.mjs +39 -21
  73. package/dist-lib/swift-package.cjs +1 -1
  74. package/dist-lib/swift-package.mjs +1 -1
  75. package/dist-lib/swift-submit.cjs +1 -1
  76. package/dist-lib/swift-submit.mjs +1 -1
  77. package/dist-lib/swift-toolchain.cjs +1 -1
  78. package/dist-lib/swift.cjs +1 -1
  79. package/dist-lib/vite-swift.cjs +112 -31
  80. package/dist-lib/vite.cjs +3 -3
  81. package/dist-lib/worklet-executable.cjs +1 -1
  82. package/dist-lib/worklet-executable.mjs +1 -1
  83. package/dist-types/packages/peach-engine/src/render-worker/compositor-protocol.d.ts +1 -0
  84. package/package.json +1 -1
  85. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Headers/NSLayoutConstraint.h +1 -8
  86. package/sdk/ios/System/Library/Frameworks/UIKit.framework/Modules/module.modulemap +1 -0
  87. package/sdk/ios/System/Library/Frameworks/UIKitTypes.framework/Headers/UIKitTypes.h +1 -0
  88. package/sdk/ios/System/Library/Frameworks/UIKitTypes.framework/Headers/UILayoutPriority.h +11 -0
  89. package/src/swift-compile.ts +43 -23
  90. package/src/swift-host.ts +84 -2
  91. package/src/swift-objc-import.ts +4 -0
  92. package/src/swift-packages.ts +19 -10
  93. package/src/swift-standins.ts +1 -1
@@ -0,0 +1,11 @@
1
+ #pragma once
2
+ #import <Foundation/Foundation.h>
3
+
4
+ typedef float UILayoutPriority NS_TYPED_EXTENSIBLE_ENUM API_UNAVAILABLE(watchos);
5
+ static const UILayoutPriority UILayoutPriorityRequired API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos) = 1000; // A required constraint. Do not exceed this.
6
+ static const UILayoutPriority UILayoutPriorityDefaultHigh API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos) = 750; // This is the priority level with which a button resists compressing its content.
7
+ static const UILayoutPriority UILayoutPriorityDragThatCanResizeScene API_AVAILABLE(macCatalyst(13.0)) API_UNAVAILABLE(watchos) = 510; // This is the appropriate priority level for a drag that may end up resizing the window's scene.
8
+ static const UILayoutPriority UILayoutPrioritySceneSizeStayPut API_AVAILABLE(macCatalyst(13.0)) API_UNAVAILABLE(watchos) = 500; // This is the priority level at which the window's scene prefers to stay the same size. It's generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower.
9
+ static const UILayoutPriority UILayoutPriorityDragThatCannotResizeScene API_AVAILABLE(macCatalyst(13.0)) API_UNAVAILABLE(watchos) = 490; // This is the priority level at which a split view divider, say, is dragged. It won't resize the window's scene.
10
+ static const UILayoutPriority UILayoutPriorityDefaultLow API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos) = 250; // This is the priority level at which a button hugs its contents horizontally.
11
+ static const UILayoutPriority UILayoutPriorityFittingSizeLevel API_AVAILABLE(ios(6.0)) API_UNAVAILABLE(watchos) = 50; // When you send -[UIView systemLayoutSizeFittingSize:], the size fitting most closely to the target size (the argument) is computed. UILayoutPriorityFittingSizeLevel is the priority level with which the view wants to conform to the target size in that computation. It's quite low. It is generally not appropriate to make a constraint at exactly this priority. You want to be higher or lower.
@@ -424,11 +424,14 @@ export function swiftModuleInterface(
424
424
  // the compiler imports the module that defines a type, and UIKit's declarations
425
425
  // live in UIKitCore/UIKitText, which only the umbrella UIKit module represents
426
426
  // to clang. CoreFoundation's CGFloat lives in the Swift CoreFoundation overlay,
427
- // while clang's Foundation umbrella provides CoreFoundation/CoreFoundation.h.
427
+ // while clang's Foundation umbrella also owns networking class declarations.
428
428
  const clangInterfaceHeader = (header: string): string =>
429
429
  header
430
430
  .replace(/^@import (?:UIKitCore|UIKitText);$/gm, '@import UIKit;')
431
- .replace(/^@import CoreFoundation;$/gm, '@import Foundation;')
431
+ .replace(
432
+ /^@import (?:CoreFoundation|FoundationNetworking);$/gm,
433
+ '@import Foundation;',
434
+ )
432
435
  .replace(/\b_TtC10Foundation\d+(NS\w+)\b/g, '$1')
433
436
  .replace(/\b__attribute__\(\(objc_subclassing_restricted\)\)\s*/g, '')
434
437
 
@@ -1853,6 +1856,7 @@ export function emitSwiftPackageManifest(args: {
1853
1856
  nativeFlags?: Map<string, string[]>
1854
1857
  nativeImportFlags?: Map<string, string[]>
1855
1858
  nativeHeaderFlags?: string[]
1859
+ nativeSwiftHeaderMaps?: ReadonlyMap<string, string>
1856
1860
  nativeHeaderDeclarations?: Readonly<Record<string, readonly string[]>>
1857
1861
  objcImplementationModules?: Set<string>
1858
1862
  siblings: Map<string, string[]>
@@ -2163,6 +2167,11 @@ export function emitSwiftPackageManifest(args: {
2163
2167
  includeImportContext(dependency)
2164
2168
  const importedNativeFlags = [
2165
2169
  ...(args.nativeImportFlags?.get(target.name) ?? []),
2170
+ ...[...importContext].flatMap((name) => {
2171
+ const map =
2172
+ name === target.name ? undefined : args.nativeSwiftHeaderMaps?.get(name)
2173
+ return map ? ['-fmodule-map-file=' + map] : []
2174
+ }),
2166
2175
  ...[...importContext].flatMap((name) => args.native?.get(name)?.importFlags ?? []),
2167
2176
  ...[...importContext].flatMap((name) => {
2168
2177
  const flags = targets.find((target) => target.name === name)?.swiftFlags ?? []
@@ -4610,6 +4619,7 @@ export function writeSwiftProject(
4610
4619
  // declarations are imported before swift can emit the header that native
4611
4620
  // implementations consume. give those implementations a downstream target.
4612
4621
  const importModuleMaps = new Map<string, string>()
4622
+ const sourceModuleMaps = new Map<string, { path: string; contents: string }>()
4613
4623
  const generatedModuleMaps: { output: string; module: string; published: string }[] = []
4614
4624
  for (const target of targets) {
4615
4625
  const prefix = target.path === '.' ? '' : `${target.path}/`
@@ -4938,6 +4948,10 @@ export function writeSwiftProject(
4938
4948
  stageTargetFile(target.name, path.join(layout.root, modulemap), moduleContents, {
4939
4949
  allowExisting: true,
4940
4950
  })
4951
+ sourceModuleMaps.set(swiftTargetModuleName(target.name), {
4952
+ path: path.join(layout.root, modulemap),
4953
+ contents: moduleContents.toString(),
4954
+ })
4941
4955
  // clang resolves a framework map loaded through extern module against
4942
4956
  // the map directory, not the framework root, so mirror every header
4943
4957
  // the map names there. clang looks in Headers/ and PrivateHeaders/ for
@@ -5272,6 +5286,7 @@ export function writeSwiftProject(
5272
5286
  ? ['-ivfsoverlay', headerSearch.files[0]!]
5273
5287
  : []
5274
5288
  const nativeHeaderFlags: string[] = [...headerAliasFlags]
5289
+ const nativeSwiftHeaderMaps = new Map<string, string>()
5275
5290
  const originalMaps = new Map<string, string>()
5276
5291
  for (const target of input.nativeTargets ?? []) {
5277
5292
  for (const flag of [...target.flags, ...target.cxxFlags]) {
@@ -5304,9 +5319,14 @@ export function writeSwiftProject(
5304
5319
  )
5305
5320
  const moduleName = swiftTargetModuleName(name)
5306
5321
  const originalMap = originalMaps.get(moduleName)
5307
- const originalTokens = originalMap ? moduleMapTokens(input.files[originalMap]!) : []
5322
+ const stagedMap = sourceModuleMaps.get(moduleName)
5323
+ const originalPath = originalMap
5324
+ ? path.join(layout.root, originalMap)
5325
+ : stagedMap?.path
5326
+ const originalContents = originalMap ? input.files[originalMap]! : stagedMap?.contents
5327
+ const originalTokens = originalContents ? moduleMapTokens(originalContents) : []
5308
5328
  if (
5309
- originalMap &&
5329
+ originalPath &&
5310
5330
  originalTokens.some(
5311
5331
  (token, index) =>
5312
5332
  token === 'module' &&
@@ -5314,26 +5334,26 @@ export function writeSwiftProject(
5314
5334
  originalTokens[index + 1] === `${moduleName}.Swift`),
5315
5335
  )
5316
5336
  ) {
5317
- nativeHeaderFlags.push('-fmodule-map-file=' + path.join(layout.root, originalMap))
5337
+ nativeHeaderFlags.push('-fmodule-map-file=' + originalPath)
5338
+ nativeSwiftHeaderMaps.set(name, originalPath)
5318
5339
  continue
5319
5340
  }
5320
5341
  files.set(
5321
5342
  modulemap,
5322
- originalMap
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`
5343
+ originalPath
5344
+ ? `extern module ${moduleName} ${JSON.stringify(originalPath)}\nmodule ${moduleName}.Swift {\n header ${JSON.stringify(path.join(headerDirectory, name + '-Swift.h'))}\n requires objc\n}\n`
5324
5345
  : swiftObjCModuleMap(
5325
5346
  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
- ],
5347
+ (
5348
+ input.nativeTargets?.find((target) => target.name === name)
5349
+ ?.publicHeaders ?? []
5350
+ ).map((header) => path.join(layout.root, header)),
5333
5351
  submoduleImports.get(moduleName),
5352
+ path.join(headerDirectory, name + '-Swift.h'),
5334
5353
  ),
5335
5354
  )
5336
5355
  nativeHeaderFlags.push('-fmodule-map-file=' + modulemap)
5356
+ nativeSwiftHeaderMaps.set(name, modulemap)
5337
5357
  }
5338
5358
  // swiftpm plans a build root's build once and reuses the plan until a
5339
5359
  // manifest changes, so a file added to the module would never compile
@@ -5788,6 +5808,7 @@ export function writeSwiftProject(
5788
5808
  nativeFlags,
5789
5809
  nativeImportFlags,
5790
5810
  nativeHeaderFlags,
5811
+ nativeSwiftHeaderMaps,
5791
5812
  nativeHeaderDeclarations,
5792
5813
  objcImplementationModules: new Set(
5793
5814
  targets
@@ -5974,31 +5995,30 @@ export function writeSwiftProject(
5974
5995
  ),
5975
5996
  ]),
5976
5997
  )
5998
+ const producerSet = new Set([...Object.keys(nativeHeaderDeclarations), ...producers])
5999
+ const orderedProducers: string[] = []
5977
6000
  const included = new Set<string>()
5978
6001
  const include = (name: string): void => {
5979
6002
  if (included.has(name)) return
5980
6003
  included.add(name)
5981
6004
  for (const dependency of dependencies.get(name) ?? []) include(dependency)
6005
+ if (producerSet.has(name)) orderedProducers.push(name)
5982
6006
  }
5983
- for (const producer of producers)
6007
+ for (const producer of producerSet)
5984
6008
  for (const dependency of dependencies.get(producer) ?? []) include(dependency)
5985
- // building a producer also emits its dependency producers' headers.
6009
+ const needsHeaderStages = [...producerSet].some((name) => included.has(name))
6010
+ for (const producer of producerSet) include(producer)
5986
6011
  return {
5987
6012
  nativeBuildTargets: [...native].flatMap(([name, plan]) => [
5988
6013
  ...(!plan.mixed && plan.sources.length > 0 ? [name] : []),
5989
6014
  ...(plan.groups?.map((group) => group.name) ?? (plan.late ? [plan.late.name] : [])),
5990
6015
  ]),
5991
- headerProducers: [
5992
- ...new Set([
5993
- ...Object.keys(nativeHeaderDeclarations),
5994
- ...producers.filter((name) => !included.has(name)),
5995
- ]),
5996
- ],
6016
+ headerProducers: orderedProducers,
5997
6017
  emittedHeaderProducers: [
5998
6018
  ...new Set([...Object.keys(nativeHeaderDeclarations), ...producers]),
5999
6019
  ],
6000
6020
  nativeHeaderDeclarations,
6001
- headerProductTarget,
6021
+ headerProductTarget: needsHeaderStages ? undefined : headerProductTarget,
6002
6022
  targetFailures,
6003
6023
  generatedOwners,
6004
6024
  targetToolset,
package/src/swift-host.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from 'node:async_hooks'
2
- import { execFileSync } from 'node:child_process'
2
+ import { execFile, execFileSync } from 'node:child_process'
3
3
  import { createHash } from 'node:crypto'
4
4
  // the node host for every Swift preview: package inputs, one compile and
5
5
  // immutable artifact addresses. vite and the foreground CLI adapt this host.
@@ -42,6 +42,7 @@ import {
42
42
  swiftDistributionAt,
43
43
  swiftOptionalFramework,
44
44
  compilerSourceDigest,
45
+ swiftSdkPaths,
45
46
  } from './swift-compile'
46
47
  import {
47
48
  assetSymbolText,
@@ -522,6 +523,79 @@ export function configureSwiftStandinBehavior(
522
523
  const standinBuilds = new Map<string, Promise<SwiftStandins>>()
523
524
 
524
525
  // packages resolve once per set of linked products, pins and local manifests.
526
+ // assembly guarded to the architectures it was written for preprocesses to
527
+ // nothing for wasm32 under the target's own headers and the sdk's c flags, so
528
+ // swiftpm builds that target as plain c instead of it standing in. a file that
529
+ // fails to preprocess (#error on an unknown platform) keeps the stand-in.
530
+ const emptyWasmAssembly = new Map<string, Promise<boolean>>()
531
+ async function wasmPortableAssembly(
532
+ binaries: readonly SwiftPackageBinary[],
533
+ toolchainBin: string,
534
+ moduleRoot: string,
535
+ ): Promise<Set<string>> {
536
+ const assembly = binaries.filter(
537
+ (binary) =>
538
+ binary.unloweredSources?.length &&
539
+ binary.unloweredSources.every((file) => /\.(s|S)$/.test(file)) &&
540
+ binary.publicHeaders !== undefined,
541
+ )
542
+ if (assembly.length === 0) return new Set()
543
+ const sdk = swiftSdkPaths(moduleRoot, toolchainBin)
544
+ const clang = path.join(toolchainBin, 'clang')
545
+ const empty = (binary: SwiftPackageBinary, file: string) => {
546
+ const source = path.join(binary.dir, file)
547
+ const key = createHash('sha256')
548
+ .update(
549
+ JSON.stringify([
550
+ clang,
551
+ sdk.sysroot,
552
+ sdk.cFlags,
553
+ binary.dir,
554
+ binary.publicHeaders,
555
+ ]),
556
+ )
557
+ .update(fs.readFileSync(source))
558
+ .digest('hex')
559
+ const known = emptyWasmAssembly.get(key)
560
+ if (known) return known
561
+ const result = new Promise<boolean>((resolve) =>
562
+ execFile(
563
+ clang,
564
+ [
565
+ '-target',
566
+ 'wasm32-unknown-wasip1',
567
+ '--sysroot',
568
+ sdk.sysroot,
569
+ ...sdk.cFlags,
570
+ '-I',
571
+ path.join(binary.dir, binary.publicHeaders!),
572
+ '-I',
573
+ path.dirname(source),
574
+ '-E',
575
+ '-P',
576
+ '-x',
577
+ 'assembler-with-cpp',
578
+ source,
579
+ ],
580
+ { maxBuffer: 64 * 1024 * 1024 },
581
+ (error, stdout) => resolve(!error && stdout.trim() === ''),
582
+ ),
583
+ )
584
+ emptyWasmAssembly.set(key, result)
585
+ return result
586
+ }
587
+ const portable = await Promise.all(
588
+ assembly.map(async (binary) =>
589
+ (
590
+ await Promise.all(binary.unloweredSources!.map((file) => empty(binary, file)))
591
+ ).every(Boolean)
592
+ ? [binary.target]
593
+ : [],
594
+ ),
595
+ )
596
+ return new Set(portable.flat())
597
+ }
598
+
525
599
  async function swiftPackages(
526
600
  entry: XcodeProjectEntry,
527
601
  app: XcodeAppTarget,
@@ -616,7 +690,14 @@ async function swiftPackages(
616
690
  entry.moduleRoot,
617
691
  path.join(resolved.toolchainBin, 'clang++'),
618
692
  )
619
- const cxxArtifacts = reached.filter(standinArtifact)
693
+ const portableAssembly = await wasmPortableAssembly(
694
+ reached,
695
+ resolved.toolchainBin,
696
+ entry.moduleRoot,
697
+ )
698
+ const cxxArtifacts = reached.filter(
699
+ (binary) => standinArtifact(binary) && !portableAssembly.has(binary.target),
700
+ )
620
701
  const generation = standinGenerationInputs(cxxArtifacts, toolchain, entry.behavior)
621
702
  if (cached.standinKey !== generation) {
622
703
  // an archive other than the one peach ships a module for stands in itself
@@ -648,6 +729,7 @@ async function swiftPackages(
648
729
  [...replaced].filter((target) => !built.gaps.has(target)),
649
730
  ),
650
731
  binaryGaps: built.gaps,
732
+ portableAssembly,
651
733
  owners,
652
734
  })
653
735
  for (const target of new Set(built.standins.map((standin) => standin.target)))
@@ -49,6 +49,7 @@ export function swiftObjCModuleMap(
49
49
  module: string,
50
50
  headers: readonly string[],
51
51
  submodules: ReadonlySet<string> = new Set(),
52
+ swiftHeader?: string,
52
53
  ): string {
53
54
  const header = (file: string) => `header ${JSON.stringify(file)}`
54
55
  const stem = (file: string) =>
@@ -60,6 +61,9 @@ export function swiftObjCModuleMap(
60
61
  ? ` module ${stem(file)} { ${header(file)} export * }`
61
62
  : ` ${header(file)}`,
62
63
  ),
64
+ ...(swiftHeader
65
+ ? [' module Swift {', ` ${header(swiftHeader)}`, ' requires objc', ' }']
66
+ : []),
63
67
  ' export *',
64
68
  '}',
65
69
  '',
@@ -165,18 +165,23 @@ const UNSUPPORTED_NATIVE = /\.(s|S)$/
165
165
  // return address, cannot lower to wasm, unless upstream declares
166
166
  // wasi-conditioned c settings for it: that is the package's own supported
167
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.
168
+ // compiles with those flags exactly as swiftpm builds it. assembly that
169
+ // preprocesses to nothing for wasm32 (guarded to the architectures it was
170
+ // written for) is the same portable path without the signal: swiftpm compiles
171
+ // it as plain c. otherwise the target keeps the refusal below. when a refused
172
+ // target also ships public headers, those headers stand in for it and every
173
+ // declaration they spell traps by name. this is the assembly rule above,
174
+ // widened only where the target has a header surface to stand in from.
173
175
  function unlowerableSources(
174
176
  files: readonly string[],
175
177
  target: SwiftManifestTarget,
178
+ portable: ReadonlySet<string>,
176
179
  ): string[] {
177
180
  if (target.declaresWasiNativeSettings) return []
178
181
  return [
179
- ...files.filter((file) => UNSUPPORTED_NATIVE.test(file)),
182
+ ...(portable.has(target.name)
183
+ ? []
184
+ : files.filter((file) => UNSUPPORTED_NATIVE.test(file))),
180
185
  ...files
181
186
  .filter(isSwiftNativeTranslationUnit)
182
187
  .filter((file) => swiftCTakesReturnAddress(fs.readFileSync(file, 'utf8'))),
@@ -186,10 +191,11 @@ function unlowerableSources(
186
191
  function unloweredSources(
187
192
  files: readonly string[],
188
193
  target: SwiftManifestTarget,
194
+ portable: ReadonlySet<string>,
189
195
  ): string[] | null {
190
196
  if (target.type !== 'regular') return null
191
197
  if (!files.some(isSwiftNativeTranslationUnit)) return null
192
- const unlowered = unlowerableSources(files, target)
198
+ const unlowered = unlowerableSources(files, target, portable)
193
199
  if (unlowered.length === 0) return null
194
200
  const headers = path.resolve(target.dir, target.publicHeadersPath)
195
201
  if (
@@ -533,6 +539,8 @@ export function resolveSwiftPackages(options: {
533
539
  standinTargets?: ReadonlySet<string>
534
540
  /** why a binary target has no stand-in, added to its reason. */
535
541
  binaryGaps?: ReadonlyMap<string, string>
542
+ /** assembly targets whose sources preprocess to nothing for wasm32. */
543
+ portableAssembly?: ReadonlySet<string>
536
544
  /**
537
545
  * each compiling module and the package products it links. a clang target
538
546
  * in that product's closure records the module as a client.
@@ -542,6 +550,7 @@ export function resolveSwiftPackages(options: {
542
550
  }): SwiftPackages {
543
551
  const { rootDir, resolved, products, localDirs } = options
544
552
  const providedTargets = new Set(options.provided ?? [])
553
+ const portableAssembly = options.portableAssembly ?? new Set<string>()
545
554
  const providedProducts = new Set(options.provided ?? [])
546
555
  const result: SwiftPackages = {
547
556
  sourceLinks: { targets: [], owners: [] },
@@ -674,7 +683,7 @@ export function resolveSwiftPackages(options: {
674
683
  ? swiftTargetFiles(pkg.manifest, target)
675
684
  : []
676
685
  const gap = options.binaryGaps?.get(name)
677
- const unlowerable = unlowerableSources(files, target)
686
+ const unlowerable = unlowerableSources(files, target, portableAssembly)
678
687
  const placeholder = placeholderPackage(pkg)
679
688
  const ownReason =
680
689
  target.type === 'binary'
@@ -794,7 +803,7 @@ export function resolveSwiftPackages(options: {
794
803
  )
795
804
  return false
796
805
  // a target whose headers stand in for its unlowered sources stays with the stand-in
797
- if (unloweredSources(files, target)) return false
806
+ if (unloweredSources(files, target, portableAssembly)) return false
798
807
  claimed.add(key)
799
808
  providedTargets.delete(name)
800
809
  for (const dependency of target.dependencies) {
@@ -865,7 +874,7 @@ export function resolveSwiftPackages(options: {
865
874
  : []
866
875
  const objc =
867
876
  target.type === 'regular' && files.some((file) => /\.(m|mm)$/.test(file))
868
- const unlowered = unloweredSources(files, target)
877
+ const unlowered = unloweredSources(files, target, portableAssembly)
869
878
  const gap = placeholderPackage(pkg)
870
879
  const sources = files.filter((file) => file.endsWith('.swift'))
871
880
  // swiftpm's release settings, as xcode builds a package for any
@@ -1747,7 +1747,7 @@ function graphStandin(
1747
1747
  before
1748
1748
  )
1749
1749
  throw new Error(
1750
- `its generated source does not typecheck: ${elsewhere.slice(0, 3).join('; ') || check.stderr.trim().slice(0, 400)}`,
1750
+ `its generated source does not typecheck: ${(elsewhere.length > 0 ? elsewhere : [...check.stderr.matchAll(/^\S+?:\d+:\d+: error: .*$/gm)].map((line) => line[0].replace(/^[^:]*\//, ''))).slice(0, 3).join('; ') || check.stderr.trim().slice(0, 400)}`,
1751
1751
  )
1752
1752
  }
1753
1753
  }