react-native 0.78.2 → 0.78.3

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.
@@ -275,6 +275,10 @@ class RCTAppDelegateBridgelessFeatureFlags : public ReactNativeFeatureFlagsDefau
275
275
  {
276
276
  return true;
277
277
  }
278
+ bool enableFixForViewCommandRace() override
279
+ {
280
+ return true;
281
+ }
278
282
  };
279
283
 
280
284
  - (void)_setUpFeatureFlags
@@ -16,7 +16,7 @@ const version: $ReadOnly<{
16
16
  }> = {
17
17
  major: 0,
18
18
  minor: 78,
19
- patch: 2,
19
+ patch: 3,
20
20
  prerelease: null,
21
21
  };
22
22
 
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(78),
26
- RCTVersionPatch: @(2),
26
+ RCTVersionPatch: @(3),
27
27
  RCTVersionPrerelease: [NSNull null],
28
28
  };
29
29
  });
@@ -170,10 +170,24 @@ static NSString *const kRCTLegacyInteropChildIndexKey = @"index";
170
170
 
171
171
  - (void)mountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
172
172
  {
173
- [_viewsToBeMounted addObject:@{
174
- kRCTLegacyInteropChildIndexKey : [NSNumber numberWithInteger:index],
175
- kRCTLegacyInteropChildComponentKey : childComponentView
176
- }];
173
+ if (_adapter && index == _adapter.paperView.reactSubviews.count) {
174
+ // This is a new child view that is being added to the end of the children array.
175
+ // After the children is added, we need to call didUpdateReactSubviews to make sure that it is rendered.
176
+ // Without this change, the new child will not be rendered right away because the didUpdateReactSubviews is not
177
+ // called and the `finalizeUpdate` is not invoked.
178
+ if ([childComponentView isKindOfClass:[RCTLegacyViewManagerInteropComponentView class]]) {
179
+ UIView *target = ((RCTLegacyViewManagerInteropComponentView *)childComponentView).contentView;
180
+ [_adapter.paperView insertReactSubview:target atIndex:index];
181
+ } else {
182
+ [_adapter.paperView insertReactSubview:childComponentView atIndex:index];
183
+ }
184
+ [_adapter.paperView didUpdateReactSubviews];
185
+ } else {
186
+ [_viewsToBeMounted addObject:@{
187
+ kRCTLegacyInteropChildIndexKey : [NSNumber numberWithInteger:index],
188
+ kRCTLegacyInteropChildComponentKey : childComponentView
189
+ }];
190
+ }
177
191
  }
178
192
 
179
193
  - (void)unmountChildComponentView:(UIView<RCTComponentViewProtocol> *)childComponentView index:(NSInteger)index
@@ -60,7 +60,7 @@ using namespace facebook::react;
60
60
  const auto &newSwitchProps = static_cast<const SwitchProps &>(*props);
61
61
 
62
62
  // `value`
