Skip to content

Commit 9d45e33

Browse files
bghgaryCopilot
andauthored
Use quick_exit in test UnhandledExceptionHandlers for consistency (#1640)
Replace `set_exception`-based error handling with `std::quick_exit(1)` in unit test `UnhandledExceptionHandler`s to match the pattern used by Playground and PrecompiledShaderTest. **Why:** When an unhandled JS exception occurs, the JS thread continues processing the work queue after the handler returns. Using `set_exception` on a promise signals the waiting thread, but more queued work can execute before the main thread reacts — causing cascading errors and confusing logs. `quick_exit` stops everything immediately, which is the right behavior for tests. **Changes:** - Replace `set_exception` with `std::quick_exit(1)` in Tests.JavaScript, Tests.ShaderCache, and Tests.UniformPadding - Keep `std::cerr` output before `quick_exit` so CI captures the error message - Move `std::promise` declarations closer to first use (no longer captured by the handler) - Remove redundant `.flush()` calls after `std::endl` (which already guarantees a flush per the C++ spec) --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 6bde319 commit 9d45e33

File tree

3 files changed

+18
-19
lines changed

3 files changed

+18
-19
lines changed

Apps/UnitTests/Source/Tests.JavaScript.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include <Babylon/Plugins/NativeEncoding.h>
1212
#include <Babylon/ScriptLoader.h>
1313

14+
#include <cstdlib>
15+
1416
extern Babylon::Graphics::Configuration g_deviceConfig;
1517

1618
namespace
@@ -36,19 +38,15 @@ TEST(JavaScript, All)
3638
// Change this to true to wait for the JavaScript debugger to attach (only applies to V8)
3739
constexpr const bool waitForDebugger = false;
3840

39-
std::promise<int32_t> exitCodePromise;
40-
4141
Babylon::Graphics::Device device{g_deviceConfig};
4242

4343
std::optional<Babylon::Polyfills::Canvas> nativeCanvas;
4444

4545
Babylon::AppRuntime::Options options{};
4646

47-
options.UnhandledExceptionHandler = [&exitCodePromise](const Napi::Error& error) {
47+
options.UnhandledExceptionHandler = [](const Napi::Error& error) {
4848
std::cerr << "[Uncaught Error] " << Napi::GetErrorString(error) << std::endl;
49-
std::cerr.flush();
50-
51-
exitCodePromise.set_exception(std::make_exception_ptr(std::exception{}));
49+
std::quick_exit(1);
5250
};
5351

5452
if (waitForDebugger)
@@ -59,13 +57,14 @@ TEST(JavaScript, All)
5957

6058
Babylon::AppRuntime runtime{options};
6159

60+
std::promise<int32_t> exitCodePromise;
61+
6262
runtime.Dispatch([&exitCodePromise, &device, &nativeCanvas](Napi::Env env) {
6363
device.AddToJavaScript(env);
6464

6565
Babylon::Polyfills::XMLHttpRequest::Initialize(env);
6666
Babylon::Polyfills::Console::Initialize(env, [](const char* message, Babylon::Polyfills::Console::LogLevel logLevel) {
6767
std::cout << "[" << EnumToString(logLevel) << "] " << message << std::endl;
68-
std::cout.flush();
6968
});
7069
Babylon::Polyfills::Window::Initialize(env);
7170
Babylon::Polyfills::Blob::Initialize(env);

Apps/UnitTests/Source/Tests.ShaderCache.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <Babylon/ScriptLoader.h>
1010

1111
#include <chrono>
12+
#include <cstdlib>
1213
#include <optional>
1314
#include <future>
1415
#include <iostream>
@@ -28,25 +29,23 @@ TEST(ShaderCache, SaveAndLoad)
2829
device.StartRenderingCurrentFrame();
2930
update.Start();
3031

31-
std::promise<void> scriptIsDone{};
32-
std::promise<void> sceneIsReady{};
33-
3432
Babylon::AppRuntime::Options options{};
3533

36-
options.UnhandledExceptionHandler = [&scriptIsDone](const Napi::Error& error) {
34+
options.UnhandledExceptionHandler = [](const Napi::Error& error) {
3735
std::cerr << "[Uncaught Error] " << Napi::GetErrorString(error) << std::endl;
38-
std::cerr.flush();
39-
40-
scriptIsDone.set_exception(std::make_exception_ptr(std::exception{}));
36+
std::quick_exit(1);
4137
};
4238

4339
Babylon::AppRuntime runtime{options};
40+
41+
std::promise<void> scriptIsDone{};
42+
std::promise<void> sceneIsReady{};
43+
4444
runtime.Dispatch([&device, &sceneIsReady](Napi::Env env) {
4545
device.AddToJavaScript(env);
4646

4747
Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) {
4848
std::cout << message << std::endl;
49-
std::cout.flush();
5049
});
5150
Babylon::Polyfills::Window::Initialize(env);
5251
Babylon::Plugins::NativeEngine::Initialize(env);

Apps/UnitTests/Source/Tests.UniformPadding.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <Babylon/Plugins/NativeEngine.h>
88
#include <Babylon/ScriptLoader.h>
99

10+
#include <cstdlib>
1011
#include <future>
1112
#include <iostream>
1213

@@ -30,12 +31,10 @@ TEST(UniformPadding, SubVec4UniformsDoNotOverflow)
3031
device.StartRenderingCurrentFrame();
3132
update.Start();
3233

33-
std::promise<void> done{};
34-
3534
Babylon::AppRuntime::Options options{};
36-
options.UnhandledExceptionHandler = [&done](const Napi::Error& error) {
35+
options.UnhandledExceptionHandler = [](const Napi::Error& error) {
3736
std::cerr << "[Uncaught Error] " << Napi::GetErrorString(error) << std::endl;
38-
done.set_exception(std::make_exception_ptr(std::exception{}));
37+
std::quick_exit(1);
3938
};
4039

4140
Babylon::AppRuntime runtime{options};
@@ -95,6 +94,8 @@ TEST(UniformPadding, SubVec4UniformsDoNotOverflow)
9594
if (!scene.isReady()) { throw new Error("Scene should be ready with synchronous shader compilation"); }
9695
)", "uniform_padding_test.js");
9796

97+
std::promise<void> done{};
98+
9899
loader.Dispatch([&done](Napi::Env) {
99100
done.set_value();
100101
});

0 commit comments

Comments
 (0)