Skip to content

Commit 3f36d6e

Browse files
authored
Merge pull request #41 from InputActions/scripting-unhandled-promise-rejection
scripting: handle unhandled promise rejection
2 parents 26ca4f6 + b3f1d45 commit 3f36d6e

2 files changed

Lines changed: 48 additions & 6 deletions

File tree

src/libinputactions/scripting/FunctionWrapper.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,14 @@ class FunctionWrapper : public QObject
5959
if constexpr (std::is_void_v<TReturn>) {
6060
function(engine->fromScriptValue<TArgs>(args[I])...);
6161
return {};
62-
}
62+
} else {
63+
const auto result = function(engine->fromScriptValue<TArgs>(args[I])...);
64+
if constexpr (std::is_same_v<TReturn, QJSValue>) {
65+
return result;
66+
}
6367

64-
const auto result = function(engine->fromScriptValue<TArgs>(args[I])...);
65-
if constexpr (std::is_same_v<TReturn, QJSValue>) {
66-
return result;
68+
return engine->toScriptValue(std::move(result));
6769
}
68-
69-
return engine->toScriptValue(std::move(result));
7070
}
7171

7272
QJSEngine *m_engine;

src/libinputactions/scripting/ScriptingEngine.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,48 @@ void ScriptingEngine::initialize()
8888

8989
return m_engine->importModule(module);
9090
}));
91+
92+
// Unhandled promise rejection handling
93+
// TODO Maybe perform the check when the promise is garbage collected if possible
94+
m_engine->evaluate(R"(
95+
const { delay } = require("inputactions/core");
96+
97+
const patch = (promise) => {
98+
promise.__then = promise.then;
99+
promise.then = function(onFulfilled, onRejected) {
100+
this.__handled = true;
101+
return patch(this.__then(onFulfilled, onRejected));
102+
};
103+
104+
promise.__then(undefined, x => {
105+
delay(100).__then(() => {
106+
if (!promise.__handled) {
107+
__unhandledPromiseRejection(x);
108+
}
109+
})
110+
});
111+
112+
return promise;
113+
}
114+
115+
const _Promise = Promise;
116+
Promise = function(executor) {
117+
return patch(new _Promise((resolve, reject) => {
118+
executor(resolve, reject);
119+
}));
120+
}
121+
Promise.all = _Promise.all;
122+
Promise.race = _Promise.race;
123+
Promise.reject = _Promise.reject;
124+
Promise.resolve = _Promise.resolve;
125+
)");
126+
globalObject.setProperty("__unhandledPromiseRejection", newFunction<void, QJSValue>([this](QJSValue error) {
127+
if (error.isError()) {
128+
qCCritical(INPUTACTIONS_SCRIPTING).nospace().noquote() << "Uncaught (in promise) script error\n" << errorToString(error);
129+
} else {
130+
qCCritical(INPUTACTIONS_SCRIPTING).nospace().noquote() << "Uncaught (in promise) " << error.toString();
131+
}
132+
}));
91133
}
92134

93135
void ScriptingEngine::initializeWatchdog()

0 commit comments

Comments
 (0)