Failed to show GUI in WASM after JavaScript call
-
Hi,
I made a minimal example to demonstrate a problem. I try to call
alert()
before showing GUI (oneQLabel
with "Hello" text). I see thealert()
call but I don't see aQLabel
. But if I comment this line:call_alert();
I see theQLabel
. Is it a bug?#include <QtWidgets/QApplication> #include <QtWidgets/QLabel> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QWidget> #include <emscripten.h> EM_JS(void, call_alert, (), { alert("hello"); throw "all done"; }) class Widget : public QWidget { Q_OBJECT public: Widget() { call_alert(); QLabel *label = new QLabel("Hello"); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(label); layout->addStretch(); setLayout(layout); } }; #include "main.moc" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
-
@8Observer8
You don't see the label at all, or you mean you don't see it till after you have dismissed thealert()
?
Are you wanting to testthrow
, or can that be removed from your example? -
@JonB said in Failed to show GUI in WASM after JavaScript call:
You don't see the label at all
Yes. I can see a label only if I comment this line
call_alert();
It is not a problem with dismissingalert()
. I replacedalert()
withconsole.log()
. I don't see a label but I see "hello" in the console:EM_JS(void, call_alert, (), { console.log("hello"); throw "all done"; })
But if I comment
call_alert();
like this:Widget() { // call_alert(); QLabel *label = new QLabel("Hello"); QVBoxLayout *layout = new QVBoxLayout(); layout->addWidget(label); layout->addStretch(); setLayout(layout); }
I see the label:
-
@JonB said in Failed to show GUI in WASM after JavaScript call:
Are you wanting to test throw, or can that be removed from your example?
I don't know why I should call
throw "all done";
I found it in the Emscripten docs. I tried to comment it:EM_JS(void, call_alert, (), { console.log("hello"); // throw "all done"; })
I see a label now:
It solved. Thank you very much!
-
-
@8Observer8
Well, that's why I asked about thethrow
! That causes a JS error and aborts the script. I don't know how that then impacts whatever state the WASM is in (I don't use), but it perhaps does not even return into your calling program? -
@JonB said in Failed to show GUI in WASM after JavaScript call:
but it perhaps does not even return into your calling program?
Yes, you are right! When I comment
throw "all done"
It returns to a calling program:EM_JS(void, call_alert, (), { console.log("hello"); // throw "all done"; }) class Widget : public QWidget { Q_OBJECT public: Widget() { call_alert(); qDebug() << "Text in Widget";
And withthrow "all done"
it doesn't return:EM_JS(void, call_alert, (), { console.log("hello"); throw "all done"; }) class Widget : public QWidget { Q_OBJECT public: Widget() { call_alert(); qDebug() << "Text in Widget";
-
@8Observer8
Now that you know that, you could protect yourself with "neat" code by enclosing anything in the body of that function insidetry ... catch ...
(with some warning/alert dialog), so that if it ever does something bad your calling code still continues. -
I wrote an example that play a sound using Web Audio API in Qt WebAssembly. It is a 2D sound but Web Audio API can play 3D sounds too. There are two buttons in this example: "Run" and "Play". The "Run" button must be pressed first and next the "Play" button must be pressed. You can run it by one click: https://replit.com/@8Observer8/play-audio-with-web-audio-api-qt6-cpp
main.cpp
#include <QtWidgets/QApplication> #include <QtWidgets/QPushButton> #include <QtWidgets/QVBoxLayout> #include <QtWidgets/QWidget> #include <emscripten.h> EM_JS(void, call_init, (), { my_init(); }) EM_JS(void, call_run, (), { my_run(); }) EM_JS(void, call_play, (), { playSound(); }) class Widget : public QWidget { Q_OBJECT public: Widget() { call_init(); runButton = new QPushButton("Run"); playButton = new QPushButton("Play"); playButton->setEnabled(false); QVBoxLayout *vbox = new QVBoxLayout(); vbox->addWidget(runButton); vbox->addWidget(playButton); vbox->addStretch(); setLayout(vbox); connect(runButton, &QPushButton::pressed, this, &Widget::runButtonClick); connect(playButton, &QPushButton::pressed, this, &Widget::playButtonClick); } private slots: void runButtonClick() { call_run(); runButton->setEnabled(false); playButton->setEnabled(true); } void playButtonClick() { call_play(); } private: QPushButton *runButton; QPushButton *playButton; }; #include "main.moc" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
my_script.js
let audioContext, decideArrayBuffer, decideAudioBuffer; async function my_init() { console.log("init"); const decideResponse = await fetch("assets/sounds/decidemp3-14575.mp3"); decideArrayBuffer = await decideResponse.arrayBuffer(); } async function my_run() { console.log("my run"); audioContext = new window.AudioContext(); decideAudioBuffer = await audioContext.decodeAudioData(decideArrayBuffer); } function play(audioBuffer, isLoop = false) { const source = audioContext.createBufferSource(); source.buffer = audioBuffer; source.loop = isLoop; const gain = audioContext.createGain(); source.connect(gain).connect(audioContext.destination); gain.gain.value = 0.3; source.start(); return source; } function playSound() { play(decideAudioBuffer); }