react-native 0.85.0-rc.0 → 0.85.0-rc.1

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 (29) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Libraries/Core/setUpReactDevTools.js +23 -6
  3. package/Libraries/Network/RCTHTTPRequestHandler.h +9 -0
  4. package/Libraries/Network/RCTHTTPRequestHandler.mm +15 -1
  5. package/React/Base/RCTMultipartDataTask.h +9 -0
  6. package/React/Base/RCTMultipartDataTask.m +16 -1
  7. package/React/Base/RCTVersion.m +1 -1
  8. package/React/CoreModules/RCTWebSocketModule.h +6 -0
  9. package/React/CoreModules/RCTWebSocketModule.mm +14 -1
  10. package/React/DevSupport/RCTInspectorDevServerHelper.mm +31 -22
  11. package/ReactAndroid/gradle.properties +1 -1
  12. package/ReactAndroid/src/main/java/com/facebook/react/modules/systeminfo/ReactNativeVersion.kt +1 -1
  13. package/ReactAndroid/src/main/java/com/facebook/react/modules/websocket/WebSocketModule.kt +3 -4
  14. package/ReactAndroid/src/main/jni/CMakeLists.txt +3 -0
  15. package/ReactApple/RCTAnimatedModuleProvider/RCTAnimatedModuleProvider.mm +4 -1
  16. package/ReactCommon/cxxreact/ReactNativeVersion.h +1 -1
  17. package/ReactCommon/jsinspector-modern/InspectorInterfaces.cpp +6 -0
  18. package/ReactCommon/react/nativemodule/defaults/CMakeLists.txt +1 -0
  19. package/ReactCommon/react/nativemodule/defaults/DefaultTurboModules.cpp +8 -0
  20. package/ReactCommon/react/nativemodule/defaults/React-defaultsnativemodule.podspec +1 -0
  21. package/ReactCommon/react/renderer/animated/NativeAnimatedNodesManagerProvider.cpp +79 -71
  22. package/ReactCommon/react/renderer/animationbackend/AnimatedPropsRegistry.cpp +3 -1
  23. package/ReactCommon/react/renderer/animationbackend/AnimatedPropsRegistry.h +3 -3
  24. package/ReactCommon/react/renderer/animationbackend/AnimationBackend.cpp +3 -2
  25. package/ReactCommon/react/renderer/animationbackend/AnimationBackendCommitHook.cpp +4 -3
  26. package/ReactCommon/react/renderer/core/ShadowNode.cpp +14 -13
  27. package/ReactCommon/react/renderer/core/ShadowNode.h +1 -1
  28. package/ReactCommon/react/renderer/core/tests/ShadowNodeTest.cpp +4 -4
  29. package/package.json +9 -9
@@ -29,7 +29,7 @@ export default class ReactNativeVersion {
29
29
  static major: number = 0;
30
30
  static minor: number = 85;
31
31
  static patch: number = 0;
32
- static prerelease: string | null = 'rc.0';
32
+ static prerelease: string | null = 'rc.1';
33
33
 
34
34
  static getVersionString(): string {
35
35
  return `${this.major}.${this.minor}.${this.patch}${this.prerelease != null ? `-${this.prerelease}` : ''}`;
@@ -146,17 +146,34 @@ if (__DEV__) {
146
146
  ? guessHostFromDevServerUrl(devServer.url)
147
147
  : 'localhost';
148
148
 
149
- // Read the optional global variable for backward compatibility.
150
- // It was added in https://github.com/facebook/react-native/commit/bf2b435322e89d0aeee8792b1c6e04656c2719a0.
151
- const port =
149
+ // Derive scheme and port from the dev server URL when possible,
150
+ // falling back to ws://host:8097 for local development.
151
+ let wsScheme = 'ws';
152
+ let port = 8097;
153
+
154
+ if (
152
155
  // $FlowFixMe[prop-missing]
153
156
  // $FlowFixMe[incompatible-use]
154
157
  window.__REACT_DEVTOOLS_PORT__ != null
155
- ? window.__REACT_DEVTOOLS_PORT__
156
- : 8097;
158
+ ) {
159
+ // $FlowFixMe[prop-missing]
160
+ port = window.__REACT_DEVTOOLS_PORT__;
161
+ } else if (devServer.bundleLoadedFromServer) {
162
+ try {
163
+ const devUrl = new URL(devServer.url);
164
+ if (devUrl.protocol === 'https:') {
165
+ wsScheme = 'wss';
166
+ }
167
+ if (devUrl.port) {
168
+ port = parseInt(devUrl.port, 10);
169
+ } else if (devUrl.protocol === 'https:') {
170
+ port = 443;
171
+ }
172
+ } catch (e) {}
173
+ }
157
174
 
158
175
  const WebSocket = require('../WebSocket/WebSocket').default;
159
- ws = new WebSocket('ws://' + host + ':' + port);
176
+ ws = new WebSocket(wsScheme + '://' + host + ':' + port);
160
177
  ws.addEventListener('close', event => {
161
178
  isWebSocketOpen = false;
162
179
  });
@@ -14,6 +14,15 @@ typedef NSURLSessionConfiguration * (^NSURLSessionConfigurationProvider)(void);
14
14
  * app.
15
15
  */
16
16
  RCT_EXTERN void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProvider /*provider*/);
17
+
18
+ typedef NSURLRequest *_Nullable (^RCTHTTPRequestInterceptor)(NSURLRequest *request);
19
+ /**
20
+ * The block provided via this function can inspect/modify HTTP requests before
21
+ * they are sent. Return a modified request to override, or nil to use the
22
+ * original request unchanged.
23
+ */
24
+ RCT_EXTERN void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor /*interceptor*/);
25
+
17
26
  /**
18
27
  * This is the default RCTURLRequestHandler implementation for HTTP requests.
19
28
  */
@@ -25,6 +25,13 @@ void RCTSetCustomNSURLSessionConfigurationProvider(NSURLSessionConfigurationProv
25
25
  urlSessionConfigurationProvider = provider;
26
26
  }
27
27
 
28
+ static RCTHTTPRequestInterceptor httpRequestInterceptor;
29
+
30
+ void RCTSetCustomHTTPRequestInterceptor(RCTHTTPRequestInterceptor interceptor)
31
+ {
32
+ httpRequestInterceptor = interceptor;
33
+ }
34
+
28
35
  @implementation RCTHTTPRequestHandler {
29
36
  NSMapTable *_delegates;
30
37
  NSURLSession *_session;
@@ -99,7 +106,14 @@ RCT_EXPORT_MODULE()
99
106
  valueOptions:NSPointerFunctionsStrongMemory
100
107
  capacity:0];
101
108
  }
