diff options
-rw-r--r-- | src/library.js | 117 | ||||
-rw-r--r-- | src/library_browser.js | 107 | ||||
-rw-r--r-- | src/library_sdl.js | 17 | ||||
-rw-r--r-- | src/postamble.js | 1 | ||||
-rw-r--r-- | src/preamble.js | 19 | ||||
-rw-r--r-- | src/shell.html | 2 | ||||
-rw-r--r-- | system/include/emscripten/emscripten.h | 24 | ||||
-rw-r--r-- | tests/emscripten_fs_api_browser.cpp | 17 | ||||
-rwxr-xr-x | tests/runner.py | 63 | ||||
-rw-r--r-- | third_party/closure-compiler/README | 2 | ||||
-rw-r--r-- | third_party/closure-compiler/compiler.jar | bin | 5378434 -> 5427247 bytes | |||
-rw-r--r-- | third_party/closure-compiler/readme.txt | 3 | ||||
-rw-r--r-- | tools/file_packager.py | 97 |
13 files changed, 331 insertions, 138 deletions
diff --git a/src/library.js b/src/library.js index d1ede6bc..52102f63 100644 --- a/src/library.js +++ b/src/library.js @@ -33,6 +33,7 @@ LibraryManager.library = { 'Module["FS_createFolder"] = FS.createFolder;' + 'Module["FS_createPath"] = FS.createPath;' + 'Module["FS_createDataFile"] = FS.createDataFile;' + + 'Module["FS_createPreloadedFile"] = FS.createPreloadedFile;' + 'Module["FS_createLazyFile"] = FS.createLazyFile;' + 'Module["FS_createLink"] = FS.createLink;' + 'Module["FS_createDevice"] = FS.createDevice;', @@ -51,6 +52,15 @@ LibraryManager.library = { // This is set to false when the runtime is initialized, allowing you // to modify the filesystem freely before run() is called. ignorePermissions: true, + joinPath: function(parts, forceRelative) { + var ret = parts[0]; + for (var i = 1; i < parts.length; i++) { + if (ret[ret.length-1] != '/') ret += '/'; + ret += parts[i]; + } + if (forceRelative && ret[0] == '/') ret = ret.substr(1); + return ret; + }, // Converts any path to an absolute path. Resolves embedded "." and ".." // parts. absolutePath: function(relative, base) { @@ -273,10 +283,87 @@ LibraryManager.library = { }, // Preloads a file asynchronously. You can call this before run, for example in // preRun. run will be delayed until this file arrives and is set up. - createPreloadedFile: function(parent, name, url, canRead, canWrite) { - Browser.asyncLoad(url, function(data) { - FS.createDataFile(parent, name, data, canRead, canWrite); - }); + // If you call it after run(), you may want to pause the main loop until it + // completes, if so, you can use the onload parameter to be notified when + // that happens. + // In addition to normally creating the file, we also asynchronously preload + // the browser-friendly versions of it: For an image, we preload an Image + // element and for an audio, and Audio. These are necessary for SDL_Image + // and _Mixer to find the files in preloadedImages/Audios. + // You can also call this with a typed array instead of a url. It will then + // do preloading for the Image/Audio part, as if the typed array were the + // result of an XHR that you did manually. + createPreloadedFile: function(parent, name, url, canRead, canWrite, onload, onerror) { + Browser.ensureObjects(); + var fullname = FS.joinPath([parent, name], true); + function finish(byteArray) { + FS.createDataFile(parent, name, byteArray, canRead, canWrite); + if (Browser.isImageFile(name)) { + var bb = new Browser.BlobBuilder(); + bb.append(byteArray.buffer); + var b = bb.getBlob(); + var url = Browser.URLObject.createObjectURL(b); + var img = new Image(); + img.onload = function() { + assert(img.complete, 'Image ' + url + ' could not be decoded'); + var canvas = document.createElement('canvas'); + canvas.width = img.width; + canvas.height = img.height; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + Module["preloadedImages"][fullname] = canvas; + Browser.URLObject.revokeObjectURL(url); + if (onload) onload(); + removeRunDependency('cp ' + fullname); + }; + img.onerror = function(event) { + console.log('Image ' + url + ' could not be decoded'); + if (onerror) onerror(); + }; + img.src = url; + } else if (Browser.isAudioFile(name)) { + if (Browser.hasBlobConstructor) { + var b = new Blob([byteArray.buffer], { type: Browser.getAudioMimetype(name) }); + var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this! + var audio = new Audio(); + audio.removedDependency = false; + audio['oncanplaythrough'] = function() { // XXX string for closure + audio['oncanplaythrough'] = null; + Module["preloadedAudios"][fullname] = audio; + if (!audio.removedDependency) { + if (onload) onload(); + removeRunDependency('cp ' + fullname); + audio.removedDependency = true; + } + }; + audio.onerror = function(event) { + if (!audio.removedDependency) { + console.log('Audio ' + url + ' could not be decoded or timed out trying to decode'); + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); // keep calm and carry on + audio.removedDependency = true; + } + }; + setTimeout(audio.onerror, 2000); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) + audio.src = url; + } else { + Module["preloadedAudios"][fullname] = new Audio(); // empty shim + if (onerror) onerror(); + removeRunDependency('cp ' + fullname); + } + } else { + if (onload) onload(); + removeRunDependency('cp ' + fullname); + } + } + addRunDependency('cp ' + fullname); + if (typeof url == 'string') { + Browser.asyncLoad(url, function(byteArray) { + finish(byteArray); + }, onerror); + } else { + finish(url); + } }, // Creates a link to a sepcific local path. createLink: function(parent, name, target, canRead, canWrite) { @@ -4199,10 +4286,22 @@ LibraryManager.library = { }, strstr: function(ptr1, ptr2) { - var str1 = Pointer_stringify(ptr1); - var str2 = Pointer_stringify(ptr2); - var ret = str1.search(str2); - return ret >= 0 ? ptr1 + ret : 0; + var check = 0, start; + do { + if (!check) { + start = ptr1; + check = ptr2; + } + var curr1 = {{{ makeGetValue('ptr1++', 0, 'i8') }}}; + var curr2 = {{{ makeGetValue('check++', 0, 'i8') }}}; + if (curr2 == 0) return start; + if (curr2 != curr1) { + // rewind to one character after start, to find ez in eeez + ptr1 = start + 1; + check = 0; + } + } while (curr1); + return 0; }, strchr: function(ptr, chr) { @@ -4926,7 +5025,7 @@ LibraryManager.library = { floor: 'Math.floor', floorf: 'Math.floor', pow: 'Math.pow', - powf: 'Math.powf', + powf: 'Math.pow', llvm_sqrt_f32: 'Math.sqrt', llvm_sqrt_f64: 'Math.sqrt', llvm_pow_f32: 'Math.pow', diff --git a/src/library_browser.js b/src/library_browser.js index ce59dbdd..3ac61dc5 100644 --- a/src/library_browser.js +++ b/src/library_browser.js @@ -23,10 +23,39 @@ mergeInto(LibraryManager.library, { } Browser.mainLoop.shouldPause = false; }, + updateStatus: function() { + if (Module['setStatus']) { + var remaining = Browser.mainLoop.remainingBlockers; + var expected = Browser.mainLoop.expectedBlockers; + if (remaining) { + if (remaining < expected) { + Module['setStatus']('Please wait... (' + (expected - remaining) + '/' + expected + ')'); + } else { + Module['setStatus']('Please wait...'); + } + } else { + Module['setStatus'](''); + } + } + } }, pointerLock: false, moduleContextCreatedCallbacks: [], + ensureObjects: function() { + if (Browser.ensured) return; + Browser.ensured = true; + try { + new Blob(); + Browser.hasBlobConstructor = true; + } catch(e) { + Browser.hasBlobConstructor = false; + console.log("warning: no blob constructor, cannot create blobs with mimetypes"); + } + Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : console.log("warning: cannot build blobs")); + Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); + }, + createContext: function(canvas, useWebGL, setInModule) { #if !USE_TYPED_ARRAYS if (useWebGL) { @@ -172,38 +201,52 @@ mergeInto(LibraryManager.library, { xhr.send(null); }, - asyncLoad: function(url, callback) { + asyncLoad: function(url, onload, onerror) { Browser.xhrLoad(url, function(arrayBuffer) { assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).'); - callback(new Uint8Array(arrayBuffer)); - removeRunDependency(); + onload(new Uint8Array(arrayBuffer)); + removeRunDependency('al ' + url); }, function(event) { - throw 'Loading data file "' + url + '" failed.'; + if (onerror) { + onerror(); + } else { + throw 'Loading data file "' + url + '" failed.'; + } }); - addRunDependency(); - } + addRunDependency('al ' + url); + }, + + isImageFile: function(name) { + return name.substr(-4) in { '.jpg': 1, '.png': 1, '.bmp': 1 }; + }, + + isAudioFile: function(name) { + return name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 }; + }, + + getAudioMimetype: function(name) { + var ret = { 'ogg': 'audio/ogg', 'wav': 'audio/wav', 'mp3': 'audio/mpeg' }[name.substr(-3)]; + assert(ret); + return ret; + }, + }, emscripten_async_wget: function(url, file, onload, onerror) { - url = Pointer_stringify(url); - - Browser.xhrLoad(url, function(response) { - var absolute = Pointer_stringify(file); - var index = absolute.lastIndexOf('/'); - FS.createDataFile( - absolute.substr(0, index), - absolute.substr(index +1), - new Uint8Array(response), - true, true); - - if (onload) { + var _url = Pointer_stringify(url); + var _file = Pointer_stringify(file); + var index = _file.lastIndexOf('/'); + FS.createPreloadedFile( + _file.substr(0, index), + _file.substr(index +1), + _url, true, true, + function() { FUNCTION_TABLE[onload](file); - } - }, function(event) { - if (onerror) { + }, + function() { FUNCTION_TABLE[onerror](file); } - }); + ); }, emscripten_async_run_script__deps: ['emscripten_run_script'], @@ -222,8 +265,12 @@ mergeInto(LibraryManager.library, { var jsFunc = FUNCTION_TABLE[func]; var wrapper = function() { if (Browser.mainLoop.queue.length > 0) { - Browser.mainLoop.queue.shift()(); - if (Browser.mainLoop.queue.length == 0 && Module['setStatus']) Module['setStatus'](''); + var start = Date.now(); + var blocker = Browser.mainLoop.queue.shift(); + blocker.func(); + console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); + if (Browser.mainLoop.remainingBlockers) Browser.mainLoop.remainingBlockers--; + Browser.mainLoop.updateStatus(); setTimeout(wrapper, 0); return; } @@ -267,9 +314,15 @@ mergeInto(LibraryManager.library, { Browser.mainLoop.resume(); }, - emscripten_push_main_loop_blocker: function(func) { - if (Module['setStatus']) Module['setStatus']('Please wait..'); - Browser.mainLoop.queue.push(FUNCTION_TABLE[func]); + _emscripten_push_main_loop_blocker: function(func, name) { + Browser.mainLoop.queue.push({ func: FUNCTION_TABLE[func], name: Pointer_stringify(name) }); + Browser.mainLoop.updateStatus(); + }, + + emscripten_set_main_loop_expected_blockers: function(num) { + Browser.mainLoop.expectedBlockers = num; + Browser.mainLoop.remainingBlockers = num; + Browser.mainLoop.updateStatus(); }, emscripten_async_call: function(func, millis) { diff --git a/src/library_sdl.js b/src/library_sdl.js index 7de9bfe3..580330e8 100644 --- a/src/library_sdl.js +++ b/src/library_sdl.js @@ -45,6 +45,7 @@ var LibrarySDL = { DOMEventToSDLEvent: {}, keyCodes: { // DOM code ==> SDL code. See https://developer.mozilla.org/en/Document_Object_Model_%28DOM%29/KeyboardEvent and SDL_keycode.h + 46: 127, // SDLK_DEL == '\177' 38: 1106, // up arrow 40: 1105, // down arrow 37: 1104, // left arrow @@ -429,9 +430,13 @@ var LibrarySDL = { {{{ makeSetValue('SDL.keyboardState', 'SDL.keyCodes[event.keyCode] || event.keyCode', 'event.type == "keydown"', 'i8') }}}; - SDL.shiftKey = event.shiftKey; - SDL.ctrlKey = event.ctrlKey; - SDL.altKey = event.altKey; + if (event.keyCode == 16) { //shift + SDL.shiftKey = event.type == "keydown"; + } else if (event.keyCode == 17) { //control + SDL.ctrlKey = event.type == "keydown"; + } else if (event.keyCode == 18) { //alt + SDL.altKey = event.type == "keydown"; + } break; } @@ -796,9 +801,9 @@ var LibrarySDL = { SDL_GetModState: function() { // TODO: numlock, capslock, etc. - return (SDL.shiftKey ? 0x0001 & 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT - (SDL.ctrlKey ? 0x0040 & 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL - (SDL.altKey ? 0x0100 & 0x0200 : 0); // KMOD_LALT & KMOD_RALT + return (SDL.shiftKey ? 0x0001 | 0x0002 : 0) | // KMOD_LSHIFT & KMOD_RSHIFT + (SDL.ctrlKey ? 0x0040 | 0x0080 : 0) | // KMOD_LCTRL & KMOD_RCTRL + (SDL.altKey ? 0x0100 | 0x0200 : 0); // KMOD_LALT & KMOD_RALT }, SDL_GetMouseState: function(x, y) { diff --git a/src/postamble.js b/src/postamble.js index 10ac1888..2944e681 100644 --- a/src/postamble.js +++ b/src/postamble.js @@ -45,6 +45,7 @@ function run(args) { function doRun() { var ret = 0; + calledRun = true; if (Module['_main']) { preMain(); ret = Module.callMain(args); diff --git a/src/preamble.js b/src/preamble.js index 5c5e64fc..7abe0db8 100644 --- a/src/preamble.js +++ b/src/preamble.js @@ -793,21 +793,34 @@ var STRING_TABLE = []; // it happens right before run - run will be postponed until // the dependencies are met. var runDependencies = 0; -function addRunDependency() { +var runDependencyTracking = {}; +var calledRun = false; +function addRunDependency(id) { runDependencies++; if (Module['monitorRunDependencies']) { Module['monitorRunDependencies'](runDependencies); } + if (id) { + assert(!runDependencyTracking[id]); + runDependencyTracking[id] = 1; + } } Module['addRunDependency'] = addRunDependency; -function removeRunDependency() { +function removeRunDependency(id) { runDependencies--; if (Module['monitorRunDependencies']) { Module['monitorRunDependencies'](runDependencies); } - if (runDependencies == 0) run(); + if (id) { + assert(runDependencyTracking[id]); + delete runDependencyTracking[id]; + } + if (runDependencies == 0 && !calledRun) run(); } Module['removeRunDependency'] = removeRunDependency; +Module["preloadedImages"] = {}; // maps url to image data +Module["preloadedAudios"] = {}; // maps url to audio data + // === Body === diff --git a/src/shell.html b/src/shell.html index c04ae84b..336f926d 100644 --- a/src/shell.html +++ b/src/shell.html @@ -65,7 +65,7 @@ totalDependencies: 0, monitorRunDependencies: function(left) { this.totalDependencies = Math.max(this.totalDependencies, left); - Module.setStatus(left ? 'Preparing: ' + (this.totalDependencies-left) + '/' + this.totalDependencies + '...' : 'All downloads complete.'); + Module.setStatus(left ? 'Preparing... (' + (this.totalDependencies-left) + '/' + this.totalDependencies + ')' : 'All downloads complete.'); } }; Module.setStatus('Downloading...'); diff --git a/system/include/emscripten/emscripten.h b/system/include/emscripten/emscripten.h index 9bc6c410..6850d2eb 100644 --- a/system/include/emscripten/emscripten.h +++ b/system/include/emscripten/emscripten.h @@ -50,15 +50,33 @@ extern void emscripten_cancel_main_loop(); /* * Add a function to a queue of events that will execute - * before the main loop will continue. + * before the main loop will continue. The event is pushed + * into the back of the queue. (Note that in the native version + * of this we simply execute the function, so to keep semantics + * identical be careful to not push while the queue is being + * used.) */ #if EMSCRIPTEN -extern void emscripten_push_main_loop_blocker(void (*func)()); +extern void _emscripten_push_main_loop_blocker(void (*func)(), const char *name); #else -inline void emscripten_push_main_loop_blocker(void (*func)()) { +inline void _emscripten_push_main_loop_blocker(void (*func)(), const char *name) { func(); } #endif +#define emscripten_push_main_loop_blocker(func) \ + _emscripten_push_main_loop_blocker(func, #func) + +/* + * Sets the number of blockers remaining until some user-relevant + * event. This affects how we show progress. So if you set this + * to 10, then push 10 blockers, as they complete the user will + * see x/10 and so forth. + */ +#if EMSCRIPTEN +extern void emscripten_set_main_loop_expected_blockers(int num); +#else +inline void emscripten_set_main_loop_expected_blockers(int num) {} +#endif /* * Call a C function asynchronously, that is, after returning diff --git a/tests/emscripten_fs_api_browser.cpp b/tests/emscripten_fs_api_browser.cpp index 07469f34..7757ef8a 100644 --- a/tests/emscripten_fs_api_browser.cpp +++ b/tests/emscripten_fs_api_browser.cpp @@ -1,22 +1,25 @@ #include<stdio.h> #include<emscripten.h> #include<assert.h> -#include <string.h> - +#include<string.h> +#include<SDL/SDL.h> +#include"SDL/SDL_image.h" + extern "C" { int result = 1; int get_count = 0; void wait_wgets() { - if (get_count == 2) { + if (get_count == 3) { + assert(IMG_Load("/tmp/screen_shot.png")); emscripten_cancel_main_loop(); REPORT_RESULT(); } } void onLoaded(const char* file) { - if (strcmp(file, "/tmp/test.html")) { + if (strcmp(file, "/tmp/test.html") && strcmp(file, "/tmp/screen_shot.png")) { result = 0; } @@ -60,6 +63,12 @@ int main() { onLoaded, onError); + emscripten_async_wget( + "http://localhost:8888/screenshot.png", + "/tmp/screen_shot.png", + onLoaded, + onError); + emscripten_set_main_loop(wait_wgets, 0); return 0; diff --git a/tests/runner.py b/tests/runner.py index 9c714da5..1ad8f3a3 100755 --- a/tests/runner.py +++ b/tests/runner.py @@ -3979,6 +3979,68 @@ at function.:blag ''' self.do_run(src, '0*0*0*0*6*5*4*3*3*9*8') + def test_strstr(self): + src = r''' + #include <stdio.h> + #include <string.h> + + int main() + { + printf("%d\n", !!strstr("\\n", "\\n")); + printf("%d\n", !!strstr("cheezy", "ez")); + printf("%d\n", !!strstr("cheeezy", "ez")); + printf("%d\n", !!strstr("cheeeeeeeeeezy", "ez")); + printf("%d\n", !!strstr("cheeeeeeeeee1zy", "ez")); + printf("%d\n", !!strstr("che1ezy", "ez")); + printf("%d\n", !!strstr("che1ezy", "che")); + printf("%d\n", !!strstr("ce1ezy", "che")); + printf("%d\n", !!strstr("ce1ezy", "ezy")); + printf("%d\n", !!strstr("ce1ezyt", "ezy")); + printf("%d\n", !!strstr("ce1ez1y", "ezy")); + printf("%d\n", !!strstr("cheezy", "a")); + printf("%d\n", !!strstr("cheezy", "b")); + printf("%d\n", !!strstr("cheezy", "c")); + printf("%d\n", !!strstr("cheezy", "d")); + printf("%d\n", !!strstr("cheezy", "g")); + printf("%d\n", !!strstr("cheezy", "h")); + printf("%d\n", !!strstr("cheezy", "i")); + printf("%d\n", !!strstr("cheezy", "e")); + printf("%d\n", !!strstr("cheezy", "x")); + printf("%d\n", !!strstr("cheezy", "y")); + printf("%d\n", !!strstr("cheezy", "z")); + printf("%d\n", !!strstr("cheezy", "_")); + + const char *str = "a big string"; + printf("%d\n", strstr(str, "big") - str); + return 0; + } + ''' + self.do_run(src, '''1 +1 +1 +1 +0 +1 +1 +0 +1 +1 +0 +0 +0 +1 +0 +0 +1 +0 +1 +0 +1 +1 +0 +2 +''') + def test_sscanf(self): src = r''' #include <stdio.h> @@ -7910,6 +7972,7 @@ elif 'browser' in str(sys.argv): self.btest('emscripten_api_browser.cpp', '1') def test_emscripten_fs_api(self): + shutil.copyfile(path_from_root('tests', 'screenshot.png'), os.path.join(self.get_dir(), 'screenshot.png')) # preloaded *after* run self.btest('emscripten_fs_api_browser.cpp', '1') def test_gc(self): diff --git a/third_party/closure-compiler/README b/third_party/closure-compiler/README index e6d12c4a..77ab89db 100644 --- a/third_party/closure-compiler/README +++ b/third_party/closure-compiler/README @@ -146,7 +146,7 @@ the parse tree data structures were extracted and modified significantly for use by Google's JavaScript compiler. Local Modifications: The packages have been renamespaced. All code not -relavant to parsing has been removed. A JSDoc parser and static typing +relevant to parsing has been removed. A JsDoc parser and static typing system have been added. diff --git a/third_party/closure-compiler/compiler.jar b/third_party/closure-compiler/compiler.jar Binary files differindex d958a618..da191b01 100644 --- a/third_party/closure-compiler/compiler.jar +++ b/third_party/closure-compiler/compiler.jar diff --git a/third_party/closure-compiler/readme.txt b/third_party/closure-compiler/readme.txt new file mode 100644 index 00000000..afc56ddc --- /dev/null +++ b/third_party/closure-compiler/readme.txt @@ -0,0 +1,3 @@ + +rev 2093, Jul 19 2012 + diff --git a/tools/file_packager.py b/tools/file_packager.py index 8c1e0a43..b02eac24 100644 --- a/tools/file_packager.py +++ b/tools/file_packager.py @@ -92,27 +92,10 @@ for arg in sys.argv[1:]: code = ''' function assert(check, msg) { - if (!check) throw msg; + if (!check) throw msg + new Error().stack; } ''' -if has_preloaded: - code += ''' - var BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : console.log("warning: cannot build blobs")); - var URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : console.log("warning: cannot create object URLs"); - var hasBlobConstructor; - try { - new Blob(); - hasBlobConstructor = true; - } catch(e) { - hasBlobConstructor = false; - console.log("warning: no blob constructor, cannot create blobs with mimetypes"); - } -''' - - code += 'Module["preloadedImages"] = {}; // maps url to image data\n' - code += 'Module["preloadedAudios"] = {}; // maps url to audio data\n' - # Expand directories into individual files def add(mode, dirname, names): for name in names: @@ -244,67 +227,12 @@ for file_ in data_files: # Preload varname = 'filePreload%d' % counter counter += 1 - image = filename.endswith(IMAGE_SUFFIXES) - audio = filename.endswith(AUDIO_SUFFIXES) dds = crunch and filename.endswith(CRUNCH_INPUT_SUFFIX) prepare = '' - finish = "Module['removeRunDependency']();\n" - - if image: - finish = ''' - var bb = new BlobBuilder(); - bb.append(byteArray.buffer); - var b = bb.getBlob(); - var url = URLObject.createObjectURL(b); - var img = new Image(); - img.onload = function() { - assert(img.complete, 'Image %(filename)s could not be decoded'); - var canvas = document.createElement('canvas'); - canvas.width = img.width; - canvas.height = img.height; - var ctx = canvas.getContext('2d'); - ctx.drawImage(img, 0, 0); - Module["preloadedImages"]['%(filename)s'] = canvas; - URLObject.revokeObjectURL(url); - Module['removeRunDependency'](); - }; - img.onerror = function(event) { - console.log('Image %(filename)s could not be decoded'); - }; - img.src = url; -''' % { 'filename': filename } - elif audio: - # Need actual blob constructor here, to set the mimetype or else audios fail to decode - finish = ''' - if (hasBlobConstructor) { - var b = new Blob([byteArray.buffer], { type: '%(mimetype)s' }); - var url = URLObject.createObjectURL(b); // XXX we never revoke this! - var audio = new Audio(); - audio.removedDependency = false; - audio['oncanplaythrough'] = function() { // XXX string for closure - audio['oncanplaythrough'] = null; - Module["preloadedAudios"]['%(filename)s'] = audio; - if (!audio.removedDependency) { - Module['removeRunDependency'](); - audio.removedDependency = true; - } - }; - audio.onerror = function(event) { - if (!audio.removedDependency) { - console.log('Audio %(filename)s could not be decoded or timed out trying to decode'); - Module['removeRunDependency'](); - audio.removedDependency = true; - } - }; - setTimeout(audio.onerror, 2000); // workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) - audio.src = url; - } else { - Module["preloadedAudios"]['%(filename)s'] = new Audio(); // empty shim - Module['removeRunDependency'](); - } -''' % { 'filename': filename, 'mimetype': AUDIO_MIMETYPES[suffix(filename)] } - elif dds: + finish = "Module['removeRunDependency']('fp %s');\n" % filename + + if dds: # decompress crunch format into dds prepare = ''' var ddsHeader = byteArray.subarray(0, %(dds_header_size)d); @@ -314,8 +242,7 @@ for file_ in data_files: byteArray.set(ddsData, %(dds_header_size)d); ''' % { 'filename': filename, 'dds_header_size': DDS_HEADER_SIZE } - finish = ''' - Module['removeRunDependency'](); + finish += ''' }); ''' @@ -328,10 +255,11 @@ for file_ in data_files: assert(arrayBuffer, 'Loading file %(filename)s failed.'); var byteArray = arrayBuffer.byteLength ? new Uint8Array(arrayBuffer) : arrayBuffer; %(prepare)s - Module['FS_createDataFile']('/%(dirname)s', '%(basename)s', byteArray, true, true); - %(finish)s + Module['FS_createPreloadedFile']('/%(dirname)s', '%(basename)s', byteArray, true, true, function() { + %(finish)s + }%(fail)s); }; - Module['addRunDependency'](); + Module['addRunDependency']('fp %(filename)s'); %(varname)s.send(null); ''' % { 'request': 'DataRequest', # In the past we also supported XHRs here @@ -340,7 +268,8 @@ for file_ in data_files: 'dirname': os.path.dirname(filename), 'basename': os.path.basename(filename), 'prepare': prepare, - 'finish': finish + 'finish': finish, + 'fail': '' if filename[-4:] not in AUDIO_SUFFIXES else ''', function() { Module['removeRunDependency']('fp %s') }''' % filename # workaround for chromium bug 124926 (still no audio with this, but at least we don't hang) } else: assert 0 @@ -355,7 +284,7 @@ if has_preloaded: curr.response = byteArray.subarray(%d,%d); curr.onload(); ''' % (file_['name'], file_['data_start'], file_['data_end']) - use_data += " Module['removeRunDependency']();\n" + use_data += " Module['removeRunDependency']('datafile');\n" if Compression.on: use_data = ''' @@ -376,7 +305,7 @@ if has_preloaded: var curr; %s }; - Module['addRunDependency'](); + Module['addRunDependency']('datafile'); dataFile.send(null); if (Module['setStatus']) Module['setStatus']('Downloading...'); ''' % (Compression.compressed_name(data_target) if Compression.on else data_target, use_data) |