| /** |
| * @license |
| * Copyright 2022 The Emscripten Authors |
| * SPDX-License-Identifier: MIT |
| */ |
| |
| addToLibrary({ |
| $MEMFS__deps: ['wasmfs_create_memory_backend'], |
| $MEMFS: { |
| createBackend(opts) { |
| return _wasmfs_create_memory_backend(); |
| } |
| }, |
| $wasmFSPreloadedFiles: [], |
| $wasmFSPreloadedDirs: [], |
| // We must note when preloading has been "flushed", that is, the time at which |
| // WasmFS has started up and read the preloaded data. After that time, no more |
| // data needs to be preloaded (and it would be invalid to do so, as any |
| // further additions to wasmFSPreloadedFiles|Dirs would be ignored). |
| $wasmFSPreloadingFlushed: false, |
| $wasmFSDevices: {}, |
| $wasmFSDeviceStreams: {}, |
| |
| $FS__deps: [ |
| '$MEMFS', |
| '$wasmFSPreloadedFiles', |
| '$wasmFSPreloadedDirs', |
| '$wasmFSPreloadingFlushed', |
| '$PATH', |
| '$stringToUTF8OnStack', |
| '$withStackSave', |
| '$readI53FromI64', |
| '$readI53FromU64', |
| '$FS_createDataFile', |
| '$FS_createPreloadedFile', |
| '$FS_getMode', |
| // For FS.readFile |
| '$UTF8ArrayToString', |
| #if FORCE_FILESYSTEM || INCLUDE_FULL_LIBRARY // FULL_LIBRARY will include JS |
| // code in other places that ends |
| // up requiring all of our code |
| // here. |
| '$FS_modeStringToFlags', |
| '$FS_create', |
| '$FS_mknod', |
| '$FS_mkdir', |
| '$FS_mkdirTree', |
| '$FS_writeFile', |
| '$FS_unlink', |
| #if LibraryManager.has('libicasefs.js') |
| '$ICASEFS', |
| #endif |
| #if LibraryManager.has('libnodefs.js') |
| '$NODEFS', |
| #endif |
| #if LibraryManager.has('libopfs.js') |
| '$OPFS', |
| #endif |
| #if LibraryManager.has('libjsfilefs.js') |
| '$JSFILEFS', |
| #endif |
| #if LibraryManager.has('libfetchfs.js') |
| '$FETCHFS', |
| #endif |
| 'malloc', |
| 'free', |
| 'wasmfs_create_jsimpl_backend', |
| '$wasmFS$backends', |
| '$wasmFSDevices', |
| '$wasmFSDeviceStreams' |
| #endif |
| ], |
| $FS : { |
| ErrnoError: class extends Error { |
| name = 'ErrnoError'; |
| message = 'FS error'; |
| constructor(code) { |
| super(); |
| this.errno = code |
| } |
| }, |
| handleError(returnValue) { |
| // Assume errors correspond to negative returnValues |
| // since some functions like _wasmfs_open() return positive |
| // numbers on success (some callers of this function may need to negate the parameter). |
| if (returnValue < 0) { |
| throw new FS.ErrnoError(-returnValue); |
| } |
| |
| return returnValue; |
| }, |
| createDataFile(parent, name, fileData, canRead, canWrite, canOwn) { |
| FS_createDataFile(parent, name, fileData, canRead, canWrite, canOwn); |
| }, |
| createPath(parent, path, canRead, canWrite) { |
| // Cache file path directory names. |
| var parts = path.split('/').reverse(); |
| while (parts.length) { |
| var part = parts.pop(); |
| if (!part) continue; |
| var current = PATH.join2(parent, part); |
| if (!wasmFSPreloadingFlushed) { |
| wasmFSPreloadedDirs.push({parentPath: parent, childName: part}); |
| } else { |
| try { |
| FS.mkdir(current); |
| } catch (e) { |
| if (e.errno != {{{ cDefs.EEXIST }}}) throw e; |
| } |
| } |
| parent = current; |
| } |
| return current; |
| }, |
| |
| createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) { |
| return FS_createPreloadedFile(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish); |
| }, |
| |
| #if hasExportedSymbol('_wasmfs_read_file') // Support the JS function exactly |
| // when the __wasmfs_* function is |
| // present to be called (otherwise, |
| // we'd error anyhow). This depends |
| // on other code including the |
| // __wasmfs_* method properly. |
| readFile(path, opts = {}) { |
| opts.encoding = opts.encoding || 'binary'; |
| if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') { |
| throw new Error(`Invalid encoding type "${opts.encoding}"`); |
| } |
| |
| var buf, length; |
| // Copy the file into a JS buffer on the heap. |
| withStackSave(() => { |
| var bufPtr = stackAlloc({{{ POINTER_SIZE }}}); |
| var sizePtr = stackAlloc({{{ POINTER_SIZE }}}); |
| FS.handleError(-__wasmfs_read_file(stringToUTF8OnStack(path), bufPtr, sizePtr)); |
| buf = {{{ makeGetValue('bufPtr', '0', '*') }}}; |
| length = {{{ makeGetValue('sizePtr', '0', 'i53') }}}; |
| }); |
| |
| // Default return type is binary. |
| // The buffer contents exist 8 bytes after the returned pointer. |
| return opts.encoding === 'utf8' ? UTF8ToString(buf, length) : HEAPU8.slice(buf, buf + length); |
| }, |
| #endif |
| |
| #if hasExportedSymbol('_wasmfs_get_cwd') // Similar to readFile, above. |
| cwd: () => UTF8ToString(__wasmfs_get_cwd()), |
| #endif |
| |
| #if FORCE_FILESYSTEM || INCLUDE_FULL_LIBRARY // see comment above |
| // Full JS API support |
| |
| analyzePath(path) { |
| // TODO: Consider simplifying this API, which for now matches the JS FS. |
| var exists = !!FS.findObject(path); |
| return { |
| exists, |
| object: { |
| contents: exists ? FS.readFile(path) : null |
| } |
| }; |
| }, |
| |
| // libc methods |
| |
| mkdir: (path, mode) => FS_mkdir(path, mode), |
| mkdirTree: (path, mode) => FS_mkdirTree(path, mode), |
| rmdir: (path) => FS.handleError( |
| withStackSave(() => __wasmfs_rmdir(stringToUTF8OnStack(path))) |
| ), |
| open: (path, flags, mode = 0o666) => withStackSave(() => { |
| flags = typeof flags == 'string' ? FS_modeStringToFlags(flags) : flags; |
| var buffer = stringToUTF8OnStack(path); |
| var fd = FS.handleError(__wasmfs_open(buffer, flags, mode)); |
| return { fd : fd }; |
| }), |
| create: (path, mode) => FS_create(path, mode), |
| close: (stream) => FS.handleError(-__wasmfs_close(stream.fd)), |
| unlink: (path) => FS_unlink(path), |
| chdir: (path) => withStackSave(() => __wasmfs_chdir(stringToUTF8OnStack(path))), |
| read(stream, buffer, offset, length, position) { |
| var seeking = typeof position != 'undefined'; |
| |
| var dataBuffer = _malloc(length); |
| |
| var bytesRead; |
| if (seeking) { |
| bytesRead = __wasmfs_pread(stream.fd, dataBuffer, length, {{{ splitI64('position') }}}); |
| } else { |
| bytesRead = __wasmfs_read(stream.fd, dataBuffer, length); |
| } |
| if (bytesRead > 0) { |
| buffer.set(HEAPU8.subarray(dataBuffer, dataBuffer + bytesRead), offset); |
| } |
| |
| _free(dataBuffer); |
| return FS.handleError(bytesRead); |
| }, |
| // Note that canOwn is an optimization that we ignore for now in WasmFS. |
| write(stream, buffer, offset, length, position, canOwn) { |
| var seeking = typeof position != 'undefined'; |
| |
| var dataBuffer = _malloc(length); |
| for (var i = 0; i < length; i++) { |
| {{{ makeSetValue('dataBuffer', 'i', 'buffer[offset + i]', 'i8') }}}; |
| } |
| |
| var bytesRead; |
| if (seeking) { |
| bytesRead = __wasmfs_pwrite(stream.fd, dataBuffer, length, {{{ splitI64('position') }}}); |
| } else { |
| bytesRead = __wasmfs_write(stream.fd, dataBuffer, length); |
| } |
| _free(dataBuffer); |
| return FS.handleError(bytesRead); |
| }, |
| writeFile: (path, data) => FS_writeFile(path, data), |
| mmap: (stream, length, offset, prot, flags) => { |
| var buf = FS.handleError(__wasmfs_mmap(length, prot, flags, stream.fd, {{{ splitI64('offset') }}})); |
| return { ptr: buf, allocated: true }; |
| }, |
| // offset is passed to msync to maintain backwards compatibility with the legacy JS API but is not used by WasmFS. |
| msync: (stream, bufferPtr, offset, length, mmapFlags) => { |
| assert(offset === 0); |
| // TODO: assert that stream has the fd corresponding to the mapped buffer (bufferPtr). |
| return FS.handleError(__wasmfs_msync(bufferPtr, length, mmapFlags)); |
| }, |
| munmap: (addr, length) => ( |
| FS.handleError(__wasmfs_munmap(addr, length)) |
| ), |
| symlink: (target, linkpath) => withStackSave(() => ( |
| __wasmfs_symlink(stringToUTF8OnStack(target), stringToUTF8OnStack(linkpath)) |
| )), |
| readlink(path) { |
| return withStackSave(() => { |
| var bufPtr = stackAlloc({{{ POINTER_SIZE }}}); |
| FS.handleError(__wasmfs_readlink(stringToUTF8OnStack(path), bufPtr)); |
| var readBuffer = {{{ makeGetValue('bufPtr', '0', '*') }}}; |
| return UTF8ToString(readBuffer); |
| }); |
| }, |
| statBufToObject(statBuf) { |
| // i53/u53 are enough for times and ino in practice. |
| return { |
| dev: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_dev, "u32") }}}, |
| mode: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_mode, "u32") }}}, |
| nlink: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_nlink, "u32") }}}, |
| uid: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_uid, "u32") }}}, |
| gid: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_gid, "u32") }}}, |
| rdev: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_rdev, "u32") }}}, |
| size: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_size, "i53") }}}, |
| blksize: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_blksize, "u32") }}}, |
| blocks: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_blocks, "u32") }}}, |
| atime: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_atim.tv_sec, "i53") }}}, |
| mtime: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_mtim.tv_sec, "i53") }}}, |
| ctime: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_ctim.tv_sec, "i53") }}}, |
| ino: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_ino, "u53") }}} |
| } |
| }, |
| stat(path) { |
| return withStackSave(() => { |
| var statBuf = stackAlloc({{{ C_STRUCTS.stat.__size__ }}}); |
| FS.handleError(__wasmfs_stat(stringToUTF8OnStack(path), statBuf)); |
| return FS.statBufToObject(statBuf); |
| }); |
| }, |
| lstat(path) { |
| return withStackSave(() => { |
| var statBuf = stackAlloc({{{ C_STRUCTS.stat.__size__ }}}); |
| FS.handleError(__wasmfs_lstat(stringToUTF8OnStack(path), statBuf)); |
| return FS.statBufToObject(statBuf); |
| }); |
| }, |
| chmod(path, mode) { |
| return FS.handleError(withStackSave(() => { |
| var buffer = stringToUTF8OnStack(path); |
| return __wasmfs_chmod(buffer, mode); |
| })); |
| }, |
| lchmod(path, mode) { |
| return FS.handleError(withStackSave(() => { |
| var buffer = stringToUTF8OnStack(path); |
| return __wasmfs_lchmod(buffer, mode); |
| })); |
| }, |
| fchmod(fd, mode) { |
| return FS.handleError(__wasmfs_fchmod(fd, mode)); |
| }, |
| utime: (path, atime, mtime) => ( |
| FS.handleError(withStackSave(() => ( |
| __wasmfs_utime(stringToUTF8OnStack(path), atime, mtime) |
| ))) |
| ), |
| truncate(path, len) { |
| return FS.handleError(withStackSave(() => (__wasmfs_truncate(stringToUTF8OnStack(path), {{{ splitI64('len') }}})))); |
| }, |
| ftruncate(fd, len) { |
| return FS.handleError(__wasmfs_ftruncate(fd, {{{ splitI64('len') }}})); |
| }, |
| findObject(path) { |
| var result = withStackSave(() => __wasmfs_identify(stringToUTF8OnStack(path))); |
| if (result == {{{ cDefs.ENOENT }}}) { |
| return null; |
| } |
| return { |
| isFolder: result == {{{ cDefs.EISDIR }}}, |
| isDevice: false, // TODO: wasmfs support for devices |
| }; |
| }, |
| readdir: (path) => withStackSave(() => { |
| var pathBuffer = stringToUTF8OnStack(path); |
| var entries = []; |
| var state = __wasmfs_readdir_start(pathBuffer); |
| if (!state) { |
| // TODO: The old FS threw an ErrnoError here. |
| throw new Error("No such directory"); |
| } |
| var entry; |
| while (entry = __wasmfs_readdir_get(state)) { |
| entries.push(UTF8ToString(entry)); |
| } |
| __wasmfs_readdir_finish(state); |
| return entries; |
| }), |
| mount: (type, opts, mountpoint) => { |
| #if ASSERTIONS |
| if (typeof type == 'string') { |
| // The filesystem was not included, and instead we have an error |
| // message stored in the variable. |
| throw type; |
| } |
| #endif |
| var backendPointer = type.createBackend(opts); |
| return FS.handleError(withStackSave(() => __wasmfs_mount(stringToUTF8OnStack(mountpoint), backendPointer))); |
| }, |
| unmount: (mountpoint) => ( |
| FS.handleError(withStackSave(() => _wasmfs_unmount(stringToUTF8OnStack(mountpoint)))) |
| ), |
| // TODO: lookup |
| mknod: (path, mode, dev) => FS_mknod(path, mode, dev), |
| makedev: (ma, mi) => ((ma) << 8 | (mi)), |
| registerDevice(dev, ops) { |
| var backendPointer = _wasmfs_create_jsimpl_backend(); |
| var definedOps = { |
| userRead: ops.read, |
| userWrite: ops.write, |
| |
| allocFile: (file) => { |
| wasmFSDeviceStreams[file] = {} |
| }, |
| freeFile: (file) => { |
| wasmFSDeviceStreams[file] = undefined; |
| }, |
| getSize: (file) => {}, |
| // Devices cannot be resized. |
| setSize: (file, size) => 0, |
| read: (file, buffer, length, offset) => { |
| var bufferArray = HEAP8.subarray(buffer, buffer + length); |
| try { |
| var bytesRead = definedOps.userRead(wasmFSDeviceStreams[file], bufferArray, 0, length, offset); |
| } catch (e) { |
| return -e.errno; |
| } |
| HEAP8.set(bufferArray, buffer); |
| return bytesRead; |
| }, |
| write: (file, buffer, length, offset) => { |
| var bufferArray = HEAP8.subarray(buffer, buffer + length); |
| try { |
| var bytesWritten = definedOps.userWrite(wasmFSDeviceStreams[file], bufferArray, 0, length, offset); |
| } catch (e) { |
| return -e.errno; |
| } |
| HEAP8.set(bufferArray, buffer); |
| return bytesWritten; |
| }, |
| }; |
| |
| wasmFS$backends[backendPointer] = definedOps; |
| wasmFSDevices[dev] = backendPointer; |
| }, |
| createDevice(parent, name, input, output) { |
| if (typeof parent != 'string') { |
| // The old API allowed parents to be objects, which do not exist in WasmFS. |
| throw new Error("Only string paths are accepted"); |
| } |
| var path = PATH.join2(parent, name); |
| var mode = FS_getMode(!!input, !!output); |
| FS.createDevice.major ??= 64; |
| var dev = FS.makedev(FS.createDevice.major++, 0); |
| // Create a fake device with a set of stream ops to emulate |
| // the old API's createDevice(). |
| FS.registerDevice(dev, { |
| read(stream, buffer, offset, length, pos /* ignored */) { |
| var bytesRead = 0; |
| for (var i = 0; i < length; i++) { |
| var result; |
| try { |
| result = input(); |
| } catch (e) { |
| throw new FS.ErrnoError({{{ cDefs.EIO }}}); |
| } |
| if (result === undefined && bytesRead === 0) { |
| throw new FS.ErrnoError({{{ cDefs.EAGAIN }}}); |
| } |
| if (result === null || result === undefined) break; |
| bytesRead++; |
| buffer[offset+i] = result; |
| } |
| return bytesRead; |
| }, |
| write(stream, buffer, offset, length, pos) { |
| for (var i = 0; i < length; i++) { |
| try { |
| output(buffer[offset+i]); |
| } catch (e) { |
| throw new FS.ErrnoError({{{ cDefs.EIO }}}); |
| } |
| } |
| return i; |
| } |
| }); |
| return FS.mkdev(path, mode, dev); |
| }, |
| // mode is an optional argument, which will be set to 0666 if not passed in. |
| mkdev(path, mode, dev) { |
| if (typeof dev === 'undefined') { |
| dev = mode; |
| mode = 0o666; |
| } |
| |
| var deviceBackend = wasmFSDevices[dev]; |
| if (!deviceBackend) { |
| throw new Error("Invalid device ID."); |
| } |
| |
| return FS.handleError(withStackSave(() => ( |
| _wasmfs_create_file(stringToUTF8OnStack(path), mode, deviceBackend) |
| ))); |
| }, |
| rename(oldPath, newPath) { |
| return FS.handleError(withStackSave(() => { |
| var oldPathBuffer = stringToUTF8OnStack(oldPath); |
| var newPathBuffer = stringToUTF8OnStack(newPath); |
| return __wasmfs_rename(oldPathBuffer, newPathBuffer); |
| })); |
| }, |
| // TODO: syncfs |
| llseek(stream, offset, whence) { |
| return FS.handleError(__wasmfs_llseek(stream.fd, {{{ splitI64('offset') }}}, whence)); |
| } |
| // TODO: ioctl |
| |
| #endif |
| }, |
| |
| // Split-out FS.* methods. These are split out for code size reasons, so that |
| // we can include the ones we need on demand, rather than put them all on the |
| // main FS object. As a result the entire FS object is not needed if you just |
| // need some specific FS_* operations. When the FS object is present, it calls |
| // into those FS_* methods as needed. |
| // |
| // In contrast, the old JS FS (libfs.js) does the opposite: it puts all |
| // things on the FS object, and copies them to FS_* methods for use from JS |
| // library code. Given that the JS FS is implemented entirely in JS, that |
| // makes sense there (as almost all that FS object ends up needed anyhow all |
| // the time). |
| |
| $FS_createDataFile__deps: [ |
| '$wasmFSPreloadingFlushed', '$wasmFSPreloadedFiles', |
| '$FS_create', '$FS_writeFile', |
| ], |
| $FS_createDataFile: (parent, name, fileData, canRead, canWrite, canOwn) => { |
| var pathName = name ? parent + '/' + name : parent; |
| var mode = FS_getMode(canRead, canWrite); |
| |
| if (!wasmFSPreloadingFlushed) { |
| // WasmFS code in the wasm is not ready to be called yet. Cache the |
| // files we want to create here in JS, and WasmFS will read them |
| // later. |
| wasmFSPreloadedFiles.push({pathName, fileData, mode}); |
| } else { |
| // WasmFS is already running, so create the file normally. |
| FS_create(pathName, mode); |
| FS_writeFile(pathName, fileData); |
| } |
| }, |
| |
| $FS_mknod__deps: ['_wasmfs_mknod'], |
| $FS_mknod: (path, mode, dev) => FS.handleError(withStackSave(() => { |
| var pathBuffer = stringToUTF8OnStack(path); |
| return __wasmfs_mknod(pathBuffer, mode, dev); |
| })), |
| |
| $FS_create__deps: ['$FS_mknod'], |
| // Default settings copied from the legacy JS FS API. |
| $FS_create: (path, mode = 0o666) => { |
| mode &= {{{ cDefs.S_IALLUGO }}}; |
| mode |= {{{ cDefs.S_IFREG }}}; |
| return FS_mknod(path, mode, 0); |
| }, |
| |
| $FS_writeFile__deps: ['_wasmfs_write_file', '$stackSave', '$stackRestore', 'malloc', 'free'], |
| $FS_writeFile: (path, data) => { |
| var sp = stackSave(); |
| var pathBuffer = stringToUTF8OnStack(path); |
| var len = typeof data == 'string' ? lengthBytesUTF8(data) + 1 : data.length; |
| var dataBuffer = _malloc(len); |
| #if ASSERTIONS |
| assert(dataBuffer); |
| #endif |
| if (typeof data == 'string') { |
| len = stringToUTF8(data, dataBuffer, len); |
| } else { |
| HEAPU8.set(data, dataBuffer); |
| } |
| var ret = __wasmfs_write_file(pathBuffer, dataBuffer, len); |
| _free(dataBuffer); |
| stackRestore(sp); |
| return ret; |
| }, |
| |
| $FS_mkdir__deps: ['_wasmfs_mkdir'], |
| $FS_mkdir: (path, mode = 0o777) => FS.handleError(withStackSave(() => { |
| var buffer = stringToUTF8OnStack(path); |
| return __wasmfs_mkdir(buffer, mode); |
| })), |
| |
| $FS_mkdirTree__docs: ` |
| /** |
| * @param {number=} mode Optionally, the mode to create in. Uses mkdir's |
| * default if not set. |
| */`, |
| $FS_mkdirTree__deps: ['$FS_mkdir'], |
| $FS_mkdirTree: (path, mode) => { |
| var dirs = path.split('/'); |
| var d = ''; |
| for (var dir of dirs) { |
| if (!dir) continue; |
| if (d || PATH.isAbs(path)) d += '/'; |
| d += dir; |
| try { |
| FS_mkdir(d, mode); |
| } catch(e) { |
| if (e.errno != {{{ cDefs.EEXIST }}}) throw e; |
| } |
| } |
| }, |
| |
| $FS_unlink__deps: ['_wasmfs_unlink'], |
| $FS_unlink: (path) => withStackSave(() => { |
| var buffer = stringToUTF8OnStack(path); |
| return __wasmfs_unlink(buffer); |
| }), |
| |
| // Wasm access calls. |
| |
| _wasmfs_get_num_preloaded_files__deps: [ |
| '$wasmFSPreloadedFiles', |
| '$wasmFSPreloadingFlushed'], |
| _wasmfs_get_num_preloaded_files: () => { |
| // When this method is called from WasmFS it means that we are about to |
| // flush all the preloaded data, so mark that. (There is no call that |
| // occurs at the end of that flushing, which would be more natural, but it |
| // is fine to mark the flushing here as during the flushing itself no user |
| // code can run, so nothing will check whether we have flushed or not.) |
| wasmFSPreloadingFlushed = true; |
| return wasmFSPreloadedFiles.length; |
| }, |
| _wasmfs_get_num_preloaded_dirs__deps: ['$wasmFSPreloadedDirs'], |
| _wasmfs_get_num_preloaded_dirs: () => wasmFSPreloadedDirs.length, |
| _wasmfs_get_preloaded_file_mode: (index) => wasmFSPreloadedFiles[index].mode, |
| _wasmfs_get_preloaded_parent_path: (index, parentPathBuffer) => { |
| var s = wasmFSPreloadedDirs[index].parentPath; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, parentPathBuffer, len); |
| }, |
| _wasmfs_get_preloaded_child_path: (index, childNameBuffer) => { |
| var s = wasmFSPreloadedDirs[index].childName; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, childNameBuffer, len); |
| }, |
| _wasmfs_get_preloaded_path_name__deps: ['$lengthBytesUTF8', '$stringToUTF8'], |
| _wasmfs_get_preloaded_path_name: (index, fileNameBuffer) => { |
| var s = wasmFSPreloadedFiles[index].pathName; |
| var len = lengthBytesUTF8(s) + 1; |
| stringToUTF8(s, fileNameBuffer, len); |
| }, |
| _wasmfs_get_preloaded_file_size: (index) => |
| wasmFSPreloadedFiles[index].fileData.length, |
| _wasmfs_copy_preloaded_file_data: (index, buffer) => |
| HEAPU8.set(wasmFSPreloadedFiles[index].fileData, buffer), |
| |
| _wasmfs_thread_utils_heartbeat__deps: ['emscripten_proxy_execute_queue'], |
| _wasmfs_thread_utils_heartbeat: (queue) => { |
| var intervalID = |
| setInterval(() => { |
| if (ABORT) { |
| clearInterval(intervalID); |
| } else { |
| _emscripten_proxy_execute_queue(queue); |
| } |
| }, 50); |
| }, |
| |
| _wasmfs_stdin_get_char__deps: ['$FS_stdin_getChar'], |
| _wasmfs_stdin_get_char: () => { |
| // Return the read character, or -1 to indicate EOF. |
| var c = FS_stdin_getChar(); |
| if (typeof c === 'number') { |
| return c; |
| } |
| return -1; |
| } |
| }); |