Buckets:
| /** | |
| * @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_preloadFile', | |
| '$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); | |
| }, | |
| async preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) { | |
| return FS_preloadFile(parent, name, url, canRead, canWrite, 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 = FS_modeStringToFlags(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) => { | |
| #if ASSERTIONS | |
| assert(offset === 0); | |
| #endif | |
| // 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, SIZE_TYPE) }}}, | |
| 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, "i32") }}}, | |
| blocks: {{{ makeGetValue('statBuf', C_STRUCTS.stat.st_blocks, "i32") }}}, | |
| 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: ['$FS_fileDataToTypedArray', '_wasmfs_write_file', '$stackSave', '$stackRestore', 'malloc', 'free'], | |
| $FS_writeFile: (path, data) => { | |
| var sp = stackSave(); | |
| var pathBuffer = stringToUTF8OnStack(path); | |
| data = FS_fileDataToTypedArray(data); | |
| var len = data.length; | |
| var dataBuffer = _malloc(len); | |
| #if ASSERTIONS | |
| assert(dataBuffer); | |
| #endif | |
| 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; | |
| } | |
| }); | |
Xet Storage Details
- Size:
- 22.4 kB
- Xet hash:
- f9b522923cd4e66ac535ad2660a8498958aca394ee35a565a517d15a37574027
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.