aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/library.js117
-rw-r--r--src/library_browser.js107
-rw-r--r--src/library_sdl.js17
-rw-r--r--src/postamble.js1
-rw-r--r--src/preamble.js19
-rw-r--r--src/shell.html2
-rw-r--r--system/include/emscripten/emscripten.h24
-rw-r--r--tests/emscripten_fs_api_browser.cpp17
-rwxr-xr-xtests/runner.py63
-rw-r--r--third_party/closure-compiler/README2
-rw-r--r--third_party/closure-compiler/compiler.jarbin5378434 -> 5427247 bytes
-rw-r--r--third_party/closure-compiler/readme.txt3
-rw-r--r--tools/file_packager.py97
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
index d958a618..da191b01 100644
--- a/third_party/closure-compiler/compiler.jar
+++ b/third_party/closure-compiler/compiler.jar
Binary files differ
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)