用于存放学校的作业便于复习。
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

5442 lines
206 KiB

  1. // The Module object: Our interface to the outside world. We import
  2. // and export values on it. There are various ways Module can be used:
  3. // 1. Not defined. We create it here
  4. // 2. A function parameter, function(Module) { ..generated code.. }
  5. // 3. pre-run appended it, var Module = {}; ..generated code..
  6. // 4. External script tag defines var Module.
  7. // We need to check if Module already exists (e.g. case 3 above).
  8. // Substitution will be replaced with actual code on later stage of the build,
  9. // this way Closure Compiler will not mangle it (e.g. case 4. above).
  10. // Note that if you want to run closure, and also to use Module
  11. // after the generated code, you will need to define var Module = {};
  12. // before the code. Then that object will be used in the code, and you
  13. // can continue to use Module afterwards as well.
  14. var Module = typeof Module != 'undefined' ? Module : {};
  15. // See https://caniuse.com/mdn-javascript_builtins_object_assign
  16. // --pre-jses are emitted after the Module integration code, so that they can
  17. // refer to Module (if they choose; they can also define Module)
  18. // {{PRE_JSES}}
  19. // Sometimes an existing Module object exists with properties
  20. // meant to overwrite the default module functionality. Here
  21. // we collect those properties and reapply _after_ we configure
  22. // the current environment's defaults to avoid having to be so
  23. // defensive during initialization.
  24. var moduleOverrides = Object.assign({}, Module);
  25. var arguments_ = [];
  26. var thisProgram = './this.program';
  27. var quit_ = (status, toThrow) => {
  28. throw toThrow;
  29. };
  30. // Determine the runtime environment we are in. You can customize this by
  31. // setting the ENVIRONMENT setting at compile time (see settings.js).
  32. // Attempt to auto-detect the environment
  33. var ENVIRONMENT_IS_WEB = typeof window == 'object';
  34. var ENVIRONMENT_IS_WORKER = typeof importScripts == 'function';
  35. // N.b. Electron.js environment is simultaneously a NODE-environment, but
  36. // also a web environment.
  37. var ENVIRONMENT_IS_NODE = typeof process == 'object' && typeof process.versions == 'object' && typeof process.versions.node == 'string';
  38. var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
  39. if (Module['ENVIRONMENT']) {
  40. throw new Error('Module.ENVIRONMENT has been deprecated. To force the environment, use the ENVIRONMENT compile-time option (for example, -s ENVIRONMENT=web or -s ENVIRONMENT=node)');
  41. }
  42. // `/` should be present at the end if `scriptDirectory` is not empty
  43. var scriptDirectory = '';
  44. function locateFile(path) {
  45. if (Module['locateFile']) {
  46. return Module['locateFile'](path, scriptDirectory);
  47. }
  48. return scriptDirectory + path;
  49. }
  50. // Hooks that are implemented differently in different runtime environments.
  51. var read_,
  52. readAsync,
  53. readBinary,
  54. setWindowTitle;
  55. // Normally we don't log exceptions but instead let them bubble out the top
  56. // level where the embedding environment (e.g. the browser) can handle
  57. // them.
  58. // However under v8 and node we sometimes exit the process direcly in which case
  59. // its up to use us to log the exception before exiting.
  60. // If we fix https://github.com/emscripten-core/emscripten/issues/15080
  61. // this may no longer be needed under node.
  62. function logExceptionOnExit(e) {
  63. if (e instanceof ExitStatus) return;
  64. let toLog = e;
  65. if (e && typeof e == 'object' && e.stack) {
  66. toLog = [e, e.stack];
  67. }
  68. err('exiting due to exception: ' + toLog);
  69. }
  70. var fs;
  71. var nodePath;
  72. var requireNodeFS;
  73. if (ENVIRONMENT_IS_NODE) {
  74. if (!(typeof process == 'object' && typeof require == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
  75. if (ENVIRONMENT_IS_WORKER) {
  76. scriptDirectory = require('path').dirname(scriptDirectory) + '/';
  77. } else {
  78. scriptDirectory = __dirname + '/';
  79. }
  80. // include: node_shell_read.js
  81. requireNodeFS = () => {
  82. // Use nodePath as the indicator for these not being initialized,
  83. // since in some environments a global fs may have already been
  84. // created.
  85. if (!nodePath) {
  86. fs = require('fs');
  87. nodePath = require('path');
  88. }
  89. };
  90. read_ = function shell_read(filename, binary) {
  91. requireNodeFS();
  92. filename = nodePath['normalize'](filename);
  93. return fs.readFileSync(filename, binary ? undefined : 'utf8');
  94. };
  95. readBinary = (filename) => {
  96. var ret = read_(filename, true);
  97. if (!ret.buffer) {
  98. ret = new Uint8Array(ret);
  99. }
  100. assert(ret.buffer);
  101. return ret;
  102. };
  103. readAsync = (filename, onload, onerror) => {
  104. requireNodeFS();
  105. filename = nodePath['normalize'](filename);
  106. fs.readFile(filename, function(err, data) {
  107. if (err) onerror(err);
  108. else onload(data.buffer);
  109. });
  110. };
  111. // end include: node_shell_read.js
  112. if (process['argv'].length > 1) {
  113. thisProgram = process['argv'][1].replace(/\\/g, '/');
  114. }
  115. arguments_ = process['argv'].slice(2);
  116. if (typeof module != 'undefined') {
  117. module['exports'] = Module;
  118. }
  119. process['on']('uncaughtException', function(ex) {
  120. // suppress ExitStatus exceptions from showing an error
  121. if (!(ex instanceof ExitStatus)) {
  122. throw ex;
  123. }
  124. });
  125. // Without this older versions of node (< v15) will log unhandled rejections
  126. // but return 0, which is not normally the desired behaviour. This is
  127. // not be needed with node v15 and about because it is now the default
  128. // behaviour:
  129. // See https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode
  130. process['on']('unhandledRejection', function(reason) { throw reason; });
  131. quit_ = (status, toThrow) => {
  132. if (keepRuntimeAlive()) {
  133. process['exitCode'] = status;
  134. throw toThrow;
  135. }
  136. logExceptionOnExit(toThrow);
  137. process['exit'](status);
  138. };
  139. Module['inspect'] = function () { return '[Emscripten Module object]'; };
  140. } else
  141. if (ENVIRONMENT_IS_SHELL) {
  142. if ((typeof process == 'object' && typeof require === 'function') || typeof window == 'object' || typeof importScripts == 'function') throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
  143. if (typeof read != 'undefined') {
  144. read_ = function shell_read(f) {
  145. return read(f);
  146. };
  147. }
  148. readBinary = function readBinary(f) {
  149. let data;
  150. if (typeof readbuffer == 'function') {
  151. return new Uint8Array(readbuffer(f));
  152. }
  153. data = read(f, 'binary');
  154. assert(typeof data == 'object');
  155. return data;
  156. };
  157. readAsync = function readAsync(f, onload, onerror) {
  158. setTimeout(() => onload(readBinary(f)), 0);
  159. };
  160. if (typeof scriptArgs != 'undefined') {
  161. arguments_ = scriptArgs;
  162. } else if (typeof arguments != 'undefined') {
  163. arguments_ = arguments;
  164. }
  165. if (typeof quit == 'function') {
  166. quit_ = (status, toThrow) => {
  167. // Unlike node which has process.exitCode, d8 has no such mechanism. So we
  168. // have no way to set the exit code and then let the program exit with
  169. // that code when it naturally stops running (say, when all setTimeouts
  170. // have completed). For that reason we must call `quit` - the only way to
  171. // set the exit code - but quit also halts immediately, so we need to be
  172. // careful of whether the runtime is alive or not, which is why this code
  173. // path looks different than node. It also has the downside that it will
  174. // halt the entire program when no code remains to run, which means this
  175. // is not friendly for bundling this code into a larger codebase, and for
  176. // that reason the "shell" environment is mainly useful for testing whole
  177. // programs by themselves, basically.
  178. if (runtimeKeepaliveCounter) {
  179. throw toThrow;
  180. }
  181. logExceptionOnExit(toThrow);
  182. quit(status);
  183. };
  184. }
  185. if (typeof print != 'undefined') {
  186. // Prefer to use print/printErr where they exist, as they usually work better.
  187. if (typeof console == 'undefined') console = /** @type{!Console} */({});
  188. console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);
  189. console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr != 'undefined' ? printErr : print);
  190. }
  191. } else
  192. // Note that this includes Node.js workers when relevant (pthreads is enabled).
  193. // Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
  194. // ENVIRONMENT_IS_NODE.
  195. if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
  196. if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled
  197. scriptDirectory = self.location.href;
  198. } else if (typeof document != 'undefined' && document.currentScript) { // web
  199. scriptDirectory = document.currentScript.src;
  200. }
  201. // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
  202. // otherwise, slice off the final part of the url to find the script directory.
  203. // if scriptDirectory does not contain a slash, lastIndexOf will return -1,
  204. // and scriptDirectory will correctly be replaced with an empty string.
  205. // If scriptDirectory contains a query (starting with ?) or a fragment (starting with #),
  206. // they are removed because they could contain a slash.
  207. if (scriptDirectory.indexOf('blob:') !== 0) {
  208. scriptDirectory = scriptDirectory.substr(0, scriptDirectory.replace(/[?#].*/, "").lastIndexOf('/')+1);
  209. } else {
  210. scriptDirectory = '';
  211. }
  212. if (!(typeof window == 'object' || typeof importScripts == 'function')) throw new Error('not compiled for this environment (did you build to HTML and try to run it not on the web, or set ENVIRONMENT to something - like node - and run it someplace else - like on the web?)');
  213. // Differentiate the Web Worker from the Node Worker case, as reading must
  214. // be done differently.
  215. {
  216. // include: web_or_worker_shell_read.js
  217. read_ = (url) => {
  218. var xhr = new XMLHttpRequest();
  219. xhr.open('GET', url, false);
  220. xhr.send(null);
  221. return xhr.responseText;
  222. }
  223. if (ENVIRONMENT_IS_WORKER) {
  224. readBinary = (url) => {
  225. var xhr = new XMLHttpRequest();
  226. xhr.open('GET', url, false);
  227. xhr.responseType = 'arraybuffer';
  228. xhr.send(null);
  229. return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
  230. };
  231. }
  232. readAsync = (url, onload, onerror) => {
  233. var xhr = new XMLHttpRequest();
  234. xhr.open('GET', url, true);
  235. xhr.responseType = 'arraybuffer';
  236. xhr.onload = () => {
  237. if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
  238. onload(xhr.response);
  239. return;
  240. }
  241. onerror();
  242. };
  243. xhr.onerror = onerror;
  244. xhr.send(null);
  245. }
  246. // end include: web_or_worker_shell_read.js
  247. }
  248. setWindowTitle = (title) => document.title = title;
  249. } else
  250. {
  251. throw new Error('environment detection error');
  252. }
  253. var out = Module['print'] || console.log.bind(console);
  254. var err = Module['printErr'] || console.warn.bind(console);
  255. // Merge back in the overrides
  256. Object.assign(Module, moduleOverrides);
  257. // Free the object hierarchy contained in the overrides, this lets the GC
  258. // reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
  259. moduleOverrides = null;
  260. checkIncomingModuleAPI();
  261. // Emit code to handle expected values on the Module object. This applies Module.x
  262. // to the proper local x. This has two benefits: first, we only emit it if it is
  263. // expected to arrive, and second, by using a local everywhere else that can be
  264. // minified.
  265. if (Module['arguments']) arguments_ = Module['arguments'];legacyModuleProp('arguments', 'arguments_');
  266. if (Module['thisProgram']) thisProgram = Module['thisProgram'];legacyModuleProp('thisProgram', 'thisProgram');
  267. if (Module['quit']) quit_ = Module['quit'];legacyModuleProp('quit', 'quit_');
  268. // perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
  269. // Assertions on removed incoming Module JS APIs.
  270. assert(typeof Module['memoryInitializerPrefixURL'] == 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
  271. assert(typeof Module['pthreadMainPrefixURL'] == 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
  272. assert(typeof Module['cdInitializerPrefixURL'] == 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
  273. assert(typeof Module['filePackagePrefixURL'] == 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
  274. assert(typeof Module['read'] == 'undefined', 'Module.read option was removed (modify read_ in JS)');
  275. assert(typeof Module['readAsync'] == 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
  276. assert(typeof Module['readBinary'] == 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
  277. assert(typeof Module['setWindowTitle'] == 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)');
  278. assert(typeof Module['TOTAL_MEMORY'] == 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
  279. legacyModuleProp('read', 'read_');
  280. legacyModuleProp('readAsync', 'readAsync');
  281. legacyModuleProp('readBinary', 'readBinary');
  282. legacyModuleProp('setWindowTitle', 'setWindowTitle');
  283. var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js';
  284. var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js';
  285. var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js';
  286. var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
  287. assert(!ENVIRONMENT_IS_SHELL, "shell environment detected but not enabled at build time. Add 'shell' to `-s ENVIRONMENT` to enable.");
  288. var STACK_ALIGN = 16;
  289. var POINTER_SIZE = 4;
  290. function getNativeTypeSize(type) {
  291. switch (type) {
  292. case 'i1': case 'i8': return 1;
  293. case 'i16': return 2;
  294. case 'i32': return 4;
  295. case 'i64': return 8;
  296. case 'float': return 4;
  297. case 'double': return 8;
  298. default: {
  299. if (type[type.length - 1] === '*') {
  300. return POINTER_SIZE;
  301. } else if (type[0] === 'i') {
  302. const bits = Number(type.substr(1));
  303. assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);
  304. return bits / 8;
  305. } else {
  306. return 0;
  307. }
  308. }
  309. }
  310. }
  311. function warnOnce(text) {
  312. if (!warnOnce.shown) warnOnce.shown = {};
  313. if (!warnOnce.shown[text]) {
  314. warnOnce.shown[text] = 1;
  315. err(text);
  316. }
  317. }
  318. // include: runtime_functions.js
  319. // Wraps a JS function as a wasm function with a given signature.
  320. function convertJsFunctionToWasm(func, sig) {
  321. // If the type reflection proposal is available, use the new
  322. // "WebAssembly.Function" constructor.
  323. // Otherwise, construct a minimal wasm module importing the JS function and
  324. // re-exporting it.
  325. if (typeof WebAssembly.Function == "function") {
  326. var typeNames = {
  327. 'i': 'i32',
  328. 'j': 'i64',
  329. 'f': 'f32',
  330. 'd': 'f64'
  331. };
  332. var type = {
  333. parameters: [],
  334. results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
  335. };
  336. for (var i = 1; i < sig.length; ++i) {
  337. type.parameters.push(typeNames[sig[i]]);
  338. }
  339. return new WebAssembly.Function(type, func);
  340. }
  341. // The module is static, with the exception of the type section, which is
  342. // generated based on the signature passed in.
  343. var typeSection = [
  344. 0x01, // id: section,
  345. 0x00, // length: 0 (placeholder)
  346. 0x01, // count: 1
  347. 0x60, // form: func
  348. ];
  349. var sigRet = sig.slice(0, 1);
  350. var sigParam = sig.slice(1);
  351. var typeCodes = {
  352. 'i': 0x7f, // i32
  353. 'j': 0x7e, // i64
  354. 'f': 0x7d, // f32
  355. 'd': 0x7c, // f64
  356. };
  357. // Parameters, length + signatures
  358. typeSection.push(sigParam.length);
  359. for (var i = 0; i < sigParam.length; ++i) {
  360. typeSection.push(typeCodes[sigParam[i]]);
  361. }
  362. // Return values, length + signatures
  363. // With no multi-return in MVP, either 0 (void) or 1 (anything else)
  364. if (sigRet == 'v') {
  365. typeSection.push(0x00);
  366. } else {
  367. typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
  368. }
  369. // Write the overall length of the type section back into the section header
  370. // (excepting the 2 bytes for the section id and length)
  371. typeSection[1] = typeSection.length - 2;
  372. // Rest of the module is static
  373. var bytes = new Uint8Array([
  374. 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
  375. 0x01, 0x00, 0x00, 0x00, // version: 1
  376. ].concat(typeSection, [
  377. 0x02, 0x07, // import section
  378. // (import "e" "f" (func 0 (type 0)))
  379. 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
  380. 0x07, 0x05, // export section
  381. // (export "f" (func 0 (type 0)))
  382. 0x01, 0x01, 0x66, 0x00, 0x00,
  383. ]));
  384. // We can compile this wasm module synchronously because it is very small.
  385. // This accepts an import (at "e.f"), that it reroutes to an export (at "f")
  386. var module = new WebAssembly.Module(bytes);
  387. var instance = new WebAssembly.Instance(module, {
  388. 'e': {
  389. 'f': func
  390. }
  391. });
  392. var wrappedFunc = instance.exports['f'];
  393. return wrappedFunc;
  394. }
  395. var freeTableIndexes = [];
  396. // Weak map of functions in the table to their indexes, created on first use.
  397. var functionsInTableMap;
  398. function getEmptyTableSlot() {
  399. // Reuse a free index if there is one, otherwise grow.
  400. if (freeTableIndexes.length) {
  401. return freeTableIndexes.pop();
  402. }
  403. // Grow the table
  404. try {
  405. wasmTable.grow(1);
  406. } catch (err) {
  407. if (!(err instanceof RangeError)) {
  408. throw err;
  409. }
  410. throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.';
  411. }
  412. return wasmTable.length - 1;
  413. }
  414. function updateTableMap(offset, count) {
  415. for (var i = offset; i < offset + count; i++) {
  416. var item = getWasmTableEntry(i);
  417. // Ignore null values.
  418. if (item) {
  419. functionsInTableMap.set(item, i);
  420. }
  421. }
  422. }
  423. /**
  424. * Add a function to the table.
  425. * 'sig' parameter is required if the function being added is a JS function.
  426. * @param {string=} sig
  427. */
  428. function addFunction(func, sig) {
  429. assert(typeof func != 'undefined');
  430. // Check if the function is already in the table, to ensure each function
  431. // gets a unique index. First, create the map if this is the first use.
  432. if (!functionsInTableMap) {
  433. functionsInTableMap = new WeakMap();
  434. updateTableMap(0, wasmTable.length);
  435. }
  436. if (functionsInTableMap.has(func)) {
  437. return functionsInTableMap.get(func);
  438. }
  439. // It's not in the table, add it now.
  440. var ret = getEmptyTableSlot();
  441. // Set the new value.
  442. try {
  443. // Attempting to call this with JS function will cause of table.set() to fail
  444. setWasmTableEntry(ret, func);
  445. } catch (err) {
  446. if (!(err instanceof TypeError)) {
  447. throw err;
  448. }
  449. assert(typeof sig != 'undefined', 'Missing signature argument to addFunction: ' + func);
  450. var wrapped = convertJsFunctionToWasm(func, sig);
  451. setWasmTableEntry(ret, wrapped);
  452. }
  453. functionsInTableMap.set(func, ret);
  454. return ret;
  455. }
  456. function removeFunction(index) {
  457. functionsInTableMap.delete(getWasmTableEntry(index));
  458. freeTableIndexes.push(index);
  459. }
  460. // end include: runtime_functions.js
  461. // include: runtime_debug.js
  462. function legacyModuleProp(prop, newName) {
  463. if (!Object.getOwnPropertyDescriptor(Module, prop)) {
  464. Object.defineProperty(Module, prop, {
  465. configurable: true,
  466. get: function() {
  467. abort('Module.' + prop + ' has been replaced with plain ' + newName + ' (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)');
  468. }
  469. });
  470. }
  471. }
  472. function ignoredModuleProp(prop) {
  473. if (Object.getOwnPropertyDescriptor(Module, prop)) {
  474. abort('`Module.' + prop + '` was supplied but `' + prop + '` not included in INCOMING_MODULE_JS_API');
  475. }
  476. }
  477. function unexportedMessage(sym, isFSSybol) {
  478. var msg = "'" + sym + "' was not exported. add it to EXPORTED_RUNTIME_METHODS (see the FAQ)";
  479. if (isFSSybol) {
  480. msg += '. Alternatively, forcing filesystem support (-s FORCE_FILESYSTEM=1) can export this for you';
  481. }
  482. return msg;
  483. }
  484. function unexportedRuntimeSymbol(sym, isFSSybol) {
  485. if (!Object.getOwnPropertyDescriptor(Module, sym)) {
  486. Object.defineProperty(Module, sym, {
  487. configurable: true,
  488. get: function() {
  489. abort(unexportedMessage(sym, isFSSybol));
  490. }
  491. });
  492. }
  493. }
  494. function unexportedRuntimeFunction(sym, isFSSybol) {
  495. if (!Object.getOwnPropertyDescriptor(Module, sym)) {
  496. Module[sym] = () => abort(unexportedMessage(sym, isFSSybol));
  497. }
  498. }
  499. // end include: runtime_debug.js
  500. var tempRet0 = 0;
  501. var setTempRet0 = (value) => { tempRet0 = value; };
  502. var getTempRet0 = () => tempRet0;
  503. // === Preamble library stuff ===
  504. // Documentation for the public APIs defined in this file must be updated in:
  505. // site/source/docs/api_reference/preamble.js.rst
  506. // A prebuilt local version of the documentation is available at:
  507. // site/build/text/docs/api_reference/preamble.js.txt
  508. // You can also build docs locally as HTML or other formats in site/
  509. // An online HTML version (which may be of a different version of Emscripten)
  510. // is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
  511. var wasmBinary;
  512. if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];legacyModuleProp('wasmBinary', 'wasmBinary');
  513. var noExitRuntime = Module['noExitRuntime'] || true;legacyModuleProp('noExitRuntime', 'noExitRuntime');
  514. if (typeof WebAssembly != 'object') {
  515. abort('no native wasm support detected');
  516. }
  517. // include: runtime_safe_heap.js
  518. // In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking.
  519. // In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties)
  520. /** @param {number} ptr
  521. @param {number} value
  522. @param {string} type
  523. @param {number|boolean=} noSafe */
  524. function setValue(ptr, value, type = 'i8', noSafe) {
  525. if (type.charAt(type.length-1) === '*') type = 'i32';
  526. switch (type) {
  527. case 'i1': HEAP8[((ptr)>>0)] = value; break;
  528. case 'i8': HEAP8[((ptr)>>0)] = value; break;
  529. case 'i16': HEAP16[((ptr)>>1)] = value; break;
  530. case 'i32': HEAP32[((ptr)>>2)] = value; break;
  531. case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((ptr)>>2)] = tempI64[0],HEAP32[(((ptr)+(4))>>2)] = tempI64[1]); break;
  532. case 'float': HEAPF32[((ptr)>>2)] = value; break;
  533. case 'double': HEAPF64[((ptr)>>3)] = value; break;
  534. default: abort('invalid type for setValue: ' + type);
  535. }
  536. }
  537. /** @param {number} ptr
  538. @param {string} type
  539. @param {number|boolean=} noSafe */
  540. function getValue(ptr, type = 'i8', noSafe) {
  541. if (type.charAt(type.length-1) === '*') type = 'i32';
  542. switch (type) {
  543. case 'i1': return HEAP8[((ptr)>>0)];
  544. case 'i8': return HEAP8[((ptr)>>0)];
  545. case 'i16': return HEAP16[((ptr)>>1)];
  546. case 'i32': return HEAP32[((ptr)>>2)];
  547. case 'i64': return HEAP32[((ptr)>>2)];
  548. case 'float': return HEAPF32[((ptr)>>2)];
  549. case 'double': return Number(HEAPF64[((ptr)>>3)]);
  550. default: abort('invalid type for getValue: ' + type);
  551. }
  552. return null;
  553. }
  554. // end include: runtime_safe_heap.js
  555. // Wasm globals
  556. var wasmMemory;
  557. //========================================
  558. // Runtime essentials
  559. //========================================
  560. // whether we are quitting the application. no code should run after this.
  561. // set in exit() and abort()
  562. var ABORT = false;
  563. // set by exit() and abort(). Passed to 'onExit' handler.
  564. // NOTE: This is also used as the process return code code in shell environments
  565. // but only when noExitRuntime is false.
  566. var EXITSTATUS;
  567. /** @type {function(*, string=)} */
  568. function assert(condition, text) {
  569. if (!condition) {
  570. abort('Assertion failed' + (text ? ': ' + text : ''));
  571. }
  572. }
  573. // Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
  574. function getCFunc(ident) {
  575. var func = Module['_' + ident]; // closure exported function
  576. assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
  577. return func;
  578. }
  579. // C calling interface.
  580. /** @param {string|null=} returnType
  581. @param {Array=} argTypes
  582. @param {Arguments|Array=} args
  583. @param {Object=} opts */
  584. function ccall(ident, returnType, argTypes, args, opts) {
  585. // For fast lookup of conversion functions
  586. var toC = {
  587. 'string': function(str) {
  588. var ret = 0;
  589. if (str !== null && str !== undefined && str !== 0) { // null string
  590. // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
  591. var len = (str.length << 2) + 1;
  592. ret = stackAlloc(len);
  593. stringToUTF8(str, ret, len);
  594. }
  595. return ret;
  596. },
  597. 'array': function(arr) {
  598. var ret = stackAlloc(arr.length);
  599. writeArrayToMemory(arr, ret);
  600. return ret;
  601. }
  602. };
  603. function convertReturnValue(ret) {
  604. if (returnType === 'string') return UTF8ToString(ret);
  605. if (returnType === 'boolean') return Boolean(ret);
  606. return ret;
  607. }
  608. var func = getCFunc(ident);
  609. var cArgs = [];
  610. var stack = 0;
  611. assert(returnType !== 'array', 'Return type should not be "array".');
  612. if (args) {
  613. for (var i = 0; i < args.length; i++) {
  614. var converter = toC[argTypes[i]];
  615. if (converter) {
  616. if (stack === 0) stack = stackSave();
  617. cArgs[i] = converter(args[i]);
  618. } else {
  619. cArgs[i] = args[i];
  620. }
  621. }
  622. }
  623. var ret = func.apply(null, cArgs);
  624. function onDone(ret) {
  625. if (stack !== 0) stackRestore(stack);
  626. return convertReturnValue(ret);
  627. }
  628. ret = onDone(ret);
  629. return ret;
  630. }
  631. /** @param {string=} returnType
  632. @param {Array=} argTypes
  633. @param {Object=} opts */
  634. function cwrap(ident, returnType, argTypes, opts) {
  635. return function() {
  636. return ccall(ident, returnType, argTypes, arguments, opts);
  637. }
  638. }
  639. // We used to include malloc/free by default in the past. Show a helpful error in
  640. // builds with assertions.
  641. function _free() {
  642. // Show a helpful error since we used to include free by default in the past.
  643. abort("free() called but not included in the build - add '_free' to EXPORTED_FUNCTIONS");
  644. }
  645. // include: runtime_legacy.js
  646. var ALLOC_NORMAL = 0; // Tries to use _malloc()
  647. var ALLOC_STACK = 1; // Lives for the duration of the current function call
  648. /**
  649. * allocate(): This function is no longer used by emscripten but is kept around to avoid
  650. * breaking external users.
  651. * You should normally not use allocate(), and instead allocate
  652. * memory using _malloc()/stackAlloc(), initialize it with
  653. * setValue(), and so forth.
  654. * @param {(Uint8Array|Array<number>)} slab: An array of data.
  655. * @param {number=} allocator : How to allocate memory, see ALLOC_*
  656. */
  657. function allocate(slab, allocator) {
  658. var ret;
  659. assert(typeof allocator == 'number', 'allocate no longer takes a type argument')
  660. assert(typeof slab != 'number', 'allocate no longer takes a number as arg0')
  661. if (allocator == ALLOC_STACK) {
  662. ret = stackAlloc(slab.length);
  663. } else {
  664. ret = _malloc(slab.length);
  665. }
  666. if (!slab.subarray && !slab.slice) {
  667. slab = new Uint8Array(slab);
  668. }
  669. HEAPU8.set(slab, ret);
  670. return ret;
  671. }
  672. // end include: runtime_legacy.js
  673. // include: runtime_strings.js
  674. // runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime.
  675. // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
  676. // a copy of that string as a Javascript String object.
  677. var UTF8Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf8') : undefined;
  678. /**
  679. * @param {number} idx
  680. * @param {number=} maxBytesToRead
  681. * @return {string}
  682. */
  683. function UTF8ArrayToString(heap, idx, maxBytesToRead) {
  684. var endIdx = idx + maxBytesToRead;
  685. var endPtr = idx;
  686. // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
  687. // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
  688. // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
  689. while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
  690. if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
  691. return UTF8Decoder.decode(heap.subarray(idx, endPtr));
  692. } else {
  693. var str = '';
  694. // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
  695. while (idx < endPtr) {
  696. // For UTF8 byte structure, see:
  697. // http://en.wikipedia.org/wiki/UTF-8#Description
  698. // https://www.ietf.org/rfc/rfc2279.txt
  699. // https://tools.ietf.org/html/rfc3629
  700. var u0 = heap[idx++];
  701. if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
  702. var u1 = heap[idx++] & 63;
  703. if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
  704. var u2 = heap[idx++] & 63;
  705. if ((u0 & 0xF0) == 0xE0) {
  706. u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
  707. } else {
  708. if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string in wasm memory to a JS string!');
  709. u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
  710. }
  711. if (u0 < 0x10000) {
  712. str += String.fromCharCode(u0);
  713. } else {
  714. var ch = u0 - 0x10000;
  715. str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
  716. }
  717. }
  718. }
  719. return str;
  720. }
  721. // Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a
  722. // copy of that string as a Javascript String object.
  723. // maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit
  724. // this parameter to scan the string until the first \0 byte. If maxBytesToRead is
  725. // passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the
  726. // middle, then the string will cut short at that byte index (i.e. maxBytesToRead will
  727. // not produce a string of exact length [ptr, ptr+maxBytesToRead[)
  728. // N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may
  729. // throw JS JIT optimizations off, so it is worth to consider consistently using one
  730. // style or the other.
  731. /**
  732. * @param {number} ptr
  733. * @param {number=} maxBytesToRead
  734. * @return {string}
  735. */
  736. function UTF8ToString(ptr, maxBytesToRead) {
  737. ;
  738. return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
  739. }
  740. // Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
  741. // encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
  742. // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
  743. // Parameters:
  744. // str: the Javascript string to copy.
  745. // heap: the array to copy to. Each index in this array is assumed to be one 8-byte element.
  746. // outIdx: The starting offset in the array to begin the copying.
  747. // maxBytesToWrite: The maximum number of bytes this function can write to the array.
  748. // This count should include the null terminator,
  749. // i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
  750. // maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
  751. // Returns the number of bytes written, EXCLUDING the null terminator.
  752. function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
  753. if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
  754. return 0;
  755. var startIdx = outIdx;
  756. var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
  757. for (var i = 0; i < str.length; ++i) {
  758. // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
  759. // See http://unicode.org/faq/utf_bom.html#utf16-3
  760. // For UTF8 byte structure, see http://en.wikipedia.org/wiki/UTF-8#Description and https://www.ietf.org/rfc/rfc2279.txt and https://tools.ietf.org/html/rfc3629
  761. var u = str.charCodeAt(i); // possibly a lead surrogate
  762. if (u >= 0xD800 && u <= 0xDFFF) {
  763. var u1 = str.charCodeAt(++i);
  764. u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
  765. }
  766. if (u <= 0x7F) {
  767. if (outIdx >= endIdx) break;
  768. heap[outIdx++] = u;
  769. } else if (u <= 0x7FF) {
  770. if (outIdx + 1 >= endIdx) break;
  771. heap[outIdx++] = 0xC0 | (u >> 6);
  772. heap[outIdx++] = 0x80 | (u & 63);
  773. } else if (u <= 0xFFFF) {
  774. if (outIdx + 2 >= endIdx) break;
  775. heap[outIdx++] = 0xE0 | (u >> 12);
  776. heap[outIdx++] = 0x80 | ((u >> 6) & 63);
  777. heap[outIdx++] = 0x80 | (u & 63);
  778. } else {
  779. if (outIdx + 3 >= endIdx) break;
  780. if (u > 0x10FFFF) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to a UTF-8 string in wasm memory! (Valid unicode code points should be in range 0-0x10FFFF).');
  781. heap[outIdx++] = 0xF0 | (u >> 18);
  782. heap[outIdx++] = 0x80 | ((u >> 12) & 63);
  783. heap[outIdx++] = 0x80 | ((u >> 6) & 63);
  784. heap[outIdx++] = 0x80 | (u & 63);
  785. }
  786. }
  787. // Null-terminate the pointer to the buffer.
  788. heap[outIdx] = 0;
  789. return outIdx - startIdx;
  790. }
  791. // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
  792. // null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
  793. // Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
  794. // Returns the number of bytes written, EXCLUDING the null terminator.
  795. function stringToUTF8(str, outPtr, maxBytesToWrite) {
  796. assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
  797. return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
  798. }
  799. // Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
  800. function lengthBytesUTF8(str) {
  801. var len = 0;
  802. for (var i = 0; i < str.length; ++i) {
  803. // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! So decode UTF16->UTF32->UTF8.
  804. // See http://unicode.org/faq/utf_bom.html#utf16-3
  805. var u = str.charCodeAt(i); // possibly a lead surrogate
  806. if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
  807. if (u <= 0x7F) ++len;
  808. else if (u <= 0x7FF) len += 2;
  809. else if (u <= 0xFFFF) len += 3;
  810. else len += 4;
  811. }
  812. return len;
  813. }
  814. // end include: runtime_strings.js
  815. // include: runtime_strings_extra.js
  816. // runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime.
  817. // Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
  818. // a copy of that string as a Javascript String object.
  819. function AsciiToString(ptr) {
  820. var str = '';
  821. while (1) {
  822. var ch = HEAPU8[((ptr++)>>0)];
  823. if (!ch) return str;
  824. str += String.fromCharCode(ch);
  825. }
  826. }
  827. // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
  828. // null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
  829. function stringToAscii(str, outPtr) {
  830. return writeAsciiToMemory(str, outPtr, false);
  831. }
  832. // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
  833. // a copy of that string as a Javascript String object.
  834. var UTF16Decoder = typeof TextDecoder != 'undefined' ? new TextDecoder('utf-16le') : undefined;
  835. function UTF16ToString(ptr, maxBytesToRead) {
  836. assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!');
  837. var endPtr = ptr;
  838. // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
  839. // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
  840. var idx = endPtr >> 1;
  841. var maxIdx = idx + maxBytesToRead / 2;
  842. // If maxBytesToRead is not passed explicitly, it will be undefined, and this
  843. // will always evaluate to true. This saves on code size.
  844. while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
  845. endPtr = idx << 1;
  846. if (endPtr - ptr > 32 && UTF16Decoder) {
  847. return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
  848. } else {
  849. var str = '';
  850. // If maxBytesToRead is not passed explicitly, it will be undefined, and the for-loop's condition
  851. // will always evaluate to true. The loop is then terminated on the first null char.
  852. for (var i = 0; !(i >= maxBytesToRead / 2); ++i) {
  853. var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
  854. if (codeUnit == 0) break;
  855. // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
  856. str += String.fromCharCode(codeUnit);
  857. }
  858. return str;
  859. }
  860. }
  861. // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
  862. // null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
  863. // Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
  864. // Parameters:
  865. // str: the Javascript string to copy.
  866. // outPtr: Byte address in Emscripten HEAP where to write the string to.
  867. // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
  868. // terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
  869. // maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
  870. // Returns the number of bytes written, EXCLUDING the null terminator.
  871. function stringToUTF16(str, outPtr, maxBytesToWrite) {
  872. assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!');
  873. assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
  874. // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
  875. if (maxBytesToWrite === undefined) {
  876. maxBytesToWrite = 0x7FFFFFFF;
  877. }
  878. if (maxBytesToWrite < 2) return 0;
  879. maxBytesToWrite -= 2; // Null terminator.
  880. var startPtr = outPtr;
  881. var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
  882. for (var i = 0; i < numCharsToWrite; ++i) {
  883. // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
  884. var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
  885. HEAP16[((outPtr)>>1)] = codeUnit;
  886. outPtr += 2;
  887. }
  888. // Null-terminate the pointer to the HEAP.
  889. HEAP16[((outPtr)>>1)] = 0;
  890. return outPtr - startPtr;
  891. }
  892. // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
  893. function lengthBytesUTF16(str) {
  894. return str.length*2;
  895. }
  896. function UTF32ToString(ptr, maxBytesToRead) {
  897. assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!');
  898. var i = 0;
  899. var str = '';
  900. // If maxBytesToRead is not passed explicitly, it will be undefined, and this
  901. // will always evaluate to true. This saves on code size.
  902. while (!(i >= maxBytesToRead / 4)) {
  903. var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
  904. if (utf32 == 0) break;
  905. ++i;
  906. // Gotcha: fromCharCode constructs a character from a UTF-16 encoded code (pair), not from a Unicode code point! So encode the code point to UTF-16 for constructing.
  907. // See http://unicode.org/faq/utf_bom.html#utf16-3
  908. if (utf32 >= 0x10000) {
  909. var ch = utf32 - 0x10000;
  910. str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
  911. } else {
  912. str += String.fromCharCode(utf32);
  913. }
  914. }
  915. return str;
  916. }
  917. // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
  918. // null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
  919. // Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
  920. // Parameters:
  921. // str: the Javascript string to copy.
  922. // outPtr: Byte address in Emscripten HEAP where to write the string to.
  923. // maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
  924. // terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
  925. // maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
  926. // Returns the number of bytes written, EXCLUDING the null terminator.
  927. function stringToUTF32(str, outPtr, maxBytesToWrite) {
  928. assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!');
  929. assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
  930. // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
  931. if (maxBytesToWrite === undefined) {
  932. maxBytesToWrite = 0x7FFFFFFF;
  933. }
  934. if (maxBytesToWrite < 4) return 0;
  935. var startPtr = outPtr;
  936. var endPtr = startPtr + maxBytesToWrite - 4;
  937. for (var i = 0; i < str.length; ++i) {
  938. // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
  939. // See http://unicode.org/faq/utf_bom.html#utf16-3
  940. var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
  941. if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
  942. var trailSurrogate = str.charCodeAt(++i);
  943. codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
  944. }
  945. HEAP32[((outPtr)>>2)] = codeUnit;
  946. outPtr += 4;
  947. if (outPtr + 4 > endPtr) break;
  948. }
  949. // Null-terminate the pointer to the HEAP.
  950. HEAP32[((outPtr)>>2)] = 0;
  951. return outPtr - startPtr;
  952. }
  953. // Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
  954. function lengthBytesUTF32(str) {
  955. var len = 0;
  956. for (var i = 0; i < str.length; ++i) {
  957. // Gotcha: charCodeAt returns a 16-bit word that is a UTF-16 encoded code unit, not a Unicode code point of the character! We must decode the string to UTF-32 to the heap.
  958. // See http://unicode.org/faq/utf_bom.html#utf16-3
  959. var codeUnit = str.charCodeAt(i);
  960. if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
  961. len += 4;
  962. }
  963. return len;
  964. }
  965. // Allocate heap space for a JS string, and write it there.
  966. // It is the responsibility of the caller to free() that memory.
  967. function allocateUTF8(str) {
  968. var size = lengthBytesUTF8(str) + 1;
  969. var ret = _malloc(size);
  970. if (ret) stringToUTF8Array(str, HEAP8, ret, size);
  971. return ret;
  972. }
  973. // Allocate stack space for a JS string, and write it there.
  974. function allocateUTF8OnStack(str) {
  975. var size = lengthBytesUTF8(str) + 1;
  976. var ret = stackAlloc(size);
  977. stringToUTF8Array(str, HEAP8, ret, size);
  978. return ret;
  979. }
  980. // Deprecated: This function should not be called because it is unsafe and does not provide
  981. // a maximum length limit of how many bytes it is allowed to write. Prefer calling the
  982. // function stringToUTF8Array() instead, which takes in a maximum length that can be used
  983. // to be secure from out of bounds writes.
  984. /** @deprecated
  985. @param {boolean=} dontAddNull */
  986. function writeStringToMemory(string, buffer, dontAddNull) {
  987. warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
  988. var /** @type {number} */ lastChar, /** @type {number} */ end;
  989. if (dontAddNull) {
  990. // stringToUTF8Array always appends null. If we don't want to do that, remember the
  991. // character that existed at the location where the null will be placed, and restore
  992. // that after the write (below).
  993. end = buffer + lengthBytesUTF8(string);
  994. lastChar = HEAP8[end];
  995. }
  996. stringToUTF8(string, buffer, Infinity);
  997. if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
  998. }
  999. function writeArrayToMemory(array, buffer) {
  1000. assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
  1001. HEAP8.set(array, buffer);
  1002. }
  1003. /** @param {boolean=} dontAddNull */
  1004. function writeAsciiToMemory(str, buffer, dontAddNull) {
  1005. for (var i = 0; i < str.length; ++i) {
  1006. assert(str.charCodeAt(i) === (str.charCodeAt(i) & 0xff));
  1007. HEAP8[((buffer++)>>0)] = str.charCodeAt(i);
  1008. }
  1009. // Null-terminate the pointer to the HEAP.
  1010. if (!dontAddNull) HEAP8[((buffer)>>0)] = 0;
  1011. }
  1012. // end include: runtime_strings_extra.js
  1013. // Memory management
  1014. var HEAP,
  1015. /** @type {!ArrayBuffer} */
  1016. buffer,
  1017. /** @type {!Int8Array} */
  1018. HEAP8,
  1019. /** @type {!Uint8Array} */
  1020. HEAPU8,
  1021. /** @type {!Int16Array} */
  1022. HEAP16,
  1023. /** @type {!Uint16Array} */
  1024. HEAPU16,
  1025. /** @type {!Int32Array} */
  1026. HEAP32,
  1027. /** @type {!Uint32Array} */
  1028. HEAPU32,
  1029. /** @type {!Float32Array} */
  1030. HEAPF32,
  1031. /** @type {!Float64Array} */
  1032. HEAPF64;
  1033. function updateGlobalBufferAndViews(buf) {
  1034. buffer = buf;
  1035. Module['HEAP8'] = HEAP8 = new Int8Array(buf);
  1036. Module['HEAP16'] = HEAP16 = new Int16Array(buf);
  1037. Module['HEAP32'] = HEAP32 = new Int32Array(buf);
  1038. Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf);
  1039. Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf);
  1040. Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf);
  1041. Module['HEAPF32'] = HEAPF32 = new Float32Array(buf);
  1042. Module['HEAPF64'] = HEAPF64 = new Float64Array(buf);
  1043. }
  1044. var TOTAL_STACK = 5242880;
  1045. if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime')
  1046. var INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;legacyModuleProp('INITIAL_MEMORY', 'INITIAL_MEMORY');
  1047. assert(INITIAL_MEMORY >= TOTAL_STACK, 'INITIAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
  1048. // check for full engine support (use string 'subarray' to avoid closure compiler confusion)
  1049. assert(typeof Int32Array != 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray != undefined && Int32Array.prototype.set != undefined,
  1050. 'JS engine does not provide full typed array support');
  1051. // If memory is defined in wasm, the user can't provide it.
  1052. assert(!Module['wasmMemory'], 'Use of `wasmMemory` detected. Use -s IMPORTED_MEMORY to define wasmMemory externally');
  1053. assert(INITIAL_MEMORY == 16777216, 'Detected runtime INITIAL_MEMORY setting. Use -s IMPORTED_MEMORY to define wasmMemory dynamically');
  1054. // include: runtime_init_table.js
  1055. // In regular non-RELOCATABLE mode the table is exported
  1056. // from the wasm module and this will be assigned once
  1057. // the exports are available.
  1058. var wasmTable;
  1059. // end include: runtime_init_table.js
  1060. // include: runtime_stack_check.js
  1061. // Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
  1062. function writeStackCookie() {
  1063. var max = _emscripten_stack_get_end();
  1064. assert((max & 3) == 0);
  1065. // The stack grows downwards
  1066. HEAP32[((max + 4)>>2)] = 0x2135467;
  1067. HEAP32[((max + 8)>>2)] = 0x89BACDFE;
  1068. // Also test the global address 0 for integrity.
  1069. HEAP32[0] = 0x63736d65; /* 'emsc' */
  1070. }
  1071. function checkStackCookie() {
  1072. if (ABORT) return;
  1073. var max = _emscripten_stack_get_end();
  1074. var cookie1 = HEAPU32[((max + 4)>>2)];
  1075. var cookie2 = HEAPU32[((max + 8)>>2)];
  1076. if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) {
  1077. abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x' + cookie2.toString(16) + ' 0x' + cookie1.toString(16));
  1078. }
  1079. // Also test the global address 0 for integrity.
  1080. if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
  1081. }
  1082. // end include: runtime_stack_check.js
  1083. // include: runtime_assertions.js
  1084. // Endianness check
  1085. (function() {
  1086. var h16 = new Int16Array(1);
  1087. var h8 = new Int8Array(h16.buffer);
  1088. h16[0] = 0x6373;
  1089. if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian! (Run with -s SUPPORT_BIG_ENDIAN=1 to bypass)';
  1090. })();
  1091. // end include: runtime_assertions.js
  1092. var __ATPRERUN__ = []; // functions called before the runtime is initialized
  1093. var __ATINIT__ = []; // functions called during startup
  1094. var __ATMAIN__ = []; // functions called when main() is to be run
  1095. var __ATEXIT__ = []; // functions called during shutdown
  1096. var __ATPOSTRUN__ = []; // functions called after the main() is called
  1097. var runtimeInitialized = false;
  1098. var runtimeExited = false;
  1099. var runtimeKeepaliveCounter = 0;
  1100. function keepRuntimeAlive() {
  1101. return noExitRuntime || runtimeKeepaliveCounter > 0;
  1102. }
  1103. function preRun() {
  1104. if (Module['preRun']) {
  1105. if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
  1106. while (Module['preRun'].length) {
  1107. addOnPreRun(Module['preRun'].shift());
  1108. }
  1109. }
  1110. callRuntimeCallbacks(__ATPRERUN__);
  1111. }
  1112. function initRuntime() {
  1113. checkStackCookie();
  1114. assert(!runtimeInitialized);
  1115. runtimeInitialized = true;
  1116. if (!Module["noFSInit"] && !FS.init.initialized)
  1117. FS.init();
  1118. FS.ignorePermissions = false;
  1119. TTY.init();
  1120. callRuntimeCallbacks(__ATINIT__);
  1121. }
  1122. function preMain() {
  1123. checkStackCookie();
  1124. callRuntimeCallbacks(__ATMAIN__);
  1125. }
  1126. function exitRuntime() {
  1127. checkStackCookie();
  1128. runtimeExited = true;
  1129. }
  1130. function postRun() {
  1131. checkStackCookie();
  1132. if (Module['postRun']) {
  1133. if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
  1134. while (Module['postRun'].length) {
  1135. addOnPostRun(Module['postRun'].shift());
  1136. }
  1137. }
  1138. callRuntimeCallbacks(__ATPOSTRUN__);
  1139. }
  1140. function addOnPreRun(cb) {
  1141. __ATPRERUN__.unshift(cb);
  1142. }
  1143. function addOnInit(cb) {
  1144. __ATINIT__.unshift(cb);
  1145. }
  1146. function addOnPreMain(cb) {
  1147. __ATMAIN__.unshift(cb);
  1148. }
  1149. function addOnExit(cb) {
  1150. }
  1151. function addOnPostRun(cb) {
  1152. __ATPOSTRUN__.unshift(cb);
  1153. }
  1154. // include: runtime_math.js
  1155. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
  1156. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
  1157. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
  1158. // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
  1159. assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
  1160. assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
  1161. assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
  1162. assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
  1163. // end include: runtime_math.js
  1164. // A counter of dependencies for calling run(). If we need to
  1165. // do asynchronous work before running, increment this and
  1166. // decrement it. Incrementing must happen in a place like
  1167. // Module.preRun (used by emcc to add file preloading).
  1168. // Note that you can add dependencies in preRun, even though
  1169. // it happens right before run - run will be postponed until
  1170. // the dependencies are met.
  1171. var runDependencies = 0;
  1172. var runDependencyWatcher = null;
  1173. var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
  1174. var runDependencyTracking = {};
  1175. function getUniqueRunDependency(id) {
  1176. var orig = id;
  1177. while (1) {
  1178. if (!runDependencyTracking[id]) return id;
  1179. id = orig + Math.random();
  1180. }
  1181. }
  1182. function addRunDependency(id) {
  1183. runDependencies++;
  1184. if (Module['monitorRunDependencies']) {
  1185. Module['monitorRunDependencies'](runDependencies);
  1186. }
  1187. if (id) {
  1188. assert(!runDependencyTracking[id]);
  1189. runDependencyTracking[id] = 1;
  1190. if (runDependencyWatcher === null && typeof setInterval != 'undefined') {
  1191. // Check for missing dependencies every few seconds
  1192. runDependencyWatcher = setInterval(function() {
  1193. if (ABORT) {
  1194. clearInterval(runDependencyWatcher);
  1195. runDependencyWatcher = null;
  1196. return;
  1197. }
  1198. var shown = false;
  1199. for (var dep in runDependencyTracking) {
  1200. if (!shown) {
  1201. shown = true;
  1202. err('still waiting on run dependencies:');
  1203. }
  1204. err('dependency: ' + dep);
  1205. }
  1206. if (shown) {
  1207. err('(end of list)');
  1208. }
  1209. }, 10000);
  1210. }
  1211. } else {
  1212. err('warning: run dependency added without ID');
  1213. }
  1214. }
  1215. function removeRunDependency(id) {
  1216. runDependencies--;
  1217. if (Module['monitorRunDependencies']) {
  1218. Module['monitorRunDependencies'](runDependencies);
  1219. }
  1220. if (id) {
  1221. assert(runDependencyTracking[id]);
  1222. delete runDependencyTracking[id];
  1223. } else {
  1224. err('warning: run dependency removed without ID');
  1225. }
  1226. if (runDependencies == 0) {
  1227. if (runDependencyWatcher !== null) {
  1228. clearInterval(runDependencyWatcher);
  1229. runDependencyWatcher = null;
  1230. }
  1231. if (dependenciesFulfilled) {
  1232. var callback = dependenciesFulfilled;
  1233. dependenciesFulfilled = null;
  1234. callback(); // can add another dependenciesFulfilled
  1235. }
  1236. }
  1237. }
  1238. Module["preloadedImages"] = {}; // maps url to image data
  1239. Module["preloadedAudios"] = {}; // maps url to audio data
  1240. /** @param {string|number=} what */
  1241. function abort(what) {
  1242. {
  1243. if (Module['onAbort']) {
  1244. Module['onAbort'](what);
  1245. }
  1246. }
  1247. what = 'Aborted(' + what + ')';
  1248. // TODO(sbc): Should we remove printing and leave it up to whoever
  1249. // catches the exception?
  1250. err(what);
  1251. ABORT = true;
  1252. EXITSTATUS = 1;
  1253. // Use a wasm runtime error, because a JS error might be seen as a foreign
  1254. // exception, which means we'd run destructors on it. We need the error to
  1255. // simply make the program stop.
  1256. // Suppress closure compiler warning here. Closure compiler's builtin extern
  1257. // defintion for WebAssembly.RuntimeError claims it takes no arguments even
  1258. // though it can.
  1259. // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure gets fixed.
  1260. /** @suppress {checkTypes} */
  1261. var e = new WebAssembly.RuntimeError(what);
  1262. // Throw the error whether or not MODULARIZE is set because abort is used
  1263. // in code paths apart from instantiation where an exception is expected
  1264. // to be thrown when abort is called.
  1265. throw e;
  1266. }
  1267. // {{MEM_INITIALIZER}}
  1268. // include: memoryprofiler.js
  1269. // end include: memoryprofiler.js
  1270. // include: URIUtils.js
  1271. // Prefix of data URIs emitted by SINGLE_FILE and related options.
  1272. var dataURIPrefix = 'data:application/octet-stream;base64,';
  1273. // Indicates whether filename is a base64 data URI.
  1274. function isDataURI(filename) {
  1275. // Prefix of data URIs emitted by SINGLE_FILE and related options.
  1276. return filename.startsWith(dataURIPrefix);
  1277. }
  1278. // Indicates whether filename is delivered via file protocol (as opposed to http/https)
  1279. function isFileURI(filename) {
  1280. return filename.startsWith('file://');
  1281. }
  1282. // end include: URIUtils.js
  1283. /** @param {boolean=} fixedasm */
  1284. function createExportWrapper(name, fixedasm) {
  1285. return function() {
  1286. var displayName = name;
  1287. var asm = fixedasm;
  1288. if (!fixedasm) {
  1289. asm = Module['asm'];
  1290. }
  1291. assert(runtimeInitialized, 'native function `' + displayName + '` called before runtime initialization');
  1292. assert(!runtimeExited, 'native function `' + displayName + '` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
  1293. if (!asm[name]) {
  1294. assert(asm[name], 'exported native function `' + displayName + '` not found');
  1295. }
  1296. return asm[name].apply(null, arguments);
  1297. };
  1298. }
  1299. var wasmBinaryFile;
  1300. wasmBinaryFile = '第七章作业2.wasm';
  1301. if (!isDataURI(wasmBinaryFile)) {
  1302. wasmBinaryFile = locateFile(wasmBinaryFile);
  1303. }
  1304. function getBinary(file) {
  1305. try {
  1306. if (file == wasmBinaryFile && wasmBinary) {
  1307. return new Uint8Array(wasmBinary);
  1308. }
  1309. if (readBinary) {
  1310. return readBinary(file);
  1311. } else {
  1312. throw "both async and sync fetching of the wasm failed";
  1313. }
  1314. }
  1315. catch (err) {
  1316. abort(err);
  1317. }
  1318. }
  1319. function getBinaryPromise() {
  1320. // If we don't have the binary yet, try to to load it asynchronously.
  1321. // Fetch has some additional restrictions over XHR, like it can't be used on a file:// url.
  1322. // See https://github.com/github/fetch/pull/92#issuecomment-140665932
  1323. // Cordova or Electron apps are typically loaded from a file:// url.
  1324. // So use fetch if it is available and the url is not a file, otherwise fall back to XHR.
  1325. if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER)) {
  1326. if (typeof fetch == 'function'
  1327. && !isFileURI(wasmBinaryFile)
  1328. ) {
  1329. return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
  1330. if (!response['ok']) {
  1331. throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
  1332. }
  1333. return response['arrayBuffer']();
  1334. }).catch(function () {
  1335. return getBinary(wasmBinaryFile);
  1336. });
  1337. }
  1338. else {
  1339. if (readAsync) {
  1340. // fetch is not available or url is file => try XHR (readAsync uses XHR internally)
  1341. return new Promise(function(resolve, reject) {
  1342. readAsync(wasmBinaryFile, function(response) { resolve(new Uint8Array(/** @type{!ArrayBuffer} */(response))) }, reject)
  1343. });
  1344. }
  1345. }
  1346. }
  1347. // Otherwise, getBinary should be able to get it synchronously
  1348. return Promise.resolve().then(function() { return getBinary(wasmBinaryFile); });
  1349. }
  1350. // Create the wasm instance.
  1351. // Receives the wasm imports, returns the exports.
  1352. function createWasm() {
  1353. // prepare imports
  1354. var info = {
  1355. 'env': asmLibraryArg,
  1356. 'wasi_snapshot_preview1': asmLibraryArg,
  1357. };
  1358. // Load the wasm module and create an instance of using native support in the JS engine.
  1359. // handle a generated wasm instance, receiving its exports and
  1360. // performing other necessary setup
  1361. /** @param {WebAssembly.Module=} module*/
  1362. function receiveInstance(instance, module) {
  1363. var exports = instance.exports;
  1364. Module['asm'] = exports;
  1365. wasmMemory = Module['asm']['memory'];
  1366. assert(wasmMemory, "memory not found in wasm exports");
  1367. // This assertion doesn't hold when emscripten is run in --post-link
  1368. // mode.
  1369. // TODO(sbc): Read INITIAL_MEMORY out of the wasm file in post-link mode.
  1370. //assert(wasmMemory.buffer.byteLength === 16777216);
  1371. updateGlobalBufferAndViews(wasmMemory.buffer);
  1372. wasmTable = Module['asm']['__indirect_function_table'];
  1373. assert(wasmTable, "table not found in wasm exports");
  1374. addOnInit(Module['asm']['__wasm_call_ctors']);
  1375. removeRunDependency('wasm-instantiate');
  1376. }
  1377. // we can't run yet (except in a pthread, where we have a custom sync instantiator)
  1378. addRunDependency('wasm-instantiate');
  1379. // Prefer streaming instantiation if available.
  1380. // Async compilation can be confusing when an error on the page overwrites Module
  1381. // (for example, if the order of elements is wrong, and the one defining Module is
  1382. // later), so we save Module and check it later.
  1383. var trueModule = Module;
  1384. function receiveInstantiationResult(result) {
  1385. // 'result' is a ResultObject object which has both the module and instance.
  1386. // receiveInstance() will swap in the exports (to Module.asm) so they can be called
  1387. assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
  1388. trueModule = null;
  1389. // TODO: Due to Closure regression https://github.com/google/closure-compiler/issues/3193, the above line no longer optimizes out down to the following line.
  1390. // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.
  1391. receiveInstance(result['instance']);
  1392. }
  1393. function instantiateArrayBuffer(receiver) {
  1394. return getBinaryPromise().then(function(binary) {
  1395. return WebAssembly.instantiate(binary, info);
  1396. }).then(function (instance) {
  1397. return instance;
  1398. }).then(receiver, function(reason) {
  1399. err('failed to asynchronously prepare wasm: ' + reason);
  1400. // Warn on some common problems.
  1401. if (isFileURI(wasmBinaryFile)) {
  1402. err('warning: Loading from a file URI (' + wasmBinaryFile + ') is not supported in most browsers. See https://emscripten.org/docs/getting_started/FAQ.html#how-do-i-run-a-local-webserver-for-testing-why-does-my-program-stall-in-downloading-or-preparing');
  1403. }
  1404. abort(reason);
  1405. });
  1406. }
  1407. function instantiateAsync() {
  1408. if (!wasmBinary &&
  1409. typeof WebAssembly.instantiateStreaming == 'function' &&
  1410. !isDataURI(wasmBinaryFile) &&
  1411. // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
  1412. !isFileURI(wasmBinaryFile) &&
  1413. typeof fetch == 'function') {
  1414. return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
  1415. // Suppress closure warning here since the upstream definition for
  1416. // instantiateStreaming only allows Promise<Repsponse> rather than
  1417. // an actual Response.
  1418. // TODO(https://github.com/google/closure-compiler/pull/3913): Remove if/when upstream closure is fixed.
  1419. /** @suppress {checkTypes} */
  1420. var result = WebAssembly.instantiateStreaming(response, info);
  1421. return result.then(
  1422. receiveInstantiationResult,
  1423. function(reason) {
  1424. // We expect the most common failure cause to be a bad MIME type for the binary,
  1425. // in which case falling back to ArrayBuffer instantiation should work.
  1426. err('wasm streaming compile failed: ' + reason);
  1427. err('falling back to ArrayBuffer instantiation');
  1428. return instantiateArrayBuffer(receiveInstantiationResult);
  1429. });
  1430. });
  1431. } else {
  1432. return instantiateArrayBuffer(receiveInstantiationResult);
  1433. }
  1434. }
  1435. // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
  1436. // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
  1437. // to any other async startup actions they are performing.
  1438. if (Module['instantiateWasm']) {
  1439. try {
  1440. var exports = Module['instantiateWasm'](info, receiveInstance);
  1441. return exports;
  1442. } catch(e) {
  1443. err('Module.instantiateWasm callback failed with error: ' + e);
  1444. return false;
  1445. }
  1446. }
  1447. instantiateAsync();
  1448. return {}; // no exports yet; we'll fill them in later
  1449. }
  1450. // Globals used by JS i64 conversions (see makeSetValue)
  1451. var tempDouble;
  1452. var tempI64;
  1453. // === Body ===
  1454. var ASM_CONSTS = {
  1455. };
  1456. function callRuntimeCallbacks(callbacks) {
  1457. while (callbacks.length > 0) {
  1458. var callback = callbacks.shift();
  1459. if (typeof callback == 'function') {
  1460. callback(Module); // Pass the module as the first argument.
  1461. continue;
  1462. }
  1463. var func = callback.func;
  1464. if (typeof func == 'number') {
  1465. if (callback.arg === undefined) {
  1466. getWasmTableEntry(func)();
  1467. } else {
  1468. getWasmTableEntry(func)(callback.arg);
  1469. }
  1470. } else {
  1471. func(callback.arg === undefined ? null : callback.arg);
  1472. }
  1473. }
  1474. }
  1475. function withStackSave(f) {
  1476. var stack = stackSave();
  1477. var ret = f();
  1478. stackRestore(stack);
  1479. return ret;
  1480. }
  1481. function demangle(func) {
  1482. warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
  1483. return func;
  1484. }
  1485. function demangleAll(text) {
  1486. var regex =
  1487. /\b_Z[\w\d_]+/g;
  1488. return text.replace(regex,
  1489. function(x) {
  1490. var y = demangle(x);
  1491. return x === y ? x : (y + ' [' + x + ']');
  1492. });
  1493. }
  1494. var wasmTableMirror = [];
  1495. function getWasmTableEntry(funcPtr) {
  1496. var func = wasmTableMirror[funcPtr];
  1497. if (!func) {
  1498. if (funcPtr >= wasmTableMirror.length) wasmTableMirror.length = funcPtr + 1;
  1499. wasmTableMirror[funcPtr] = func = wasmTable.get(funcPtr);
  1500. }
  1501. assert(wasmTable.get(funcPtr) == func, "JavaScript-side Wasm function table mirror is out of date!");
  1502. return func;
  1503. }
  1504. function handleException(e) {
  1505. // Certain exception types we do not treat as errors since they are used for
  1506. // internal control flow.
  1507. // 1. ExitStatus, which is thrown by exit()
  1508. // 2. "unwind", which is thrown by emscripten_unwind_to_js_event_loop() and others
  1509. // that wish to return to JS event loop.
  1510. if (e instanceof ExitStatus || e == 'unwind') {
  1511. return EXITSTATUS;
  1512. }
  1513. quit_(1, e);
  1514. }
  1515. function jsStackTrace() {
  1516. var error = new Error();
  1517. if (!error.stack) {
  1518. // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
  1519. // so try that as a special-case.
  1520. try {
  1521. throw new Error();
  1522. } catch(e) {
  1523. error = e;
  1524. }
  1525. if (!error.stack) {
  1526. return '(no stack trace available)';
  1527. }
  1528. }
  1529. return error.stack.toString();
  1530. }
  1531. function setWasmTableEntry(idx, func) {
  1532. wasmTable.set(idx, func);
  1533. wasmTableMirror[idx] = func;
  1534. }
  1535. function stackTrace() {
  1536. var js = jsStackTrace();
  1537. if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
  1538. return demangleAll(js);
  1539. }
  1540. function ___assert_fail(condition, filename, line, func) {
  1541. abort('Assertion failed: ' + UTF8ToString(condition) + ', at: ' + [filename ? UTF8ToString(filename) : 'unknown filename', line, func ? UTF8ToString(func) : 'unknown function']);
  1542. }
  1543. function ___cxa_allocate_exception(size) {
  1544. // Thrown object is prepended by exception metadata block
  1545. return _malloc(size + 16) + 16;
  1546. }
  1547. /** @constructor */
  1548. function ExceptionInfo(excPtr) {
  1549. this.excPtr = excPtr;
  1550. this.ptr = excPtr - 16;
  1551. this.set_type = function(type) {
  1552. HEAP32[(((this.ptr)+(4))>>2)] = type;
  1553. };
  1554. this.get_type = function() {
  1555. return HEAP32[(((this.ptr)+(4))>>2)];
  1556. };
  1557. this.set_destructor = function(destructor) {
  1558. HEAP32[(((this.ptr)+(8))>>2)] = destructor;
  1559. };
  1560. this.get_destructor = function() {
  1561. return HEAP32[(((this.ptr)+(8))>>2)];
  1562. };
  1563. this.set_refcount = function(refcount) {
  1564. HEAP32[((this.ptr)>>2)] = refcount;
  1565. };
  1566. this.set_caught = function (caught) {
  1567. caught = caught ? 1 : 0;
  1568. HEAP8[(((this.ptr)+(12))>>0)] = caught;
  1569. };
  1570. this.get_caught = function () {
  1571. return HEAP8[(((this.ptr)+(12))>>0)] != 0;
  1572. };
  1573. this.set_rethrown = function (rethrown) {
  1574. rethrown = rethrown ? 1 : 0;
  1575. HEAP8[(((this.ptr)+(13))>>0)] = rethrown;
  1576. };
  1577. this.get_rethrown = function () {
  1578. return HEAP8[(((this.ptr)+(13))>>0)] != 0;
  1579. };
  1580. // Initialize native structure fields. Should be called once after allocated.
  1581. this.init = function(type, destructor) {
  1582. this.set_type(type);
  1583. this.set_destructor(destructor);
  1584. this.set_refcount(0);
  1585. this.set_caught(false);
  1586. this.set_rethrown(false);
  1587. }
  1588. this.add_ref = function() {
  1589. var value = HEAP32[((this.ptr)>>2)];
  1590. HEAP32[((this.ptr)>>2)] = value + 1;
  1591. };
  1592. // Returns true if last reference released.
  1593. this.release_ref = function() {
  1594. var prev = HEAP32[((this.ptr)>>2)];
  1595. HEAP32[((this.ptr)>>2)] = prev - 1;
  1596. assert(prev > 0);
  1597. return prev === 1;
  1598. };
  1599. }
  1600. var exceptionLast = 0;
  1601. var uncaughtExceptionCount = 0;
  1602. function ___cxa_throw(ptr, type, destructor) {
  1603. var info = new ExceptionInfo(ptr);
  1604. // Initialize ExceptionInfo content after it was allocated in __cxa_allocate_exception.
  1605. info.init(type, destructor);
  1606. exceptionLast = ptr;
  1607. uncaughtExceptionCount++;
  1608. throw ptr + " - Exception catching is disabled, this exception cannot be caught. Compile with -s NO_DISABLE_EXCEPTION_CATCHING or -s EXCEPTION_CATCHING_ALLOWED=[..] to catch.";
  1609. }
  1610. function _abort() {
  1611. abort('native code called abort()');
  1612. }
  1613. function _emscripten_memcpy_big(dest, src, num) {
  1614. HEAPU8.copyWithin(dest, src, src + num);
  1615. }
  1616. function _emscripten_get_heap_max() {
  1617. return HEAPU8.length;
  1618. }
  1619. function abortOnCannotGrowMemory(requestedSize) {
  1620. abort('Cannot enlarge memory arrays to size ' + requestedSize + ' bytes (OOM). Either (1) compile with -s INITIAL_MEMORY=X with X higher than the current value ' + HEAP8.length + ', (2) compile with -s ALLOW_MEMORY_GROWTH=1 which allows increasing the size at runtime, or (3) if you want malloc to return NULL (0) instead of this abort, compile with -s ABORTING_MALLOC=0 ');
  1621. }
  1622. function _emscripten_resize_heap(requestedSize) {
  1623. var oldSize = HEAPU8.length;
  1624. requestedSize = requestedSize >>> 0;
  1625. abortOnCannotGrowMemory(requestedSize);
  1626. }
  1627. var ENV = {};
  1628. function getExecutableName() {
  1629. return thisProgram || './this.program';
  1630. }
  1631. function getEnvStrings() {
  1632. if (!getEnvStrings.strings) {
  1633. // Default values.
  1634. // Browser language detection #8751
  1635. var lang = ((typeof navigator == 'object' && navigator.languages && navigator.languages[0]) || 'C').replace('-', '_') + '.UTF-8';
  1636. var env = {
  1637. 'USER': 'web_user',
  1638. 'LOGNAME': 'web_user',
  1639. 'PATH': '/',
  1640. 'PWD': '/',
  1641. 'HOME': '/home/web_user',
  1642. 'LANG': lang,
  1643. '_': getExecutableName()
  1644. };
  1645. // Apply the user-provided values, if any.
  1646. for (var x in ENV) {
  1647. // x is a key in ENV; if ENV[x] is undefined, that means it was
  1648. // explicitly set to be so. We allow user code to do that to
  1649. // force variables with default values to remain unset.
  1650. if (ENV[x] === undefined) delete env[x];
  1651. else env[x] = ENV[x];
  1652. }
  1653. var strings = [];
  1654. for (var x in env) {
  1655. strings.push(x + '=' + env[x]);
  1656. }
  1657. getEnvStrings.strings = strings;
  1658. }
  1659. return getEnvStrings.strings;
  1660. }
  1661. var PATH = {splitPath:function(filename) {
  1662. var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
  1663. return splitPathRe.exec(filename).slice(1);
  1664. },normalizeArray:function(parts, allowAboveRoot) {
  1665. // if the path tries to go above the root, `up` ends up > 0
  1666. var up = 0;
  1667. for (var i = parts.length - 1; i >= 0; i--) {
  1668. var last = parts[i];
  1669. if (last === '.') {
  1670. parts.splice(i, 1);
  1671. } else if (last === '..') {
  1672. parts.splice(i, 1);
  1673. up++;
  1674. } else if (up) {
  1675. parts.splice(i, 1);
  1676. up--;
  1677. }
  1678. }
  1679. // if the path is allowed to go above the root, restore leading ..s
  1680. if (allowAboveRoot) {
  1681. for (; up; up--) {
  1682. parts.unshift('..');
  1683. }
  1684. }
  1685. return parts;
  1686. },normalize:function(path) {
  1687. var isAbsolute = path.charAt(0) === '/',
  1688. trailingSlash = path.substr(-1) === '/';
  1689. // Normalize the path
  1690. path = PATH.normalizeArray(path.split('/').filter(function(p) {
  1691. return !!p;
  1692. }), !isAbsolute).join('/');
  1693. if (!path && !isAbsolute) {
  1694. path = '.';
  1695. }
  1696. if (path && trailingSlash) {
  1697. path += '/';
  1698. }
  1699. return (isAbsolute ? '/' : '') + path;
  1700. },dirname:function(path) {
  1701. var result = PATH.splitPath(path),
  1702. root = result[0],
  1703. dir = result[1];
  1704. if (!root && !dir) {
  1705. // No dirname whatsoever
  1706. return '.';
  1707. }
  1708. if (dir) {
  1709. // It has a dirname, strip trailing slash
  1710. dir = dir.substr(0, dir.length - 1);
  1711. }
  1712. return root + dir;
  1713. },basename:function(path) {
  1714. // EMSCRIPTEN return '/'' for '/', not an empty string
  1715. if (path === '/') return '/';
  1716. path = PATH.normalize(path);
  1717. path = path.replace(/\/$/, "");
  1718. var lastSlash = path.lastIndexOf('/');
  1719. if (lastSlash === -1) return path;
  1720. return path.substr(lastSlash+1);
  1721. },extname:function(path) {
  1722. return PATH.splitPath(path)[3];
  1723. },join:function() {
  1724. var paths = Array.prototype.slice.call(arguments, 0);
  1725. return PATH.normalize(paths.join('/'));
  1726. },join2:function(l, r) {
  1727. return PATH.normalize(l + '/' + r);
  1728. }};
  1729. function getRandomDevice() {
  1730. if (typeof crypto == 'object' && typeof crypto['getRandomValues'] == 'function') {
  1731. // for modern web browsers
  1732. var randomBuffer = new Uint8Array(1);
  1733. return function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
  1734. } else
  1735. if (ENVIRONMENT_IS_NODE) {
  1736. // for nodejs with or without crypto support included
  1737. try {
  1738. var crypto_module = require('crypto');
  1739. // nodejs has crypto support
  1740. return function() { return crypto_module['randomBytes'](1)[0]; };
  1741. } catch (e) {
  1742. // nodejs doesn't have crypto support
  1743. }
  1744. }
  1745. // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
  1746. return function() { abort("no cryptographic support found for randomDevice. consider polyfilling it if you want to use something insecure like Math.random(), e.g. put this in a --pre-js: var crypto = { getRandomValues: function(array) { for (var i = 0; i < array.length; i++) array[i] = (Math.random()*256)|0 } };"); };
  1747. }
  1748. var PATH_FS = {resolve:function() {
  1749. var resolvedPath = '',
  1750. resolvedAbsolute = false;
  1751. for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
  1752. var path = (i >= 0) ? arguments[i] : FS.cwd();
  1753. // Skip empty and invalid entries
  1754. if (typeof path != 'string') {
  1755. throw new TypeError('Arguments to path.resolve must be strings');
  1756. } else if (!path) {
  1757. return ''; // an invalid portion invalidates the whole thing
  1758. }
  1759. resolvedPath = path + '/' + resolvedPath;
  1760. resolvedAbsolute = path.charAt(0) === '/';
  1761. }
  1762. // At this point the path should be resolved to a full absolute path, but
  1763. // handle relative paths to be safe (might happen when process.cwd() fails)
  1764. resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
  1765. return !!p;
  1766. }), !resolvedAbsolute).join('/');
  1767. return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
  1768. },relative:function(from, to) {
  1769. from = PATH_FS.resolve(from).substr(1);
  1770. to = PATH_FS.resolve(to).substr(1);
  1771. function trim(arr) {
  1772. var start = 0;
  1773. for (; start < arr.length; start++) {
  1774. if (arr[start] !== '') break;
  1775. }
  1776. var end = arr.length - 1;
  1777. for (; end >= 0; end--) {
  1778. if (arr[end] !== '') break;
  1779. }
  1780. if (start > end) return [];
  1781. return arr.slice(start, end - start + 1);
  1782. }
  1783. var fromParts = trim(from.split('/'));
  1784. var toParts = trim(to.split('/'));
  1785. var length = Math.min(fromParts.length, toParts.length);
  1786. var samePartsLength = length;
  1787. for (var i = 0; i < length; i++) {
  1788. if (fromParts[i] !== toParts[i]) {
  1789. samePartsLength = i;
  1790. break;
  1791. }
  1792. }
  1793. var outputParts = [];
  1794. for (var i = samePartsLength; i < fromParts.length; i++) {
  1795. outputParts.push('..');
  1796. }
  1797. outputParts = outputParts.concat(toParts.slice(samePartsLength));
  1798. return outputParts.join('/');
  1799. }};
  1800. var TTY = {ttys:[],init:function () {
  1801. // https://github.com/emscripten-core/emscripten/pull/1555
  1802. // if (ENVIRONMENT_IS_NODE) {
  1803. // // currently, FS.init does not distinguish if process.stdin is a file or TTY
  1804. // // device, it always assumes it's a TTY device. because of this, we're forcing
  1805. // // process.stdin to UTF8 encoding to at least make stdin reading compatible
  1806. // // with text files until FS.init can be refactored.
  1807. // process['stdin']['setEncoding']('utf8');
  1808. // }
  1809. },shutdown:function() {
  1810. // https://github.com/emscripten-core/emscripten/pull/1555
  1811. // if (ENVIRONMENT_IS_NODE) {
  1812. // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
  1813. // // isaacs: because now it's reading from the stream, you've expressed interest in it, so that read() kicks off a _read() which creates a ReadReq operation
  1814. // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
  1815. // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
  1816. // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
  1817. // process['stdin']['pause']();
  1818. // }
  1819. },register:function(dev, ops) {
  1820. TTY.ttys[dev] = { input: [], output: [], ops: ops };
  1821. FS.registerDevice(dev, TTY.stream_ops);
  1822. },stream_ops:{open:function(stream) {
  1823. var tty = TTY.ttys[stream.node.rdev];
  1824. if (!tty) {
  1825. throw new FS.ErrnoError(43);
  1826. }
  1827. stream.tty = tty;
  1828. stream.seekable = false;
  1829. },close:function(stream) {
  1830. // flush any pending line data
  1831. stream.tty.ops.flush(stream.tty);
  1832. },flush:function(stream) {
  1833. stream.tty.ops.flush(stream.tty);
  1834. },read:function(stream, buffer, offset, length, pos /* ignored */) {
  1835. if (!stream.tty || !stream.tty.ops.get_char) {
  1836. throw new FS.ErrnoError(60);
  1837. }
  1838. var bytesRead = 0;
  1839. for (var i = 0; i < length; i++) {
  1840. var result;
  1841. try {
  1842. result = stream.tty.ops.get_char(stream.tty);
  1843. } catch (e) {
  1844. throw new FS.ErrnoError(29);
  1845. }
  1846. if (result === undefined && bytesRead === 0) {
  1847. throw new FS.ErrnoError(6);
  1848. }
  1849. if (result === null || result === undefined) break;
  1850. bytesRead++;
  1851. buffer[offset+i] = result;
  1852. }
  1853. if (bytesRead) {
  1854. stream.node.timestamp = Date.now();
  1855. }
  1856. return bytesRead;
  1857. },write:function(stream, buffer, offset, length, pos) {
  1858. if (!stream.tty || !stream.tty.ops.put_char) {
  1859. throw new FS.ErrnoError(60);
  1860. }
  1861. try {
  1862. for (var i = 0; i < length; i++) {
  1863. stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
  1864. }
  1865. } catch (e) {
  1866. throw new FS.ErrnoError(29);
  1867. }
  1868. if (length) {
  1869. stream.node.timestamp = Date.now();
  1870. }
  1871. return i;
  1872. }},default_tty_ops:{get_char:function(tty) {
  1873. if (!tty.input.length) {
  1874. var result = null;
  1875. if (ENVIRONMENT_IS_NODE) {
  1876. // we will read data by chunks of BUFSIZE
  1877. var BUFSIZE = 256;
  1878. var buf = Buffer.alloc(BUFSIZE);
  1879. var bytesRead = 0;
  1880. try {
  1881. bytesRead = fs.readSync(process.stdin.fd, buf, 0, BUFSIZE, -1);
  1882. } catch(e) {
  1883. // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
  1884. // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
  1885. if (e.toString().includes('EOF')) bytesRead = 0;
  1886. else throw e;
  1887. }
  1888. if (bytesRead > 0) {
  1889. result = buf.slice(0, bytesRead).toString('utf-8');
  1890. } else {
  1891. result = null;
  1892. }
  1893. } else
  1894. if (typeof window != 'undefined' &&
  1895. typeof window.prompt == 'function') {
  1896. // Browser.
  1897. result = window.prompt('Input: '); // returns null on cancel
  1898. if (result !== null) {
  1899. result += '\n';
  1900. }
  1901. } else if (typeof readline == 'function') {
  1902. // Command line.
  1903. result = readline();
  1904. if (result !== null) {
  1905. result += '\n';
  1906. }
  1907. }
  1908. if (!result) {
  1909. return null;
  1910. }
  1911. tty.input = intArrayFromString(result, true);
  1912. }
  1913. return tty.input.shift();
  1914. },put_char:function(tty, val) {
  1915. if (val === null || val === 10) {
  1916. out(UTF8ArrayToString(tty.output, 0));
  1917. tty.output = [];
  1918. } else {
  1919. if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle.
  1920. }
  1921. },flush:function(tty) {
  1922. if (tty.output && tty.output.length > 0) {
  1923. out(UTF8ArrayToString(tty.output, 0));
  1924. tty.output = [];
  1925. }
  1926. }},default_tty1_ops:{put_char:function(tty, val) {
  1927. if (val === null || val === 10) {
  1928. err(UTF8ArrayToString(tty.output, 0));
  1929. tty.output = [];
  1930. } else {
  1931. if (val != 0) tty.output.push(val);
  1932. }
  1933. },flush:function(tty) {
  1934. if (tty.output && tty.output.length > 0) {
  1935. err(UTF8ArrayToString(tty.output, 0));
  1936. tty.output = [];
  1937. }
  1938. }}};
  1939. function zeroMemory(address, size) {
  1940. HEAPU8.fill(0, address, address + size);
  1941. }
  1942. function alignMemory(size, alignment) {
  1943. assert(alignment, "alignment argument is required");
  1944. return Math.ceil(size / alignment) * alignment;
  1945. }
  1946. function mmapAlloc(size) {
  1947. abort('internal error: mmapAlloc called but `emscripten_builtin_memalign` native symbol not exported');
  1948. }
  1949. var MEMFS = {ops_table:null,mount:function(mount) {
  1950. return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
  1951. },createNode:function(parent, name, mode, dev) {
  1952. if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
  1953. // no supported
  1954. throw new FS.ErrnoError(63);
  1955. }
  1956. if (!MEMFS.ops_table) {
  1957. MEMFS.ops_table = {
  1958. dir: {
  1959. node: {
  1960. getattr: MEMFS.node_ops.getattr,
  1961. setattr: MEMFS.node_ops.setattr,
  1962. lookup: MEMFS.node_ops.lookup,
  1963. mknod: MEMFS.node_ops.mknod,
  1964. rename: MEMFS.node_ops.rename,
  1965. unlink: MEMFS.node_ops.unlink,
  1966. rmdir: MEMFS.node_ops.rmdir,
  1967. readdir: MEMFS.node_ops.readdir,
  1968. symlink: MEMFS.node_ops.symlink
  1969. },
  1970. stream: {
  1971. llseek: MEMFS.stream_ops.llseek
  1972. }
  1973. },
  1974. file: {
  1975. node: {
  1976. getattr: MEMFS.node_ops.getattr,
  1977. setattr: MEMFS.node_ops.setattr
  1978. },
  1979. stream: {
  1980. llseek: MEMFS.stream_ops.llseek,
  1981. read: MEMFS.stream_ops.read,
  1982. write: MEMFS.stream_ops.write,
  1983. allocate: MEMFS.stream_ops.allocate,
  1984. mmap: MEMFS.stream_ops.mmap,
  1985. msync: MEMFS.stream_ops.msync
  1986. }
  1987. },
  1988. link: {
  1989. node: {
  1990. getattr: MEMFS.node_ops.getattr,
  1991. setattr: MEMFS.node_ops.setattr,
  1992. readlink: MEMFS.node_ops.readlink
  1993. },
  1994. stream: {}
  1995. },
  1996. chrdev: {
  1997. node: {
  1998. getattr: MEMFS.node_ops.getattr,
  1999. setattr: MEMFS.node_ops.setattr
  2000. },
  2001. stream: FS.chrdev_stream_ops
  2002. }
  2003. };
  2004. }
  2005. var node = FS.createNode(parent, name, mode, dev);
  2006. if (FS.isDir(node.mode)) {
  2007. node.node_ops = MEMFS.ops_table.dir.node;
  2008. node.stream_ops = MEMFS.ops_table.dir.stream;
  2009. node.contents = {};
  2010. } else if (FS.isFile(node.mode)) {
  2011. node.node_ops = MEMFS.ops_table.file.node;
  2012. node.stream_ops = MEMFS.ops_table.file.stream;
  2013. node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
  2014. // When the byte data of the file is populated, this will point to either a typed array, or a normal JS array. Typed arrays are preferred
  2015. // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
  2016. // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
  2017. node.contents = null;
  2018. } else if (FS.isLink(node.mode)) {
  2019. node.node_ops = MEMFS.ops_table.link.node;
  2020. node.stream_ops = MEMFS.ops_table.link.stream;
  2021. } else if (FS.isChrdev(node.mode)) {
  2022. node.node_ops = MEMFS.ops_table.chrdev.node;
  2023. node.stream_ops = MEMFS.ops_table.chrdev.stream;
  2024. }
  2025. node.timestamp = Date.now();
  2026. // add the new node to the parent
  2027. if (parent) {
  2028. parent.contents[name] = node;
  2029. parent.timestamp = node.timestamp;
  2030. }
  2031. return node;
  2032. },getFileDataAsTypedArray:function(node) {
  2033. if (!node.contents) return new Uint8Array(0);
  2034. if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
  2035. return new Uint8Array(node.contents);
  2036. },expandFileStorage:function(node, newCapacity) {
  2037. var prevCapacity = node.contents ? node.contents.length : 0;
  2038. if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
  2039. // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
  2040. // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
  2041. // avoid overshooting the allocation cap by a very large margin.
  2042. var CAPACITY_DOUBLING_MAX = 1024 * 1024;
  2043. newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
  2044. if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
  2045. var oldContents = node.contents;
  2046. node.contents = new Uint8Array(newCapacity); // Allocate new storage.
  2047. if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
  2048. },resizeFileStorage:function(node, newSize) {
  2049. if (node.usedBytes == newSize) return;
  2050. if (newSize == 0) {
  2051. node.contents = null; // Fully decommit when requesting a resize to zero.
  2052. node.usedBytes = 0;
  2053. } else {
  2054. var oldContents = node.contents;
  2055. node.contents = new Uint8Array(newSize); // Allocate new storage.
  2056. if (oldContents) {
  2057. node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
  2058. }
  2059. node.usedBytes = newSize;
  2060. }
  2061. },node_ops:{getattr:function(node) {
  2062. var attr = {};
  2063. // device numbers reuse inode numbers.
  2064. attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
  2065. attr.ino = node.id;
  2066. attr.mode = node.mode;
  2067. attr.nlink = 1;
  2068. attr.uid = 0;
  2069. attr.gid = 0;
  2070. attr.rdev = node.rdev;
  2071. if (FS.isDir(node.mode)) {
  2072. attr.size = 4096;
  2073. } else if (FS.isFile(node.mode)) {
  2074. attr.size = node.usedBytes;
  2075. } else if (FS.isLink(node.mode)) {
  2076. attr.size = node.link.length;
  2077. } else {
  2078. attr.size = 0;
  2079. }
  2080. attr.atime = new Date(node.timestamp);
  2081. attr.mtime = new Date(node.timestamp);
  2082. attr.ctime = new Date(node.timestamp);
  2083. // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
  2084. // but this is not required by the standard.
  2085. attr.blksize = 4096;
  2086. attr.blocks = Math.ceil(attr.size / attr.blksize);
  2087. return attr;
  2088. },setattr:function(node, attr) {
  2089. if (attr.mode !== undefined) {
  2090. node.mode = attr.mode;
  2091. }
  2092. if (attr.timestamp !== undefined) {
  2093. node.timestamp = attr.timestamp;
  2094. }
  2095. if (attr.size !== undefined) {
  2096. MEMFS.resizeFileStorage(node, attr.size);
  2097. }
  2098. },lookup:function(parent, name) {
  2099. throw FS.genericErrors[44];
  2100. },mknod:function(parent, name, mode, dev) {
  2101. return MEMFS.createNode(parent, name, mode, dev);
  2102. },rename:function(old_node, new_dir, new_name) {
  2103. // if we're overwriting a directory at new_name, make sure it's empty.
  2104. if (FS.isDir(old_node.mode)) {
  2105. var new_node;
  2106. try {
  2107. new_node = FS.lookupNode(new_dir, new_name);
  2108. } catch (e) {
  2109. }
  2110. if (new_node) {
  2111. for (var i in new_node.contents) {
  2112. throw new FS.ErrnoError(55);
  2113. }
  2114. }
  2115. }
  2116. // do the internal rewiring
  2117. delete old_node.parent.contents[old_node.name];
  2118. old_node.parent.timestamp = Date.now()
  2119. old_node.name = new_name;
  2120. new_dir.contents[new_name] = old_node;
  2121. new_dir.timestamp = old_node.parent.timestamp;
  2122. old_node.parent = new_dir;
  2123. },unlink:function(parent, name) {
  2124. delete parent.contents[name];
  2125. parent.timestamp = Date.now();
  2126. },rmdir:function(parent, name) {
  2127. var node = FS.lookupNode(parent, name);
  2128. for (var i in node.contents) {
  2129. throw new FS.ErrnoError(55);
  2130. }
  2131. delete parent.contents[name];
  2132. parent.timestamp = Date.now();
  2133. },readdir:function(node) {
  2134. var entries = ['.', '..'];
  2135. for (var key in node.contents) {
  2136. if (!node.contents.hasOwnProperty(key)) {
  2137. continue;
  2138. }
  2139. entries.push(key);
  2140. }
  2141. return entries;
  2142. },symlink:function(parent, newname, oldpath) {
  2143. var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
  2144. node.link = oldpath;
  2145. return node;
  2146. },readlink:function(node) {
  2147. if (!FS.isLink(node.mode)) {
  2148. throw new FS.ErrnoError(28);
  2149. }
  2150. return node.link;
  2151. }},stream_ops:{read:function(stream, buffer, offset, length, position) {
  2152. var contents = stream.node.contents;
  2153. if (position >= stream.node.usedBytes) return 0;
  2154. var size = Math.min(stream.node.usedBytes - position, length);
  2155. assert(size >= 0);
  2156. if (size > 8 && contents.subarray) { // non-trivial, and typed array
  2157. buffer.set(contents.subarray(position, position + size), offset);
  2158. } else {
  2159. for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
  2160. }
  2161. return size;
  2162. },write:function(stream, buffer, offset, length, position, canOwn) {
  2163. // The data buffer should be a typed array view
  2164. assert(!(buffer instanceof ArrayBuffer));
  2165. if (!length) return 0;
  2166. var node = stream.node;
  2167. node.timestamp = Date.now();
  2168. if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
  2169. if (canOwn) {
  2170. assert(position === 0, 'canOwn must imply no weird position inside the file');
  2171. node.contents = buffer.subarray(offset, offset + length);
  2172. node.usedBytes = length;
  2173. return length;
  2174. } else if (node.usedBytes === 0 && position === 0) { // If this is a simple first write to an empty file, do a fast set since we don't need to care about old data.
  2175. node.contents = buffer.slice(offset, offset + length);
  2176. node.usedBytes = length;
  2177. return length;
  2178. } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
  2179. node.contents.set(buffer.subarray(offset, offset + length), position);
  2180. return length;
  2181. }
  2182. }
  2183. // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
  2184. MEMFS.expandFileStorage(node, position+length);
  2185. if (node.contents.subarray && buffer.subarray) {
  2186. // Use typed array write which is available.
  2187. node.contents.set(buffer.subarray(offset, offset + length), position);
  2188. } else {
  2189. for (var i = 0; i < length; i++) {
  2190. node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
  2191. }
  2192. }
  2193. node.usedBytes = Math.max(node.usedBytes, position + length);
  2194. return length;
  2195. },llseek:function(stream, offset, whence) {
  2196. var position = offset;
  2197. if (whence === 1) {
  2198. position += stream.position;
  2199. } else if (whence === 2) {
  2200. if (FS.isFile(stream.node.mode)) {
  2201. position += stream.node.usedBytes;
  2202. }
  2203. }
  2204. if (position < 0) {
  2205. throw new FS.ErrnoError(28);
  2206. }
  2207. return position;
  2208. },allocate:function(stream, offset, length) {
  2209. MEMFS.expandFileStorage(stream.node, offset + length);
  2210. stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
  2211. },mmap:function(stream, address, length, position, prot, flags) {
  2212. if (address !== 0) {
  2213. // We don't currently support location hints for the address of the mapping
  2214. throw new FS.ErrnoError(28);
  2215. }
  2216. if (!FS.isFile(stream.node.mode)) {
  2217. throw new FS.ErrnoError(43);
  2218. }
  2219. var ptr;
  2220. var allocated;
  2221. var contents = stream.node.contents;
  2222. // Only make a new copy when MAP_PRIVATE is specified.
  2223. if (!(flags & 2) && contents.buffer === buffer) {
  2224. // We can't emulate MAP_SHARED when the file is not backed by the buffer
  2225. // we're mapping to (e.g. the HEAP buffer).
  2226. allocated = false;
  2227. ptr = contents.byteOffset;
  2228. } else {
  2229. // Try to avoid unnecessary slices.
  2230. if (position > 0 || position + length < contents.length) {
  2231. if (contents.subarray) {
  2232. contents = contents.subarray(position, position + length);
  2233. } else {
  2234. contents = Array.prototype.slice.call(contents, position, position + length);
  2235. }
  2236. }
  2237. allocated = true;
  2238. ptr = mmapAlloc(length);
  2239. if (!ptr) {
  2240. throw new FS.ErrnoError(48);
  2241. }
  2242. HEAP8.set(contents, ptr);
  2243. }
  2244. return { ptr: ptr, allocated: allocated };
  2245. },msync:function(stream, buffer, offset, length, mmapFlags) {
  2246. if (!FS.isFile(stream.node.mode)) {
  2247. throw new FS.ErrnoError(43);
  2248. }
  2249. if (mmapFlags & 2) {
  2250. // MAP_PRIVATE calls need not to be synced back to underlying fs
  2251. return 0;
  2252. }
  2253. var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
  2254. // should we check if bytesWritten and length are the same?
  2255. return 0;
  2256. }}};
  2257. /** @param {boolean=} noRunDep */
  2258. function asyncLoad(url, onload, onerror, noRunDep) {
  2259. var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : '';
  2260. readAsync(url, function(arrayBuffer) {
  2261. assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
  2262. onload(new Uint8Array(arrayBuffer));
  2263. if (dep) removeRunDependency(dep);
  2264. }, function(event) {
  2265. if (onerror) {
  2266. onerror();
  2267. } else {
  2268. throw 'Loading data file "' + url + '" failed.';
  2269. }
  2270. });
  2271. if (dep) addRunDependency(dep);
  2272. }
  2273. var ERRNO_MESSAGES = {0:"Success",1:"Arg list too long",2:"Permission denied",3:"Address already in use",4:"Address not available",5:"Address family not supported by protocol family",6:"No more processes",7:"Socket already connected",8:"Bad file number",9:"Trying to read unreadable message",10:"Mount device busy",11:"Operation canceled",12:"No children",13:"Connection aborted",14:"Connection refused",15:"Connection reset by peer",16:"File locking deadlock error",17:"Destination address required",18:"Math arg out of domain of func",19:"Quota exceeded",20:"File exists",21:"Bad address",22:"File too large",23:"Host is unreachable",24:"Identifier removed",25:"Illegal byte sequence",26:"Connection already in progress",27:"Interrupted system call",28:"Invalid argument",29:"I/O error",30:"Socket is already connected",31:"Is a directory",32:"Too many symbolic links",33:"Too many open files",34:"Too many links",35:"Message too long",36:"Multihop attempted",37:"File or path name too long",38:"Network interface is not configured",39:"Connection reset by network",40:"Network is unreachable",41:"Too many open files in system",42:"No buffer space available",43:"No such device",44:"No such file or directory",45:"Exec format error",46:"No record locks available",47:"The link has been severed",48:"Not enough core",49:"No message of desired type",50:"Protocol not available",51:"No space left on device",52:"Function not implemented",53:"Socket is not connected",54:"Not a directory",55:"Directory not empty",56:"State not recoverable",57:"Socket operation on non-socket",59:"Not a typewriter",60:"No such device or address",61:"Value too large for defined data type",62:"Previous owner died",63:"Not super-user",64:"Broken pipe",65:"Protocol error",66:"Unknown protocol",67:"Protocol wrong type for socket",68:"Math result not representable",69:"Read only file system",70:"Illegal seek",71:"No such process",72:"Stale file handle",73:"Connection timed out",74:"Text file busy",75:"Cross-device link",100:"Device not a stream",101:"Bad font file fmt",102:"Invalid slot",103:"Invalid request code",104:"No anode",105:"Block device required",106:"Channel number out of range",107:"Level 3 halted",108:"Level 3 reset",109:"Link number out of range",110:"Protocol driver not attached",111:"No CSI structure available",112:"Level 2 halted",113:"Invalid exchange",114:"Invalid request descriptor",115:"Exchange full",116:"No data (for no delay io)",117:"Timer expired",118:"Out of streams resources",119:"Machine is not on the network",120:"Package not installed",121:"The object is remote",122:"Advertise error",123:"Srmount error",124:"Communication error on send",125:"Cross mount point (not really error)",126:"Given log. name not unique",127:"f.d. invalid for this operation",128:"Remote address changed",129:"Can access a needed shared lib",130:"Accessing a corrupted shared lib",131:".lib section in a.out corrupted",132:"Attempting to link in too many libs",133:"Attempting to exec a shared library",135:"Streams pipe error",136:"Too many users",137:"Socket type not supported",138:"Not supported",139:"Protocol family not supported",140:"Can't send after socket shutdown",141:"Too many references",142:"Host is down",148:"No medium (in tape drive)",156:"Level 2 not synchronized"};
  2274. var ERRNO_CODES = {};
  2275. var FS = {root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,lookupPath:(path, opts = {}) => {
  2276. path = PATH_FS.resolve(FS.cwd(), path);
  2277. if (!path) return { path: '', node: null };
  2278. var defaults = {
  2279. follow_mount: true,
  2280. recurse_count: 0
  2281. };
  2282. for (var key in defaults) {
  2283. if (opts[key] === undefined) {
  2284. opts[key] = defaults[key];
  2285. }
  2286. }
  2287. if (opts.recurse_count > 8) { // max recursive lookup of 8
  2288. throw new FS.ErrnoError(32);
  2289. }
  2290. // split the path
  2291. var parts = PATH.normalizeArray(path.split('/').filter((p) => !!p), false);
  2292. // start at the root
  2293. var current = FS.root;
  2294. var current_path = '/';
  2295. for (var i = 0; i < parts.length; i++) {
  2296. var islast = (i === parts.length-1);
  2297. if (islast && opts.parent) {
  2298. // stop resolving
  2299. break;
  2300. }
  2301. current = FS.lookupNode(current, parts[i]);
  2302. current_path = PATH.join2(current_path, parts[i]);
  2303. // jump to the mount's root node if this is a mountpoint
  2304. if (FS.isMountpoint(current)) {
  2305. if (!islast || (islast && opts.follow_mount)) {
  2306. current = current.mounted.root;
  2307. }
  2308. }
  2309. // by default, lookupPath will not follow a symlink if it is the final path component.
  2310. // setting opts.follow = true will override this behavior.
  2311. if (!islast || opts.follow) {
  2312. var count = 0;
  2313. while (FS.isLink(current.mode)) {
  2314. var link = FS.readlink(current_path);
  2315. current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
  2316. var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
  2317. current = lookup.node;
  2318. if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
  2319. throw new FS.ErrnoError(32);
  2320. }
  2321. }
  2322. }
  2323. }
  2324. return { path: current_path, node: current };
  2325. },getPath:(node) => {
  2326. var path;
  2327. while (true) {
  2328. if (FS.isRoot(node)) {
  2329. var mount = node.mount.mountpoint;
  2330. if (!path) return mount;
  2331. return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
  2332. }
  2333. path = path ? node.name + '/' + path : node.name;
  2334. node = node.parent;
  2335. }
  2336. },hashName:(parentid, name) => {
  2337. var hash = 0;
  2338. for (var i = 0; i < name.length; i++) {
  2339. hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
  2340. }
  2341. return ((parentid + hash) >>> 0) % FS.nameTable.length;
  2342. },hashAddNode:(node) => {
  2343. var hash = FS.hashName(node.parent.id, node.name);
  2344. node.name_next = FS.nameTable[hash];
  2345. FS.nameTable[hash] = node;
  2346. },hashRemoveNode:(node) => {
  2347. var hash = FS.hashName(node.parent.id, node.name);
  2348. if (FS.nameTable[hash] === node) {
  2349. FS.nameTable[hash] = node.name_next;
  2350. } else {
  2351. var current = FS.nameTable[hash];
  2352. while (current) {
  2353. if (current.name_next === node) {
  2354. current.name_next = node.name_next;
  2355. break;
  2356. }
  2357. current = current.name_next;
  2358. }
  2359. }
  2360. },lookupNode:(parent, name) => {
  2361. var errCode = FS.mayLookup(parent);
  2362. if (errCode) {
  2363. throw new FS.ErrnoError(errCode, parent);
  2364. }
  2365. var hash = FS.hashName(parent.id, name);
  2366. for (var node = FS.nameTable[hash]; node; node = node.name_next) {
  2367. var nodeName = node.name;
  2368. if (node.parent.id === parent.id && nodeName === name) {
  2369. return node;
  2370. }
  2371. }
  2372. // if we failed to find it in the cache, call into the VFS
  2373. return FS.lookup(parent, name);
  2374. },createNode:(parent, name, mode, rdev) => {
  2375. assert(typeof parent == 'object')
  2376. var node = new FS.FSNode(parent, name, mode, rdev);
  2377. FS.hashAddNode(node);
  2378. return node;
  2379. },destroyNode:(node) => {
  2380. FS.hashRemoveNode(node);
  2381. },isRoot:(node) => {
  2382. return node === node.parent;
  2383. },isMountpoint:(node) => {
  2384. return !!node.mounted;
  2385. },isFile:(mode) => {
  2386. return (mode & 61440) === 32768;
  2387. },isDir:(mode) => {
  2388. return (mode & 61440) === 16384;
  2389. },isLink:(mode) => {
  2390. return (mode & 61440) === 40960;
  2391. },isChrdev:(mode) => {
  2392. return (mode & 61440) === 8192;
  2393. },isBlkdev:(mode) => {
  2394. return (mode & 61440) === 24576;
  2395. },isFIFO:(mode) => {
  2396. return (mode & 61440) === 4096;
  2397. },isSocket:(mode) => {
  2398. return (mode & 49152) === 49152;
  2399. },flagModes:{"r":0,"r+":2,"w":577,"w+":578,"a":1089,"a+":1090},modeStringToFlags:(str) => {
  2400. var flags = FS.flagModes[str];
  2401. if (typeof flags == 'undefined') {
  2402. throw new Error('Unknown file open mode: ' + str);
  2403. }
  2404. return flags;
  2405. },flagsToPermissionString:(flag) => {
  2406. var perms = ['r', 'w', 'rw'][flag & 3];
  2407. if ((flag & 512)) {
  2408. perms += 'w';
  2409. }
  2410. return perms;
  2411. },nodePermissions:(node, perms) => {
  2412. if (FS.ignorePermissions) {
  2413. return 0;
  2414. }
  2415. // return 0 if any user, group or owner bits are set.
  2416. if (perms.includes('r') && !(node.mode & 292)) {
  2417. return 2;
  2418. } else if (perms.includes('w') && !(node.mode & 146)) {
  2419. return 2;
  2420. } else if (perms.includes('x') && !(node.mode & 73)) {
  2421. return 2;
  2422. }
  2423. return 0;
  2424. },mayLookup:(dir) => {
  2425. var errCode = FS.nodePermissions(dir, 'x');
  2426. if (errCode) return errCode;
  2427. if (!dir.node_ops.lookup) return 2;
  2428. return 0;
  2429. },mayCreate:(dir, name) => {
  2430. try {
  2431. var node = FS.lookupNode(dir, name);
  2432. return 20;
  2433. } catch (e) {
  2434. }
  2435. return FS.nodePermissions(dir, 'wx');
  2436. },mayDelete:(dir, name, isdir) => {
  2437. var node;
  2438. try {
  2439. node = FS.lookupNode(dir, name);
  2440. } catch (e) {
  2441. return e.errno;
  2442. }
  2443. var errCode = FS.nodePermissions(dir, 'wx');
  2444. if (errCode) {
  2445. return errCode;
  2446. }
  2447. if (isdir) {
  2448. if (!FS.isDir(node.mode)) {
  2449. return 54;
  2450. }
  2451. if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
  2452. return 10;
  2453. }
  2454. } else {
  2455. if (FS.isDir(node.mode)) {
  2456. return 31;
  2457. }
  2458. }
  2459. return 0;
  2460. },mayOpen:(node, flags) => {
  2461. if (!node) {
  2462. return 44;
  2463. }
  2464. if (FS.isLink(node.mode)) {
  2465. return 32;
  2466. } else if (FS.isDir(node.mode)) {
  2467. if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write
  2468. (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only)
  2469. return 31;
  2470. }
  2471. }
  2472. return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
  2473. },MAX_OPEN_FDS:4096,nextfd:(fd_start = 0, fd_end = FS.MAX_OPEN_FDS) => {
  2474. for (var fd = fd_start; fd <= fd_end; fd++) {
  2475. if (!FS.streams[fd]) {
  2476. return fd;
  2477. }
  2478. }
  2479. throw new FS.ErrnoError(33);
  2480. },getStream:(fd) => FS.streams[fd],createStream:(stream, fd_start, fd_end) => {
  2481. if (!FS.FSStream) {
  2482. FS.FSStream = /** @constructor */ function(){};
  2483. FS.FSStream.prototype = {
  2484. object: {
  2485. get: function() { return this.node; },
  2486. set: function(val) { this.node = val; }
  2487. },
  2488. isRead: {
  2489. get: function() { return (this.flags & 2097155) !== 1; }
  2490. },
  2491. isWrite: {
  2492. get: function() { return (this.flags & 2097155) !== 0; }
  2493. },
  2494. isAppend: {
  2495. get: function() { return (this.flags & 1024); }
  2496. }
  2497. };
  2498. }
  2499. // clone it, so we can return an instance of FSStream
  2500. stream = Object.assign(new FS.FSStream(), stream);
  2501. var fd = FS.nextfd(fd_start, fd_end);
  2502. stream.fd = fd;
  2503. FS.streams[fd] = stream;
  2504. return stream;
  2505. },closeStream:(fd) => {
  2506. FS.streams[fd] = null;
  2507. },chrdev_stream_ops:{open:(stream) => {
  2508. var device = FS.getDevice(stream.node.rdev);
  2509. // override node's stream ops with the device's
  2510. stream.stream_ops = device.stream_ops;
  2511. // forward the open call
  2512. if (stream.stream_ops.open) {
  2513. stream.stream_ops.open(stream);
  2514. }
  2515. },llseek:() => {
  2516. throw new FS.ErrnoError(70);
  2517. }},major:(dev) => ((dev) >> 8),minor:(dev) => ((dev) & 0xff),makedev:(ma, mi) => ((ma) << 8 | (mi)),registerDevice:(dev, ops) => {
  2518. FS.devices[dev] = { stream_ops: ops };
  2519. },getDevice:(dev) => FS.devices[dev],getMounts:(mount) => {
  2520. var mounts = [];
  2521. var check = [mount];
  2522. while (check.length) {
  2523. var m = check.pop();
  2524. mounts.push(m);
  2525. check.push.apply(check, m.mounts);
  2526. }
  2527. return mounts;
  2528. },syncfs:(populate, callback) => {
  2529. if (typeof populate == 'function') {
  2530. callback = populate;
  2531. populate = false;
  2532. }
  2533. FS.syncFSRequests++;
  2534. if (FS.syncFSRequests > 1) {
  2535. err('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work');
  2536. }
  2537. var mounts = FS.getMounts(FS.root.mount);
  2538. var completed = 0;
  2539. function doCallback(errCode) {
  2540. assert(FS.syncFSRequests > 0);
  2541. FS.syncFSRequests--;
  2542. return callback(errCode);
  2543. }
  2544. function done(errCode) {
  2545. if (errCode) {
  2546. if (!done.errored) {
  2547. done.errored = true;
  2548. return doCallback(errCode);
  2549. }
  2550. return;
  2551. }
  2552. if (++completed >= mounts.length) {
  2553. doCallback(null);
  2554. }
  2555. };
  2556. // sync all mounts
  2557. mounts.forEach((mount) => {
  2558. if (!mount.type.syncfs) {
  2559. return done(null);
  2560. }
  2561. mount.type.syncfs(mount, populate, done);
  2562. });
  2563. },mount:(type, opts, mountpoint) => {
  2564. if (typeof type == 'string') {
  2565. // The filesystem was not included, and instead we have an error
  2566. // message stored in the variable.
  2567. throw type;
  2568. }
  2569. var root = mountpoint === '/';
  2570. var pseudo = !mountpoint;
  2571. var node;
  2572. if (root && FS.root) {
  2573. throw new FS.ErrnoError(10);
  2574. } else if (!root && !pseudo) {
  2575. var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
  2576. mountpoint = lookup.path; // use the absolute path
  2577. node = lookup.node;
  2578. if (FS.isMountpoint(node)) {
  2579. throw new FS.ErrnoError(10);
  2580. }
  2581. if (!FS.isDir(node.mode)) {
  2582. throw new FS.ErrnoError(54);
  2583. }
  2584. }
  2585. var mount = {
  2586. type: type,
  2587. opts: opts,
  2588. mountpoint: mountpoint,
  2589. mounts: []
  2590. };
  2591. // create a root node for the fs
  2592. var mountRoot = type.mount(mount);
  2593. mountRoot.mount = mount;
  2594. mount.root = mountRoot;
  2595. if (root) {
  2596. FS.root = mountRoot;
  2597. } else if (node) {
  2598. // set as a mountpoint
  2599. node.mounted = mount;
  2600. // add the new mount to the current mount's children
  2601. if (node.mount) {
  2602. node.mount.mounts.push(mount);
  2603. }
  2604. }
  2605. return mountRoot;
  2606. },unmount:(mountpoint) => {
  2607. var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
  2608. if (!FS.isMountpoint(lookup.node)) {
  2609. throw new FS.ErrnoError(28);
  2610. }
  2611. // destroy the nodes for this mount, and all its child mounts
  2612. var node = lookup.node;
  2613. var mount = node.mounted;
  2614. var mounts = FS.getMounts(mount);
  2615. Object.keys(FS.nameTable).forEach((hash) => {
  2616. var current = FS.nameTable[hash];
  2617. while (current) {
  2618. var next = current.name_next;
  2619. if (mounts.includes(current.mount)) {
  2620. FS.destroyNode(current);
  2621. }
  2622. current = next;
  2623. }
  2624. });
  2625. // no longer a mountpoint
  2626. node.mounted = null;
  2627. // remove this mount from the child mounts
  2628. var idx = node.mount.mounts.indexOf(mount);
  2629. assert(idx !== -1);
  2630. node.mount.mounts.splice(idx, 1);
  2631. },lookup:(parent, name) => {
  2632. return parent.node_ops.lookup(parent, name);
  2633. },mknod:(path, mode, dev) => {
  2634. var lookup = FS.lookupPath(path, { parent: true });
  2635. var parent = lookup.node;
  2636. var name = PATH.basename(path);
  2637. if (!name || name === '.' || name === '..') {
  2638. throw new FS.ErrnoError(28);
  2639. }
  2640. var errCode = FS.mayCreate(parent, name);
  2641. if (errCode) {
  2642. throw new FS.ErrnoError(errCode);
  2643. }
  2644. if (!parent.node_ops.mknod) {
  2645. throw new FS.ErrnoError(63);
  2646. }
  2647. return parent.node_ops.mknod(parent, name, mode, dev);
  2648. },create:(path, mode) => {
  2649. mode = mode !== undefined ? mode : 438 /* 0666 */;
  2650. mode &= 4095;
  2651. mode |= 32768;
  2652. return FS.mknod(path, mode, 0);
  2653. },mkdir:(path, mode) => {
  2654. mode = mode !== undefined ? mode : 511 /* 0777 */;
  2655. mode &= 511 | 512;
  2656. mode |= 16384;
  2657. return FS.mknod(path, mode, 0);
  2658. },mkdirTree:(path, mode) => {
  2659. var dirs = path.split('/');
  2660. var d = '';
  2661. for (var i = 0; i < dirs.length; ++i) {
  2662. if (!dirs[i]) continue;
  2663. d += '/' + dirs[i];
  2664. try {
  2665. FS.mkdir(d, mode);
  2666. } catch(e) {
  2667. if (e.errno != 20) throw e;
  2668. }
  2669. }
  2670. },mkdev:(path, mode, dev) => {
  2671. if (typeof dev == 'undefined') {
  2672. dev = mode;
  2673. mode = 438 /* 0666 */;
  2674. }
  2675. mode |= 8192;
  2676. return FS.mknod(path, mode, dev);
  2677. },symlink:(oldpath, newpath) => {
  2678. if (!PATH_FS.resolve(oldpath)) {
  2679. throw new FS.ErrnoError(44);
  2680. }
  2681. var lookup = FS.lookupPath(newpath, { parent: true });
  2682. var parent = lookup.node;
  2683. if (!parent) {
  2684. throw new FS.ErrnoError(44);
  2685. }
  2686. var newname = PATH.basename(newpath);
  2687. var errCode = FS.mayCreate(parent, newname);
  2688. if (errCode) {
  2689. throw new FS.ErrnoError(errCode);
  2690. }
  2691. if (!parent.node_ops.symlink) {
  2692. throw new FS.ErrnoError(63);
  2693. }
  2694. return parent.node_ops.symlink(parent, newname, oldpath);
  2695. },rename:(old_path, new_path) => {
  2696. var old_dirname = PATH.dirname(old_path);
  2697. var new_dirname = PATH.dirname(new_path);
  2698. var old_name = PATH.basename(old_path);
  2699. var new_name = PATH.basename(new_path);
  2700. // parents must exist
  2701. var lookup, old_dir, new_dir;
  2702. // let the errors from non existant directories percolate up
  2703. lookup = FS.lookupPath(old_path, { parent: true });
  2704. old_dir = lookup.node;
  2705. lookup = FS.lookupPath(new_path, { parent: true });
  2706. new_dir = lookup.node;
  2707. if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
  2708. // need to be part of the same mount
  2709. if (old_dir.mount !== new_dir.mount) {
  2710. throw new FS.ErrnoError(75);
  2711. }
  2712. // source must exist
  2713. var old_node = FS.lookupNode(old_dir, old_name);
  2714. // old path should not be an ancestor of the new path
  2715. var relative = PATH_FS.relative(old_path, new_dirname);
  2716. if (relative.charAt(0) !== '.') {
  2717. throw new FS.ErrnoError(28);
  2718. }
  2719. // new path should not be an ancestor of the old path
  2720. relative = PATH_FS.relative(new_path, old_dirname);
  2721. if (relative.charAt(0) !== '.') {
  2722. throw new FS.ErrnoError(55);
  2723. }
  2724. // see if the new path already exists
  2725. var new_node;
  2726. try {
  2727. new_node = FS.lookupNode(new_dir, new_name);
  2728. } catch (e) {
  2729. // not fatal
  2730. }
  2731. // early out if nothing needs to change
  2732. if (old_node === new_node) {
  2733. return;
  2734. }
  2735. // we'll need to delete the old entry
  2736. var isdir = FS.isDir(old_node.mode);
  2737. var errCode = FS.mayDelete(old_dir, old_name, isdir);
  2738. if (errCode) {
  2739. throw new FS.ErrnoError(errCode);
  2740. }
  2741. // need delete permissions if we'll be overwriting.
  2742. // need create permissions if new doesn't already exist.
  2743. errCode = new_node ?
  2744. FS.mayDelete(new_dir, new_name, isdir) :
  2745. FS.mayCreate(new_dir, new_name);
  2746. if (errCode) {
  2747. throw new FS.ErrnoError(errCode);
  2748. }
  2749. if (!old_dir.node_ops.rename) {
  2750. throw new FS.ErrnoError(63);
  2751. }
  2752. if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
  2753. throw new FS.ErrnoError(10);
  2754. }
  2755. // if we are going to change the parent, check write permissions
  2756. if (new_dir !== old_dir) {
  2757. errCode = FS.nodePermissions(old_dir, 'w');
  2758. if (errCode) {
  2759. throw new FS.ErrnoError(errCode);
  2760. }
  2761. }
  2762. // remove the node from the lookup hash
  2763. FS.hashRemoveNode(old_node);
  2764. // do the underlying fs rename
  2765. try {
  2766. old_dir.node_ops.rename(old_node, new_dir, new_name);
  2767. } catch (e) {
  2768. throw e;
  2769. } finally {
  2770. // add the node back to the hash (in case node_ops.rename
  2771. // changed its name)
  2772. FS.hashAddNode(old_node);
  2773. }
  2774. },rmdir:(path) => {
  2775. var lookup = FS.lookupPath(path, { parent: true });
  2776. var parent = lookup.node;
  2777. var name = PATH.basename(path);
  2778. var node = FS.lookupNode(parent, name);
  2779. var errCode = FS.mayDelete(parent, name, true);
  2780. if (errCode) {
  2781. throw new FS.ErrnoError(errCode);
  2782. }
  2783. if (!parent.node_ops.rmdir) {
  2784. throw new FS.ErrnoError(63);
  2785. }
  2786. if (FS.isMountpoint(node)) {
  2787. throw new FS.ErrnoError(10);
  2788. }
  2789. parent.node_ops.rmdir(parent, name);
  2790. FS.destroyNode(node);
  2791. },readdir:(path) => {
  2792. var lookup = FS.lookupPath(path, { follow: true });
  2793. var node = lookup.node;
  2794. if (!node.node_ops.readdir) {
  2795. throw new FS.ErrnoError(54);
  2796. }
  2797. return node.node_ops.readdir(node);
  2798. },unlink:(path) => {
  2799. var lookup = FS.lookupPath(path, { parent: true });
  2800. var parent = lookup.node;
  2801. if (!parent) {
  2802. throw new FS.ErrnoError(44);
  2803. }
  2804. var name = PATH.basename(path);
  2805. var node = FS.lookupNode(parent, name);
  2806. var errCode = FS.mayDelete(parent, name, false);
  2807. if (errCode) {
  2808. // According to POSIX, we should map EISDIR to EPERM, but
  2809. // we instead do what Linux does (and we must, as we use
  2810. // the musl linux libc).
  2811. throw new FS.ErrnoError(errCode);
  2812. }
  2813. if (!parent.node_ops.unlink) {
  2814. throw new FS.ErrnoError(63);
  2815. }
  2816. if (FS.isMountpoint(node)) {
  2817. throw new FS.ErrnoError(10);
  2818. }
  2819. parent.node_ops.unlink(parent, name);
  2820. FS.destroyNode(node);
  2821. },readlink:(path) => {
  2822. var lookup = FS.lookupPath(path);
  2823. var link = lookup.node;
  2824. if (!link) {
  2825. throw new FS.ErrnoError(44);
  2826. }
  2827. if (!link.node_ops.readlink) {
  2828. throw new FS.ErrnoError(28);
  2829. }
  2830. return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
  2831. },stat:(path, dontFollow) => {
  2832. var lookup = FS.lookupPath(path, { follow: !dontFollow });
  2833. var node = lookup.node;
  2834. if (!node) {
  2835. throw new FS.ErrnoError(44);
  2836. }
  2837. if (!node.node_ops.getattr) {
  2838. throw new FS.ErrnoError(63);
  2839. }
  2840. return node.node_ops.getattr(node);
  2841. },lstat:(path) => {
  2842. return FS.stat(path, true);
  2843. },chmod:(path, mode, dontFollow) => {
  2844. var node;
  2845. if (typeof path == 'string') {
  2846. var lookup = FS.lookupPath(path, { follow: !dontFollow });
  2847. node = lookup.node;
  2848. } else {
  2849. node = path;
  2850. }
  2851. if (!node.node_ops.setattr) {
  2852. throw new FS.ErrnoError(63);
  2853. }
  2854. node.node_ops.setattr(node, {
  2855. mode: (mode & 4095) | (node.mode & ~4095),
  2856. timestamp: Date.now()
  2857. });
  2858. },lchmod:(path, mode) => {
  2859. FS.chmod(path, mode, true);
  2860. },fchmod:(fd, mode) => {
  2861. var stream = FS.getStream(fd);
  2862. if (!stream) {
  2863. throw new FS.ErrnoError(8);
  2864. }
  2865. FS.chmod(stream.node, mode);
  2866. },chown:(path, uid, gid, dontFollow) => {
  2867. var node;
  2868. if (typeof path == 'string') {
  2869. var lookup = FS.lookupPath(path, { follow: !dontFollow });
  2870. node = lookup.node;
  2871. } else {
  2872. node = path;
  2873. }
  2874. if (!node.node_ops.setattr) {
  2875. throw new FS.ErrnoError(63);
  2876. }
  2877. node.node_ops.setattr(node, {
  2878. timestamp: Date.now()
  2879. // we ignore the uid / gid for now
  2880. });
  2881. },lchown:(path, uid, gid) => {
  2882. FS.chown(path, uid, gid, true);
  2883. },fchown:(fd, uid, gid) => {
  2884. var stream = FS.getStream(fd);
  2885. if (!stream) {
  2886. throw new FS.ErrnoError(8);
  2887. }
  2888. FS.chown(stream.node, uid, gid);
  2889. },truncate:(path, len) => {
  2890. if (len < 0) {
  2891. throw new FS.ErrnoError(28);
  2892. }
  2893. var node;
  2894. if (typeof path == 'string') {
  2895. var lookup = FS.lookupPath(path, { follow: true });
  2896. node = lookup.node;
  2897. } else {
  2898. node = path;
  2899. }
  2900. if (!node.node_ops.setattr) {
  2901. throw new FS.ErrnoError(63);
  2902. }
  2903. if (FS.isDir(node.mode)) {
  2904. throw new FS.ErrnoError(31);
  2905. }
  2906. if (!FS.isFile(node.mode)) {
  2907. throw new FS.ErrnoError(28);
  2908. }
  2909. var errCode = FS.nodePermissions(node, 'w');
  2910. if (errCode) {
  2911. throw new FS.ErrnoError(errCode);
  2912. }
  2913. node.node_ops.setattr(node, {
  2914. size: len,
  2915. timestamp: Date.now()
  2916. });
  2917. },ftruncate:(fd, len) => {
  2918. var stream = FS.getStream(fd);
  2919. if (!stream) {
  2920. throw new FS.ErrnoError(8);
  2921. }
  2922. if ((stream.flags & 2097155) === 0) {
  2923. throw new FS.ErrnoError(28);
  2924. }
  2925. FS.truncate(stream.node, len);
  2926. },utime:(path, atime, mtime) => {
  2927. var lookup = FS.lookupPath(path, { follow: true });
  2928. var node = lookup.node;
  2929. node.node_ops.setattr(node, {
  2930. timestamp: Math.max(atime, mtime)
  2931. });
  2932. },open:(path, flags, mode, fd_start, fd_end) => {
  2933. if (path === "") {
  2934. throw new FS.ErrnoError(44);
  2935. }
  2936. flags = typeof flags == 'string' ? FS.modeStringToFlags(flags) : flags;
  2937. mode = typeof mode == 'undefined' ? 438 /* 0666 */ : mode;
  2938. if ((flags & 64)) {
  2939. mode = (mode & 4095) | 32768;
  2940. } else {
  2941. mode = 0;
  2942. }
  2943. var node;
  2944. if (typeof path == 'object') {
  2945. node = path;
  2946. } else {
  2947. path = PATH.normalize(path);
  2948. try {
  2949. var lookup = FS.lookupPath(path, {
  2950. follow: !(flags & 131072)
  2951. });
  2952. node = lookup.node;
  2953. } catch (e) {
  2954. // ignore
  2955. }
  2956. }
  2957. // perhaps we need to create the node
  2958. var created = false;
  2959. if ((flags & 64)) {
  2960. if (node) {
  2961. // if O_CREAT and O_EXCL are set, error out if the node already exists
  2962. if ((flags & 128)) {
  2963. throw new FS.ErrnoError(20);
  2964. }
  2965. } else {
  2966. // node doesn't exist, try to create it
  2967. node = FS.mknod(path, mode, 0);
  2968. created = true;
  2969. }
  2970. }
  2971. if (!node) {
  2972. throw new FS.ErrnoError(44);
  2973. }
  2974. // can't truncate a device
  2975. if (FS.isChrdev(node.mode)) {
  2976. flags &= ~512;
  2977. }
  2978. // if asked only for a directory, then this must be one
  2979. if ((flags & 65536) && !FS.isDir(node.mode)) {
  2980. throw new FS.ErrnoError(54);
  2981. }
  2982. // check permissions, if this is not a file we just created now (it is ok to
  2983. // create and write to a file with read-only permissions; it is read-only
  2984. // for later use)
  2985. if (!created) {
  2986. var errCode = FS.mayOpen(node, flags);
  2987. if (errCode) {
  2988. throw new FS.ErrnoError(errCode);
  2989. }
  2990. }
  2991. // do truncation if necessary
  2992. if ((flags & 512)) {
  2993. FS.truncate(node, 0);
  2994. }
  2995. // we've already handled these, don't pass down to the underlying vfs
  2996. flags &= ~(128 | 512 | 131072);
  2997. // register the stream with the filesystem
  2998. var stream = FS.createStream({
  2999. node: node,
  3000. path: FS.getPath(node), // we want the absolute path to the node
  3001. flags: flags,
  3002. seekable: true,
  3003. position: 0,
  3004. stream_ops: node.stream_ops,
  3005. // used by the file family libc calls (fopen, fwrite, ferror, etc.)
  3006. ungotten: [],
  3007. error: false
  3008. }, fd_start, fd_end);
  3009. // call the new stream's open function
  3010. if (stream.stream_ops.open) {
  3011. stream.stream_ops.open(stream);
  3012. }
  3013. if (Module['logReadFiles'] && !(flags & 1)) {
  3014. if (!FS.readFiles) FS.readFiles = {};
  3015. if (!(path in FS.readFiles)) {
  3016. FS.readFiles[path] = 1;
  3017. }
  3018. }
  3019. return stream;
  3020. },close:(stream) => {
  3021. if (FS.isClosed(stream)) {
  3022. throw new FS.ErrnoError(8);
  3023. }
  3024. if (stream.getdents) stream.getdents = null; // free readdir state
  3025. try {
  3026. if (stream.stream_ops.close) {
  3027. stream.stream_ops.close(stream);
  3028. }
  3029. } catch (e) {
  3030. throw e;
  3031. } finally {
  3032. FS.closeStream(stream.fd);
  3033. }
  3034. stream.fd = null;
  3035. },isClosed:(stream) => {
  3036. return stream.fd === null;
  3037. },llseek:(stream, offset, whence) => {
  3038. if (FS.isClosed(stream)) {
  3039. throw new FS.ErrnoError(8);
  3040. }
  3041. if (!stream.seekable || !stream.stream_ops.llseek) {
  3042. throw new FS.ErrnoError(70);
  3043. }
  3044. if (whence != 0 && whence != 1 && whence != 2) {
  3045. throw new FS.ErrnoError(28);
  3046. }
  3047. stream.position = stream.stream_ops.llseek(stream, offset, whence);
  3048. stream.ungotten = [];
  3049. return stream.position;
  3050. },read:(stream, buffer, offset, length, position) => {
  3051. if (length < 0 || position < 0) {
  3052. throw new FS.ErrnoError(28);
  3053. }
  3054. if (FS.isClosed(stream)) {
  3055. throw new FS.ErrnoError(8);
  3056. }
  3057. if ((stream.flags & 2097155) === 1) {
  3058. throw new FS.ErrnoError(8);
  3059. }
  3060. if (FS.isDir(stream.node.mode)) {
  3061. throw new FS.ErrnoError(31);
  3062. }
  3063. if (!stream.stream_ops.read) {
  3064. throw new FS.ErrnoError(28);
  3065. }
  3066. var seeking = typeof position != 'undefined';
  3067. if (!seeking) {
  3068. position = stream.position;
  3069. } else if (!stream.seekable) {
  3070. throw new FS.ErrnoError(70);
  3071. }
  3072. var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
  3073. if (!seeking) stream.position += bytesRead;
  3074. return bytesRead;
  3075. },write:(stream, buffer, offset, length, position, canOwn) => {
  3076. if (length < 0 || position < 0) {
  3077. throw new FS.ErrnoError(28);
  3078. }
  3079. if (FS.isClosed(stream)) {
  3080. throw new FS.ErrnoError(8);
  3081. }
  3082. if ((stream.flags & 2097155) === 0) {
  3083. throw new FS.ErrnoError(8);
  3084. }
  3085. if (FS.isDir(stream.node.mode)) {
  3086. throw new FS.ErrnoError(31);
  3087. }
  3088. if (!stream.stream_ops.write) {
  3089. throw new FS.ErrnoError(28);
  3090. }
  3091. if (stream.seekable && stream.flags & 1024) {
  3092. // seek to the end before writing in append mode
  3093. FS.llseek(stream, 0, 2);
  3094. }
  3095. var seeking = typeof position != 'undefined';
  3096. if (!seeking) {
  3097. position = stream.position;
  3098. } else if (!stream.seekable) {
  3099. throw new FS.ErrnoError(70);
  3100. }
  3101. var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
  3102. if (!seeking) stream.position += bytesWritten;
  3103. return bytesWritten;
  3104. },allocate:(stream, offset, length) => {
  3105. if (FS.isClosed(stream)) {
  3106. throw new FS.ErrnoError(8);
  3107. }
  3108. if (offset < 0 || length <= 0) {
  3109. throw new FS.ErrnoError(28);
  3110. }
  3111. if ((stream.flags & 2097155) === 0) {
  3112. throw new FS.ErrnoError(8);
  3113. }
  3114. if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
  3115. throw new FS.ErrnoError(43);
  3116. }
  3117. if (!stream.stream_ops.allocate) {
  3118. throw new FS.ErrnoError(138);
  3119. }
  3120. stream.stream_ops.allocate(stream, offset, length);
  3121. },mmap:(stream, address, length, position, prot, flags) => {
  3122. // User requests writing to file (prot & PROT_WRITE != 0).
  3123. // Checking if we have permissions to write to the file unless
  3124. // MAP_PRIVATE flag is set. According to POSIX spec it is possible
  3125. // to write to file opened in read-only mode with MAP_PRIVATE flag,
  3126. // as all modifications will be visible only in the memory of
  3127. // the current process.
  3128. if ((prot & 2) !== 0
  3129. && (flags & 2) === 0
  3130. && (stream.flags & 2097155) !== 2) {
  3131. throw new FS.ErrnoError(2);
  3132. }
  3133. if ((stream.flags & 2097155) === 1) {
  3134. throw new FS.ErrnoError(2);
  3135. }
  3136. if (!stream.stream_ops.mmap) {
  3137. throw new FS.ErrnoError(43);
  3138. }
  3139. return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
  3140. },msync:(stream, buffer, offset, length, mmapFlags) => {
  3141. if (!stream || !stream.stream_ops.msync) {
  3142. return 0;
  3143. }
  3144. return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
  3145. },munmap:(stream) => 0,ioctl:(stream, cmd, arg) => {
  3146. if (!stream.stream_ops.ioctl) {
  3147. throw new FS.ErrnoError(59);
  3148. }
  3149. return stream.stream_ops.ioctl(stream, cmd, arg);
  3150. },readFile:(path, opts = {}) => {
  3151. opts.flags = opts.flags || 0;
  3152. opts.encoding = opts.encoding || 'binary';
  3153. if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
  3154. throw new Error('Invalid encoding type "' + opts.encoding + '"');
  3155. }
  3156. var ret;
  3157. var stream = FS.open(path, opts.flags);
  3158. var stat = FS.stat(path);
  3159. var length = stat.size;
  3160. var buf = new Uint8Array(length);
  3161. FS.read(stream, buf, 0, length, 0);
  3162. if (opts.encoding === 'utf8') {
  3163. ret = UTF8ArrayToString(buf, 0);
  3164. } else if (opts.encoding === 'binary') {
  3165. ret = buf;
  3166. }
  3167. FS.close(stream);
  3168. return ret;
  3169. },writeFile:(path, data, opts = {}) => {
  3170. opts.flags = opts.flags || 577;
  3171. var stream = FS.open(path, opts.flags, opts.mode);
  3172. if (typeof data == 'string') {
  3173. var buf = new Uint8Array(lengthBytesUTF8(data)+1);
  3174. var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
  3175. FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
  3176. } else if (ArrayBuffer.isView(data)) {
  3177. FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
  3178. } else {
  3179. throw new Error('Unsupported data type');
  3180. }
  3181. FS.close(stream);
  3182. },cwd:() => FS.currentPath,chdir:(path) => {
  3183. var lookup = FS.lookupPath(path, { follow: true });
  3184. if (lookup.node === null) {
  3185. throw new FS.ErrnoError(44);
  3186. }
  3187. if (!FS.isDir(lookup.node.mode)) {
  3188. throw new FS.ErrnoError(54);
  3189. }
  3190. var errCode = FS.nodePermissions(lookup.node, 'x');
  3191. if (errCode) {
  3192. throw new FS.ErrnoError(errCode);
  3193. }
  3194. FS.currentPath = lookup.path;
  3195. },createDefaultDirectories:() => {
  3196. FS.mkdir('/tmp');
  3197. FS.mkdir('/home');
  3198. FS.mkdir('/home/web_user');
  3199. },createDefaultDevices:() => {
  3200. // create /dev
  3201. FS.mkdir('/dev');
  3202. // setup /dev/null
  3203. FS.registerDevice(FS.makedev(1, 3), {
  3204. read: () => 0,
  3205. write: (stream, buffer, offset, length, pos) => length,
  3206. });
  3207. FS.mkdev('/dev/null', FS.makedev(1, 3));
  3208. // setup /dev/tty and /dev/tty1
  3209. // stderr needs to print output using err() rather than out()
  3210. // so we register a second tty just for it.
  3211. TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
  3212. TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
  3213. FS.mkdev('/dev/tty', FS.makedev(5, 0));
  3214. FS.mkdev('/dev/tty1', FS.makedev(6, 0));
  3215. // setup /dev/[u]random
  3216. var random_device = getRandomDevice();
  3217. FS.createDevice('/dev', 'random', random_device);
  3218. FS.createDevice('/dev', 'urandom', random_device);
  3219. // we're not going to emulate the actual shm device,
  3220. // just create the tmp dirs that reside in it commonly
  3221. FS.mkdir('/dev/shm');
  3222. FS.mkdir('/dev/shm/tmp');
  3223. },createSpecialDirectories:() => {
  3224. // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the
  3225. // name of the stream for fd 6 (see test_unistd_ttyname)
  3226. FS.mkdir('/proc');
  3227. var proc_self = FS.mkdir('/proc/self');
  3228. FS.mkdir('/proc/self/fd');
  3229. FS.mount({
  3230. mount: () => {
  3231. var node = FS.createNode(proc_self, 'fd', 16384 | 511 /* 0777 */, 73);
  3232. node.node_ops = {
  3233. lookup: (parent, name) => {
  3234. var fd = +name;
  3235. var stream = FS.getStream(fd);
  3236. if (!stream) throw new FS.ErrnoError(8);
  3237. var ret = {
  3238. parent: null,
  3239. mount: { mountpoint: 'fake' },
  3240. node_ops: { readlink: () => stream.path },
  3241. };
  3242. ret.parent = ret; // make it look like a simple root node
  3243. return ret;
  3244. }
  3245. };
  3246. return node;
  3247. }
  3248. }, {}, '/proc/self/fd');
  3249. },createStandardStreams:() => {
  3250. // TODO deprecate the old functionality of a single
  3251. // input / output callback and that utilizes FS.createDevice
  3252. // and instead require a unique set of stream ops
  3253. // by default, we symlink the standard streams to the
  3254. // default tty devices. however, if the standard streams
  3255. // have been overwritten we create a unique device for
  3256. // them instead.
  3257. if (Module['stdin']) {
  3258. FS.createDevice('/dev', 'stdin', Module['stdin']);
  3259. } else {
  3260. FS.symlink('/dev/tty', '/dev/stdin');
  3261. }
  3262. if (Module['stdout']) {
  3263. FS.createDevice('/dev', 'stdout', null, Module['stdout']);
  3264. } else {
  3265. FS.symlink('/dev/tty', '/dev/stdout');
  3266. }
  3267. if (Module['stderr']) {
  3268. FS.createDevice('/dev', 'stderr', null, Module['stderr']);
  3269. } else {
  3270. FS.symlink('/dev/tty1', '/dev/stderr');
  3271. }
  3272. // open default streams for the stdin, stdout and stderr devices
  3273. var stdin = FS.open('/dev/stdin', 0);
  3274. var stdout = FS.open('/dev/stdout', 1);
  3275. var stderr = FS.open('/dev/stderr', 1);
  3276. assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')');
  3277. assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')');
  3278. assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')');
  3279. },ensureErrnoError:() => {
  3280. if (FS.ErrnoError) return;
  3281. FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
  3282. this.node = node;
  3283. this.setErrno = /** @this{Object} */ function(errno) {
  3284. this.errno = errno;
  3285. for (var key in ERRNO_CODES) {
  3286. if (ERRNO_CODES[key] === errno) {
  3287. this.code = key;
  3288. break;
  3289. }
  3290. }
  3291. };
  3292. this.setErrno(errno);
  3293. this.message = ERRNO_MESSAGES[errno];
  3294. // Try to get a maximally helpful stack trace. On Node.js, getting Error.stack
  3295. // now ensures it shows what we want.
  3296. if (this.stack) {
  3297. // Define the stack property for Node.js 4, which otherwise errors on the next line.
  3298. Object.defineProperty(this, "stack", { value: (new Error).stack, writable: true });
  3299. this.stack = demangleAll(this.stack);
  3300. }
  3301. };
  3302. FS.ErrnoError.prototype = new Error();
  3303. FS.ErrnoError.prototype.constructor = FS.ErrnoError;
  3304. // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
  3305. [44].forEach((code) => {
  3306. FS.genericErrors[code] = new FS.ErrnoError(code);
  3307. FS.genericErrors[code].stack = '<generic error, no stack>';
  3308. });
  3309. },staticInit:() => {
  3310. FS.ensureErrnoError();
  3311. FS.nameTable = new Array(4096);
  3312. FS.mount(MEMFS, {}, '/');
  3313. FS.createDefaultDirectories();
  3314. FS.createDefaultDevices();
  3315. FS.createSpecialDirectories();
  3316. FS.filesystems = {
  3317. 'MEMFS': MEMFS,
  3318. };
  3319. },init:(input, output, error) => {
  3320. assert(!FS.init.initialized, 'FS.init was previously called. If you want to initialize later with custom parameters, remove any earlier calls (note that one is automatically added to the generated code)');
  3321. FS.init.initialized = true;
  3322. FS.ensureErrnoError();
  3323. // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
  3324. Module['stdin'] = input || Module['stdin'];
  3325. Module['stdout'] = output || Module['stdout'];
  3326. Module['stderr'] = error || Module['stderr'];
  3327. FS.createStandardStreams();
  3328. },quit:() => {
  3329. FS.init.initialized = false;
  3330. // Call musl-internal function to close all stdio streams, so nothing is
  3331. // left in internal buffers.
  3332. ___stdio_exit();
  3333. // close all of our streams
  3334. for (var i = 0; i < FS.streams.length; i++) {
  3335. var stream = FS.streams[i];
  3336. if (!stream) {
  3337. continue;
  3338. }
  3339. FS.close(stream);
  3340. }
  3341. },getMode:(canRead, canWrite) => {
  3342. var mode = 0;
  3343. if (canRead) mode |= 292 | 73;
  3344. if (canWrite) mode |= 146;
  3345. return mode;
  3346. },findObject:(path, dontResolveLastLink) => {
  3347. var ret = FS.analyzePath(path, dontResolveLastLink);
  3348. if (ret.exists) {
  3349. return ret.object;
  3350. } else {
  3351. return null;
  3352. }
  3353. },analyzePath:(path, dontResolveLastLink) => {
  3354. // operate from within the context of the symlink's target
  3355. try {
  3356. var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
  3357. path = lookup.path;
  3358. } catch (e) {
  3359. }
  3360. var ret = {
  3361. isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
  3362. parentExists: false, parentPath: null, parentObject: null
  3363. };
  3364. try {
  3365. var lookup = FS.lookupPath(path, { parent: true });
  3366. ret.parentExists = true;
  3367. ret.parentPath = lookup.path;
  3368. ret.parentObject = lookup.node;
  3369. ret.name = PATH.basename(path);
  3370. lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
  3371. ret.exists = true;
  3372. ret.path = lookup.path;
  3373. ret.object = lookup.node;
  3374. ret.name = lookup.node.name;
  3375. ret.isRoot = lookup.path === '/';
  3376. } catch (e) {
  3377. ret.error = e.errno;
  3378. };
  3379. return ret;
  3380. },createPath:(parent, path, canRead, canWrite) => {
  3381. parent = typeof parent == 'string' ? parent : FS.getPath(parent);
  3382. var parts = path.split('/').reverse();
  3383. while (parts.length) {
  3384. var part = parts.pop();
  3385. if (!part) continue;
  3386. var current = PATH.join2(parent, part);
  3387. try {
  3388. FS.mkdir(current);
  3389. } catch (e) {
  3390. // ignore EEXIST
  3391. }
  3392. parent = current;
  3393. }
  3394. return current;
  3395. },createFile:(parent, name, properties, canRead, canWrite) => {
  3396. var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name);
  3397. var mode = FS.getMode(canRead, canWrite);
  3398. return FS.create(path, mode);
  3399. },createDataFile:(parent, name, data, canRead, canWrite, canOwn) => {
  3400. var path = name;
  3401. if (parent) {
  3402. parent = typeof parent == 'string' ? parent : FS.getPath(parent);
  3403. path = name ? PATH.join2(parent, name) : parent;
  3404. }
  3405. var mode = FS.getMode(canRead, canWrite);
  3406. var node = FS.create(path, mode);
  3407. if (data) {
  3408. if (typeof data == 'string') {
  3409. var arr = new Array(data.length);
  3410. for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
  3411. data = arr;
  3412. }
  3413. // make sure we can write to the file
  3414. FS.chmod(node, mode | 146);
  3415. var stream = FS.open(node, 577);
  3416. FS.write(stream, data, 0, data.length, 0, canOwn);
  3417. FS.close(stream);
  3418. FS.chmod(node, mode);
  3419. }
  3420. return node;
  3421. },createDevice:(parent, name, input, output) => {
  3422. var path = PATH.join2(typeof parent == 'string' ? parent : FS.getPath(parent), name);
  3423. var mode = FS.getMode(!!input, !!output);
  3424. if (!FS.createDevice.major) FS.createDevice.major = 64;
  3425. var dev = FS.makedev(FS.createDevice.major++, 0);
  3426. // Create a fake device that a set of stream ops to emulate
  3427. // the old behavior.
  3428. FS.registerDevice(dev, {
  3429. open: (stream) => {
  3430. stream.seekable = false;
  3431. },
  3432. close: (stream) => {
  3433. // flush any pending line data
  3434. if (output && output.buffer && output.buffer.length) {
  3435. output(10);
  3436. }
  3437. },
  3438. read: (stream, buffer, offset, length, pos /* ignored */) => {
  3439. var bytesRead = 0;
  3440. for (var i = 0; i < length; i++) {
  3441. var result;
  3442. try {
  3443. result = input();
  3444. } catch (e) {
  3445. throw new FS.ErrnoError(29);
  3446. }
  3447. if (result === undefined && bytesRead === 0) {
  3448. throw new FS.ErrnoError(6);
  3449. }
  3450. if (result === null || result === undefined) break;
  3451. bytesRead++;
  3452. buffer[offset+i] = result;
  3453. }
  3454. if (bytesRead) {
  3455. stream.node.timestamp = Date.now();
  3456. }
  3457. return bytesRead;
  3458. },
  3459. write: (stream, buffer, offset, length, pos) => {
  3460. for (var i = 0; i < length; i++) {
  3461. try {
  3462. output(buffer[offset+i]);
  3463. } catch (e) {
  3464. throw new FS.ErrnoError(29);
  3465. }
  3466. }
  3467. if (length) {
  3468. stream.node.timestamp = Date.now();
  3469. }
  3470. return i;
  3471. }
  3472. });
  3473. return FS.mkdev(path, mode, dev);
  3474. },forceLoadFile:(obj) => {
  3475. if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
  3476. if (typeof XMLHttpRequest != 'undefined') {
  3477. throw new Error("Lazy loading should have been performed (contents set) in createLazyFile, but it was not. Lazy loading only works in web workers. Use --embed-file or --preload-file in emcc on the main thread.");
  3478. } else if (read_) {
  3479. // Command-line.
  3480. try {
  3481. // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
  3482. // read() will try to parse UTF8.
  3483. obj.contents = intArrayFromString(read_(obj.url), true);
  3484. obj.usedBytes = obj.contents.length;
  3485. } catch (e) {
  3486. throw new FS.ErrnoError(29);
  3487. }
  3488. } else {
  3489. throw new Error('Cannot load without read() or XMLHttpRequest.');
  3490. }
  3491. },createLazyFile:(parent, name, url, canRead, canWrite) => {
  3492. // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
  3493. /** @constructor */
  3494. function LazyUint8Array() {
  3495. this.lengthKnown = false;
  3496. this.chunks = []; // Loaded chunks. Index is the chunk number
  3497. }
  3498. LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) {
  3499. if (idx > this.length-1 || idx < 0) {
  3500. return undefined;
  3501. }
  3502. var chunkOffset = idx % this.chunkSize;
  3503. var chunkNum = (idx / this.chunkSize)|0;
  3504. return this.getter(chunkNum)[chunkOffset];
  3505. };
  3506. LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
  3507. this.getter = getter;
  3508. };
  3509. LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
  3510. // Find length
  3511. var xhr = new XMLHttpRequest();
  3512. xhr.open('HEAD', url, false);
  3513. xhr.send(null);
  3514. if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
  3515. var datalength = Number(xhr.getResponseHeader("Content-length"));
  3516. var header;
  3517. var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
  3518. var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
  3519. var chunkSize = 1024*1024; // Chunk size in bytes
  3520. if (!hasByteServing) chunkSize = datalength;
  3521. // Function to get a range from the remote URL.
  3522. var doXHR = (from, to) => {
  3523. if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
  3524. if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
  3525. // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
  3526. var xhr = new XMLHttpRequest();
  3527. xhr.open('GET', url, false);
  3528. if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
  3529. // Some hints to the browser that we want binary data.
  3530. xhr.responseType = 'arraybuffer';
  3531. if (xhr.overrideMimeType) {
  3532. xhr.overrideMimeType('text/plain; charset=x-user-defined');
  3533. }
  3534. xhr.send(null);
  3535. if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
  3536. if (xhr.response !== undefined) {
  3537. return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
  3538. } else {
  3539. return intArrayFromString(xhr.responseText || '', true);
  3540. }
  3541. };
  3542. var lazyArray = this;
  3543. lazyArray.setDataGetter((chunkNum) => {
  3544. var start = chunkNum * chunkSize;
  3545. var end = (chunkNum+1) * chunkSize - 1; // including this byte
  3546. end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
  3547. if (typeof lazyArray.chunks[chunkNum] == 'undefined') {
  3548. lazyArray.chunks[chunkNum] = doXHR(start, end);
  3549. }
  3550. if (typeof lazyArray.chunks[chunkNum] == 'undefined') throw new Error('doXHR failed!');
  3551. return lazyArray.chunks[chunkNum];
  3552. });
  3553. if (usesGzip || !datalength) {
  3554. // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
  3555. chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
  3556. datalength = this.getter(0).length;
  3557. chunkSize = datalength;
  3558. out("LazyFiles on gzip forces download of the whole file when length is accessed");
  3559. }
  3560. this._length = datalength;
  3561. this._chunkSize = chunkSize;
  3562. this.lengthKnown = true;
  3563. };
  3564. if (typeof XMLHttpRequest != 'undefined') {
  3565. if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
  3566. var lazyArray = new LazyUint8Array();
  3567. Object.defineProperties(lazyArray, {
  3568. length: {
  3569. get: /** @this{Object} */ function() {
  3570. if (!this.lengthKnown) {
  3571. this.cacheLength();
  3572. }
  3573. return this._length;
  3574. }
  3575. },
  3576. chunkSize: {
  3577. get: /** @this{Object} */ function() {
  3578. if (!this.lengthKnown) {
  3579. this.cacheLength();
  3580. }
  3581. return this._chunkSize;
  3582. }
  3583. }
  3584. });
  3585. var properties = { isDevice: false, contents: lazyArray };
  3586. } else {
  3587. var properties = { isDevice: false, url: url };
  3588. }
  3589. var node = FS.createFile(parent, name, properties, canRead, canWrite);
  3590. // This is a total hack, but I want to get this lazy file code out of the
  3591. // core of MEMFS. If we want to keep this lazy file concept I feel it should
  3592. // be its own thin LAZYFS proxying calls to MEMFS.
  3593. if (properties.contents) {
  3594. node.contents = properties.contents;
  3595. } else if (properties.url) {
  3596. node.contents = null;
  3597. node.url = properties.url;
  3598. }
  3599. // Add a function that defers querying the file size until it is asked the first time.
  3600. Object.defineProperties(node, {
  3601. usedBytes: {
  3602. get: /** @this {FSNode} */ function() { return this.contents.length; }
  3603. }
  3604. });
  3605. // override each stream op with one that tries to force load the lazy file first
  3606. var stream_ops = {};
  3607. var keys = Object.keys(node.stream_ops);
  3608. keys.forEach((key) => {
  3609. var fn = node.stream_ops[key];
  3610. stream_ops[key] = function forceLoadLazyFile() {
  3611. FS.forceLoadFile(node);
  3612. return fn.apply(null, arguments);
  3613. };
  3614. });
  3615. // use a custom read function
  3616. stream_ops.read = (stream, buffer, offset, length, position) => {
  3617. FS.forceLoadFile(node);
  3618. var contents = stream.node.contents;
  3619. if (position >= contents.length)
  3620. return 0;
  3621. var size = Math.min(contents.length - position, length);
  3622. assert(size >= 0);
  3623. if (contents.slice) { // normal array
  3624. for (var i = 0; i < size; i++) {
  3625. buffer[offset + i] = contents[position + i];
  3626. }
  3627. } else {
  3628. for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
  3629. buffer[offset + i] = contents.get(position + i);
  3630. }
  3631. }
  3632. return size;
  3633. };
  3634. node.stream_ops = stream_ops;
  3635. return node;
  3636. },createPreloadedFile:(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) => {
  3637. // TODO we should allow people to just pass in a complete filename instead
  3638. // of parent and name being that we just join them anyways
  3639. var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
  3640. var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
  3641. function processData(byteArray) {
  3642. function finish(byteArray) {
  3643. if (preFinish) preFinish();
  3644. if (!dontCreateFile) {
  3645. FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
  3646. }
  3647. if (onload) onload();
  3648. removeRunDependency(dep);
  3649. }
  3650. if (Browser.handledByPreloadPlugin(byteArray, fullname, finish, () => {
  3651. if (onerror) onerror();
  3652. removeRunDependency(dep);
  3653. })) {
  3654. return;
  3655. }
  3656. finish(byteArray);
  3657. }
  3658. addRunDependency(dep);
  3659. if (typeof url == 'string') {
  3660. asyncLoad(url, (byteArray) => processData(byteArray), onerror);
  3661. } else {
  3662. processData(url);
  3663. }
  3664. },indexedDB:() => {
  3665. return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
  3666. },DB_NAME:() => {
  3667. return 'EM_FS_' + window.location.pathname;
  3668. },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:(paths, onload, onerror) => {
  3669. onload = onload || (() => {});
  3670. onerror = onerror || (() => {});
  3671. var indexedDB = FS.indexedDB();
  3672. try {
  3673. var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  3674. } catch (e) {
  3675. return onerror(e);
  3676. }
  3677. openRequest.onupgradeneeded = () => {
  3678. out('creating db');
  3679. var db = openRequest.result;
  3680. db.createObjectStore(FS.DB_STORE_NAME);
  3681. };
  3682. openRequest.onsuccess = () => {
  3683. var db = openRequest.result;
  3684. var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
  3685. var files = transaction.objectStore(FS.DB_STORE_NAME);
  3686. var ok = 0, fail = 0, total = paths.length;
  3687. function finish() {
  3688. if (fail == 0) onload(); else onerror();
  3689. }
  3690. paths.forEach((path) => {
  3691. var putRequest = files.put(FS.analyzePath(path).object.contents, path);
  3692. putRequest.onsuccess = () => { ok++; if (ok + fail == total) finish() };
  3693. putRequest.onerror = () => { fail++; if (ok + fail == total) finish() };
  3694. });
  3695. transaction.onerror = onerror;
  3696. };
  3697. openRequest.onerror = onerror;
  3698. },loadFilesFromDB:(paths, onload, onerror) => {
  3699. onload = onload || (() => {});
  3700. onerror = onerror || (() => {});
  3701. var indexedDB = FS.indexedDB();
  3702. try {
  3703. var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
  3704. } catch (e) {
  3705. return onerror(e);
  3706. }
  3707. openRequest.onupgradeneeded = onerror; // no database to load from
  3708. openRequest.onsuccess = () => {
  3709. var db = openRequest.result;
  3710. try {
  3711. var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
  3712. } catch(e) {
  3713. onerror(e);
  3714. return;
  3715. }
  3716. var files = transaction.objectStore(FS.DB_STORE_NAME);
  3717. var ok = 0, fail = 0, total = paths.length;
  3718. function finish() {
  3719. if (fail == 0) onload(); else onerror();
  3720. }
  3721. paths.forEach((path) => {
  3722. var getRequest = files.get(path);
  3723. getRequest.onsuccess = () => {
  3724. if (FS.analyzePath(path).exists) {
  3725. FS.unlink(path);
  3726. }
  3727. FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
  3728. ok++;
  3729. if (ok + fail == total) finish();
  3730. };
  3731. getRequest.onerror = () => { fail++; if (ok + fail == total) finish() };
  3732. });
  3733. transaction.onerror = onerror;
  3734. };
  3735. openRequest.onerror = onerror;
  3736. },absolutePath:() => {
  3737. abort('FS.absolutePath has been removed; use PATH_FS.resolve instead');
  3738. },createFolder:() => {
  3739. abort('FS.createFolder has been removed; use FS.mkdir instead');
  3740. },createLink:() => {
  3741. abort('FS.createLink has been removed; use FS.symlink instead');
  3742. },joinPath:() => {
  3743. abort('FS.joinPath has been removed; use PATH.join instead');
  3744. },mmapAlloc:() => {
  3745. abort('FS.mmapAlloc has been replaced by the top level function mmapAlloc');
  3746. },standardizePath:() => {
  3747. abort('FS.standardizePath has been removed; use PATH.normalize instead');
  3748. }};
  3749. var SYSCALLS = {DEFAULT_POLLMASK:5,calculateAt:function(dirfd, path, allowEmpty) {
  3750. if (path[0] === '/') {
  3751. return path;
  3752. }
  3753. // relative path
  3754. var dir;
  3755. if (dirfd === -100) {
  3756. dir = FS.cwd();
  3757. } else {
  3758. var dirstream = FS.getStream(dirfd);
  3759. if (!dirstream) throw new FS.ErrnoError(8);
  3760. dir = dirstream.path;
  3761. }
  3762. if (path.length == 0) {
  3763. if (!allowEmpty) {
  3764. throw new FS.ErrnoError(44);;
  3765. }
  3766. return dir;
  3767. }
  3768. return PATH.join2(dir, path);
  3769. },doStat:function(func, path, buf) {
  3770. try {
  3771. var stat = func(path);
  3772. } catch (e) {
  3773. if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
  3774. // an error occurred while trying to look up the path; we should just report ENOTDIR
  3775. return -54;
  3776. }
  3777. throw e;
  3778. }
  3779. HEAP32[((buf)>>2)] = stat.dev;
  3780. HEAP32[(((buf)+(4))>>2)] = 0;
  3781. HEAP32[(((buf)+(8))>>2)] = stat.ino;
  3782. HEAP32[(((buf)+(12))>>2)] = stat.mode;
  3783. HEAP32[(((buf)+(16))>>2)] = stat.nlink;
  3784. HEAP32[(((buf)+(20))>>2)] = stat.uid;
  3785. HEAP32[(((buf)+(24))>>2)] = stat.gid;
  3786. HEAP32[(((buf)+(28))>>2)] = stat.rdev;
  3787. HEAP32[(((buf)+(32))>>2)] = 0;
  3788. (tempI64 = [stat.size>>>0,(tempDouble=stat.size,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[(((buf)+(40))>>2)] = tempI64[0],HEAP32[(((buf)+(44))>>2)] = tempI64[1]);
  3789. HEAP32[(((buf)+(48))>>2)] = 4096;
  3790. HEAP32[(((buf)+(52))>>2)] = stat.blocks;
  3791. HEAP32[(((buf)+(56))>>2)] = (stat.atime.getTime() / 1000)|0;
  3792. HEAP32[(((buf)+(60))>>2)] = 0;
  3793. HEAP32[(((buf)+(64))>>2)] = (stat.mtime.getTime() / 1000)|0;
  3794. HEAP32[(((buf)+(68))>>2)] = 0;
  3795. HEAP32[(((buf)+(72))>>2)] = (stat.ctime.getTime() / 1000)|0;
  3796. HEAP32[(((buf)+(76))>>2)] = 0;
  3797. (tempI64 = [stat.ino>>>0,(tempDouble=stat.ino,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[(((buf)+(80))>>2)] = tempI64[0],HEAP32[(((buf)+(84))>>2)] = tempI64[1]);
  3798. return 0;
  3799. },doMsync:function(addr, stream, len, flags, offset) {
  3800. var buffer = HEAPU8.slice(addr, addr + len);
  3801. FS.msync(stream, buffer, offset, len, flags);
  3802. },doMkdir:function(path, mode) {
  3803. // remove a trailing slash, if one - /a/b/ has basename of '', but
  3804. // we want to create b in the context of this function
  3805. path = PATH.normalize(path);
  3806. if (path[path.length-1] === '/') path = path.substr(0, path.length-1);
  3807. FS.mkdir(path, mode, 0);
  3808. return 0;
  3809. },doMknod:function(path, mode, dev) {
  3810. // we don't want this in the JS API as it uses mknod to create all nodes.
  3811. switch (mode & 61440) {
  3812. case 32768:
  3813. case 8192:
  3814. case 24576:
  3815. case 4096:
  3816. case 49152:
  3817. break;
  3818. default: return -28;
  3819. }
  3820. FS.mknod(path, mode, dev);
  3821. return 0;
  3822. },doReadlink:function(path, buf, bufsize) {
  3823. if (bufsize <= 0) return -28;
  3824. var ret = FS.readlink(path);
  3825. var len = Math.min(bufsize, lengthBytesUTF8(ret));
  3826. var endChar = HEAP8[buf+len];
  3827. stringToUTF8(ret, buf, bufsize+1);
  3828. // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
  3829. // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
  3830. HEAP8[buf+len] = endChar;
  3831. return len;
  3832. },doAccess:function(path, amode) {
  3833. if (amode & ~7) {
  3834. // need a valid mode
  3835. return -28;
  3836. }
  3837. var lookup = FS.lookupPath(path, { follow: true });
  3838. var node = lookup.node;
  3839. if (!node) {
  3840. return -44;
  3841. }
  3842. var perms = '';
  3843. if (amode & 4) perms += 'r';
  3844. if (amode & 2) perms += 'w';
  3845. if (amode & 1) perms += 'x';
  3846. if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
  3847. return -2;
  3848. }
  3849. return 0;
  3850. },doDup:function(path, flags, suggestFD) {
  3851. var suggest = FS.getStream(suggestFD);
  3852. if (suggest) FS.close(suggest);
  3853. return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
  3854. },doReadv:function(stream, iov, iovcnt, offset) {
  3855. var ret = 0;
  3856. for (var i = 0; i < iovcnt; i++) {
  3857. var ptr = HEAP32[(((iov)+(i*8))>>2)];
  3858. var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
  3859. var curr = FS.read(stream, HEAP8,ptr, len, offset);
  3860. if (curr < 0) return -1;
  3861. ret += curr;
  3862. if (curr < len) break; // nothing more to read
  3863. }
  3864. return ret;
  3865. },doWritev:function(stream, iov, iovcnt, offset) {
  3866. var ret = 0;
  3867. for (var i = 0; i < iovcnt; i++) {
  3868. var ptr = HEAP32[(((iov)+(i*8))>>2)];
  3869. var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
  3870. var curr = FS.write(stream, HEAP8,ptr, len, offset);
  3871. if (curr < 0) return -1;
  3872. ret += curr;
  3873. }
  3874. return ret;
  3875. },varargs:undefined,get:function() {
  3876. assert(SYSCALLS.varargs != undefined);
  3877. SYSCALLS.varargs += 4;
  3878. var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
  3879. return ret;
  3880. },getStr:function(ptr) {
  3881. var ret = UTF8ToString(ptr);
  3882. return ret;
  3883. },getStreamFromFD:function(fd) {
  3884. var stream = FS.getStream(fd);
  3885. if (!stream) throw new FS.ErrnoError(8);
  3886. return stream;
  3887. },get64:function(low, high) {
  3888. if (low >= 0) assert(high === 0);
  3889. else assert(high === -1);
  3890. return low;
  3891. }};
  3892. function _environ_get(__environ, environ_buf) {
  3893. var bufSize = 0;
  3894. getEnvStrings().forEach(function(string, i) {
  3895. var ptr = environ_buf + bufSize;
  3896. HEAP32[(((__environ)+(i * 4))>>2)] = ptr;
  3897. writeAsciiToMemory(string, ptr);
  3898. bufSize += string.length + 1;
  3899. });
  3900. return 0;
  3901. }
  3902. function _environ_sizes_get(penviron_count, penviron_buf_size) {
  3903. var strings = getEnvStrings();
  3904. HEAP32[((penviron_count)>>2)] = strings.length;
  3905. var bufSize = 0;
  3906. strings.forEach(function(string) {
  3907. bufSize += string.length + 1;
  3908. });
  3909. HEAP32[((penviron_buf_size)>>2)] = bufSize;
  3910. return 0;
  3911. }
  3912. function _fd_close(fd) {
  3913. try {
  3914. var stream = SYSCALLS.getStreamFromFD(fd);
  3915. FS.close(stream);
  3916. return 0;
  3917. } catch (e) {
  3918. if (typeof FS == 'undefined' || !(e instanceof FS.ErrnoError)) throw e;
  3919. return e.errno;
  3920. }
  3921. }
  3922. function _fd_read(fd, iov, iovcnt, pnum) {
  3923. try {
  3924. var stream = SYSCALLS.getStreamFromFD(fd);
  3925. var num = SYSCALLS.doReadv(stream, iov, iovcnt);
  3926. HEAP32[((pnum)>>2)] = num;
  3927. return 0;
  3928. } catch (e) {
  3929. if (typeof FS == 'undefined' || !(e instanceof FS.ErrnoError)) throw e;
  3930. return e.errno;
  3931. }
  3932. }
  3933. function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {
  3934. try {
  3935. var stream = SYSCALLS.getStreamFromFD(fd);
  3936. var HIGH_OFFSET = 0x100000000; // 2^32
  3937. // use an unsigned operator on low and shift high by 32-bits
  3938. var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
  3939. var DOUBLE_LIMIT = 0x20000000000000; // 2^53
  3940. // we also check for equality since DOUBLE_LIMIT + 1 == DOUBLE_LIMIT
  3941. if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
  3942. return -61;
  3943. }
  3944. FS.llseek(stream, offset, whence);
  3945. (tempI64 = [stream.position>>>0,(tempDouble=stream.position,(+(Math.abs(tempDouble))) >= 1.0 ? (tempDouble > 0.0 ? ((Math.min((+(Math.floor((tempDouble)/4294967296.0))), 4294967295.0))|0)>>>0 : (~~((+(Math.ceil((tempDouble - +(((~~(tempDouble)))>>>0))/4294967296.0)))))>>>0) : 0)],HEAP32[((newOffset)>>2)] = tempI64[0],HEAP32[(((newOffset)+(4))>>2)] = tempI64[1]);
  3946. if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
  3947. return 0;
  3948. } catch (e) {
  3949. if (typeof FS == 'undefined' || !(e instanceof FS.ErrnoError)) throw e;
  3950. return e.errno;
  3951. }
  3952. }
  3953. function _fd_write(fd, iov, iovcnt, pnum) {
  3954. try {
  3955. ;
  3956. var stream = SYSCALLS.getStreamFromFD(fd);
  3957. var num = SYSCALLS.doWritev(stream, iov, iovcnt);
  3958. HEAP32[((pnum)>>2)] = num;
  3959. return 0;
  3960. } catch (e) {
  3961. if (typeof FS == 'undefined' || !(e instanceof FS.ErrnoError)) throw e;
  3962. return e.errno;
  3963. }
  3964. }
  3965. function _setTempRet0(val) {
  3966. setTempRet0(val);
  3967. }
  3968. function __isLeapYear(year) {
  3969. return year%4 === 0 && (year%100 !== 0 || year%400 === 0);
  3970. }
  3971. function __arraySum(array, index) {
  3972. var sum = 0;
  3973. for (var i = 0; i <= index; sum += array[i++]) {
  3974. // no-op
  3975. }
  3976. return sum;
  3977. }
  3978. var __MONTH_DAYS_LEAP = [31,29,31,30,31,30,31,31,30,31,30,31];
  3979. var __MONTH_DAYS_REGULAR = [31,28,31,30,31,30,31,31,30,31,30,31];
  3980. function __addDays(date, days) {
  3981. var newDate = new Date(date.getTime());
  3982. while (days > 0) {
  3983. var leap = __isLeapYear(newDate.getFullYear());
  3984. var currentMonth = newDate.getMonth();
  3985. var daysInCurrentMonth = (leap ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR)[currentMonth];
  3986. if (days > daysInCurrentMonth-newDate.getDate()) {
  3987. // we spill over to next month
  3988. days -= (daysInCurrentMonth-newDate.getDate()+1);
  3989. newDate.setDate(1);
  3990. if (currentMonth < 11) {
  3991. newDate.setMonth(currentMonth+1)
  3992. } else {
  3993. newDate.setMonth(0);
  3994. newDate.setFullYear(newDate.getFullYear()+1);
  3995. }
  3996. } else {
  3997. // we stay in current month
  3998. newDate.setDate(newDate.getDate()+days);
  3999. return newDate;
  4000. }
  4001. }
  4002. return newDate;
  4003. }
  4004. function _strftime(s, maxsize, format, tm) {
  4005. // size_t strftime(char *restrict s, size_t maxsize, const char *restrict format, const struct tm *restrict timeptr);
  4006. // http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html
  4007. var tm_zone = HEAP32[(((tm)+(40))>>2)];
  4008. var date = {
  4009. tm_sec: HEAP32[((tm)>>2)],
  4010. tm_min: HEAP32[(((tm)+(4))>>2)],
  4011. tm_hour: HEAP32[(((tm)+(8))>>2)],
  4012. tm_mday: HEAP32[(((tm)+(12))>>2)],
  4013. tm_mon: HEAP32[(((tm)+(16))>>2)],
  4014. tm_year: HEAP32[(((tm)+(20))>>2)],
  4015. tm_wday: HEAP32[(((tm)+(24))>>2)],
  4016. tm_yday: HEAP32[(((tm)+(28))>>2)],
  4017. tm_isdst: HEAP32[(((tm)+(32))>>2)],
  4018. tm_gmtoff: HEAP32[(((tm)+(36))>>2)],
  4019. tm_zone: tm_zone ? UTF8ToString(tm_zone) : ''
  4020. };
  4021. var pattern = UTF8ToString(format);
  4022. // expand format
  4023. var EXPANSION_RULES_1 = {
  4024. '%c': '%a %b %d %H:%M:%S %Y', // Replaced by the locale's appropriate date and time representation - e.g., Mon Aug 3 14:02:01 2013
  4025. '%D': '%m/%d/%y', // Equivalent to %m / %d / %y
  4026. '%F': '%Y-%m-%d', // Equivalent to %Y - %m - %d
  4027. '%h': '%b', // Equivalent to %b
  4028. '%r': '%I:%M:%S %p', // Replaced by the time in a.m. and p.m. notation
  4029. '%R': '%H:%M', // Replaced by the time in 24-hour notation
  4030. '%T': '%H:%M:%S', // Replaced by the time
  4031. '%x': '%m/%d/%y', // Replaced by the locale's appropriate date representation
  4032. '%X': '%H:%M:%S', // Replaced by the locale's appropriate time representation
  4033. // Modified Conversion Specifiers
  4034. '%Ec': '%c', // Replaced by the locale's alternative appropriate date and time representation.
  4035. '%EC': '%C', // Replaced by the name of the base year (period) in the locale's alternative representation.
  4036. '%Ex': '%m/%d/%y', // Replaced by the locale's alternative date representation.
  4037. '%EX': '%H:%M:%S', // Replaced by the locale's alternative time representation.
  4038. '%Ey': '%y', // Replaced by the offset from %EC (year only) in the locale's alternative representation.
  4039. '%EY': '%Y', // Replaced by the full alternative year representation.
  4040. '%Od': '%d', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading zeros if there is any alternative symbol for zero; otherwise, with leading <space> characters.
  4041. '%Oe': '%e', // Replaced by the day of the month, using the locale's alternative numeric symbols, filled as needed with leading <space> characters.
  4042. '%OH': '%H', // Replaced by the hour (24-hour clock) using the locale's alternative numeric symbols.
  4043. '%OI': '%I', // Replaced by the hour (12-hour clock) using the locale's alternative numeric symbols.
  4044. '%Om': '%m', // Replaced by the month using the locale's alternative numeric symbols.
  4045. '%OM': '%M', // Replaced by the minutes using the locale's alternative numeric symbols.
  4046. '%OS': '%S', // Replaced by the seconds using the locale's alternative numeric symbols.
  4047. '%Ou': '%u', // Replaced by the weekday as a number in the locale's alternative representation (Monday=1).
  4048. '%OU': '%U', // Replaced by the week number of the year (Sunday as the first day of the week, rules corresponding to %U ) using the locale's alternative numeric symbols.
  4049. '%OV': '%V', // Replaced by the week number of the year (Monday as the first day of the week, rules corresponding to %V ) using the locale's alternative numeric symbols.
  4050. '%Ow': '%w', // Replaced by the number of the weekday (Sunday=0) using the locale's alternative numeric symbols.
  4051. '%OW': '%W', // Replaced by the week number of the year (Monday as the first day of the week) using the locale's alternative numeric symbols.
  4052. '%Oy': '%y', // Replaced by the year (offset from %C ) using the locale's alternative numeric symbols.
  4053. };
  4054. for (var rule in EXPANSION_RULES_1) {
  4055. pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_1[rule]);
  4056. }
  4057. var WEEKDAYS = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
  4058. var MONTHS = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
  4059. function leadingSomething(value, digits, character) {
  4060. var str = typeof value == 'number' ? value.toString() : (value || '');
  4061. while (str.length < digits) {
  4062. str = character[0]+str;
  4063. }
  4064. return str;
  4065. }
  4066. function leadingNulls(value, digits) {
  4067. return leadingSomething(value, digits, '0');
  4068. }
  4069. function compareByDay(date1, date2) {
  4070. function sgn(value) {
  4071. return value < 0 ? -1 : (value > 0 ? 1 : 0);
  4072. }
  4073. var compare;
  4074. if ((compare = sgn(date1.getFullYear()-date2.getFullYear())) === 0) {
  4075. if ((compare = sgn(date1.getMonth()-date2.getMonth())) === 0) {
  4076. compare = sgn(date1.getDate()-date2.getDate());
  4077. }
  4078. }
  4079. return compare;
  4080. }
  4081. function getFirstWeekStartDate(janFourth) {
  4082. switch (janFourth.getDay()) {
  4083. case 0: // Sunday
  4084. return new Date(janFourth.getFullYear()-1, 11, 29);
  4085. case 1: // Monday
  4086. return janFourth;
  4087. case 2: // Tuesday
  4088. return new Date(janFourth.getFullYear(), 0, 3);
  4089. case 3: // Wednesday
  4090. return new Date(janFourth.getFullYear(), 0, 2);
  4091. case 4: // Thursday
  4092. return new Date(janFourth.getFullYear(), 0, 1);
  4093. case 5: // Friday
  4094. return new Date(janFourth.getFullYear()-1, 11, 31);
  4095. case 6: // Saturday
  4096. return new Date(janFourth.getFullYear()-1, 11, 30);
  4097. }
  4098. }
  4099. function getWeekBasedYear(date) {
  4100. var thisDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
  4101. var janFourthThisYear = new Date(thisDate.getFullYear(), 0, 4);
  4102. var janFourthNextYear = new Date(thisDate.getFullYear()+1, 0, 4);
  4103. var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  4104. var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  4105. if (compareByDay(firstWeekStartThisYear, thisDate) <= 0) {
  4106. // this date is after the start of the first week of this year
  4107. if (compareByDay(firstWeekStartNextYear, thisDate) <= 0) {
  4108. return thisDate.getFullYear()+1;
  4109. } else {
  4110. return thisDate.getFullYear();
  4111. }
  4112. } else {
  4113. return thisDate.getFullYear()-1;
  4114. }
  4115. }
  4116. var EXPANSION_RULES_2 = {
  4117. '%a': function(date) {
  4118. return WEEKDAYS[date.tm_wday].substring(0,3);
  4119. },
  4120. '%A': function(date) {
  4121. return WEEKDAYS[date.tm_wday];
  4122. },
  4123. '%b': function(date) {
  4124. return MONTHS[date.tm_mon].substring(0,3);
  4125. },
  4126. '%B': function(date) {
  4127. return MONTHS[date.tm_mon];
  4128. },
  4129. '%C': function(date) {
  4130. var year = date.tm_year+1900;
  4131. return leadingNulls((year/100)|0,2);
  4132. },
  4133. '%d': function(date) {
  4134. return leadingNulls(date.tm_mday, 2);
  4135. },
  4136. '%e': function(date) {
  4137. return leadingSomething(date.tm_mday, 2, ' ');
  4138. },
  4139. '%g': function(date) {
  4140. // %g, %G, and %V give values according to the ISO 8601:2000 standard week-based year.
  4141. // In this system, weeks begin on a Monday and week 1 of the year is the week that includes
  4142. // January 4th, which is also the week that includes the first Thursday of the year, and
  4143. // is also the first week that contains at least four days in the year.
  4144. // If the first Monday of January is the 2nd, 3rd, or 4th, the preceding days are part of
  4145. // the last week of the preceding year; thus, for Saturday 2nd January 1999,
  4146. // %G is replaced by 1998 and %V is replaced by 53. If December 29th, 30th,
  4147. // or 31st is a Monday, it and any following days are part of week 1 of the following year.
  4148. // Thus, for Tuesday 30th December 1997, %G is replaced by 1998 and %V is replaced by 01.
  4149. return getWeekBasedYear(date).toString().substring(2);
  4150. },
  4151. '%G': function(date) {
  4152. return getWeekBasedYear(date);
  4153. },
  4154. '%H': function(date) {
  4155. return leadingNulls(date.tm_hour, 2);
  4156. },
  4157. '%I': function(date) {
  4158. var twelveHour = date.tm_hour;
  4159. if (twelveHour == 0) twelveHour = 12;
  4160. else if (twelveHour > 12) twelveHour -= 12;
  4161. return leadingNulls(twelveHour, 2);
  4162. },
  4163. '%j': function(date) {
  4164. // Day of the year (001-366)
  4165. return leadingNulls(date.tm_mday+__arraySum(__isLeapYear(date.tm_year+1900) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, date.tm_mon-1), 3);
  4166. },
  4167. '%m': function(date) {
  4168. return leadingNulls(date.tm_mon+1, 2);
  4169. },
  4170. '%M': function(date) {
  4171. return leadingNulls(date.tm_min, 2);
  4172. },
  4173. '%n': function() {
  4174. return '\n';
  4175. },
  4176. '%p': function(date) {
  4177. if (date.tm_hour >= 0 && date.tm_hour < 12) {
  4178. return 'AM';
  4179. } else {
  4180. return 'PM';
  4181. }
  4182. },
  4183. '%S': function(date) {
  4184. return leadingNulls(date.tm_sec, 2);
  4185. },
  4186. '%t': function() {
  4187. return '\t';
  4188. },
  4189. '%u': function(date) {
  4190. return date.tm_wday || 7;
  4191. },
  4192. '%U': function(date) {
  4193. // Replaced by the week number of the year as a decimal number [00,53].
  4194. // The first Sunday of January is the first day of week 1;
  4195. // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
  4196. var janFirst = new Date(date.tm_year+1900, 0, 1);
  4197. var firstSunday = janFirst.getDay() === 0 ? janFirst : __addDays(janFirst, 7-janFirst.getDay());
  4198. var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday);
  4199. // is target date after the first Sunday?
  4200. if (compareByDay(firstSunday, endDate) < 0) {
  4201. // calculate difference in days between first Sunday and endDate
  4202. var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31;
  4203. var firstSundayUntilEndJanuary = 31-firstSunday.getDate();
  4204. var days = firstSundayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();
  4205. return leadingNulls(Math.ceil(days/7), 2);
  4206. }
  4207. return compareByDay(firstSunday, janFirst) === 0 ? '01': '00';
  4208. },
  4209. '%V': function(date) {
  4210. // Replaced by the week number of the year (Monday as the first day of the week)
  4211. // as a decimal number [01,53]. If the week containing 1 January has four
  4212. // or more days in the new year, then it is considered week 1.
  4213. // Otherwise, it is the last week of the previous year, and the next week is week 1.
  4214. // Both January 4th and the first Thursday of January are always in week 1. [ tm_year, tm_wday, tm_yday]
  4215. var janFourthThisYear = new Date(date.tm_year+1900, 0, 4);
  4216. var janFourthNextYear = new Date(date.tm_year+1901, 0, 4);
  4217. var firstWeekStartThisYear = getFirstWeekStartDate(janFourthThisYear);
  4218. var firstWeekStartNextYear = getFirstWeekStartDate(janFourthNextYear);
  4219. var endDate = __addDays(new Date(date.tm_year+1900, 0, 1), date.tm_yday);
  4220. if (compareByDay(endDate, firstWeekStartThisYear) < 0) {
  4221. // if given date is before this years first week, then it belongs to the 53rd week of last year
  4222. return '53';
  4223. }
  4224. if (compareByDay(firstWeekStartNextYear, endDate) <= 0) {
  4225. // if given date is after next years first week, then it belongs to the 01th week of next year
  4226. return '01';
  4227. }
  4228. // given date is in between CW 01..53 of this calendar year
  4229. var daysDifference;
  4230. if (firstWeekStartThisYear.getFullYear() < date.tm_year+1900) {
  4231. // first CW of this year starts last year
  4232. daysDifference = date.tm_yday+32-firstWeekStartThisYear.getDate()
  4233. } else {
  4234. // first CW of this year starts this year
  4235. daysDifference = date.tm_yday+1-firstWeekStartThisYear.getDate();
  4236. }
  4237. return leadingNulls(Math.ceil(daysDifference/7), 2);
  4238. },
  4239. '%w': function(date) {
  4240. return date.tm_wday;
  4241. },
  4242. '%W': function(date) {
  4243. // Replaced by the week number of the year as a decimal number [00,53].
  4244. // The first Monday of January is the first day of week 1;
  4245. // days in the new year before this are in week 0. [ tm_year, tm_wday, tm_yday]
  4246. var janFirst = new Date(date.tm_year, 0, 1);
  4247. var firstMonday = janFirst.getDay() === 1 ? janFirst : __addDays(janFirst, janFirst.getDay() === 0 ? 1 : 7-janFirst.getDay()+1);
  4248. var endDate = new Date(date.tm_year+1900, date.tm_mon, date.tm_mday);
  4249. // is target date after the first Monday?
  4250. if (compareByDay(firstMonday, endDate) < 0) {
  4251. var februaryFirstUntilEndMonth = __arraySum(__isLeapYear(endDate.getFullYear()) ? __MONTH_DAYS_LEAP : __MONTH_DAYS_REGULAR, endDate.getMonth()-1)-31;
  4252. var firstMondayUntilEndJanuary = 31-firstMonday.getDate();
  4253. var days = firstMondayUntilEndJanuary+februaryFirstUntilEndMonth+endDate.getDate();
  4254. return leadingNulls(Math.ceil(days/7), 2);
  4255. }
  4256. return compareByDay(firstMonday, janFirst) === 0 ? '01': '00';
  4257. },
  4258. '%y': function(date) {
  4259. // Replaced by the last two digits of the year as a decimal number [00,99]. [ tm_year]
  4260. return (date.tm_year+1900).toString().substring(2);
  4261. },
  4262. '%Y': function(date) {
  4263. // Replaced by the year as a decimal number (for example, 1997). [ tm_year]
  4264. return date.tm_year+1900;
  4265. },
  4266. '%z': function(date) {
  4267. // Replaced by the offset from UTC in the ISO 8601:2000 standard format ( +hhmm or -hhmm ).
  4268. // For example, "-0430" means 4 hours 30 minutes behind UTC (west of Greenwich).
  4269. var off = date.tm_gmtoff;
  4270. var ahead = off >= 0;
  4271. off = Math.abs(off) / 60;
  4272. // convert from minutes into hhmm format (which means 60 minutes = 100 units)
  4273. off = (off / 60)*100 + (off % 60);
  4274. return (ahead ? '+' : '-') + String("0000" + off).slice(-4);
  4275. },
  4276. '%Z': function(date) {
  4277. return date.tm_zone;
  4278. },
  4279. '%%': function() {
  4280. return '%';
  4281. }
  4282. };
  4283. // Replace %% with a pair of NULLs (which cannot occur in a C string), then
  4284. // re-inject them after processing.
  4285. pattern = pattern.replace(/%%/g, '\0\0')
  4286. for (var rule in EXPANSION_RULES_2) {
  4287. if (pattern.includes(rule)) {
  4288. pattern = pattern.replace(new RegExp(rule, 'g'), EXPANSION_RULES_2[rule](date));
  4289. }
  4290. }
  4291. pattern = pattern.replace(/\0\0/g, '%')
  4292. var bytes = intArrayFromString(pattern, false);
  4293. if (bytes.length > maxsize) {
  4294. return 0;
  4295. }
  4296. writeArrayToMemory(bytes, s);
  4297. return bytes.length-1;
  4298. }
  4299. function _strftime_l(s, maxsize, format, tm) {
  4300. return _strftime(s, maxsize, format, tm); // no locale support yet
  4301. }
  4302. var FSNode = /** @constructor */ function(parent, name, mode, rdev) {
  4303. if (!parent) {
  4304. parent = this; // root node sets parent to itself
  4305. }
  4306. this.parent = parent;
  4307. this.mount = parent.mount;
  4308. this.mounted = null;
  4309. this.id = FS.nextInode++;
  4310. this.name = name;
  4311. this.mode = mode;
  4312. this.node_ops = {};
  4313. this.stream_ops = {};
  4314. this.rdev = rdev;
  4315. };
  4316. var readMode = 292/*292*/ | 73/*73*/;
  4317. var writeMode = 146/*146*/;
  4318. Object.defineProperties(FSNode.prototype, {
  4319. read: {
  4320. get: /** @this{FSNode} */function() {
  4321. return (this.mode & readMode) === readMode;
  4322. },
  4323. set: /** @this{FSNode} */function(val) {
  4324. val ? this.mode |= readMode : this.mode &= ~readMode;
  4325. }
  4326. },
  4327. write: {
  4328. get: /** @this{FSNode} */function() {
  4329. return (this.mode & writeMode) === writeMode;
  4330. },
  4331. set: /** @this{FSNode} */function(val) {
  4332. val ? this.mode |= writeMode : this.mode &= ~writeMode;
  4333. }
  4334. },
  4335. isFolder: {
  4336. get: /** @this{FSNode} */function() {
  4337. return FS.isDir(this.mode);
  4338. }
  4339. },
  4340. isDevice: {
  4341. get: /** @this{FSNode} */function() {
  4342. return FS.isChrdev(this.mode);
  4343. }
  4344. }
  4345. });
  4346. FS.FSNode = FSNode;
  4347. FS.staticInit();;
  4348. ERRNO_CODES = {
  4349. 'EPERM': 63,
  4350. 'ENOENT': 44,
  4351. 'ESRCH': 71,
  4352. 'EINTR': 27,
  4353. 'EIO': 29,
  4354. 'ENXIO': 60,
  4355. 'E2BIG': 1,
  4356. 'ENOEXEC': 45,
  4357. 'EBADF': 8,
  4358. 'ECHILD': 12,
  4359. 'EAGAIN': 6,
  4360. 'EWOULDBLOCK': 6,
  4361. 'ENOMEM': 48,
  4362. 'EACCES': 2,
  4363. 'EFAULT': 21,
  4364. 'ENOTBLK': 105,
  4365. 'EBUSY': 10,
  4366. 'EEXIST': 20,
  4367. 'EXDEV': 75,
  4368. 'ENODEV': 43,
  4369. 'ENOTDIR': 54,
  4370. 'EISDIR': 31,
  4371. 'EINVAL': 28,
  4372. 'ENFILE': 41,
  4373. 'EMFILE': 33,
  4374. 'ENOTTY': 59,
  4375. 'ETXTBSY': 74,
  4376. 'EFBIG': 22,
  4377. 'ENOSPC': 51,
  4378. 'ESPIPE': 70,
  4379. 'EROFS': 69,
  4380. 'EMLINK': 34,
  4381. 'EPIPE': 64,
  4382. 'EDOM': 18,
  4383. 'ERANGE': 68,
  4384. 'ENOMSG': 49,
  4385. 'EIDRM': 24,
  4386. 'ECHRNG': 106,
  4387. 'EL2NSYNC': 156,
  4388. 'EL3HLT': 107,
  4389. 'EL3RST': 108,
  4390. 'ELNRNG': 109,
  4391. 'EUNATCH': 110,
  4392. 'ENOCSI': 111,
  4393. 'EL2HLT': 112,
  4394. 'EDEADLK': 16,
  4395. 'ENOLCK': 46,
  4396. 'EBADE': 113,
  4397. 'EBADR': 114,
  4398. 'EXFULL': 115,
  4399. 'ENOANO': 104,
  4400. 'EBADRQC': 103,
  4401. 'EBADSLT': 102,
  4402. 'EDEADLOCK': 16,
  4403. 'EBFONT': 101,
  4404. 'ENOSTR': 100,
  4405. 'ENODATA': 116,
  4406. 'ETIME': 117,
  4407. 'ENOSR': 118,
  4408. 'ENONET': 119,
  4409. 'ENOPKG': 120,
  4410. 'EREMOTE': 121,
  4411. 'ENOLINK': 47,
  4412. 'EADV': 122,
  4413. 'ESRMNT': 123,
  4414. 'ECOMM': 124,
  4415. 'EPROTO': 65,
  4416. 'EMULTIHOP': 36,
  4417. 'EDOTDOT': 125,
  4418. 'EBADMSG': 9,
  4419. 'ENOTUNIQ': 126,
  4420. 'EBADFD': 127,
  4421. 'EREMCHG': 128,
  4422. 'ELIBACC': 129,
  4423. 'ELIBBAD': 130,
  4424. 'ELIBSCN': 131,
  4425. 'ELIBMAX': 132,
  4426. 'ELIBEXEC': 133,
  4427. 'ENOSYS': 52,
  4428. 'ENOTEMPTY': 55,
  4429. 'ENAMETOOLONG': 37,
  4430. 'ELOOP': 32,
  4431. 'EOPNOTSUPP': 138,
  4432. 'EPFNOSUPPORT': 139,
  4433. 'ECONNRESET': 15,
  4434. 'ENOBUFS': 42,
  4435. 'EAFNOSUPPORT': 5,
  4436. 'EPROTOTYPE': 67,
  4437. 'ENOTSOCK': 57,
  4438. 'ENOPROTOOPT': 50,
  4439. 'ESHUTDOWN': 140,
  4440. 'ECONNREFUSED': 14,
  4441. 'EADDRINUSE': 3,
  4442. 'ECONNABORTED': 13,
  4443. 'ENETUNREACH': 40,
  4444. 'ENETDOWN': 38,
  4445. 'ETIMEDOUT': 73,
  4446. 'EHOSTDOWN': 142,
  4447. 'EHOSTUNREACH': 23,
  4448. 'EINPROGRESS': 26,
  4449. 'EALREADY': 7,
  4450. 'EDESTADDRREQ': 17,
  4451. 'EMSGSIZE': 35,
  4452. 'EPROTONOSUPPORT': 66,
  4453. 'ESOCKTNOSUPPORT': 137,
  4454. 'EADDRNOTAVAIL': 4,
  4455. 'ENETRESET': 39,
  4456. 'EISCONN': 30,
  4457. 'ENOTCONN': 53,
  4458. 'ETOOMANYREFS': 141,
  4459. 'EUSERS': 136,
  4460. 'EDQUOT': 19,
  4461. 'ESTALE': 72,
  4462. 'ENOTSUP': 138,
  4463. 'ENOMEDIUM': 148,
  4464. 'EILSEQ': 25,
  4465. 'EOVERFLOW': 61,
  4466. 'ECANCELED': 11,
  4467. 'ENOTRECOVERABLE': 56,
  4468. 'EOWNERDEAD': 62,
  4469. 'ESTRPIPE': 135,
  4470. };;
  4471. var ASSERTIONS = true;
  4472. /** @type {function(string, boolean=, number=)} */
  4473. function intArrayFromString(stringy, dontAddNull, length) {
  4474. var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
  4475. var u8array = new Array(len);
  4476. var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
  4477. if (dontAddNull) u8array.length = numBytesWritten;
  4478. return u8array;
  4479. }
  4480. function intArrayToString(array) {
  4481. var ret = [];
  4482. for (var i = 0; i < array.length; i++) {
  4483. var chr = array[i];
  4484. if (chr > 0xFF) {
  4485. if (ASSERTIONS) {
  4486. assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
  4487. }
  4488. chr &= 0xFF;
  4489. }
  4490. ret.push(String.fromCharCode(chr));
  4491. }
  4492. return ret.join('');
  4493. }
  4494. function checkIncomingModuleAPI() {
  4495. ignoredModuleProp('fetchSettings');
  4496. }
  4497. var asmLibraryArg = {
  4498. "__assert_fail": ___assert_fail,
  4499. "__cxa_allocate_exception": ___cxa_allocate_exception,
  4500. "__cxa_throw": ___cxa_throw,
  4501. "abort": _abort,
  4502. "emscripten_memcpy_big": _emscripten_memcpy_big,
  4503. "emscripten_resize_heap": _emscripten_resize_heap,
  4504. "environ_get": _environ_get,
  4505. "environ_sizes_get": _environ_sizes_get,
  4506. "fd_close": _fd_close,
  4507. "fd_read": _fd_read,
  4508. "fd_seek": _fd_seek,
  4509. "fd_write": _fd_write,
  4510. "setTempRet0": _setTempRet0,
  4511. "strftime_l": _strftime_l
  4512. };
  4513. var asm = createWasm();
  4514. /** @type {function(...*):?} */
  4515. var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors");
  4516. /** @type {function(...*):?} */
  4517. var _main = Module["_main"] = createExportWrapper("main");
  4518. /** @type {function(...*):?} */
  4519. var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location");
  4520. /** @type {function(...*):?} */
  4521. var ___stdio_exit = Module["___stdio_exit"] = createExportWrapper("__stdio_exit");
  4522. /** @type {function(...*):?} */
  4523. var _malloc = Module["_malloc"] = createExportWrapper("malloc");
  4524. /** @type {function(...*):?} */
  4525. var _emscripten_stack_init = Module["_emscripten_stack_init"] = function() {
  4526. return (_emscripten_stack_init = Module["_emscripten_stack_init"] = Module["asm"]["emscripten_stack_init"]).apply(null, arguments);
  4527. };
  4528. /** @type {function(...*):?} */
  4529. var _emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = function() {
  4530. return (_emscripten_stack_get_free = Module["_emscripten_stack_get_free"] = Module["asm"]["emscripten_stack_get_free"]).apply(null, arguments);
  4531. };
  4532. /** @type {function(...*):?} */
  4533. var _emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = function() {
  4534. return (_emscripten_stack_get_base = Module["_emscripten_stack_get_base"] = Module["asm"]["emscripten_stack_get_base"]).apply(null, arguments);
  4535. };
  4536. /** @type {function(...*):?} */
  4537. var _emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = function() {
  4538. return (_emscripten_stack_get_end = Module["_emscripten_stack_get_end"] = Module["asm"]["emscripten_stack_get_end"]).apply(null, arguments);
  4539. };
  4540. /** @type {function(...*):?} */
  4541. var stackSave = Module["stackSave"] = createExportWrapper("stackSave");
  4542. /** @type {function(...*):?} */
  4543. var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore");
  4544. /** @type {function(...*):?} */
  4545. var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc");
  4546. /** @type {function(...*):?} */
  4547. var dynCall_viijii = Module["dynCall_viijii"] = createExportWrapper("dynCall_viijii");
  4548. /** @type {function(...*):?} */
  4549. var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji");
  4550. /** @type {function(...*):?} */
  4551. var dynCall_iiiiij = Module["dynCall_iiiiij"] = createExportWrapper("dynCall_iiiiij");
  4552. /** @type {function(...*):?} */
  4553. var dynCall_iiiiijj = Module["dynCall_iiiiijj"] = createExportWrapper("dynCall_iiiiijj");
  4554. /** @type {function(...*):?} */
  4555. var dynCall_iiiiiijj = Module["dynCall_iiiiiijj"] = createExportWrapper("dynCall_iiiiiijj");
  4556. // === Auto-generated postamble setup entry stuff ===
  4557. unexportedRuntimeFunction('intArrayFromString', false);
  4558. unexportedRuntimeFunction('intArrayToString', false);
  4559. unexportedRuntimeFunction('ccall', false);
  4560. unexportedRuntimeFunction('cwrap', false);
  4561. unexportedRuntimeFunction('setValue', false);
  4562. unexportedRuntimeFunction('getValue', false);
  4563. unexportedRuntimeFunction('allocate', false);
  4564. unexportedRuntimeFunction('UTF8ArrayToString', false);
  4565. unexportedRuntimeFunction('UTF8ToString', false);
  4566. unexportedRuntimeFunction('stringToUTF8Array', false);
  4567. unexportedRuntimeFunction('stringToUTF8', false);
  4568. unexportedRuntimeFunction('lengthBytesUTF8', false);
  4569. unexportedRuntimeFunction('stackTrace', false);
  4570. unexportedRuntimeFunction('addOnPreRun', false);
  4571. unexportedRuntimeFunction('addOnInit', false);
  4572. unexportedRuntimeFunction('addOnPreMain', false);
  4573. unexportedRuntimeFunction('addOnExit', false);
  4574. unexportedRuntimeFunction('addOnPostRun', false);
  4575. unexportedRuntimeFunction('writeStringToMemory', false);
  4576. unexportedRuntimeFunction('writeArrayToMemory', false);
  4577. unexportedRuntimeFunction('writeAsciiToMemory', false);
  4578. unexportedRuntimeFunction('addRunDependency', true);
  4579. unexportedRuntimeFunction('removeRunDependency', true);
  4580. unexportedRuntimeFunction('FS_createFolder', false);
  4581. unexportedRuntimeFunction('FS_createPath', true);
  4582. unexportedRuntimeFunction('FS_createDataFile', true);
  4583. unexportedRuntimeFunction('FS_createPreloadedFile', true);
  4584. unexportedRuntimeFunction('FS_createLazyFile', true);
  4585. unexportedRuntimeFunction('FS_createLink', false);
  4586. unexportedRuntimeFunction('FS_createDevice', true);
  4587. unexportedRuntimeFunction('FS_unlink', true);
  4588. unexportedRuntimeFunction('getLEB', false);
  4589. unexportedRuntimeFunction('getFunctionTables', false);
  4590. unexportedRuntimeFunction('alignFunctionTables', false);
  4591. unexportedRuntimeFunction('registerFunctions', false);
  4592. unexportedRuntimeFunction('addFunction', false);
  4593. unexportedRuntimeFunction('removeFunction', false);
  4594. unexportedRuntimeFunction('getFuncWrapper', false);
  4595. unexportedRuntimeFunction('prettyPrint', false);
  4596. unexportedRuntimeFunction('dynCall', false);
  4597. unexportedRuntimeFunction('getCompilerSetting', false);
  4598. unexportedRuntimeFunction('print', false);
  4599. unexportedRuntimeFunction('printErr', false);
  4600. unexportedRuntimeFunction('getTempRet0', false);
  4601. unexportedRuntimeFunction('setTempRet0', false);
  4602. unexportedRuntimeFunction('callMain', false);
  4603. unexportedRuntimeFunction('abort', false);
  4604. unexportedRuntimeFunction('keepRuntimeAlive', false);
  4605. unexportedRuntimeFunction('zeroMemory', false);
  4606. unexportedRuntimeFunction('stringToNewUTF8', false);
  4607. unexportedRuntimeFunction('abortOnCannotGrowMemory', false);
  4608. unexportedRuntimeFunction('emscripten_realloc_buffer', false);
  4609. unexportedRuntimeFunction('ENV', false);
  4610. unexportedRuntimeFunction('withStackSave', false);
  4611. unexportedRuntimeFunction('ERRNO_CODES', false);
  4612. unexportedRuntimeFunction('ERRNO_MESSAGES', false);
  4613. unexportedRuntimeFunction('setErrNo', false);
  4614. unexportedRuntimeFunction('inetPton4', false);
  4615. unexportedRuntimeFunction('inetNtop4', false);
  4616. unexportedRuntimeFunction('inetPton6', false);
  4617. unexportedRuntimeFunction('inetNtop6', false);
  4618. unexportedRuntimeFunction('readSockaddr', false);
  4619. unexportedRuntimeFunction('writeSockaddr', false);
  4620. unexportedRuntimeFunction('DNS', false);
  4621. unexportedRuntimeFunction('getHostByName', false);
  4622. unexportedRuntimeFunction('Protocols', false);
  4623. unexportedRuntimeFunction('Sockets', false);
  4624. unexportedRuntimeFunction('getRandomDevice', false);
  4625. unexportedRuntimeFunction('traverseStack', false);
  4626. unexportedRuntimeFunction('convertFrameToPC', false);
  4627. unexportedRuntimeFunction('UNWIND_CACHE', false);
  4628. unexportedRuntimeFunction('saveInUnwindCache', false);
  4629. unexportedRuntimeFunction('convertPCtoSourceLocation', false);
  4630. unexportedRuntimeFunction('readAsmConstArgsArray', false);
  4631. unexportedRuntimeFunction('readAsmConstArgs', false);
  4632. unexportedRuntimeFunction('mainThreadEM_ASM', false);
  4633. unexportedRuntimeFunction('jstoi_q', false);
  4634. unexportedRuntimeFunction('jstoi_s', false);
  4635. unexportedRuntimeFunction('getExecutableName', false);
  4636. unexportedRuntimeFunction('listenOnce', false);
  4637. unexportedRuntimeFunction('autoResumeAudioContext', false);
  4638. unexportedRuntimeFunction('dynCallLegacy', false);
  4639. unexportedRuntimeFunction('getDynCaller', false);
  4640. unexportedRuntimeFunction('dynCall', false);
  4641. unexportedRuntimeFunction('callRuntimeCallbacks', false);
  4642. unexportedRuntimeFunction('wasmTableMirror', false);
  4643. unexportedRuntimeFunction('setWasmTableEntry', false);
  4644. unexportedRuntimeFunction('getWasmTableEntry', false);
  4645. unexportedRuntimeFunction('handleException', false);
  4646. unexportedRuntimeFunction('runtimeKeepalivePush', false);
  4647. unexportedRuntimeFunction('runtimeKeepalivePop', false);
  4648. unexportedRuntimeFunction('callUserCallback', false);
  4649. unexportedRuntimeFunction('maybeExit', false);
  4650. unexportedRuntimeFunction('safeSetTimeout', false);
  4651. unexportedRuntimeFunction('asmjsMangle', false);
  4652. unexportedRuntimeFunction('asyncLoad', false);
  4653. unexportedRuntimeFunction('alignMemory', false);
  4654. unexportedRuntimeFunction('mmapAlloc', false);
  4655. unexportedRuntimeFunction('reallyNegative', false);
  4656. unexportedRuntimeFunction('unSign', false);
  4657. unexportedRuntimeFunction('reSign', false);
  4658. unexportedRuntimeFunction('formatString', false);
  4659. unexportedRuntimeFunction('PATH', false);
  4660. unexportedRuntimeFunction('PATH_FS', false);
  4661. unexportedRuntimeFunction('SYSCALLS', false);
  4662. unexportedRuntimeFunction('getSocketFromFD', false);
  4663. unexportedRuntimeFunction('getSocketAddress', false);
  4664. unexportedRuntimeFunction('JSEvents', false);
  4665. unexportedRuntimeFunction('registerKeyEventCallback', false);
  4666. unexportedRuntimeFunction('specialHTMLTargets', false);
  4667. unexportedRuntimeFunction('maybeCStringToJsString', false);
  4668. unexportedRuntimeFunction('findEventTarget', false);
  4669. unexportedRuntimeFunction('findCanvasEventTarget', false);
  4670. unexportedRuntimeFunction('getBoundingClientRect', false);
  4671. unexportedRuntimeFunction('fillMouseEventData', false);
  4672. unexportedRuntimeFunction('registerMouseEventCallback', false);
  4673. unexportedRuntimeFunction('registerWheelEventCallback', false);
  4674. unexportedRuntimeFunction('registerUiEventCallback', false);
  4675. unexportedRuntimeFunction('registerFocusEventCallback', false);
  4676. unexportedRuntimeFunction('fillDeviceOrientationEventData', false);
  4677. unexportedRuntimeFunction('registerDeviceOrientationEventCallback', false);
  4678. unexportedRuntimeFunction('fillDeviceMotionEventData', false);
  4679. unexportedRuntimeFunction('registerDeviceMotionEventCallback', false);
  4680. unexportedRuntimeFunction('screenOrientation', false);
  4681. unexportedRuntimeFunction('fillOrientationChangeEventData', false);
  4682. unexportedRuntimeFunction('registerOrientationChangeEventCallback', false);
  4683. unexportedRuntimeFunction('fillFullscreenChangeEventData', false);
  4684. unexportedRuntimeFunction('registerFullscreenChangeEventCallback', false);
  4685. unexportedRuntimeFunction('registerRestoreOldStyle', false);
  4686. unexportedRuntimeFunction('hideEverythingExceptGivenElement', false);
  4687. unexportedRuntimeFunction('restoreHiddenElements', false);
  4688. unexportedRuntimeFunction('setLetterbox', false);
  4689. unexportedRuntimeFunction('currentFullscreenStrategy', false);
  4690. unexportedRuntimeFunction('restoreOldWindowedStyle', false);
  4691. unexportedRuntimeFunction('softFullscreenResizeWebGLRenderTarget', false);
  4692. unexportedRuntimeFunction('doRequestFullscreen', false);
  4693. unexportedRuntimeFunction('fillPointerlockChangeEventData', false);
  4694. unexportedRuntimeFunction('registerPointerlockChangeEventCallback', false);
  4695. unexportedRuntimeFunction('registerPointerlockErrorEventCallback', false);
  4696. unexportedRuntimeFunction('requestPointerLock', false);
  4697. unexportedRuntimeFunction('fillVisibilityChangeEventData', false);
  4698. unexportedRuntimeFunction('registerVisibilityChangeEventCallback', false);
  4699. unexportedRuntimeFunction('registerTouchEventCallback', false);
  4700. unexportedRuntimeFunction('fillGamepadEventData', false);
  4701. unexportedRuntimeFunction('registerGamepadEventCallback', false);
  4702. unexportedRuntimeFunction('registerBeforeUnloadEventCallback', false);
  4703. unexportedRuntimeFunction('fillBatteryEventData', false);
  4704. unexportedRuntimeFunction('battery', false);
  4705. unexportedRuntimeFunction('registerBatteryEventCallback', false);
  4706. unexportedRuntimeFunction('setCanvasElementSize', false);
  4707. unexportedRuntimeFunction('getCanvasElementSize', false);
  4708. unexportedRuntimeFunction('demangle', false);
  4709. unexportedRuntimeFunction('demangleAll', false);
  4710. unexportedRuntimeFunction('jsStackTrace', false);
  4711. unexportedRuntimeFunction('stackTrace', false);
  4712. unexportedRuntimeFunction('getEnvStrings', false);
  4713. unexportedRuntimeFunction('checkWasiClock', false);
  4714. unexportedRuntimeFunction('writeI53ToI64', false);
  4715. unexportedRuntimeFunction('writeI53ToI64Clamped', false);
  4716. unexportedRuntimeFunction('writeI53ToI64Signaling', false);
  4717. unexportedRuntimeFunction('writeI53ToU64Clamped', false);
  4718. unexportedRuntimeFunction('writeI53ToU64Signaling', false);
  4719. unexportedRuntimeFunction('readI53FromI64', false);
  4720. unexportedRuntimeFunction('readI53FromU64', false);
  4721. unexportedRuntimeFunction('convertI32PairToI53', false);
  4722. unexportedRuntimeFunction('convertU32PairToI53', false);
  4723. unexportedRuntimeFunction('setImmediateWrapped', false);
  4724. unexportedRuntimeFunction('clearImmediateWrapped', false);
  4725. unexportedRuntimeFunction('polyfillSetImmediate', false);
  4726. unexportedRuntimeFunction('uncaughtExceptionCount', false);
  4727. unexportedRuntimeFunction('exceptionLast', false);
  4728. unexportedRuntimeFunction('exceptionCaught', false);
  4729. unexportedRuntimeFunction('ExceptionInfo', false);
  4730. unexportedRuntimeFunction('CatchInfo', false);
  4731. unexportedRuntimeFunction('exception_addRef', false);
  4732. unexportedRuntimeFunction('exception_decRef', false);
  4733. unexportedRuntimeFunction('Browser', false);
  4734. unexportedRuntimeFunction('funcWrappers', false);
  4735. unexportedRuntimeFunction('getFuncWrapper', false);
  4736. unexportedRuntimeFunction('setMainLoop', false);
  4737. unexportedRuntimeFunction('wget', false);
  4738. unexportedRuntimeFunction('FS', false);
  4739. unexportedRuntimeFunction('MEMFS', false);
  4740. unexportedRuntimeFunction('TTY', false);
  4741. unexportedRuntimeFunction('PIPEFS', false);
  4742. unexportedRuntimeFunction('SOCKFS', false);
  4743. unexportedRuntimeFunction('_setNetworkCallback', false);
  4744. unexportedRuntimeFunction('tempFixedLengthArray', false);
  4745. unexportedRuntimeFunction('miniTempWebGLFloatBuffers', false);
  4746. unexportedRuntimeFunction('heapObjectForWebGLType', false);
  4747. unexportedRuntimeFunction('heapAccessShiftForWebGLHeap', false);
  4748. unexportedRuntimeFunction('GL', false);
  4749. unexportedRuntimeFunction('emscriptenWebGLGet', false);
  4750. unexportedRuntimeFunction('computeUnpackAlignedImageSize', false);
  4751. unexportedRuntimeFunction('emscriptenWebGLGetTexPixelData', false);
  4752. unexportedRuntimeFunction('emscriptenWebGLGetUniform', false);
  4753. unexportedRuntimeFunction('webglGetUniformLocation', false);
  4754. unexportedRuntimeFunction('webglPrepareUniformLocationsBeforeFirstUse', false);
  4755. unexportedRuntimeFunction('webglGetLeftBracePos', false);
  4756. unexportedRuntimeFunction('emscriptenWebGLGetVertexAttrib', false);
  4757. unexportedRuntimeFunction('writeGLArray', false);
  4758. unexportedRuntimeFunction('AL', false);
  4759. unexportedRuntimeFunction('SDL_unicode', false);
  4760. unexportedRuntimeFunction('SDL_ttfContext', false);
  4761. unexportedRuntimeFunction('SDL_audio', false);
  4762. unexportedRuntimeFunction('SDL', false);
  4763. unexportedRuntimeFunction('SDL_gfx', false);
  4764. unexportedRuntimeFunction('GLUT', false);
  4765. unexportedRuntimeFunction('EGL', false);
  4766. unexportedRuntimeFunction('GLFW_Window', false);
  4767. unexportedRuntimeFunction('GLFW', false);
  4768. unexportedRuntimeFunction('GLEW', false);
  4769. unexportedRuntimeFunction('IDBStore', false);
  4770. unexportedRuntimeFunction('runAndAbortIfError', false);
  4771. unexportedRuntimeFunction('warnOnce', false);
  4772. unexportedRuntimeFunction('stackSave', false);
  4773. unexportedRuntimeFunction('stackRestore', false);
  4774. unexportedRuntimeFunction('stackAlloc', false);
  4775. unexportedRuntimeFunction('AsciiToString', false);
  4776. unexportedRuntimeFunction('stringToAscii', false);
  4777. unexportedRuntimeFunction('UTF16ToString', false);
  4778. unexportedRuntimeFunction('stringToUTF16', false);
  4779. unexportedRuntimeFunction('lengthBytesUTF16', false);
  4780. unexportedRuntimeFunction('UTF32ToString', false);
  4781. unexportedRuntimeFunction('stringToUTF32', false);
  4782. unexportedRuntimeFunction('lengthBytesUTF32', false);
  4783. unexportedRuntimeFunction('allocateUTF8', false);
  4784. unexportedRuntimeFunction('allocateUTF8OnStack', false);
  4785. Module["writeStackCookie"] = writeStackCookie;
  4786. Module["checkStackCookie"] = checkStackCookie;
  4787. unexportedRuntimeSymbol('ALLOC_NORMAL', false);
  4788. unexportedRuntimeSymbol('ALLOC_STACK', false);
  4789. var calledRun;
  4790. /**
  4791. * @constructor
  4792. * @this {ExitStatus}
  4793. */
  4794. function ExitStatus(status) {
  4795. this.name = "ExitStatus";
  4796. this.message = "Program terminated with exit(" + status + ")";
  4797. this.status = status;
  4798. }
  4799. var calledMain = false;
  4800. dependenciesFulfilled = function runCaller() {
  4801. // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
  4802. if (!calledRun) run();
  4803. if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
  4804. };
  4805. function callMain(args) {
  4806. assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
  4807. assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');
  4808. var entryFunction = Module['_main'];
  4809. args = args || [];
  4810. var argc = args.length+1;
  4811. var argv = stackAlloc((argc + 1) * 4);
  4812. HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram);
  4813. for (var i = 1; i < argc; i++) {
  4814. HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
  4815. }
  4816. HEAP32[(argv >> 2) + argc] = 0;
  4817. try {
  4818. var ret = entryFunction(argc, argv);
  4819. // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as
  4820. // execution is asynchronously handed off to a pthread.
  4821. // if we're not running an evented main loop, it's time to exit
  4822. exit(ret, /* implicit = */ true);
  4823. return ret;
  4824. }
  4825. catch (e) {
  4826. return handleException(e);
  4827. } finally {
  4828. calledMain = true;
  4829. }
  4830. }
  4831. function stackCheckInit() {
  4832. // This is normally called automatically during __wasm_call_ctors but need to
  4833. // get these values before even running any of the ctors so we call it redundantly
  4834. // here.
  4835. // TODO(sbc): Move writeStackCookie to native to to avoid this.
  4836. _emscripten_stack_init();
  4837. writeStackCookie();
  4838. }
  4839. /** @type {function(Array=)} */
  4840. function run(args) {
  4841. args = args || arguments_;
  4842. if (runDependencies > 0) {
  4843. return;
  4844. }
  4845. stackCheckInit();
  4846. preRun();
  4847. // a preRun added a dependency, run will be called later
  4848. if (runDependencies > 0) {
  4849. return;
  4850. }
  4851. function doRun() {
  4852. // run may have just been called through dependencies being fulfilled just in this very frame,
  4853. // or while the async setStatus time below was happening
  4854. if (calledRun) return;
  4855. calledRun = true;
  4856. Module['calledRun'] = true;
  4857. if (ABORT) return;
  4858. initRuntime();
  4859. preMain();
  4860. if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
  4861. if (shouldRunNow) callMain(args);
  4862. postRun();
  4863. }
  4864. if (Module['setStatus']) {
  4865. Module['setStatus']('Running...');
  4866. setTimeout(function() {
  4867. setTimeout(function() {
  4868. Module['setStatus']('');
  4869. }, 1);
  4870. doRun();
  4871. }, 1);
  4872. } else
  4873. {
  4874. doRun();
  4875. }
  4876. checkStackCookie();
  4877. }
  4878. Module['run'] = run;
  4879. function checkUnflushedContent() {
  4880. // Compiler settings do not allow exiting the runtime, so flushing
  4881. // the streams is not possible. but in ASSERTIONS mode we check
  4882. // if there was something to flush, and if so tell the user they
  4883. // should request that the runtime be exitable.
  4884. // Normally we would not even include flush() at all, but in ASSERTIONS
  4885. // builds we do so just for this check, and here we see if there is any
  4886. // content to flush, that is, we check if there would have been
  4887. // something a non-ASSERTIONS build would have not seen.
  4888. // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
  4889. // mode (which has its own special function for this; otherwise, all
  4890. // the code is inside libc)
  4891. var oldOut = out;
  4892. var oldErr = err;
  4893. var has = false;
  4894. out = err = (x) => {
  4895. has = true;
  4896. }
  4897. try { // it doesn't matter if it fails
  4898. ___stdio_exit();
  4899. // also flush in the JS FS layer
  4900. ['stdout', 'stderr'].forEach(function(name) {
  4901. var info = FS.analyzePath('/dev/' + name);
  4902. if (!info) return;
  4903. var stream = info.object;
  4904. var rdev = stream.rdev;
  4905. var tty = TTY.ttys[rdev];
  4906. if (tty && tty.output && tty.output.length) {
  4907. has = true;
  4908. }
  4909. });
  4910. } catch(e) {}
  4911. out = oldOut;
  4912. err = oldErr;
  4913. if (has) {
  4914. warnOnce('stdio streams had content in them that was not flushed. you should set EXIT_RUNTIME to 1 (see the FAQ), or make sure to emit a newline when you printf etc.');
  4915. }
  4916. }
  4917. /** @param {boolean|number=} implicit */
  4918. function exit(status, implicit) {
  4919. EXITSTATUS = status;
  4920. // Skip this check if the runtime is being kept alive deliberately.
  4921. // For example if `exit_with_live_runtime` is called.
  4922. if (!runtimeKeepaliveCounter) {
  4923. checkUnflushedContent();
  4924. }
  4925. if (keepRuntimeAlive()) {
  4926. // if exit() was called, we may warn the user if the runtime isn't actually being shut down
  4927. if (!implicit) {
  4928. var msg = 'program exited (with status: ' + status + '), but EXIT_RUNTIME is not set, so halting execution but not exiting the runtime or preventing further async execution (build with EXIT_RUNTIME=1, if you want a true shutdown)';
  4929. err(msg);
  4930. }
  4931. } else {
  4932. exitRuntime();
  4933. }
  4934. procExit(status);
  4935. }
  4936. function procExit(code) {
  4937. EXITSTATUS = code;
  4938. if (!keepRuntimeAlive()) {
  4939. if (Module['onExit']) Module['onExit'](code);
  4940. ABORT = true;
  4941. }
  4942. quit_(code, new ExitStatus(code));
  4943. }
  4944. if (Module['preInit']) {
  4945. if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
  4946. while (Module['preInit'].length > 0) {
  4947. Module['preInit'].pop()();
  4948. }
  4949. }
  4950. // shouldRunNow refers to calling main(), not run().
  4951. var shouldRunNow = true;
  4952. if (Module['noInitialRun']) shouldRunNow = false;
  4953. run();