102
- NSURLSessionDataTask *task = [_session dataTaskWithRequest:request];
109
+ NSURLRequest *finalRequest = request;
110
+ if (httpRequestInterceptor != nullptr) {
111
+ NSURLRequest *intercepted = httpRequestInterceptor(request);
112
+ if (intercepted != nil) {
113
+ finalRequest = intercepted;
114
+ }
115
+ }
116
+ NSURLSessionDataTask *task = [_session dataTaskWithRequest:finalRequest];
103
117
  [_delegates setObject:delegate forKey:task];
104
118
  [task resume];
105
119
  return task;
@@ -7,6 +7,7 @@
7
7
 
8
8
  #import <Foundation/Foundation.h>
9
9
 
10
+ #import <React/RCTDefines.h>
10
11
  #import <React/RCTMultipartStreamReader.h>
11
12
 
12
13
  typedef void (^RCTMultipartDataTaskCallback)(
@@ -16,6 +17,14 @@ typedef void (^RCTMultipartDataTaskCallback)(
16
17
  NSError *error,
17
18
  BOOL done);
18
19
 
20
+ typedef NSURLRequest * _Nullable (^RCTMultipartDataTaskRequestInterceptor)(NSURLRequest *request);
21
+ /**
22
+ * The block provided via this function can inspect/modify multipart data task
23
+ * requests before they are sent. Return a modified request to override, or nil
24
+ * to use the original request unchanged.
25
+ */
26
+ RCT_EXTERN void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor /*interceptor*/);
27
+
19
28
  @interface RCTMultipartDataTask : NSObject
20
29
 
21
30
  - (instancetype)initWithURL:(NSURL *)url
@@ -7,6 +7,13 @@
7
7
 
8
8
  #import "RCTMultipartDataTask.h"
9
9
 
10
+ static RCTMultipartDataTaskRequestInterceptor multipartRequestInterceptor;
11
+
12
+ void RCTSetCustomMultipartDataTaskRequestInterceptor(RCTMultipartDataTaskRequestInterceptor interceptor)
13
+ {
14
+ multipartRequestInterceptor = interceptor;
15
+ }
16
+
10
17
  #import "RCTDevSupportHttpHeaders.h"
11
18
 
12
19
  @interface RCTMultipartDataTask () <NSURLSessionDataDelegate, NSURLSessionDataDelegate>
@@ -43,7 +50,15 @@
43
50
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:_url];
44
51
  [request addValue:@"multipart/mixed" forHTTPHeaderField:@"Accept"];
45
52
  [[RCTDevSupportHttpHeaders sharedInstance] applyHeadersToRequest:request];
46
- NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
53
+ NSURLRequest *finalRequest = request;
54
+ if (multipartRequestInterceptor != nil) {
55
+ NSURLRequest *intercepted = multipartRequestInterceptor(request);
56
+ if (intercepted != nil) {
57
+ finalRequest = intercepted;
58
+ }
59
+ }
60
+ NSLog(@"[RCTMultipartDataTask] %@ %@", finalRequest.HTTPMethod ?: @"GET", finalRequest.URL.absoluteString);
61
+ NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:finalRequest];
47
62
  [dataTask resume];
48
63
  [session finishTasksAndInvalidate];
49
64
  }
@@ -24,7 +24,7 @@ NSDictionary* RCTGetReactNativeVersion(void)
24
24
  RCTVersionMajor: @(0),
25
25
  RCTVersionMinor: @(85),
26
26
  RCTVersionPatch: @(0),
27
- RCTVersionPrerelease: @"rc.0",
27
+ RCTVersionPrerelease: @"rc.1",
28
28
  };
29
29
  });
30
30
  return __rnVersion;
@@ -18,6 +18,12 @@ NS_ASSUME_NONNULL_BEGIN
18
18
 
19
19
  @end
20
20
 
21
+ @class SRWebSocket;
22
+
23
+ typedef SRWebSocket * (^SRWebSocketProvider)(NSURLRequest *request);
24
+
25
+ RCT_EXTERN void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider);
26
+
21
27
  @interface RCTWebSocketModule : RCTEventEmitter
22
28
 
23
29
  // Register a custom handler for a specific websocket. The handler will be strongly held by the WebSocketModule.
@@ -34,6 +34,13 @@
34
34
 
35
35
  @end
36
36
 
