From 0bd5fc32811a26d772e5dd6e30f0b226bc33d925 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20S=C3=B8rvig?= Date: Mon, 10 Oct 2022 12:58:14 +0200 Subject: [PATCH] wasm: disable run-time check for specialHTMLTargets Recent versions of Emscripten may abort if module_property() is used to look up specialHTMLTargets, which makes run-time checking impossible. The abort is implemented on the JS property getter on the Module object, which means that it's not possible to bypass this by using e.g. EM_ASM instead of the C++ API. Disable usage of specialHTMLTargets on emsdk > 3.1.14 for now, until we can add API (or find some other means) for opting in. This commit also adds functions for comparing Emscripten versions. Change-Id: Ibe5d1a82f267fa95dd62cdfc66595bc23036933f Reviewed-by: Aleksandr Reviakin Reviewed-by: Lorn Potter (cherry picked from commit 4711f078b77011f389a3a5af368e76c72799bb9b) Reviewed-by: Qt Cherry-pick Bot --- src/plugins/platforms/wasm/qwasmscreen.cpp | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/plugins/platforms/wasm/qwasmscreen.cpp b/src/plugins/platforms/wasm/qwasmscreen.cpp index 350832ebf58..9ce2996fd4b 100644 --- a/src/plugins/platforms/wasm/qwasmscreen.cpp +++ b/src/plugins/platforms/wasm/qwasmscreen.cpp @@ -20,6 +20,8 @@ #include #include +#include + QT_BEGIN_NAMESPACE using namespace emscripten; @@ -169,10 +171,46 @@ std::string QWasmScreen::canvasSpecialHtmlTargetId() const return std::string("!qtcanvas_") + std::to_string(uint32_t(this)); } +namespace { + +// Compare Emscripten versions, returns > 0 if a is greater than b. + +int compareVersionComponents(int a, int b) +{ + return a >= 0 && b >= 0 ? a - b : 0; +} + +int compareEmscriptenVersions(std::tuple a, std::tuple b) +{ + if (std::get<0>(a) == std::get<0>(b)) { + if (std::get<1>(a) == std::get<1>(b)) { + return compareVersionComponents(std::get<2>(a), std::get<2>(b)); + } + return compareVersionComponents(std::get<1>(a), std::get<1>(b)); + } + return compareVersionComponents(std::get<0>(a), std::get<0>(b)); +} + +bool isEmsdkVersionGreaterThan(std::tuple test) +{ + return compareEmscriptenVersions( + std::make_tuple(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__), test) > 0; +} + +} // namespace + bool QWasmScreen::hasSpecialHtmlTargets() const { static bool gotIt = []{ // Enable use of specialHTMLTargets, if available + + // On Emscripten > 3.1.14 (exact version not known), emscripten::val::module_property() + // aborts instead of returning undefined when attempting to resolve the specialHTMLTargets + // property, in the case where it is not defined. Disable the availability test in this case. + // FIXME: Add alternative way to enable. + if (isEmsdkVersionGreaterThan(std::make_tuple(3, 1, 14))) + return false; + emscripten::val htmlTargets = emscripten::val::module_property("specialHTMLTargets"); if (htmlTargets.isUndefined()) return false;