microsoft / react-native-xaml

A React Native Windows library to use XAML / WinUI controls
MIT License
97 stars 28 forks source link

JS Promises are not being processed and RN app crashes when changing pages/rendering new components #247

Closed pawisesa closed 1 year ago

pawisesa commented 1 year ago

Problem Description

Using a brand-new test app created following https://microsoft.github.io/react-native-windows/docs/getting-started and using these dependencies:

"react": "18.0.0",
"react-native": "0.69.6",
"react-native-webview": "^11.17.2",
"react-native-windows": "0.69.20",
"react-native-xaml": "0.0.70"

we see that when it loads our internal library that downloads a metadata and renders react-native-xaml elements according to it, where the interactable elements such as TextBoxes, Button, etc that are rendered and have been hooked up to our library on interaction (e.g. OnTextChanged for TextBoxes, OnClick for buttons, etc), we see that our callback functions in JS are run but promises that are generated in that callback function are not processed (so the functions attached to the promises for on success and on failure themselves are never run).

When we then change pages/load a different component from our library we immediately get an app crash due to "disconnectAnimatedNodeFromView".

Looking into the react-native-xaml code we found this code in XamlMetadata.cpp:

void XamlMetadata::JsiDispatchEvent(jsi::Runtime& rt, int64_t viewTag, std::string&& eventName, std::shared_ptr<facebook::jsi::Object>& eventData) const noexcept {
  auto params = jsi::Array(rt, 3);
  params.setValueAtIndex(rt, 0, static_cast<int>(viewTag));
  params.setValueAtIndex(rt, 1, eventName);
  params.setValueAtIndex(rt, 2, *eventData.get());

  m_callFunctionReturnFlushedQueue->call(rt, "RCTEventEmitter", "receiveEvent", params);
}

that triggers the JS interaction callback, but this may be dangerous because m_callFunctionReturnFlushedQueue is retrieved directly from the JSI bridge.

Steps To Reproduce

Unfortunately, due to the fact that our library is internal to Microsoft I can't share the code here, please ping me at @pawisesa to get a repro and discuss the issue.

Expected Results

For JS promises to be processed and the app to not crash when rendering a different component.

Environment

System:
    OS: Windows 10 10.0.22621
    CPU: (12) x64 Intel(R) Xeon(R) W-2133 CPU @ 3.60GHz
    Memory: 10.73 GB / 31.60 GB
  Binaries:
    Node: 16.14.0 - C:\Program Files\nodejs\node.EXE
    Yarn: 1.22.19 - ~\AppData\Roaming\npm\yarn.CMD
    npm: 8.3.1 - C:\Program Files\nodejs\npm.CMD
    Watchman: Not Found
  SDKs:
    Android SDK: Not Found
    Windows SDK:
      AllowDevelopmentWithoutDevLicense: Enabled
      AllowAllTrustedApps: Enabled
      Versions: 10.0.16299.0, 10.0.17134.0, 10.0.17763.0, 10.0.18362.0, 10.0.19041.0, 10.0.22000.0, 10.0.22621.0
  IDEs:
    Android Studio: Not Found
    Visual Studio: 16.11.33328.57 (Visual Studio Enterprise 2019), 17.4.33403.182 (Visual Studio Enterprise 2022)
  Languages:
    Java: Not Found
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.0.0 => 18.0.0
    react-native: 0.69.6 => 0.69.6
    react-native-windows: 0.69.20 => 0.69.20
  npmGlobalPackages:
    *react-native*: Not Found
acoates-ms commented 1 year ago

The issue here is that m_callFunctionReturnFlushedQueue returns a list of native module calls from the bridge that should be called. But this code isn't calling them. This essentially means that any calls to a native module being made in response to this event will not get called.