Skip to content
Draft
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
Expand Up @@ -140,10 +140,11 @@ struct WindowData {

winrt::Microsoft::ReactNative::ReactNativeHost Host() noexcept {
if (!m_host) {
OutputDebugStringA("Playground: Creating ReactNativeHost with debugger support\n");
m_host = winrt::Microsoft::ReactNative::ReactNativeHost();
m_host.InstanceSettings(InstanceSettings());
OutputDebugStringA("Playground: ReactNativeHost created with debugging enabled\n");
}

return m_host;
}
winrt::Microsoft::ReactNative::ReactInstanceSettings InstanceSettings() noexcept {
Expand Down Expand Up @@ -206,6 +207,7 @@ struct WindowData {
}

if (windowData->m_useLiftedComposition) {
OutputDebugStringA("Playground: Setting up lifted composition\n");
// By setting the compositor here we opt into using the new architecture.
winrt::Microsoft::ReactNative::Composition::CompositionUIService::SetCompositor(
InstanceSettings(), g_liftedCompositor);
Expand Down Expand Up @@ -264,8 +266,10 @@ struct WindowData {
m_compRootView.Arrange(constraints, {0, 0});

m_bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
OutputDebugStringA("Playground: Lifted composition setup complete\n");

} else if (!m_target) {
OutputDebugStringA("Playground: Setting up system composition\n");
// General users of RNW should never set CompositionContext - this is an advanced usage to inject another
// composition implementation. By using the SystemCompositionContextHelper here, React Native Windows will
// use System Visuals for its tree.
Expand All @@ -276,6 +280,7 @@ struct WindowData {
L"ReactNative.Composition", L"CompositionContext"},
winrt::Microsoft::ReactNative::Composition::Experimental::SystemCompositionContextHelper::
CreateContext(g_compositor));
OutputDebugStringA("Playground: CompositionContext set\n");

auto interop = g_compositor.as<ABI::Windows::UI::Composition::Desktop::ICompositorDesktopInterop>();
winrt::Windows::UI::Composition::Desktop::DesktopWindowTarget target{nullptr};
Expand Down Expand Up @@ -303,15 +308,32 @@ struct WindowData {
contraints.MaximumSize =
contraints.MinimumSize = {m_width / ScaleFactor(hwnd), m_height / ScaleFactor(hwnd)};
m_compRootView.Arrange(contraints, {0, 0});
OutputDebugStringA("Playground: System composition setup complete\n");
}
}

// Nudge the ReactNativeHost to create the instance and wrapping context
OutputDebugStringA("Playground: About to ReloadInstance\n");
host.ReloadInstance();
OutputDebugStringA("Playground: ReloadInstance complete\n");

// Verify composition context is ready before assigning ReactViewHost
OutputDebugStringA("Playground: Verifying composition context is available\n");
if (windowData->m_useLiftedComposition) {
auto compositor = winrt::Microsoft::ReactNative::Composition::CompositionUIService::GetCompositor(
InstanceSettings().Properties());
if (compositor) {
OutputDebugStringA("Playground: Lifted compositor verified - context ready\n");
} else {
OutputDebugStringA("Playground: WARNING - Lifted compositor not found\n");
}
}

m_compRootView.ReactViewHost(
winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions));
OutputDebugStringA("Playground: ReactViewHost assigned successfully\n");
}


break;
}
Expand Down Expand Up @@ -635,8 +657,10 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
constexpr PCWSTR c_windowClassName = L"MS_REACTNATIVE_PLAYGROUND_COMPOSITION";

