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 (oneQLabelwith "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(); } -
Hi,
I made a minimal example to demonstrate a problem. I try to call
alert()before showing GUI (oneQLabelwith "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? -
@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:

-
@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:
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!
-
8 8Observer8 has marked this topic as solved on
-
@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? -
@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";
-
@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); }