diff options
-rw-r--r-- | src/library_fs.js | 84 | ||||
-rw-r--r-- | tests/file_db.cpp | 47 | ||||
-rw-r--r-- | tests/test_browser.py | 11 |
3 files changed, 142 insertions, 0 deletions
diff --git a/src/library_fs.js b/src/library_fs.js index e1397356..9c8223ab 100644 --- a/src/library_fs.js +++ b/src/library_fs.js @@ -802,6 +802,90 @@ mergeInto(LibraryManager.library, { } }, + indexedDB: function() { + return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB; + }, + + DB_NAME: function() { + return 'EM_FS_' + window.location.pathname; + }, + DB_VERSION: 20, + DB_STORE_NAME: 'FILE_DATA', + + // asynchronously saves a list of files to an IndexedDB. The DB will be created if not already existing. + saveFilesToDB: function(paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = function() { + console.log('creating db'); + var db = openRequest.result; + db.createObjectStore(FS.DB_STORE_NAME); + }; + openRequest.onsuccess = function() { + var db = openRequest.result; + var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite'); + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var putRequest = files.put(FS.analyzePath(path).object.contents, path); + putRequest.onsuccess = function() { ok++; if (ok + fail == total) finish() }; + putRequest.onerror = function() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }, + + // asychronously loads a file from IndexedDB. + loadFilesFromDB: function(paths, onload, onerror) { + onload = onload || function(){}; + onerror = onerror || function(){}; + var indexedDB = FS.indexedDB(); + try { + var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION); + } catch (e) { + return onerror(e); + } + openRequest.onupgradeneeded = onerror; // no database to load from + openRequest.onsuccess = function() { + var db = openRequest.result; + try { + var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly'); + } catch(e) { + onerror(e); + return; + } + var files = transaction.objectStore(FS.DB_STORE_NAME); + var ok = 0, fail = 0, total = paths.length; + function finish() { + if (fail == 0) onload(); else onerror(); + } + paths.forEach(function(path) { + var getRequest = files.get(path); + getRequest.onsuccess = function() { + if (FS.analyzePath(path).exists) { + FS.unlink(path); + } + FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true); + ok++; + if (ok + fail == total) finish(); + }; + getRequest.onerror = function() { fail++; if (ok + fail == total) finish() }; + }); + transaction.onerror = onerror; + }; + openRequest.onerror = onerror; + }, + // // general // diff --git a/tests/file_db.cpp b/tests/file_db.cpp new file mode 100644 index 00000000..ebb3bb30 --- /dev/null +++ b/tests/file_db.cpp @@ -0,0 +1,47 @@ +#include <stdio.h> +#include <emscripten.h> + +void later(void *) {} + +int main() { +#if FIRST + FILE *f = fopen("waka.txt", "w"); + fputc('a', f); + fputc('z', f); + fclose(f); + + EM_ASM( + FS.saveFilesToDB(['waka.txt', 'moar.txt'], function() { + Module.print('save ok'); + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'http://localhost:8888/report_result?1'); + xhr.send(); + setTimeout(function() { window.close() }, 1000); + }, function(e) { + abort('saving should succeed ' + e); + }); + ); +#else + EM_ASM( + FS.loadFilesFromDB(['waka.txt', 'moar.txt'], function() { + function stringy(arr) { + return Array.prototype.map.call(arr, function(x) { return String.fromCharCode(x) }).join(''); + } + assert(stringy(FS.analyzePath('waka.txt').object.contents) == 'az'); + var secret = stringy(FS.analyzePath('moar.txt').object.contents); + Module.print('load: ' + secret); + var xhr = new XMLHttpRequest(); + xhr.open('GET', 'http://localhost:8888/report_result?' + secret); + xhr.send(); + setTimeout(function() { window.close() }, 1000); + }, function() { + abort('loading should succeed'); + }); + ); +#endif + + emscripten_async_call(later, NULL, 100); // keep runtime alive + + return 0; +} + diff --git a/tests/test_browser.py b/tests/test_browser.py index 1c9cbfad..32b29966 100644 --- a/tests/test_browser.py +++ b/tests/test_browser.py @@ -794,6 +794,17 @@ If manually bisecting: def test_glut_touchevents(self): self.btest('glut_touchevents.c', '1') + def test_file_db(self): + secret = str(time.time()) + open('moar.txt', 'w').write(secret) + self.btest('file_db.cpp', '1', args=['--preload-file', 'moar.txt', '-DFIRST']) + shutil.copyfile('test.html', 'first.html') + self.btest('file_db.cpp', secret) + shutil.copyfile('test.html', 'second.html') + open('moar.txt', 'w').write('aliantha') + self.btest('file_db.cpp', secret, args=['--preload-file', 'moar.txt']) # even with a file there, we load over it + shutil.move('test.html', 'third.html') + def test_sdl_pumpevents(self): # key events should be detected using SDL_PumpEvents open(os.path.join(self.get_dir(), 'pre.js'), 'w').write(''' |