37
+ static SRWebSocketProvider srWebSocketProvider;
38
+
39
+ void RCTSetCustomSRWebSocketProvider(SRWebSocketProvider provider)
40
+ {
41
+ srWebSocketProvider = provider;
42
+ }
43
+
37
44
  @implementation RCTWebSocketModule {
38
45
  NSMutableDictionary<NSNumber *, SRWebSocket *> *_sockets;
39
46
  NSMutableDictionary<NSNumber *, id<RCTWebSocketContentHandler>> *_contentHandlers;
@@ -88,7 +95,13 @@ RCT_EXPORT_METHOD(
88
95
  }];
89
96
  }
90
97
 
91
- SRWebSocket *webSocket = [[SRWebSocket alloc] initWithURLRequest:request protocols:protocols];
98
+ SRWebSocket *webSocket;
99
+ if (srWebSocketProvider != nullptr) {
100
+ webSocket = srWebSocketProvider(request);
101
+ }
102
+ if (webSocket == nil) {
103
+ webSocket = [[SRWebSocket alloc] initWithURLRequest:request protocols:protocols];
104
+ }
92
105
  [webSocket setDelegateDispatchQueue:[self methodQueue]];
93
106
  webSocket.delegate = self;
94
107
  webSocket.reactTag = @(socketID);
@@ -20,28 +20,33 @@
20
20
  #import <jsinspector-modern/InspectorFlags.h>
21
21
 
22
22
  static NSString *const kDebuggerMsgDisable = @"{ \"id\":1,\"method\":\"Debugger.disable\" }";
23
+ static const int kDefaultMetroPort = 8081;
23
24
 
24
25
  static NSString *getServerHost(NSURL *bundleURL)
25
26
  {
26
- NSNumber *port = @8081;
27
- NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
28
- if ((portStr != nullptr) && [portStr length] > 0) {
29
- port = [NSNumber numberWithInt:[portStr intValue]];
30
- }
31
- if ([bundleURL port] != nullptr) {
32
- port = [bundleURL port];
33
- }
34
27
  NSString *host = [bundleURL host];
35
28
  if (host == nullptr) {
36
29
  host = @"localhost";
37
30
  }
38
31
 
39
- // this is consistent with the Android implementation, where http:// is the
40
- // hardcoded implicit scheme for the debug server. Note, packagerURL
41
- // technically looks like it could handle schemes/protocols other than HTTP,
42
- // so rather than force HTTP, leave it be for now, in case someone is relying
43
- // on that ability when developing against iOS.
44
- return [NSString stringWithFormat:@"%@:%@", host, port];
32
+ // Use explicit port from URL if available
33
+ if ([bundleURL port] != nullptr) {
34
+ return [NSString stringWithFormat:@"%@:%@", host, [bundleURL port]];
35
+ }
36
+
37
+ // Check environment variable
38
+ NSString *portStr = [[[NSProcessInfo processInfo] environment] objectForKey:@"RCT_METRO_PORT"];
39
+ if ((portStr != nullptr) && [portStr length] > 0) {
40
+ return [NSString stringWithFormat:@"%@:%@", host, portStr];
41
+ }
42
+
43
+ // For https, omit port — the scheme implies 443
44
+ if ([[bundleURL scheme] isEqualToString:@"https"]) {
45
+ return host;
46
+ }
47
+
48
+ // Default to 8081 for local development (Metro's default port)
49
+ return [NSString stringWithFormat:@"%@:%d", host, kDefaultMetroPort];
45
50
  }
46
51
 
47
52
  static NSString *getSHA256(NSString *string)
@@ -112,13 +117,15 @@ static NSURL *getInspectorDeviceUrl(NSURL *bundleURL)
112
117
  NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
113
118
  stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
114
119
 
115
- return [NSURL
116
- URLWithString:[NSString stringWithFormat:@"http://%@/inspector/device?name=%@&app=%@&device=%@&profiling=%@",
117
- getServerHost(bundleURL),
118
- escapedDeviceName,
119
- escapedAppName,
120
- escapedInspectorDeviceId,
121
- isProfilingBuild ? @"true" : @"false"]];
120
+ NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
121
+ return
122
+ [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/inspector/device?name=%@&app=%@&device=%@&profiling=%@",
123
+ scheme,
124
+ getServerHost(bundleURL),
125
+ escapedDeviceName,
126
+ escapedAppName,
127
+ escapedInspectorDeviceId,
128
+ isProfilingBuild ? @"true" : @"false"]];
122
129
  }
123
130
 
124
131
  @implementation RCTInspectorDevServerHelper
@@ -150,7 +157,9 @@ static void sendEventToAllConnections(NSString *event)
150
157
  NSString *escapedInspectorDeviceId = [getInspectorDeviceId()
151
158
  stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
152
159
 
153
- NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/open-debugger?device=%@",
160
+ NSString *scheme = [bundleURL scheme] != nullptr ? [bundleURL scheme] : @"http";
161
+ NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@://%@/open-debugger?device=%@",
162
+ scheme,
154
163
  getServerHost(bundleURL),
155
164
  escapedInspectorDeviceId]];
156
165
  NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
@@ -1,4 +1,4 @@
1
- VERSION_NAME=0.85.0-rc.0
1
+ VERSION_NAME=0.85.0-rc.1
2
2
  react.internal.publishingGroup=com.facebook.react
3
3
  react.internal.hermesPublishingGroup=com.facebook.hermes
4
4
 
@@ -15,6 +15,6 @@ public object ReactNativeVersion {
15
15
  "major" to 0,
16
16
  "minor" to 85,
17
17
  "patch" to 0,
18
- "prerelease" to "rc.0"
18
+ "prerelease" to "rc.1"
19
19
  )
20
20
  }
@@ -22,6 +22,7 @@ import com.facebook.react.common.ReactConstants
22
22
  import com.facebook.react.module.annotations.ReactModule
23
23
  import com.facebook.react.modules.network.CustomClientBuilder