int RunPlayground(int showCmd, bool /*useWebDebugger*/) {
OutputDebugStringA("Playground: RunPlayground starting\n");

constexpr PCWSTR appName = L"React Native Playground (Composition)";

auto windowData = std::make_unique<WindowData>();
HWND hwnd = CreateWindow(
c_windowClassName,
Expand Down Expand Up @@ -673,8 +697,12 @@ int RunPlayground(int showCmd, bool /*useWebDebugger*/) {
}

_Use_decl_annotations_ int CALLBACK WinMain(HINSTANCE instance, HINSTANCE, PSTR /* commandLine */, int showCmd) {
OutputDebugStringA("Playground: WinMain starting\n");

// Island-support: Call init_apartment to initialize COM and WinRT for the thread.
OutputDebugStringA("Playground: About to init_apartment\n");
winrt::init_apartment(winrt::apartment_type::single_threaded);
OutputDebugStringA("Playground: init_apartment completed\n");

WNDCLASSEXW wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -215,8 +215,10 @@ void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewH
m_reactViewHost = value;

if (m_reactViewHost) {
OutputDebugStringA("ReactNativeIsland::ReactViewHost() - Attaching view instance\n");
auto viewInstance = winrt::make<CompositionReactViewInstance>(this->get_weak());
m_reactViewHost.AttachViewInstance(viewInstance);
OutputDebugStringA("ReactNativeIsland::ReactViewHost() - View instance attached\n");
}
}

Expand Down Expand Up @@ -725,16 +727,25 @@ Composition::Experimental::IDrawingSurfaceBrush ReactNativeIsland::CreateLoading
}

void ReactNativeIsland::ShowInstanceLoading() noexcept {
OutputDebugStringA("ReactNativeIsland::ShowInstanceLoading() - START\n");

if (!Mso::React::ReactOptions::UseDeveloperSupport(m_context.Properties().Handle()))
return;

if (m_loadingVisual)
return;

OutputDebugStringA("ReactNativeIsland::ShowInstanceLoading() - Getting composition context\n");
auto compContext =
winrt::Microsoft::ReactNative::Composition::implementation::CompositionUIService::GetCompositionContext(
m_context.Properties().Handle());

if (!compContext) {
OutputDebugStringA("ReactNativeIsland::ShowInstanceLoading() - ERROR: compContext is NULL - skipping loading UI\n");
return;
}

OutputDebugStringA("ReactNativeIsland::ShowInstanceLoading() - Creating sprite visual\n");
m_loadingVisual = compContext.CreateSpriteVisual();

auto foregroundBrush = compContext.CreateColorBrush({255, 255, 255, 255});
Expand All @@ -747,6 +758,7 @@ void ReactNativeIsland::ShowInstanceLoading() noexcept {
UpdateLoadingVisualSize();

InternalRootVisual().InsertAt(m_loadingVisual, m_hasRenderedVisual ? 1 : 0);
OutputDebugStringA("ReactNativeIsland::ShowInstanceLoading() - COMPLETE\n");
}

void ReactNativeIsland::InitTextScaleMultiplier() noexcept {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@
<SubType>Code</SubType>
</ClInclude>
<ClInclude Include="ReactHost\AsyncActionQueue.h" />
<ClInclude Include="ReactHost\DebuggerNotifications.h" />
<ClInclude Include="ReactHost\InstanceFactory.h" />
<ClInclude Include="ReactHost\IReactInstanceInternal.h" />
<ClInclude Include="ReactHost\JSBundle.h" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,9 @@
<ClInclude Include="ReactHost\AsyncActionQueue.h">
<Filter>ReactHost</Filter>
</ClInclude>
<ClInclude Include="ReactHost\DebuggerNotifications.h">
<Filter>ReactHost</Filter>
</ClInclude>
<ClInclude Include="ReactHost\InstanceFactory.h">
<Filter>ReactHost</Filter>
</ClInclude>
Expand Down
54 changes: 54 additions & 0 deletions vnext/Microsoft.ReactNative/ReactHost/DebuggerNotifications.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#pragma once

#include <winrt/Microsoft.ReactNative.h>

namespace Microsoft::ReactNative {

struct DebuggerNotifications {
static winrt::Microsoft::ReactNative::IReactPropertyName ShowDebuggerPausedOverlayEventName() noexcept {
static winrt::Microsoft::ReactNative::IReactPropertyName propertyName{
winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetName(
winrt::Microsoft::ReactNative::ReactPropertyBagHelper::GetNamespace(L"ReactNative.Debugger"),
L"ShowDebuggerPausedOverlay")};
return propertyName;
}

static void OnShowDebuggerPausedOverlay(
winrt::Microsoft::ReactNative::IReactNotificationService const &service,
std::string message,
std::function<void()> onResume) {
const winrt::Microsoft::ReactNative::ReactNonAbiValue<std::tuple<std::string, std::function<void()>>> nonAbiValue{
std::in_place, std::tie(message, onResume)};
service.SendNotification(ShowDebuggerPausedOverlayEventName(), nullptr, nonAbiValue);
}

static void OnHideDebuggerPausedOverlay(winrt::Microsoft::ReactNative::IReactNotificationService const &service) {
service.SendNotification(ShowDebuggerPausedOverlayEventName(), nullptr, nullptr);
}

static winrt::Microsoft::ReactNative::IReactNotificationSubscription SubscribeShowDebuggerPausedOverlay(
winrt::Microsoft::ReactNative::IReactNotificationService const &service,
winrt::Microsoft::ReactNative::IReactDispatcher const &dispatcher,
std::function<void(std::string, std::function<void()>)> showCallback,
std::function<void()> hideCallback) {
return service.Subscribe(
ShowDebuggerPausedOverlayEventName(),
dispatcher,
[showCallback, hideCallback](auto &&, winrt::Microsoft::ReactNative::IReactNotificationArgs const &args) {
if (args.Data()) {
const auto [message, onResume] = args.Data()
.as<winrt::Microsoft::ReactNative::ReactNonAbiValue<
std::tuple<std::string, std::function<void()>>>>()
.Value();
showCallback(message, onResume);
} else {
hideCallback();
}
});
}
};

} // namespace Microsoft::ReactNative
7 changes: 7 additions & 0 deletions vnext/Microsoft.ReactNative/ReactHost/React.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#include <Fabric/Composition/UriImageManager.h>
#endif

namespace facebook::react::jsinspector_modern {
class HostTarget;
} // namespace facebook::react::jsinspector_modern

namespace Mso::React {

// Forward declarations
Expand Down Expand Up @@ -347,6 +351,9 @@ struct ReactOptions {
//! The callback is called when IReactInstance is destroyed and must not be used anymore.
//! It is called from the native queue.
OnReactInstanceDestroyedCallback OnInstanceDestroyed;

//! The HostTarget instance for Fusebox
facebook::react::jsinspector_modern::HostTarget *InspectorTarget;
};

//! IReactHost manages a ReactNative instance.
Expand Down
12 changes: 12 additions & 0 deletions vnext/Microsoft.ReactNative/ReactHost/ReactHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,7 @@ class ReactNativeWindowsFeatureFlags : public facebook::react::ReactNativeFeatur
public:
bool enableBridgelessArchitecture() override {
#ifdef USE_FABRIC
OutputDebugStringA("ReactNativeWindowsFeatureFlags::enableBridgelessArchitecture() called\n");
return true;
#else
return false;
Expand All @@ -295,6 +296,17 @@ class ReactNativeWindowsFeatureFlags : public facebook::react::ReactNativeFeatur
bool enableCppPropsIteratorSetter() override {
return true;
}

bool fuseboxEnabledRelease() override {
// log when called
OutputDebugStringA("ReactNativeWindowsFeatureFlags::fuseboxEnabledRelease() called\n");
return true; // Enable Fusebox (modern CDP backend) by default for React Native Windows
}

bool fuseboxNetworkInspectionEnabled() override {
OutputDebugStringA("ReactNativeWindowsFeatureFlags::fuseboxNetworkInspectionEnabled() called\n");
return true; // Enable network inspection support in Fusebox
}
};

std::once_flag g_FlagInitFeatureFlags;
Expand Down
38 changes: 35 additions & 3 deletions vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
#include <react/runtime/PlatformTimerRegistry.h>
#include <react/runtime/TimerManager.h>
#include <react/threading/MessageQueueThreadImpl.h>
#include "Inspector/ReactInspectorThread.h"
#endif

#if !defined(CORE_ABI) && !defined(USE_FABRIC)
Expand Down Expand Up @@ -299,6 +300,18 @@ ReactInstanceWin::ReactInstanceWin(
}

ReactInstanceWin::~ReactInstanceWin() noexcept {
#ifdef USE_FABRIC
if (m_bridgelessReactInstance && m_options.InspectorTarget) {
auto messageDispatchQueue =
Mso::React::MessageDispatchQueue(::Microsoft::ReactNative::ReactInspectorThread::Instance(), nullptr);
messageDispatchQueue.runOnQueueSync([weakBridgelessReactInstance = std::weak_ptr(m_bridgelessReactInstance)]() {
if (auto bridgelessReactInstance = weakBridgelessReactInstance.lock()) {
bridgelessReactInstance->unregisterFromInspector();
}
});
}
#endif

std::scoped_lock lock{s_registryMutex};
auto it = std::find(s_instanceRegistry.begin(), s_instanceRegistry.end(), this);
if (it != s_instanceRegistry.end()) {
Expand Down Expand Up @@ -553,6 +566,8 @@ std::shared_ptr<facebook::react::DevSettings> ReactInstanceWin::CreateDevSetting

devSettings->useRuntimeScheduler = useRuntimeScheduler;

devSettings->inspectorTarget = m_options.InspectorTarget;

return devSettings;
}

Expand Down Expand Up @@ -665,15 +680,27 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {

if (devSettings->useDirectDebugger) {
::Microsoft::ReactNative::GetSharedDevManager()->EnsureHermesInspector(
devSettings->sourceBundleHost, devSettings->sourceBundlePort);
devSettings->sourceBundleHost, devSettings->sourceBundlePort, devSettings->bundleAppId);
}

m_jsiRuntimeHolder = std::make_shared<Microsoft::ReactNative::HermesRuntimeHolder>(
devSettings, jsMessageThread, CreatePreparedScriptStore());
auto jsRuntime = std::make_unique<Microsoft::ReactNative::HermesJSRuntime>(m_jsiRuntimeHolder);
jsRuntime->getRuntime();
m_bridgelessReactInstance = std::make_unique<facebook::react::ReactInstance>(
std::move(jsRuntime), jsMessageThread, timerManager, jsErrorHandlingFunc);

// Check InspectorTarget before creating ReactInstance
if (m_options.InspectorTarget) {
OutputDebugStringA("ReactInstanceWin: InspectorTarget is NOT null\n");
} else {
OutputDebugStringA("ReactInstanceWin: InspectorTarget IS NULL\n");
}

m_bridgelessReactInstance = std::make_shared<facebook::react::ReactInstance>(
std::move(jsRuntime),
jsMessageThread,
timerManager,
jsErrorHandlingFunc,
m_options.InspectorTarget);

auto bufferedRuntimeExecutor = m_bridgelessReactInstance->getBufferedRuntimeExecutor();
timerManager->setRuntimeExecutor(bufferedRuntimeExecutor);
Expand All @@ -695,6 +722,10 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
winrt::make<implementation::ReactContext>(Mso::Copy(m_reactContext)));

facebook::react::ReactInstance::JSRuntimeFlags options;

// Add logging before initializeRuntime
OutputDebugStringA("ReactInstanceWin: About to call initializeRuntime\n");

m_bridgelessReactInstance->initializeRuntime(
options,
[=, onCreated = m_options.OnInstanceCreated, reactContext = m_reactContext](
Expand Down Expand Up @@ -749,6 +780,7 @@ void ReactInstanceWin::InitializeBridgeless() noexcept {
LoadJSBundlesBridgeless(devSettings);
SetupHMRClient();

OutputDebugStringA("ReactInstanceWin: initializeRuntime call completed\n");
} catch (std::exception &e) {
OnErrorWithMessage(e.what());
OnErrorWithMessage("ReactInstanceWin: Failed to create React Instance.");
Expand Down
2 changes: 1 addition & 1 deletion vnext/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ class ReactInstanceWin final : public Mso::ActiveObject<IReactInstanceInternal>

#ifdef USE_FABRIC
// Bridgeless
std::unique_ptr<facebook::react::ReactInstance> m_bridgelessReactInstance;
std::shared_ptr<facebook::react::ReactInstance> m_bridgelessReactInstance;
#endif

std::atomic<ReactInstanceState> m_state{ReactInstanceState::Loading};
Expand Down
Loading
Loading