peachsim 0.1.1640 → 0.1.1641
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 -0
- package/cli/app-stubs.ts +38 -13
- package/cli/cloud-session.ts +16 -0
- package/cli/commands/assert.ts +17 -4
- package/cli/commands/box.ts +33 -19
- package/cli/commands/doctor.ts +24 -15
- package/cli/commands/inspect/actions.ts +3 -2
- package/cli/commands/inspect/core.ts +0 -8
- package/cli/commands/inspect.ts +0 -14
- package/cli/commands/platform.ts +2 -1
- package/cli/commands/record.ts +64 -28
- package/cli/commands/swift.ts +10 -2
- package/cli/commands/three-mode.ts +4 -38
- package/cli/commands/upload.ts +8 -8
- package/cli/flow-live-status.ts +0 -2
- package/cli/main.ts +1 -1
- package/cli/ws-bridge.ts +0 -6
- package/detox/attempt-events.cjs +41 -5
- package/detox/index.ts +155 -109
- package/detox/jest-environment.cjs +5 -1
- 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 +10 -1
- 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 +2059 -1368
- 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 +572 -125
- package/dist-lib/detox/jest-environment.cjs +5 -1
- package/dist-lib/dev-bundle-resolution.cjs +1 -1
- package/dist-lib/expo-swift-bundle.cjs +1837 -1164
- package/dist-lib/expo-swift-metadata.cjs +1 -1
- package/dist-lib/expo-swift-metadata.mjs +1 -1
- package/dist-lib/home-paths.cjs +1 -1
- package/dist-lib/host/bridge-host.cjs +2290 -1616
- 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 +44 -17
- 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 +33 -13
- package/dist-lib/native-app-identity-project.cjs +7 -4
- package/dist-lib/native-app-identity-project.mjs +7 -4
- package/dist-lib/native-app-identity.cjs +1 -1
- package/dist-lib/native-app-identity.mjs +1 -1
- 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 +1 -1
- package/dist-lib/react-native-host-modules.mjs +1 -1
- package/dist-lib/scripts/dev-server-scanner.cjs +1 -1
- package/dist-lib/sdk.cjs +4 -3
- package/dist-lib/sdk.mjs +4 -3
- package/dist-lib/skills.cjs +2823 -2109
- package/dist-lib/swift-compile.cjs +370 -239
- package/dist-lib/swift-compile.mjs +368 -230
- package/dist-lib/swift-package.cjs +1 -1
- package/dist-lib/swift-package.mjs +1 -1
- package/dist-lib/swift-submit.cjs +8 -3
- package/dist-lib/swift-submit.mjs +8 -3
- package/dist-lib/swift-toolchain.cjs +1 -1
- package/dist-lib/swift.cjs +1 -1
- package/dist-lib/vite-swift.cjs +1757 -1108
- package/dist-lib/vite.cjs +1 -1
- package/dist-lib/worklet-executable.cjs +1 -1
- package/dist-lib/worklet-executable.mjs +1 -1
- package/package.json +1 -1
- package/src/backend-origin.ts +8 -0
- package/src/react-native-bridge-modules.ts +89 -76
- package/src/swift-compile.ts +134 -107
- package/src/swift-distribution.lock.json +9 -8
- package/src/swift-host.ts +6 -4
- package/src/swift-objc-compile.ts +385 -193
- package/src/swift-objc-metadata.ts +204 -0
- package/src/swift-objc-sdk.ts +195 -2
- package/src/swift-package-manifest.ts +6 -3
- package/src/swift-root-lock.ts +153 -0
- package/src/swift-submit.ts +15 -2
- package/src/swiftContract.ts +12 -0
- package/src/xcode-project.ts +10 -3
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process'
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { IOS_SDK_HEADERS } from './swift-objc-sdk'
|
|
6
|
+
import { IOS_SDK_ID, materializeObjcSdk } from './swift-objc-standin'
|
|
7
|
+
import { swiftEnvironment } from './swift-toolchain'
|
|
8
|
+
import type { SwiftObjCPeerClass } from './swiftContract'
|
|
9
|
+
|
|
10
|
+
export class ObjcPeerMetadataError extends Error {
|
|
11
|
+
constructor(
|
|
12
|
+
message: string,
|
|
13
|
+
readonly files: string[],
|
|
14
|
+
readonly reusable: boolean,
|
|
15
|
+
) {
|
|
16
|
+
super(message)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function validateObjcPeerClasses(
|
|
21
|
+
classes: readonly SwiftObjCPeerClass[],
|
|
22
|
+
): Set<string> {
|
|
23
|
+
const names = new Set<string>()
|
|
24
|
+
for (const peer of classes) {
|
|
25
|
+
if (!/^[A-Za-z_]\w*$/.test(peer.name) || names.has(peer.name))
|
|
26
|
+
throw new Error(`invalid or duplicate Objective-C metadata class: ${peer.name}`)
|
|
27
|
+
names.add(peer.name)
|
|
28
|
+
const header = /^(\w+)\/([\w./-]+\.h)$/.exec(peer.header)
|
|
29
|
+
if (
|
|
30
|
+
!header ||
|
|
31
|
+
header[2]!.split('/').some((part) => part === '..' || part === '.') ||
|
|
32
|
+
!Object.hasOwn(
|
|
33
|
+
IOS_SDK_HEADERS,
|
|
34
|
+
`System/Library/Frameworks/${header[1]}.framework/Headers/${header[2]}`,
|
|
35
|
+
)
|
|
36
|
+
)
|
|
37
|
+
throw new Error(`Objective-C peer header is outside the shared SDK: ${peer.header}`)
|
|
38
|
+
}
|
|
39
|
+
if (names.size === 0) throw new Error('Objective-C metadata requires peer classes')
|
|
40
|
+
return names
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** emits class metadata and its startup registration; adapters own every method. */
|
|
44
|
+
export function compileObjcPeerMetadata(args: {
|
|
45
|
+
classes: readonly SwiftObjCPeerClass[]
|
|
46
|
+
work: string
|
|
47
|
+
headerCache: string
|
|
48
|
+
toolchainBin: string
|
|
49
|
+
sysroot: string
|
|
50
|
+
minimum: number
|
|
51
|
+
descriptor?: number
|
|
52
|
+
}): { object: string; registration: string; files: string[] } {
|
|
53
|
+
const names = validateObjcPeerClasses(args.classes)
|
|
54
|
+
const headers = materializeObjcSdk(args.headerCache)
|
|
55
|
+
const source = path.join(args.work, 'peer-metadata.m')
|
|
56
|
+
const object = path.join(args.work, 'peer-metadata.o')
|
|
57
|
+
const log = path.join(args.work, 'peer-metadata.log')
|
|
58
|
+
const receipt = path.join(args.work, 'peer-metadata.json')
|
|
59
|
+
const registration = path.join(args.work, 'peer-registration.swift')
|
|
60
|
+
fs.writeFileSync(
|
|
61
|
+
registration,
|
|
62
|
+
[
|
|
63
|
+
'import PeachObjC',
|
|
64
|
+
...[...new Set(args.classes.map((peer) => peer.header.split('/')[0]!))].map(
|
|
65
|
+
(module) => `import ${module}`,
|
|
66
|
+
),
|
|
67
|
+
'@_cdecl("_peach_objc_register_peers")',
|
|
68
|
+
'public func _peachRegisterObjcPeers() {',
|
|
69
|
+
...[...args.classes]
|
|
70
|
+
.sort(
|
|
71
|
+
(left, right) =>
|
|
72
|
+
Number(right.name === 'NSObject') - Number(left.name === 'NSObject'),
|
|
73
|
+
)
|
|
74
|
+
.map(
|
|
75
|
+
(peer) =>
|
|
76
|
+
` _objcRegisterPeerClass(\`${peer.name}\`.self, nativeName: "${peer.name}")`,
|
|
77
|
+
),
|
|
78
|
+
'}',
|
|
79
|
+
'',
|
|
80
|
+
].join('\n'),
|
|
81
|
+
)
|
|
82
|
+
fs.writeFileSync(
|
|
83
|
+
source,
|
|
84
|
+
[
|
|
85
|
+
...[...new Set(args.classes.map((peer) => peer.header))].map(
|
|
86
|
+
(header) => `#import <${header}>`,
|
|
87
|
+
),
|
|
88
|
+
...args.classes.map((peer) => `@implementation ${peer.name}\n@end`),
|
|
89
|
+
'extern void _peach_objc_register_peers(void);',
|
|
90
|
+
'__attribute__((constructor)) static void peach_register_objc_peers(void) {',
|
|
91
|
+
' _peach_objc_register_peers();',
|
|
92
|
+
'}',
|
|
93
|
+
'',
|
|
94
|
+
].join('\n'),
|
|
95
|
+
)
|
|
96
|
+
const command = [
|
|
97
|
+
'--target=wasm32-unknown-wasip1',
|
|
98
|
+
`--sysroot=${args.sysroot}`,
|
|
99
|
+
'-fwasm-exceptions',
|
|
100
|
+
'-fexceptions',
|
|
101
|
+
'-D_WASI_EMULATED_SIGNAL',
|
|
102
|
+
'-D_WASI_EMULATED_MMAN',
|
|
103
|
+
`-D__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__=${args.minimum}`,
|
|
104
|
+
`-D__IPHONE_OS_VERSION_MIN_REQUIRED=${args.minimum}`,
|
|
105
|
+
'-fobjc-runtime=gnustep-2.2',
|
|
106
|
+
'-fobjc-exceptions',
|
|
107
|
+
'-fobjc-arc',
|
|
108
|
+
'-fblocks',
|
|
109
|
+
// empty implementations must not synthesize framework getters or storage.
|
|
110
|
+
'-Xclang',
|
|
111
|
+
'-disable-objc-default-synthesize-properties',
|
|
112
|
+
'-Werror=objc-root-class',
|
|
113
|
+
'-F',
|
|
114
|
+
path.join(headers, 'System/Library/Frameworks'),
|
|
115
|
+
'-idirafter',
|
|
116
|
+
path.join(headers, 'usr/include'),
|
|
117
|
+
'-Os',
|
|
118
|
+
'-c',
|
|
119
|
+
source,
|
|
120
|
+
'-o',
|
|
121
|
+
object,
|
|
122
|
+
]
|
|
123
|
+
const compiler = path.join(args.toolchainBin, 'clang')
|
|
124
|
+
const result = spawnSync(compiler, command, {
|
|
125
|
+
cwd: args.work,
|
|
126
|
+
env: swiftEnvironment(),
|
|
127
|
+
encoding: 'utf8',
|
|
128
|
+
stdio: [
|
|
129
|
+
'ignore',
|
|
130
|
+
'pipe',
|
|
131
|
+
'pipe',
|
|
132
|
+
...(args.descriptor === undefined ? [] : [args.descriptor]),
|
|
133
|
+
],
|
|
134
|
+
timeout: 120_000,
|
|
135
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
136
|
+
})
|
|
137
|
+
fs.writeFileSync(
|
|
138
|
+
log,
|
|
139
|
+
`${result.stdout ?? ''}${result.stderr ?? ''}${result.error?.message ?? ''}`,
|
|
140
|
+
)
|
|
141
|
+
const digest = (file: string) =>
|
|
142
|
+
createHash('sha256').update(fs.readFileSync(file)).digest('hex')
|
|
143
|
+
fs.writeFileSync(
|
|
144
|
+
receipt,
|
|
145
|
+
JSON.stringify(
|
|
146
|
+
{
|
|
147
|
+
classes: args.classes,
|
|
148
|
+
declarations: IOS_SDK_ID,
|
|
149
|
+
compiler: digest(compiler),
|
|
150
|
+
command,
|
|
151
|
+
source: digest(source),
|
|
152
|
+
status: result.status,
|
|
153
|
+
signal: result.signal,
|
|
154
|
+
error: result.error?.message,
|
|
155
|
+
...(result.status === 0 && !result.error ? { object: digest(object) } : {}),
|
|
156
|
+
},
|
|
157
|
+
null,
|
|
158
|
+
2,
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
const files = [source, registration, log, receipt]
|
|
162
|
+
if (result.error || result.status !== 0)
|
|
163
|
+
throw new ObjcPeerMetadataError(
|
|
164
|
+
`Objective-C peer metadata compilation failed: ${log}`,
|
|
165
|
+
files,
|
|
166
|
+
!result.error && !result.signal && result.status !== null,
|
|
167
|
+
)
|
|
168
|
+
files.push(object)
|
|
169
|
+
const symbols = spawnSync(
|
|
170
|
+
path.join(args.toolchainBin, 'llvm-nm'),
|
|
171
|
+
['--format=posix', object],
|
|
172
|
+
{
|
|
173
|
+
encoding: 'utf8',
|
|
174
|
+
env: swiftEnvironment(),
|
|
175
|
+
timeout: 120_000,
|
|
176
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
177
|
+
},
|
|
178
|
+
)
|
|
179
|
+
fs.appendFileSync(
|
|
180
|
+
log,
|
|
181
|
+
`${symbols.stdout ?? ''}${symbols.stderr ?? ''}${symbols.error?.message ?? ''}`,
|
|
182
|
+
)
|
|
183
|
+
if (symbols.error || symbols.status !== 0)
|
|
184
|
+
throw new ObjcPeerMetadataError(
|
|
185
|
+
`could not inspect Objective-C peer metadata: ${log}`,
|
|
186
|
+
files,
|
|
187
|
+
!symbols.error && !symbols.signal && symbols.status !== null,
|
|
188
|
+
)
|
|
189
|
+
const emitted = [...symbols.stdout.matchAll(/^\._OBJC_CLASS_(\w+) [^U] /gm)].map(
|
|
190
|
+
(match) => match[1]!,
|
|
191
|
+
)
|
|
192
|
+
if (
|
|
193
|
+
emitted.length !== names.size ||
|
|
194
|
+
!emitted.every((name) => names.has(name)) ||
|
|
195
|
+
/^\._OBJC_CLASS_\w+ U(?: |$)/m.test(symbols.stdout) ||
|
|
196
|
+
/^_[ic]_\w+/m.test(symbols.stdout)
|
|
197
|
+
)
|
|
198
|
+
throw new ObjcPeerMetadataError(
|
|
199
|
+
`Objective-C peer metadata contains unexpected classes or methods: ${receipt}`,
|
|
200
|
+
files,
|
|
201
|
+
true,
|
|
202
|
+
)
|
|
203
|
+
return { object, registration, files }
|
|
204
|
+
}
|
package/src/swift-objc-sdk.ts
CHANGED
|
@@ -24,6 +24,7 @@ int removexattr(const char *path, const char *name, int options);
|
|
|
24
24
|
`,
|
|
25
25
|
'usr/include/MacTypes.h': `#pragma once
|
|
26
26
|
enum { noErr = 0 };
|
|
27
|
+
enum { kNilOptions = 0 };
|
|
27
28
|
`,
|
|
28
29
|
// darwin pointer and mach port identities used in public native headers.
|
|
29
30
|
'usr/include/pthread.h': `#pragma once
|
|
@@ -273,6 +274,7 @@ __attribute__((objc_root_class))
|
|
|
273
274
|
+ (void)initialize;
|
|
274
275
|
- (instancetype)init __attribute__((objc_designated_initializer));
|
|
275
276
|
+ (instancetype)new __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
|
277
|
+
+ (instancetype)allocWithZone:(struct _NSZone *)zone __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
|
276
278
|
+ (instancetype)alloc __attribute__((availability(swift, unavailable, message="use object initializers instead")));
|
|
277
279
|
+ (Class)class __attribute__((availability(swift, unavailable, message="use 'aClass.self' instead")));
|
|
278
280
|
- (id)copy;
|
|
@@ -355,6 +357,127 @@ OSStatus SecItemDelete(CFDictionaryRef query) __attribute__((availability(macos,
|
|
|
355
357
|
#ifdef __cplusplus
|
|
356
358
|
}
|
|
357
359
|
#endif
|
|
360
|
+
`,
|
|
361
|
+
'System/Library/Frameworks/CoreData.framework/Headers/CoreData.h': `#pragma once
|
|
362
|
+
#import <CoreData/NSManagedObjectModel.h>
|
|
363
|
+
#import <CoreData/NSPersistentStoreCoordinator.h>
|
|
364
|
+
#import <CoreData/NSManagedObjectContext.h>
|
|
365
|
+
#import <CoreData/NSFetchedResultsController.h>
|
|
366
|
+
`,
|
|
367
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectModel.h': `#pragma once
|
|
368
|
+
#import <Foundation/Foundation.h>
|
|
369
|
+
__attribute__((availability(ios,introduced=3.0)))
|
|
370
|
+
@interface NSManagedObjectModel : NSObject <NSCoding, NSCopying, NSFastEnumeration>
|
|
371
|
+
@end
|
|
372
|
+
`,
|
|
373
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSPersistentStoreCoordinator.h': `#pragma once
|
|
374
|
+
#import <Foundation/Foundation.h>
|
|
375
|
+
__attribute__((availability(ios,introduced=3.0))) NS_SWIFT_SENDABLE
|
|
376
|
+
@interface NSPersistentStoreCoordinator : NSObject <NSLocking>
|
|
377
|
+
@end
|
|
378
|
+
`,
|
|
379
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectID.h': `#pragma once
|
|
380
|
+
#import <Foundation/Foundation.h>
|
|
381
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
382
|
+
__attribute__((availability(ios,introduced=3.0))) NS_SWIFT_SENDABLE
|
|
383
|
+
@interface NSManagedObjectID : NSObject <NSCopying>
|
|
384
|
+
@end
|
|
385
|
+
NS_ASSUME_NONNULL_END
|
|
386
|
+
`,
|
|
387
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSManagedObject.h': `#pragma once
|
|
388
|
+
#import <Foundation/Foundation.h>
|
|
389
|
+
#import <CoreData/NSManagedObjectID.h>
|
|
390
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
391
|
+
__attribute__((availability(ios,introduced=3.0))) NS_SWIFT_NONISOLATED NS_SWIFT_NONSENDABLE __attribute__((objc_requires_property_definitions))
|
|
392
|
+
@interface NSManagedObject : NSObject
|
|
393
|
+
@property (nonatomic, readonly, strong) NSManagedObjectID *objectID;
|
|
394
|
+
@property (nonatomic, getter=isFault, readonly) BOOL fault;
|
|
395
|
+
@end
|
|
396
|
+
NS_ASSUME_NONNULL_END
|
|
397
|
+
`,
|
|
398
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSManagedObjectContext.h': `#pragma once
|
|
399
|
+
#import <Foundation/Foundation.h>
|
|
400
|
+
#import <CoreData/NSManagedObject.h>
|
|
401
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
402
|
+
__attribute__((availability(ios,introduced=3.0))) NS_SWIFT_NONISOLATED NS_SWIFT_SENDABLE
|
|
403
|
+
@interface NSManagedObjectContext : NSObject <NSCoding, NSLocking>
|
|
404
|
+
- (nullable __kindof NSManagedObject *)existingObjectWithID:(NSManagedObjectID *)objectID error:(NSError **)error __attribute__((availability(ios,introduced=3.0)));
|
|
405
|
+
@end
|
|
406
|
+
NS_ASSUME_NONNULL_END
|
|
407
|
+
`,
|
|
408
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSPersistentStoreRequest.h': `#pragma once
|
|
409
|
+
#import <Foundation/Foundation.h>
|
|
410
|
+
__attribute__((availability(ios,introduced=5.0)))
|
|
411
|
+
@interface NSPersistentStoreRequest : NSObject <NSCopying>
|
|
412
|
+
@end
|
|
413
|
+
`,
|
|
414
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSFetchRequest.h': `#pragma once
|
|
415
|
+
#import <Foundation/Foundation.h>
|
|
416
|
+
#import <CoreData/NSPersistentStoreRequest.h>
|
|
417
|
+
#import <CoreData/NSManagedObject.h>
|
|
418
|
+
#import <CoreData/NSManagedObjectID.h>
|
|
419
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
420
|
+
@protocol NSFetchRequestResult <NSObject>
|
|
421
|
+
@end
|
|
422
|
+
@interface NSNumber (NSFetchedResultSupport) <NSFetchRequestResult>
|
|
423
|
+
@end
|
|
424
|
+
@interface NSDictionary (NSFetchedResultSupport) <NSFetchRequestResult>
|
|
425
|
+
@end
|
|
426
|
+
@interface NSManagedObject (NSFetchedResultSupport) <NSFetchRequestResult>
|
|
427
|
+
@end
|
|
428
|
+
@interface NSManagedObjectID (NSFetchedResultSupport) <NSFetchRequestResult>
|
|
429
|
+
@end
|
|
430
|
+
__attribute__((availability(ios,introduced=3.0)))
|
|
431
|
+
@interface NSFetchRequest<__covariant ResultType:id<NSFetchRequestResult>> : NSPersistentStoreRequest <NSCoding, NSCopying>
|
|
432
|
+
@property (nullable, nonatomic, readonly, strong) NSString *entityName __attribute__((availability(ios,introduced=4.0)));
|
|
433
|
+
@end
|
|
434
|
+
NS_ASSUME_NONNULL_END
|
|
435
|
+
`,
|
|
436
|
+
'System/Library/Frameworks/CoreData.framework/Headers/NSFetchedResultsController.h': `#pragma once
|
|
437
|
+
#import <Foundation/Foundation.h>
|
|
438
|
+
#import <CoreData/NSManagedObjectContext.h>
|
|
439
|
+
#import <CoreData/NSFetchRequest.h>
|
|
440
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
441
|
+
@protocol NSFetchedResultsControllerDelegate;
|
|
442
|
+
@protocol NSFetchedResultsSectionInfo;
|
|
443
|
+
__attribute__((availability(ios,introduced=3.0)))
|
|
444
|
+
@interface NSFetchedResultsController<ResultType:id<NSFetchRequestResult>> : NSObject
|
|
445
|
+
- (instancetype)initWithFetchRequest:(NSFetchRequest<ResultType> *)fetchRequest managedObjectContext:(NSManagedObjectContext *)context sectionNameKeyPath:(nullable NSString *)sectionNameKeyPath cacheName:(nullable NSString *)name;
|
|
446
|
+
- (BOOL)performFetch:(NSError **)error;
|
|
447
|
+
@property (nonatomic, readonly) NSFetchRequest<ResultType> *fetchRequest;
|
|
448
|
+
@property (nonatomic, readonly) NSManagedObjectContext *managedObjectContext;
|
|
449
|
+
@property (nullable, nonatomic, assign) id<NSFetchedResultsControllerDelegate> delegate;
|
|
450
|
+
@property (nullable, nonatomic, readonly) NSArray<ResultType> *fetchedObjects;
|
|
451
|
+
- (ResultType)objectAtIndexPath:(NSIndexPath *)indexPath;
|
|
452
|
+
- (nullable NSIndexPath *)indexPathForObject:(ResultType)object;
|
|
453
|
+
@property (nullable, nonatomic, readonly) NSArray<id<NSFetchedResultsSectionInfo>> *sections;
|
|
454
|
+
@end
|
|
455
|
+
@protocol NSFetchedResultsSectionInfo
|
|
456
|
+
@property (nonatomic, readonly) NSString *name;
|
|
457
|
+
@property (nullable, nonatomic, readonly) NSString *indexTitle;
|
|
458
|
+
@property (nonatomic, readonly) NSUInteger numberOfObjects;
|
|
459
|
+
@property (nullable, nonatomic, readonly) NSArray *objects;
|
|
460
|
+
@end
|
|
461
|
+
typedef NS_ENUM(NSUInteger, NSFetchedResultsChangeType) {
|
|
462
|
+
NSFetchedResultsChangeInsert = 1,
|
|
463
|
+
NSFetchedResultsChangeDelete = 2,
|
|
464
|
+
NSFetchedResultsChangeMove = 3,
|
|
465
|
+
NSFetchedResultsChangeUpdate = 4
|
|
466
|
+
} __attribute__((availability(ios,introduced=3.0)));
|
|
467
|
+
@protocol NSFetchedResultsControllerDelegate <NSObject>
|
|
468
|
+
@optional
|
|
469
|
+
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(nullable NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(nullable NSIndexPath *)newIndexPath;
|
|
470
|
+
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type;
|
|
471
|
+
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller;
|
|
472
|
+
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller;
|
|
473
|
+
@end
|
|
474
|
+
NS_ASSUME_NONNULL_END
|
|
475
|
+
`,
|
|
476
|
+
'System/Library/Frameworks/CoreData.framework/Modules/module.modulemap': `framework module CoreData [system] {
|
|
477
|
+
umbrella header "CoreData.h"
|
|
478
|
+
export *
|
|
479
|
+
module * { export * }
|
|
480
|
+
}
|
|
358
481
|
`,
|
|
359
482
|
'System/Library/Frameworks/Security.framework/Modules/module.modulemap': `framework module Security {
|
|
360
483
|
umbrella header "Security.h"
|
|
@@ -603,7 +726,7 @@ typedef struct __attribute__((objc_bridge(id))) CGColorSpace *CGColorSpaceRef;
|
|
|
603
726
|
#import <CoreGraphics/CoreGraphics.h>
|
|
604
727
|
|
|
605
728
|
@class NSException;
|
|
606
|
-
typedef void NSUncaughtExceptionHandler(NSException *exception);
|
|
729
|
+
typedef void NSUncaughtExceptionHandler(NSException * _Nonnull exception);
|
|
607
730
|
#define FOUNDATION_EXPORT extern
|
|
608
731
|
#define FOUNDATION_EXTERN extern
|
|
609
732
|
#define FOUNDATION_STATIC_INLINE static inline
|
|
@@ -978,6 +1101,9 @@ __attribute__((swift_bridge("DateInterval")))
|
|
|
978
1101
|
__attribute__((swift_bridge("URL")))
|
|
979
1102
|
@interface NSURL : NSObject <NSCopying, NSSecureCoding>
|
|
980
1103
|
@property (nullable, readonly, copy) NSString *path;
|
|
1104
|
+
@property (nullable, readonly, copy) NSString *scheme;
|
|
1105
|
+
@property (nullable, readonly, copy) NSString *host;
|
|
1106
|
+
+ (nullable instancetype)URLWithString:(NSString * _Nonnull)URLString;
|
|
981
1107
|
+ (NSURL *)fileURLWithPath:(NSString *)path;
|
|
982
1108
|
@end
|
|
983
1109
|
__attribute__((swift_bridge("URLComponents")))
|
|
@@ -988,6 +1114,7 @@ __attribute__((swift_bridge("URLQueryItem")))
|
|
|
988
1114
|
@end
|
|
989
1115
|
__attribute__((swift_bridge("URLRequest")))
|
|
990
1116
|
@interface NSURLRequest : NSObject <NSCopying, NSMutableCopying, NSSecureCoding>
|
|
1117
|
+
+ (instancetype _Nonnull)requestWithURL:(NSURL * _Nonnull)URL;
|
|
991
1118
|
@end
|
|
992
1119
|
@interface NSMutableURLRequest : NSURLRequest
|
|
993
1120
|
@end
|
|
@@ -1006,16 +1133,26 @@ NS_SWIFT_NAME(URLSessionTaskDelegate)
|
|
|
1006
1133
|
NS_SWIFT_NAME(URLSessionDataDelegate)
|
|
1007
1134
|
@protocol NSURLSessionDataDelegate <NSURLSessionTaskDelegate>
|
|
1008
1135
|
@end
|
|
1136
|
+
@class NSURLSessionDataTask;
|
|
1009
1137
|
NS_SWIFT_NAME(URLSession)
|
|
1138
|
+
NS_SWIFT_SENDABLE
|
|
1139
|
+
__attribute__((availability(ios,introduced=7.0)))
|
|
1010
1140
|
@interface NSURLSession : NSObject
|
|
1141
|
+
@property (class, readonly, strong) NSURLSession * _Nonnull sharedSession;
|
|
1142
|
+
- (NSURLSessionDataTask * _Nonnull)dataTaskWithRequest:(NSURLRequest * _Nonnull)request completionHandler:(void (NS_SWIFT_SENDABLE ^ _Nonnull)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler;
|
|
1011
1143
|
@end
|
|
1012
1144
|
NS_SWIFT_NAME(URLSessionTask)
|
|
1145
|
+
NS_SWIFT_SENDABLE
|
|
1146
|
+
__attribute__((availability(ios,introduced=7.0)))
|
|
1013
1147
|
@interface NSURLSessionTask : NSObject <NSCopying>
|
|
1148
|
+
- (void)resume;
|
|
1014
1149
|
@end
|
|
1015
1150
|
NS_SWIFT_NAME(URLSessionTaskMetrics)
|
|
1016
1151
|
@interface NSURLSessionTaskMetrics : NSObject
|
|
1017
1152
|
@end
|
|
1018
1153
|
NS_SWIFT_NAME(URLSessionDataTask)
|
|
1154
|
+
NS_SWIFT_SENDABLE
|
|
1155
|
+
__attribute__((availability(ios,introduced=7.0)))
|
|
1019
1156
|
@interface NSURLSessionDataTask : NSURLSessionTask
|
|
1020
1157
|
@end
|
|
1021
1158
|
NS_SWIFT_NAME(URLSessionConfiguration)
|
|
@@ -1158,8 +1295,18 @@ NS_SWIFT_NAME(DateFormatter)
|
|
|
1158
1295
|
NS_SWIFT_NAME(NumberFormatter)
|
|
1159
1296
|
@interface NSNumberFormatter : NSObject
|
|
1160
1297
|
@end
|
|
1298
|
+
typedef NS_OPTIONS(NSUInteger, NSJSONReadingOptions) {
|
|
1299
|
+
NSJSONReadingMutableContainers = (1UL << 0),
|
|
1300
|
+
NSJSONReadingMutableLeaves = (1UL << 1),
|
|
1301
|
+
NSJSONReadingFragmentsAllowed = (1UL << 2),
|
|
1302
|
+
NSJSONReadingJSON5Allowed __attribute__((availability(ios,introduced=15.0))) = (1UL << 3),
|
|
1303
|
+
NSJSONReadingTopLevelDictionaryAssumed __attribute__((availability(ios,introduced=15.0))) = (1UL << 4),
|
|
1304
|
+
NSJSONReadingAllowFragments __attribute__((availability(ios,introduced=5.0,deprecated=100000,replacement="NSJSONReadingFragmentsAllowed"))) = NSJSONReadingFragmentsAllowed
|
|
1305
|
+
} __attribute__((availability(ios,introduced=5.0)));
|
|
1161
1306
|
NS_SWIFT_NAME(JSONSerialization)
|
|
1307
|
+
__attribute__((availability(ios,introduced=5.0)))
|
|
1162
1308
|
@interface NSJSONSerialization : NSObject
|
|
1309
|
+
+ (nullable id)JSONObjectWithData:(NSData * _Nonnull)data options:(NSJSONReadingOptions)opt error:(NSError * _Nullable * _Nullable)error;
|
|
1163
1310
|
@end
|
|
1164
1311
|
@interface NSPredicate : NSObject <NSSecureCoding, NSCopying>
|
|
1165
1312
|
@end
|
|
@@ -1279,12 +1426,14 @@ typedef NS_ENUM(NSInteger, UIImageOrientation) { UIImageOrientationUp, UIImageOr
|
|
|
1279
1426
|
typedef NS_ENUM(NSInteger, UIViewContentMode) { UIViewContentModeScaleToFill, UIViewContentModeScaleAspectFit, UIViewContentModeScaleAspectFill } NS_SWIFT_NAME(UIView.ContentMode);
|
|
1280
1427
|
typedef NS_OPTIONS(NSUInteger, UIControlState) { UIControlStateNormal = 0, UIControlStateHighlighted = 1 << 0, UIControlStateDisabled = 1 << 1, UIControlStateSelected = 1 << 2 } NS_SWIFT_NAME(UIControl.State);
|
|
1281
1428
|
typedef NS_OPTIONS(NSUInteger, UIControlEvents) { UIControlEventTouchDown = 1 << 0, UIControlEventTouchUpInside = 1 << 6, UIControlEventValueChanged = 1 << 12, UIControlEventPrimaryActionTriggered = 1 << 13 } NS_SWIFT_NAME(UIControl.Event);
|
|
1429
|
+
typedef NS_ENUM(NSInteger, UITableViewCellEditingStyle) { UITableViewCellEditingStyleNone, UITableViewCellEditingStyleDelete, UITableViewCellEditingStyleInsert } __attribute__((availability(watchos,unavailable)));
|
|
1430
|
+
typedef NS_ENUM(NSInteger, UITableViewRowAnimation) { UITableViewRowAnimationFade, UITableViewRowAnimationRight, UITableViewRowAnimationLeft, UITableViewRowAnimationTop, UITableViewRowAnimationBottom, UITableViewRowAnimationNone, UITableViewRowAnimationMiddle, UITableViewRowAnimationAutomatic = 100 };
|
|
1282
1431
|
typedef NS_ENUM(NSInteger, UIStatusBarStyle) { UIStatusBarStyleDefault = 0, UIStatusBarStyleLightContent = 1, UIStatusBarStyleDarkContent = 3 };
|
|
1283
1432
|
typedef NS_OPTIONS(NSUInteger, UIInterfaceOrientationMask) { UIInterfaceOrientationMaskPortrait = 1 << 1, UIInterfaceOrientationMaskLandscapeLeft = 1 << 4, UIInterfaceOrientationMaskLandscapeRight = 1 << 3, UIInterfaceOrientationMaskAll = 30 };
|
|
1284
1433
|
typedef NS_ENUM(NSInteger, UIInterfaceOrientation) { UIInterfaceOrientationUnknown = 0, UIInterfaceOrientationPortrait = 1, UIInterfaceOrientationPortraitUpsideDown = 2, UIInterfaceOrientationLandscapeLeft = 4, UIInterfaceOrientationLandscapeRight = 3 };
|
|
1285
1434
|
typedef NS_ENUM(NSInteger, UIModalPresentationStyle) { UIModalPresentationFullScreen = 0, UIModalPresentationPageSheet = 1, UIModalPresentationFormSheet = 2, UIModalPresentationOverFullScreen = 5, UIModalPresentationAutomatic = -2 };
|
|
1286
1435
|
typedef NS_ENUM(NSInteger, UIUserInterfaceStyle) { UIUserInterfaceStyleUnspecified, UIUserInterfaceStyleLight, UIUserInterfaceStyleDark };
|
|
1287
|
-
@class UIView, UIViewController, UIWindow, UIColor, UIImage, UIFont, UIEvent, UITouch, UIPress, UIScreen, UIWindowScene, UIGestureRecognizer;
|
|
1436
|
+
@class UIView, UIViewController, UIWindow, UIColor, UIImage, UIFont, UIEvent, UITouch, UIPress, UIScreen, UIWindowScene, UIGestureRecognizer, UITableViewCell;
|
|
1288
1437
|
@interface UIGraphicsRendererFormat : NSObject <NSCopying>
|
|
1289
1438
|
@end
|
|
1290
1439
|
@interface UIGraphicsImageRendererFormat : UIGraphicsRendererFormat
|
|
@@ -1343,6 +1492,50 @@ NS_SWIFT_UI_ACTOR @interface UIScrollView : UIView
|
|
|
1343
1492
|
@end
|
|
1344
1493
|
NS_SWIFT_UI_ACTOR @interface UITableView : UIScrollView
|
|
1345
1494
|
@end
|
|
1495
|
+
@class UISwipeActionsConfiguration, UIContextMenuConfiguration;
|
|
1496
|
+
__attribute__((availability(watchos,unavailable))) NS_SWIFT_UI_ACTOR
|
|
1497
|
+
@protocol UIScrollViewDelegate <NSObject>
|
|
1498
|
+
@optional
|
|
1499
|
+
- (void)scrollViewDidScroll:(UIScrollView *)scrollView;
|
|
1500
|
+
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView;
|
|
1501
|
+
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset __attribute__((availability(ios,introduced=5.0)));
|
|
1502
|
+
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
|
|
1503
|
+
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;
|
|
1504
|
+
@end
|
|
1505
|
+
__attribute__((availability(watchos,unavailable))) NS_SWIFT_UI_ACTOR
|
|
1506
|
+
@protocol UITableViewDelegate <NSObject, UIScrollViewDelegate>
|
|
1507
|
+
@optional
|
|
1508
|
+
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1509
|
+
- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section __attribute__((availability(ios,introduced=6.0)));
|
|
1510
|
+
- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section __attribute__((availability(ios,introduced=6.0)));
|
|
1511
|
+
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=6.0)));
|
|
1512
|
+
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1513
|
+
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
|
|
1514
|
+
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section;
|
|
1515
|
+
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=7.0)));
|
|
1516
|
+
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;
|
|
1517
|
+
- (nullable UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;
|
|
1518
|
+
- (BOOL)tableView:(UITableView *)tableView shouldHighlightRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=6.0)));
|
|
1519
|
+
- (nullable NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1520
|
+
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1521
|
+
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1522
|
+
- (nullable NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=3.0), availability(tvos,unavailable)));
|
|
1523
|
+
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView leadingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=11.0), availability(watchos,unavailable), availability(tvos,unavailable)));
|
|
1524
|
+
- (nullable UISwipeActionsConfiguration *)tableView:(UITableView *)tableView trailingSwipeActionsConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath __attribute__((availability(ios,introduced=11.0), availability(watchos,unavailable), availability(tvos,unavailable)));
|
|
1525
|
+
- (nullable UIContextMenuConfiguration *)tableView:(UITableView *)tableView contextMenuConfigurationForRowAtIndexPath:(NSIndexPath *)indexPath point:(CGPoint)point __attribute__((availability(ios,introduced=13.0), availability(tvos,introduced=17.0), availability(watchos,unavailable)));
|
|
1526
|
+
@end
|
|
1527
|
+
__attribute__((availability(watchos,unavailable))) NS_SWIFT_UI_ACTOR
|
|
1528
|
+
@protocol UITableViewDataSource <NSObject>
|
|
1529
|
+
@required
|
|
1530
|
+
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
|
|
1531
|
+
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1532
|
+
@optional
|
|
1533
|
+
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
|
|
1534
|
+
- (nullable NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
|
|
1535
|
+
- (nullable NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
|
|
1536
|
+
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1537
|
+
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
|
|
1538
|
+
@end
|
|
1346
1539
|
NS_SWIFT_UI_ACTOR @protocol UIGestureRecognizerDelegate <NSObject>
|
|
1347
1540
|
@optional
|
|
1348
1541
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer;
|
|
@@ -277,14 +277,17 @@ export function swiftPackageManifest(dir: string): SwiftPackageManifest {
|
|
|
277
277
|
const header = string(record(settingKind.headerSearchPath)._0)
|
|
278
278
|
const definition = string(record(settingKind.define)._0)
|
|
279
279
|
const value = string(record(settingKind.define)._1)
|
|
280
|
+
const disabledWarning = string(record(settingKind.disableWarning)._0)
|
|
280
281
|
const unsafe = record(settingKind.unsafeFlags)._0
|
|
281
282
|
const flags = header
|
|
282
283
|
? ['-I', path.resolve(targetDir, header)]
|
|
283
284
|
: definition
|
|
284
285
|
? [`-D${definition}${value === undefined ? '' : `=${value}`}`]
|
|
285
|
-
:
|
|
286
|
-
?
|
|
287
|
-
:
|
|
286
|
+
: disabledWarning !== undefined
|
|
287
|
+
? [`-Wno-${disabledWarning}`]
|
|
288
|
+
: Array.isArray(unsafe)
|
|
289
|
+
? unsafe.flatMap((flag) => string(flag) ?? [])
|
|
290
|
+
: null
|
|
288
291
|
if (!flags)
|
|
289
292
|
throw new Error(
|
|
290
293
|
`${name}: unsupported ${tool} compiler setting ${JSON.stringify(rawKind)}`,
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process'
|
|
2
|
+
import { createHash, randomUUID } from 'node:crypto'
|
|
3
|
+
import {
|
|
4
|
+
linkSync,
|
|
5
|
+
mkdirSync,
|
|
6
|
+
readFileSync,
|
|
7
|
+
renameSync,
|
|
8
|
+
rmSync,
|
|
9
|
+
writeFileSync,
|
|
10
|
+
} from 'node:fs'
|
|
11
|
+
import path from 'node:path'
|
|
12
|
+
import { rnxHomeDir } from './home-paths'
|
|
13
|
+
|
|
14
|
+
const POLL_MS = 250
|
|
15
|
+
|
|
16
|
+
interface Holder {
|
|
17
|
+
pid: number
|
|
18
|
+
start: string | null
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// a pid alone is reused; the start time names the process that wrote the lock.
|
|
22
|
+
function processStart(pid: number): string | null {
|
|
23
|
+
try {
|
|
24
|
+
return (
|
|
25
|
+
execFileSync('ps', ['-o', 'lstart=', '-p', String(pid)], {
|
|
26
|
+
encoding: 'utf8',
|
|
27
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
28
|
+
}).trim() || null
|
|
29
|
+
)
|
|
30
|
+
} catch {
|
|
31
|
+
return null
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function parseHolder(text: string): Holder | null {
|
|
36
|
+
try {
|
|
37
|
+
const value: unknown = JSON.parse(text)
|
|
38
|
+
if (
|
|
39
|
+
value &&
|
|
40
|
+
typeof value === 'object' &&
|
|
41
|
+
'pid' in value &&
|
|
42
|
+
typeof value.pid === 'number' &&
|
|
43
|
+
'start' in value &&
|
|
44
|
+
(typeof value.start === 'string' || value.start === null)
|
|
45
|
+
)
|
|
46
|
+
return { pid: value.pid, start: value.start }
|
|
47
|
+
} catch {}
|
|
48
|
+
return null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function readLock(lock: string): string | null {
|
|
52
|
+
try {
|
|
53
|
+
return readFileSync(lock, 'utf8')
|
|
54
|
+
} catch (error) {
|
|
55
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') return null
|
|
56
|
+
throw error
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function holderAlive(text: string): boolean {
|
|
61
|
+
const holder = parseHolder(text)
|
|
62
|
+
if (!holder) return false
|
|
63
|
+
const start = processStart(holder.pid)
|
|
64
|
+
return start !== null && start === holder.start
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function pause(ms: number, signal?: AbortSignal): Promise<void> {
|
|
68
|
+
return new Promise((resolve) => {
|
|
69
|
+
const done = () => {
|
|
70
|
+
clearTimeout(timer)
|
|
71
|
+
signal?.removeEventListener('abort', done)
|
|
72
|
+
resolve()
|
|
73
|
+
}
|
|
74
|
+
const timer = setTimeout(done, ms)
|
|
75
|
+
signal?.addEventListener('abort', done, { once: true })
|
|
76
|
+
})
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** runs `work` as the only process using a swift build root. the in-process
|
|
80
|
+
* queue orders one process's requests; two processes sharing a root each
|
|
81
|
+
* rewrite its sources and manifest, and swiftpm's own build lock only orders
|
|
82
|
+
* the builds, so a build can compile the other process's sources and then
|
|
83
|
+
* read back that process's executable. the lock lives beside the root's
|
|
84
|
+
* tree, never inside it: a write sweeps every file of the tree it does not
|
|
85
|
+
* name. a lock whose owner process is gone is taken over. */
|
|
86
|
+
export async function withSwiftRootLock<T>(
|
|
87
|
+
root: string,
|
|
88
|
+
work: () => Promise<T>,
|
|
89
|
+
signal?: AbortSignal,
|
|
90
|
+
): Promise<T> {
|
|
91
|
+
const directory = path.join(rnxHomeDir(), 'cache', 'swift-root-locks')
|
|
92
|
+
mkdirSync(directory, { recursive: true })
|
|
93
|
+
const lock = path.join(
|
|
94
|
+
directory,
|
|
95
|
+
`${createHash('sha256').update(root).digest('hex').slice(0, 32)}.lock`,
|
|
96
|
+
)
|
|
97
|
+
const token = randomUUID()
|
|
98
|
+
const owner = JSON.stringify({
|
|
99
|
+
pid: process.pid,
|
|
100
|
+
start: processStart(process.pid),
|
|
101
|
+
token,
|
|
102
|
+
})
|
|
103
|
+
const pending = `${lock}.${token}`
|
|
104
|
+
// the owner record is complete before the lock path exists, so a waiter
|
|
105
|
+
// never reads a half-written lock.
|
|
106
|
+
writeFileSync(pending, owner)
|
|
107
|
+
try {
|
|
108
|
+
for (;;) {
|
|
109
|
+
signal?.throwIfAborted()
|
|
110
|
+
try {
|
|
111
|
+
linkSync(pending, lock)
|
|
112
|
+
break
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
|
|
115
|
+
throw error
|
|
116
|
+
}
|
|
117
|
+
const held = readLock(lock)
|
|
118
|
+
if (held === null) continue
|
|
119
|
+
if (holderAlive(held)) {
|
|
120
|
+
await pause(POLL_MS, signal)
|
|
121
|
+
continue
|
|
122
|
+
}
|
|
123
|
+
// take over by moving the dead record aside. a different record in the
|
|
124
|
+
// moved file means a new owner landed first; put it back.
|
|
125
|
+
const dead = `${lock}.dead-${token}`
|
|
126
|
+
try {
|
|
127
|
+
renameSync(lock, dead)
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (error instanceof Error && 'code' in error && error.code === 'ENOENT') continue
|
|
130
|
+
throw error
|
|
131
|
+
}
|
|
132
|
+
try {
|
|
133
|
+
if (readLock(dead) !== held) {
|
|
134
|
+
try {
|
|
135
|
+
linkSync(dead, lock)
|
|
136
|
+
} catch (error) {
|
|
137
|
+
if (!(error instanceof Error && 'code' in error && error.code === 'EEXIST'))
|
|
138
|
+
throw error
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
} finally {
|
|
142
|
+
rmSync(dead, { force: true })
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
} finally {
|
|
146
|
+
rmSync(pending, { force: true })
|
|
147
|
+
}
|
|
148
|
+
try {
|
|
149
|
+
return await work()
|
|
150
|
+
} finally {
|
|
151
|
+
if (readLock(lock) === owner) rmSync(lock, { force: true })
|
|
152
|
+
}
|
|
153
|
+
}
|