peachsim 0.1.1635 → 0.1.1640
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.
- package/README.md +5 -1
- package/cli/app-config.ts +14 -5
- package/cli/app-stubs.ts +62 -13
- package/cli/bridge-flow-runner.ts +2 -2
- package/cli/cloud-client.ts +60 -40
- package/cli/commands/doctor.ts +13 -5
- package/cli/commands/flow.ts +1 -1
- package/cli/commands/inspect/shared.ts +9 -4
- package/cli/commands/inspect.ts +65 -47
- package/cli/commands/preview.ts +1 -1
- package/cli/commands/record.ts +97 -47
- package/cli/commands/swift.ts +9 -3
- package/cli/commands/upload.ts +48 -42
- package/cli/drivers/playwright-sim-host.ts +65 -42
- package/cli/main.ts +1 -1
- package/cli/outbound-endpoints.ts +7 -5
- package/cli/pause-aware-timeout.ts +4 -0
- package/cli/ws-bridge.ts +19 -10
- package/detox/attempt-events.cjs +62 -5
- package/detox/attempt-events.d.cts +7 -0
- package/detox/expectations.ts +7 -3
- package/detox/index.ts +121 -47
- package/detox/motion-change.cjs +170 -21
- package/detox/motion-change.d.cts +32 -0
- package/detox/navigation-lifecycle.ts +35 -3
- package/dist-lib/agent-daemon-client.cjs +1 -1
- package/dist-lib/agent-events.cjs +1 -1
- package/dist-lib/attached-projects.cjs +1 -1
- package/dist-lib/auth/shared-session.cjs +1 -1
- package/dist-lib/backend-origin.cjs +8 -7
- package/dist-lib/beta.cjs +1 -1
- package/dist-lib/beta.mjs +1 -1
- package/dist-lib/bridge-constants.cjs +1 -1
- package/dist-lib/bridge-contract-input.cjs +1 -1
- package/dist-lib/bridge-contract-input.mjs +1 -1
- package/dist-lib/bridge-contract.cjs +1 -1
- package/dist-lib/bridge-contract.mjs +1 -1
- package/dist-lib/bundle-channel.cjs +4038 -1983
- package/dist-lib/capture-contract.cjs +1 -1
- package/dist-lib/capture-contract.mjs +1 -1
- package/dist-lib/cloud-contract.cjs +1 -1
- package/dist-lib/cloud-contract.mjs +1 -1
- package/dist-lib/cloud-test-args.cjs +1 -1
- package/dist-lib/cloud-test-args.mjs +1 -1
- package/dist-lib/cloud.cjs +1 -1
- package/dist-lib/cloud.mjs +1 -1
- package/dist-lib/config.cjs +1 -1
- package/dist-lib/config.mjs +1 -1
- package/dist-lib/detox/index.cjs +509 -86
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +3551 -1574
- package/dist-lib/expo-swift-metadata.cjs +9 -7
- package/dist-lib/expo-swift-metadata.mjs +9 -7
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +43633 -2635
- package/dist-lib/host/fetch-proxy-handler.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.cjs +1 -1
- package/dist-lib/host/fetch-proxy-overrides.mjs +1 -1
- package/dist-lib/host/replacement-module-handler.cjs +1 -1
- package/dist-lib/host/websocket-proxy.cjs +1 -1
- package/dist-lib/index.cjs +2748 -128
- package/dist-lib/jump-to-source-babel.cjs +1 -1
- package/dist-lib/jump-to-source-native.cjs +1 -1
- package/dist-lib/kotlin-host.cjs +1 -1
- package/dist-lib/menu.cjs +1 -1
- package/dist-lib/menu.mjs +1 -1
- package/dist-lib/metro-fingerprint-registry.cjs +1 -1
- package/dist-lib/metro-fingerprint-registry.mjs +1 -1
- package/dist-lib/metro-production-bundle.cjs +1 -1
- package/dist-lib/metro-production-bundle.mjs +1 -1
- package/dist-lib/metro.cjs +2547 -83
- package/dist-lib/native-app-identity-project.cjs +237 -50
- package/dist-lib/native-app-identity-project.mjs +237 -50
- package/dist-lib/native-app-identity.cjs +29 -30
- package/dist-lib/native-app-identity.mjs +29 -30
- package/dist-lib/native-firebase-metadata.cjs +1 -1
- package/dist-lib/native-firebase-metadata.mjs +1 -1
- package/dist-lib/plist.cjs +1 -1
- package/dist-lib/plist.mjs +1 -1
- package/dist-lib/profiles.cjs +1 -1
- package/dist-lib/public-brand.cjs +1 -1
- package/dist-lib/react-native-host-modules.cjs +2 -2
- package/dist-lib/react-native-host-modules.mjs +2 -2
- package/dist-lib/scripts/dev-server-scanner.cjs +8 -6
- package/dist-lib/sdk.cjs +1 -1
- package/dist-lib/sdk.mjs +1 -1
- package/dist-lib/skills.cjs +65403 -22739
- package/dist-lib/swift-compile.cjs +93 -32
- package/dist-lib/swift-compile.mjs +93 -32
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +7 -5
- package/dist-lib/swift-submit.mjs +7 -5
- package/dist-lib/swift-toolchain.cjs +316 -41
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +7335 -5432
- package/dist-lib/vite.cjs +2857 -12
- package/dist-lib/worklet-executable.cjs +14 -2
- package/dist-lib/worklet-executable.mjs +14 -2
- package/package.json +1 -1
- package/src/backend-origin.ts +13 -6
- package/src/expo-swift-host.ts +5 -2
- package/src/expoKotlinContract.ts +4 -7
- package/src/expoSwiftContract.ts +4 -6
- package/src/host/staged-host-files.ts +9 -0
- package/src/native-app-identity-project.ts +1 -4
- package/src/native-app-identity.ts +1 -4
- package/src/nativeAppIconContract.ts +1 -4
- package/src/output-lock-stdio.ts +36 -0
- package/src/react-native-bridge-modules.ts +21 -6
- package/src/react-native-host-modules.ts +4 -1
- package/src/settings-bundle.ts +1 -4
- package/src/swift-compile.ts +91 -33
- package/src/swift-distribution.lock.json +22 -12
- package/src/swift-distribution.ts +103 -4
- package/src/swift-host.ts +89 -26
- package/src/swift-icu.ts +16 -10
- package/src/swift-objc-compile.ts +355 -0
- package/src/swift-objc-sdk.ts +689 -18
- package/src/swift-objc-standin.ts +126 -14
- package/src/swift-package-manifest.ts +39 -1
- package/src/swift-packages.ts +35 -21
- package/src/swift-standin-emit.ts +40 -7
- package/src/swift-standins.ts +404 -138
- package/src/swift-submit.ts +3 -5
- package/src/swift-toolchain.ts +378 -46
- package/src/worker-system-chunks.ts +11 -12
- package/src/worklet-executable.ts +19 -1
- package/src/xcode-project.ts +270 -30
|
@@ -13,11 +13,12 @@
|
|
|
13
13
|
// headers import; the stand-in's own typecheck then leaves out whatever peach
|
|
14
14
|
// cannot spell.
|
|
15
15
|
|
|
16
|
-
import { spawnSync } from 'node:child_process'
|
|
16
|
+
import { execFileSync, spawnSync } from 'node:child_process'
|
|
17
17
|
import { createHash } from 'node:crypto'
|
|
18
18
|
import fs from 'node:fs'
|
|
19
19
|
import path from 'node:path'
|
|
20
20
|
import { IOS_SDK_HEADERS, IOS_SDK_OVERLAYS, IOS_SDK_TARGET } from './swift-objc-sdk'
|
|
21
|
+
import { swiftEnvironment } from './swift-toolchain'
|
|
21
22
|
import type { SymbolGraph } from './swift-standin-emit'
|
|
22
23
|
|
|
23
24
|
/** a module map and the headers it reaches: a framework's, or a library
|
|
@@ -37,6 +38,100 @@ export interface ObjcView {
|
|
|
37
38
|
imports: string[]
|
|
38
39
|
}
|
|
39
40
|
|
|
41
|
+
/** bump when importer behavior changes the Swift view independently of SDK headers. */
|
|
42
|
+
export const OBJC_IMPORT_VERSION = '3'
|
|
43
|
+
|
|
44
|
+
export const NATIVE_GRAPH_SDK_VERSION = '27.1'
|
|
45
|
+
|
|
46
|
+
const NATIVE_GRAPH_INPUTS = {
|
|
47
|
+
sdk: NATIVE_GRAPH_SDK_VERSION,
|
|
48
|
+
settings: 'e68503e5e534e9194af5efe8c636ca8b824e2d8237c5f38ec84aa4d155bc8418',
|
|
49
|
+
build: 'ff785237ba22f1d8f347a5c4f4c68400a387c6d935ef3a443545a72faef57e70',
|
|
50
|
+
compiler: 'Apple Swift version 6.4 (swiftlang-6.4.0.34.1 clang-2100.3.34.1)',
|
|
51
|
+
target: IOS_SDK_TARGET,
|
|
52
|
+
}
|
|
53
|
+
export const NATIVE_GRAPH_ID = createHash('sha256')
|
|
54
|
+
.update(JSON.stringify(NATIVE_GRAPH_INPUTS))
|
|
55
|
+
.digest('hex')
|
|
56
|
+
|
|
57
|
+
/** a mixed framework's swift overlay and underlying clang module load together. */
|
|
58
|
+
export function nativeInterfaceView(
|
|
59
|
+
surface: ObjcSurface,
|
|
60
|
+
frameworks: readonly string[],
|
|
61
|
+
work: string,
|
|
62
|
+
): ObjcView {
|
|
63
|
+
if (process.platform !== 'darwin')
|
|
64
|
+
throw new Error('mixed framework declarations require the pinned native iOS SDK')
|
|
65
|
+
const xcrun = (args: string[]) =>
|
|
66
|
+
execFileSync('xcrun', args, {
|
|
67
|
+
encoding: 'utf8',
|
|
68
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
69
|
+
}).trim()
|
|
70
|
+
const sdk = xcrun(['--sdk', 'iphonesimulator', '--show-sdk-path'])
|
|
71
|
+
const compiler = xcrun(['--find', 'swiftc'])
|
|
72
|
+
const version = execFileSync(compiler, ['--version'], { encoding: 'utf8' })
|
|
73
|
+
.trim()
|
|
74
|
+
.split('\n')[0]
|
|
75
|
+
const digest = (file: string) =>
|
|
76
|
+
createHash('sha256')
|
|
77
|
+
.update(fs.readFileSync(path.join(sdk, file)))
|
|
78
|
+
.digest('hex')
|
|
79
|
+
const actual = {
|
|
80
|
+
sdk: xcrun(['--sdk', 'iphonesimulator', '--show-sdk-version']),
|
|
81
|
+
compiler: version,
|
|
82
|
+
settings: digest('SDKSettings.json'),
|
|
83
|
+
build: digest('System/Library/CoreServices/SystemVersion.plist'),
|
|
84
|
+
}
|
|
85
|
+
const mismatches = Object.entries(actual)
|
|
86
|
+
.filter(([key, value]) => Reflect.get(NATIVE_GRAPH_INPUTS, key) !== value)
|
|
87
|
+
.map(
|
|
88
|
+
([key, value]) =>
|
|
89
|
+
`${key}: expected ${Reflect.get(NATIVE_GRAPH_INPUTS, key)}, got ${value}`,
|
|
90
|
+
)
|
|
91
|
+
if (mismatches.length)
|
|
92
|
+
throw new Error(
|
|
93
|
+
`native declaration SDK or compiler differs from ${NATIVE_GRAPH_ID}: ${mismatches.join('; ')}`,
|
|
94
|
+
)
|
|
95
|
+
const toolchainBin = path.dirname(compiler)
|
|
96
|
+
const search = ['-sdk', sdk, ...frameworks.flatMap((dir) => ['-F', dir])]
|
|
97
|
+
const out = path.join(work, 'native-graphs')
|
|
98
|
+
fs.mkdirSync(out, { recursive: true })
|
|
99
|
+
const run = spawnSync(
|
|
100
|
+
path.join(toolchainBin, 'swift-symbolgraph-extract'),
|
|
101
|
+
[
|
|
102
|
+
'-module-name',
|
|
103
|
+
surface.module,
|
|
104
|
+
'-target',
|
|
105
|
+
IOS_SDK_TARGET,
|
|
106
|
+
...search,
|
|
107
|
+
'-minimum-access-level',
|
|
108
|
+
'public',
|
|
109
|
+
'-skip-synthesized-members',
|
|
110
|
+
'-omit-extension-block-symbols',
|
|
111
|
+
'-output-dir',
|
|
112
|
+
out,
|
|
113
|
+
],
|
|
114
|
+
{ encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 },
|
|
115
|
+
)
|
|
116
|
+
if (run.error) throw run.error
|
|
117
|
+
if (run.status !== 0)
|
|
118
|
+
throw new Error(
|
|
119
|
+
`native interface extraction ${run.signal ?? `exit ${run.status}`}: ${run.stderr.trim().slice(-4000)}`,
|
|
120
|
+
)
|
|
121
|
+
const graphs = fs
|
|
122
|
+
.readdirSync(out)
|
|
123
|
+
.filter((file) => file.endsWith('.symbols.json'))
|
|
124
|
+
.sort()
|
|
125
|
+
.map((file): SymbolGraph => JSON.parse(fs.readFileSync(path.join(out, file), 'utf8')))
|
|
126
|
+
if (graphs.length === 0)
|
|
127
|
+
throw new Error('native interface extraction returned no graphs')
|
|
128
|
+
return {
|
|
129
|
+
graphs,
|
|
130
|
+
values: enumValues(graphs, surface, true, toolchainBin, search, work),
|
|
131
|
+
imports: [],
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
40
135
|
// the opaque declarations a failed import asks for, by name.
|
|
41
136
|
type Missing = Map<string, 'class' | 'protocol' | 'struct' | 'macro'>
|
|
42
137
|
|
|
@@ -63,7 +158,7 @@ export const IOS_SDK_ID = createHash('sha256')
|
|
|
63
158
|
|
|
64
159
|
// the sdk, written once per content under the cache directory so the module
|
|
65
160
|
// cache keyed by its paths stays warm across stand-ins.
|
|
66
|
-
function
|
|
161
|
+
export function materializeObjcSdk(cacheDir: string): string {
|
|
67
162
|
const sdk = path.join(cacheDir, 'ios-sdk', IOS_SDK_ID)
|
|
68
163
|
if (fs.existsSync(sdk)) return sdk
|
|
69
164
|
fs.mkdirSync(path.dirname(sdk), { recursive: true })
|
|
@@ -116,7 +211,7 @@ export function objcView(
|
|
|
116
211
|
throw new Error(
|
|
117
212
|
`this peach's Swift has no iOS simulator standard library at ${stdlib}`,
|
|
118
213
|
)
|
|
119
|
-
const sdk =
|
|
214
|
+
const sdk = materializeObjcSdk(cacheDir)
|
|
120
215
|
// a framework's module map sits in Modules/ beside Headers/; a library
|
|
121
216
|
// slice keeps it among its headers.
|
|
122
217
|
const framework = path.basename(path.dirname(surface.modulemap)) === 'Modules'
|
|
@@ -127,13 +222,13 @@ export function objcView(
|
|
|
127
222
|
: path.join(include, surface.module)
|
|
128
223
|
const originals = new Map(
|
|
129
224
|
headerFiles(surface.headers).map((file) => [
|
|
130
|
-
file,
|
|
225
|
+
path.join(headersDir, file),
|
|
131
226
|
fs.readFileSync(path.join(surface.headers, file), 'utf8'),
|
|
132
227
|
]),
|
|
133
228
|
)
|
|
134
229
|
for (const [file, text] of originals) {
|
|
135
|
-
fs.mkdirSync(path.dirname(
|
|
136
|
-
fs.writeFileSync(
|
|
230
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
231
|
+
fs.writeFileSync(file, text)
|
|
137
232
|
}
|
|
138
233
|
if (framework) {
|
|
139
234
|
fs.mkdirSync(path.join(frameworks, `${surface.module}.framework`, 'Modules'), {
|
|
@@ -146,12 +241,18 @@ export function objcView(
|
|
|
146
241
|
} else {
|
|
147
242
|
fs.copyFileSync(surface.modulemap, path.join(headersDir, 'module.modulemap'))
|
|
148
243
|
}
|
|
244
|
+
// dependency headers take the same learned declarations but never become
|
|
245
|
+
// the surface's own imports.
|
|
246
|
+
const dependencyOriginals = new Map<string, string>()
|
|
149
247
|
for (const dependency of surface.dependencies ?? []) {
|
|
150
248
|
const dir = path.join(include, dependency.module)
|
|
151
249
|
fs.mkdirSync(dir, { recursive: true })
|
|
152
250
|
for (const file of headerFiles(dependency.headers)) {
|
|
153
|
-
|
|
154
|
-
fs.
|
|
251
|
+
const destination = path.join(dir, file)
|
|
252
|
+
const text = fs.readFileSync(path.join(dependency.headers, file), 'utf8')
|
|
253
|
+
dependencyOriginals.set(destination, text)
|
|
254
|
+
fs.mkdirSync(path.dirname(destination), { recursive: true })
|
|
255
|
+
fs.writeFileSync(destination, text)
|
|
155
256
|
}
|
|
156
257
|
const supplied = path.join(dependency.headers, 'module.modulemap')
|
|
157
258
|
fs.writeFileSync(
|
|
@@ -168,6 +269,13 @@ export function objcView(
|
|
|
168
269
|
const search = [
|
|
169
270
|
'-sdk',
|
|
170
271
|
sdk,
|
|
272
|
+
// keep compiler support headers without importing host platform modules.
|
|
273
|
+
'-resource-dir',
|
|
274
|
+
path.join(sdk, 'usr/lib/swift'),
|
|
275
|
+
'-I',
|
|
276
|
+
path.resolve(toolchainBin, '../lib/swift/clang/include'),
|
|
277
|
+
'-I',
|
|
278
|
+
path.resolve(toolchainBin, '../lib/swift/shims'),
|
|
171
279
|
'-I',
|
|
172
280
|
stdlib,
|
|
173
281
|
'-F',
|
|
@@ -237,8 +345,8 @@ export function objcView(
|
|
|
237
345
|
path.join(root, 'Modules', 'module.modulemap'),
|
|
238
346
|
'framework module PeachMissing {\n umbrella header "PeachMissing.h"\n export *\n}\n',
|
|
239
347
|
)
|
|
240
|
-
for (const [file, text] of originals)
|
|
241
|
-
fs.writeFileSync(
|
|
348
|
+
for (const [file, text] of [...originals, ...dependencyOriginals])
|
|
349
|
+
fs.writeFileSync(file, `${MISSING_IMPORT}${text}`)
|
|
242
350
|
}
|
|
243
351
|
// the identifier a diagnostic points at, read from the header as compiled.
|
|
244
352
|
const tokenAt = (file: string, line: number, column: number) => {
|
|
@@ -276,11 +384,11 @@ export function objcView(
|
|
|
276
384
|
'-output-dir',
|
|
277
385
|
out,
|
|
278
386
|
],
|
|
279
|
-
{ encoding: 'utf8', maxBuffer: 256 * 1024 * 1024 },
|
|
387
|
+
{ encoding: 'utf8', env: swiftEnvironment(), maxBuffer: 256 * 1024 * 1024 },
|
|
280
388
|
)
|
|
281
389
|
if (run.error) throw run.error
|
|
282
390
|
const errors = [
|
|
283
|
-
...run.stderr.matchAll(/^(?:(
|
|
391
|
+
...run.stderr.matchAll(/^(?:(.+?):(\d+):(\d+): )?(?:fatal )?error: (.*)$/gm),
|
|
284
392
|
]
|
|
285
393
|
if (errors.length === 0 && run.status === 0) break
|
|
286
394
|
let progress = false
|
|
@@ -322,7 +430,11 @@ export function objcView(
|
|
|
322
430
|
}
|
|
323
431
|
if (!progress || round === ROUNDS)
|
|
324
432
|
throw new Error(
|
|
325
|
-
`its headers do not import as Swift: ${
|
|
433
|
+
`its headers do not import as Swift: ${
|
|
434
|
+
errors.length > 0
|
|
435
|
+
? [...new Set(errors.map((match) => match[4]!))].slice(0, 10).join('; ')
|
|
436
|
+
: `swift-symbolgraph-extract ${run.signal ?? `exit ${run.status}`}: ${(run.stderr.trim() || run.stdout.trim() || 'no diagnostic').slice(0, 4000)}`
|
|
437
|
+
}`,
|
|
326
438
|
)
|
|
327
439
|
if (missing.size > 0) declareMissing()
|
|
328
440
|
}
|
|
@@ -405,7 +517,7 @@ function enumValues(
|
|
|
405
517
|
'-ast-dump=json',
|
|
406
518
|
probe,
|
|
407
519
|
],
|
|
408
|
-
{ encoding: 'utf8', maxBuffer: 1024 * 1024 * 1024 },
|
|
520
|
+
{ encoding: 'utf8', env: swiftEnvironment(), maxBuffer: 1024 * 1024 * 1024 },
|
|
409
521
|
)
|
|
410
522
|
if (run.status !== 0)
|
|
411
523
|
throw new Error(
|
|
@@ -11,7 +11,7 @@ import fs from 'node:fs'
|
|
|
11
11
|
import path from 'node:path'
|
|
12
12
|
import { cacheDir as peachCacheDir, swiftPackageCacheOptions } from './home-paths'
|
|
13
13
|
import lock from './swift-distribution.lock.json' with { type: 'json' }
|
|
14
|
-
import { swiftToolchainBin } from './swift-toolchain'
|
|
14
|
+
import { swiftEnvironment, swiftToolchainBin } from './swift-toolchain'
|
|
15
15
|
import type { SwiftTargetDependency } from './swift-package'
|
|
16
16
|
|
|
17
17
|
const TARGET_TYPES = [
|
|
@@ -49,6 +49,11 @@ export interface SwiftManifestTarget {
|
|
|
49
49
|
mainActorIsolation: boolean
|
|
50
50
|
defines: SwiftManifestSetting[]
|
|
51
51
|
libraries: SwiftManifestSetting[]
|
|
52
|
+
nativeSettings: {
|
|
53
|
+
tool: 'c' | 'cxx'
|
|
54
|
+
flags: string[]
|
|
55
|
+
configuration: 'debug' | 'release' | null
|
|
56
|
+
}[]
|
|
52
57
|
/** true when the target declares `resources:`. */
|
|
53
58
|
declaresResources: boolean
|
|
54
59
|
/** public header directory relative to the target, as SwiftPM declares it. */
|
|
@@ -121,6 +126,7 @@ function dump(dir: string): { key: string; raw: Record<string, Json> } {
|
|
|
121
126
|
],
|
|
122
127
|
{
|
|
123
128
|
encoding: 'utf8',
|
|
129
|
+
env: swiftEnvironment(),
|
|
124
130
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
125
131
|
maxBuffer: 64 * 1024 * 1024,
|
|
126
132
|
},
|
|
@@ -255,9 +261,40 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
255
261
|
let mainActorIsolation = false
|
|
256
262
|
const defines: SwiftManifestSetting[] = []
|
|
257
263
|
const libraries: SwiftManifestSetting[] = []
|
|
264
|
+
const nativeSettings: SwiftManifestTarget['nativeSettings'] = []
|
|
265
|
+
for (const [tool, standard] of [
|
|
266
|
+
['c', string(raw.cLanguageStandard)],
|
|
267
|
+
['cxx', string(raw.cxxLanguageStandard)],
|
|
268
|
+
] satisfies ['c' | 'cxx', string | undefined][]) {
|
|
269
|
+
if (standard)
|
|
270
|
+
nativeSettings.push({ tool, flags: [`-std=${standard}`], configuration: null })
|
|
271
|
+
}
|
|
258
272
|
for (const setting of array(target.settings)) {
|
|
259
273
|
const { kind: rawKind, tool, condition } = record(setting)
|
|
260
274
|
const settingKind = record(rawKind)
|
|
275
|
+
if ((tool === 'c' || tool === 'cxx') && linksOnIOS(condition, traits)) {
|
|
276
|
+
const config = string(record(condition).config)
|
|
277
|
+
const header = string(record(settingKind.headerSearchPath)._0)
|
|
278
|
+
const definition = string(record(settingKind.define)._0)
|
|
279
|
+
const value = string(record(settingKind.define)._1)
|
|
280
|
+
const unsafe = record(settingKind.unsafeFlags)._0
|
|
281
|
+
const flags = header
|
|
282
|
+
? ['-I', path.resolve(targetDir, header)]
|
|
283
|
+
: definition
|
|
284
|
+
? [`-D${definition}${value === undefined ? '' : `=${value}`}`]
|
|
285
|
+
: Array.isArray(unsafe)
|
|
286
|
+
? unsafe.flatMap((flag) => string(flag) ?? [])
|
|
287
|
+
: null
|
|
288
|
+
if (!flags)
|
|
289
|
+
throw new Error(
|
|
290
|
+
`${name}: unsupported ${tool} compiler setting ${JSON.stringify(rawKind)}`,
|
|
291
|
+
)
|
|
292
|
+
nativeSettings.push({
|
|
293
|
+
tool,
|
|
294
|
+
flags,
|
|
295
|
+
configuration: config === 'debug' || config === 'release' ? config : null,
|
|
296
|
+
})
|
|
297
|
+
}
|
|
261
298
|
const mode = string(record(settingKind.swiftLanguageMode)._0)
|
|
262
299
|
if (mode)
|
|
263
300
|
languageMode = Math.max(5, Number(/^(\d+)/.exec(mode)?.[1] ?? languageMode))
|
|
@@ -299,6 +336,7 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
299
336
|
mainActorIsolation,
|
|
300
337
|
defines,
|
|
301
338
|
libraries,
|
|
339
|
+
nativeSettings,
|
|
302
340
|
declaresResources: array(target.resources).length > 0,
|
|
303
341
|
publicHeadersPath: string(target.publicHeadersPath) ?? 'include',
|
|
304
342
|
url: string(target.url) ?? null,
|
package/src/swift-packages.ts
CHANGED
|
@@ -106,25 +106,39 @@ interface Pin {
|
|
|
106
106
|
revision: string
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
function readPins(resolved: string): Map<string, Pin> {
|
|
110
|
-
const data: unknown = JSON.parse(fs.readFileSync(resolved, 'utf8'))
|
|
111
|
-
const pins =
|
|
112
|
-
data && typeof data === 'object' && 'pins' in data && Array.isArray(data.pins)
|
|
113
|
-
? data.pins
|
|
114
|
-
: null
|
|
115
|
-
if (!pins)
|
|
116
|
-
throw new Error(`${resolved} has no pins; resolve packages in a current Xcode`)
|
|
109
|
+
function readPins(resolved: readonly string[]): Map<string, Pin> {
|
|
117
110
|
const out = new Map<string, Pin>()
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
const
|
|
121
|
-
const
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
)
|
|
127
|
-
|
|
111
|
+
const owners = new Map<string, string>()
|
|
112
|
+
for (const file of resolved) {
|
|
113
|
+
const data: unknown = JSON.parse(fs.readFileSync(file, 'utf8'))
|
|
114
|
+
const pins =
|
|
115
|
+
data && typeof data === 'object' && 'pins' in data && Array.isArray(data.pins)
|
|
116
|
+
? data.pins
|
|
117
|
+
: null
|
|
118
|
+
if (!pins) throw new Error(`${file} has no pins; resolve packages in a current Xcode`)
|
|
119
|
+
for (const pin of pins) {
|
|
120
|
+
const identity = pin?.identity
|
|
121
|
+
const location = pin?.location
|
|
122
|
+
const revision = pin?.state?.revision
|
|
123
|
+
if (
|
|
124
|
+
typeof identity === 'string' &&
|
|
125
|
+
typeof location === 'string' &&
|
|
126
|
+
typeof revision === 'string'
|
|
127
|
+
) {
|
|
128
|
+
const previous = out.get(identity)
|
|
129
|
+
const repository = (url: string) => url.replace(/(?:\.git)?\/?$/, '')
|
|
130
|
+
if (
|
|
131
|
+
previous &&
|
|
132
|
+
(previous.revision !== revision ||
|
|
133
|
+
repository(previous.location) !== repository(location))
|
|
134
|
+
)
|
|
135
|
+
throw new Error(
|
|
136
|
+
`conflicting Package.resolved pins for ${identity}: ${owners.get(identity)} pins ${previous.location} at ${previous.revision}; ${file} pins ${location} at ${revision}`,
|
|
137
|
+
)
|
|
138
|
+
out.set(identity, { location, revision })
|
|
139
|
+
owners.set(identity, file)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
128
142
|
}
|
|
129
143
|
return out
|
|
130
144
|
}
|
|
@@ -177,8 +191,8 @@ interface LoadedPackage {
|
|
|
177
191
|
*/
|
|
178
192
|
export function resolveSwiftPackages(options: {
|
|
179
193
|
rootDir: string
|
|
180
|
-
/** the
|
|
181
|
-
resolved: string
|
|
194
|
+
/** the selected workspace or local Package.resolved files. */
|
|
195
|
+
resolved: readonly string[]
|
|
182
196
|
products: readonly SwiftLinkedProduct[]
|
|
183
197
|
/** local package directories the workspace or a project references. */
|
|
184
198
|
localDirs: readonly string[]
|
|
@@ -194,7 +208,7 @@ export function resolveSwiftPackages(options: {
|
|
|
194
208
|
modules: new Map(),
|
|
195
209
|
binaries: [],
|
|
196
210
|
}
|
|
197
|
-
const pins = resolved ? readPins(resolved) : null
|
|
211
|
+
const pins = resolved.length > 0 ? readPins(resolved) : null
|
|
198
212
|
const checkouts = remoteSwiftCheckouts(rootDir)
|
|
199
213
|
|
|
200
214
|
const packages = new Map<string, LoadedPackage | string>()
|
|
@@ -90,7 +90,7 @@ export type StandinResult = {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
/** bump when emitted source changes: the stand-in cache keys on it. */
|
|
93
|
-
export const STANDIN_EMIT_VERSION = '
|
|
93
|
+
export const STANDIN_EMIT_VERSION = '12'
|
|
94
94
|
|
|
95
95
|
/** the modules every stand-in source imports. */
|
|
96
96
|
export const STANDIN_IMPORTS = ['Foundation', 'UIKit']
|
|
@@ -229,6 +229,11 @@ export function emitSwiftStandin(
|
|
|
229
229
|
family.has(parts[0]!) && parts[0] !== 'SwiftUICore' ? parts.join('.') : unqualified
|
|
230
230
|
return { name, module, local: false }
|
|
231
231
|
}
|
|
232
|
+
const nsObject = nameOf('c:objc(cs)NSObject', 'ObjectiveC.NSObject')!.name
|
|
233
|
+
const nsObjectProtocol = nameOf(
|
|
234
|
+
'c:objc(pl)NSObject',
|
|
235
|
+
'ObjectiveC.NSObjectProtocol',
|
|
236
|
+
)!.name
|
|
232
237
|
for (const graph of graphs)
|
|
233
238
|
for (const edge of graph.relationships) {
|
|
234
239
|
const source = byId.get(edge.source)
|
|
@@ -577,7 +582,18 @@ export function emitSwiftStandin(
|
|
|
577
582
|
const inner = `${indent} `
|
|
578
583
|
switch (symbol.kind.identifier) {
|
|
579
584
|
case 'swift.typealias': {
|
|
580
|
-
|
|
585
|
+
// a graph shortens an external alias to its leaf, which can shadow itself.
|
|
586
|
+
const fragments = (symbol.declarationFragments ?? []).map((fragment) =>
|
|
587
|
+
fragment.kind === 'typeIdentifier' &&
|
|
588
|
+
fragment.spelling === leaf(symbol) &&
|
|
589
|
+
fragment.preciseIdentifier?.startsWith('s:s') &&
|
|
590
|
+
fragment.preciseIdentifier !== id
|
|
591
|
+
? { ...fragment, spelling: `Swift.${fragment.spelling}` }
|
|
592
|
+
: fragment,
|
|
593
|
+
)
|
|
594
|
+
const { 1: attrs, 2: rest } = LEADING_ATTRS.exec(
|
|
595
|
+
text({ ...symbol, declarationFragments: fragments }),
|
|
596
|
+
)!
|
|
581
597
|
emit(`${indent}${attrs}public ${rest}`)
|
|
582
598
|
return
|
|
583
599
|
}
|
|
@@ -598,7 +614,8 @@ export function emitSwiftStandin(
|
|
|
598
614
|
...(conforms.get(id) ?? []).filter(
|
|
599
615
|
(name) =>
|
|
600
616
|
!ancestors.has(name) &&
|
|
601
|
-
!(parent && [...KEEP_EXTERNAL.values()].includes(name))
|
|
617
|
+
!(parent && [...KEEP_EXTERNAL.values()].includes(name)) &&
|
|
618
|
+
!(name === nsObjectProtocol && externalRoot(id) === nsObject),
|
|
602
619
|
),
|
|
603
620
|
].filter((name, at, all) => all.indexOf(name) === at)
|
|
604
621
|
const parentSymbol = superId.has(id) ? byId.get(superId.get(id)!) : undefined
|
|
@@ -719,7 +736,8 @@ export function emitSwiftStandin(
|
|
|
719
736
|
synthesizedEquality(member, list))
|
|
720
737
|
)
|
|
721
738
|
continue
|
|
722
|
-
const
|
|
739
|
+
const header = values.get(member.identifier.precise)
|
|
740
|
+
const value = header === undefined ? undefined : atWidth(header, raw)
|
|
723
741
|
if (value !== undefined && member.kind.identifier === 'swift.type.property') {
|
|
724
742
|
emit(
|
|
725
743
|
`${inner}public static let ${tick(leaf(member))} = ${shape.name}(rawValue: ${value})`,
|
|
@@ -739,10 +757,13 @@ export function emitSwiftStandin(
|
|
|
739
757
|
if (!shape)
|
|
740
758
|
return void skipped.push({ path, reason: `unparsed enum ${text(symbol)}` })
|
|
741
759
|
const members = membersOf(id)
|
|
742
|
-
const raw = rawType(members)
|
|
743
760
|
const cases = members.filter(
|
|
744
761
|
(member) => member.kind.identifier === 'swift.enum.case',
|
|
745
762
|
)
|
|
763
|
+
// payload cases use a manual RawRepresentable witness, not a raw enum.
|
|
764
|
+
const raw = cases.some((member) => text(member).includes('('))
|
|
765
|
+
? null
|
|
766
|
+
: rawType(members)
|
|
746
767
|
const missing = raw
|
|
747
768
|
? cases.filter((member) => !values.has(member.identifier.precise))
|
|
748
769
|
: []
|
|
@@ -754,14 +775,15 @@ export function emitSwiftStandin(
|
|
|
754
775
|
reason: `no header value for ${missing.map(leaf).join(', ')}`,
|
|
755
776
|
})
|
|
756
777
|
const list = inheritance(id, raw ?? undefined).filter(
|
|
757
|
-
(name) => name !== 'RawRepresentable',
|
|
778
|
+
(name) => !raw || name !== 'RawRepresentable',
|
|
758
779
|
)
|
|
759
780
|
emit(
|
|
760
781
|
`${indent}${shape.attrs}public enum ${shape.name}${shape.generics}${list.length ? `: ${list.join(', ')}` : ''}${shape.where} {`,
|
|
761
782
|
)
|
|
762
783
|
const seenValues = new Map<string, string>()
|
|
763
784
|
for (const member of cases) {
|
|
764
|
-
const
|
|
785
|
+
const header = values.get(member.identifier.precise)
|
|
786
|
+
const value = header === undefined ? undefined : atWidth(header, raw)
|
|
765
787
|
// objective-c aliases a value under a second name; swift spells
|
|
766
788
|
// the alias as a static member of the first case.
|
|
767
789
|
if (value !== undefined && seenValues.has(value)) {
|
|
@@ -891,6 +913,17 @@ export function emitSwiftStandin(
|
|
|
891
913
|
const init = members.find((member) => leaf(member) === 'init(rawValue:)')
|
|
892
914
|
return init ? (/rawValue:\s*([^)]+)\)/.exec(text(init))?.[1]?.trim() ?? null) : null
|
|
893
915
|
}
|
|
916
|
+
// header values are clang's for 64-bit iOS. NSUIntegerMax, NSIntegerMax
|
|
917
|
+
// and NSIntegerMin are the platform-width type's own extremes, which on
|
|
918
|
+
// wasm32 are the 32-bit ones.
|
|
919
|
+
const atWidth = (value: string, raw: string | null) =>
|
|
920
|
+
(raw === 'UInt' || raw === 'Swift.UInt') && value === '18446744073709551615'
|
|
921
|
+
? '4294967295'
|
|
922
|
+
: (raw === 'Int' || raw === 'Swift.Int') && value === '9223372036854775807'
|
|
923
|
+
? '2147483647'
|
|
924
|
+
: (raw === 'Int' || raw === 'Swift.Int') && value === '-9223372036854775808'
|
|
925
|
+
? '-2147483648'
|
|
926
|
+
: value
|
|
894
927
|
|
|
895
928
|
const emitGlobal = scoped((symbol: GraphSymbol) => {
|
|
896
929
|
const path = pathOf(symbol)
|