Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Add SetProperties method to ReactNativeIsland",
"packageName": "react-native-windows",
"email": "30809111+acoates-ms@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,15 @@ struct WindowData {
}
m_forceRTL = !m_forceRTL;
}
case IDM_SETPROPS: {
m_compRootView.SetProperties([](const winrt::Microsoft::ReactNative::IJSValueWriter &writer) {
static int value = 123;
writer.WriteObjectBegin();
winrt::Microsoft::ReactNative::WriteProperty(writer, L"testProp1", value++);
winrt::Microsoft::ReactNative::WriteProperty(writer, L"testProp2", L"value2");
writer.WriteObjectEnd();
});
}
}

return 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ BEGIN
MENUITEM "&Refresh\tF5", IDM_REFRESH
MENUITEM "&Unload", IDM_UNLOAD
MENUITEM "Toggle Layout &Direction", IDM_TOGGLE_LAYOUT_DIRECTION
MENUITEM "Set Props to running Island", IDM_SETPROPS
MENUITEM SEPARATOR
MENUITEM "&Settings...\tAlt+S", IDM_SETTINGS
MENUITEM SEPARATOR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#define IDC_SIZETOCONTENT 112
#define IDM_UNLOAD 113
#define IDM_TOGGLE_LAYOUT_DIRECTION 114
#define IDM_SETPROPS 115
#define IDI_ICON1 1008

// Next default values for new objects
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,8 @@ void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewH
return;
}

m_props = nullptr;

if (m_reactViewHost) {
UninitRootView();
m_reactViewHost.DetachViewInstance();
Expand Down Expand Up @@ -577,7 +579,9 @@ void ReactNativeIsland::ShowInstanceLoaded() noexcept {
winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()));

m_rootTag = ::Microsoft::ReactNative::getNextRootViewTag();
auto initProps = DynamicWriter::ToDynamic(Mso::Copy(m_reactViewOptions.InitialProps()));

auto initProps =
m_props.isNull() ? m_props : DynamicWriter::ToDynamic(Mso::Copy(m_reactViewOptions.InitialProps()));
if (initProps.isNull()) {
initProps = folly::dynamic::object();
}
Expand Down Expand Up @@ -965,6 +969,24 @@ void ReactNativeIsland::OnUnmounted() noexcept {
}
}

void ReactNativeIsland::SetProperties(winrt::Microsoft::ReactNative::JSValueArgWriter props) noexcept {
auto initProps = DynamicWriter::ToDynamic(props);
if (initProps.isNull()) {
initProps = folly::dynamic::object();
}

if (m_isJSViewAttached) {
if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
initProps["concurrentRoot"] = true;
fabricuiManager->setProps(static_cast<facebook::react::SurfaceId>(m_rootTag), initProps);
return;
}
}

m_props = initProps;
}

