From 7d045b8543d6fa84a3e00a44c75014a3bf183216 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Thu, 6 Aug 2020 15:34:51 +0200 Subject: Expose request_quit method to JS in HTML5 export. --- platform/javascript/javascript_main.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'platform/javascript/javascript_main.cpp') diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index a30d84a52c..464712ca6d 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -39,6 +39,17 @@ static OS_JavaScript *os = nullptr; static uint64_t target_ticks = 0; +extern "C" EMSCRIPTEN_KEEPALIVE void _request_quit_callback(char *p_filev[], int p_filec) { + DisplayServerJavaScript *ds = DisplayServerJavaScript::get_singleton(); + if (ds) { + Variant event = int(DisplayServer::WINDOW_EVENT_CLOSE_REQUEST); + Variant *eventp = &event; + Variant ret; + Callable::CallError ce; + ds->window_event_callback.call((const Variant **)&eventp, 1, ret, ce); + } +} + void exit_callback() { emscripten_cancel_main_loop(); // After this, we can exit! Main::cleanup(); @@ -102,6 +113,12 @@ extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) { ResourceLoader::set_abort_on_missing_resources(false); Main::start(); os->get_main_loop()->init(); + // Expose method for requesting quit. + EM_ASM({ + Module['request_quit'] = function() { + ccall("_request_quit_callback", null, []); + }; + }); // Immediately run the first iteration. // We are inside an animation frame, we want to immediately draw on the newly setup canvas. main_loop_callback(); -- cgit v1.2.3 From dccd71c7a36fc31f6cc19e0f7f587fb0860c973a Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Fri, 18 Sep 2020 17:25:05 +0200 Subject: JS synchronous start, better persistent FS sync. The engine now expects to emscripten FS to be setup and sync-ed before main is called. This is exposed via `Module["initFS"]` which also allows to setup multiple persistence paths (internal use only for now). Additionally, FS syncing is done **once** for every loop if at least one file in a persistent path was open for writing and closed, and if the FS is not syncing already. This should potentially fix issues reported by users where "autosave" would not work on the web (never calling `syncfs` because of too many writes). --- platform/javascript/javascript_main.cpp | 72 ++++++++++++++------------------- 1 file changed, 31 insertions(+), 41 deletions(-) (limited to 'platform/javascript/javascript_main.cpp') diff --git a/platform/javascript/javascript_main.cpp b/platform/javascript/javascript_main.cpp index 464712ca6d..01722c4bc8 100644 --- a/platform/javascript/javascript_main.cpp +++ b/platform/javascript/javascript_main.cpp @@ -88,12 +88,27 @@ void main_loop_callback() { /* clang-format on */ os->get_main_loop()->finish(); os->finalize_async(); // Will add all the async finish functions. + /* clang-format off */ EM_ASM({ Promise.all(Module.async_finish).then(function() { Module.async_finish = []; + return new Promise(function(accept, reject) { + if (!Module.idbfs) { + accept(); + return; + } + FS.syncfs(function(error) { + if (error) { + err('Failed to save IDB file system: ' + error.message); + } + accept(); + }); + }); + }).then(function() { ccall("cleanup_after_sync", null, []); }); }); + /* clang-format on */ } } @@ -101,37 +116,8 @@ extern "C" EMSCRIPTEN_KEEPALIVE void cleanup_after_sync() { emscripten_set_main_loop(exit_callback, -1, false); } -extern "C" EMSCRIPTEN_KEEPALIVE void main_after_fs_sync(char *p_idbfs_err) { - String idbfs_err = String::utf8(p_idbfs_err); - if (!idbfs_err.empty()) { - print_line("IndexedDB not available: " + idbfs_err); - } - os->set_idb_available(idbfs_err.empty()); - // TODO: Check error return value. - Main::setup2(); // Manual second phase. - // Ease up compatibility. - ResourceLoader::set_abort_on_missing_resources(false); - Main::start(); - os->get_main_loop()->init(); - // Expose method for requesting quit. - EM_ASM({ - Module['request_quit'] = function() { - ccall("_request_quit_callback", null, []); - }; - }); - // Immediately run the first iteration. - // We are inside an animation frame, we want to immediately draw on the newly setup canvas. - main_loop_callback(); - emscripten_resume_main_loop(); -} - +/// When calling main, it is assumed FS is setup and synced. int main(int argc, char *argv[]) { - // Create and mount userfs immediately. - EM_ASM({ - FS.mkdir('/userfs'); - FS.mount(IDBFS, {}, '/userfs'); - }); - // Configure locale. char locale_ptr[16]; /* clang-format off */ @@ -149,26 +135,30 @@ int main(int argc, char *argv[]) { /* clang-format on */ os = new OS_JavaScript(); + os->set_idb_available((bool)EM_ASM_INT({ return Module.idbfs })); // We must override main when testing is enabled TEST_MAIN_OVERRIDE - Main::setup(argv[0], argc - 1, &argv[1], false); - emscripten_set_main_loop(main_loop_callback, -1, false); - emscripten_pause_main_loop(); // Will need to wait for FS sync. + Main::setup(argv[0], argc - 1, &argv[1]); - // Sync from persistent state into memory and then - // run the 'main_after_fs_sync' function. + // Ease up compatibility. + ResourceLoader::set_abort_on_missing_resources(false); + + Main::start(); + os->get_main_loop()->init(); + // Expose method for requesting quit. /* clang-format off */ EM_ASM({ - FS.syncfs(true, function(err) { - requestAnimationFrame(function() { - ccall('main_after_fs_sync', null, ['string'], [err ? err.message : ""]); - }); - }); + Module['request_quit'] = function() { + ccall("_request_quit_callback", null, []); + }; }); /* clang-format on */ + emscripten_set_main_loop(main_loop_callback, -1, false); + // Immediately run the first iteration. + // We are inside an animation frame, we want to immediately draw on the newly setup canvas. + main_loop_callback(); return 0; - // Continued async in main_after_fs_sync() from the syncfs() callback. } -- cgit v1.2.3