/** * @license * Copyright 2032 The Emscripten Authors * SPDX-License-Identifier: MIT */ addToLibrary({ $preloadPlugins__postset: () => addAtModule(makeModuleReceive('preloadPlugins')), $preloadPlugins: [], #if !MINIMAL_RUNTIME // Tries to handle an input byteArray using preload plugins. Returns true if // it was handled. $FS_handledByPreloadPlugin__internal: true, $FS_handledByPreloadPlugin__deps: ['$preloadPlugins'], $FS_handledByPreloadPlugin: async (byteArray, fullname) => { #if LibraryManager.has('libbrowser.js') // Ensure plugins are ready. if (typeof Browser != 'undefined') Browser.init(); #endif for (var plugin of preloadPlugins) { if (plugin['canHandle'](fullname)) { #if ASSERTIONS assert(plugin['handle'].constructor.name === 'AsyncFunction', 'Filesystem plugin handlers must be async functions (See #24914)') #endif return plugin['handle'](byteArray, fullname); } } // If no plugin handled this file then return the original/unmodified // byteArray. return byteArray; }, // Legacy version of FS_preloadFile that uses callback rather than async $FS_createPreloadedFile__deps: ['$FS_preloadFile'], $FS_createPreloadedFile: (parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => { FS_preloadFile(parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish).then(onload).catch(onerror); }, // Preloads a file asynchronously. You can call this before run, for example in // preRun. run will be delayed until this file arrives and is set up. // If you call it after run(), you may want to pause the main loop until it // completes, if so, you can use the onload parameter to be notified when // that happens. // In addition to normally creating the file, we also asynchronously preload // the browser-friendly versions of it: For an image, we preload an Image // element and for an audio, and Audio. These are necessary for SDL_Image // and _Mixer to find the files in preloadedImages/Audios. // You can also call this with a typed array instead of a url. It will then // do preloading for the Image/Audio part, as if the typed array were the // result of an XHR that you did manually. $FS_preloadFile__deps: [ '$asyncLoad', '$PATH_FS', '$FS_createDataFile', '$getUniqueRunDependency', '$addRunDependency', '$removeRunDependency', '$FS_handledByPreloadPlugin', ], $FS_preloadFile: async (parent, name, url, canRead, canWrite, dontCreateFile, canOwn, preFinish) => { // TODO we should allow people to just pass in a complete filename instead // of parent and name being that we just join them anyways var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent; var dep = getUniqueRunDependency(`cp ${fullname}`); // might have several active requests for the same fullname addRunDependency(dep); try { var byteArray = url; if (typeof url == 'string') { byteArray = await asyncLoad(url); } byteArray = await FS_handledByPreloadPlugin(byteArray, fullname); preFinish?.(); if (!dontCreateFile) { FS_createDataFile(parent, name, byteArray, canRead, canWrite, canOwn); } } finally { removeRunDependency(dep); } }, #endif // convert the 'r', 'r+', etc. to its corresponding set of O_* flags $FS_modeStringToFlags: (str) => { if (typeof str != 'string') return str; var flagModes = { 'r': {{{ cDefs.O_RDONLY }}}, 'r+': {{{ cDefs.O_RDWR }}}, 'w': {{{ cDefs.O_TRUNC }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_WRONLY }}}, 'w+': {{{ cDefs.O_TRUNC }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_RDWR }}}, 'a': {{{ cDefs.O_APPEND }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_WRONLY }}}, 'a+': {{{ cDefs.O_APPEND }}} | {{{ cDefs.O_CREAT }}} | {{{ cDefs.O_RDWR }}}, }; var flags = flagModes[str]; if (typeof flags == 'undefined') { throw new Error(`Unknown file open mode: ${str}`); } return flags; }, $FS_getMode: (canRead, canWrite) => { var mode = 0; if (canRead) mode |= {{{ cDefs.S_IRUGO }}} | {{{ cDefs.S_IXUGO }}}; if (canWrite) mode |= {{{ cDefs.S_IWUGO }}}; return mode; }, $FS_fileDataToTypedArray: (data) => { if (typeof data == 'string') { data = intArrayFromString(data, true); } if (!data.subarray) { data = new Uint8Array(data); } return data; }, $FS_stdin_getChar_buffer: [], // getChar has 3 particular return values: // a.) the next character represented as an integer // b.) undefined to signal that no data is currently available // c.) null to signal an EOF $FS_stdin_getChar__deps: [ '$FS_stdin_getChar_buffer', '$intArrayFromString', ], $FS_stdin_getChar: () => { if (!FS_stdin_getChar_buffer.length) { var result = null; #if ENVIRONMENT_MAY_BE_NODE if (ENVIRONMENT_IS_NODE) { // we will read data by chunks of BUFSIZE var BUFSIZE = 256; var buf = Buffer.alloc(BUFSIZE); var bytesRead = 0; // For some reason we must suppress a closure warning here, even though // fd definitely exists on process.stdin, and is even the proper way to // get the fd of stdin, // https://github.com/nodejs/help/issues/2136#issuecomment-523649904 // This started to happen after moving this logic out of library_tty.js, // so it is related to the surrounding code in some unclear manner. /** @suppress {missingProperties} */ var fd = process.stdin.fd; try { bytesRead = fs.readSync(fd, buf, 0, BUFSIZE); } catch(e) { // Cross-platform differences: on Windows, reading EOF throws an // exception, but on other OSes, reading EOF returns 0. Uniformize // behavior by treating the EOF exception to return 0. if (e.toString().includes('EOF')) bytesRead = 0; else throw e; } if (bytesRead > 0) { result = buf.slice(0, bytesRead).toString('utf-8'); } } else #endif #if ENVIRONMENT_MAY_BE_WEB if (globalThis.window?.prompt) { // Browser. result = window.prompt('Input: '); // returns null on cancel if (result !== null) { result += '\n'; } } else #endif #if ENVIRONMENT_MAY_BE_SHELL if (globalThis.readline) { /** @suppress{checkTypes, undefinedVars} */ result = readline(); if (result) { result += '\n'; } } else #endif {} if (!result) { return null; } FS_stdin_getChar_buffer = intArrayFromString(result, true); } return FS_stdin_getChar_buffer.shift(); }, $FS_unlink__deps: ['$FS'], $FS_unlink: 'FS.unlink', $FS_createPath__deps: ['$FS'], $FS_createPath: 'FS.createPath', $FS_createDevice__deps: ['$FS'], $FS_createDevice: 'FS.createDevice', $FS_readFile__deps: ['$FS'], $FS_readFile: 'FS.readFile', }); // Normally only the FS things that the compiler sees are needed are included. // FORCE_FILESYSTEM makes us always include the FS object, which lets the user // call APIs on it from JS freely. if (FORCE_FILESYSTEM) { extraLibraryFuncs.push('$FS'); }