winrt::com_ptr<winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView>
ReactNativeIsland::GetComponentView() noexcept {
if (auto portal = m_portal.get()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ struct ReactNativeIsland
float ScaleFactor() noexcept;
void ScaleFactor(float value) noexcept;

void SetProperties(winrt::Microsoft::ReactNative::JSValueArgWriter props) noexcept;

float FontSizeMultiplier() const noexcept;

winrt::event_token SizeChanged(
Expand Down Expand Up @@ -159,6 +161,9 @@ struct ReactNativeIsland
IReactDispatcher m_uiDispatcher{nullptr};
winrt::IInspectable m_uiaProvider{nullptr};

// If SetProps is called before the surface is loaded, store it locally to use on start
folly::dynamic m_props;

// This is the surfaceId that this island belongs to.
// In the case of portal content root, this will be the surfaceId that contains the portal.
int64_t m_rootTag{-1};
Expand Down
64 changes: 53 additions & 11 deletions vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,6 @@ void FabricUIManager::installFabricUIManager() noexcept {

m_scheduler = std::make_shared<facebook::react::Scheduler>(
toolbox, (/*animationDriver_ ? animationDriver_.get() :*/ nullptr), this);
m_surfaceManager = std::make_shared<facebook::react::SurfaceManager>(*m_scheduler);
}

const IComponentViewRegistry &FabricUIManager::GetViewRegistry() const noexcept {
Expand Down Expand Up @@ -135,17 +134,38 @@ void FabricUIManager::startSurface(
layoutContext.pointScaleFactor = rootView.ScaleFactor();
layoutContext.fontSizeMultiplier = rootView.FontSizeMultiplier();

m_surfaceManager->startSurface(
surfaceId,
moduleName,
initialProps,
layoutConstraints,
layoutContext // layout context
);
{
std::unique_lock lock(m_handlerMutex);
auto surfaceHandler = facebook::react::SurfaceHandler{moduleName, surfaceId};
surfaceHandler.setContextContainer(m_scheduler->getContextContainer());
m_handlerRegistry.emplace(surfaceId, std::move(surfaceHandler));
}

visit(surfaceId, [&](const facebook::react::SurfaceHandler &surfaceHandler) {
surfaceHandler.setProps(initialProps);
surfaceHandler.constraintLayout(layoutConstraints, layoutContext);
m_scheduler->registerSurface(surfaceHandler);
surfaceHandler.start();
});
}

void FabricUIManager::setProps(facebook::react::SurfaceId surfaceId, const folly::dynamic &props) const noexcept {
visit(surfaceId, [=](const facebook::react::SurfaceHandler &surfaceHandler) { surfaceHandler.setProps(props); });
}

void FabricUIManager::stopSurface(facebook::react::SurfaceId surfaceId) noexcept {
m_surfaceManager->stopSurface(surfaceId);
visit(surfaceId, [&](const facebook::react::SurfaceHandler &surfaceHandler) {
surfaceHandler.stop();
m_scheduler->unregisterSurface(surfaceHandler);
});

{
std::unique_lock lock(m_handlerMutex);

auto iterator = m_handlerRegistry.find(surfaceId);
m_handlerRegistry.erase(iterator);
}

auto &rootDescriptor = m_registry.componentViewDescriptorWithTag(surfaceId);
rootDescriptor.view.as<winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView>()->stop();
m_registry.enqueueComponentViewWithComponentHandle(
Expand All @@ -156,14 +176,36 @@ facebook::react::Size FabricUIManager::measureSurface(
facebook::react::SurfaceId surfaceId,
const facebook::react::LayoutConstraints &layoutConstraints,
const facebook::react::LayoutContext &layoutContext) const noexcept {
return m_surfaceManager->measureSurface(surfaceId, layoutConstraints, layoutContext);
auto size = facebook::react::Size{};

visit(surfaceId, [&](const facebook::react::SurfaceHandler &surfaceHandler) {
size = surfaceHandler.measure(layoutConstraints, layoutContext);
});

return size;
}

void FabricUIManager::constraintSurfaceLayout(
facebook::react::SurfaceId surfaceId,
const facebook::react::LayoutConstraints &layoutConstraints,
const facebook::react::LayoutContext &layoutContext) const noexcept {
m_surfaceManager->constraintSurfaceLayout(surfaceId, layoutConstraints, layoutContext);
visit(surfaceId, [=](const facebook::react::SurfaceHandler &surfaceHandler) {
surfaceHandler.constraintLayout(layoutConstraints, layoutContext);
});
}

void FabricUIManager::visit(
facebook::react::SurfaceId surfaceId,
const std::function<void(const facebook::react::SurfaceHandler &surfaceHandler)> &callback) const noexcept {
std::shared_lock lock(m_handlerMutex);

auto iterator = m_handlerRegistry.find(surfaceId);

if (iterator == m_handlerRegistry.end()) {
return;
}

callback(iterator->second);
}

winrt::Microsoft::ReactNative::ReactNotificationId<facebook::react::SurfaceId>
Expand Down
12 changes: 10 additions & 2 deletions vnext/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
#include <NativeModules.h>
#include <React.h>
#include <react/renderer/scheduler/SchedulerDelegate.h>
#include <react/renderer/scheduler/SurfaceManager.h>
#include <winrt/Windows.UI.Composition.h>
#include "Composition/ComponentViewRegistry.h"

namespace facebook::react {
class Scheduler;
class ReactNativeConfig;
class SurfaceHandler;
} // namespace facebook::react

namespace Microsoft::ReactNative {
Expand Down Expand Up @@ -47,6 +47,8 @@ struct FabricUIManager final : public std::enable_shared_from_this<FabricUIManag
const facebook::react::LayoutConstraints &layoutConstraints,
const facebook::react::LayoutContext &layoutContext) const noexcept;

void setProps(facebook::react::SurfaceId surfaceId, const folly::dynamic &props) const noexcept;

const IComponentViewRegistry &GetViewRegistry() const noexcept;

static winrt::Microsoft::ReactNative::ReactNotificationId<facebook::react::SurfaceId> NotifyMountedId() noexcept;
Expand All @@ -62,10 +64,13 @@ struct FabricUIManager final : public std::enable_shared_from_this<FabricUIManag
facebook::react::SurfaceId surfaceId);
void didMountComponentsWithRootTag(facebook::react::SurfaceId surfaceId) noexcept;

void visit(
facebook::react::SurfaceId surfaceId,
const std::function<void(const facebook::react::SurfaceHandler &surfaceHandler)> &callback) const noexcept;

winrt::Microsoft::ReactNative::ReactContext m_context;
winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext m_compContext;
std::shared_ptr<facebook::react::Scheduler> m_scheduler;
std::shared_ptr<facebook::react::SurfaceManager> m_surfaceManager;
std::mutex m_schedulerMutex; // Protect m_scheduler
bool m_transactionInFlight{false};
bool m_followUpTransactionRequired{false};
Expand All @@ -77,6 +82,9 @@ struct FabricUIManager final : public std::enable_shared_from_this<FabricUIManag

std::unordered_map<facebook::react::SurfaceId, SurfaceInfo> m_surfaceRegistry;

std::unordered_map<facebook::react::SurfaceId, facebook::react::SurfaceHandler> m_handlerRegistry{};
mutable std::shared_mutex m_handlerMutex;

// Inherited via SchedulerDelegate
virtual void schedulerDidFinishTransaction(
const std::shared_ptr<const facebook::react::MountingCoordinator> &mountingCoordinator) override;
Expand Down
3 changes: 3 additions & 0 deletions vnext/Microsoft.ReactNative/ReactNativeIsland.idl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ namespace Microsoft.ReactNative
Microsoft.ReactNative.Composition.Theme Theme { get; };
Int64 RootTag { get; };

DOC_STRING("Initial props should be set on ReactViewHost. This is used to update props after the initial props are set")
void SetProperties(JSValueArgWriter props);

#ifdef USE_WINUI3
Microsoft.UI.Content.ContentIsland Island { get; };
#endif
Expand Down
1 change: 0 additions & 1 deletion vnext/Shared/Shared.vcxitems
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,6 @@
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\observers\events\EventPerformanceLogger.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\scheduler\Scheduler.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\scheduler\SurfaceHandler.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\scheduler\SurfaceManager.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\telemetry\SurfaceTelemetry.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\telemetry\TransactionTelemetry.cpp" />
<ClCompile Include="$(ReactNativeDir)\ReactCommon\react\renderer\textlayoutmanager\TextMeasureCache.cpp" />
Expand Down
4 changes: 1 addition & 3 deletions vnext/Shared/Shared.vcxitems.filters
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,6 @@
<ClCompile Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\Fabric\WindowsImageManager.cpp">
<Filter>Source Files\Fabric</Filter>
</ClCompile>
<ClInclude Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\Fabric\ImageRequestParams.cpp">
<Filter>Source Files\Fabric</Filter>
</ClInclude>
<ClCompile Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\SchedulerSettings.cpp">
<Filter>Source Files</Filter>
</ClCompile>
Expand Down Expand Up @@ -341,6 +338,7 @@
<ClCompile Include="$(ReactNativeDir)\ReactCommon\jsinspector-modern\tracing\PerformanceTracer.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\Fabric\Composition\CompositionTextProvider.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\Fabric\Composition\CompositionTextRangeProvider.cpp" />
<ClCompile Include="$(MSBuildThisFileDirectory)..\Microsoft.ReactNative\Fabric\ImageRequestParams.cpp" />
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">
Expand Down