Buckets:
| /** | |
| * @license | |
| * Copyright 2019 The Emscripten Authors | |
| * SPDX-License-Identifier: MIT | |
| */ | |
| var WasiLibrary = { | |
| #if !MINIMAL_RUNTIME | |
| $ExitStatus: class { | |
| name = 'ExitStatus'; | |
| constructor(status) { | |
| this.message = `Program terminated with exit(${status})`; | |
| this.status = status; | |
| } | |
| }, | |
| proc_exit__deps: ['$ExitStatus', '$keepRuntimeAlive'], | |
| #endif | |
| proc_exit__nothrow: true, | |
| proc_exit: (code) => { | |
| #if MINIMAL_RUNTIME | |
| throw `exit(${code})`; | |
| #else | |
| #if RUNTIME_DEBUG | |
| dbg(`proc_exit: ${code}`); | |
| #endif | |
| EXITSTATUS = code; | |
| if (!keepRuntimeAlive()) { | |
| #if PTHREADS | |
| PThread.terminateAllThreads(); | |
| #endif | |
| #if expectToReceiveOnModule('onExit') | |
| Module['onExit']?.(code); | |
| #endif | |
| ABORT = true; | |
| } | |
| quit_(code, new ExitStatus(code)); | |
| #endif // MINIMAL_RUNTIME | |
| }, | |
| sched_yield__nothrow: true, | |
| sched_yield: () => 0, | |
| $getEnvStrings__deps: ['$ENV', | |
| #if !PURE_WASI | |
| '$getExecutableName' | |
| #endif | |
| ], | |
| $getEnvStrings: () => { | |
| if (!getEnvStrings.strings) { | |
| // Default values. | |
| var lang = (globalThis.navigator?.language ?? 'C').replace('-', '_') + '.UTF-8'; | |
| var env = { | |
| #if !PURE_WASI | |
| 'USER': 'web_user', | |
| 'LOGNAME': 'web_user', | |
| 'PATH': '/', | |
| 'PWD': '/', | |
| 'HOME': '/home/web_user', | |
| 'LANG': lang, | |
| '_': getExecutableName() | |
| #endif | |
| }; | |
| #if ENVIRONMENT_MAY_BE_NODE && NODE_HOST_ENV | |
| if (ENVIRONMENT_IS_NODE) { | |
| // When NODE_HOST_ENV is enabled we mirror the entire host environment. | |
| env = process.env; | |
| } | |
| #endif | |
| // Apply the user-provided values, if any. | |
| for (var x in ENV) { | |
| // x is a key in ENV; if ENV[x] is undefined, that means it was | |
| // explicitly set to be so. We allow user code to do that to | |
| // force variables with default values to remain unset. | |
| if (ENV[x] === undefined) delete env[x]; | |
| else env[x] = ENV[x]; | |
| } | |
| var strings = []; | |
| for (var x in env) { | |
| strings.push(`${x}=${env[x]}`); | |
| } | |
| getEnvStrings.strings = strings; | |
| } | |
| return getEnvStrings.strings; | |
| }, | |
| environ_sizes_get__deps: ['$getEnvStrings', '$lengthBytesUTF8'], | |
| environ_sizes_get__nothrow: true, | |
| environ_sizes_get: (penviron_count, penviron_buf_size) => { | |
| var strings = getEnvStrings(); | |
| {{{ makeSetValue('penviron_count', 0, 'strings.length', SIZE_TYPE) }}}; | |
| var bufSize = 0; | |
| for (var string of strings) { | |
| bufSize += lengthBytesUTF8(string) + 1; | |
| } | |
| {{{ makeSetValue('penviron_buf_size', 0, 'bufSize', SIZE_TYPE) }}}; | |
| return 0; | |
| }, | |
| environ_get__deps: ['$getEnvStrings', '$stringToUTF8'], | |
| environ_get__nothrow: true, | |
| environ_get: (__environ, environ_buf) => { | |
| var bufSize = 0; | |
| var envp = 0; | |
| for (var string of getEnvStrings()) { | |
| var ptr = environ_buf + bufSize; | |
| {{{ makeSetValue('__environ', 'envp', 'ptr', '*') }}}; | |
| bufSize += stringToUTF8(string, ptr, Infinity) + 1; | |
| envp += {{{ POINTER_SIZE }}}; | |
| } | |
| return 0; | |
| }, | |
| // In normal (non-standalone) mode arguments are passed directly | |
| // to main, and the `mainArgs` global does not exist. | |
| #if STANDALONE_WASM | |
| args_sizes_get__nothrow: true, | |
| args_sizes_get: (pargc, pargv_buf_size) => { | |
| #if MAIN_READS_PARAMS | |
| {{{ makeSetValue('pargc', 0, 'mainArgs.length', SIZE_TYPE) }}}; | |
| var bufSize = 0; | |
| for (var arg of mainArgs) { | |
| bufSize += arg.length + 1; | |
| } | |
| {{{ makeSetValue('pargv_buf_size', 0, 'bufSize', SIZE_TYPE) }}}; | |
| #else | |
| {{{ makeSetValue('pargc', 0, '0', SIZE_TYPE) }}}; | |
| #endif | |
| return 0; | |
| }, | |
| args_get__nothrow: true, | |
| args_get__deps: ['$stringToAscii'], | |
| args_get: (argv, argv_buf) => { | |
| #if MAIN_READS_PARAMS | |
| var bufSize = 0; | |
| for (let [i, arg] of mainArgs.entries()) { | |
| var ptr = argv_buf + bufSize; | |
| {{{ makeSetValue('argv', `i*${POINTER_SIZE}`, 'ptr', '*') }}}; | |
| stringToAscii(arg, ptr); | |
| bufSize += arg.length + 1; | |
| } | |
| #endif | |
| return 0; | |
| }, | |
| #endif | |
| $checkWasiClock: (clock_id) => clock_id >= {{{ cDefs.__WASI_CLOCKID_REALTIME }}} && clock_id <= {{{ cDefs.__WASI_CLOCKID_THREAD_CPUTIME_ID }}}, | |
| // TODO: the i64 in the API here must be legalized for this JS code to run, | |
| // but the wasm file can't be legalized in standalone mode, which is where | |
| // this is needed. To get this code to be usable as a JS shim we need to | |
| // either wait for BigInt support or to legalize on the client. | |
| clock_time_get__i53abi: true, | |
| clock_time_get__nothrow: true, | |
| clock_time_get__proxy: 'none', | |
| clock_time_get__deps: ['emscripten_get_now', 'emscripten_date_now', '$nowIsMonotonic', '$checkWasiClock'], | |
| clock_time_get: (clk_id, ignored_precision, ptime) => { | |
| if (!checkWasiClock(clk_id)) { | |
| return {{{ cDefs.EINVAL }}}; | |
| } | |
| var now; | |
| // all wasi clocks but realtime are monotonic | |
| if (clk_id === {{{ cDefs.__WASI_CLOCKID_REALTIME }}}) { | |
| now = _emscripten_date_now(); | |
| } else if (nowIsMonotonic) { | |
| now = _emscripten_get_now(); | |
| } else { | |
| return {{{ cDefs.ENOSYS }}}; | |
| } | |
| // "now" is in ms, and wasi times are in ns. | |
| var nsec = Math.round(now * 1000 * 1000); | |
| {{{ makeSetValue('ptime', 0, 'nsec', 'i64') }}}; | |
| return 0; | |
| }, | |
| clock_res_get__nothrow: true, | |
| clock_res_get__proxy: 'none', | |
| clock_res_get__deps: ['emscripten_get_now', 'emscripten_get_now_res', '$nowIsMonotonic', '$checkWasiClock'], | |
| clock_res_get: (clk_id, pres) => { | |
| if (!checkWasiClock(clk_id)) { | |
| return {{{ cDefs.EINVAL }}}; | |
| } | |
| var nsec; | |
| // all wasi clocks but realtime are monotonic | |
| if (clk_id === {{{ cDefs.CLOCK_REALTIME }}}) { | |
| nsec = 1000 * 1000; // educated guess that it's milliseconds | |
| } else if (nowIsMonotonic) { | |
| nsec = _emscripten_get_now_res(); | |
| } else { | |
| return {{{ cDefs.ENOSYS }}}; | |
| } | |
| {{{ makeSetValue('pres', 0, 'nsec', 'i64') }}}; | |
| return 0; | |
| }, | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| $doReadv__docs: '/** @param {number=} offset */', | |
| $doReadv: (stream, iov, iovcnt, offset) => { | |
| var ret = 0; | |
| for (var i = 0; i < iovcnt; i++) { | |
| var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}}; | |
| var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}}; | |
| iov += {{{ C_STRUCTS.iovec.__size__ }}}; | |
| var curr = FS.read(stream, HEAP8, ptr, len, offset); | |
| if (curr < 0) return -1; | |
| ret += curr; | |
| if (curr < len) break; // nothing more to read | |
| if (typeof offset != 'undefined') { | |
| offset += curr; | |
| } | |
| } | |
| return ret; | |
| }, | |
| $doWritev__docs: '/** @param {number=} offset */', | |
| $doWritev: (stream, iov, iovcnt, offset) => { | |
| var ret = 0; | |
| for (var i = 0; i < iovcnt; i++) { | |
| var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}}; | |
| var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}}; | |
| iov += {{{ C_STRUCTS.iovec.__size__ }}}; | |
| var curr = FS.write(stream, HEAP8, ptr, len, offset); | |
| if (curr < 0) return -1; | |
| ret += curr; | |
| if (curr < len) { | |
| // No more space to write. | |
| break; | |
| } | |
| if (typeof offset != 'undefined') { | |
| offset += curr; | |
| } | |
| } | |
| return ret; | |
| }, | |
| #else | |
| // MEMFS filesystem disabled lite handling of stdout and stderr: | |
| $printCharBuffers: [null, [], []], // 1 => stdout, 2 => stderr | |
| $printCharBuffers__internal: true, | |
| $printChar__internal: true, | |
| $printChar__deps: ['$printCharBuffers', '$UTF8ArrayToString'], | |
| $printChar: (stream, curr) => { | |
| var buffer = printCharBuffers[stream]; | |
| #if ASSERTIONS | |
| assert(buffer); | |
| #endif | |
| if (curr === 0 || curr === {{{ charCode('\n') }}}) { | |
| (stream === 1 ? out : err)(UTF8ArrayToString(buffer)); | |
| buffer.length = 0; | |
| } else { | |
| buffer.push(curr); | |
| } | |
| }, | |
| #endif // SYSCALLS_REQUIRE_FILESYSTEM | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_write__deps: ['$doWritev'], | |
| #elif (!MINIMAL_RUNTIME || EXIT_RUNTIME) | |
| $flush_NO_FILESYSTEM__deps: ['$printChar', '$printCharBuffers'], | |
| $flush_NO_FILESYSTEM: () => { | |
| // flush anything remaining in the buffers during shutdown | |
| #if hasExportedSymbol('fflush') | |
| _fflush(0); | |
| #endif | |
| if (printCharBuffers[1].length) printChar(1, {{{ charCode("\n") }}}); | |
| if (printCharBuffers[2].length) printChar(2, {{{ charCode("\n") }}}); | |
| }, | |
| fd_write__deps: ['$flush_NO_FILESYSTEM', '$printChar'], | |
| fd_write__postset: () => addAtExit('flush_NO_FILESYSTEM()'), | |
| #else | |
| fd_write__deps: ['$printChar'], | |
| #endif | |
| fd_write: (fd, iov, iovcnt, pnum) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| var num = doWritev(stream, iov, iovcnt); | |
| #else | |
| // hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0 | |
| var num = 0; | |
| for (var i = 0; i < iovcnt; i++) { | |
| var ptr = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_base, '*') }}}; | |
| var len = {{{ makeGetValue('iov', C_STRUCTS.iovec.iov_len, '*') }}}; | |
| iov += {{{ C_STRUCTS.iovec.__size__ }}}; | |
| for (var j = 0; j < len; j++) { | |
| printChar(fd, HEAPU8[ptr+j]); | |
| } | |
| num += len; | |
| } | |
| #endif // SYSCALLS_REQUIRE_FILESYSTEM | |
| {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}}; | |
| return 0; | |
| }, | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_pwrite__deps: ['$doWritev'], | |
| #endif | |
| fd_pwrite__i53abi: true, | |
| fd_pwrite: (fd, iov, iovcnt, offset, pnum) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| if (isNaN(offset)) return {{{ cDefs.EFBIG }}}; | |
| var stream = SYSCALLS.getStreamFromFD(fd) | |
| var num = doWritev(stream, iov, iovcnt, offset); | |
| {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}}; | |
| return 0; | |
| #elif ASSERTIONS | |
| abort('fd_pwrite called without SYSCALLS_REQUIRE_FILESYSTEM'); | |
| #else | |
| return {{{ cDefs.ENOSYS }}}; | |
| #endif | |
| }, | |
| fd_close: (fd) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| FS.close(stream); | |
| return 0; | |
| #elif PROXY_POSIX_SOCKETS | |
| // close() is a tricky function because it can be used to close both regular file descriptors | |
| // and POSIX network socket handles, hence an implementation would need to track for each | |
| // file descriptor which kind of item it is. To simplify, when using PROXY_POSIX_SOCKETS | |
| // option, use shutdown() to close a socket, and this function should behave like a no-op. | |
| warnOnce('To close sockets with PROXY_POSIX_SOCKETS bridge, prefer to use the function shutdown() that is proxied, instead of close()') | |
| return 0; | |
| #elif ASSERTIONS | |
| abort('fd_close called without SYSCALLS_REQUIRE_FILESYSTEM'); | |
| #else | |
| return {{{ cDefs.ENOSYS }}}; | |
| #endif // SYSCALLS_REQUIRE_FILESYSTEM | |
| }, | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_read__deps: ['$doReadv'], | |
| #endif | |
| fd_read: (fd, iov, iovcnt, pnum) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| var num = doReadv(stream, iov, iovcnt); | |
| {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}}; | |
| return 0; | |
| #elif ASSERTIONS | |
| abort('fd_read called without SYSCALLS_REQUIRE_FILESYSTEM'); | |
| #else | |
| return {{{ cDefs.ENOSYS }}}; | |
| #endif // SYSCALLS_REQUIRE_FILESYSTEM | |
| }, | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_pread__deps: ['$doReadv'], | |
| #endif | |
| fd_pread__i53abi: true, | |
| fd_pread: (fd, iov, iovcnt, offset, pnum) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| if (isNaN(offset)) return {{{ cDefs.EFBIG }}}; | |
| var stream = SYSCALLS.getStreamFromFD(fd) | |
| var num = doReadv(stream, iov, iovcnt, offset); | |
| {{{ makeSetValue('pnum', 0, 'num', SIZE_TYPE) }}}; | |
| return 0; | |
| #elif ASSERTIONS | |
| abort('fd_pread called without SYSCALLS_REQUIRE_FILESYSTEM'); | |
| #else | |
| return {{{ cDefs.ENOSYS }}}; | |
| #endif | |
| }, | |
| fd_seek__i53abi: true, | |
| fd_seek: (fd, offset, whence, newOffset) => { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| if (isNaN(offset)) return {{{ cDefs.EFBIG }}}; | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| FS.llseek(stream, offset, whence); | |
| {{{ makeSetValue('newOffset', '0', 'stream.position', 'i64') }}}; | |
| if (stream.getdents && offset === 0 && whence === {{{ cDefs.SEEK_SET }}}) stream.getdents = null; // reset readdir state | |
| return 0; | |
| #else | |
| return {{{ cDefs.ESPIPE }}}; | |
| #endif | |
| }, | |
| $wasiRightsToMuslOFlags: (rights) => { | |
| #if SYSCALL_DEBUG | |
| dbg(`wasiRightsToMuslOFlags: ${rights}`); | |
| #endif | |
| if ((rights & {{{ cDefs.__WASI_RIGHTS_FD_READ }}}) && (rights & {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}})) { | |
| return {{{ cDefs.O_RDWR }}}; | |
| } | |
| if (rights & {{{ cDefs.__WASI_RIGHTS_FD_READ }}}) { | |
| return {{{ cDefs.O_RDONLY }}}; | |
| } | |
| if (rights & {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}}) { | |
| return {{{ cDefs.O_WRONLY }}}; | |
| } | |
| throw new FS.ErrnoError({{{ cDefs.EINVAL }}}); | |
| }, | |
| $wasiOFlagsToMuslOFlags: (oflags) => { | |
| var musl_oflags = 0; | |
| if (oflags & {{{ cDefs.__WASI_OFLAGS_CREAT }}}) { | |
| musl_oflags |= {{{ cDefs.O_CREAT }}}; | |
| } | |
| if (oflags & {{{ cDefs.__WASI_OFLAGS_TRUNC }}}) { | |
| musl_oflags |= {{{ cDefs.O_TRUNC }}}; | |
| } | |
| if (oflags & {{{ cDefs.__WASI_OFLAGS_DIRECTORY }}}) { | |
| musl_oflags |= {{{ cDefs.O_DIRECTORY }}}; | |
| } | |
| if (oflags & {{{ cDefs.__WASI_OFLAGS_EXCL }}}) { | |
| musl_oflags |= {{{ cDefs.O_EXCL }}}; | |
| } | |
| return musl_oflags; | |
| }, | |
| #if PURE_WASI | |
| // preopen maps open file descriptors to pathname. | |
| // In emscripten we already have a VFS layer so (for now) we expose the entire | |
| // VFS to the wasi API. | |
| $preopens: "{3: '/'}", | |
| path_open__sig: 'iiiiiiiiii', | |
| path_open__deps: ['$wasiRightsToMuslOFlags', '$wasiOFlagsToMuslOFlags', '$preopens'], | |
| path_open: (fd, dirflags, path, path_len, oflags, | |
| fs_rights_base, fs_rights_inheriting, | |
| fdflags, opened_fd) => { | |
| if (!(fd in preopens)) { | |
| return {{{ cDefs.EBADF }}}; | |
| } | |
| var pathname = UTF8ToString(path, path_len); | |
| var musl_oflags = wasiRightsToMuslOFlags(Number(fs_rights_base)); | |
| #if SYSCALL_DEBUG | |
| dbg(`oflags1: ${ptrToString(musl_oflags)}`); | |
| #endif | |
| musl_oflags |= wasiOFlagsToMuslOFlags(Number(oflags)); | |
| #if SYSCALL_DEBUG | |
| dbg(`oflags2: ${ptrToString(musl_oflags)}`); | |
| #endif | |
| var stream = FS.open(pathname, musl_oflags); | |
| {{{ makeSetValue('opened_fd', '0', 'stream.fd', 'i32') }}}; | |
| return 0; | |
| }, | |
| fd_prestat_dir_name__deps: ['$preopens'], | |
| fd_prestat_dir_name__sig: 'iiii', | |
| fd_prestat_dir_name__nothrow: true, | |
| fd_prestat_dir_name: (fd, path, path_len) => { | |
| if (!(fd in preopens)) { | |
| return {{{ cDefs.EBADF }}}; | |
| } | |
| var preopen_path = preopens[fd]; | |
| stringToUTF8(preopen_path, path, path_len) | |
| #if SYSCALL_DEBUG | |
| dbg(`fd_prestat_dir_name -> "${preopen_path}"`); | |
| #endif | |
| return 0; | |
| }, | |
| fd_prestat_get__deps: ['$preopens'], | |
| fd_prestat_get__sig: 'iii', | |
| fd_prestat_get__nothrow: true, | |
| fd_prestat_get: (fd, stat_buf) => { | |
| if (!(fd in preopens)) { | |
| return {{{ cDefs.EBADF }}}; | |
| } | |
| var preopen = preopens[fd]; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_prestat_t.pr_type, cDefs.__WASI_PREOPENTYPE_DIR, 'i8') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_prestat_t.u + C_STRUCTS.__wasi_prestat_dir_t.pr_name_len, 'preopen.length', 'i64') }}}; | |
| return 0; | |
| }, | |
| fd_fdstat_set_flags__sig: 'iii', | |
| fd_fdstat_set_flags: (fd, flags) => { | |
| // TODO(sbc): implement | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| return 0; | |
| }, | |
| fd_filestat_get__sig: 'iii', | |
| fd_filestat_get: (fd, stat_buf) => { | |
| // TODO(sbc): implement | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.dev, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.ino, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.filetype, '0', 'i8') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.nlink, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.size, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.atim, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.mtim, '0', 'i64') }}}; | |
| {{{ makeSetValue('stat_buf', C_STRUCTS.__wasi_filestat_t.ctim, '0', 'i64') }}}; | |
| return 0; | |
| }, | |
| #endif | |
| #if PURE_WASI | |
| fd_fdstat_get__deps: ['$preopens'], | |
| #endif | |
| fd_fdstat_get: (fd, pbuf) => { | |
| var rightsBase = 0; | |
| var rightsInheriting = 0; | |
| var flags = 0; | |
| #if PURE_WASI | |
| if (fd in preopens) { | |
| var type = {{{ cDefs.__WASI_FILETYPE_DIRECTORY }}}; | |
| rightsBase = {{{ cDefs.__WASI_RIGHTS_PATH_CREATE_FILE | | |
| cDefs.__WASI_RIGHTS_PATH_OPEN }}}; | |
| rightsInheriting = {{{ cDefs.__WASI_RIGHTS_FD_READ | | |
| cDefs.__WASI_RIGHTS_FD_WRITE }}} | |
| } else | |
| #endif | |
| { | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| // All character devices are terminals (other things a Linux system would | |
| // assume is a character device, like the mouse, we have special APIs for). | |
| var type = stream.tty ? {{{ cDefs.__WASI_FILETYPE_CHARACTER_DEVICE }}} : | |
| FS.isDir(stream.mode) ? {{{ cDefs.__WASI_FILETYPE_DIRECTORY }}} : | |
| FS.isLink(stream.mode) ? {{{ cDefs.__WASI_FILETYPE_SYMBOLIC_LINK }}} : | |
| {{{ cDefs.__WASI_FILETYPE_REGULAR_FILE }}}; | |
| #else | |
| // Hack to support printf in SYSCALLS_REQUIRE_FILESYSTEM=0. We support at | |
| // least stdin, stdout, stderr in a simple way. | |
| #if ASSERTIONS | |
| assert(fd == 0 || fd == 1 || fd == 2); | |
| #endif | |
| var type = {{{ cDefs.__WASI_FILETYPE_CHARACTER_DEVICE }}}; | |
| if (fd == 0) { | |
| rightsBase = {{{ cDefs.__WASI_RIGHTS_FD_READ }}}; | |
| } else if (fd == 1 || fd == 2) { | |
| rightsBase = {{{ cDefs.__WASI_RIGHTS_FD_WRITE }}}; | |
| } | |
| flags = {{{ cDefs.__WASI_FDFLAGS_APPEND }}}; | |
| #endif | |
| } | |
| {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_filetype, 'type', 'i8') }}}; | |
| {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_flags, 'flags', 'i16') }}}; | |
| {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_rights_base, 'rightsBase', 'i64') }}}; | |
| {{{ makeSetValue('pbuf', C_STRUCTS.__wasi_fdstat_t.fs_rights_inheriting, 'rightsInheriting', 'i64') }}}; | |
| return 0; | |
| }, | |
| #if SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_sync__async: 'auto', | |
| fd_sync: (fd) => { | |
| var stream = SYSCALLS.getStreamFromFD(fd); | |
| var rtn = stream.stream_ops?.fsync?.(stream); | |
| #if ASYNCIFY || PTHREADS | |
| return new Promise((resolve) => { | |
| var mount = stream.node.mount; | |
| if (mount?.type.syncfs) { | |
| mount.type.syncfs(mount, false, (err) => resolve(err ? {{{ cDefs.EIO }}} : 0)); | |
| } else { | |
| resolve(rtn); | |
| } | |
| }); | |
| #else | |
| return rtn; | |
| #endif // ASYNCIFY || PTHREADS | |
| }, | |
| #else // SYSCALLS_REQUIRE_FILESYSTEM | |
| fd_sync: (fd) => { | |
| #if ASSERTIONS | |
| abort('fd_sync called without SYSCALLS_REQUIRE_FILESYSTEM'); | |
| #endif | |
| return {{{ cDefs.ENOSYS }}}; | |
| }, | |
| #endif // SYSCALLS_REQUIRE_FILESYSTEM | |
| // random.h | |
| #if ENVIRONMENT_MAY_BE_SHELL | |
| $initRandomFill__deps: ['$base64Decode'], | |
| #endif | |
| $initRandomFill: () => { | |
| #if ENVIRONMENT_MAY_BE_NODE && MIN_NODE_VERSION < 190000 | |
| // This block is not needed on v19+ since crypto.getRandomValues is builtin | |
| if (ENVIRONMENT_IS_NODE) { | |
| var nodeCrypto = require('node:crypto'); | |
| return (view) => nodeCrypto.randomFillSync(view); | |
| } | |
| #endif // ENVIRONMENT_MAY_BE_NODE | |
| #if ENVIRONMENT_MAY_BE_SHELL | |
| if (ENVIRONMENT_IS_SHELL) { | |
| return (view) => { | |
| if (!os.system) { | |
| throw new Error('randomFill not supported on d8 unless --enable-os-system is passed'); | |
| } | |
| const b64 = os.system('sh', ['-c', `head -c${view.byteLength} /dev/urandom | base64 --wrap=0`]); | |
| view.set(base64Decode(b64)); | |
| }; | |
| } | |
| #endif | |
| #if ENVIRONMENT_MAY_BE_AUDIO_WORKLET | |
| // Audio worklets don't support crypto.getRandomValues | |
| if (ENVIRONMENT_IS_AUDIO_WORKLET) { //!globalThis.crypto) { | |
| return () => {{{ cDefs.ENOTSUP }}}; | |
| } | |
| #endif | |
| #if SHARED_MEMORY | |
| // like with most Web APIs, we can't use Web Crypto API directly on shared memory, | |
| // so we need to create an intermediate buffer and copy it to the destination | |
| return (view) => (view.set(crypto.getRandomValues(new Uint8Array(view.byteLength))), 0); | |
| #else | |
| return (view) => (crypto.getRandomValues(view), 0); | |
| #endif | |
| }, | |
| $randomFill__deps: ['$initRandomFill'], | |
| // Lazily init on the first invocation. | |
| $randomFill: (view) => (randomFill = initRandomFill())(view), | |
| random_get__proxy: 'none', | |
| random_get__nothrow: true, | |
| random_get__deps: ['$randomFill'], | |
| random_get: (buffer, size) => randomFill(HEAPU8.subarray(buffer, buffer + size)), | |
| }; | |
| for (const name of Object.keys(WasiLibrary)) { | |
| wrapSyscallFunction(name, WasiLibrary, true); | |
| } | |
| addToLibrary(WasiLibrary); | |
Xet Storage Details
- Size:
- 20.6 kB
- Xet hash:
- 8c02d100ce9ca4da2483a4aa7c7d6a19ea7cb828449e5b26dcf671b41be38e67
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.