Repository navigation
feat(react-native): run on React Native for Windows - #112
Draft
NathanWalker wants to merge 2 commits into
Draft
NathanWalker wants to merge 2 commits into
NathanWalker wants to merge 2 commits into
Conversation
@nativescript/react-native now works in react-native-windows apps (0.83, New Architecture, Hermes), with the whole Windows Runtime available from NativeScript.runOnUI worklets. React Native's own runtime can't host NativeScript on Windows: a module DLL sees it only through react-native-windows' JSI ABI, NativeScript's Windows runtime binds through Node-API, and react-native-worklets has no Windows implementation. So the module (windows/NativeScriptNativeApi) runs a Hermes runtime of its own on the UI thread: - UIRuntime: creates it through the jsr_* API of the hermes.dll react-native-windows already loaded (explicit microtasks, drained after every script and task), attaches @nativescript/windows-napi to its napi_env, and defines Windows, XamlWindow and NSWinRT. Worklets run there from the code the Worklets Babel plugin embeds (__initData.code), with arguments, captured values and results as JSON; console output is replayed through React Native's console, and errors reject. - NodeApiHost: Node's half of Node-API (threadsafe functions, cleanup hooks, buffers, async work, callback scopes), which hermes.dll lacks and the addon needs. The module sets NAPI_HOST_MODULES=<its DLL>;<hermes.dll> so the addon's napi-sys takes each function from the right module (NativeScript/windows: windows-napi support for NAPI_HOST_MODULES). - The addon and nswinrt.js are embedded in the module's DLL as resources and extracted to %LOCALAPPDATA%\nativescript-react-native\<hash>\ on first use, so they reach the app however it's packaged. - JS (src/windows.ts): init() starts the runtime; runOnUI() sends the worklet there. Windows, NSWinRT and XamlWindow are declared undefined in React Native's runtime so worklets can capture them. Verified in a react-native-windows 0.83.2 C++ app built with Visual Studio 2022 Build Tools: sync WinRT calls, arguments and captured values, an awaited WinRT async operation, console replay and error propagation.
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the
|
Xcode 27 ships an arm64-only libclang, so linking an x86_64 objc-metadata-generator fails. Skip that build with a warning, require only the arm64 generator in the build scripts, and let npm packaging skip the x86_64 generator when it was not built.
This branch has not been deployed
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.
Summary
@nativescript/react-nativeon React Native for Windows (react-native-windows 0.83, New Architecture, Hermes), with the whole Windows Runtime available fromNativeScript.runOnUIworklets. Stacked on #105 (feat/react-native-macos).Why its own runtime
On iOS, macOS and Android the module installs into a
jsi::RuntimeReact Native owns. On Windows none is reachable:JsiAbiRuntime), never the engine's runtime object.@nativescript/windows-napi) binds through Node-API, not JSI.So the module (
windows/NativeScriptNativeApi) runs a Hermes runtime of its own on the UI thread.How it works
UIRuntime.cppcreates the runtime through thejsr_*API of thehermes.dllreact-native-windows already loaded. Microtasks are explicit and drained after every script and task: without that, this Hermes never runs promise reactions for an embedder. It attaches windows-napi to the runtime'snapi_envand definesWindows,XamlWindowandNSWinRT.__initData.code). Arguments, captured values and results travel as JSON.consoleoutput is replayed through React Native's console, and thrown errors reject with their stack.NodeApiHost.cppis Node's half of Node-API (threadsafe functions, cleanup hooks, buffers, async work, callback scopes).hermes.dlllacks it and napi-rs needs it at registration. The module setsNAPI_HOST_MODULES=<its DLL>;<hermes.dll>, and the addon's napi-sys takes each function from the first module that exports it. That needs feat(windows-napi): take Node-API from the modules NAPI_HOST_MODULES names windows#46.nswinrt.jsare embedded in the module's DLL as resources. On first use the addon is extracted to%LOCALAPPDATA%\nativescript-react-native\<hash>\, so it reaches the app however it's packaged (MSIX or unpackaged). A referenced native project's extra files never reach the MSIX layout.src/windows.ts):init()starts the runtime andrunOnUI()sends the worklet there.Windows,NSWinRTandXamlWindoware declaredundefinedin React Native's runtime, so a worklet can capture them. The ObjC paths inindex.tsare untouched;initandrunOnUIbranch first.windows/is react-native-windows'cpp-libtemplate. It uses no Windows codegen (methods register by attribute) and the installed Visual Studio's toolset (v143orv145).Evidence
A react-native-windows 0.83.2 C++ app (
init-windows --template cpp-app), built with Visual Studio 2022 Build Tools (MSBuild directly: the RNW CLI insists on VS 18.6+), with this package linked and autolinked, run as a registered MSIX layout on Windows 11 x64:AnalyticsInfo,EasClientDeviceInformation){"family":"Windows.Desktop","name":"WINDOWS_NSTUDIO","os":"WINDOWS"}in 19 ms"Hello from Windows x 3 (object)"(Windowsresolves in the worklet)await NSWinRT.toPromise(DeviceInformation.FindAllAsync())"2387 devices"console.login the workletconsole.logreceived"logged on the UI thread Windows.Foundation.Uri"throwin the workletError: thrown in the workletThe package's JS tests are unchanged by this: the same 12 pass and the same 9 fail with and without it. Those 9 read native sources that aren't at those paths in this checkout.
Not done
@nativescript/windows-napiwithNAPI_HOST_MODULESisn't published yet. Until then, build it from NativeScript/windows and pass/p:NativeScriptWindowsNapiAddon=…\windows_napi.dll /p:NativeScriptWindowsNapiJs=…\nswinrt.js.runOnUIonly.Microsoft.UI.Windowing.AppWindow) aren't in the runtime's system metadata. Registering the app's.winmd(NSWinRT.interop.registerWinmd) is the next step for things like setting the window title.