summaryrefslogtreecommitdiffstats
path: root/tests/manual/wasm
diff options
context:
space:
mode:
authorMikolaj Boc <mikolaj.boc@qt.io>2022-07-01 11:31:03 +0200
committerMikolaj Boc <mikolaj.boc@qt.io>2022-07-07 06:28:13 +0200
commitfb8832de9c2d9cec08a83047137fbd316e6f7d1f (patch)
tree0662caa1e66b7635d480934155f7a06ea26bb12f /tests/manual/wasm
parentdbe858bf80f554c4d916ee230fc9dcde01699bd7 (diff)
Make the promises js-less using a newly introduced thunk pool
Since we cannot rely on the clients specifying a suitable CSP that will not forbid execution of js injections, we have to refrain from using any explicit <script> elements. To keep the promise system working, a thunk pool was introduced which keeps track of a limited pool of promise callback exports. In case the resources are busy, pending calls are enqueued. This works since the JS Promise.then/catch/finally always fire, even on ready/failed promises. As the situation of full thunk pool allocation is unlikely to happen en masse IRL, the solution should not adversely affect the performance. Heavy unit tests were created to confirm the solution works as expected. Task-number: QTBUG-99611 Change-Id: I0e6982d4ee76a4263b59e72b004b3ff2f167e4df Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Diffstat (limited to 'tests/manual/wasm')
-rw-r--r--tests/manual/wasm/qstdweb/promise_main.cpp181
1 files changed, 71 insertions, 110 deletions
diff --git a/tests/manual/wasm/qstdweb/promise_main.cpp b/tests/manual/wasm/qstdweb/promise_main.cpp
index 456fb7eb32..351f06c91d 100644
--- a/tests/manual/wasm/qstdweb/promise_main.cpp
+++ b/tests/manual/wasm/qstdweb/promise_main.cpp
@@ -17,14 +17,15 @@ class WasmPromiseTest : public QObject
Q_OBJECT
public:
- WasmPromiseTest() : m_window(val::global("window")), m_testSupport(val::object()) {
- m_window.set("testSupport", m_testSupport);
- }
+ WasmPromiseTest() : m_window(val::global("window")), m_testSupport(val::object()) {}
- ~WasmPromiseTest() noexcept {}
+ ~WasmPromiseTest() noexcept = default;
private:
void init() {
+ m_testSupport = val::object();
+ m_window.set("testSupport", m_testSupport);
+
EM_ASM({
testSupport.resolve = {};
testSupport.reject = {};
@@ -108,52 +109,32 @@ void WasmPromiseTest::multipleResolve()
{
init();
- auto onThen = std::make_shared<BarrierCallback>(3, []() {
+ static constexpr int promiseCount = 1000;
+
+ auto onThen = std::make_shared<BarrierCallback>(promiseCount, []() {
QWASMSUCCESS();
});
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [=](val result) {
- QWASMVERIFY(result.isString());
- QWASMCOMPARE("Data 1", result.as<std::string>());
-
- (*onThen)();
- },
- .catchFunc = [](val error) {
- Q_UNUSED(error);
- QWASMFAIL("Unexpected catch");
- }
- }, std::string("1"));
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [=](val result) {
- QWASMVERIFY(result.isString());
- QWASMCOMPARE("Data 2", result.as<std::string>());
-
- (*onThen)();
- },
- .catchFunc = [](val error) {
- Q_UNUSED(error);
- QWASMFAIL("Unexpected catch");
- }
- }, std::string("2"));
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [=](val result) {
- QWASMVERIFY(result.isString());
- QWASMCOMPARE("Data 3", result.as<std::string>());
-
- (*onThen)();
- },
- .catchFunc = [](val error) {
- Q_UNUSED(error);
- QWASMFAIL("Unexpected catch");
- }
- }, std::string("3"));
+ for (int i = 0; i < promiseCount; ++i) {
+ qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
+ .thenFunc = [=](val result) {
+ QWASMVERIFY(result.isString());
+ QWASMCOMPARE(QString::number(i).toStdString(), result.as<std::string>());
+
+ (*onThen)();
+ },
+ .catchFunc = [](val error) {
+ Q_UNUSED(error);
+ QWASMFAIL("Unexpected catch");
+ }
+ }, (QStringLiteral("test") + QString::number(i)).toStdString());
+ }
EM_ASM({
- testSupport.resolve["3"]("Data 3");
- testSupport.resolve["1"]("Data 1");
- testSupport.resolve["2"]("Data 2");
- });
+ for (let i = $0 - 1; i >= 0; --i) {
+ testSupport.resolve['test' + i](`${i}`);
+ }
+ }, promiseCount);
}
void WasmPromiseTest::simpleReject()
@@ -179,53 +160,32 @@ void WasmPromiseTest::simpleReject()
void WasmPromiseTest::multipleReject()
{
- init();
- auto onThen = std::make_shared<BarrierCallback>(3, []() {
+ static constexpr int promiseCount = 1000;
+
+ auto onCatch = std::make_shared<BarrierCallback>(promiseCount, []() {
QWASMSUCCESS();
});
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [](val result) {
- Q_UNUSED(result);
- QWASMFAIL("Unexpected then");
- },
- .catchFunc = [=](val error) {
- QWASMVERIFY(error.isString());
- QWASMCOMPARE("Error 1", error.as<std::string>());
-
- (*onThen)();
- }
- }, std::string("1"));
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [](val result) {
- Q_UNUSED(result);
- QWASMFAIL("Unexpected then");
- },
- .catchFunc = [=](val error) {
- QWASMVERIFY(error.isString());
- QWASMCOMPARE("Error 2", error.as<std::string>());
-
- (*onThen)();
- }
- }, std::string("2"));
- qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
- .thenFunc = [](val result) {
- Q_UNUSED(result);
- QWASMFAIL("Unexpected then");
- },
- .catchFunc = [=](val error) {
- QWASMVERIFY(error.isString());
- QWASMCOMPARE("Error 3", error.as<std::string>());
-
- (*onThen)();
- }
- }, std::string("3"));
+ for (int i = 0; i < promiseCount; ++i) {
+ qstdweb::Promise::make(m_testSupport, "makeTestPromise", {
+ .thenFunc = [=](val result) {
+ QWASMVERIFY(result.isString());
+ QWASMCOMPARE(QString::number(i).toStdString(), result.as<std::string>());
+
+ (*onCatch)();
+ },
+ .catchFunc = [](val error) {
+ Q_UNUSED(error);
+ QWASMFAIL("Unexpected catch");
+ }
+ }, (QStringLiteral("test") + QString::number(i)).toStdString());
+ }
EM_ASM({
- testSupport.reject["3"]("Error 3");
- testSupport.reject["1"]("Error 1");
- testSupport.reject["2"]("Error 2");
- });
+ for (let i = $0 - 1; i >= 0; --i) {
+ testSupport.resolve['test' + i](`${i}`);
+ }
+ }, promiseCount);
}
void WasmPromiseTest::throwInThen()
@@ -241,8 +201,7 @@ void WasmPromiseTest::throwInThen()
},
.catchFunc = [](val error) {
QWASMCOMPARE("Expected error", error.as<std::string>());
- //QWASMSUCCESS();
- QWASMFAIL("Other nasty problem");
+ QWASMSUCCESS();
}
}, std::string("throwInThen"));
@@ -386,39 +345,42 @@ void WasmPromiseTest::all()
{
init();
- val promise1 = m_testSupport.call<val>("makeTestPromise", val("promise1"));
- val promise2 = m_testSupport.call<val>("makeTestPromise", val("promise2"));
- val promise3 = m_testSupport.call<val>("makeTestPromise", val("promise3"));
-
+ static constexpr int promiseCount = 1000;
auto thenCalledOnce = std::shared_ptr<bool>();
*thenCalledOnce = true;
- qstdweb::Promise::all({promise1, promise2, promise3}, {
- .thenFunc = [thenCalledOnce](val result) {
+ std::vector<val> promises;
+ promises.reserve(promiseCount);
+
+ for (int i = 0; i < promiseCount; ++i) {
+ promises.push_back(m_testSupport.call<val>("makeTestPromise", val(("all" + QString::number(i)).toStdString())));
+ }
+
+ qstdweb::Promise::all(std::move(promises), {
+ .thenFunc = [=](val result) {
QWASMVERIFY(*thenCalledOnce);
*thenCalledOnce = false;
QWASMVERIFY(result.isArray());
- QWASMCOMPARE(3, result["length"].as<int>());
- QWASMCOMPARE("Data 1", result[0].as<std::string>());
- QWASMCOMPARE("Data 2", result[1].as<std::string>());
- QWASMCOMPARE("Data 3", result[2].as<std::string>());
+ QWASMCOMPARE(promiseCount, result["length"].as<int>());
+ for (int i = 0; i < promiseCount; ++i) {
+ QWASMCOMPARE(QStringLiteral("Data %1").arg(i).toStdString(), result[i].as<std::string>());
+ }
QWASMSUCCESS();
},
- .catchFunc = [](val result) {
- Q_UNUSED(result);
- EM_ASM({
- throw new Error("Unexpected error");
- });
+ .catchFunc = [](val error) {
+ Q_UNUSED(error);
+ QWASMFAIL("Unexpected catch");
}
});
EM_ASM({
- testSupport.resolve["promise3"]("Data 3");
- testSupport.resolve["promise1"]("Data 1");
- testSupport.resolve["promise2"]("Data 2");
- });
+ console.log('Resolving');
+ for (let i = $0 - 1; i >= 0; --i) {
+ testSupport.resolve['all' + i](`Data ${i}`);
+ }
+ }, promiseCount);
}
void WasmPromiseTest::allWithThrow()
@@ -503,8 +465,7 @@ void WasmPromiseTest::allWithFinallyAndThrow()
.finallyFunc = [finallyCalledOnce]() {
QWASMVERIFY(*finallyCalledOnce);
*finallyCalledOnce = false;
- // QWASMSUCCESS();
- QWASMFAIL("Some nasty problem");
+ QWASMSUCCESS();
}
});