react-native 0.78.1 → 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.
Files changed (28) hide show
  1. package/Libraries/AppDelegate/RCTDefaultReactNativeFactoryDelegate.mm +7 -0
  2. package/Libraries/AppDelegate/RCTReactNativeFactory.mm +4 -0
  3. package/Libraries/Components/TextInput/TextInput.js +3 -3
  4. package/Libraries/Core/ReactNativeVersion.js +1 -1
  5. package/Libraries/Network/RCTDataRequestHandler.mm +17 -3
  6. package/Libraries/Network/RCTFileRequestHandler.mm +17 -3
  7. package/React/Base/RCTVersion.m +1 -1
  8. package/React/Fabric/Mounting/ComponentViews/LegacyViewManagerInterop/RCTLegacyViewManagerInteropComponentView.mm +18 -4
  9. package/React/Fabric/Mounting/ComponentViews/Switch/RCTSwitchComponentView.mm +1 -1
  10. package/React/Fabric/Surface/RCTFabricSurface.mm +1 -0
  11. package/ReactAndroid/gradle.properties +1 -1
  12. package/ReactAndroid/src/main/java/com/facebook/react/fabric/FabricUIManager.java +13 -8
  13. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.java +1 -1
  14. package/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/BorderRadiusStyle.kt +2 -2
  15. package/ReactAndroid/src/main/java/com/facebook/react/views/view/ReactViewGroup.java +0 -3
  16. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  17. package/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.mm +24 -13
  18. package/ReactCommon/react/runtime/TimerManager.cpp +6 -4
  19. package/ReactCommon/react/runtime/TimerManager.h +3 -1
  20. package/ReactCommon/react/runtime/tests/cxx/ReactInstanceTest.cpp +9 -5
  21. package/package.json +10 -10
  22. package/scripts/codegen/generate-artifacts-executor.js +47 -16
  23. package/sdks/hermesc/osx-bin/hermes +0 -0
  24. package/sdks/hermesc/osx-bin/hermesc +0 -0
  25. package/sdks/hermesc/win64-bin/hermesc.exe +0 -0
  26. package/sdks/hermesc/win64-bin/msvcp140.dll +0 -0
  27. package/sdks/hermesc/win64-bin/vcruntime140.dll +0 -0
  28. package/sdks/hermesc/win64-bin/vcruntime140_1.dll +0 -0
@@ -118,4 +118,11 @@
118
118
  return nullptr;
119
119
  }
120
120
 
121
+ - (void)loadSourceForBridge:(RCTBridge *)bridge
122
+ onProgress:(RCTSourceLoadProgressBlock)onProgress
123
+ onComplete:(RCTSourceLoadBlock)loadCallback
124
+ {
125
+ [RCTJavaScriptLoader loadBundleAtURL:[self sourceURLForBridge:bridge] onProgress:onProgress onComplete:loadCallback];
126
+ }
127
+
121
128
  @end
