blob: 84321c1b0e8a5a3e036138476e563b2f6f48b6fd [file] [edit]
var WasmFSLibrary = {
$wasmFS$preloadedFiles: [],
$wasmFS$preloadedDirs: [],
#if USE_CLOSURE_COMPILER
// Declare variable for Closure, FS.createPreloadedFile() below calls Browser.handledByPreloadPlugin()
$FS__postset: '/**@suppress {duplicate, undefinedVars}*/var Browser;',
#endif
$FS__deps: [
'$wasmFS$preloadedFiles',
'$wasmFS$preloadedDirs',
'$asyncLoad',
],
$FS : {
// TODO: Clean up the following functions - currently copied from library_fs.js directly.
createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
// TODO: use WasmFS code to resolve and join the path here?
var fullname = name ? parent + '/' + name : parent;
var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
function processData(byteArray) {
function finish(byteArray) {
if (preFinish) preFinish();
if (!dontCreateFile) {
FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
}
if (onload) onload();
removeRunDependency(dep);
}
#if !MINIMAL_RUNTIME
if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {
if (onerror) onerror();
removeRunDependency(dep);
})) {
return;
}
#endif
finish(byteArray);
}
addRunDependency(dep);
if (typeof url == 'string') {
asyncLoad(url, (byteArray) => {
processData(byteArray);
}, onerror);
} else {
processData(url);
}
},
getMode: (canRead, canWrite) => {
var mode = 0;
if (canRead) mode |= {{{ cDefine('S_IRUGO') }}} | {{{ cDefine('S_IXUGO') }}};
if (canWrite) mode |= {{{ cDefine('S_IWUGO') }}};
return mode;
},
createDataFile: (parent, name, data, canRead, canWrite, canOwn) => {
// Data files must be cached until the file system itself has been initialized.
var mode = FS.getMode(canRead, canWrite);
var pathName = name ? parent + '/' + name : parent;
wasmFS$preloadedFiles.push({pathName: pathName, fileData: data, mode: mode});
},
createPath: (parent, path, canRead, canWrite) => {
// Cache file path directory names.
wasmFS$preloadedDirs.push({parentPath: parent, childName: path});
},
readFile: (path, opts) => {
opts = opts || {};
opts.encoding = opts.encoding || 'binary';
if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
throw new Error('Invalid encoding type "' + opts.encoding + '"');
}
var pathName = allocateUTF8(path);
// Copy the file into a JS buffer on the heap.
var buf = __wasmfs_read_file(pathName);
// The integer length is returned in the first 8 bytes of the buffer.
var length = {{{ makeGetValue('buf', '0', 'i64') }}};
// Default return type is binary.
// The buffer contents exist 8 bytes after the returned pointer.
var ret = new Uint8Array(HEAPU8.subarray(buf + 8, buf + 8 + length));
if (opts.encoding === 'utf8') {
ret = UTF8ArrayToString(ret, 0);
}
_free(pathName);
_free(buf);
return ret;
},
cwd: () => {
// TODO: Remove dependency on FS.cwd().
// User code should not be using FS.cwd().
// For file preloading, cwd should be '/' to begin with.
return '/';
},
#if FORCE_FILESYSTEM
// Full JS API support
mkdir: (path, mode) => {
mode = mode !== undefined ? mode : 511 /* 0777 */;
var buffer = allocateUTF8OnStack(path);
__wasmfs_mkdir(buffer, mode);
},
chdir: (path) => {
var buffer = allocateUTF8OnStack(path);
return __wasmfs_chdir(buffer);
},
writeFile: (path, data) => {
var pathBuffer = allocateUTF8OnStack(path);
var dataBuffer = _malloc(data);
__wasmfs_write_file(pathBuffer, dataBuffer, data.length);
_free(dataBuffer);
},
symlink: (target, linkpath) => {
var targetBuffer = allocateUTF8OnStack(target);
var linkpathBuffer = allocateUTF8OnStack(linkpath);
__wasmfs_symlink(targetBuffer, linkpathBuffer);
},
chmod: (path, mode) => {
var buffer = allocateUTF8OnStack(path);
return __wasmfs_chmod(buffer, mode);
},
#endif
},
_wasmfs_get_num_preloaded_files__deps: ['$wasmFS$preloadedFiles'],
_wasmfs_get_num_preloaded_files: function() {
return wasmFS$preloadedFiles.length;
},
_wasmfs_get_num_preloaded_dirs__deps: ['$wasmFS$preloadedDirs'],
_wasmfs_get_num_preloaded_dirs: function() {
return wasmFS$preloadedDirs.length;
},
_wasmfs_get_preloaded_file_mode: function(index) {
return wasmFS$preloadedFiles[index].mode;
},
_wasmfs_get_preloaded_parent_path: function(index, parentPathBuffer) {
var s = wasmFS$preloadedDirs[index].parentPath;
var len = lengthBytesUTF8(s) + 1;
stringToUTF8(s, parentPathBuffer, len);
},
_wasmfs_get_preloaded_child_path: function(index, childNameBuffer) {
var s = wasmFS$preloadedDirs[index].childName;
var len = lengthBytesUTF8(s) + 1;
stringToUTF8(s, childNameBuffer, len);
},
_wasmfs_get_preloaded_path_name: function(index, fileNameBuffer) {
var s = wasmFS$preloadedFiles[index].pathName;
var len = lengthBytesUTF8(s) + 1;
stringToUTF8(s, fileNameBuffer, len);
},
_wasmfs_get_preloaded_file_size: function(index) {
return wasmFS$preloadedFiles[index].fileData.length;
},
_wasmfs_copy_preloaded_file_data: function(index, buffer) {
HEAPU8.set(wasmFS$preloadedFiles[index].fileData, buffer);
},
// Backend support. wasmFS$backends will contain a mapping of backend IDs to
// the JS code that implements them. This is the JS side of the JSImpl* class
// in C++, together with the js_impl calls defined right after it.
$wasmFS$backends: {},
// JSImpl
_wasmfs_jsimpl_alloc_file: function(backend, file) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].allocFile(file);
},
_wasmfs_jsimpl_free_file: function(backend, file) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].freeFile(file);
},
_wasmfs_jsimpl_write: function(backend, file, buffer, length, {{{ defineI64Param('offset') }}}) {
{{{ receiveI64ParamAsDouble('offset') }}}
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].write(file, buffer, length, offset);
},
_wasmfs_jsimpl_read: function(backend, file, buffer, length, {{{ defineI64Param('offset') }}}) {
{{{ receiveI64ParamAsDouble('offset') }}}
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].read(file, buffer, length, offset);
},
_wasmfs_jsimpl_get_size: function(backend, file) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
return wasmFS$backends[backend].getSize(file);
},
// ProxiedAsyncJSImpl. Each function receives a function pointer and a
// parameter. We convert those into a convenient Promise API for the
// implementors of backends: the hooks we call should return Promises, which
// we then connect to the calling C++.
// TODO: arg is void*, which for MEMORY64 will be 64-bit. we need a way to
// declare arg in the function signature here (like defineI64Param,
// but that varies for wasm32/wasm64), and a way to do makeDynCall that
// adds a 'p' signature type for pointer, or something like that
// (however, dyncalls might also just work, given in MEMORY64 we assume
// WASM_BIGINT so the pointer is just a single argument, just like in
// wasm32).
_wasmfs_jsimpl_async_alloc_file: async function(backend, file, fptr, arg) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
{{{ runtimeKeepalivePush() }}}
await wasmFS$backends[backend].allocFile(file);
{{{ runtimeKeepalivePop() }}}
{{{ makeDynCall('vi', 'fptr') }}}(arg);
},
_wasmfs_jsimpl_async_free_file: async function(backend, file, fptr, arg) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
{{{ runtimeKeepalivePush() }}}
await wasmFS$backends[backend].freeFile(file);
{{{ runtimeKeepalivePop() }}}
{{{ makeDynCall('vi', 'fptr') }}}(arg);
},
_wasmfs_jsimpl_async_write: async function(backend, file, buffer, length, {{{ defineI64Param('offset') }}}, fptr, arg) {
{{{ receiveI64ParamAsDouble('offset') }}}
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
{{{ runtimeKeepalivePush() }}}
var size = await wasmFS$backends[backend].write(file, buffer, length, offset);
{{{ runtimeKeepalivePop() }}}
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.result, '0', 'i32') }}};
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.offset, 'size', 'i64') }}};
{{{ makeDynCall('vi', 'fptr') }}}(arg);
},
_wasmfs_jsimpl_async_read: async function(backend, file, buffer, length, {{{ defineI64Param('offset') }}}, fptr, arg) {
{{{ receiveI64ParamAsDouble('offset') }}}
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
{{{ runtimeKeepalivePush() }}}
var size = await wasmFS$backends[backend].read(file, buffer, length, offset);
{{{ runtimeKeepalivePop() }}}
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.result, '0', 'i32') }}};
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.offset, 'size', 'i64') }}};
{{{ makeDynCall('vi', 'fptr') }}}(arg);
},
_wasmfs_jsimpl_async_get_size: async function(backend, file, fptr, arg) {
#if ASSERTIONS
assert(wasmFS$backends[backend]);
#endif
{{{ runtimeKeepalivePush() }}}
var size = await wasmFS$backends[backend].getSize(file);
{{{ runtimeKeepalivePop() }}}
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.result, '0', 'i32') }}};
{{{ makeSetValue('arg', C_STRUCTS.CallbackState.offset, 'size', 'i64') }}};
{{{ makeDynCall('vi', 'fptr') }}}(arg);
},
}
mergeInto(LibraryManager.library, WasmFSLibrary);
DEFAULT_LIBRARY_FUNCS_TO_INCLUDE.push('$FS');