feat(react-native-host): allow opting out of React-RCTAppDelegate dependency (3/3)#4146
Draft
Saadnajmi wants to merge 3 commits intomicrosoft:mainfrom
Draft
feat(react-native-host): allow opting out of React-RCTAppDelegate dependency (3/3)#4146Saadnajmi wants to merge 3 commits intomicrosoft:mainfrom
Saadnajmi wants to merge 3 commits intomicrosoft:mainfrom
Conversation
Adds three optional lifecycle hooks to RNXHostConfig. All three are opt-in; consumers that don't implement them see no behavior change. * host:didLoadInstanceWithError: and hostWillUnloadInstance: ReactNativeHost subscribes to RCTJavaScriptDidLoad, RCTJavaScriptDidFailToLoad, and RCTBridgeWillBeInvalidated notifications and forwards to the config when the corresponding selectors are implemented. dealloc removes observers. * host:didInitializeRuntime: (Objective-C++ only) fires inside the bridgeless runtime-init lambda, after host bindings install but before the user JS bundle loads. Useful for loading pre-user JS (e.g. platform bundles) via runtime.evaluateJavaScript before the app bundle runs. Wired via an internal _RNXForwardingRCTHostDelegate passed as RCTHost's hostDelegate (was nil); retained as an ivar because RCTHost stores host delegates weakly.
…te via RNXHostConfig Add an optional `turboModuleManagerDelegate` property to `RNXHostConfig` that lets the consumer participate in TurboModule construction without replacing `RNXTurboModuleAdapter`. The adapter consults it via `respondsToSelector:` before its existing defaults; returning `Nil` / `nil` falls through to the previous behavior (`RCTCoreModulesClassProvider`, `RCTAppSetupDefaultModuleFromClass` / `[cls new]`). The shape mirrors how bridge mode lets consumers vend pre-constructed modules via `RCTBridgeDelegate.extraModulesForBridge:` -- a per-host injection point for modules that carry consumer-side state (e.g., `RCTExceptionsManager` with a custom delegate, `RCTDevSettings` with a custom data source).
…endency React-RCTAppDelegate's RCTAppSetupDefaultModuleFromClass / RCTAppSetupDefaultJsExecutorFactory helpers assume a single-host-per-app shape. Multi-host integrations want their own per-host module providers and executor factories, not a process-wide default. Add an `RNX_USE_RCT_APP_DELEGATE_HELPERS` opt-out macro that defaults to 1 (preserving existing behavior). When set to 0: - `getModuleInstanceFromClass:` returns nil, falling back to `RCTTurboModuleManager`'s default `[cls new]` allocation. Consumers vending custom-initialized modules do so via `RNXHostConfig.turboModuleManagerDelegate`'s `getModuleInstanceFromClass:`, added in the previous PR. - `jsExecutorFactoryForBridge:` returns nullptr. Bridgeless integrations (RCTHost-driven) don't need this; bridge-mode consumers wanting this adapter must either keep the default (HELPERS=1) or supply their own RCTBridgeDelegate that overrides `jsExecutorFactoryForBridge:`. Depends on the auxiliary `turboModuleManagerDelegate` PR for the custom-module path to be useful.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Depends on #4144
Depends on #4145
Adds
RNX_USE_RCT_APP_DELEGATE_HELPERS(default1, preserving current behavior). Set to0to drop the React-RCTAppDelegate / ReactAppDependencyProvider framework dependency fromRNXTurboModuleAdapter.Motivation
React-RCTAppDelegate'sRCTAppSetupDefaultModuleFromClassandRCTAppSetupDefaultJsExecutorFactoryhelpers assume a single-host-per-app shape — process-wide module providers andexecutor factories. Multi-host integrations (where each host has its own modules and lifecycle) want neither. Today the only way to use
RNXTurboModuleAdapteris to link againstReact-RCTAppDelegate even if it's actively the wrong design for the consumer.
Design
When
RNX_USE_RCT_APP_DELEGATE_HELPERS=0:getModuleInstanceFromClass:skipsRCTAppSetupDefaultModuleFromClassand returnsnil. Consumers vending custom-initialized modules do so viaRNXHostConfig.turboModuleManagerDelegate.getModuleInstanceFromClass:(added in the previous PR). Falling through tonilmakesRCTTurboModuleManageruse its default[cls new]formodules the consumer doesn't override — same behavior the manager has for unknown classes.
jsExecutorFactoryForBridge:returnsnullptr. Bridgeless integrations (RCTHost-driven) construct the JS runtime viaRCTHostJSEngineProviderand never reach this path.Bridge-mode consumers wanting this adapter must either keep
HELPERS=1or supply their ownRCTBridgeDelegate.jsExecutorFactoryForBridge:.The macro auto-defaults to
1when the React-RCTAppDelegate headers are reachable (via__has_include), so behavior is unchanged for existing consumers. Multi-host consumers#define RNX_USE_RCT_APP_DELEGATE_HELPERS 0in their build settings to opt out.Why this is useful
Without the previous PR in this stack (the auxiliary
turboModuleManagerDelegatehook), opting out of the helpers leaves the consumer with nil-returning defaults and no escape hatch —pointless. With the auxiliary delegate in place, consumers have a real alternative: implement
getModuleInstanceFromClass:themselves to vend whatever modules they need, andRNX_USE_RCT_APP_DELEGATE_HELPERS=0drops the framework dependency cleanly.Test plan
Tested internally