@@ -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
@@ -1019,7 +1019,7 @@ function useTextInputStateSynchronization_STATE({
1019
1019
  mostRecentEventCount: number,
1020
1020
  selection: ?Selection,
1021
1021
  inputRef: React.RefObject<null | HostInstance>,
1022
- text: string,
1022
+ text?: string,
1023
1023
  viewCommands: ViewCommands,
1024
1024
  }): {
1025
1025
  setLastNativeText: string => void,
@@ -1100,7 +1100,7 @@ function useTextInputStateSynchronization_REFS({
1100
1100
  mostRecentEventCount: number,
1101
1101
  selection: ?Selection,
1102
1102
  inputRef: React.RefObject<null | HostInstance>,
1103
- text: string,
1103
+ text?: string,
1104
1104
  viewCommands: ViewCommands,
1105
1105
  }): {
1106
1106
  setLastNativeText: string => void,
@@ -1314,7 +1314,7 @@ function InternalTextInput(props: Props): React.Node {
1314
1314
  ? props.value
1315
1315
  : typeof props.defaultValue === 'string'
1316
1316
  ? props.defaultValue
1317
- : '';
1317
+ : undefined;
1318
1318
 
1319
1319
  const viewCommands =
1320
1320
  AndroidTextInputCommands ||
@@ -16,7 +16,7 @@ const version: $ReadOnly<{
16
16
  }> = {
17
17
  major: 0,
18
18
  minor: 78,
19
- patch: 1,
19
+ patch: 3,
20
20
  prerelease: null,
21
21
  };
22
22
 
@@ -8,6 +8,8 @@
8
8
  #import <React/RCTDataRequestHandler.h>
9
9
  #import <ReactCommon/RCTTurboModule.h>
10
10
 
11
+ #import <mutex>
12
+
11
13
  #import "RCTNetworkPlugins.h"
12
14
 
13
15
  @interface RCTDataRequestHandler () <RCTTurboModule>
@@ -15,14 +17,22 @@
15
17
 
16
18
  @implementation RCTDataRequestHandler {
17
19
  NSOperationQueue *_queue;
20
+ std::mutex _operationHandlerMutexLock;
18
21
  }
19
22
 
20
23
  RCT_EXPORT_MODULE()
21
24
 
22
25
  - (void)invalidate
23
26
  {
24
- [_queue cancelAllOperations];
25
- _queue = nil;
27
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
28
+ if (_queue) {
29
+ for (NSOperation *operation in _queue.operations) {
30
+ if (!operation.isCancelled && !operation.isFinished) {
31
+ [operation cancel];
32
+ }
33
+ }
34
+ _queue = nil;
35
+ }
26
36
  }
27
37
 
28
38
  - (BOOL)canHandleRequest:(NSURLRequest *)request
@@ -32,6 +42,7 @@ RCT_EXPORT_MODULE()
32
42
 
33
43
  - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
34
44
  {
45
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
35
46
  // Lazy setup
36
47
  if (!_queue) {
37
48
  _queue = [NSOperationQueue new];
@@ -69,7 +80,10 @@ RCT_EXPORT_MODULE()
69
80
 
70
81
  - (void)cancelRequest:(NSOperation *)op
71
82
  {
72
- [op cancel];
83
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
84
+ if (!op.isCancelled && !op.isFinished) {
85
+ [op cancel];
86
+ }
73
87
  }
74
88
 
75
89
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
@@ -7,6 +7,8 @@
7
7
 
8
8
  #import <React/RCTFileRequestHandler.h>
9
9
 
10
+ #import <mutex>
11
+
10
12
  #import <MobileCoreServices/MobileCoreServices.h>
11
13
 
12
14
  #import <React/RCTUtils.h>
@@ -19,14 +21,22 @@
19
21
 
20
22
  @implementation RCTFileRequestHandler {
21
23
  NSOperationQueue *_fileQueue;
24
+ std::mutex _operationHandlerMutexLock;
22
25
  }
23
26
 
24
27
  RCT_EXPORT_MODULE()
25
28
 
26
29
  - (void)invalidate
27
30
  {
28
- [_fileQueue cancelAllOperations];
29
- _fileQueue = nil;
31
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
32
+ if (_fileQueue) {
33
+ for (NSOperation *operation in _fileQueue.operations) {
34
+ if (!operation.isCancelled && !operation.isFinished) {
35
+ [operation cancel];
36
+ }
37
+ }
38
+ _fileQueue = nil;
39
+ }
30
40
  }
31
41
 
32
42
  - (BOOL)canHandleRequest:(NSURLRequest *)request
@@ -36,6 +46,7 @@ RCT_EXPORT_MODULE()
36
46
 
37
47
  - (NSOperation *)sendRequest:(NSURLRequest *)request withDelegate:(id<RCTURLRequestDelegate>)delegate
38
48
  {
49
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
39
50
  // Lazy setup
40
51
  if (!_fileQueue) {
41
52
  _fileQueue = [NSOperationQueue new];
@@ -83,7 +94,10 @@ RCT_EXPORT_MODULE()
83
94
 
84
95
  - (void)cancelRequest:(NSOperation *)op
85
96
  {
86
- [op cancel];
97
+ std::lock_guard<std::mutex> lock(_operationHandlerMutexLock);
98
+ if (!op.isCancelled && !op.isFinished) {
99
+ [op cancel];
100
+ }
87
101
  }
88
102
 
89
103
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
@@ -23,7 +23,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
23
23
  __rnVersion = @{
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(78),
26
- RCTVersionPatch: @(1),
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.1
1
+ VERSION_NAME=0.78.3
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
 
4
4
  android.useAndroidX=true
@@ -173,7 +173,7 @@ public class FabricUIManager
173
173
  private final CopyOnWriteArrayList<UIManagerListener> mListeners = new CopyOnWriteArrayList<>();
174
174
 
175
175
  private boolean mMountNotificationScheduled = false;
176
- private final List<Integer> mMountedSurfaceIds = new ArrayList<>();
176
+ private List<Integer> mSurfaceIdsWithPendingMountNotification = new ArrayList<>();
177
177
 
178
178
  @ThreadConfined(UI)
179
179
  @NonNull
@@ -1250,12 +1250,15 @@ public class FabricUIManager
1250
1250
 
1251
1251
  // Collect surface IDs for all the mount items
1252
1252
  for (MountItem mountItem : mountItems) {
1253
- if (mountItem != null && !mMountedSurfaceIds.contains(mountItem.getSurfaceId())) {
1254
- mMountedSurfaceIds.add(mountItem.getSurfaceId());
1253
+ if (mountItem != null
1254
+ && !mSurfaceIdsWithPendingMountNotification.contains(mountItem.getSurfaceId())) {
1255
+ mSurfaceIdsWithPendingMountNotification.add(mountItem.getSurfaceId());
1255
1256
  }
1256
1257
  }
1257
1258
 
1258
- if (!mMountNotificationScheduled && !mMountedSurfaceIds.isEmpty()) {
1259
+ if (!mMountNotificationScheduled && !mSurfaceIdsWithPendingMountNotification.isEmpty()) {
1260
+ mMountNotificationScheduled = true;
1261
+
1259
1262
  // Notify mount when the effects are visible and prevent mount hooks to
1260
1263
  // delay paint.
1261
1264
  UiThreadUtil.getUiThreadHandler()
@@ -1265,17 +1268,19 @@ public class FabricUIManager
1265
1268
  public void run() {
1266
1269
  mMountNotificationScheduled = false;
1267
1270
 
1271
+ // Create a copy in case mount hooks trigger more mutations
1272
+ final List<Integer> surfaceIdsToReportMount =
1273
+ mSurfaceIdsWithPendingMountNotification;
1274
+ mSurfaceIdsWithPendingMountNotification = new ArrayList<>();
1275
+
1268
1276
  final @Nullable FabricUIManagerBinding binding = mBinding;
1269
1277
  if (binding == null || mDestroyed) {
1270
- mMountedSurfaceIds.clear();
1271
1278
  return;
1272
1279
  }
1273
1280
 
1274
- for (int surfaceId : mMountedSurfaceIds) {
1281
+ for (int surfaceId : surfaceIdsToReportMount) {
1275
1282
  binding.reportMount(surfaceId);
1276
1283
  }
1277
-
1278
- mMountedSurfaceIds.clear();
1279
1284
  }
1280
1285
  });
1281
1286
  }
@@ -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", 1,
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,
@@ -588,9 +588,6 @@ public class ReactViewGroup extends ViewGroup
588
588
  UiThreadUtil.assertOnUiThread();
589
589
  checkViewClippingTag(child, Boolean.TRUE);
590
590
  if (!customDrawOrderDisabled()) {
591
- if (indexOfChild(child) == -1) {
592
- return;
593
- }
594
591
  getDrawingOrderHelper().handleRemoveView(child);
595
592
  setChildrenDrawingOrderEnabled(getDrawingOrderHelper().shouldEnableCustomDrawingOrder());
596
593
  } else {
@@ -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 = 1;
20
+ int32_t Patch = 3;
21
21
  std::string_view Prerelease = "";
22
22
  } ReactNativeVersion;
23
23
 
@@ -57,7 +57,7 @@ static jsi::Value convertNSNumberToJSINumber(jsi::Runtime &runtime, NSNumber *va
57
57
 
58
58
  static jsi::String convertNSStringToJSIString(jsi::Runtime &runtime, NSString *value)
59
59
  {
60
- return jsi::String::createFromUtf8(runtime, [value UTF8String] ?: "");
60
+ return jsi::String::createFromUtf8(runtime, [value UTF8String] ? [value UTF8String] : "");
61
61
  }
62
62
 
63
63
  static jsi::Object convertNSDictionaryToJSIObject(jsi::Runtime &runtime, NSDictionary *value)
@@ -203,7 +203,11 @@ static jsi::Value createJSRuntimeError(jsi::Runtime &runtime, const std::string
203
203
  /**
204
204
  * Creates JSError with current JS runtime and NSException stack trace.
205
205
  */
206
- static jsi::JSError convertNSExceptionToJSError(jsi::Runtime &runtime, NSException *exception)
206
+ static jsi::JSError convertNSExceptionToJSError(
207
+ jsi::Runtime &runtime,
208
+ NSException *exception,
209
+ const std::string &moduleName,
210
+ const std::string &methodName)
207
211
  {
208
212
  std::string reason = [exception.reason UTF8String];
209
213
 
@@ -214,7 +218,8 @@ static jsi::JSError convertNSExceptionToJSError(jsi::Runtime &runtime, NSExcepti
214
218
  cause.setProperty(
215
219
  runtime, "stackReturnAddresses", convertNSArrayToJSIArray(runtime, exception.callStackReturnAddresses));
216
220
 
217
- jsi::Value error = createJSRuntimeError(runtime, "Exception in HostFunction: " + reason);
221
+ std::string message = moduleName + "." + methodName + " raised an exception: " + reason;
222
+ jsi::Value error = createJSRuntimeError(runtime, message);
218
223
  error.asObject(runtime).setProperty(runtime, "cause", std::move(cause));
219
224
  return {runtime, std::move(error)};
220
225
  }
@@ -346,28 +351,34 @@ id ObjCTurboModule::performMethodInvocation(
346
351
  }
347
352
 
348
353
  if (isSync) {
349
- TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str());
354
+ TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName);
350
355
  } else {
351
- TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodNameStr.c_str(), asyncCallCounter);
356
+ TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter);
352
357
  }
353
358
 
354
359
  @try {
355
360
  [inv invokeWithTarget:strongModule];
356
361
  } @catch (NSException *exception) {
357
- throw convertNSExceptionToJSError(runtime, exception);
362
+ if (isSync) {
363
+ // We can only convert NSException to JSError in sync method calls.
364
+ // See https://github.com/reactwg/react-native-new-architecture/discussions/276#discussioncomment-12567155
365
+ throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr);
366
+ } else {
367
+ @throw exception;
368
+ }
358
369
  } @finally {
359
370
  [retainedObjectsForInvocation removeAllObjects];
360
371
  }
361
372
 
362
373
  if (!isSync) {
363
- TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodNameStr.c_str(), asyncCallCounter);
374
+ TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter);
364
375
  return;
365
376
  }
366
377
 
367
378
  void *rawResult;
368
379
  [inv getReturnValue:&rawResult];
369
380
  result = (__bridge id)rawResult;
370
- TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str());
381
+ TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName);
371
382
  };
372
383
 
373
384
  if (isSync) {
@@ -409,23 +420,23 @@ void ObjCTurboModule::performVoidMethodInvocation(
409
420
  }
410
421
 
411
422
  if (shouldVoidMethodsExecuteSync_) {
412
- TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodNameStr.c_str());
423
+ TurboModulePerfLogger::syncMethodCallExecutionStart(moduleName, methodName);
413
424
  } else {
414
- TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodNameStr.c_str(), asyncCallCounter);
425
+ TurboModulePerfLogger::asyncMethodCallExecutionStart(moduleName, methodName, asyncCallCounter);
415
426
  }
416
427
 
417
428
  @try {
418
429
  [inv invokeWithTarget:strongModule];
419
430
  } @catch (NSException *exception) {
420
- throw convertNSExceptionToJSError(runtime, exception);
431
+ throw convertNSExceptionToJSError(runtime, exception, std::string{moduleName}, methodNameStr);
421
432
  } @finally {
422
433
  [retainedObjectsForInvocation removeAllObjects];
423
434
  }
424
435
 
425
436
  if (shouldVoidMethodsExecuteSync_) {
426
- TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodNameStr.c_str());
437
+ TurboModulePerfLogger::syncMethodCallExecutionEnd(moduleName, methodName);
427
438
  } else {
428
- TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodNameStr.c_str(), asyncCallCounter);
439
+ TurboModulePerfLogger::asyncMethodCallExecutionEnd(moduleName, methodName, asyncCallCounter);
429
440
  }
430
441
 
431
442
  return;
@@ -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.1",
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.1",
112
- "@react-native/codegen": "0.78.1",
113
- "@react-native/community-cli-plugin": "0.78.1",
114
- "@react-native/gradle-plugin": "0.78.1",
115
- "@react-native/js-polyfills": "0.78.1",
116
- "@react-native/normalize-colors": "0.78.1",
117
- "@react-native/virtualized-lists": "0.78.1",
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",
@@ -129,8 +129,8 @@
129
129
  "invariant": "^2.2.4",
130
130
  "jest-environment-node": "^29.6.3",
131
131
  "memoize-one": "^5.0.0",
132
- "metro-runtime": "^0.81.0",
133
- "metro-source-map": "^0.81.0",
132
+ "metro-runtime": "^0.81.3",
133
+ "metro-source-map": "^0.81.3",
134
134
  "nullthrows": "^1.1.1",
135
135
  "pretty-format": "^29.7.0",
136
136
  "promise": "^8.3.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