react-native 0.81.4 → 0.81.6
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 +38 -35
- package/Libraries/Renderer/implementations/ReactFabric-prod.js +51 -22
- package/Libraries/Renderer/implementations/ReactFabric-profiling.js +54 -24
- package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +36 -33
- package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +5 -5
- package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +5 -5
- package/Libraries/Renderer/shims/ReactNativeTypes.js +23 -11
- package/React/Base/RCTUtils.mm +5 -1
- package/React/Base/RCTVersion.m +1 -1
- package/React/CoreModules/RCTDeviceInfo.mm +3 -4
- package/React/Fabric/RCTSurfacePointerHandler.mm +1 -1
- package/React/Fabric/RCTSurfaceTouchHandler.mm +1 -1
- package/React/Views/RCTSwitchManager.m +24 -0
- package/ReactAndroid/gradle.properties +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactActivityDelegate.java +25 -1
- package/ReactAndroid/src/main/java/com/facebook/react/ReactInstanceManager.java +2 -2
- package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/uimanager/NativeViewHierarchyManager.java +0 -3
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextShadowNode.kt +1 -1
- package/ReactAndroid/src/main/java/com/facebook/react/views/text/ReactTextViewManager.kt +2 -2
- package/ReactAndroid/src/main/jni/react/jni/TransformHelper.cpp +3 -1
- package/ReactCommon/cxxreact/ReactNativeVersion.h +2 -2
- package/ReactCommon/react/renderer/components/view/BaseViewProps.cpp +0 -3
- package/ReactCommon/react/renderer/components/view/tests/ResolveTransformTest.cpp +377 -0
- package/package.json +10 -10
- package/scripts/codegen/generate-artifacts-executor/generateReactCodegenPodspec.js +7 -3
- package/scripts/codegen/generate-artifacts-executor/index.js +48 -22
- package/scripts/codegen/generate-artifacts-executor/utils.js +15 -3
- package/scripts/react_native_pods_utils/script_phases.sh +1 -3
- package/sdks/hermesc/osx-bin/hermes +0 -0
- package/sdks/hermesc/osx-bin/hermesc +0 -0
- package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
- package/third-party-podspecs/ReactNativeDependencies.podspec +1 -1
- package/types_generated/Libraries/Renderer/shims/ReactNativeTypes.d.ts +17 -10
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
#include <gtest/gtest.h>
|
|
9
|
+
|
|
10
|
+
#include <react/renderer/components/view/BaseViewProps.h>
|
|
11
|
+
|
|
12
|
+
namespace facebook::react {
|
|
13
|
+
|
|
14
|
+
namespace {
|
|
15
|
+
|
|
16
|
+
// For transforms involving rotations, use this helper to fix floating point
|
|
17
|
+
// accuracies
|
|
18
|
+
void expectTransformsEqual(const Transform& t1, const Transform& t2) {
|
|
19
|
+
for (int i = 0; i < 16; i++) {
|
|
20
|
+
EXPECT_NEAR(t1.matrix[i], t2.matrix[i], 0.0001);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
} // namespace
|
|
25
|
+
|
|
26
|
+
class ResolveTransformTest : public ::testing::Test {
|
|
27
|
+
protected:
|
|
28
|
+
TransformOrigin createTransformOriginPoints(float x, float y, float z = 0) {
|
|
29
|
+
TransformOrigin origin;
|
|
30
|
+
origin.xy[0] = ValueUnit(x, UnitType::Point);
|
|
31
|
+
origin.xy[1] = ValueUnit(y, UnitType::Point);
|
|
32
|
+
origin.z = z;
|
|
33
|
+
return origin;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
TransformOrigin createTransformOriginPercent(float x, float y, float z = 0) {
|
|
37
|
+
TransformOrigin origin;
|
|
38
|
+
origin.xy[0] = ValueUnit(x, UnitType::Percent);
|
|
39
|
+
origin.xy[1] = ValueUnit(y, UnitType::Percent);
|
|
40
|
+
origin.z = z;
|
|
41
|
+
return origin;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
TEST_F(ResolveTransformTest, EmptyFrameNoTransformOrigin) {
|
|
46
|
+
Size frameSize{.width = 0, .height = 0};
|
|
47
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
48
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
49
|
+
|
|
50
|
+
auto result =
|
|
51
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
52
|
+
|
|
53
|
+
// With empty frame size and no transform origin, should just apply the
|
|
54
|
+
// transform directly
|
|
55
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPoints) {
|
|
59
|
+
Size frameSize{.width = 0, .height = 0};
|
|
60
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
61
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(5, 8);
|
|
62
|
+
|
|
63
|
+
auto result =
|
|
64
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
65
|
+
|
|
66
|
+
// Should handle transform origin even with empty frame size
|
|
67
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
TEST_F(ResolveTransformTest, EmptyFrameTransformOriginPercent) {
|
|
71
|
+
Size frameSize{.width = 0, .height = 0};
|
|
72
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
73
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
74
|
+
|
|
75
|
+
auto result =
|
|
76
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
77
|
+
|
|
78
|
+
// Transform origin does not affect translate transform
|
|
79
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameNoTransformOrigin) {
|
|
83
|
+
Size frameSize{.width = 100, .height = 200};
|
|
84
|
+
Transform transform = Transform::Translate(10.0, 20.0, 0.0);
|
|
85
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
86
|
+
|
|
87
|
+
auto result =
|
|
88
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
89
|
+
|
|
90
|
+
// Transform origin does not affect translate transform
|
|
91
|
+
EXPECT_EQ(result.matrix, Transform::Translate(10.0, 20.0, 0.0).matrix);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPoints) {
|
|
95
|
+
Size frameSize{.width = 100, .height = 200};
|
|
96
|
+
Transform transform = Transform::Scale(2.0, 1.5, 0.);
|
|
97
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
98
|
+
|
|
99
|
+
auto result =
|
|
100
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
101
|
+
|
|
102
|
+
auto expected = Transform::Translate(25.0, 25.0, 0.0) * transform;
|
|
103
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
TEST_F(ResolveTransformTest, NonEmptyFrameTransformOriginPercent) {
|
|
107
|
+
Size frameSize{.width = 100, .height = 200};
|
|
108
|
+
Transform transform = Transform::Scale(2.0, 1.5, 0.);
|
|
109
|
+
TransformOrigin transformOrigin =
|
|
110
|
+
createTransformOriginPercent(25, 75); // 25% width, 75% height
|
|
111
|
+
|
|
112
|
+
auto result =
|
|
113
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
114
|
+
|
|
115
|
+
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
|
|
116
|
+
auto expected = Transform::Translate(25.0, -25.0, 0.0) * transform;
|
|
117
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
TEST_F(ResolveTransformTest, IdentityTransformWithOrigin) {
|
|
121
|
+
Size frameSize{.width = 100, .height = 200};
|
|
122
|
+
Transform transform = Transform::Identity();
|
|
123
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
124
|
+
|
|
125
|
+
auto result =
|
|
126
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
127
|
+
|
|
128
|
+
// Even with identity transform, transform origin should still apply
|
|
129
|
+
// translations but they should cancel out, resulting in identity
|
|
130
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
TEST_F(ResolveTransformTest, MultipleTransformOperations) {
|
|
134
|
+
Size frameSize{.width = 100, .height = 200};
|
|
135
|
+
|
|
136
|
+
Transform transform = Transform::Identity();
|
|
137
|
+
transform = transform * Transform::Translate(10.0, 20.0, 0.0);
|
|
138
|
+
transform = transform * Transform::Scale(2.0, 1.5, 0.0);
|
|
139
|
+
|
|
140
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
141
|
+
|
|
142
|
+
auto result =
|
|
143
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
144
|
+
|
|
145
|
+
EXPECT_EQ(result.matrix, transform.matrix);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
TEST_F(ResolveTransformTest, VariousTransformOriginPositions) {
|
|
149
|
+
Size frameSize{.width = 100, .height = 200};
|
|
150
|
+
Transform transform = Transform::Scale(2.0, 2.0, 0.);
|
|
151
|
+
|
|
152
|
+
// Test origin at top-left (0, 0)
|
|
153
|
+
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
|
|
154
|
+
auto resultTopLeft =
|
|
155
|
+
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
|
|
156
|
+
auto expected = Transform::Translate(50.0, 100.0, 0.0) * transform;
|
|
157
|
+
EXPECT_EQ(resultTopLeft.matrix, expected.matrix);
|
|
158
|
+
|
|
159
|
+
// Test origin at center (50%, 50%)
|
|
160
|
+
TransformOrigin center = createTransformOriginPercent(50, 50);
|
|
161
|
+
auto resultCenter =
|
|
162
|
+
BaseViewProps::resolveTransform(frameSize, transform, center);
|
|
163
|
+
EXPECT_EQ(resultCenter.matrix, transform.matrix);
|
|
164
|
+
|
|
165
|
+
// Test origin at bottom-right (100%, 100%)
|
|
166
|
+
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
|
|
167
|
+
auto resultBottomRight =
|
|
168
|
+
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
|
|
169
|
+
expected = Transform::Translate(-50.0, -100.0, 0.0) * transform;
|
|
170
|
+
EXPECT_EQ(resultBottomRight.matrix, expected.matrix);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Test with z-component in transform origin
|
|
174
|
+
TEST_F(ResolveTransformTest, TransformOriginWithZComponent) {
|
|
175
|
+
Size frameSize{.width = 100, .height = 200};
|
|
176
|
+
Transform transform = Transform::Scale(1.5, 1.5, 0.);
|
|
177
|
+
|
|
178
|
+
TransformOrigin transformOrigin;
|
|
179
|
+
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
|
|
180
|
+
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
|
|
181
|
+
transformOrigin.z = 10.0f;
|
|
182
|
+
|
|
183
|
+
auto result =
|
|
184
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
185
|
+
auto expected = Transform::Translate(0.0, 0.0, 10.0) * transform;
|
|
186
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
TEST_F(ResolveTransformTest, ArbitraryTransformMatrix) {
|
|
190
|
+
Size frameSize{.width = 100, .height = 200};
|
|
191
|
+
|
|
192
|
+
Transform transform;
|
|
193
|
+
transform.operations.push_back({
|
|
194
|
+
.type = TransformOperationType::Arbitrary,
|
|
195
|
+
.x = ValueUnit(0, UnitType::Point),
|
|
196
|
+
.y = ValueUnit(0, UnitType::Point),
|
|
197
|
+
.z = ValueUnit(0, UnitType::Point),
|
|
198
|
+
});
|
|
199
|
+
// Set custom matrix
|
|
200
|
+
transform.matrix = {{2, 0, 0, 0, 0, 2, 0, 0, 0, 0, 1, 0, 10, 20, 0, 1}};
|
|
201
|
+
|
|
202
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
203
|
+
|
|
204
|
+
auto result =
|
|
205
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
206
|
+
|
|
207
|
+
auto expected = Transform::Translate(25.0, 50.0, 0.0) * transform;
|
|
208
|
+
EXPECT_EQ(result.matrix, expected.matrix);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// Test rotation with empty frame size and no transform origin
|
|
212
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameNoTransformOrigin) {
|
|
213
|
+
Size frameSize{.width = 0, .height = 0};
|
|
214
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
215
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
216
|
+
|
|
217
|
+
auto result =
|
|
218
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
219
|
+
|
|
220
|
+
// With empty frame size and no transform origin, should just apply the
|
|
221
|
+
// rotation directly
|
|
222
|
+
expectTransformsEqual(result, transform);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
// Test rotation with empty frame size and transform origin in points
|
|
226
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPoints) {
|
|
227
|
+
Size frameSize{.width = 0, .height = 0};
|
|
228
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
229
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(10, 20);
|
|
230
|
+
|
|
231
|
+
auto result =
|
|
232
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
233
|
+
|
|
234
|
+
// With empty frame size, center is (0, 0), so origin offset is (10, 20)
|
|
235
|
+
auto expected = Transform::Translate(10.0, 20.0, 0.0) * transform *
|
|
236
|
+
Transform::Translate(-10.0, -20.0, 0.0);
|
|
237
|
+
expectTransformsEqual(result, expected);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Test rotation with empty frame size and transform origin in percentages
|
|
241
|
+
TEST_F(ResolveTransformTest, RotationEmptyFrameTransformOriginPercent) {
|
|
242
|
+
Size frameSize{.width = 0, .height = 0};
|
|
243
|
+
Transform transform = Transform::RotateZ(M_PI / 6.0); // 30 degrees
|
|
244
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
245
|
+
|
|
246
|
+
auto result =
|
|
247
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
248
|
+
|
|
249
|
+
// With 0 frame size, percentages resolve to 0, so no origin offset
|
|
250
|
+
expectTransformsEqual(result, transform);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Test rotation with non-empty frame size and no transform origin
|
|
254
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameNoTransformOrigin) {
|
|
255
|
+
Size frameSize{.width = 100, .height = 200};
|
|
256
|
+
Transform transform = Transform::RotateZ(M_PI / 3.0); // 60 degrees
|
|
257
|
+
TransformOrigin transformOrigin; // Default (not set)
|
|
258
|
+
|
|
259
|
+
auto result =
|
|
260
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
261
|
+
|
|
262
|
+
// Without transform origin, rotation should happen around default center
|
|
263
|
+
expectTransformsEqual(result, transform);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Test rotation with non-empty frame size and transform origin in points
|
|
267
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPoints) {
|
|
268
|
+
Size frameSize{.width = 100, .height = 200};
|
|
269
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
270
|
+
TransformOrigin transformOrigin = createTransformOriginPoints(25, 50);
|
|
271
|
+
|
|
272
|
+
auto result =
|
|
273
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
274
|
+
|
|
275
|
+
// Center of 100x200 frame is (50, 100), origin at (25, 50) means offset of
|
|
276
|
+
// (-25, -50)
|
|
277
|
+
auto expected = Transform::Translate(-25.0, -50.0, 0.0) * transform *
|
|
278
|
+
Transform::Translate(25.0, 50.0, 0.0);
|
|
279
|
+
expectTransformsEqual(result, expected);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// Test rotation with non-empty frame size and transform origin in percentages
|
|
283
|
+
TEST_F(ResolveTransformTest, RotationNonEmptyFrameTransformOriginPercent) {
|
|
284
|
+
Size frameSize{.width = 100, .height = 200};
|
|
285
|
+
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
|
|
286
|
+
TransformOrigin transformOrigin =
|
|
287
|
+
createTransformOriginPercent(25, 75); // 25% width, 75% height
|
|
288
|
+
|
|
289
|
+
auto result =
|
|
290
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
291
|
+
|
|
292
|
+
// Should resolve percentages: 25% of 100 = 25, 75% of 200 = 150
|
|
293
|
+
// Center is (50, 100), so origin offset is (25-50, 150-100) = (-25, 50)
|
|
294
|
+
auto expected = Transform::Translate(-25.0, 50.0, 0.0) * transform *
|
|
295
|
+
Transform::Translate(25.0, -50.0, 0.0);
|
|
296
|
+
expectTransformsEqual(result, expected);
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// Test rotation with mixed transform origin units
|
|
300
|
+
TEST_F(ResolveTransformTest, RotationMixedTransformOriginUnits) {
|
|
301
|
+
Size frameSize{.width = 100, .height = 200};
|
|
302
|
+
Transform transform = Transform::RotateZ(M_PI); // 180 degrees
|
|
303
|
+
|
|
304
|
+
TransformOrigin transformOrigin;
|
|
305
|
+
transformOrigin.xy[0] = ValueUnit(30, UnitType::Point); // 30 points
|
|
306
|
+
transformOrigin.xy[1] = ValueUnit(25, UnitType::Percent); // 25% of 200 = 50
|
|
307
|
+
transformOrigin.z = 0;
|
|
308
|
+
|
|
309
|
+
auto result =
|
|
310
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
311
|
+
|
|
312
|
+
// Center is (50, 100), origin is (30, 50), so offset is (-20, -50)
|
|
313
|
+
auto expected = Transform::Translate(-20.0, -50.0, 0.0) * transform *
|
|
314
|
+
Transform::Translate(20.0, 50.0, 0.0);
|
|
315
|
+
expectTransformsEqual(result, expected);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Test multiple rotations (RotateX, RotateY, RotateZ)
|
|
319
|
+
TEST_F(ResolveTransformTest, MultipleRotationsWithTransformOrigin) {
|
|
320
|
+
Size frameSize{.width = 100, .height = 100};
|
|
321
|
+
|
|
322
|
+
Transform transform = Transform::Rotate(M_PI / 6.0, M_PI / 4.0, M_PI / 3.0);
|
|
323
|
+
TransformOrigin transformOrigin = createTransformOriginPercent(50, 50);
|
|
324
|
+
|
|
325
|
+
auto result =
|
|
326
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
327
|
+
expectTransformsEqual(result, transform);
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// Test rotation with z-component in transform origin
|
|
331
|
+
TEST_F(ResolveTransformTest, RotationWithZTransformOrigin) {
|
|
332
|
+
Size frameSize{.width = 100, .height = 200};
|
|
333
|
+
Transform transform = Transform::RotateZ(M_PI / 4.0); // 45 degrees
|
|
334
|
+
|
|
335
|
+
TransformOrigin transformOrigin;
|
|
336
|
+
transformOrigin.xy[0] = ValueUnit(50, UnitType::Point);
|
|
337
|
+
transformOrigin.xy[1] = ValueUnit(100, UnitType::Point);
|
|
338
|
+
transformOrigin.z = 15.0f;
|
|
339
|
+
|
|
340
|
+
auto result =
|
|
341
|
+
BaseViewProps::resolveTransform(frameSize, transform, transformOrigin);
|
|
342
|
+
|
|
343
|
+
// Center is (50, 100), origin is (50, 100, 15), so offset is (0, 0, 15)
|
|
344
|
+
auto expected = Transform::Translate(0.0, 0.0, 15.0) * transform *
|
|
345
|
+
Transform::Translate(0.0, 0.0, -15.0);
|
|
346
|
+
expectTransformsEqual(result, expected);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Test rotation at different origin positions (corners vs center)
|
|
350
|
+
TEST_F(ResolveTransformTest, RotationDifferentOriginPositions) {
|
|
351
|
+
Size frameSize{.width = 100, .height = 100};
|
|
352
|
+
Transform transform = Transform::RotateZ(M_PI / 2.0); // 90 degrees
|
|
353
|
+
|
|
354
|
+
// Test rotation around top-left corner (0, 0)
|
|
355
|
+
TransformOrigin topLeft = createTransformOriginPoints(0, 0);
|
|
356
|
+
auto resultTopLeft =
|
|
357
|
+
BaseViewProps::resolveTransform(frameSize, transform, topLeft);
|
|
358
|
+
auto expectedTopLeft = Transform::Translate(-50.0, -50.0, 0.0) * transform *
|
|
359
|
+
Transform::Translate(50.0, 50.0, 0.0);
|
|
360
|
+
expectTransformsEqual(resultTopLeft, expectedTopLeft);
|
|
361
|
+
|
|
362
|
+
// Test rotation around center (50%, 50%)
|
|
363
|
+
TransformOrigin center = createTransformOriginPercent(50, 50);
|
|
364
|
+
auto resultCenter =
|
|
365
|
+
BaseViewProps::resolveTransform(frameSize, transform, center);
|
|
366
|
+
expectTransformsEqual(resultCenter, transform);
|
|
367
|
+
|
|
368
|
+
// Test rotation around bottom-right corner (100%, 100%)
|
|
369
|
+
TransformOrigin bottomRight = createTransformOriginPercent(100, 100);
|
|
370
|
+
auto resultBottomRight =
|
|
371
|
+
BaseViewProps::resolveTransform(frameSize, transform, bottomRight);
|
|
372
|
+
auto expectedBottomRight = Transform::Translate(50.0, 50.0, 0.0) * transform *
|
|
373
|
+
Transform::Translate(-50.0, -50.0, 0.0);
|
|
374
|
+
expectTransformsEqual(resultBottomRight, expectedBottomRight);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
} // namespace facebook::react
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.6",
|
|
4
4
|
"description": "A framework for building native apps using React",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -152,8 +152,8 @@
|
|
|
152
152
|
"featureflags": "node ./scripts/featureflags/index.js"
|
|
153
153
|
},
|
|
154
154
|
"peerDependencies": {
|
|
155
|
-
"@types/react": "^19.1.
|
|
156
|
-
"react": "^19.1.
|
|
155
|
+
"@types/react": "^19.1.4",
|
|
156
|
+
"react": "^19.1.4"
|
|
157
157
|
},
|
|
158
158
|
"peerDependenciesMeta": {
|
|
159
159
|
"@types/react": {
|
|
@@ -162,13 +162,13 @@
|
|
|
162
162
|
},
|
|
163
163
|
"dependencies": {
|
|
164
164
|
"@jest/create-cache-key-function": "^29.7.0",
|
|
165
|
-
"@react-native/assets-registry": "0.81.
|
|
166
|
-
"@react-native/codegen": "0.81.
|
|
167
|
-
"@react-native/community-cli-plugin": "0.81.
|
|
168
|
-
"@react-native/gradle-plugin": "0.81.
|
|
169
|
-
"@react-native/js-polyfills": "0.81.
|
|
170
|
-
"@react-native/normalize-colors": "0.81.
|
|
171
|
-
"@react-native/virtualized-lists": "0.81.
|
|
165
|
+
"@react-native/assets-registry": "0.81.6",
|
|
166
|
+
"@react-native/codegen": "0.81.6",
|
|
167
|
+
"@react-native/community-cli-plugin": "0.81.6",
|
|
168
|
+
"@react-native/gradle-plugin": "0.81.6",
|
|
169
|
+
"@react-native/js-polyfills": "0.81.6",
|
|
170
|
+
"@react-native/normalize-colors": "0.81.6",
|
|
171
|
+
"@react-native/virtualized-lists": "0.81.6",
|
|
172
172
|
"abort-controller": "^3.0.0",
|
|
173
173
|
"anser": "^1.4.9",
|
|
174
174
|
"ansi-regex": "^5.0.0",
|
|
@@ -71,14 +71,18 @@ function getInputFiles(appPath /*: string */, appPkgJson /*: $FlowFixMe */) {
|
|
|
71
71
|
return `[${list}]`;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
function codegenScripts(appPath /*: string */,
|
|
75
|
-
const relativeAppPath = path.relative(
|
|
74
|
+
function codegenScripts(appPath /*: string */, baseOutputPath /*: string */) {
|
|
75
|
+
const relativeAppPath = path.relative(baseOutputPath, appPath);
|
|
76
|
+
const relativeReactNativeRootFolder = path.relative(
|
|
77
|
+
baseOutputPath,
|
|
78
|
+
REACT_NATIVE_PACKAGE_ROOT_FOLDER,
|
|
79
|
+
);
|
|
76
80
|
return `<<-SCRIPT
|
|
77
81
|
pushd "$PODS_ROOT/../" > /dev/null
|
|
78
82
|
RCT_SCRIPT_POD_INSTALLATION_ROOT=$(pwd)
|
|
79
83
|
popd >/dev/null
|
|
80
84
|
|
|
81
|
-
export RCT_SCRIPT_RN_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${
|
|
85
|
+
export RCT_SCRIPT_RN_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeReactNativeRootFolder}"
|
|
82
86
|
export RCT_SCRIPT_APP_PATH="$RCT_SCRIPT_POD_INSTALLATION_ROOT/${relativeAppPath.length === 0 ? '.' : relativeAppPath}"
|
|
83
87
|
export RCT_SCRIPT_OUTPUT_DIR="$RCT_SCRIPT_POD_INSTALLATION_ROOT"
|
|
84
88
|
export RCT_SCRIPT_TYPE="withCodegenDiscovery"
|
|
@@ -61,7 +61,7 @@ const path = require('path');
|
|
|
61
61
|
function execute(
|
|
62
62
|
projectRoot /*: string */,
|
|
63
63
|
targetPlatform /*: string */,
|
|
64
|
-
|
|
64
|
+
optionalBaseOutputPath /*: ?string */,
|
|
65
65
|
source /*: string */,
|
|
66
66
|
runReactNativeCodegen /*: boolean */ = true,
|
|
67
67
|
) {
|
|
@@ -86,25 +86,35 @@ function execute(
|
|
|
86
86
|
buildCodegenIfNeeded();
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
const
|
|
90
|
-
projectRoot,
|
|
91
|
-
baseOutputPath,
|
|
92
|
-
);
|
|
93
|
-
const codegenEnabledLibraries = findCodegenEnabledLibraries(
|
|
94
|
-
pkgJson,
|
|
95
|
-
projectRoot,
|
|
96
|
-
baseOutputPath,
|
|
97
|
-
reactNativeConfig,
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
if (codegenEnabledLibraries.length === 0) {
|
|
101
|
-
codegenLog('No codegen-enabled libraries found.', true);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let platforms =
|
|
89
|
+
const platforms =
|
|
105
90
|
targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
|
|
106
91
|
|
|
92
|
+
// NOTE: We cache the external libraries search (which may not run) across platforms to not change previous behaviour
|
|
93
|
+
const externalLibrariesCache /*: { current?: ?Array<$FlowFixMe> } */ = {};
|
|
94
|
+
|
|
107
95
|
for (const platform of platforms) {
|
|
96
|
+
// NOTE: This needs to be computed per-platform since `platform` can alter the path via a `package.json:codegenConfig.outputDir[platform]` override
|
|
97
|
+
const baseOutputPath = computeBaseOutputPath(
|
|
98
|
+
projectRoot,
|
|
99
|
+
optionalBaseOutputPath,
|
|
100
|
+
pkgJson,
|
|
101
|
+
platform,
|
|
102
|
+
);
|
|
103
|
+
const reactNativeConfig = readReactNativeConfig(
|
|
104
|
+
projectRoot,
|
|
105
|
+
baseOutputPath,
|
|
106
|
+
);
|
|
107
|
+
const codegenEnabledLibraries = findCodegenEnabledLibraries(
|
|
108
|
+
pkgJson,
|
|
109
|
+
projectRoot,
|
|
110
|
+
baseOutputPath,
|
|
111
|
+
reactNativeConfig,
|
|
112
|
+
externalLibrariesCache,
|
|
113
|
+
);
|
|
114
|
+
if (codegenEnabledLibraries.length === 0) {
|
|
115
|
+
codegenLog('No codegen-enabled libraries found.', true);
|
|
116
|
+
}
|
|
117
|
+
|
|
108
118
|
const disabledLibraries = findDisabledLibrariesByPlatform(
|
|
109
119
|
reactNativeConfig,
|
|
110
120
|
platform,
|
|
@@ -182,22 +192,38 @@ function readOutputDirFromPkgJson(
|
|
|
182
192
|
return null;
|
|
183
193
|
}
|
|
184
194
|
|
|
185
|
-
function
|
|
195
|
+
function computeBaseOutputPath(
|
|
186
196
|
projectRoot /*: string */,
|
|
187
|
-
|
|
197
|
+
optionalBaseOutputPath /*: ?string */,
|
|
188
198
|
pkgJson /*: $FlowFixMe */,
|
|
189
199
|
platform /*: string */,
|
|
190
200
|
) {
|
|
191
|
-
if (
|
|
201
|
+
if (
|
|
202
|
+
process.env.RCT_SCRIPT_OUTPUT_DIR != null &&
|
|
203
|
+
process.env.RCT_SCRIPT_OUTPUT_DIR.length > 0
|
|
204
|
+
) {
|
|
205
|
+
return process.env.RCT_SCRIPT_OUTPUT_DIR;
|
|
206
|
+
}
|
|
207
|
+
let baseOutputPath /*: string */;
|
|
208
|
+
if (optionalBaseOutputPath == null) {
|
|
192
209
|
const outputDirFromPkgJson = readOutputDirFromPkgJson(pkgJson, platform);
|
|
193
210
|
if (outputDirFromPkgJson != null) {
|
|
194
|
-
// $FlowFixMe[reassign-const]
|
|
195
211
|
baseOutputPath = path.join(projectRoot, outputDirFromPkgJson);
|
|
196
212
|
} else {
|
|
197
|
-
// $FlowFixMe[reassign-const]
|
|
198
213
|
baseOutputPath = projectRoot;
|
|
199
214
|
}
|
|
215
|
+
} else {
|
|
216
|
+
baseOutputPath = optionalBaseOutputPath;
|
|
200
217
|
}
|
|
218
|
+
return baseOutputPath;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function computeOutputPath(
|
|
222
|
+
projectRoot /*: string */,
|
|
223
|
+
baseOutputPath /*: string */,
|
|
224
|
+
pkgJson /*: $FlowFixMe */,
|
|
225
|
+
platform /*: string */,
|
|
226
|
+
) /*: string */ {
|
|
201
227
|
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
|
|
202
228
|
// Don't create nested directories for libraries to make importing generated headers easier.
|
|
203
229
|
return baseOutputPath;
|
|
@@ -98,9 +98,11 @@ function cleanupEmptyFilesAndFolders(filepath /*: string */) {
|
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
function readGeneratedAutolinkingOutput(
|
|
101
|
+
projectRoot /*: string */,
|
|
101
102
|
baseOutputPath /*: string */,
|
|
102
103
|
) /*: $FlowFixMe */ {
|
|
103
104
|
// NOTE: Generated by scripts/cocoapods/autolinking.rb in list_native_modules (called by use_native_modules)
|
|
105
|
+
// The `baseOutputPath` is based on a CLI argument and optional
|
|
104
106
|
const autolinkingGeneratedPath = path.resolve(
|
|
105
107
|
baseOutputPath,
|
|
106
108
|
'build/generated/autolinking/autolinking.json',
|
|
@@ -120,7 +122,10 @@ function readReactNativeConfig(
|
|
|
120
122
|
projectRoot /*: string */,
|
|
121
123
|
baseOutputPath /*: string */,
|
|
122
124
|
) /*: $FlowFixMe */ {
|
|
123
|
-
const autolinkingOutput = readGeneratedAutolinkingOutput(
|
|
125
|
+
const autolinkingOutput = readGeneratedAutolinkingOutput(
|
|
126
|
+
projectRoot,
|
|
127
|
+
baseOutputPath,
|
|
128
|
+
);
|
|
124
129
|
const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
|
|
125
130
|
if (autolinkingOutput) {
|
|
126
131
|
return autolinkingOutput;
|
|
@@ -141,6 +146,7 @@ function findCodegenEnabledLibraries(
|
|
|
141
146
|
projectRoot /*: string */,
|
|
142
147
|
baseOutputPath /*: string */,
|
|
143
148
|
reactNativeConfig /*: $FlowFixMe */,
|
|
149
|
+
externalLibrariesCache /*: { current?: ?Array<$FlowFixMe> } */ = {},
|
|
144
150
|
) /*: Array<$FlowFixMe> */ {
|
|
145
151
|
const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
|
|
146
152
|
if (pkgJsonIncludesGeneratedCode(pkgJson)) {
|
|
@@ -149,8 +155,14 @@ function findCodegenEnabledLibraries(
|
|
|
149
155
|
const libraries = [...projectLibraries];
|
|
150
156
|
// If we ran autolinking, we shouldn't try to run our own "autolinking-like"
|
|
151
157
|
// library discovery
|
|
152
|
-
if (!readGeneratedAutolinkingOutput(baseOutputPath)) {
|
|
153
|
-
|
|
158
|
+
if (!readGeneratedAutolinkingOutput(projectRoot, baseOutputPath)) {
|
|
159
|
+
const externalLibraries =
|
|
160
|
+
externalLibrariesCache.current ??
|
|
161
|
+
(externalLibrariesCache.current = findExternalLibraries(
|
|
162
|
+
pkgJson,
|
|
163
|
+
projectRoot,
|
|
164
|
+
));
|
|
165
|
+
libraries.push(...externalLibraries);
|
|
154
166
|
}
|
|
155
167
|
libraries.push(
|
|
156
168
|
...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
|
|
@@ -96,7 +96,7 @@ generateCodegenArtifactsFromSchema () {
|
|
|
96
96
|
generateArtifacts () {
|
|
97
97
|
describe "Generating codegen artifacts"
|
|
98
98
|
pushd "$RCT_SCRIPT_RN_DIR" >/dev/null || exit 1
|
|
99
|
-
"$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$
|
|
99
|
+
"$NODE_BINARY" "scripts/generate-codegen-artifacts.js" --path "$RCT_SCRIPT_APP_PATH" --outputPath "$RCT_SCRIPT_OUTPUT_DIR" --targetPlatform "ios"
|
|
100
100
|
popd >/dev/null || exit 1
|
|
101
101
|
}
|
|
102
102
|
|
|
@@ -110,11 +110,9 @@ moveOutputs () {
|
|
|
110
110
|
}
|
|
111
111
|
|
|
112
112
|
withCodegenDiscovery () {
|
|
113
|
-
setup_dirs
|
|
114
113
|
find_node
|
|
115
114
|
find_codegen
|
|
116
115
|
generateArtifacts
|
|
117
|
-
moveOutputs
|
|
118
116
|
}
|
|
119
117
|
|
|
120
118
|
noCodegenDiscovery () {
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -62,7 +62,7 @@ Pod::Spec.new do |spec|
|
|
|
62
62
|
exit 0
|
|
63
63
|
fi
|
|
64
64
|
|
|
65
|
-
cp -R "$HEADERS_PATH
|
|
65
|
+
cp -R "$HEADERS_PATH/." Headers
|
|
66
66
|
mkdir -p framework/packages/react-native
|
|
67
67
|
cp -R "$XCFRAMEWORK_PATH/../." framework/packages/react-native/
|
|
68
68
|
find "$XCFRAMEWORK_PATH/.." -type f -exec rm {} +
|