react-native 0.86.0-rc.0 → 0.86.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/Components/Pressable/Pressable.d.ts +1 -0
- package/Libraries/Components/Pressable/useAndroidRippleForView.js +7 -8
- package/Libraries/Components/Touchable/TouchableNativeFeedback.js +6 -10
- package/Libraries/Components/View/ViewPropTypes.js +3 -1
- package/Libraries/Core/ReactNativeVersion.js +1 -1
- package/React/Base/RCTVersion.m +1 -1
- package/ReactAndroid/api/ReactAndroid.api +1 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/modules/image/ImageLoaderModule.kt +59 -62
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactDrawableHelper.kt +59 -20
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.kt +30 -0
- package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewManager.kt +2 -7
- package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/HostPlatformViewProps.cpp +19 -2
- package/ReactCommon/react/renderer/components/view/platform/android/react/renderer/components/view/NativeDrawable.h +47 -16
- package/package.json +9 -9
- package/scripts/cocoapods/rncore.rb +65 -11
- package/scripts/cocoapods/rndependencies.rb +65 -11
- package/scripts/cocoapods/utils.rb +52 -0
- package/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +8 -3
- package/scripts/react_native_pods.rb +15 -2
- package/sdks/hermes-engine/hermes-utils.rb +92 -5
- package/types_generated/Libraries/Components/Pressable/useAndroidRippleForView.d.ts +5 -2
- package/types_generated/Libraries/Components/Touchable/TouchableNativeFeedback.d.ts +8 -6
- package/types_generated/Libraries/Components/View/ViewPropTypes.d.ts +4 -2
|
@@ -10,6 +10,7 @@
|
|
|
10
10
|
#include <glog/logging.h>
|
|
11
11
|
#include <react/debug/react_native_expect.h>
|
|
12
12
|
#include <react/renderer/core/PropsParserContext.h>
|
|
13
|
+
#include <react/renderer/core/graphicsConversions.h>
|
|
13
14
|
#include <react/renderer/graphics/Float.h>
|
|
14
15
|
#include <unordered_map>
|
|
15
16
|
|
|
@@ -22,14 +23,16 @@ struct NativeDrawable {
|
|
|
22
23
|
};
|
|
23
24
|
|
|
24
25
|
struct Ripple {
|
|
25
|
-
std::optional<
|
|
26
|
+
std::optional<SharedColor> color{};
|
|
27
|
+
std::optional<std::vector<std::string>> colorResourcePaths{};
|
|
26
28
|
std::optional<Float> rippleRadius{};
|
|
27
29
|
bool borderless{false};
|
|
30
|
+
std::optional<Float> alpha{};
|
|
28
31
|
|
|
29
32
|
bool operator==(const Ripple &rhs) const
|
|
30
33
|
{
|
|
31
|
-
return std::tie(this->color, this->borderless, this->rippleRadius) ==
|
|
32
|
-
std::tie(rhs.color, rhs.borderless, rhs.rippleRadius);
|
|
34
|
+
return std::tie(this->color, this->colorResourcePaths, this->borderless, this->rippleRadius, this->alpha) ==
|
|
35
|
+
std::tie(rhs.color, rhs.colorResourcePaths, rhs.borderless, rhs.rippleRadius, rhs.alpha);
|
|
33
36
|
}
|
|
34
37
|
};
|
|
35
38
|
|
|
@@ -59,8 +62,7 @@ struct NativeDrawable {
|
|
|
59
62
|
~NativeDrawable() = default;
|
|
60
63
|
};
|
|
61
64
|
|
|
62
|
-
static inline void
|
|
63
|
-
fromRawValue(const PropsParserContext & /*context*/, const RawValue &rawValue, NativeDrawable &result)
|
|
65
|
+
static inline void fromRawValue(const PropsParserContext &context, const RawValue &rawValue, NativeDrawable &result)
|
|
64
66
|
{
|
|
65
67
|
auto map = (std::unordered_map<std::string, RawValue>)rawValue;
|
|
66
68
|
|
|
@@ -73,24 +75,53 @@ fromRawValue(const PropsParserContext & /*context*/, const RawValue &rawValue, N
|
|
|
73
75
|
react_native_expect(attrIterator != map.end() && attrIterator->second.hasType<std::string>());
|
|
74
76
|
|
|
75
77
|
result = NativeDrawable{
|
|
76
|
-
(std::string)attrIterator->second,
|
|
77
|
-
{},
|
|
78
|
-
NativeDrawable::Kind::ThemeAttr,
|
|
78
|
+
.themeAttr = (std::string)attrIterator->second,
|
|
79
|
+
.ripple = {},
|
|
80
|
+
.kind = NativeDrawable::Kind::ThemeAttr,
|
|
79
81
|
};
|
|
80
82
|
} else if (type == "RippleAndroid") {
|
|
81
83
|
auto color = map.find("color");
|
|
82
84
|
auto borderless = map.find("borderless");
|
|
83
85
|
auto rippleRadius = map.find("rippleRadius");
|
|
86
|
+
auto alpha = map.find("alpha");
|
|
87
|
+
|
|
88
|
+
std::optional<SharedColor> parsedColor{};
|
|
89
|
+
std::optional<std::vector<std::string>> parsedColorResourcePaths{};
|
|
90
|
+
if (color != map.end()) {
|
|
91
|
+
if (color->second.hasType<std::unordered_map<std::string, std::vector<std::string>>>()) {
|
|
92
|
+
auto colorMap = (std::unordered_map<std::string, std::vector<std::string>>)color->second;
|
|
93
|
+
auto pathsIt = colorMap.find("resource_paths");
|
|
94
|
+
if (pathsIt != colorMap.end()) {
|
|
95
|
+
parsedColorResourcePaths = pathsIt->second;
|
|
96
|
+
}
|
|
97
|
+
} else {
|
|
98
|
+
SharedColor resolved;
|
|
99
|
+
fromRawValue(context, color->second, resolved);
|
|
100
|
+
if (resolved) {
|
|
101
|
+
parsedColor = resolved;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
std::optional<Float> parsedAlpha{};
|
|
107
|
+
if (alpha != map.end() && alpha->second.hasType<Float>()) {
|
|
108
|
+
parsedAlpha = (Float)alpha->second;
|
|
109
|
+
}
|
|
84
110
|
|
|
85
111
|
result = NativeDrawable{
|
|
86
|
-
std::string{},
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
112
|
+
.themeAttr = std::string{},
|
|
113
|
+
.ripple =
|
|
114
|
+
NativeDrawable::Ripple{
|
|
115
|
+
.color = parsedColor,
|
|
116
|
+
.colorResourcePaths = parsedColorResourcePaths,
|
|
117
|
+
.rippleRadius = rippleRadius != map.end() && rippleRadius->second.hasType<Float>()
|
|
118
|
+
? (Float)rippleRadius->second
|
|
119
|
+
: std::optional<Float>{},
|
|
120
|
+
.borderless =
|
|
121
|
+
borderless != map.end() && borderless->second.hasType<bool>() ? (bool)borderless->second : false,
|
|
122
|
+
.alpha = parsedAlpha,
|
|
123
|
+
},
|
|
124
|
+
.kind = NativeDrawable::Kind::Ripple,
|
|
94
125
|
};
|
|
95
126
|
} else {
|
|
96
127
|
LOG(ERROR) << "Unknown native drawable type: " << type;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.86.0-rc.
|
|
3
|
+
"version": "0.86.0-rc.2",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -149,7 +149,7 @@
|
|
|
149
149
|
"featureflags": "node ./scripts/featureflags/index.js"
|
|
150
150
|
},
|
|
151
151
|
"peerDependencies": {
|
|
152
|
-
"@react-native/jest-preset": "0.86.0-rc.
|
|
152
|
+
"@react-native/jest-preset": "0.86.0-rc.2",
|
|
153
153
|
"@types/react": "^19.1.1",
|
|
154
154
|
"react": "^19.2.3"
|
|
155
155
|
},
|
|
@@ -162,13 +162,13 @@
|
|
|
162
162
|
}
|
|
163
163
|
},
|
|
164
164
|
"dependencies": {
|
|
165
|
-
"@react-native/assets-registry": "0.86.0-rc.
|
|
166
|
-
"@react-native/codegen": "0.86.0-rc.
|
|
167
|
-
"@react-native/community-cli-plugin": "0.86.0-rc.
|
|
168
|
-
"@react-native/gradle-plugin": "0.86.0-rc.
|
|
169
|
-
"@react-native/js-polyfills": "0.86.0-rc.
|
|
170
|
-
"@react-native/normalize-colors": "0.86.0-rc.
|
|
171
|
-
"@react-native/virtualized-lists": "0.86.0-rc.
|
|
165
|
+
"@react-native/assets-registry": "0.86.0-rc.2",
|
|
166
|
+
"@react-native/codegen": "0.86.0-rc.2",
|
|
167
|
+
"@react-native/community-cli-plugin": "0.86.0-rc.2",
|
|
168
|
+
"@react-native/gradle-plugin": "0.86.0-rc.2",
|
|
169
|
+
"@react-native/js-polyfills": "0.86.0-rc.2",
|
|
170
|
+
"@react-native/normalize-colors": "0.86.0-rc.2",
|
|
171
|
+
"@react-native/virtualized-lists": "0.86.0-rc.2",
|
|
172
172
|
"abort-controller": "^3.0.0",
|
|
173
173
|
"anser": "^1.4.9",
|
|
174
174
|
"ansi-regex": "^5.0.0",
|
|
@@ -103,7 +103,7 @@ class ReactNativeCoreUtils
|
|
|
103
103
|
if ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"]
|
|
104
104
|
abort_if_use_local_rncore_with_no_file()
|
|
105
105
|
rncore_log("Using local xcframework at #{ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"]}")
|
|
106
|
-
return {:http =>
|
|
106
|
+
return {:http => ReactNativePodsUtils.local_file_uri(ENV["RCT_TESTONLY_RNCORE_TARBALL_PATH"]) }
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
if ENV["RCT_USE_PREBUILT_RNCORE"] == "1"
|
|
@@ -160,7 +160,8 @@ class ReactNativeCoreUtils
|
|
|
160
160
|
rncore_log(" #{Pathname.new(destinationDebug).relative_path_from(Pathname.pwd).to_s}")
|
|
161
161
|
rncore_log(" #{Pathname.new(destinationRelease).relative_path_from(Pathname.pwd).to_s}")
|
|
162
162
|
|
|
163
|
-
return {:http =>
|
|
163
|
+
return {:http => stable_tarball_url(@@react_native_version, :debug) } unless @@download_dsyms
|
|
164
|
+
return {:http => ReactNativePodsUtils.local_file_uri(destinationDebug) }
|
|
164
165
|
end
|
|
165
166
|
|
|
166
167
|
def self.podspec_source_download_prebuilt_nightly_tarball()
|
|
@@ -196,7 +197,8 @@ class ReactNativeCoreUtils
|
|
|
196
197
|
rncore_log("Resolved nightly ReactNativeCore-prebuilt version:")
|
|
197
198
|
rncore_log(" #{Pathname.new(destinationDebug).relative_path_from(Pathname.pwd).to_s}")
|
|
198
199
|
rncore_log(" #{Pathname.new(destinationRelease).relative_path_from(Pathname.pwd).to_s}")
|
|
199
|
-
return {:http =>
|
|
200
|
+
return {:http => nightly_tarball_url(@@react_native_version, :debug) } unless @@download_dsyms
|
|
201
|
+
return {:http => ReactNativePodsUtils.local_file_uri(destinationDebug) }
|
|
200
202
|
end
|
|
201
203
|
|
|
202
204
|
def self.process_dsyms(frameworkTarball, dSymsTarball)
|
|
@@ -404,17 +406,69 @@ class ReactNativeCoreUtils
|
|
|
404
406
|
end
|
|
405
407
|
|
|
406
408
|
def self.download_rncore_tarball(react_native_path, tarball_url, version, configuration, dsyms = false)
|
|
407
|
-
|
|
408
|
-
"
|
|
409
|
-
"
|
|
409
|
+
filename = configuration == nil ?
|
|
410
|
+
"reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}.tar.gz" :
|
|
411
|
+
"reactnative-core-#{version}#{dsyms ? "-dSYM" : ""}-#{configuration}.tar.gz"
|
|
412
|
+
destination_path = "#{artifacts_dir()}/#{filename}"
|
|
413
|
+
|
|
414
|
+
if File.exist?(destination_path)
|
|
415
|
+
rncore_log("Tarball #{filename} already exists in Pods. Skipping download.")
|
|
416
|
+
return destination_path
|
|
417
|
+
end
|
|
410
418
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
419
|
+
`mkdir -p "#{artifacts_dir()}"`
|
|
420
|
+
|
|
421
|
+
if ReactNativePodsUtils.skip_caches?
|
|
422
|
+
rncore_log("RCT_SKIP_CACHES is set. Downloading #{filename} directly (bypassing shared cache).")
|
|
414
423
|
tmp_file = "#{artifacts_dir()}/reactnative-core.download"
|
|
415
|
-
`
|
|
424
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
425
|
+
unless File.exist?(destination_path)
|
|
426
|
+
abort("[ReactNativeCore] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
427
|
+
end
|
|
428
|
+
return destination_path
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
cached_path = File.join(ReactNativePodsUtils.shared_cache_dir(), filename)
|
|
432
|
+
if File.exist?(cached_path)
|
|
433
|
+
rncore_log("Verifying checksum for cached #{filename}...")
|
|
434
|
+
if ReactNativePodsUtils.validate_tarball(cached_path, tarball_url)
|
|
435
|
+
rncore_log("Cache hit: copying #{filename} from shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
436
|
+
FileUtils.cp(cached_path, destination_path)
|
|
437
|
+
else
|
|
438
|
+
rncore_log("Shared cache file #{filename} failed SHA verification. Re-downloading.")
|
|
439
|
+
File.delete(cached_path)
|
|
440
|
+
tmp_file = "#{artifacts_dir()}/reactnative-core.download"
|
|
441
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
442
|
+
unless File.exist?(destination_path)
|
|
443
|
+
abort("[ReactNativeCore] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
444
|
+
end
|
|
445
|
+
rncore_log("Verifying checksum for downloaded #{filename}...")
|
|
446
|
+
if ReactNativePodsUtils.validate_tarball(destination_path, tarball_url)
|
|
447
|
+
FileUtils.cp(destination_path, cached_path)
|
|
448
|
+
rncore_log("Saved #{filename} to shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
449
|
+
else
|
|
450
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
451
|
+
abort("[ReactNativeCore] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
452
|
+
end
|
|
453
|
+
end
|
|
416
454
|
else
|
|
417
|
-
rncore_log("
|
|
455
|
+
rncore_log("Cache miss: downloading #{filename} from #{tarball_url}")
|
|
456
|
+
# Download to a temporary file first so we don't cache incomplete downloads.
|
|
457
|
+
tmp_file = "#{artifacts_dir()}/reactnative-core.download"
|
|
458
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
459
|
+
unless File.exist?(destination_path)
|
|
460
|
+
abort("[ReactNativeCore] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
461
|
+
end
|
|
462
|
+
rncore_log("Verifying checksum for downloaded #{filename}...")
|
|
463
|
+
if ReactNativePodsUtils.validate_tarball(destination_path, tarball_url)
|
|
464
|
+
# Save to shared cache for future use
|
|
465
|
+
`mkdir -p "#{ReactNativePodsUtils.shared_cache_dir()}"`
|
|
466
|
+
FileUtils.cp(destination_path, cached_path)
|
|
467
|
+
rncore_log("Saved #{filename} to shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
468
|
+
else
|
|
469
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
470
|
+
abort("[ReactNativeCore] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
471
|
+
end
|
|
418
472
|
end
|
|
419
473
|
|
|
420
474
|
return destination_path
|
|
@@ -70,7 +70,7 @@ class ReactNativeDependenciesUtils
|
|
|
70
70
|
if ENV["RCT_USE_LOCAL_RN_DEP"]
|
|
71
71
|
abort_if_use_local_rndeps_with_no_file()
|
|
72
72
|
rndeps_log("Using local xcframework at #{ENV["RCT_USE_LOCAL_RN_DEP"]}")
|
|
73
|
-
return {:http =>
|
|
73
|
+
return {:http => ReactNativePodsUtils.local_file_uri(ENV["RCT_USE_LOCAL_RN_DEP"]) }
|
|
74
74
|
end
|
|
75
75
|
|
|
76
76
|
if ENV["RCT_USE_RN_DEP"] && ENV["RCT_USE_RN_DEP"] == "1"
|
|
@@ -158,10 +158,10 @@ class ReactNativeDependenciesUtils
|
|
|
158
158
|
|
|
159
159
|
url = release_tarball_url(@@react_native_version, :debug)
|
|
160
160
|
rndeps_log("Using tarball from URL: #{url}")
|
|
161
|
-
|
|
161
|
+
download_stable_rndeps(@@react_native_path, @@react_native_version, :debug)
|
|
162
162
|
download_stable_rndeps(@@react_native_path, @@react_native_version, :release)
|
|
163
163
|
|
|
164
|
-
return {:http =>
|
|
164
|
+
return {:http => url }
|
|
165
165
|
end
|
|
166
166
|
|
|
167
167
|
def self.release_tarball_url(version, build_type)
|
|
@@ -225,22 +225,76 @@ class ReactNativeDependenciesUtils
|
|
|
225
225
|
|
|
226
226
|
url = nightly_tarball_url(version, :debug)
|
|
227
227
|
rndeps_log("Using tarball from URL: #{url}")
|
|
228
|
-
|
|
228
|
+
download_nightly_rndeps(@@react_native_path, @@react_native_version, :debug)
|
|
229
229
|
download_nightly_rndeps(@@react_native_path, @@react_native_version, :release)
|
|
230
230
|
|
|
231
|
-
return {:http =>
|
|
232
|
-
return {:http => url}
|
|
231
|
+
return {:http => url }
|
|
233
232
|
end
|
|
234
233
|
|
|
235
234
|
def self.download_rndeps_tarball(react_native_path, tarball_url, version, configuration)
|
|
236
|
-
|
|
237
|
-
"
|
|
238
|
-
"
|
|
235
|
+
filename = configuration == nil ?
|
|
236
|
+
"reactnative-dependencies-#{version}.tar.gz" :
|
|
237
|
+
"reactnative-dependencies-#{version}-#{configuration}.tar.gz"
|
|
238
|
+
destination_path = "#{artifacts_dir()}/#{filename}"
|
|
239
|
+
|
|
240
|
+
if File.exist?(destination_path)
|
|
241
|
+
rndeps_log("Tarball #{filename} already exists in Pods. Skipping download.")
|
|
242
|
+
return destination_path
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
`mkdir -p "#{artifacts_dir()}"`
|
|
246
|
+
|
|
247
|
+
if ReactNativePodsUtils.skip_caches?
|
|
248
|
+
rndeps_log("RCT_SKIP_CACHES is set. Downloading #{filename} directly (bypassing shared cache).")
|
|
249
|
+
tmp_file = "#{artifacts_dir()}/reactnative-dependencies.download"
|
|
250
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
251
|
+
unless File.exist?(destination_path)
|
|
252
|
+
abort("[ReactNativeDependencies] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
253
|
+
end
|
|
254
|
+
return destination_path
|
|
255
|
+
end
|
|
239
256
|
|
|
240
|
-
|
|
257
|
+
cached_path = File.join(ReactNativePodsUtils.shared_cache_dir(), filename)
|
|
258
|
+
if File.exist?(cached_path)
|
|
259
|
+
rndeps_log("Verifying checksum for cached #{filename}...")
|
|
260
|
+
if ReactNativePodsUtils.validate_tarball(cached_path, tarball_url)
|
|
261
|
+
rndeps_log("Cache hit: copying #{filename} from shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
262
|
+
FileUtils.cp(cached_path, destination_path)
|
|
263
|
+
else
|
|
264
|
+
rndeps_log("Shared cache file #{filename} failed SHA verification. Re-downloading.")
|
|
265
|
+
File.delete(cached_path)
|
|
266
|
+
tmp_file = "#{artifacts_dir()}/reactnative-dependencies.download"
|
|
267
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
268
|
+
unless File.exist?(destination_path)
|
|
269
|
+
abort("[ReactNativeDependencies] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
270
|
+
end
|
|
271
|
+
rndeps_log("Verifying checksum for downloaded #{filename}...")
|
|
272
|
+
if ReactNativePodsUtils.validate_tarball(destination_path, tarball_url)
|
|
273
|
+
FileUtils.cp(destination_path, cached_path)
|
|
274
|
+
rndeps_log("Saved #{filename} to shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
275
|
+
else
|
|
276
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
277
|
+
abort("[ReactNativeDependencies] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
else
|
|
281
|
+
rndeps_log("Cache miss: downloading #{filename} from #{tarball_url}")
|
|
241
282
|
# Download to a temporary file first so we don't cache incomplete downloads.
|
|
242
283
|
tmp_file = "#{artifacts_dir()}/reactnative-dependencies.download"
|
|
243
|
-
`
|
|
284
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
285
|
+
unless File.exist?(destination_path)
|
|
286
|
+
abort("[ReactNativeDependencies] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
287
|
+
end
|
|
288
|
+
rndeps_log("Verifying checksum for downloaded #{filename}...")
|
|
289
|
+
if ReactNativePodsUtils.validate_tarball(destination_path, tarball_url)
|
|
290
|
+
# Save to shared cache for future use
|
|
291
|
+
`mkdir -p "#{ReactNativePodsUtils.shared_cache_dir()}"`
|
|
292
|
+
FileUtils.cp(destination_path, cached_path)
|
|
293
|
+
rndeps_log("Saved #{filename} to shared cache (#{ReactNativePodsUtils.shared_cache_dir()})")
|
|
294
|
+
else
|
|
295
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
296
|
+
abort("[ReactNativeDependencies] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
297
|
+
end
|
|
244
298
|
end
|
|
245
299
|
|
|
246
300
|
return destination_path
|
|
@@ -4,12 +4,19 @@
|
|
|
4
4
|
# LICENSE file in the root directory of this source tree.
|
|
5
5
|
|
|
6
6
|
require 'shellwords'
|
|
7
|
+
require 'digest'
|
|
8
|
+
require 'uri'
|
|
7
9
|
|
|
8
10
|
require_relative "./helpers.rb"
|
|
9
11
|
require_relative "./jsengine.rb"
|
|
10
12
|
|
|
11
13
|
# Utilities class for React Native Cocoapods
|
|
12
14
|
class ReactNativePodsUtils
|
|
15
|
+
# URI::File.build validates path components as ASCII, so escape the filesystem path first.
|
|
16
|
+
def self.local_file_uri(path)
|
|
17
|
+
URI::File.build(path: URI::DEFAULT_PARSER.escape(path)).to_s
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
def self.warn_if_not_on_arm64
|
|
14
21
|
if SysctlChecker.new().call_sysctl_arm64() == 1 && !Environment.new().ruby_platform().include?('arm64')
|
|
15
22
|
Pod::UI.warn 'Do not use "pod install" from inside Rosetta2 (x86_64 emulation on arm64).'
|
|
@@ -727,4 +734,49 @@ class ReactNativePodsUtils
|
|
|
727
734
|
spec.header_mappings_dir = header_mappings_dir
|
|
728
735
|
end
|
|
729
736
|
end
|
|
737
|
+
|
|
738
|
+
# ==================== #
|
|
739
|
+
# Shared download cache #
|
|
740
|
+
# ==================== #
|
|
741
|
+
|
|
742
|
+
def self.skip_caches?
|
|
743
|
+
ENV['RCT_SKIP_CACHES'] == '1'
|
|
744
|
+
end
|
|
745
|
+
|
|
746
|
+
def self.shared_cache_dir()
|
|
747
|
+
return File.join(Dir.home, "Library", "Caches", "ReactNative")
|
|
748
|
+
end
|
|
749
|
+
|
|
750
|
+
def self.fetch_maven_sha1(tarball_url)
|
|
751
|
+
sha1 = `curl -sL "#{tarball_url}.sha1"`.strip
|
|
752
|
+
return sha1.downcase if $?.success? && sha1.match?(/\A[a-fA-F0-9]{40}\z/)
|
|
753
|
+
nil
|
|
754
|
+
end
|
|
755
|
+
|
|
756
|
+
def self.validate_tarball(path, tarball_url)
|
|
757
|
+
expected_sha1 = fetch_maven_sha1(tarball_url)
|
|
758
|
+
basename = File.basename(path)
|
|
759
|
+
if expected_sha1.nil?
|
|
760
|
+
cache_log("SHA1 not available from Maven for #{basename}. Skipping validation.")
|
|
761
|
+
return true
|
|
762
|
+
end
|
|
763
|
+
actual_sha1 = Digest::SHA1.file(path).hexdigest
|
|
764
|
+
if actual_sha1 == expected_sha1
|
|
765
|
+
cache_log("SHA1 verified for #{basename}")
|
|
766
|
+
return true
|
|
767
|
+
end
|
|
768
|
+
cache_log("SHA1 mismatch for #{basename}: expected #{expected_sha1}, got #{actual_sha1}", :error)
|
|
769
|
+
return false
|
|
770
|
+
end
|
|
771
|
+
|
|
772
|
+
def self.cache_log(message, level = :info)
|
|
773
|
+
return unless Object.const_defined?("Pod::UI")
|
|
774
|
+
prefix = '[Cache] '
|
|
775
|
+
case level
|
|
776
|
+
when :error
|
|
777
|
+
Pod::UI.puts prefix.red + message
|
|
778
|
+
else
|
|
779
|
+
Pod::UI.puts prefix.green + message
|
|
780
|
+
end
|
|
781
|
+
end
|
|
730
782
|
end
|
|
@@ -49,8 +49,13 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) {
|
|
|
49
49
|
return '[]';
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
// Normalize appPath so any "Pods/.." segment is collapsed before find runs.
|
|
53
|
+
// Otherwise every find result inherits the search-root prefix containing
|
|
54
|
+
// "/Pods/" and gets dropped by the exclusion filter below.
|
|
55
|
+
const resolvedAppPath = path.resolve(appPath);
|
|
56
|
+
|
|
52
57
|
const xcodeproj = String(
|
|
53
|
-
execSync(`find ${
|
|
58
|
+
execSync(`find ${resolvedAppPath} -type d -name "*.xcodeproj"`),
|
|
54
59
|
)
|
|
55
60
|
.trim()
|
|
56
61
|
.split('\n')
|
|
@@ -61,12 +66,12 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) {
|
|
|
61
66
|
)[0];
|
|
62
67
|
if (!xcodeproj) {
|
|
63
68
|
throw new Error(
|
|
64
|
-
`Cannot find .xcodeproj file inside ${
|
|
69
|
+
`Cannot find .xcodeproj file inside ${resolvedAppPath}. This is required to determine codegen spec paths relative to native project.`,
|
|
65
70
|
);
|
|
66
71
|
}
|
|
67
72
|
const jsFiles = '-name "Native*.js" -or -name "*NativeComponent.js"';
|
|
68
73
|
const tsFiles = '-name "Native*.ts" -or -name "*NativeComponent.ts"';
|
|
69
|
-
const findCommand = `find ${path.join(
|
|
74
|
+
const findCommand = `find ${path.join(resolvedAppPath, jsSrcsDir)} -type f -not -path "*/__mocks__/*" -and \\( ${jsFiles} -or ${tsFiles} \\)`;
|
|
70
75
|
const list = String(execSync(findCommand))
|
|
71
76
|
.trim()
|
|
72
77
|
.split('\n')
|
|
@@ -539,8 +539,21 @@ def react_native_post_install(
|
|
|
539
539
|
rn_relative_to_pods = rn_real.relative_path_from(pods_dir_real)
|
|
540
540
|
ReactNativePodsUtils.set_build_setting(installer, build_setting: "REACT_NATIVE_PATH", value: File.join("${PODS_ROOT}", rn_relative_to_pods.to_s))
|
|
541
541
|
# Store the Podfile directory as a build setting so that shell scripts can
|
|
542
|
-
# locate it without
|
|
543
|
-
|
|
542
|
+
# locate it without hardcoding an absolute path. Use Xcode variable
|
|
543
|
+
# substitution per-project so the value persisted in project.pbxproj is
|
|
544
|
+
# portable across machines: $(SRCROOT) is the Podfile dir for user projects
|
|
545
|
+
# (also avoids the PODS_ROOT/.. traversal that breaks when Pods/ is a
|
|
546
|
+
# symlink), and $(SRCROOT)/.. for the Pods project.
|
|
547
|
+
installer.aggregate_targets.map(&:user_project).uniq(&:path).each do |user_project|
|
|
548
|
+
user_project.build_configurations.each do |config|
|
|
549
|
+
config.build_settings['PODFILE_DIR'] = '$(SRCROOT)'
|
|
550
|
+
end
|
|
551
|
+
user_project.save
|
|
552
|
+
end
|
|
553
|
+
installer.pods_project.build_configurations.each do |config|
|
|
554
|
+
config.build_settings['PODFILE_DIR'] = '$(SRCROOT)/..'
|
|
555
|
+
end
|
|
556
|
+
installer.pods_project.save
|
|
544
557
|
ReactNativePodsUtils.set_build_setting(installer, build_setting: "SWIFT_ACTIVE_COMPILATION_CONDITIONS", value: ['$(inherited)', 'DEBUG'], config_name: "Debug")
|
|
545
558
|
|
|
546
559
|
if (ENV['RCT_REMOVE_LEGACY_ARCH'] == '1')
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
# This source code is licensed under the MIT license found in the
|
|
4
4
|
# LICENSE file in the root directory of this source tree.
|
|
5
5
|
|
|
6
|
+
require 'digest'
|
|
6
7
|
require 'net/http'
|
|
7
8
|
require 'rexml/document'
|
|
8
9
|
|
|
@@ -236,16 +237,102 @@ def download_stable_hermes(react_native_path, version, configuration)
|
|
|
236
237
|
download_hermes_tarball(react_native_path, tarball_url, version, configuration)
|
|
237
238
|
end
|
|
238
239
|
|
|
240
|
+
def shared_cache_dir()
|
|
241
|
+
return File.join(Dir.home, "Library", "Caches", "ReactNative")
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def fetch_maven_sha1(tarball_url)
|
|
245
|
+
sha1 = `curl -sL "#{tarball_url}.sha1"`.strip
|
|
246
|
+
return sha1.downcase if $?.success? && sha1.match?(/\A[a-fA-F0-9]{40}\z/)
|
|
247
|
+
nil
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def skip_caches?
|
|
251
|
+
ENV['RCT_SKIP_CACHES'] == '1'
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def validate_hermes_tarball(path, tarball_url)
|
|
255
|
+
expected_sha1 = fetch_maven_sha1(tarball_url)
|
|
256
|
+
basename = File.basename(path)
|
|
257
|
+
if expected_sha1.nil?
|
|
258
|
+
hermes_log("SHA1 not available from Maven for #{basename}. Skipping validation.", :info)
|
|
259
|
+
return true
|
|
260
|
+
end
|
|
261
|
+
actual_sha1 = Digest::SHA1.file(path).hexdigest
|
|
262
|
+
if actual_sha1 == expected_sha1
|
|
263
|
+
hermes_log("SHA1 verified for #{basename}", :info)
|
|
264
|
+
return true
|
|
265
|
+
end
|
|
266
|
+
hermes_log("SHA1 mismatch for #{basename}: expected #{expected_sha1}, got #{actual_sha1}", :error)
|
|
267
|
+
return false
|
|
268
|
+
end
|
|
269
|
+
|
|
239
270
|
def download_hermes_tarball(react_native_path, tarball_url, version, configuration)
|
|
240
|
-
|
|
241
|
-
"
|
|
242
|
-
"
|
|
271
|
+
filename = configuration == nil ?
|
|
272
|
+
"hermes-ios-#{version}.tar.gz" :
|
|
273
|
+
"hermes-ios-#{version}-#{configuration}.tar.gz"
|
|
274
|
+
destination_path = "#{artifacts_dir()}/#{filename}"
|
|
275
|
+
|
|
276
|
+
if File.exist?(destination_path)
|
|
277
|
+
hermes_log("Tarball #{filename} already exists in Pods. Skipping download.", :info)
|
|
278
|
+
return destination_path
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
`mkdir -p "#{artifacts_dir()}"`
|
|
282
|
+
|
|
283
|
+
if skip_caches?
|
|
284
|
+
hermes_log("RCT_SKIP_CACHES is set. Downloading #{filename} directly (bypassing shared cache).", :info)
|
|
285
|
+
tmp_file = "#{artifacts_dir()}/hermes-ios.download"
|
|
286
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
287
|
+
unless File.exist?(destination_path)
|
|
288
|
+
abort("[Hermes] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
289
|
+
end
|
|
290
|
+
return destination_path
|
|
291
|
+
end
|
|
243
292
|
|
|
244
|
-
|
|
293
|
+
cached_path = File.join(shared_cache_dir(), filename)
|
|
294
|
+
if File.exist?(cached_path)
|
|
295
|
+
hermes_log("Verifying checksum for cached #{filename}...", :info)
|
|
296
|
+
if validate_hermes_tarball(cached_path, tarball_url)
|
|
297
|
+
hermes_log("Cache hit: copying #{filename} from shared cache (#{shared_cache_dir()})", :info)
|
|
298
|
+
FileUtils.cp(cached_path, destination_path)
|
|
299
|
+
else
|
|
300
|
+
hermes_log("Shared cache file #{filename} failed SHA verification. Re-downloading.", :info)
|
|
301
|
+
File.delete(cached_path)
|
|
302
|
+
tmp_file = "#{artifacts_dir()}/hermes-ios.download"
|
|
303
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
304
|
+
unless File.exist?(destination_path)
|
|
305
|
+
abort("[Hermes] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
306
|
+
end
|
|
307
|
+
hermes_log("Verifying checksum for downloaded #{filename}...", :info)
|
|
308
|
+
if validate_hermes_tarball(destination_path, tarball_url)
|
|
309
|
+
FileUtils.cp(destination_path, cached_path)
|
|
310
|
+
hermes_log("Saved #{filename} to shared cache (#{shared_cache_dir()})", :info)
|
|
311
|
+
else
|
|
312
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
313
|
+
abort("[Hermes] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
314
|
+
end
|
|
315
|
+
end
|
|
316
|
+
else
|
|
317
|
+
hermes_log("Cache miss: downloading #{filename} from #{tarball_url}", :info)
|
|
245
318
|
# Download to a temporary file first so we don't cache incomplete downloads.
|
|
246
319
|
tmp_file = "#{artifacts_dir()}/hermes-ios.download"
|
|
247
|
-
`
|
|
320
|
+
`curl -A "react-native-#{version}" "#{tarball_url}" -Lo "#{tmp_file}" && mv "#{tmp_file}" "#{destination_path}"`
|
|
321
|
+
unless File.exist?(destination_path)
|
|
322
|
+
abort("[Hermes] Failed to download #{filename} from #{tarball_url}. Aborting.")
|
|
323
|
+
end
|
|
324
|
+
hermes_log("Verifying checksum for downloaded #{filename}...", :info)
|
|
325
|
+
if validate_hermes_tarball(destination_path, tarball_url)
|
|
326
|
+
# Save to shared cache for future use
|
|
327
|
+
`mkdir -p "#{shared_cache_dir()}"`
|
|
328
|
+
FileUtils.cp(destination_path, cached_path)
|
|
329
|
+
hermes_log("Saved #{filename} to shared cache (#{shared_cache_dir()})", :info)
|
|
330
|
+
else
|
|
331
|
+
File.delete(destination_path) if File.exist?(destination_path)
|
|
332
|
+
abort("[Hermes] Downloaded file #{filename} failed SHA verification. Aborting.")
|
|
333
|
+
end
|
|
248
334
|
end
|
|
335
|
+
|
|
249
336
|
return destination_path
|
|
250
337
|
end
|
|
251
338
|
|
|
@@ -4,27 +4,30 @@
|
|
|
4
4
|
* This source code is licensed under the MIT license found in the
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*
|
|
7
|
-
* @generated SignedSource<<
|
|
7
|
+
* @generated SignedSource<<92efce69dca1861d7bdfc6d9c5ee3a62>>
|
|
8
8
|
*
|
|
9
9
|
* This file was translated from Flow by scripts/js-api/build-types/index.js.
|
|
10
10
|
* Original file: packages/react-native/Libraries/Components/Pressable/useAndroidRippleForView.js
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
import type { ProcessedColorValue } from "../../StyleSheet/processColor";
|
|
13
14
|
import type { ColorValue } from "../../StyleSheet/StyleSheet";
|
|
14
15
|
import type { GestureResponderEvent } from "../../Types/CoreEventTypes";
|
|
15
16
|
import View from "../View/View";
|
|
16
17
|
import * as React from "react";
|
|
17
18
|
type NativeBackgroundProp = Readonly<{
|
|
18
19
|
type: "RippleAndroid";
|
|
19
|
-
color:
|
|
20
|
+
color: ProcessedColorValue | undefined;
|
|
20
21
|
borderless: boolean;
|
|
21
22
|
rippleRadius: number | undefined;
|
|
23
|
+
alpha: number | undefined;
|
|
22
24
|
}>;
|
|
23
25
|
export type PressableAndroidRippleConfig = {
|
|
24
26
|
color?: ColorValue;
|
|
25
27
|
borderless?: boolean;
|
|
26
28
|
radius?: number;
|
|
27
29
|
foreground?: boolean;
|
|
30
|
+
alpha?: number;
|
|
28
31
|
};
|
|
29
32
|
/**
|
|
30
33
|
* Provides the event handlers and props for configuring the ripple effect on
|