react-native 0.88.0-rc.0 → 0.88.0-rc.2
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/Libraries/Core/ReactNativeVersion.js +1 -1
- package/Libraries/Renderer/implementations/ReactFabric-dev.js +3056 -1531
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +2239 -1011
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +2451 -1124
- package/React/Base/RCTVersion.m +1 -1
- package/React/FBReactNativeSpec/FBReactNativeSpec/FBReactNativeSpec.h +3 -4
- package/React/FBReactNativeSpec/FBReactNativeSpecJSI.h +8 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlags.kt +7 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxAccessor.kt +11 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsCxxInterop.kt +3 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsDefaults.kt +3 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsLocalAccessor.kt +12 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsOverrides_RNOSS_Canary_Android.kt +3 -1
- package/ReactAndroid/src/main/java/com/facebook/react/internal/featureflags/ReactNativeFeatureFlagsProvider.kt +3 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.cpp +15 -1
- package/ReactAndroid/src/main/jni/react/featureflags/JReactNativeFeatureFlagsCxxInterop.h +4 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.cpp +5 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlags.h +6 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.cpp +74 -56
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsAccessor.h +4 -2
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDefaults.h +5 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsDynamicProvider.h +10 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsOverridesOSSCanary.h +5 -1
- package/ReactCommon/react/featureflags/ReactNativeFeatureFlagsProvider.h +2 -1
- package/ReactCommon/react/nativemodule/core/iostests/RCTTurboModuleTests.mm +18 -65
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.h +1 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTInteropTurboModule.mm +1 -2
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h +2 -9
- package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +33 -71
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.cpp +6 -1
- package/ReactCommon/react/nativemodule/featureflags/NativeReactNativeFeatureFlags.h +3 -1
- package/ReactCommon/react/nativemodule/samples/platform/ios/ReactCommon/RCTSampleTurboModule.mm +8 -19
- package/package.json +16 -13
- package/scripts/codegen/generate-artifacts-executor/generateRCTThirdPartyComponents.js +18 -4
- package/scripts/setup-apple-spm.js +82 -4
- package/scripts/spm/autolinking-plugins.js +8 -5
- package/scripts/spm/expand-spm-dependencies.js +217 -156
- package/scripts/spm/generate-spm-autolinking.js +114 -88
- package/scripts/spm/generate-spm-xcodeproj.js +67 -22
- package/scripts/spm/ios-deployment-target.js +378 -0
- package/scripts/spm/read-podspec.js +156 -8
- package/scripts/spm/scaffold-package-swift.js +272 -105
- package/scripts/spm/spm-pbxproj.js +36 -21
- package/scripts/spm/spm-types.js +25 -8
- package/scripts/spm/spm-utils.js +26 -0
- package/scripts/spm/swiftpm-config.js +245 -0
- package/scripts/spm/sync-spm-autolinking.js +11 -2
- package/sdks/hermes-engine/version.properties +1 -1
- package/src/private/featureflags/ReactNativeFeatureFlags.js +10 -5
- package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +2 -1
- package/src/private/webapis/dom/nodes/ReactNativeElement.js +6 -4
- package/src/private/webapis/dom/nodes/ReadOnlyText.js +6 -4
- package/src/react-private-interface.js +4 -0
- package/src/react-private-interface.js.flow +2 -0
- package/types_generated/Libraries/ReactNative/FabricUIManager.d.ts +47 -0
- package/types_generated/src/react-private-interface.d.ts +4 -1
- package/React/Base/RCTArrayBuffer.h +0 -64
- package/React/Base/RCTArrayBuffer.mm +0 -127
|
@@ -10,53 +10,86 @@
|
|
|
10
10
|
|
|
11
11
|
'use strict';
|
|
12
12
|
|
|
13
|
-
const {
|
|
13
|
+
const {
|
|
14
|
+
findPodspecs,
|
|
15
|
+
readPodspecCached,
|
|
16
|
+
readPodspecNames,
|
|
17
|
+
} = require('./read-podspec');
|
|
18
|
+
const {
|
|
19
|
+
RESERVED_SWIFT_NAMES,
|
|
20
|
+
isValidSwiftName,
|
|
21
|
+
makeLogger,
|
|
22
|
+
swiftNameKey,
|
|
23
|
+
toC99Name,
|
|
24
|
+
toSwiftName,
|
|
25
|
+
} = require('./spm-utils');
|
|
26
|
+
const {readSwiftpmConfig, stringList} = require('./swiftpm-config');
|
|
14
27
|
const fs = require('node:fs');
|
|
15
28
|
const path = require('node:path');
|
|
16
29
|
|
|
17
30
|
const {warn} = makeLogger('expand-spm-dependencies');
|
|
18
31
|
|
|
19
32
|
/**
|
|
20
|
-
* expand-spm-dependencies.js — Resolves transitive native deps
|
|
21
|
-
*
|
|
33
|
+
* expand-spm-dependencies.js — Resolves transitive native deps a library
|
|
34
|
+
* declares in its `swiftpmConfig`.
|
|
22
35
|
*
|
|
23
36
|
* SPM has no equivalent of CocoaPods' podspec `s.dependency`, so library
|
|
24
37
|
* authors declare the same relationships explicitly:
|
|
25
38
|
*
|
|
26
|
-
* // react-native-reanimated/
|
|
27
|
-
*
|
|
28
|
-
* dependency: { platforms: { ios: {} } },
|
|
29
|
-
* spm: { dependencies: ['react-native-worklets'] },
|
|
30
|
-
* };
|
|
39
|
+
* // react-native-reanimated/package.json
|
|
40
|
+
* { "swiftpmConfig": { "dependencies": ["react-native-worklets"] } }
|
|
31
41
|
*
|
|
32
42
|
* This module reads the directly-autolinked deps (from autolinking.json),
|
|
33
|
-
* follows each one's
|
|
43
|
+
* follows each one's declared dependencies recursively, and returns the deduped
|
|
34
44
|
* list with autolinking-shaped entries so the downstream pipeline can convert
|
|
35
45
|
* each to an SPM target without further branching.
|
|
36
46
|
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
47
|
+
* It also resolves each dep's Swift target name — see resolveSwiftName.
|
|
48
|
+
*
|
|
49
|
+
* I/O is injected (readConfig, resolveDep, readPodspec) so the logic stays pure
|
|
50
|
+
* and testable.
|
|
39
51
|
*/
|
|
40
52
|
|
|
41
53
|
/*::
|
|
42
54
|
import type {AutolinkedDep} from './spm-types';
|
|
55
|
+
import type {SwiftpmConfig} from './swiftpm-config';
|
|
43
56
|
|
|
44
57
|
// react-native.config.js entries have a user-defined shape, so we use an
|
|
45
58
|
// inexact object type and access properties dynamically.
|
|
46
59
|
type RnConfig = {...};
|
|
47
60
|
type ReadConfig = (root: string) => ?RnConfig;
|
|
48
61
|
type ResolveDep = (name: string, fromRoot: string) => ?string;
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
//
|
|
62
|
+
// Where a resolved name came from: what the library declared, what its podspec
|
|
63
|
+
// says, or the npm-name guess. `podspecKey` narrows a podspec-sourced name to
|
|
64
|
+
// the field it was read from — `header_dir` and `module_name` can name the same
|
|
65
|
+
// library differently, and only one of them wins.
|
|
66
|
+
type PodspecNameKey = 'header_dir' | 'module_name' | 'name';
|
|
67
|
+
type ResolvedSwiftName = {
|
|
68
|
+
name: string,
|
|
69
|
+
source: 'config' | 'podspec' | 'npm',
|
|
70
|
+
podspecKey?: PodspecNameKey,
|
|
71
|
+
};
|
|
72
|
+
// The podspec fields that name a library. A PodspecModel satisfies it.
|
|
73
|
+
type PodspecFacts = {
|
|
74
|
+
readonly name?: ?string,
|
|
75
|
+
readonly moduleName?: ?string,
|
|
76
|
+
readonly headerDir?: ?string,
|
|
77
|
+
...
|
|
78
|
+
};
|
|
79
|
+
type ReadPodspec = (root: string, podspecPath: ?string) => ?PodspecFacts;
|
|
80
|
+
type ReadSwiftpmConfig = (root: string, rnConfig: ?RnConfig) => ?SwiftpmConfig;
|
|
81
|
+
// Keyed by swiftNameKey, valued with the canonical spelling: a name that only
|
|
82
|
+
// differs from a reserved one in case or punctuation is not distinct enough for
|
|
83
|
+
// the build to keep the two apart.
|
|
52
84
|
type ReservedNames = ReadonlyMap<string, string>;
|
|
53
85
|
type Options = {
|
|
54
86
|
readConfig: ReadConfig,
|
|
55
87
|
resolveDep: ResolveDep,
|
|
88
|
+
readPodspec?: ?ReadPodspec,
|
|
89
|
+
readSwiftpmConfig?: ?ReadSwiftpmConfig,
|
|
56
90
|
// Names to reserve alongside RESERVED_SWIFT_NAMES, supplied by the caller
|
|
57
91
|
// (remote mode relabels the RN package) since this module reads no config.
|
|
58
92
|
extraReservedNames?: ?ReadonlyArray<string>,
|
|
59
|
-
log?: ?Log,
|
|
60
93
|
};
|
|
61
94
|
*/
|
|
62
95
|
|
|
@@ -71,74 +104,133 @@ class SpmNameCollisionError extends Error {
|
|
|
71
104
|
}
|
|
72
105
|
}
|
|
73
106
|
|
|
74
|
-
// The charset `spm.name` must satisfy — permissive on purpose, since it has to
|
|
75
|
-
// admit header-dir style (lowercase with hyphens) as well as Swift identifiers.
|
|
76
|
-
// Shared with the app's own `spm.modules` names.
|
|
77
|
-
function isValidSwiftName(name /*: unknown */) /*: boolean */ {
|
|
78
|
-
return typeof name === 'string' && /^[A-Za-z_][A-Za-z0-9_-]*$/.test(name);
|
|
79
|
-
}
|
|
80
|
-
|
|
81
107
|
function reservedSwiftNames(
|
|
82
108
|
extraReservedNames /*: ?ReadonlyArray<string> */,
|
|
83
109
|
) /*: ReservedNames */ {
|
|
84
110
|
return new Map(
|
|
85
111
|
[...RESERVED_SWIFT_NAMES, ...(extraReservedNames ?? [])].map(name => [
|
|
86
|
-
name
|
|
112
|
+
swiftNameKey(name),
|
|
87
113
|
name,
|
|
88
114
|
]),
|
|
89
115
|
);
|
|
90
116
|
}
|
|
91
117
|
|
|
92
|
-
// The
|
|
93
|
-
//
|
|
94
|
-
|
|
118
|
+
// The prefix a podspec publishes its headers under, and the field it came from
|
|
119
|
+
// — or null when the podspec declares none. A prefix Swift cannot spell is
|
|
120
|
+
// normalized rather than abandoned: reverting to the npm name would silently
|
|
121
|
+
// produce a prefix nothing imports.
|
|
122
|
+
function podspecSwiftName(
|
|
95
123
|
npmName /*: string */,
|
|
96
|
-
|
|
97
|
-
) /*: ?string */ {
|
|
98
|
-
|
|
99
|
-
|
|
124
|
+
podspec /*: ?PodspecFacts */,
|
|
125
|
+
) /*: ?{name: string, key: PodspecNameKey} */ {
|
|
126
|
+
// CocoaPods' own order is `module_name` first (specification.rb), but our
|
|
127
|
+
// single name is the ObjC include prefix as well as the Swift module: a
|
|
128
|
+
// declared `header_dir` IS the prefix a library's consumers write, so it keeps
|
|
129
|
+
// winning. `module_name` comes next, being what Swift and `@import` consumers
|
|
130
|
+
// spell, and the pod name — often dashed — is the last resort.
|
|
131
|
+
const candidates /*: ReadonlyArray<[PodspecNameKey, ?string]> */ = [
|
|
132
|
+
['header_dir', podspec?.headerDir],
|
|
133
|
+
['module_name', podspec?.moduleName],
|
|
134
|
+
['name', podspec?.name],
|
|
135
|
+
];
|
|
136
|
+
for (const [key, candidate] of candidates) {
|
|
137
|
+
if (typeof candidate !== 'string' || candidate.length === 0) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
// Ruby the evaluator never ran: what the prefix would be is unknowable, so
|
|
141
|
+
// the npm name is the honest answer — and, not being derived, it is not
|
|
142
|
+
// recorded in the library's package.json.
|
|
143
|
+
if (candidate.includes('#{')) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
if (isValidSwiftName(candidate)) {
|
|
147
|
+
return {name: candidate, key};
|
|
148
|
+
}
|
|
149
|
+
const normalized = toC99Name(candidate);
|
|
150
|
+
warn(
|
|
151
|
+
`'${npmName}' declares the podspec prefix '${candidate}', which is not a valid Swift target name; using '${normalized}'. ` +
|
|
152
|
+
`Set 'swiftpmConfig.name' in ${npmName}'s package.json to choose the prefix yourself.`,
|
|
153
|
+
);
|
|
154
|
+
return {name: normalized, key};
|
|
155
|
+
}
|
|
156
|
+
return null;
|
|
100
157
|
}
|
|
101
158
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
159
|
+
/**
|
|
160
|
+
* The Swift target name for one dep, which is also the prefix its headers are
|
|
161
|
+
* imported under (`#import <Name/Header.h>`), and where it came from. The name
|
|
162
|
+
* a library declares wins; the podspec is the transitional source of truth
|
|
163
|
+
* behind it — `react-native-svg` publishes `RNSVG`, not `ReactNativeSvg` — in
|
|
164
|
+
* the order `header_dir` → `module_name` → pod name. The npm name is the last
|
|
165
|
+
* resort, for a library that ships a `Package.swift` and no podspec.
|
|
166
|
+
*
|
|
167
|
+
* The source is what tells the scaffolder which names are safe to write into a
|
|
168
|
+
* library's package.json: a derived one, never a guessed one.
|
|
169
|
+
*/
|
|
107
170
|
function resolveSwiftName(
|
|
108
171
|
npmName /*: string */,
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
if (override != null) {
|
|
116
|
-
if (typeof override !== 'string' || override.length === 0) {
|
|
172
|
+
spmConfig /*: ?SwiftpmConfig */,
|
|
173
|
+
podspec /*: ?PodspecFacts */,
|
|
174
|
+
) /*: ResolvedSwiftName */ {
|
|
175
|
+
const declared = spmConfig?.name;
|
|
176
|
+
if (declared != null) {
|
|
177
|
+
if (typeof declared !== 'string' || declared.length === 0) {
|
|
117
178
|
throw new Error(
|
|
118
|
-
`react-native autolinking: '${npmName}'
|
|
179
|
+
`react-native autolinking: '${npmName}' declares an invalid SwiftPM name: expected a non-empty string, got ${String(declared)}. Set 'swiftpmConfig.name' in its package.json.`,
|
|
119
180
|
);
|
|
120
181
|
}
|
|
121
|
-
if (!isValidSwiftName(
|
|
182
|
+
if (!isValidSwiftName(declared)) {
|
|
122
183
|
throw new Error(
|
|
123
|
-
`react-native autolinking: '${npmName}'
|
|
184
|
+
`react-native autolinking: '${npmName}' declares an invalid SwiftPM name '${declared}': must start with a letter or underscore and contain only letters, digits, underscores, or hyphens. Set 'swiftpmConfig.name' in its package.json.`,
|
|
124
185
|
);
|
|
125
186
|
}
|
|
126
|
-
return
|
|
187
|
+
return {name: declared, source: 'config'};
|
|
127
188
|
}
|
|
128
189
|
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
131
|
-
return
|
|
190
|
+
const fromPodspec = podspecSwiftName(npmName, podspec);
|
|
191
|
+
if (fromPodspec != null) {
|
|
192
|
+
return {
|
|
193
|
+
name: fromPodspec.name,
|
|
194
|
+
source: 'podspec',
|
|
195
|
+
podspecKey: fromPodspec.key,
|
|
196
|
+
};
|
|
132
197
|
}
|
|
133
|
-
const
|
|
134
|
-
if (
|
|
135
|
-
|
|
198
|
+
const fromNpm = toSwiftName(npmName);
|
|
199
|
+
if (podspec != null) {
|
|
200
|
+
warn(
|
|
201
|
+
`'${npmName}' ships a podspec React Native could not read a name from (CocoaPods may not be installed), so it is named '${fromNpm}' after its npm package instead. ` +
|
|
202
|
+
`A machine that can read the podspec may resolve a different name — set 'swiftpmConfig.name' in ${npmName}'s package.json to settle it everywhere.`,
|
|
203
|
+
);
|
|
136
204
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
205
|
+
return {name: fromNpm, source: 'npm'};
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function collisionDiagnosis(
|
|
209
|
+
existing /*: string */,
|
|
210
|
+
swiftName /*: string */,
|
|
211
|
+
) /*: string */ {
|
|
212
|
+
if (existing === swiftName) {
|
|
213
|
+
return `both resolve to '${swiftName}'.`;
|
|
214
|
+
}
|
|
215
|
+
if (existing.toLowerCase() === swiftName.toLowerCase()) {
|
|
216
|
+
return `differ only in case, which collides on case-insensitive filesystems.`;
|
|
217
|
+
}
|
|
218
|
+
return `both compile as the module '${toC99Name(swiftName)}' — SwiftPM replaces every character C99 rejects.`;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Vaguer about the clash than the dep-vs-dep message on purpose: this set spans
|
|
222
|
+
// package identities and product names, which collide differently.
|
|
223
|
+
function reservedDiagnosis(
|
|
224
|
+
swiftName /*: string */,
|
|
225
|
+
reservedName /*: string */,
|
|
226
|
+
) /*: string */ {
|
|
227
|
+
if (reservedName === swiftName) {
|
|
228
|
+
return `which React Native reserves for its own SPM package and products.`;
|
|
229
|
+
}
|
|
230
|
+
if (reservedName.toLowerCase() === swiftName.toLowerCase()) {
|
|
231
|
+
return `which differs from React Native's reserved '${reservedName}' only in case — not distinct enough for the build to keep the two apart.`;
|
|
232
|
+
}
|
|
233
|
+
return `which compiles as the same module as React Native's reserved '${reservedName}'.`;
|
|
142
234
|
}
|
|
143
235
|
|
|
144
236
|
function assertNameNotReserved(
|
|
@@ -146,24 +238,21 @@ function assertNameNotReserved(
|
|
|
146
238
|
reserved /*: ReservedNames */,
|
|
147
239
|
labels /*: {label: string, remedy: string} */,
|
|
148
240
|
) /*: void */ {
|
|
149
|
-
const reservedName = reserved.get(swiftName
|
|
241
|
+
const reservedName = reserved.get(swiftNameKey(swiftName));
|
|
150
242
|
if (reservedName == null) {
|
|
151
243
|
return;
|
|
152
244
|
}
|
|
153
|
-
// Vaguer about the case clash than the dep-vs-dep message on purpose: this
|
|
154
|
-
// set spans package identities and product names, which collide differently.
|
|
155
245
|
throw new SpmNameCollisionError(
|
|
156
246
|
`react-native autolinking: SPM Swift name collision: ${labels.label} resolves to '${swiftName}', ` +
|
|
157
|
-
(reservedName
|
|
158
|
-
? `which React Native reserves for its own SPM package and products.`
|
|
159
|
-
: `which differs from React Native's reserved '${reservedName}' only in case — not distinct enough for the build to keep the two apart.`) +
|
|
247
|
+
reservedDiagnosis(swiftName, reservedName) +
|
|
160
248
|
` ${labels.remedy}`,
|
|
161
249
|
);
|
|
162
250
|
}
|
|
163
251
|
|
|
164
252
|
/**
|
|
165
253
|
* Throws when `swiftName` is one React Native's own manifests use. `remedy` is
|
|
166
|
-
* the fix: a library sets `
|
|
254
|
+
* the fix: a library sets `swiftpmConfig.name`, an app renames its
|
|
255
|
+
* `swiftpmConfig.modules` entry.
|
|
167
256
|
*/
|
|
168
257
|
function assertSwiftNameNotReserved(
|
|
169
258
|
swiftName /*: string */,
|
|
@@ -194,83 +283,36 @@ function assertNoReservedSwiftNames(
|
|
|
194
283
|
}
|
|
195
284
|
assertNameNotReserved(swiftName, reserved, {
|
|
196
285
|
label: `'${dep.name}'`,
|
|
197
|
-
remedy: `Set a different '
|
|
286
|
+
remedy: `Set a different 'swiftpmConfig.name' in ${dep.name}'s package.json.`,
|
|
198
287
|
});
|
|
199
288
|
}
|
|
200
289
|
}
|
|
201
290
|
|
|
202
|
-
// Pulls apart deps that resolved to the same name by borrowing their npm scopes.
|
|
203
|
-
// Every scoped member of a colliding group moves: there is no non-arbitrary
|
|
204
|
-
// winner to keep. Exactly one pass — retrying would trade a diagnosable error
|
|
205
|
-
// for a name nobody can predict.
|
|
206
|
-
function disambiguateSharedSwiftNames(
|
|
207
|
-
deps /*: ReadonlyArray<AutolinkedDep> */,
|
|
208
|
-
autoNamed /*: ReadonlySet<string> */,
|
|
209
|
-
log /*: ?Log */,
|
|
210
|
-
) /*: void */ {
|
|
211
|
-
const groups /*: Map<string, Array<{dep: AutolinkedDep, swiftName: string}>> */ =
|
|
212
|
-
new Map();
|
|
213
|
-
for (const dep of deps) {
|
|
214
|
-
const swiftName = dep.swiftName;
|
|
215
|
-
if (swiftName == null) {
|
|
216
|
-
continue;
|
|
217
|
-
}
|
|
218
|
-
const key = swiftName.toLowerCase();
|
|
219
|
-
const group = groups.get(key);
|
|
220
|
-
if (group == null) {
|
|
221
|
-
groups.set(key, [{dep, swiftName}]);
|
|
222
|
-
} else {
|
|
223
|
-
group.push({dep, swiftName});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
for (const group of groups.values()) {
|
|
228
|
-
if (group.length < 2) {
|
|
229
|
-
continue;
|
|
230
|
-
}
|
|
231
|
-
for (const {dep, swiftName} of group) {
|
|
232
|
-
// A name we derived can borrow a second time (`AAReactNative`); the
|
|
233
|
-
// member whose name we did not derive is the incumbent and keeps it.
|
|
234
|
-
if (!autoNamed.has(dep.name)) {
|
|
235
|
-
continue;
|
|
236
|
-
}
|
|
237
|
-
const borrowed = scopeBorrowedName(dep.name, swiftName);
|
|
238
|
-
if (borrowed == null) {
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
const others = group
|
|
242
|
-
.filter(other => other.dep !== dep)
|
|
243
|
-
.map(other => `'${other.dep.name}'`)
|
|
244
|
-
.join(', ');
|
|
245
|
-
log?.(
|
|
246
|
-
`'${dep.name}' would share the name '${swiftName}' with ${others}, so its npm scope is prepended: '${borrowed}'. ` +
|
|
247
|
-
`Set 'spm.name' in ${dep.name}'s react-native.config.js to choose the name yourself.`,
|
|
248
|
-
);
|
|
249
|
-
dep.swiftName = borrowed;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
|
|
254
291
|
function expandSpmDependencies(
|
|
255
292
|
directDeps /*: Array<AutolinkedDep> */,
|
|
256
293
|
options /*: Options */,
|
|
257
294
|
) /*: Array<AutolinkedDep> */ {
|
|
258
|
-
const {readConfig, resolveDep,
|
|
295
|
+
const {readConfig, resolveDep, readPodspec, extraReservedNames} = options;
|
|
296
|
+
const spmConfigOf = options.readSwiftpmConfig ?? readSwiftpmConfig;
|
|
259
297
|
const reserved = reservedSwiftNames(extraReservedNames);
|
|
260
298
|
const byName /*: Map<string, AutolinkedDep> */ = new Map();
|
|
261
299
|
for (const dep of directDeps) {
|
|
262
300
|
byName.set(dep.name, {...dep, spmDependencies: []});
|
|
263
301
|
}
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
if (
|
|
271
|
-
|
|
302
|
+
// A podspec that cannot be read leaves the name to the next precedence step,
|
|
303
|
+
// rather than failing a build over a file only CocoaPods needs.
|
|
304
|
+
const podspecFor = (
|
|
305
|
+
root /*: string */,
|
|
306
|
+
podspecPath /*: ?string */,
|
|
307
|
+
) /*: ?PodspecFacts */ => {
|
|
308
|
+
if (readPodspec == null) {
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
return readPodspec(root, podspecPath);
|
|
313
|
+
} catch {
|
|
314
|
+
return null;
|
|
272
315
|
}
|
|
273
|
-
return resolveSwiftName(npmName, config, reserved, log);
|
|
274
316
|
};
|
|
275
317
|
|
|
276
318
|
const queue /*: Array<string> */ = directDeps.map(d => d.name);
|
|
@@ -283,14 +325,18 @@ function expandSpmDependencies(
|
|
|
283
325
|
if (current == null) {
|
|
284
326
|
continue;
|
|
285
327
|
}
|
|
286
|
-
const
|
|
287
|
-
// Resolve swiftName lazily from the same config read we already need for
|
|
288
|
-
// spm.dependencies — saves a duplicate readConfig call per direct dep.
|
|
328
|
+
const spmConfig = spmConfigOf(current.root, readConfig(current.root));
|
|
289
329
|
if (current.swiftName == null) {
|
|
290
|
-
|
|
330
|
+
const resolved = resolveSwiftName(
|
|
331
|
+
currentName,
|
|
332
|
+
spmConfig,
|
|
333
|
+
podspecFor(current.root, current.platforms.ios.podspecPath),
|
|
334
|
+
);
|
|
335
|
+
current.swiftName = resolved.name;
|
|
336
|
+
current.swiftNameSource = resolved.source;
|
|
337
|
+
current.swiftNamePodspecKey = resolved.podspecKey;
|
|
291
338
|
}
|
|
292
|
-
|
|
293
|
-
const transitives /*: Array<string> */ = config?.spm?.dependencies ?? [];
|
|
339
|
+
const transitives = stringList(spmConfig?.dependencies);
|
|
294
340
|
|
|
295
341
|
const currentSpmDeps /*: Array<string> */ = [];
|
|
296
342
|
for (const transitiveName of transitives) {
|
|
@@ -298,7 +344,7 @@ function expandSpmDependencies(
|
|
|
298
344
|
const transitiveRoot = resolveDep(transitiveName, current.root);
|
|
299
345
|
if (transitiveRoot == null) {
|
|
300
346
|
throw new Error(
|
|
301
|
-
`react-native autolinking: '${currentName}' declares an unresolvable
|
|
347
|
+
`react-native autolinking: '${currentName}' declares an unresolvable SwiftPM dependency '${transitiveName}'. Ensure '${transitiveName}' is installed and visible via Node module resolution from ${current.root}.`,
|
|
302
348
|
);
|
|
303
349
|
}
|
|
304
350
|
|
|
@@ -312,11 +358,18 @@ function expandSpmDependencies(
|
|
|
312
358
|
continue;
|
|
313
359
|
}
|
|
314
360
|
|
|
361
|
+
const resolved = resolveSwiftName(
|
|
362
|
+
transitiveName,
|
|
363
|
+
spmConfigOf(transitiveRoot, transitiveConfig),
|
|
364
|
+
podspecFor(transitiveRoot, iosPlatform.podspecPath),
|
|
365
|
+
);
|
|
315
366
|
byName.set(transitiveName, {
|
|
316
367
|
name: transitiveName,
|
|
317
368
|
root: transitiveRoot,
|
|
318
369
|
platforms: {ios: iosPlatform},
|
|
319
|
-
swiftName:
|
|
370
|
+
swiftName: resolved.name,
|
|
371
|
+
swiftNameSource: resolved.source,
|
|
372
|
+
swiftNamePodspecKey: resolved.podspecKey,
|
|
320
373
|
spmDependencies: [],
|
|
321
374
|
});
|
|
322
375
|
queue.push(transitiveName);
|
|
@@ -328,37 +381,26 @@ function expandSpmDependencies(
|
|
|
328
381
|
|
|
329
382
|
const allDeps /*: Array<AutolinkedDep> */ = Array.from(byName.values());
|
|
330
383
|
|
|
331
|
-
disambiguateSharedSwiftNames(allDeps, autoNamed, log);
|
|
332
|
-
|
|
333
|
-
// Both checks below validate the FINAL set, after that pass: a borrowed scope
|
|
334
|
-
// can land on a reserved name, or on one another dep already holds.
|
|
335
384
|
assertNoReservedSwiftNames(allDeps, reserved);
|
|
336
385
|
|
|
337
|
-
// Collision check: two deps mapping to the same Swift name
|
|
338
|
-
//
|
|
339
|
-
//
|
|
340
|
-
//
|
|
341
|
-
//
|
|
342
|
-
// Key case-INSENSITIVELY: resolveSwiftName permits lowercase ('worklets')
|
|
343
|
-
// while toSwiftName produces TitleCase ('Worklets') — an exact-equality check
|
|
344
|
-
// passes but the two still collide as directories on the default
|
|
345
|
-
// case-insensitive macOS filesystem (synth package layout + headers tree).
|
|
386
|
+
// Collision check: two deps mapping to the same Swift name would clobber each
|
|
387
|
+
// other in the synth package layout and the centralized headers tree. Surface
|
|
388
|
+
// it now with a clear message instead of letting SPM emit a confusing
|
|
389
|
+
// duplicate-target error later. swiftNameKey is what makes two names two
|
|
390
|
+
// targets — punctuation collapses into one module, case into one directory.
|
|
346
391
|
const seen /*: Map<string, {name: string, swiftName: string}> */ = new Map();
|
|
347
392
|
for (const dep of allDeps) {
|
|
348
393
|
const swiftName = dep.swiftName;
|
|
349
394
|
if (swiftName == null) {
|
|
350
395
|
continue;
|
|
351
396
|
}
|
|
352
|
-
const key = swiftName
|
|
397
|
+
const key = swiftNameKey(swiftName);
|
|
353
398
|
const existing = seen.get(key);
|
|
354
399
|
if (existing != null) {
|
|
355
|
-
const same = existing.swiftName === swiftName;
|
|
356
400
|
throw new SpmNameCollisionError(
|
|
357
401
|
`react-native autolinking: SPM Swift name collision: '${existing.name}' ('${existing.swiftName}') and '${dep.name}' ('${swiftName}') ` +
|
|
358
|
-
(
|
|
359
|
-
|
|
360
|
-
: `differ only in case, which collides on case-insensitive filesystems.`) +
|
|
361
|
-
` Set a distinct 'spm.name' in one of their react-native.config.js files.`,
|
|
402
|
+
collisionDiagnosis(existing.swiftName, swiftName) +
|
|
403
|
+
` Set a distinct 'swiftpmConfig.name' in one of their package.json files.`,
|
|
362
404
|
);
|
|
363
405
|
}
|
|
364
406
|
seen.set(key, {name: dep.name, swiftName});
|
|
@@ -424,12 +466,31 @@ function defaultResolveDep(
|
|
|
424
466
|
}
|
|
425
467
|
}
|
|
426
468
|
|
|
469
|
+
function defaultReadPodspec(
|
|
470
|
+
root /*: string */,
|
|
471
|
+
podspecPath /*: ?string */,
|
|
472
|
+
) /*: ?PodspecFacts */ {
|
|
473
|
+
// Deps synthesized from declared dependencies carry no podspecPath — only
|
|
474
|
+
// autolinking.json records one — so the dep root is searched as well.
|
|
475
|
+
const found = podspecPath ?? findPodspecs(root)[0];
|
|
476
|
+
if (found == null) {
|
|
477
|
+
return null;
|
|
478
|
+
}
|
|
479
|
+
try {
|
|
480
|
+
// Ruby-computed fields need the real evaluator; everything else is spared
|
|
481
|
+
// the `pod ipc spec` spawn.
|
|
482
|
+
return readPodspecNames(found) ?? readPodspecCached(found);
|
|
483
|
+
} catch {
|
|
484
|
+
return null;
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
427
488
|
module.exports = {
|
|
428
489
|
SpmNameCollisionError,
|
|
429
490
|
assertSwiftNameNotReserved,
|
|
430
491
|
expandSpmDependencies,
|
|
431
|
-
isValidSwiftName,
|
|
432
492
|
resolveSwiftName,
|
|
433
493
|
defaultReadConfig,
|
|
494
|
+
defaultReadPodspec,
|
|
434
495
|
defaultResolveDep,
|
|
435
496
|
};
|