24
24
  import com.facebook.react.modules.network.ForwardingCookieHandler
25
+ import com.facebook.react.modules.network.OkHttpClientProvider
25
26
  import java.io.IOException
26
27
  import java.net.URI
27
28
  import java.net.URISyntaxException
@@ -80,7 +81,8 @@ public class WebSocketModule(context: ReactApplicationContext) :
80
81
  ) {
81
82
  val id = socketID.toInt()
82
83
  val okHttpBuilder =
83
- OkHttpClient.Builder()
84
+ OkHttpClientProvider.getOkHttpClient()
85
+ .newBuilder()
84
86
  .connectTimeout(10, TimeUnit.SECONDS)
85
87
  .writeTimeout(10, TimeUnit.SECONDS)
86
88
  .readTimeout(0, TimeUnit.MINUTES) // Disable timeouts for read
@@ -198,9 +200,6 @@ public class WebSocketModule(context: ReactApplicationContext) :
198
200
  }
199
201
  },
200
202
  )
201
-
202
- // Trigger shutdown of the dispatcher's executor so this process can exit cleanly
203
- client.dispatcher().executorService().shutdown()
204
203
  }
205
204
 
206
205
  override fun close(code: Double, reason: String?, socketID: Double) {
@@ -82,6 +82,7 @@ add_react_common_subdir(react/debug)
82
82
  add_react_common_subdir(react/featureflags)
83
83
  add_react_common_subdir(react/performance/cdpmetrics)
84
84
  add_react_common_subdir(react/performance/timeline)
85
+ add_react_common_subdir(react/renderer/animated)
85
86
  add_react_common_subdir(react/renderer/animationbackend)
86
87
  add_react_common_subdir(react/renderer/animations)
87
88
  add_react_common_subdir(react/renderer/attributedstring)
@@ -201,6 +202,7 @@ add_library(reactnative
201
202
  $<TARGET_OBJECTS:react_newarchdefaults>
202
203
  $<TARGET_OBJECTS:react_performance_cdpmetrics>
203
204
  $<TARGET_OBJECTS:react_performance_timeline>
205
+ $<TARGET_OBJECTS:react_renderer_animated>
204
206
  $<TARGET_OBJECTS:react_renderer_animationbackend>
205
207
  $<TARGET_OBJECTS:react_renderer_animations>
206
208
  $<TARGET_OBJECTS:react_renderer_attributedstring>
@@ -295,6 +297,7 @@ target_include_directories(reactnative
295
297
  $<TARGET_PROPERTY:react_newarchdefaults,INTERFACE_INCLUDE_DIRECTORIES>
296
298
  $<TARGET_PROPERTY:react_performance_cdpmetrics,INTERFACE_INCLUDE_DIRECTORIES>
297
299
  $<TARGET_PROPERTY:react_performance_timeline,INTERFACE_INCLUDE_DIRECTORIES>
300
+ $<TARGET_PROPERTY:react_renderer_animated,INTERFACE_INCLUDE_DIRECTORIES>
298
301
  $<TARGET_PROPERTY:react_renderer_animationbackend,INTERFACE_INCLUDE_DIRECTORIES>
299
302
  $<TARGET_PROPERTY:react_renderer_animations,INTERFACE_INCLUDE_DIRECTORIES>
300
303
  $<TARGET_PROPERTY:react_renderer_attributedstring,INTERFACE_INCLUDE_DIRECTORIES>
@@ -70,7 +70,10 @@
70
70
  - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:(const std::string &)name
71
71
  jsInvoker:(std::shared_ptr<facebook::react::CallInvoker>)jsInvoker
72
72
  {
73
- if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled()) {
73
+ if (facebook::react::ReactNativeFeatureFlags::cxxNativeAnimatedEnabled() &&
74
+ // initialization is moved to DefaultTurboModules when using shared animated backend
75
+ // TODO: T257053961 deprecate RCTAnimatedModuleProvider.
76
+ !facebook::react::ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
74
77
  if (name == facebook::react::AnimatedModule::kModuleName) {
75
78
  __weak RCTAnimatedModuleProvider *weakSelf = self;
76
79
  auto provider = std::make_shared<facebook::react::NativeAnimatedNodesManagerProvider>(
@@ -22,7 +22,7 @@ struct ReactNativeVersionType {
22
22
  int32_t Major = 0;
23
23
  int32_t Minor = 85;
24
24
  int32_t Patch = 0;
25
- std::string_view Prerelease = "rc.0";
25
+ std::string_view Prerelease = "rc.1";
26
26
  };
27
27
 
28
28
  constexpr ReactNativeVersionType ReactNativeVersion;
@@ -142,6 +142,12 @@ int InspectorImpl::addPage(
142
142
  pageId,
143
143
  Page{pageId, description, vm, std::move(connectFunc), capabilities});
144
144
 
145
+ for (const auto& listenerWeak : listeners_) {
146
+ if (auto listener = listenerWeak.lock()) {
147
+ listener->unstable_onHostTargetAdded();
148
+ }
149
+ }
150
+
145
151
  return pageId;
146
152
  }
147
153
 
@@ -23,6 +23,7 @@ target_link_libraries(react_nativemodule_defaults
23
23
  react_nativemodule_idlecallbacks
24
24
  react_nativemodule_intersectionobserver
25
25
  react_nativemodule_webperformance
26
+ react_renderer_animated
26
27
  )
27
28
  target_compile_reactnative_options(react_nativemodule_defaults PRIVATE)
28
29
  target_compile_options(react_nativemodule_defaults PRIVATE -Wpedantic)
@@ -13,6 +13,7 @@
13
13
  #include <react/nativemodule/intersectionobserver/NativeIntersectionObserver.h>
14
14
  #include <react/nativemodule/microtasks/NativeMicrotasks.h>
15
15
  #include <react/nativemodule/webperformance/NativePerformance.h>
16
+ #include <react/renderer/animated/AnimatedModule.h>
16
17
 
17
18
  #ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
18
19
  #include <react/nativemodule/devtoolsruntimesettings/DevToolsRuntimeSettingsModule.h>
@@ -49,6 +50,13 @@ namespace facebook::react {
49
50
  }
50
51
  }
51
52
 
53
+ if (ReactNativeFeatureFlags::cxxNativeAnimatedEnabled() &&
54
+ ReactNativeFeatureFlags::useSharedAnimatedBackend() &&
55
+ name == AnimatedModule::kModuleName) {
56
+ return std::make_shared<AnimatedModule>(
57
+ jsInvoker, std::make_shared<NativeAnimatedNodesManagerProvider>());
58
+ }
59
+
52
60
  #ifdef REACT_NATIVE_DEBUGGER_ENABLED_DEVONLY
53
61
  if (name == DevToolsRuntimeSettingsModule::kModuleName) {
54
62
  return std::make_shared<DevToolsRuntimeSettingsModule>(jsInvoker);
@@ -54,6 +54,7 @@ Pod::Spec.new do |s|
54
54
  s.dependency "React-idlecallbacksnativemodule"
55
55
  s.dependency "React-intersectionobservernativemodule"
56
56
  s.dependency "React-webperformancenativemodule"
57
+ s.dependency "React-Fabric/animated"
57
58
  add_dependency(s, "React-RCTFBReactNativeSpec")
58
59
  add_dependency(s, "React-featureflags")
59
60
  add_dependency(s, "React-featureflagsnativemodule")
@@ -45,8 +45,16 @@ std::shared_ptr<NativeAnimatedNodesManager>
45
45
  NativeAnimatedNodesManagerProvider::getOrCreate(
46
46
  jsi::Runtime& runtime,
47
47
  std::shared_ptr<CallInvoker> jsInvoker) {
48
- if (nativeAnimatedNodesManager_ == nullptr) {
49
- auto* uiManager = &UIManagerBinding::getBinding(runtime)->getUIManager();
48
+ if (nativeAnimatedNodesManager_ != nullptr) {
49
+ return nativeAnimatedNodesManager_;
50
+ }
51
+
52
+ auto* uiManager = &UIManagerBinding::getBinding(runtime)->getUIManager();
53
+
54
+ if (!ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
55
+ // === PATH 1: Legacy Backend (useSharedAnimatedBackend = false) ===
56
+ // Uses the architecture with MergedValueDispatcher and
57
+ // AnimatedMountingOverrideDelegate
50
58
 
51
59
  mergedValueDispatcher_ = std::make_unique<MergedValueDispatcher>(
52
60
  [jsInvoker](std::function<void()>&& func) {
@@ -84,78 +92,78 @@ NativeAnimatedNodesManagerProvider::getOrCreate(
84
92
  }
85
93
  };
86
94
 
87
- if (ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
88
- auto animationBackend = uiManager->unstable_getAnimationBackend().lock();
89
- react_native_assert(
90
- animationBackend != nullptr && "animationBackend is nullptr");
91
- animationBackend->registerJSInvoker(jsInvoker);
92
-
93
- nativeAnimatedNodesManager_ =
94
- std::make_shared<NativeAnimatedNodesManager>(animationBackend);
95
- } else {
96
- nativeAnimatedNodesManager_ =
97
- std::make_shared<NativeAnimatedNodesManager>(
98
- std::move(directManipulationCallback),
99
- std::move(fabricCommitCallback),
100
- std::move(resolvePlatformColor),
101
- std::move(startOnRenderCallback_),
102
- std::move(stopOnRenderCallback_),
103
- std::move(frameRateListenerCallback_));
104
-
105
- nativeAnimatedDelegate_ =
106
- std::make_shared<UIManagerNativeAnimatedDelegateImpl>(
107
- nativeAnimatedNodesManager_);
108
- }
109
-
110
- addEventEmitterListener(
111
- nativeAnimatedNodesManager_->getEventEmitterListener());
112
-
113
- uiManager->addEventListener(
114
- std::make_shared<EventListener>(
115
- [eventEmitterListenerContainerWeak =
116
- std::weak_ptr<EventEmitterListenerContainer>(
117
- eventEmitterListenerContainer_)](
118
- const RawEvent& rawEvent) {
119
- const auto& eventTarget = rawEvent.eventTarget;
120
- const auto& eventPayload = rawEvent.eventPayload;
121
- if (eventTarget && eventPayload) {
122
- if (auto eventEmitterListenerContainer =
123
- eventEmitterListenerContainerWeak.lock();
124
- eventEmitterListenerContainer != nullptr) {
125
- return eventEmitterListenerContainer->willDispatchEvent(
126
- eventTarget->getTag(), rawEvent.type, *eventPayload);
127
- }
128
- }
129
- return false;
130
- }));
95
+ nativeAnimatedNodesManager_ = std::make_shared<NativeAnimatedNodesManager>(
96
+ std::move(directManipulationCallback),
97
+ std::move(fabricCommitCallback),
98
+ std::move(resolvePlatformColor),
99
+ std::move(startOnRenderCallback_),
100
+ std::move(stopOnRenderCallback_),
101
+ std::move(frameRateListenerCallback_));
102
+
103
+ nativeAnimatedDelegate_ =
104
+ std::make_shared<UIManagerNativeAnimatedDelegateImpl>(
105
+ nativeAnimatedNodesManager_);
106
+
107
+ animatedMountingOverrideDelegate_ =
108
+ std::make_shared<AnimatedMountingOverrideDelegate>(
109
+ *nativeAnimatedNodesManager_, *scheduler);
110
+
111
+ // Register on existing surfaces
112
+ uiManager->getShadowTreeRegistry().enumerate(
113
+ [animatedMountingOverrideDelegate =
114
+ std::weak_ptr<const AnimatedMountingOverrideDelegate>(
115
+ animatedMountingOverrideDelegate_)](
116
+ const ShadowTree& shadowTree, bool& /*stop*/) {
117
+ shadowTree.getMountingCoordinator()->setMountingOverrideDelegate(
118
+ animatedMountingOverrideDelegate);
119
+ });
131
120
 
132
- uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_);
121
+ // Register on surfaces started in the future
122
+ uiManager->setOnSurfaceStartCallback(
123
+ [animatedMountingOverrideDelegate =
124
+ std::weak_ptr<const AnimatedMountingOverrideDelegate>(
125
+ animatedMountingOverrideDelegate_)](
126
+ const ShadowTree& shadowTree) {
127
+ shadowTree.getMountingCoordinator()->setMountingOverrideDelegate(
128
+ animatedMountingOverrideDelegate);
129
+ });
133
130
 
134
- if (!ReactNativeFeatureFlags::useSharedAnimatedBackend()) {
135
- animatedMountingOverrideDelegate_ =
136
- std::make_shared<AnimatedMountingOverrideDelegate>(
137
- *nativeAnimatedNodesManager_, *scheduler);
138
-
139
- // Register on existing surfaces
140
- uiManager->getShadowTreeRegistry().enumerate(
141
- [animatedMountingOverrideDelegate =
142
- std::weak_ptr<const AnimatedMountingOverrideDelegate>(
143
- animatedMountingOverrideDelegate_)](
144
- const ShadowTree& shadowTree, bool& /*stop*/) {
145
- shadowTree.getMountingCoordinator()->setMountingOverrideDelegate(
146
- animatedMountingOverrideDelegate);
147
- });
148
- // Register on surfaces started in the future
149
- uiManager->setOnSurfaceStartCallback(
150
- [animatedMountingOverrideDelegate =
151
- std::weak_ptr<const AnimatedMountingOverrideDelegate>(
152
- animatedMountingOverrideDelegate_)](
153
- const ShadowTree& shadowTree) {
154
- shadowTree.getMountingCoordinator()->setMountingOverrideDelegate(
155
- animatedMountingOverrideDelegate);
156
- });
157
- }
131
+ uiManager->setNativeAnimatedDelegate(nativeAnimatedDelegate_);
132
+ } else {
133
+ // === PATH 2: Shared AnimationBackend (useSharedAnimatedBackend = true) ===
134
+ // Uses the shared AnimationBackend from UIManager. The backend handles all
135
+ // animation commits and platform integration internally.
136
+
137
+ auto animationBackend = uiManager->unstable_getAnimationBackend().lock();
138
+ react_native_assert(
139
+ animationBackend != nullptr && "animationBackend is nullptr");
140
+ animationBackend->registerJSInvoker(jsInvoker);
141
+
142
+ nativeAnimatedNodesManager_ =
143
+ std::make_shared<NativeAnimatedNodesManager>(animationBackend);
158
144
  }
145
+
146
+ addEventEmitterListener(
147
+ nativeAnimatedNodesManager_->getEventEmitterListener());
148
+
149
+ uiManager->addEventListener(
150
+ std::make_shared<EventListener>(
151
+ [eventEmitterListenerContainerWeak =
152
+ std::weak_ptr<EventEmitterListenerContainer>(
153
+ eventEmitterListenerContainer_)](const RawEvent& rawEvent) {
154
+ const auto& eventTarget = rawEvent.eventTarget;
155
+ const auto& eventPayload = rawEvent.eventPayload;
156
+ if (eventTarget && eventPayload) {
157
+ if (auto eventEmitterListenerContainer =
158
+ eventEmitterListenerContainerWeak.lock();
159
+ eventEmitterListenerContainer != nullptr) {
160
+ return eventEmitterListenerContainer->willDispatchEvent(
161
+ eventTarget->getTag(), rawEvent.type, *eventPayload);
162
+ }
163
+ }
164
+ return false;
165
+ }));
166
+
159
167
  return nativeAnimatedNodesManager_;
160
168
  }
161
169
 
@@ -55,7 +55,9 @@ void AnimatedPropsRegistry::update(
55
55
  }
56
56
  }
57
57
 
58
- std::pair<std::unordered_set<const ShadowNodeFamily*>&, SnapshotMap&>
58
+ std::pair<
59
+ std::unordered_set<std::shared_ptr<const ShadowNodeFamily>>&,
60
+ SnapshotMap&>
59
61
  AnimatedPropsRegistry::getMap(SurfaceId surfaceId) {
60
62
  auto lock = std::lock_guard(mutex_);
61
63
  auto& [pendingMap, map, pendingFamilies, families] =
@@ -24,11 +24,11 @@ struct PropsSnapshot {
24
24
 
25
25
  struct SurfaceContext {
26
26
  std::unordered_map<Tag, std::unique_ptr<PropsSnapshot>> pendingMap, map;
27
- std::unordered_set<const ShadowNodeFamily *> pendingFamilies, families;
27
+ std::unordered_set<std::shared_ptr<const ShadowNodeFamily>> pendingFamilies, families;
28
28
  };
29
29
 
30
30
  struct SurfaceUpdates {
31
- std::unordered_set<const ShadowNodeFamily *> families;
31
+ std::unordered_set<std::shared_ptr<const ShadowNodeFamily>> families;
32
32
  std::unordered_map<Tag, AnimatedProps> propsMap;
33
33
  bool hasLayoutUpdates{false};
34
34
  };
@@ -39,7 +39,7 @@ class AnimatedPropsRegistry {
39
39
  public:
40
40
  void update(const std::unordered_map<SurfaceId, SurfaceUpdates> &surfaceUpdates);
41
41
  void clear(SurfaceId surfaceId);
42
- std::pair<std::unordered_set<const ShadowNodeFamily *> &, SnapshotMap &> getMap(SurfaceId surfaceId);
42
+ std::pair<std::unordered_set<std::shared_ptr<const ShadowNodeFamily>> &, SnapshotMap &> getMap(SurfaceId surfaceId);
43
43
 
44
44
  private:
45
45
  std::unordered_map<SurfaceId, SurfaceContext> surfaceContexts_;
@@ -71,7 +71,7 @@ void AnimationBackend::onAnimationFrame(AnimationTimestamp timestamp) {
71
71
  auto& [families, updates, hasLayoutUpdates] =
72
72
  surfaceUpdates[family->getSurfaceId()];
73
73
  hasLayoutUpdates |= mutation.hasLayoutUpdates;
74
- families.insert(family.get());
74
+ families.insert(family);
75
75
  updates[mutation.tag] = std::move(mutation.props);
76
76
  }
77
77
  }
@@ -146,7 +146,8 @@ void AnimationBackend::commitUpdates(
146
146
  const ShadowNode& shadowNode,
147
147
  const ShadowNodeFragment& fragment) {
148
148
  auto newProps = ShadowNodeFragment::propsPlaceholder();
149
- if (surfaceFamilies.contains(&shadowNode.getFamily())) {
149
+ if (surfaceFamilies.contains(
150
+ shadowNode.getFamilyShared())) {
150
151
  auto& animatedProps = updates.at(shadowNode.getTag());
151
152
  newProps = cloneProps(animatedProps, shadowNode);
152
153
  }
@@ -43,9 +43,10 @@ RootShadowNode::Unshared AnimationBackendCommitHook::shadowTreeWillCommit(
43
43
  const ShadowNodeFragment& fragment) {
44
44
  auto newProps = ShadowNodeFragment::propsPlaceholder();
45
45
  std::shared_ptr<BaseViewProps> viewProps = nullptr;
46
- if (surfaceFamilies.contains(&shadowNode.getFamily()) &&
47
- updates.contains(shadowNode.getTag())) {
48
- auto& snapshot = updates.at(shadowNode.getTag());
46
+ if (auto updatesIter = updates.find(shadowNode.getTag());
47
+ updatesIter != updates.end() &&
48
+ surfaceFamilies.contains(shadowNode.getFamilyShared())) {
49
+ auto& snapshot = updatesIter->second;
49
50
  if (!snapshot->propNames.empty() || snapshot->rawProps) {
50
51
  PropsParserContext propsParserContext{
51
52
  shadowNode.getSurfaceId(),
@@ -413,17 +413,16 @@ namespace {
413
413
 
414
414
  std::shared_ptr<ShadowNode> cloneMultipleRecursive(
415
415
  const ShadowNode& shadowNode,
416
- const std::unordered_map<const ShadowNodeFamily*, int>& childrenCount,
416
+ const std::unordered_map<Tag, int>& childrenCount,
417
417
  const std::function<std::shared_ptr<
418
418
  ShadowNode>(const ShadowNode&, const ShadowNodeFragment&)>& callback) {
419
- const auto* family = &shadowNode.getFamily();
420
419
  auto& children = shadowNode.getChildren();
421
420
  std::shared_ptr<std::vector<std::shared_ptr<const ShadowNode>>> newChildren;
422
- auto count = childrenCount.at(family);
421
+ auto count = childrenCount.at(shadowNode.getTag());
423
422
 
424
423
  for (size_t i = 0; count > 0 && i < children.size(); i++) {
425
- const auto childFamily = &children[i]->getFamily();
426
- if (childrenCount.contains(childFamily)) {
424
+ const auto childTag = children[i]->getTag();
425
+ if (childrenCount.contains(childTag)) {
427
426
  count--;
428
427
  if (!newChildren) {
429
428
  newChildren =
@@ -441,37 +440,39 @@ std::shared_ptr<ShadowNode> cloneMultipleRecursive(
441
440
  } // namespace
442
441
 
443
442
  std::shared_ptr<ShadowNode> ShadowNode::cloneMultiple(
444
- const std::unordered_set<const ShadowNodeFamily*>& familiesToUpdate,
443
+ const std::unordered_set<std::shared_ptr<const ShadowNodeFamily>>&
444
+ familiesToUpdate,
445
445
  const std::function<std::shared_ptr<ShadowNode>(
446
446
  const ShadowNode& oldShadowNode,
447
447
  const ShadowNodeFragment& fragment)>& callback) const {
448
- std::unordered_map<const ShadowNodeFamily*, int> childrenCount;
448
+ std::unordered_map<Tag, int> childrenCount;
449
449
 
450
450
  for (const auto& family : familiesToUpdate) {
451
- if (childrenCount.contains(family)) {
451
+ if (childrenCount.contains(family->getTag())) {
452
452
  continue;
453
453
  }
454
454
 
455
- childrenCount[family] = 0;
455
+ childrenCount[family->getTag()] = 0;
456
456
 
457
457
  auto ancestor = family->parent_.lock();
458
458
  while ((ancestor != nullptr) && ancestor != family_) {
459
- auto ancestorIt = childrenCount.find(ancestor.get());
459
+ auto ancestorTag = ancestor->getTag();
460
+ auto ancestorIt = childrenCount.find(ancestorTag);
460
461
  if (ancestorIt != childrenCount.end()) {
461
462
  ancestorIt->second++;
462
463
  break;
463
464
  }
464
- childrenCount[ancestor.get()] = 1;
465
+ childrenCount[ancestorTag] = 1;
465
466
 
466
467
  ancestor = ancestor->parent_.lock();
467
468
  }
468
469
 
469
470
  if (ancestor == family_) {
470
- childrenCount[ancestor.get()]++;
471
+ childrenCount[ancestor->getTag()]++;
471
472
  }
472
473
  }
473
474
 
474
- if (!childrenCount.contains(&this->getFamily())) {
475
+ if (!childrenCount.contains(getTag())) {
475
476
  return nullptr;
476
477
  }
477
478
 
@@ -109,7 +109,7 @@ class ShadowNode : public Sealable, public DebugStringConvertible, public jsi::N
109
109
  * Returns `nullptr` if the operation cannot be performed successfully.
110
110
  */
111
111
  std::shared_ptr<ShadowNode> cloneMultiple(
112
- const std::unordered_set<const ShadowNodeFamily *> &familiesToUpdate,
112
+ const std::unordered_set<std::shared_ptr<const ShadowNodeFamily>> &familiesToUpdate,
113
113
  const std::function<
114
114
  std::shared_ptr<ShadowNode>(const ShadowNode &oldShadowNode, const ShadowNodeFragment &fragment)> &callback)
115
115
  const;
@@ -316,7 +316,7 @@ TEST_F(ShadowNodeTest, handleRuntimeReferenceTransferOnClone) {
316
316
  TEST_F(ShadowNodeTest, cloneMultiple) {
317
317
  auto newProps = std::make_shared<const TestProps>();
318
318
  auto newRoot = nodeA_->cloneMultiple(
319
- {&nodeA_->getFamily(), &nodeAB_->getFamily()},
319
+ {nodeA_->getFamilyShared(), nodeAB_->getFamilyShared()},
320
320
  [&](const ShadowNode& oldShadowNode, const ShadowNodeFragment& fragment) {
321
321
  return oldShadowNode.clone({
322
322
  .props = newProps,
@@ -346,7 +346,7 @@ TEST_F(ShadowNodeTest, cloneMultiple) {
346
346
  TEST_F(ShadowNodeTest, cloneMultipleWithSingleFamily) {
347
347
  auto newProps = std::make_shared<const TestProps>();
348
348
  auto newRoot = nodeA_->cloneMultiple(
349
- {&nodeAB_->getFamily()},
349
+ {nodeAB_->getFamilyShared()},
350
350
  [&](const ShadowNode& oldShadowNode, const ShadowNodeFragment& fragment) {
351
351
  return oldShadowNode.clone({
352
352
  .props = newProps,
@@ -379,7 +379,7 @@ TEST_F(ShadowNodeTest, cloneMultipleReturnsNullptrWhenFamilyHasNoPathToRoot) {
379
379
  auto newProps = std::make_shared<const TestProps>();
380
380
  // nodeZ_ is not part of nodeA_'s tree
381
381
  auto result = nodeA_->cloneMultiple(
382
- {&nodeZ_->getFamily()},
382
+ {nodeZ_->getFamilyShared()},
383
383
  [&](const ShadowNode& oldShadowNode, const ShadowNodeFragment& fragment) {
384
384
  return oldShadowNode.clone({
385
385
  .props = newProps,
@@ -396,7 +396,7 @@ TEST_F(ShadowNodeTest, cloneMultipleWithMixOfValidAndInvalidFamilies) {
396
396
  auto newProps = std::make_shared<const TestProps>();
397
397
  // nodeAB_ is in the tree, nodeZ_ is not
398
398
  auto result = nodeA_->cloneMultiple(
399
- {&nodeAB_->getFamily(), &nodeZ_->getFamily()},
399
+ {nodeAB_->getFamilyShared(), nodeZ_->getFamilyShared()},
400
400
  [&](const ShadowNode& oldShadowNode, const ShadowNodeFragment& fragment) {
401
401
  return oldShadowNode.clone({
402
402
  .props = newProps,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native",
3
- "version": "0.85.0-rc.0",
3
+ "version": "0.85.0-rc.1",
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.85.0-rc.0",
152
+ "@react-native/jest-preset": "0.85.0-rc.1",
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.85.0-rc.0",
166
- "@react-native/codegen": "0.85.0-rc.0",
167
- "@react-native/community-cli-plugin": "0.85.0-rc.0",
168
- "@react-native/gradle-plugin": "0.85.0-rc.0",
169
- "@react-native/js-polyfills": "0.85.0-rc.0",
170
- "@react-native/normalize-colors": "0.85.0-rc.0",
171
- "@react-native/virtualized-lists": "0.85.0-rc.0",
165
+ "@react-native/assets-registry": "0.85.0-rc.1",
166
+ "@react-native/codegen": "0.85.0-rc.1",
167
+ "@react-native/community-cli-plugin": "0.85.0-rc.1",
168
+ "@react-native/gradle-plugin": "0.85.0-rc.1",
169
+ "@react-native/js-polyfills": "0.85.0-rc.1",
170
+ "@react-native/normalize-colors": "0.85.0-rc.1",
171
+ "@react-native/virtualized-lists": "0.85.0-rc.1",
172
172
  "abort-controller": "^3.0.0",
173
173
  "anser": "^1.4.9",
174
174
  "ansi-regex": "^5.0.0",