diff --git a/src/Platform_Web.c b/src/Platform_Web.c index 8bc0c8ca4..862404682 100644 --- a/src/Platform_Web.c +++ b/src/Platform_Web.c @@ -96,6 +96,7 @@ cc_uint64 Stopwatch_Measure(void) { /*########################################################################################################################* *-----------------------------------------------------Directory/File------------------------------------------------------* *#########################################################################################################################*/ +extern void interop_InitFilesystem(void); extern int interop_DirectoryCreate(const char* path, int perms); cc_result Directory_Create(const cc_string* path) { char str[NATIVE_STR_LEN]; @@ -427,19 +428,11 @@ EMSCRIPTEN_KEEPALIVE void Platform_LogError(const char* msg) { } extern void interop_InitModule(void); -extern void interop_GetIndexedDBError(char* buffer); - void Platform_Init(void) { - char tmp[64+1] = { 0 }; + interop_InitFilesystem(); interop_InitModule(); interop_InitSockets(); - /* Check if an error occurred when pre-loading IndexedDB */ - interop_GetIndexedDBError(tmp); - if (!tmp[0]) return; - - Chat_Add1("&cError preloading IndexedDB: %c", tmp); - Chat_AddRaw("&cPreviously saved settings/maps will be lost"); /* NOTE: You must pre-load IndexedDB before main() */ /* (because pre-loading only works asynchronously) */ /* If you don't, you'll get errors later trying to sync local to remote */ diff --git a/src/interop_web.js b/src/interop_web.js index 8f5ef9655..08b32112d 100644 --- a/src/interop_web.js +++ b/src/interop_web.js @@ -126,52 +126,58 @@ mergeInto(LibraryManager.library, { //######################################################################################################################## //--------------------------------------------------------Filesystem------------------------------------------------------ //######################################################################################################################## - interop_GetIndexedDBError: function(buffer) { - if (window.cc_idbErr) stringToUTF8(window.cc_idbErr, buffer, 64); - }, - interop_SaveNode: function (path) { - var callback = function(err) { - if (!err) return; - console.log(err); - ccall('Platform_LogError', 'void', ['string'], ['&cError saving ' + path]); - ccall('Platform_LogError', 'void', ['string'], [' &c' + err]); - }; + interop_InitFilesystem: function(buffer) { + // if interop_SaveNode is directly defined as a function, it is wrongly optimised + // out when compilingas the function is not directly referenced by any C code + Module.saveNode = function(path) { + var callback = function(err) { + if (!err) return; + console.log(err); + ccall('Platform_LogError', 'void', ['string'], ['&cError saving ' + path]); + ccall('Platform_LogError', 'void', ['string'], [' &c' + err]); + }; + + var stat, node, entry; + try { + var lookup = FS.lookupPath(path); + path = lookup.path; + node = lookup.node; + stat = node.node_ops.getattr(node); + } catch (err) { + return callback(err); + } + + if (FS.isDir(stat.mode)) { + entry = { timestamp: stat.mtime, mode: stat.mode }; + } else { + // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array. + // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB. + node.contents = MEMFS.getFileDataAsTypedArray(node); + entry = { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }; + } + + IDBFS.getDB('/classicube', function(err, db) { + if (err) return callback(err); + var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); + var store = transaction.objectStore(IDBFS.DB_STORE_NAME); + + transaction.onerror = function(e) { + callback(this.error); + e.preventDefault(); + }; + + var req = store.put(entry, path); + req.onsuccess = function() { callback(null); }; + req.onerror = function(e) { + callback(this.error); + e.preventDefault(); + }; + }); + }; - var stat, node, entry; - try { - var lookup = FS.lookupPath(path); - node = lookup.node; - stat = FS.stat(path); - } catch (err) { - return callback(err); - } - - if (FS.isDir(stat.mode)) { - entry = { timestamp: stat.mtime, mode: stat.mode }; - } else { - // Performance consideration: storing a normal JavaScript array to a IndexedDB is much slower than storing a typed array. - // Therefore always convert the file contents to a typed array first before writing the data to IndexedDB. - node.contents = MEMFS.getFileDataAsTypedArray(node); - entry = { timestamp: stat.mtime, mode: stat.mode, contents: node.contents }; - } - - IDBFS.getDB('/classicube', function(err, db) { - if (err) return callback(err); - var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite'); - var store = transaction.objectStore(IDBFS.DB_STORE_NAME); - - transaction.onerror = function(e) { - callback(this.error); - e.preventDefault(); - }; - - var req = store.put(entry, node.path); - req.onsuccess = function() { callback(null); }; - req.onerror = function(e) { - callback(this.error); - e.preventDefault(); - }; - }); + if (!window.cc_idbErr) return; + ccall('Platform_LogError', 'void', ['string'], ['&cError preloading IndexedDB:' + window.cc_idbErr]); + ccall('Platform_LogError', 'void', ['string'], ['&cPreviously saved settings/maps will be lost']); }, interop_DirectorySetWorking: function (raw) { var path = UTF8ToString(raw); @@ -187,7 +193,7 @@ mergeInto(LibraryManager.library, { var path = UTF8ToString(raw); try { FS.mkdir(path, mode, 0); - interop_SaveNode(path); + Module.saveNode(path); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e); @@ -269,8 +275,8 @@ mergeInto(LibraryManager.library, { try { var stream = FS.getStream(fd); FS.close(stream); - // save writable files to IndexedDB - if (stream.isWrite.get()) interop_SaveNode(stream.path); + // save writable files to IndexedDB (check for O_RDWR) + if ((stream.flags & 3) == 2) Module.saveNode(stream.path); return 0; } catch (e) { if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);