blob: 6556d22c9b443305fba4e26437f1aaf25589a227 [file] [log] [blame]
// Copyright 2015 The Emscripten Authors. All rights reserved.
// Emscripten is available under two separate licenses, the MIT license and the
// University of Illinois/NCSA Open Source License. Both these licenses can be
// found in the LICENSE file.
var LibraryIDBStore = {
// A simple IDB-backed storage mechanism. Suitable for saving and loading large files asynchronously. This does
// *NOT* use the emscripten filesystem, intentionally, to avoid overhead. It lets you application define whatever
// filesystem-like layer you want, with the overhead 100% controlled by you. At the extremes, you could either
// just store large files, with almost no extra code; or you could implement a file b-tree using posix-compliant
// filesystem on top.
$IDBStore:
#include IDBStore.js
,
emscripten_idb_async_load: function(db, id, arg, onload, onerror) {
IDBStore.getFile(Pointer_stringify(db), Pointer_stringify(id), function(error, byteArray) {
if (error) {
if (onerror) Module['dynCall_vi'](onerror, arg);
return;
}
var buffer = _malloc(byteArray.length);
HEAPU8.set(byteArray, buffer);
Module['dynCall_viii'](onload, arg, buffer, byteArray.length);
_free(buffer);
});
},
emscripten_idb_async_store: function(db, id, ptr, num, arg, onstore, onerror) {
// note that we copy the data here, as these are async operatins - changes to HEAPU8 meanwhile should not affect us!
IDBStore.setFile(Pointer_stringify(db), Pointer_stringify(id), new Uint8Array(HEAPU8.subarray(ptr, ptr+num)), function(error) {
if (error) {
if (onerror) Module['dynCall_vi'](onerror, arg);
return;
}
if (onstore) Module['dynCall_vi'](onstore, arg);
});
},
emscripten_idb_async_delete: function(db, id, arg, ondelete, onerror) {
IDBStore.deleteFile(Pointer_stringify(db), Pointer_stringify(id), function(error) {
if (error) {
if (onerror) Module['dynCall_vi'](onerror, arg);
return;
}
if (ondelete) Module['dynCall_vi'](ondelete, arg);
});
},
emscripten_idb_async_exists: function(db, id, arg, oncheck, onerror) {
IDBStore.existsFile(Pointer_stringify(db), Pointer_stringify(id), function(error, exists) {
if (error) {
if (onerror) Module['dynCall_vi'](onerror, arg);
return;
}
if (oncheck) Module['dynCall_vii'](oncheck, arg, exists);
});
},
#if EMTERPRETIFY_ASYNC
emscripten_idb_load__deps: ['$EmterpreterAsync'],
emscripten_idb_load: function(db, id, pbuffer, pnum, perror) {
EmterpreterAsync.handle(function(resume) {
IDBStore.getFile(Pointer_stringify(db), Pointer_stringify(id), function(error, byteArray) {
if (error) {
{{{ makeSetValueAsm('perror', 0, '1', 'i32') }}};
resume();
return;
}
var buffer = _malloc(byteArray.length); // must be freed by the caller!
HEAPU8.set(byteArray, buffer);
{{{ makeSetValueAsm('pbuffer', 0, 'buffer', 'i32') }}};
{{{ makeSetValueAsm('pnum', 0, 'byteArray.length', 'i32') }}};
{{{ makeSetValueAsm('perror', 0, '0', 'i32') }}};
resume();
});
});
},
emscripten_idb_store__deps: ['$EmterpreterAsync'],
emscripten_idb_store: function(db, id, ptr, num, perror) {
EmterpreterAsync.handle(function(resume) {
IDBStore.setFile(Pointer_stringify(db), Pointer_stringify(id), new Uint8Array(HEAPU8.subarray(ptr, ptr+num)), function(error) {
{{{ makeSetValueAsm('perror', 0, '!!error', 'i32') }}};
resume();
});
});
},
emscripten_idb_delete__deps: ['$EmterpreterAsync'],
emscripten_idb_delete: function(db, id, perror) {
EmterpreterAsync.handle(function(resume) {
IDBStore.deleteFile(Pointer_stringify(db), Pointer_stringify(id), function(error) {
{{{ makeSetValueAsm('perror', 0, '!!error', 'i32') }}};
resume();
});
});
},
emscripten_idb_exists__deps: ['$EmterpreterAsync'],
emscripten_idb_exists: function(db, id, pexists, perror) {
EmterpreterAsync.handle(function(resume) {
IDBStore.existsFile(Pointer_stringify(db), Pointer_stringify(id), function(error, exists) {
{{{ makeSetValueAsm('pexists', 0, '!!exists', 'i32') }}};
{{{ makeSetValueAsm('perror', 0, '!!error', 'i32') }}};
resume();
});
});
},
// extra worker methods - proxied
emscripten_idb_load_blob__deps: ['$EmterpreterAsync'],
emscripten_idb_load_blob: function(db, id, pblob, perror) {
EmterpreterAsync.handle(function(resume) {
assert(!IDBStore.pending);
IDBStore.pending = function(msg) {
IDBStore.pending = null;
var blob = msg.blob;
if (!blob) {
{{{ makeSetValueAsm('perror', 0, '1', 'i32') }}};
resume();
return;
}
assert(blob instanceof Blob);
var blobId = IDBStore.blobs.length;
IDBStore.blobs.push(blob);
{{{ makeSetValueAsm('pblob', 0, 'blobId', 'i32') }}};
resume();
};
postMessage({
target: 'IDBStore',
method: 'loadBlob',
db: Pointer_stringify(db),
id: Pointer_stringify(id)
});
});
/*
EmterpreterAsync.handle(function(resume) {
IDBStore.getFile(Pointer_stringify(db), Pointer_stringify(id), function(error, blob) {
if (error) {
{{{ makeSetValueAsm('perror', 0, '1', 'i32') }}};
resume();
return;
}
assert(blob instanceof Blob);
var blobId = IDBStore.blobs.length;
IDBStore.blobs.push(blob);
{{{ makeSetValueAsm('pblob', 0, 'blobId', 'i32') }}};
resume();
});
});
*/
},
emscripten_idb_store_blob__deps: ['$EmterpreterAsync'],
emscripten_idb_store_blob: function(db, id, ptr, num, perror) {
EmterpreterAsync.handle(function(resume) {
assert(!IDBStore.pending);
IDBStore.pending = function(msg) {
IDBStore.pending = null;
{{{ makeSetValueAsm('perror', 0, '!!msg.error', 'i32') }}};
resume();
};
postMessage({
target: 'IDBStore',
method: 'storeBlob',
db: Pointer_stringify(db),
id: Pointer_stringify(id),
blob: new Blob([new Uint8Array(HEAPU8.subarray(ptr, ptr+num))])
});
});
/*
EmterpreterAsync.handle(function(resume) {
IDBStore.setFile(Pointer_stringify(db), Pointer_stringify(id), new Blob([new Uint8Array(HEAPU8.subarray(ptr, ptr+num))]), function(error) {
{{{ makeSetValueAsm('perror', 0, '!!error', 'i32') }}};
resume();
});
});
*/
},
emscripten_idb_read_from_blob__deps: ['$EmterpreterAsync'],
emscripten_idb_read_from_blob: function(blobId, start, num, buffer) {
var blob = IDBStore.blobs[blobId];
if (!blob) return 1;
if (start+num > blob.size) return 2;
var byteArray = (new FileReaderSync()).readAsArrayBuffer(blob.slice(start, start+num));
HEAPU8.set(new Uint8Array(byteArray), buffer);
return 0;
},
emscripten_idb_free_blob__deps: ['$EmterpreterAsync'],
emscripten_idb_free_blob: function(blobId) {
assert(IDBStore.blobs[blobId]);
IDBStore.blobs[blobId] = null;
},
#else
emscripten_idb_load: function() {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_load, etc.';
},
emscripten_idb_store: function() {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_store, etc.';
},
emscripten_idb_delete: function() {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_delete, etc.';
},
emscripten_idb_exists: function() {
throw 'Please compile your program with async support in order to use synchronous operations like emscripten_idb_exists, etc.';
},
#endif
};
autoAddDeps(LibraryIDBStore, '$IDBStore');
mergeInto(LibraryManager.library, LibraryIDBStore);