From 09b9422516bd2dc29e130c1e3f44611ae11f9eb2 Mon Sep 17 00:00:00 2001 From: Joshua Gross Date: Wed, 28 Jul 2021 20:16:53 -0700 Subject: [PATCH] Pass context through to all prop parser (core changes) Summary: Unfortunately, parsing some props requires stateful context - namely, PlatformColor on Android. We explored several different options but they all seemed inferior to the approach of using ContextContainer, and most would require using global state. By introducing this change everywhere as early as possible, we can avoid later pain. It is likely that some prop, on some platform, will require this mechanism. We'll be ready for it! Because we can pass a constref of the ContextContainer through to all props and because the context and context data is never retained by prop parsers, perf and memory hit should be ~0. This diff contains core changes only. Leaf changes to all props structs and conversions files will be in next diff(s). Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D29838789 fbshipit-source-id: f5090e7f02eb6e8fbe0ef4dd201e7d12104a3e3c --- .../com/facebook/react/fabric/jni/Binding.cpp | 2 ++ .../fabric/jni/CoreComponentsRegistry.cpp | 7 +++-- .../LayoutAnimationKeyFrameManager.cpp | 30 +++++++++++++++---- .../ComponentDescriptorProviderRegistry.cpp | 7 +++-- .../ComponentDescriptorProviderRegistry.h | 4 ++- .../ComponentDescriptorRegistry.cpp | 14 ++++++--- .../ComponentDescriptorRegistry.h | 5 +++- .../react/renderer/mounting/ShadowTree.cpp | 8 +++-- .../react/renderer/mounting/ShadowTree.h | 4 ++- .../react/renderer/runtimescheduler/BUCK | 1 + .../RuntimeSchedulerBinding.cpp | 1 + .../runtimescheduler/SchedulerPriority.h | 1 + .../react/renderer/scheduler/Scheduler.cpp | 18 +++++++---- .../react/renderer/scheduler/Scheduler.h | 9 ++++++ .../renderer/scheduler/SurfaceHandler.cpp | 24 ++++++++++++--- .../react/renderer/scheduler/SurfaceHandler.h | 8 +++++ .../renderer/scheduler/SurfaceManager.cpp | 1 + .../react/renderer/uimanager/UIManager.cpp | 19 +++++++++--- .../react/renderer/uimanager/UIManager.h | 5 +++- 19 files changed, 133 insertions(+), 35 deletions(-) diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp index f8419c8dacf..843a110d56f 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/Binding.cpp @@ -275,6 +275,7 @@ void Binding::startSurface( layoutContext.pointScaleFactor = pointScaleFactor_; auto surfaceHandler = SurfaceHandler{moduleName->toStdString(), surfaceId}; + surfaceHandler.setContextContainer(scheduler->getContextContainer()); surfaceHandler.setProps(initialProps->consume()); surfaceHandler.constraintLayout({}, layoutContext); @@ -336,6 +337,7 @@ void Binding::startSurfaceWithConstraints( isRTL ? LayoutDirection::RightToLeft : LayoutDirection::LeftToRight; auto surfaceHandler = SurfaceHandler{moduleName->toStdString(), surfaceId}; + surfaceHandler.setContextContainer(scheduler_->getContextContainer()); surfaceHandler.setProps(initialProps->consume()); surfaceHandler.constraintLayout(constraints, context); diff --git a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/CoreComponentsRegistry.cpp b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/CoreComponentsRegistry.cpp index f92c84d625c..477c819b58b 100644 --- a/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/CoreComponentsRegistry.cpp +++ b/ReactAndroid/src/main/java/com/facebook/react/fabric/jni/CoreComponentsRegistry.cpp @@ -87,9 +87,10 @@ CoreComponentsRegistry::initHybrid( [](EventDispatcher::Weak const &eventDispatcher, ContextContainer::Shared const &contextContainer) -> ComponentDescriptorRegistry::Shared { - auto registry = CoreComponentsRegistry::sharedProviderRegistry() - ->createComponentDescriptorRegistry( - {eventDispatcher, contextContainer}); + auto registry = + CoreComponentsRegistry::sharedProviderRegistry() + ->createComponentDescriptorRegistry( + {eventDispatcher, contextContainer}, contextContainer); auto mutableRegistry = std::const_pointer_cast(registry); mutableRegistry->setFallbackComponentDescriptor( diff --git a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp index 46ccd76eabe..ecf5c3568d5 100644 --- a/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp +++ b/ReactCommon/react/renderer/animations/LayoutAnimationKeyFrameManager.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -828,6 +829,15 @@ LayoutAnimationKeyFrameManager::pullTransaction( LOG(ERROR) << "BEGINNING DONE DISPLAYING ONGOING inflightAnimations_!"; #endif + // Stub PropsParserContext used for cloneProps. + // This is/should be safe because cloning doesn't actually need to + // parse props, and just copies them; therefore there should be no + // need to actually use anything in the PropsParserContext. + // If this ever changes, the LayoutAnimations API will need to change + // to pass in a real PropsParserContext. + ContextContainer contextContainer{}; + PropsParserContext propsParserContext{surfaceId, contextContainer}; + // What to do if we detect a conflict? Get current value and make // that the baseline of the next animation. Scale the remaining time // in the animation @@ -1082,7 +1092,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) - .cloneProps(viewStart.props, {}); + .cloneProps(propsParserContext, viewStart.props, {}); // Dynamic cast, because - we don't know the type of this // ShadowNode, it could be Image or Text or something else with @@ -1107,7 +1117,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( if ((isScaleX || isScaleY) && haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) - .cloneProps(viewStart.props, {}); + .cloneProps(propsParserContext, viewStart.props, {}); // Dynamic cast, because - we don't know the type of this // ShadowNode, it could be Image or Text or something else with @@ -1210,7 +1220,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) - .cloneProps(viewFinal.props, {}); + .cloneProps(propsParserContext, viewFinal.props, {}); // Dynamic cast, because - we don't know the type of this // ShadowNode, it could be Image or Text or something else with @@ -1237,7 +1247,7 @@ LayoutAnimationKeyFrameManager::pullTransaction( if ((isScaleX || isScaleY) && haveComponentDescriptor) { auto props = getComponentDescriptorForShadowView(baselineShadowView) - .cloneProps(viewFinal.props, {}); + .cloneProps(propsParserContext, viewFinal.props, {}); // Dynamic cast, because - we don't know the type of this // ShadowNode, it could be Image or Text or something else with @@ -1721,6 +1731,16 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( react_native_assert(false); return finalView; } + + // Stub PropsParserContext used for interpolateProps. + // This is/should be safe because interpolating doesn't actually need to + // parse props, and just copies them; therefore there should be no + // need to actually use anything in the PropsParserContext. + // If this ever changes, the LayoutAnimations API will need to change + // to pass in a real PropsParserContext. + ContextContainer contextContainer{}; + PropsParserContext propsParserContext{-1, contextContainer}; + ComponentDescriptor const &componentDescriptor = getComponentDescriptorForShadowView(startingView); @@ -1742,7 +1762,7 @@ ShadowView LayoutAnimationKeyFrameManager::createInterpolatedShadowView( // Animate opacity or scale/transform mutatedShadowView.props = componentDescriptor.interpolateProps( - progress, startingView.props, finalView.props); + propsParserContext, progress, startingView.props, finalView.props); react_native_assert(mutatedShadowView.props != nullptr); if (mutatedShadowView.props == nullptr) { return finalView; diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp index 4255db72157..3ffb39e493a 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.cpp @@ -65,11 +65,12 @@ void ComponentDescriptorProviderRegistry::request( ComponentDescriptorRegistry::Shared ComponentDescriptorProviderRegistry::createComponentDescriptorRegistry( - ComponentDescriptorParameters const ¶meters) const { + ComponentDescriptorParameters const ¶meters, + ContextContainer::Shared contextContainer) const { std::shared_lock lock(mutex_); - auto registry = - std::make_shared(parameters, *this); + auto registry = std::make_shared( + parameters, *this, contextContainer); for (auto const &pair : componentDescriptorProviders_) { registry->add(pair.second); diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h index 769f0f3b91c..25c3ed8c5cf 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorProviderRegistry.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace facebook { namespace react { @@ -51,7 +52,8 @@ class ComponentDescriptorProviderRegistry final { * The methods can be called on any thread. */ ComponentDescriptorRegistry::Shared createComponentDescriptorRegistry( - ComponentDescriptorParameters const ¶meters) const; + ComponentDescriptorParameters const ¶meters, + ContextContainer::Shared contextContainer) const; private: friend class ComponentDescriptorRegistry; diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp index bfbc34fc512..137fb20cbbf 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.cpp @@ -11,6 +11,7 @@ #include #include +#include #include namespace facebook { @@ -18,8 +19,11 @@ namespace react { ComponentDescriptorRegistry::ComponentDescriptorRegistry( ComponentDescriptorParameters const ¶meters, - ComponentDescriptorProviderRegistry const &providerRegistry) - : parameters_(parameters), providerRegistry_(providerRegistry) {} + ComponentDescriptorProviderRegistry const &providerRegistry, + ContextContainer::Shared contextContainer) + : parameters_(parameters), + providerRegistry_(providerRegistry), + contextContainer_(contextContainer) {} void ComponentDescriptorRegistry::add( ComponentDescriptorProvider componentDescriptorProvider) const { @@ -132,8 +136,10 @@ SharedShadowNode ComponentDescriptorRegistry::createNode( auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr}; auto family = componentDescriptor.createFamily(fragment, std::move(eventTarget)); - auto const props = - componentDescriptor.cloneProps(nullptr, RawProps(propsDynamic)); + auto const props = componentDescriptor.cloneProps( + PropsParserContext{surfaceId, *contextContainer_.get()}, + nullptr, + RawProps(propsDynamic)); auto const state = componentDescriptor.createInitialState(ShadowNodeFragment{props}, family); diff --git a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h index 29dac6f371e..e23d41c1461 100644 --- a/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h +++ b/ReactCommon/react/renderer/componentregistry/ComponentDescriptorRegistry.h @@ -14,6 +14,7 @@ #include #include +#include namespace facebook { namespace react { @@ -37,7 +38,8 @@ class ComponentDescriptorRegistry { */ ComponentDescriptorRegistry( ComponentDescriptorParameters const ¶meters, - ComponentDescriptorProviderRegistry const &providerRegistry); + ComponentDescriptorProviderRegistry const &providerRegistry, + ContextContainer::Shared contextContainer); /* * This is broken. Please do not use. @@ -85,6 +87,7 @@ class ComponentDescriptorRegistry { ComponentDescriptor::Shared _fallbackComponentDescriptor; ComponentDescriptorParameters parameters_{}; ComponentDescriptorProviderRegistry const &providerRegistry_; + ContextContainer::Shared contextContainer_; }; } // namespace react diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.cpp b/ReactCommon/react/renderer/mounting/ShadowTree.cpp index 2ed6f90cd21..1d3c6fe8dce 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.cpp +++ b/ReactCommon/react/renderer/mounting/ShadowTree.cpp @@ -223,7 +223,8 @@ ShadowTree::ShadowTree( SurfaceId surfaceId, LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext, - ShadowTreeDelegate const &delegate) + ShadowTreeDelegate const &delegate, + ContextContainer const &contextContainer) : surfaceId_(surfaceId), delegate_(delegate) { const auto noopEventEmitter = std::make_shared( nullptr, -1, std::shared_ptr()); @@ -234,7 +235,10 @@ ShadowTree::ShadowTree( EventDispatcher::Shared{}, nullptr, nullptr}); const auto props = std::make_shared( - *RootShadowNode::defaultSharedProps(), layoutConstraints, layoutContext); + PropsParserContext{surfaceId, contextContainer}, + *RootShadowNode::defaultSharedProps(), + layoutConstraints, + layoutContext); auto const fragment = ShadowNodeFamilyFragment{surfaceId, surfaceId, noopEventEmitter}; diff --git a/ReactCommon/react/renderer/mounting/ShadowTree.h b/ReactCommon/react/renderer/mounting/ShadowTree.h index 2a8f1d1fadd..2553fdc3d31 100644 --- a/ReactCommon/react/renderer/mounting/ShadowTree.h +++ b/ReactCommon/react/renderer/mounting/ShadowTree.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "MountingOverrideDelegate.h" namespace facebook { @@ -70,7 +71,8 @@ class ShadowTree final { SurfaceId surfaceId, LayoutConstraints const &layoutConstraints, LayoutContext const &layoutContext, - ShadowTreeDelegate const &delegate); + ShadowTreeDelegate const &delegate, + ContextContainer const &contextContainer); ~ShadowTree(); diff --git a/ReactCommon/react/renderer/runtimescheduler/BUCK b/ReactCommon/react/renderer/runtimescheduler/BUCK index 83037289820..7cdf02a7637 100644 --- a/ReactCommon/react/renderer/runtimescheduler/BUCK +++ b/ReactCommon/react/renderer/runtimescheduler/BUCK @@ -50,6 +50,7 @@ rn_xplat_cxx_library( tests = [":tests"], visibility = ["PUBLIC"], deps = [ + react_native_xplat_target("react/renderer/core:core"), react_native_xplat_target("runtimeexecutor:runtimeexecutor"), react_native_xplat_target("react/renderer/debug:debug"), react_native_xplat_target("better:better"), diff --git a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp index 4d5a19f8bb5..05a3d3395a4 100644 --- a/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp +++ b/ReactCommon/react/renderer/runtimescheduler/RuntimeSchedulerBinding.cpp @@ -10,6 +10,7 @@ #include "primitives.h" #include +#include #include #include diff --git a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h index 807865a67f9..4b5a1b7eab2 100644 --- a/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h +++ b/ReactCommon/react/renderer/runtimescheduler/SchedulerPriority.h @@ -8,6 +8,7 @@ #pragma once #include +#include #include namespace facebook::react { diff --git a/ReactCommon/react/renderer/scheduler/Scheduler.cpp b/ReactCommon/react/renderer/scheduler/Scheduler.cpp index ca44478f6d8..ef3166c0efa 100644 --- a/ReactCommon/react/renderer/scheduler/Scheduler.cpp +++ b/ReactCommon/react/renderer/scheduler/Scheduler.cpp @@ -36,17 +36,18 @@ Scheduler::Scheduler( UIManagerAnimationDelegate *animationDelegate, SchedulerDelegate *delegate) { runtimeExecutor_ = schedulerToolbox.runtimeExecutor; + contextContainer_ = schedulerToolbox.contextContainer; reactNativeConfig_ = - schedulerToolbox.contextContainer - ->at>("ReactNativeConfig"); + contextContainer_->at>( + "ReactNativeConfig"); // Creating a container for future `EventDispatcher` instance. eventDispatcher_ = std::make_shared>(); auto uiManager = std::make_shared( - runtimeExecutor_, schedulerToolbox.backgroundExecutor); + runtimeExecutor_, schedulerToolbox.backgroundExecutor, contextContainer_); auto eventOwnerBox = std::make_shared(); eventOwnerBox->owner = eventDispatcher_; @@ -90,7 +91,7 @@ Scheduler::Scheduler( EventDispatcher::Shared{eventDispatcher_, &eventDispatcher_->value()}; componentDescriptorRegistry_ = schedulerToolbox.componentRegistryFactory( - eventDispatcher, schedulerToolbox.contextContainer); + eventDispatcher, contextContainer_); uiManager->setDelegate(this); uiManager->setComponentDescriptorRegistry(componentDescriptorRegistry_); @@ -104,8 +105,8 @@ Scheduler::Scheduler( auto componentDescriptorRegistryKey = "ComponentDescriptorRegistry_DO_NOT_USE_PRETTY_PLEASE"; - schedulerToolbox.contextContainer->erase(componentDescriptorRegistryKey); - schedulerToolbox.contextContainer->insert( + contextContainer_->erase(componentDescriptorRegistryKey); + contextContainer_->insert( componentDescriptorRegistryKey, std::weak_ptr( componentDescriptorRegistry_)); @@ -193,6 +194,7 @@ Scheduler::~Scheduler() { void Scheduler::registerSurface( SurfaceHandler const &surfaceHandler) const noexcept { + surfaceHandler.setContextContainer(getContextContainer()); surfaceHandler.setUIManager(uiManager_.get()); } @@ -352,5 +354,9 @@ void Scheduler::uiManagerDidSetIsJSResponder( } } +ContextContainer::Shared Scheduler::getContextContainer() const { + return contextContainer_; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/react/renderer/scheduler/Scheduler.h b/ReactCommon/react/renderer/scheduler/Scheduler.h index 470890137b9..e604c4adaca 100644 --- a/ReactCommon/react/renderer/scheduler/Scheduler.h +++ b/ReactCommon/react/renderer/scheduler/Scheduler.h @@ -104,6 +104,9 @@ class Scheduler final : public UIManagerDelegate { bool isJSResponder, bool blockNativeResponder) override; +#pragma mark - ContextContainer + ContextContainer::Shared getContextContainer() const; + private: friend class SurfaceHandler; @@ -124,6 +127,12 @@ class Scheduler final : public UIManagerDelegate { */ std::shared_ptr> eventDispatcher_; + /** + * Hold onto ContextContainer. See SchedulerToolbox. + * Must not be nullptr. + */ + ContextContainer::Shared contextContainer_; + /* * Temporary flags. */ diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp index a1a134cfacb..9e366968033 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.cpp @@ -43,11 +43,17 @@ SurfaceHandler &SurfaceHandler::operator=(SurfaceHandler &&other) noexcept { other.link_ = Link{}; other.parameters_ = Parameters{}; + other.parameters_.contextContainer = parameters_.contextContainer; return *this; } #pragma mark - Surface Life-Cycle Management +void SurfaceHandler::setContextContainer( + ContextContainer::Shared contextContainer) const noexcept { + parameters_.contextContainer = contextContainer; +} + Status SurfaceHandler::getStatus() const noexcept { std::shared_lock lock(linkMutex_); return link_.status; @@ -61,6 +67,8 @@ void SurfaceHandler::start() const noexcept { react_native_assert( getLayoutConstraints().layoutDirection != LayoutDirection::Undefined && "layoutDirection must be set."); + react_native_assert( + parameters_.contextContainer && "ContextContainer must be set."); auto parameters = Parameters{}; { @@ -73,7 +81,8 @@ void SurfaceHandler::start() const noexcept { parameters.surfaceId, parameters.layoutConstraints, parameters.layoutContext, - *link_.uiManager); + *link_.uiManager, + *parameters.contextContainer); link_.shadowTree = shadowTree.get(); @@ -194,8 +203,11 @@ Size SurfaceHandler::measure( auto currentRootShadowNode = link_.shadowTree->getCurrentRevision().rootShadowNode; - auto rootShadowNode = - currentRootShadowNode->clone(layoutConstraints, layoutContext); + PropsParserContext propsParserContext{ + parameters_.surfaceId, *parameters_.contextContainer.get()}; + + auto rootShadowNode = currentRootShadowNode->clone( + propsParserContext, layoutConstraints, layoutContext); rootShadowNode->layoutIfNeeded(); return rootShadowNode->getLayoutMetrics().frame.size; } @@ -223,10 +235,14 @@ void SurfaceHandler::constraintLayout( return; } + PropsParserContext propsParserContext{ + parameters_.surfaceId, *parameters_.contextContainer.get()}; + react_native_assert( link_.shadowTree && "`link_.shadowTree` must not be null."); link_.shadowTree->commit([&](RootShadowNode const &oldRootShadowNode) { - return oldRootShadowNode.clone(layoutConstraints, layoutContext); + return oldRootShadowNode.clone( + propsParserContext, layoutConstraints, layoutContext); }); } } diff --git a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h index b564f5ebac1..a606167c370 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceHandler.h +++ b/ReactCommon/react/renderer/scheduler/SurfaceHandler.h @@ -12,6 +12,7 @@ #include #include #include +#include namespace facebook { namespace react { @@ -73,6 +74,12 @@ class SurfaceHandler final { #pragma mark - Surface Life-Cycle Management + /* + * Must be called before surface is started. + */ + void setContextContainer( + ContextContainer::Shared contextContainer) const noexcept; + /* * Returns a momentum value of the status. */ @@ -171,6 +178,7 @@ class SurfaceHandler final { folly::dynamic props{}; LayoutConstraints layoutConstraints{}; LayoutContext layoutContext{}; + ContextContainer::Shared contextContainer{}; }; /* diff --git a/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp index 2cd0c6ed27a..a6f8a537f92 100644 --- a/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp +++ b/ReactCommon/react/renderer/scheduler/SurfaceManager.cpp @@ -24,6 +24,7 @@ void SurfaceManager::startSurface( { std::unique_lock lock(mutex_); auto surfaceHandler = SurfaceHandler{moduleName, surfaceId}; + surfaceHandler.setContextContainer(scheduler_.getContextContainer()); registry_.emplace(surfaceId, std::move(surfaceHandler)); } diff --git a/ReactCommon/react/renderer/uimanager/UIManager.cpp b/ReactCommon/react/renderer/uimanager/UIManager.cpp index ea5e77036a0..56bb2bad80a 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.cpp +++ b/ReactCommon/react/renderer/uimanager/UIManager.cpp @@ -8,6 +8,7 @@ #include "UIManager.h" #include +#include #include #include #include @@ -29,9 +30,11 @@ static std::unique_ptr constructLeakCheckerIfNeeded( UIManager::UIManager( RuntimeExecutor const &runtimeExecutor, - BackgroundExecutor const &backgroundExecutor) + BackgroundExecutor const &backgroundExecutor, + ContextContainer::Shared contextContainer) : runtimeExecutor_(runtimeExecutor), backgroundExecutor_(backgroundExecutor), + contextContainer_(contextContainer), leakChecker_(constructLeakCheckerIfNeeded(runtimeExecutor)) {} UIManager::~UIManager() { @@ -51,10 +54,13 @@ SharedShadowNode UIManager::createNode( auto fallbackDescriptor = componentDescriptorRegistry_->getFallbackComponentDescriptor(); + PropsParserContext propsParserContext{surfaceId, *contextContainer_.get()}; + auto const fragment = ShadowNodeFamilyFragment{tag, surfaceId, nullptr}; auto family = componentDescriptor.createFamily(fragment, std::move(eventTarget)); - auto const props = componentDescriptor.cloneProps(nullptr, rawProps); + auto const props = + componentDescriptor.cloneProps(propsParserContext, nullptr, rawProps); auto const state = componentDescriptor.createInitialState(ShadowNodeFragment{props}, family); @@ -65,7 +71,9 @@ SharedShadowNode UIManager::createNode( fallbackDescriptor->getComponentHandle() == componentDescriptor.getComponentHandle() ? componentDescriptor.cloneProps( - props, RawProps(folly::dynamic::object("name", name))) + propsParserContext, + props, + RawProps(folly::dynamic::object("name", name))) : props, /* .children = */ ShadowNodeFragment::childrenPlaceholder(), /* .state = */ state, @@ -88,13 +96,16 @@ SharedShadowNode UIManager::cloneNode( const RawProps *rawProps) const { SystraceSection s("UIManager::cloneNode"); + PropsParserContext propsParserContext{ + shadowNode->getFamily().getSurfaceId(), *contextContainer_.get()}; + auto &componentDescriptor = shadowNode->getComponentDescriptor(); auto clonedShadowNode = componentDescriptor.cloneShadowNode( *shadowNode, { /* .props = */ rawProps ? componentDescriptor.cloneProps( - shadowNode->getProps(), *rawProps) + propsParserContext, shadowNode->getProps(), *rawProps) : ShadowNodeFragment::propsPlaceholder(), /* .children = */ children, }); diff --git a/ReactCommon/react/renderer/uimanager/UIManager.h b/ReactCommon/react/renderer/uimanager/UIManager.h index ebb8a419bd0..e24434cc9bc 100644 --- a/ReactCommon/react/renderer/uimanager/UIManager.h +++ b/ReactCommon/react/renderer/uimanager/UIManager.h @@ -23,6 +23,7 @@ #include #include #include +#include namespace facebook::react { @@ -33,7 +34,8 @@ class UIManager final : public ShadowTreeDelegate { public: UIManager( RuntimeExecutor const &runtimeExecutor, - BackgroundExecutor const &backgroundExecutor); + BackgroundExecutor const &backgroundExecutor, + ContextContainer::Shared contextContainer); ~UIManager(); @@ -189,6 +191,7 @@ class UIManager final : public ShadowTreeDelegate { RuntimeExecutor const runtimeExecutor_{}; ShadowTreeRegistry shadowTreeRegistry_{}; BackgroundExecutor const backgroundExecutor_{}; + ContextContainer::Shared contextContainer_; mutable better::shared_mutex commitHookMutex_; mutable std::vector commitHooks_;