63
- if (oldSwitchProps.value != newSwitchProps.value) {
63
+ if (!_isInitialValueSet || oldSwitchProps.value != newSwitchProps.value) {
64
64
  BOOL shouldAnimate = _isInitialValueSet == YES;
65
65
  [_switchView setOn:newSwitchProps.value animated:shouldAnimate];
66
66
  }
@@ -143,6 +143,7 @@ using namespace facebook::react;
143
143
 
144
144
  if (!_view) {
145
145
  _view = [[RCTSurfaceView alloc] initWithSurface:(RCTSurface *)self];
146
+ [self _updateLayoutContext];
146
147
  _touchHandler = [RCTSurfaceTouchHandler new];
147
148
  [_touchHandler attachToView:_view];
148
149
  }
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.78.2
1
+ VERSION_NAME=0.78.3
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
 
4
4
  android.useAndroidX=true
@@ -17,6 +17,6 @@ public class ReactNativeVersion {
17
17
  public static final Map<String, Object> VERSION = MapBuilder.<String, Object>of(
18
18
  "major", 0,
19
19
  "minor", 78,
20
- "patch", 2,
20
+ "patch", 3,
21
21
  "prerelease", null);
22
22
  }
@@ -136,10 +136,10 @@ public data class BorderRadiusStyle(
136
136
  (startStart ?: topStart ?: topLeft ?: uniform)?.resolve(width, height)
137
137
  ?: zeroRadii,
138
138
  bottomLeft =
139
- (endEnd ?: bottomStart ?: bottomRight ?: uniform)?.resolve(width, height)
139
+ (endEnd ?: bottomEnd ?: bottomRight ?: uniform)?.resolve(width, height)
140
140
  ?: zeroRadii,
141
141
  bottomRight =
142
- (startEnd ?: bottomEnd ?: bottomLeft ?: uniform)?.resolve(width, height)
142
+ (startEnd ?: bottomStart ?: bottomLeft ?: uniform)?.resolve(width, height)
143
143
  ?: zeroRadii,
144
144
  width = width,
145
145
  height = height,
@@ -17,7 +17,7 @@ namespace facebook::react {
17
17
  constexpr struct {
18
18
  int32_t Major = 0;
19
19
  int32_t Minor = 78;
20
- int32_t Patch = 2;
20
+ int32_t Patch = 3;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -300,8 +300,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
300
300
  }
301
301
 
302
302
  if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
303
- // Do not throw any error to match web spec
304
- return timerIndex_++;
303
+ // Do not throw any error to match web spec; instead return 0, an
304
+ // invalid timer id
305
+ return 0;
305
306
  }
306
307
 
307
308
  auto callback = args[0].getObject(rt).getFunction(rt);
@@ -358,8 +359,9 @@ void TimerManager::attachGlobals(jsi::Runtime& runtime) {
358
359
  }
359
360
 
360
361
  if (!args[0].isObject() || !args[0].asObject(rt).isFunction(rt)) {
361
- throw jsi::JSError(
362
- rt, "The first argument to setInterval must be a function.");
362
+ // Do not throw any error to match web spec; instead return 0, an
363
+ // invalid timer id
364
+ return 0;
363
365
  }
364
366
  auto callback = args[0].getObject(rt).getFunction(rt);
365
367
  auto delay = count > 1
@@ -93,7 +93,9 @@ class TimerManager {
93
93
 
94
94
  // Each timeout that is registered on this queue gets a sequential id. This
95
95
  // is the global count from which those are assigned.
96
- TimerHandle timerIndex_{0};
96
+ // As per WHATWG HTML 8.6.1 (Timers) ids must be greater than zero, i.e. start
97
+ // at 1
98
+ TimerHandle timerIndex_{1};
97
99
 
98
100
  // The React Native microtask queue is used to back public APIs including
99
101
  // `queueMicrotask`, `clearImmediate`, and `setImmediate` (which is used by
@@ -267,7 +267,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithoutDelay) {
267
267
  EXPECT_CALL(
268
268
  *mockRegistry_,
269
269
  createTimer(_, 0)); // If delay is not provided, it should use 0
270
- eval("setTimeout(() => {});");
270
+ auto val = eval("setTimeout(() => {});");
271
+ expectNoError();
272
+ EXPECT_EQ(val.asNumber(), 1); // First timer id should start at 1
271
273
  }
272
274
 
273
275
  TEST_F(ReactInstanceTest, testSetTimeoutWithPassThroughArgs) {
@@ -299,8 +301,9 @@ TEST_F(ReactInstanceTest, testSetTimeoutWithInvalidArgs) {
299
301
  getErrorMessage("setTimeout();"),
300
302
  "setTimeout must be called with at least one argument (the function to call).");
301
303
 
302
- eval("setTimeout('invalid');");
304
+ auto val = eval("setTimeout('invalid')");
303
305
  expectNoError();
306
+ EXPECT_EQ(val.asNumber(), 0);
304
307
 
305
308
  eval("setTimeout(() => {}, 'invalid');");
306
309
  expectNoError();
@@ -417,9 +420,10 @@ TEST_F(ReactInstanceTest, testSetIntervalWithInvalidArgs) {
417
420
  EXPECT_EQ(
418
421
  getErrorMessage("setInterval();"),
419
422
  "setInterval must be called with at least one argument (the function to call).");
420
- EXPECT_EQ(
421
- getErrorMessage("setInterval('invalid', 100);"),
422
- "The first argument to setInterval must be a function.");
423
+
424
+ auto val = eval("setInterval('invalid', 100)");
425
+ expectNoError();
426
+ EXPECT_EQ(val.asNumber(), 0);
423
427
  }
424
428
 
425
429
  TEST_F(ReactInstanceTest, testClearInterval) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.78.2",
3
+ "version": "0.78.3",
4
4
  "description": "A framework for building native apps using React",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -108,13 +108,13 @@
108
108
  },
109
109
  "dependencies": {
110
110
  "@jest/create-cache-key-function": "^29.6.3",
111
- "@react-native/assets-registry": "0.78.2",
112
- "@react-native/codegen": "0.78.2",
113
- "@react-native/community-cli-plugin": "0.78.2",
114
- "@react-native/gradle-plugin": "0.78.2",
115
- "@react-native/js-polyfills": "0.78.2",
116
- "@react-native/normalize-colors": "0.78.2",
117
- "@react-native/virtualized-lists": "0.78.2",
111
+ "@react-native/assets-registry": "0.78.3",
112
+ "@react-native/codegen": "0.78.3",
113
+ "@react-native/community-cli-plugin": "0.78.3",
114
+ "@react-native/gradle-plugin": "0.78.3",
115
+ "@react-native/js-polyfills": "0.78.3",
116
+ "@react-native/normalize-colors": "0.78.3",
117
+ "@react-native/virtualized-lists": "0.78.3",
118
118
  "abort-controller": "^3.0.0",
119
119
  "anser": "^1.4.9",
120
120
  "ansi-regex": "^5.0.0",
@@ -324,22 +324,13 @@ function findExternalLibraries(pkgJson, projectRoot) {
324
324
  });
325
325
  }
326
326
 
327
- function findLibrariesFromReactNativeConfig(projectRoot) {
328
- const rnConfigFileName = 'react-native.config.js';
329
-
327
+ function findLibrariesFromReactNativeConfig(projectRoot, rnConfig) {
330
328
  codegenLog(
331
- `Searching for codegen-enabled libraries in ${rnConfigFileName}`,
329
+ `Searching for codegen-enabled libraries in react-native.config.js`,
332
330
  true,
333
331
  );
334
332
 
335
- const rnConfigFilePath = path.resolve(projectRoot, rnConfigFileName);
336
-
337
- if (!fs.existsSync(rnConfigFilePath)) {
338
- return [];
339
- }
340
- const rnConfig = require(rnConfigFilePath);
341
-
342
- if (rnConfig.dependencies == null) {
333
+ if (!rnConfig.dependencies) {
343
334
  return [];
344
335
  }
345
336
  return Object.keys(rnConfig.dependencies).flatMap(name => {
@@ -591,7 +582,7 @@ function mustGenerateNativeCode(includeLibraryPath, schemaInfo) {
591
582
  );
592
583
  }
593
584
 
594
- function findCodegenEnabledLibraries(pkgJson, projectRoot) {
585
+ function findCodegenEnabledLibraries(pkgJson, projectRoot, reactNativeConfig) {
595
586
  const projectLibraries = findProjectRootLibraries(pkgJson, projectRoot);
596
587
  if (pkgJsonIncludesGeneratedCode(pkgJson)) {
597
588
  return projectLibraries;
@@ -599,7 +590,7 @@ function findCodegenEnabledLibraries(pkgJson, projectRoot) {
599
590
  return [
600
591
  ...projectLibraries,
601
592
  ...findExternalLibraries(pkgJson, projectRoot),
602
- ...findLibrariesFromReactNativeConfig(projectRoot),
593
+ ...findLibrariesFromReactNativeConfig(projectRoot, reactNativeConfig),
603
594
  ];
604
595
  }
605
596
  }
@@ -924,9 +915,14 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
924
915
 
925
916
  buildCodegenIfNeeded();
926
917
 
927
- const libraries = findCodegenEnabledLibraries(pkgJson, projectRoot);
918
+ const reactNativeConfig = readReactNativeConfig(projectRoot);
919
+ const codegenEnabledLibraries = findCodegenEnabledLibraries(
920
+ pkgJson,
921
+ projectRoot,
922
+ reactNativeConfig,
923
+ );
928
924
 
929
- if (libraries.length === 0) {
925
+ if (codegenEnabledLibraries.length === 0) {
930
926
  codegenLog('No codegen-enabled libraries found.', true);
931
927
  return;
932
928
  }
@@ -935,6 +931,18 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
935
931
  targetPlatform === 'all' ? supportedPlatforms : [targetPlatform];
936
932
 
937
933
  for (const platform of platforms) {
934
+ const disabledLibraries = findDisabledLibrariesByPlatform(
935
+ reactNativeConfig,
936
+ platform,
937
+ );
938
+ const libraries = codegenEnabledLibraries.filter(
939
+ ({name}) => !disabledLibraries.includes(name),
940
+ );
941
+
942
+ if (!libraries.length) {
943
+ continue;
944
+ }
945
+
938
946
  const outputPath = computeOutputPath(
939
947
  projectRoot,
940
948
  baseOutputPath,
@@ -970,6 +978,29 @@ function execute(projectRoot, targetPlatform, baseOutputPath, source) {
970
978
  return;
971
979
  }
972
980
 
981
+ /**
982
+ * Finds all disabled libraries by platform based the react native config.
983
+ *
984
+ * This is needed when selectively disabling libraries in react-native.config.js since codegen should exclude those libraries as well.
985
+ */
986
+ function findDisabledLibrariesByPlatform(reactNativeConfig, platform) {
987
+ const dependencies = reactNativeConfig.dependencies ?? {};
988
+
989
+ return Object.keys(dependencies).filter(
990
+ dependency => dependencies[dependency].platforms?.[platform] === null,
991
+ );
992
+ }
993
+
994
+ function readReactNativeConfig(projectRoot) {
995
+ const rnConfigFilePath = path.resolve(projectRoot, 'react-native.config.js');
996
+
997
+ if (!fs.existsSync(rnConfigFilePath)) {
998
+ return {};
999
+ }
1000
+
1001
+ return require(rnConfigFilePath);
1002
+ }
1003
+
973
1004
  module.exports = {
974
1005
  execute,
975
1006
  generateRNCoreComponentsIOS,
Binary file
Binary file
Binary file
Binary file