Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the Fabric Interop layer work in Bridgeless #40732

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions packages/react-native/React/Base/RCTBridgeProxy.mm
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ - (RCTUIManager *)uiManager
return (RCTUIManager *)_uiManagerProxy;
}

- (RCTBridgeProxy *)object
{
return self;
}

/**
* NSProxy setup
*/
Expand Down Expand Up @@ -387,12 +392,14 @@ - (void)logError:(NSString *)message cmd:(SEL)cmd

@implementation RCTUIManagerProxy {
RCTViewRegistry *_viewRegistry;
NSMutableDictionary<NSNumber *, UIView *> *_legacyViewRegistry;
}
- (instancetype)initWithViewRegistry:(RCTViewRegistry *)viewRegistry
{
self = [super self];
if (self) {
_viewRegistry = viewRegistry;
_legacyViewRegistry = [NSMutableDictionary new];
}
return self;
}
Expand All @@ -404,20 +411,21 @@ - (UIView *)viewForReactTag:(NSNumber *)reactTag
{
[self logWarning:@"Please migrate to RCTViewRegistry: @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED."
cmd:_cmd];
return [_viewRegistry viewForReactTag:reactTag];
return [_viewRegistry viewForReactTag:reactTag] ? [_viewRegistry viewForReactTag:reactTag]
: [_legacyViewRegistry objectForKey:reactTag];
}

- (void)addUIBlock:(RCTViewManagerUIBlock)block
{
[self
logWarning:
@"This method isn't implemented faithfully: the viewRegistry passed to RCTViewManagerUIBlock is nil. Please migrate to RCTViewRegistry: @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED."
@"This method isn't implemented faithfully. Please migrate to RCTViewRegistry if possible: @synthesize viewRegistry_DEPRECATED = _viewRegistry_DEPRECATED."
cmd:_cmd];
__weak __typeof(self) weakSelf = self;
RCTExecuteOnMainQueue(^{
__typeof(self) strongSelf = weakSelf;
if (strongSelf) {
block((RCTUIManager *)strongSelf, nil);
block((RCTUIManager *)strongSelf, strongSelf->_legacyViewRegistry);
}
});
}
Expand Down
7 changes: 7 additions & 0 deletions packages/react-native/React/Modules/RCTUIManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

#import <React/RCTBridge.h>
#import <React/RCTBridgeModule.h>
#import <React/RCTBridgeProxy.h>
#import <React/RCTInvalidating.h>
#import <React/RCTRootView.h>
#import <React/RCTViewManager.h>
Expand Down Expand Up @@ -173,6 +174,12 @@ RCT_EXTERN NSString *const RCTUIManagerWillUpdateViewsDueToContentSizeMultiplier

@end

@interface RCTBridgeProxy (RCTUIManager)

@property (nonatomic, readonly) RCTUIManager *uiManager;

@end

RCT_EXTERN NSMutableDictionary<NSString *, id> *RCTModuleConstantsForDestructuredComponent(
NSMutableDictionary<NSString *, NSDictionary *> *directEvents,
NSMutableDictionary<NSString *, NSDictionary *> *bubblingEvents,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/React/Views/RCTComponentData.m
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ - (RCTViewManager *)manager
object:nil
userInfo:@{@"module" : _bridgelessViewManager}];
}
return _manager ?: _bridgelessViewManager;
return _manager ? _manager : _bridgelessViewManager;
}

RCT_NOT_IMPLEMENTED(-(instancetype)init)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "LegacyViewManagerInteropComponentDescriptor.h"
#include <React/RCTBridge.h>
#include <React/RCTBridgeModuleDecorator.h>
#include <React/RCTBridgeProxy.h>
#include <React/RCTComponentData.h>
#include <React/RCTEventDispatcher.h>
#include <React/RCTModuleData.h>
Expand Down Expand Up @@ -86,6 +87,12 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
bridge = unwrapManagedObjectWeakly(optionalBridge.value());
}

RCTBridgeProxy *bridgeProxy;
auto optionalBridgeProxy = contextContainer->find<std::shared_ptr<void>>("RCTBridgeProxy");
if (optionalBridgeProxy) {
bridgeProxy = unwrapManagedObjectWeakly(optionalBridgeProxy.value());
}

