ReloadInstance async task and InstanceLoaded event were not correctly reporting failures (#9224)
* ReloadInstance async task and InstanceLoaded event were not correctly reporting failures * Change files * Add another test * yarn format * ignore syntax error file
This commit is contained in:
Родитель
fe53f11762
Коммит
403da047bc
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"type": "prerelease",
|
||||
"comment": "ReloadInstance async task and InstanceLoaded event were not correctly reporting failures",
|
||||
"packageName": "react-native-windows",
|
||||
"email": "30809111+acoates-ms@users.noreply.github.com",
|
||||
"dependentChangeType": "patch"
|
||||
}
|
|
@ -8,6 +8,7 @@
|
|||
/local-cli/lib
|
||||
/local-cli/lib-commonjs
|
||||
/packages
|
||||
/Microsoft.ReactNative.IntegrationTests/SyntaxError.js
|
||||
/ReactCopies
|
||||
/RNTester.d.ts
|
||||
/src/rntypes
|
||||
|
|
|
@ -112,6 +112,65 @@ TEST_CLASS (ReactNativeHostTests) {
|
|||
|
||||
TestEventService::ObserveEvents({TestEvent{"InstanceLoaded::Completed", nullptr}});
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadInstance_FiresInstanceLoaded_Success) {
|
||||
TestEventService::Initialize();
|
||||
|
||||
auto options = TestReactNativeHostHolder::Options{};
|
||||
auto reactNativeHost = TestReactNativeHostHolder(L"ReactNativeHostTests", [](ReactNativeHost const &host) noexcept {
|
||||
host.InstanceSettings().InstanceLoaded(
|
||||
[](auto const &, winrt::Microsoft::ReactNative::IInstanceLoadedEventArgs args) noexcept {
|
||||
if (args.Failed()) {
|
||||
TestEventService::LogEvent("InstanceLoaded::Failed", nullptr);
|
||||
} else {
|
||||
TestEventService::LogEvent("InstanceLoaded::Success", nullptr);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TestEventService::ObserveEvents({TestEvent{"InstanceLoaded::Success", nullptr}});
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadBundleWithError_FiresInstanceLoaded_Failed) {
|
||||
TestEventService::Initialize();
|
||||
|
||||
auto options = TestReactNativeHostHolder::Options{};
|
||||
auto reactNativeHost = TestReactNativeHostHolder(L"SyntaxError", [](ReactNativeHost const &host) noexcept {
|
||||
host.InstanceSettings().InstanceLoaded(
|
||||
[](auto const &, winrt::Microsoft::ReactNative::IInstanceLoadedEventArgs args) noexcept {
|
||||
if (args.Failed()) {
|
||||
TestEventService::LogEvent("InstanceLoaded::Failed", nullptr);
|
||||
} else {
|
||||
TestEventService::LogEvent("InstanceLoaded::Success", nullptr);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
TestEventService::ObserveEvents({TestEvent{"InstanceLoaded::Failed", nullptr}});
|
||||
}
|
||||
|
||||
TEST_METHOD(LoadBundleWithError_ReloadInstance_Fails) {
|
||||
TestEventService::Initialize();
|
||||
|
||||
auto options = TestReactNativeHostHolder::Options{};
|
||||
options.LoadInstance = false;
|
||||
auto reactNativeHost = TestReactNativeHostHolder(
|
||||
L"SyntaxError",
|
||||
[](ReactNativeHost const &host) noexcept {
|
||||
host.ReloadInstance().Completed([](auto const &, winrt::Windows::Foundation::AsyncStatus status) mutable {
|
||||
if (status == winrt::Windows::Foundation::AsyncStatus::Completed) {
|
||||
TestEventService::LogEvent("InstanceLoaded::Completed", nullptr);
|
||||
} else if (status == winrt::Windows::Foundation::AsyncStatus::Canceled) {
|
||||
TestEventService::LogEvent("InstanceLoaded::Canceled", nullptr);
|
||||
} else {
|
||||
TestEventService::LogEvent("InstanceLoaded::Failed", nullptr);
|
||||
}
|
||||
});
|
||||
},
|
||||
std::move(options));
|
||||
|
||||
TestEventService::ObserveEvents({TestEvent{"InstanceLoaded::Canceled", nullptr}});
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ReactNativeIntegrationTests
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
// Bundle with syntax error to test bundle load failures
|
||||
|
||||
global.foo(();
|
|
@ -379,8 +379,13 @@ Mso::Future<void> ReactHost::LoadInQueue(ReactOptions &&options) noexcept {
|
|||
}
|
||||
}
|
||||
|
||||
return whenLoaded.AsFuture().Then(m_executor, [this](Mso::Maybe<void> && /*value*/) noexcept {
|
||||
return whenLoaded.AsFuture().Then(m_executor, [this](Mso::Maybe<void> &&value) noexcept {
|
||||
std::vector<Mso::Future<void>> loadCompletionList;
|
||||
|
||||
if (value.IsError()) {
|
||||
return Mso::MakeFailedFuture<void>(std::move(value.TakeError()));
|
||||
}
|
||||
|
||||
ForEachViewHost([&loadCompletionList](auto &viewHost) noexcept {
|
||||
loadCompletionList.push_back(viewHost.UpdateViewInstanceInQueue());
|
||||
});
|
||||
|
|
|
@ -216,9 +216,11 @@ ReactInstanceWin::ReactInstanceWin(
|
|||
m_whenLoaded.AsFuture()
|
||||
.Then<Mso::Executors::Inline>(
|
||||
[onLoaded = m_options.OnInstanceLoaded, reactContext = m_reactContext](Mso::Maybe<void> &&value) noexcept {
|
||||
auto errCode = value.IsError() ? value.TakeError() : Mso::ErrorCode();
|
||||
if (onLoaded) {
|
||||
onLoaded.Get()->Invoke(reactContext, value.IsError() ? value.TakeError() : Mso::ErrorCode());
|
||||
onLoaded.Get()->Invoke(reactContext, errCode);
|
||||
}
|
||||
return Mso::Maybe<void>(errCode);
|
||||
})
|
||||
.Then(Queue(), [whenLoaded = std::move(whenLoaded)](Mso::Maybe<void> &&value) noexcept {
|
||||
whenLoaded.SetValue(std::move(value));
|
||||
|
@ -529,7 +531,9 @@ void ReactInstanceWin::LoadJSBundles() noexcept {
|
|||
|
||||
try {
|
||||
instanceWrapper->loadBundleSync(Mso::Copy(strongThis->JavaScriptBundleFile()));
|
||||
strongThis->OnReactInstanceLoaded(Mso::ErrorCode{});
|
||||
if (strongThis->State() != ReactInstanceState::HasError) {
|
||||
strongThis->OnReactInstanceLoaded(Mso::ErrorCode{});
|
||||
}
|
||||
} catch (...) {
|
||||
strongThis->OnReactInstanceLoaded(Mso::ExceptionErrorProvider().MakeErrorCode(std::current_exception()));
|
||||
}
|
||||
|
|
|
@ -27,18 +27,20 @@ struct AsyncActionFutureAdapter : winrt::implements<
|
|||
if (strongThis->m_status == AsyncStatus::Started) {
|
||||
if (result.IsValue()) {
|
||||
strongThis->m_status = AsyncStatus::Completed;
|
||||
if (strongThis->m_completedAssigned) {
|
||||
handler = std::move(strongThis->m_completed);
|
||||
}
|
||||
} else {
|
||||
strongThis->m_status = AsyncStatus::Error;
|
||||
strongThis->m_error = result.GetError();
|
||||
strongThis->m_status = Mso::CancellationErrorProvider().TryGetErrorInfo(strongThis->m_error, false)
|
||||
? AsyncStatus::Canceled
|
||||
: AsyncStatus::Error;
|
||||
}
|
||||
if (strongThis->m_completedAssigned) {
|
||||
handler = std::move(strongThis->m_completed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
invoke(handler, *strongThis, AsyncStatus::Completed);
|
||||
invoke(handler, *strongThis, strongThis->m_status);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче