mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-21 16:05:44 -07:00
wasm/js/emscripten: Fix page loading race
Using a stunt webserver which artificially introduces a 3s delay just before the last line of the HTML output, I have reproduced a uwer-reported loading/startup race bug: Previously the wasm loading was started by the <script> element, synchronously. If the wasm loading is fast, and finishes before the HTML loading, the onRuntimeInitialized event may occur before initPuzzles. But initPuzzles sets up the event handler. Fix this bug, and introduce a new comment containing an argument for the correctness of the new approach. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
This commit is contained in:

committed by
Simon Tatham

parent
56ef86f92b
commit
77866e1335
@ -43,6 +43,7 @@ endfunction()
|
|||||||
function(set_platform_puzzle_target_properties NAME TARGET)
|
function(set_platform_puzzle_target_properties NAME TARGET)
|
||||||
em_link_pre_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpre.js)
|
em_link_pre_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpre.js)
|
||||||
em_link_js_library(${TARGET} ${CMAKE_SOURCE_DIR}/emcclib.js)
|
em_link_js_library(${TARGET} ${CMAKE_SOURCE_DIR}/emcclib.js)
|
||||||
|
em_link_post_js(${TARGET} ${CMAKE_SOURCE_DIR}/emccpost.js)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
function(build_platform_extras)
|
function(build_platform_extras)
|
||||||
|
1
emccpost.js
Normal file
1
emccpost.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
initPuzzle();
|
45
emccpre.js
45
emccpre.js
@ -35,6 +35,51 @@ var update_xmin, update_xmax, update_ymin, update_ymax;
|
|||||||
// our own init stuff first), and that when main() returns nothing
|
// our own init stuff first), and that when main() returns nothing
|
||||||
// will get cleaned up so we remain able to call the puzzle's various
|
// will get cleaned up so we remain able to call the puzzle's various
|
||||||
// callbacks.
|
// callbacks.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// Page loading order:
|
||||||
|
//
|
||||||
|
// 1. The browser starts reading *.html (which comes from jspage.pl)
|
||||||
|
// 2. It finds the <script> tag. This is marked defer, so the
|
||||||
|
// browser will start fetching and parsing it, but not execute it
|
||||||
|
// until the page has loaded.
|
||||||
|
//
|
||||||
|
// Now the browser is loading *.html and *.js in parallel. The
|
||||||
|
// html is rendered as we go, and the js is deferred.
|
||||||
|
//
|
||||||
|
// 3. The HTML finishes loading. The browser is about to fire the
|
||||||
|
// `DOMContentLoaded` event (ie `onload`) but before that, it
|
||||||
|
// actually runs the deferred JS. THis consists of
|
||||||
|
//
|
||||||
|
// (i) emccpre.js (this file). This sets up various JS variables
|
||||||
|
// including the emscripten Module object.
|
||||||
|
//
|
||||||
|
// (ii) emscripten's JS. This starts the WASM loading.
|
||||||
|
//
|
||||||
|
// (iii) emccpost.js. This calls initPuzzle, which is defined here
|
||||||
|
// in this file. initPuzzle:
|
||||||
|
//
|
||||||
|
// (a) finds various DOM elements and bind them to variables,
|
||||||
|
// which depend on the HTML having loaded (it has).
|
||||||
|
//
|
||||||
|
// (b) makes various `cwrap` calls into the emscripten module to
|
||||||
|
// set up hooks; this depends on the emscripten JS having been
|
||||||
|
// loaded (it has).
|
||||||
|
//
|
||||||
|
// (c) Makes the call to emscripten's
|
||||||
|
// Module.onRuntimeInitialized, which sets the callback for when
|
||||||
|
// the WASM has finished loading and initialising. This has to
|
||||||
|
// come before the WASM finishes loading, or we'll miss the
|
||||||
|
// callback. We are executing synchronously here in the same JS
|
||||||
|
// file as started the WASM loading, so that is guaranteed.
|
||||||
|
//
|
||||||
|
// When this JS execution is complete, the browser fires the `onload`
|
||||||
|
// event. This is ignored. It continues loading the WASM.
|
||||||
|
//
|
||||||
|
// 4. The WASM loading and initialisation completes. The
|
||||||
|
// onRuntimeInitialised callback calls into emscripten-generated
|
||||||
|
// WASM to call the C `main`, to actually start the puzzle.
|
||||||
|
|
||||||
var Module = {
|
var Module = {
|
||||||
'noInitialRun': true,
|
'noInitialRun': true,
|
||||||
'noExitRuntime': true
|
'noExitRuntime': true
|
||||||
|
@ -73,7 +73,7 @@ EOF
|
|||||||
<head>
|
<head>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=ASCII" />
|
<meta http-equiv="Content-Type" content="text/html; charset=ASCII" />
|
||||||
<title>${puzzlename}, ${unfinishedtitlefragment}from Simon Tatham's Portable Puzzle Collection</title>
|
<title>${puzzlename}, ${unfinishedtitlefragment}from Simon Tatham's Portable Puzzle Collection</title>
|
||||||
<script type="text/javascript" src="${jspath}${filename}.js"></script>
|
<script defer type="text/javascript" src="${jspath}${filename}.js"></script>
|
||||||
<style class="text/css">
|
<style class="text/css">
|
||||||
/* Margins and centring on the top-level div for the game menu */
|
/* Margins and centring on the top-level div for the game menu */
|
||||||
#gamemenu { margin-top: 0; margin-bottom: 0.5em; text-align: center }
|
#gamemenu { margin-top: 0; margin-bottom: 0.5em; text-align: center }
|
||||||
@ -217,7 +217,7 @@ EOF
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body onLoad="initPuzzle();">
|
<body>
|
||||||
<h1 align=center>${puzzlename}</h1>
|
<h1 align=center>${puzzlename}</h1>
|
||||||
${unfinishedheading}
|
${unfinishedheading}
|
||||||
<h2 align=center>from Simon Tatham's Portable Puzzle Collection</h2>
|
<h2 align=center>from Simon Tatham's Portable Puzzle Collection</h2>
|
||||||
|
Reference in New Issue
Block a user