auto optionalEventDispatcher = contextContainer->find<std::shared_ptr<void>>("RCTEventDispatcher");
RCTEventDispatcher *eventDispatcher;
if (optionalEventDispatcher) {
Expand All @@ -104,6 +111,7 @@ static Class getViewManagerFromComponentName(const std::string &componentName)
return wrapManagedObject([[RCTLegacyViewManagerInteropCoordinator alloc]
initWithComponentData:componentData
bridge:bridge
bridgeProxy:bridgeProxy
bridgelessInteropData:bridgeModuleDecorator]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ NS_ASSUME_NONNULL_BEGIN

@class RCTComponentData;
@class RCTBridge;
@class RCTBridgeProxy;

typedef void (^InterceptorBlock)(std::string eventName, folly::dynamic event);

@interface RCTLegacyViewManagerInteropCoordinator : NSObject

- (instancetype)initWithComponentData:(RCTComponentData *)componentData
bridge:(RCTBridge *)bridge
bridge:(nullable RCTBridge *)bridge
bridgeProxy:(nullable RCTBridgeProxy *)bridgeProxy
bridgelessInteropData:(RCTBridgeModuleDecorator *)bridgelessInteropData;

- (UIView *)createPaperViewWithTag:(NSInteger)tag;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "RCTLegacyViewManagerInteropCoordinator.h"
#include <React/RCTBridge+Private.h>
#include <React/RCTBridgeMethod.h>
#include <React/RCTBridgeProxy.h>
#include <React/RCTComponentData.h>
#include <React/RCTEventDispatcherProtocol.h>
#include <React/RCTFollyConvert.h>
Expand All @@ -16,6 +17,7 @@
#include <React/RCTUIManager.h>
#include <React/RCTUIManagerUtils.h>
#include <React/RCTUtils.h>
#include <React/RCTViewManager.h>
#include <folly/json.h>
#include <objc/runtime.h>

Expand All @@ -25,6 +27,8 @@ @implementation RCTLegacyViewManagerInteropCoordinator {
RCTComponentData *_componentData;
__weak RCTBridge *_bridge;
__weak RCTBridgeModuleDecorator *_bridgelessInteropData;
__weak RCTBridgeProxy *_bridgeProxy;

/*
Each instance of `RCTLegacyViewManagerInteropComponentView` registers a block to which events are dispatched.
This is the container that maps unretained UIView pointer to a block to which the event is dispatched.
Expand All @@ -40,13 +44,16 @@ @implementation RCTLegacyViewManagerInteropCoordinator {
}

- (instancetype)initWithComponentData:(RCTComponentData *)componentData
bridge:(RCTBridge *)bridge
bridge:(nullable RCTBridge *)bridge
bridgeProxy:(nullable RCTBridgeProxy *)bridgeProxy
bridgelessInteropData:(RCTBridgeModuleDecorator *)bridgelessInteropData;
{
if (self = [super init]) {
_componentData = componentData;
_bridge = bridge;
_bridgelessInteropData = bridgelessInteropData;
_bridgeProxy = bridgeProxy;

if (bridgelessInteropData) {
// During bridge mode, RCTBridgeModules will be decorated with these APIs by the bridge.
RCTAssert(
Expand All @@ -62,7 +69,9 @@ - (instancetype)initWithComponentData:(RCTComponentData *)componentData
if (strongSelf) {
InterceptorBlock block = [strongSelf->_eventInterceptors objectForKey:reactTag];
if (block) {
block(std::string([RCTNormalizeInputEventName(eventName) UTF8String]), convertIdToFollyDynamic(event ?: @{}));
block(
std::string([RCTNormalizeInputEventName(eventName) UTF8String]),
convertIdToFollyDynamic(event ? event : @{}));
}
}
};
Expand Down Expand Up @@ -131,15 +140,9 @@ - (void)handleCommand:(NSString *)commandName
NSArray *newArgs = [@[ [NSNumber numberWithInteger:tag] ] arrayByAddingObjectsFromArray:args];

if (_bridge) {
[_bridge.batchedBridge
dispatchBlock:^{
[method invokeWithBridge:self->_bridge module:self->_componentData.manager arguments:newArgs];
[self->_bridge.uiManager setNeedsLayout];
}
queue:RCTGetUIManagerQueue()];
[self _handleCommandsOnBridge:method withArgs:newArgs];
} else {
// TODO T86826778 - Figure out which queue this should be dispatched to.
[method invokeWithBridge:nil module:self->_componentData.manager arguments:newArgs];
[self _handleCommandsOnBridgeless:method withArgs:newArgs];
}
}

Expand Down Expand Up @@ -169,8 +172,37 @@ - (void)removeViewFromRegistryWithTag:(NSInteger)tag
}

#pragma mark - Private
- (void)_handleCommandsOnBridge:(id<RCTBridgeMethod>)method withArgs:(NSArray *)newArgs
{
[_bridge.batchedBridge
dispatchBlock:^{
[method invokeWithBridge:self->_bridge module:self->_componentData.manager arguments:newArgs];
[self->_bridge.uiManager setNeedsLayout];
}
queue:RCTGetUIManagerQueue()];
}

- (void)_handleCommandsOnBridgeless:(id<RCTBridgeMethod>)method withArgs:(NSArray *)newArgs
{
RCTViewManager *componentViewManager = self->_componentData.manager;
[componentViewManager setValue:_bridgeProxy forKey:@"bridge"];

[self->_bridgeProxy.uiManager
addUIBlock:^(RCTUIManager *uiManager, NSDictionary<NSNumber *, UIView *> *viewRegistry) {
[method invokeWithBridge:nil module:componentViewManager arguments:newArgs];
}];
}

- (void)_addUIBlock:(RCTViewManagerUIBlock)block
{
if (_bridge) {
[self _addUIBlockOnBridge:block];
} else {
[self->_bridgeProxy.uiManager addUIBlock:block];
}
}

- (void)_addUIBlockOnBridge:(RCTViewManagerUIBlock)block
{
__weak __typeof__(self) weakSelf = self;
[_bridge.batchedBridge
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -227,24 +227,23 @@ - (void)_start
RuntimeExecutor bufferedRuntimeExecutor = _reactInstance->getBufferedRuntimeExecutor();
timerManager->setRuntimeExecutor(bufferedRuntimeExecutor);

RCTBridgeProxy *bridgeProxy = RCTTurboModuleInteropEnabled() && RCTTurboModuleInteropBridgeProxyEnabled()
? [[RCTBridgeProxy alloc] initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED
moduleRegistry:_bridgeModuleDecorator.moduleRegistry
bundleManager:_bridgeModuleDecorator.bundleManager
callableJSModules:_bridgeModuleDecorator.callableJSModules
dispatchToJSThread:^(dispatch_block_t block) {
__strong __typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf->_valid) {
strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); });
}
RCTBridgeProxy *bridgeProxy =
[[RCTBridgeProxy alloc] initWithViewRegistry:_bridgeModuleDecorator.viewRegistry_DEPRECATED
moduleRegistry:_bridgeModuleDecorator.moduleRegistry
bundleManager:_bridgeModuleDecorator.bundleManager
callableJSModules:_bridgeModuleDecorator.callableJSModules
dispatchToJSThread:^(dispatch_block_t block) {
__strong __typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf->_valid) {
strongSelf->_reactInstance->getBufferedRuntimeExecutor()([=](jsi::Runtime &runtime) { block(); });
}
registerSegmentWithId:^(NSNumber *segmentId, NSString *path) {
__strong __typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf->_valid) {
[strongSelf registerSegmentWithId:segmentId path:path];
}
}]
: nil;
}
registerSegmentWithId:^(NSNumber *segmentId, NSString *path) {
__strong __typeof(self) strongSelf = weakSelf;
if (strongSelf && strongSelf->_valid) {
[strongSelf registerSegmentWithId:segmentId path:path];
}
}];

// Set up TurboModules
_turboModuleManager = [[RCTTurboModuleManager alloc]
Expand All @@ -269,6 +268,7 @@ - (void)_start
facebook::react::wrapManagedObject([_turboModuleManager moduleForName:"RCTEventDispatcher"]));
contextContainer->insert("RCTBridgeModuleDecorator", facebook::react::wrapManagedObject(_bridgeModuleDecorator));
contextContainer->insert("RuntimeScheduler", std::weak_ptr<RuntimeScheduler>(_reactInstance->getRuntimeScheduler()));
contextContainer->insert("RCTBridgeProxy", facebook::react::wrapManagedObject(bridgeProxy));

_surfacePresenter = [[RCTSurfacePresenter alloc]
initWithContextContainer:contextContainer
Expand Down