source: EcnlProtoTool/trunk/webapp/webmrbc/mrbc.js

Last change on this file was 439, checked in by coas-nagasima, 4 years ago

mrubyを2.1.1に更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/javascript;charset=UTF-8
File size: 248.4 KB
Line 
1
2
3// The Module object: Our interface to the outside world. We import
4// and export values on it. There are various ways Module can be used:
5// 1. Not defined. We create it here
6// 2. A function parameter, function(Module) { ..generated code.. }
7// 3. pre-run appended it, var Module = {}; ..generated code..
8// 4. External script tag defines var Module.
9// We need to check if Module already exists (e.g. case 3 above).
10// Substitution will be replaced with actual code on later stage of the build,
11// this way Closure Compiler will not mangle it (e.g. case 4. above).
12// Note that if you want to run closure, and also to use Module
13// after the generated code, you will need to define var Module = {};
14// before the code. Then that object will be used in the code, and you
15// can continue to use Module afterwards as well.
16var Module = typeof Module !== 'undefined' ? Module : {};
17
18
19
20// --pre-jses are emitted after the Module integration code, so that they can
21// refer to Module (if they choose; they can also define Module)
22var mrbc = function(Module) {
23 Module['preRun'].push(function () {
24 Module['FS'] = FS;
25 });
26
27
28
29// Sometimes an existing Module object exists with properties
30// meant to overwrite the default module functionality. Here
31// we collect those properties and reapply _after_ we configure
32// the current environment's defaults to avoid having to be so
33// defensive during initialization.
34var moduleOverrides = {};
35var key;
36for (key in Module) {
37 if (Module.hasOwnProperty(key)) {
38 moduleOverrides[key] = Module[key];
39 }
40}
41
42var arguments_ = [];
43var thisProgram = './this.program';
44var quit_ = function(status, toThrow) {
45 throw toThrow;
46};
47
48// Determine the runtime environment we are in. You can customize this by
49// setting the ENVIRONMENT setting at compile time (see settings.js).
50
51var ENVIRONMENT_IS_WEB = false;
52var ENVIRONMENT_IS_WORKER = false;
53var ENVIRONMENT_IS_NODE = false;
54var ENVIRONMENT_IS_SHELL = false;
55ENVIRONMENT_IS_WEB = typeof window === 'object';
56ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
57// N.b. Electron.js environment is simultaneously a NODE-environment, but
58// also a web environment.
59ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof process.versions === 'object' && typeof process.versions.node === 'string';
60ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
61
62if (Module['ENVIRONMENT']) {
63 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)');
64}
65
66
67
68// `/` should be present at the end if `scriptDirectory` is not empty
69var scriptDirectory = '';
70function locateFile(path) {
71 if (Module['locateFile']) {
72 return Module['locateFile'](path, scriptDirectory);
73 }
74 return scriptDirectory + path;
75}
76
77// Hooks that are implemented differently in different runtime environments.
78var read_,
79 readAsync,
80 readBinary,
81 setWindowTitle;
82
83var nodeFS;
84var nodePath;
85
86if (ENVIRONMENT_IS_NODE) {
87 if (ENVIRONMENT_IS_WORKER) {
88 scriptDirectory = require('path').dirname(scriptDirectory) + '/';
89 } else {
90 scriptDirectory = __dirname + '/';
91 }
92
93
94
95
96 read_ = function shell_read(filename, binary) {
97 if (!nodeFS) nodeFS = require('fs');
98 if (!nodePath) nodePath = require('path');
99 filename = nodePath['normalize'](filename);
100 return nodeFS['readFileSync'](filename, binary ? null : 'utf8');
101 };
102
103 readBinary = function readBinary(filename) {
104 var ret = read_(filename, true);
105 if (!ret.buffer) {
106 ret = new Uint8Array(ret);
107 }
108 assert(ret.buffer);
109 return ret;
110 };
111
112
113
114
115 if (process['argv'].length > 1) {
116 thisProgram = process['argv'][1].replace(/\\/g, '/');
117 }
118
119 arguments_ = process['argv'].slice(2);
120
121 if (typeof module !== 'undefined') {
122 module['exports'] = Module;
123 }
124
125 process['on']('uncaughtException', function(ex) {
126 // suppress ExitStatus exceptions from showing an error
127 if (!(ex instanceof ExitStatus)) {
128 throw ex;
129 }
130 });
131
132 process['on']('unhandledRejection', abort);
133
134 quit_ = function(status) {
135 process['exit'](status);
136 };
137
138 Module['inspect'] = function () { return '[Emscripten Module object]'; };
139
140
141
142} else
143if (ENVIRONMENT_IS_SHELL) {
144
145
146 if (typeof read != 'undefined') {
147 read_ = function shell_read(f) {
148 return read(f);
149 };
150 }
151
152 readBinary = function readBinary(f) {
153 var data;
154 if (typeof readbuffer === 'function') {
155 return new Uint8Array(readbuffer(f));
156 }
157 data = read(f, 'binary');
158 assert(typeof data === 'object');
159 return data;
160 };
161
162 if (typeof scriptArgs != 'undefined') {
163 arguments_ = scriptArgs;
164 } else if (typeof arguments != 'undefined') {
165 arguments_ = arguments;
166 }
167
168 if (typeof quit === 'function') {
169 quit_ = function(status) {
170 quit(status);
171 };
172 }
173
174 if (typeof print !== 'undefined') {
175 // Prefer to use print/printErr where they exist, as they usually work better.
176 if (typeof console === 'undefined') console = /** @type{!Console} */({});
177 console.log = /** @type{!function(this:Console, ...*): undefined} */ (print);
178 console.warn = console.error = /** @type{!function(this:Console, ...*): undefined} */ (typeof printErr !== 'undefined' ? printErr : print);
179 }
180
181
182} else
183
184// Note that this includes Node.js workers when relevant (pthreads is enabled).
185// Node.js workers are detected as a combination of ENVIRONMENT_IS_WORKER and
186// ENVIRONMENT_IS_NODE.
187if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
188 if (ENVIRONMENT_IS_WORKER) { // Check worker, not web, since window could be polyfilled
189 scriptDirectory = self.location.href;
190 } else if (document.currentScript) { // web
191 scriptDirectory = document.currentScript.src;
192 }
193 // blob urls look like blob:http://site.com/etc/etc and we cannot infer anything from them.
194 // otherwise, slice off the final part of the url to find the script directory.
195 // if scriptDirectory does not contain a slash, lastIndexOf will return -1,
196 // and scriptDirectory will correctly be replaced with an empty string.
197 if (scriptDirectory.indexOf('blob:') !== 0) {
198 scriptDirectory = scriptDirectory.substr(0, scriptDirectory.lastIndexOf('/')+1);
199 } else {
200 scriptDirectory = '';
201 }
202
203
204 // Differentiate the Web Worker from the Node Worker case, as reading must
205 // be done differently.
206 {
207
208
209
210
211 read_ = function shell_read(url) {
212 var xhr = new XMLHttpRequest();
213 xhr.open('GET', url, false);
214 xhr.send(null);
215 return xhr.responseText;
216 };
217
218 if (ENVIRONMENT_IS_WORKER) {
219 readBinary = function readBinary(url) {
220 var xhr = new XMLHttpRequest();
221 xhr.open('GET', url, false);
222 xhr.responseType = 'arraybuffer';
223 xhr.send(null);
224 return new Uint8Array(/** @type{!ArrayBuffer} */(xhr.response));
225 };
226 }
227
228 readAsync = function readAsync(url, onload, onerror) {
229 var xhr = new XMLHttpRequest();
230 xhr.open('GET', url, true);
231 xhr.responseType = 'arraybuffer';
232 xhr.onload = function xhr_onload() {
233 if (xhr.status == 200 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
234 onload(xhr.response);
235 return;
236 }
237 onerror();
238 };
239 xhr.onerror = onerror;
240 xhr.send(null);
241 };
242
243
244
245
246 }
247
248 setWindowTitle = function(title) { document.title = title };
249} else
250{
251 throw new Error('environment detection error');
252}
253
254
255// Set up the out() and err() hooks, which are how we can print to stdout or
256// stderr, respectively.
257var out = Module['print'] || console.log.bind(console);
258var err = Module['printErr'] || console.warn.bind(console);
259
260// Merge back in the overrides
261for (key in moduleOverrides) {
262 if (moduleOverrides.hasOwnProperty(key)) {
263 Module[key] = moduleOverrides[key];
264 }
265}
266// Free the object hierarchy contained in the overrides, this lets the GC
267// reclaim data used e.g. in memoryInitializerRequest, which is a large typed array.
268moduleOverrides = null;
269
270// Emit code to handle expected values on the Module object. This applies Module.x
271// to the proper local x. This has two benefits: first, we only emit it if it is
272// expected to arrive, and second, by using a local everywhere else that can be
273// minified.
274if (Module['arguments']) arguments_ = Module['arguments'];if (!Object.getOwnPropertyDescriptor(Module, 'arguments')) Object.defineProperty(Module, 'arguments', { configurable: true, get: function() { abort('Module.arguments has been replaced with plain arguments_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
275if (Module['thisProgram']) thisProgram = Module['thisProgram'];if (!Object.getOwnPropertyDescriptor(Module, 'thisProgram')) Object.defineProperty(Module, 'thisProgram', { configurable: true, get: function() { abort('Module.thisProgram has been replaced with plain thisProgram (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
276if (Module['quit']) quit_ = Module['quit'];if (!Object.getOwnPropertyDescriptor(Module, 'quit')) Object.defineProperty(Module, 'quit', { configurable: true, get: function() { abort('Module.quit has been replaced with plain quit_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
277
278// perform assertions in shell.js after we set up out() and err(), as otherwise if an assertion fails it cannot print the message
279// Assertions on removed incoming Module JS APIs.
280assert(typeof Module['memoryInitializerPrefixURL'] === 'undefined', 'Module.memoryInitializerPrefixURL option was removed, use Module.locateFile instead');
281assert(typeof Module['pthreadMainPrefixURL'] === 'undefined', 'Module.pthreadMainPrefixURL option was removed, use Module.locateFile instead');
282assert(typeof Module['cdInitializerPrefixURL'] === 'undefined', 'Module.cdInitializerPrefixURL option was removed, use Module.locateFile instead');
283assert(typeof Module['filePackagePrefixURL'] === 'undefined', 'Module.filePackagePrefixURL option was removed, use Module.locateFile instead');
284assert(typeof Module['read'] === 'undefined', 'Module.read option was removed (modify read_ in JS)');
285assert(typeof Module['readAsync'] === 'undefined', 'Module.readAsync option was removed (modify readAsync in JS)');
286assert(typeof Module['readBinary'] === 'undefined', 'Module.readBinary option was removed (modify readBinary in JS)');
287assert(typeof Module['setWindowTitle'] === 'undefined', 'Module.setWindowTitle option was removed (modify setWindowTitle in JS)');
288assert(typeof Module['TOTAL_MEMORY'] === 'undefined', 'Module.TOTAL_MEMORY has been renamed Module.INITIAL_MEMORY');
289if (!Object.getOwnPropertyDescriptor(Module, 'read')) Object.defineProperty(Module, 'read', { configurable: true, get: function() { abort('Module.read has been replaced with plain read_ (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
290if (!Object.getOwnPropertyDescriptor(Module, 'readAsync')) Object.defineProperty(Module, 'readAsync', { configurable: true, get: function() { abort('Module.readAsync has been replaced with plain readAsync (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
291if (!Object.getOwnPropertyDescriptor(Module, 'readBinary')) Object.defineProperty(Module, 'readBinary', { configurable: true, get: function() { abort('Module.readBinary has been replaced with plain readBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
292if (!Object.getOwnPropertyDescriptor(Module, 'setWindowTitle')) Object.defineProperty(Module, 'setWindowTitle', { configurable: true, get: function() { abort('Module.setWindowTitle has been replaced with plain setWindowTitle (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
293var IDBFS = 'IDBFS is no longer included by default; build with -lidbfs.js';
294var PROXYFS = 'PROXYFS is no longer included by default; build with -lproxyfs.js';
295var WORKERFS = 'WORKERFS is no longer included by default; build with -lworkerfs.js';
296var NODEFS = 'NODEFS is no longer included by default; build with -lnodefs.js';
297
298
299
300
301
302
303// {{PREAMBLE_ADDITIONS}}
304
305var STACK_ALIGN = 16;
306
307function dynamicAlloc(size) {
308 assert(DYNAMICTOP_PTR);
309 var ret = HEAP32[DYNAMICTOP_PTR>>2];
310 var end = (ret + size + 15) & -16;
311 assert(end <= HEAP8.length, 'failure to dynamicAlloc - memory growth etc. is not supported there, call malloc/sbrk directly');
312 HEAP32[DYNAMICTOP_PTR>>2] = end;
313 return ret;
314}
315
316function alignMemory(size, factor) {
317 if (!factor) factor = STACK_ALIGN; // stack alignment (16-byte) by default
318 return Math.ceil(size / factor) * factor;
319}
320
321function getNativeTypeSize(type) {
322 switch (type) {
323 case 'i1': case 'i8': return 1;
324 case 'i16': return 2;
325 case 'i32': return 4;
326 case 'i64': return 8;
327 case 'float': return 4;
328 case 'double': return 8;
329 default: {
330 if (type[type.length-1] === '*') {
331 return 4; // A pointer
332 } else if (type[0] === 'i') {
333 var bits = Number(type.substr(1));
334 assert(bits % 8 === 0, 'getNativeTypeSize invalid bits ' + bits + ', type ' + type);
335 return bits / 8;
336 } else {
337 return 0;
338 }
339 }
340 }
341}
342
343function warnOnce(text) {
344 if (!warnOnce.shown) warnOnce.shown = {};
345 if (!warnOnce.shown[text]) {
346 warnOnce.shown[text] = 1;
347 err(text);
348 }
349}
350
351
352
353
354
355
356
357
358// Wraps a JS function as a wasm function with a given signature.
359function convertJsFunctionToWasm(func, sig) {
360
361 // If the type reflection proposal is available, use the new
362 // "WebAssembly.Function" constructor.
363 // Otherwise, construct a minimal wasm module importing the JS function and
364 // re-exporting it.
365 if (typeof WebAssembly.Function === "function") {
366 var typeNames = {
367 'i': 'i32',
368 'j': 'i64',
369 'f': 'f32',
370 'd': 'f64'
371 };
372 var type = {
373 parameters: [],
374 results: sig[0] == 'v' ? [] : [typeNames[sig[0]]]
375 };
376 for (var i = 1; i < sig.length; ++i) {
377 type.parameters.push(typeNames[sig[i]]);
378 }
379 return new WebAssembly.Function(type, func);
380 }
381
382 // The module is static, with the exception of the type section, which is
383 // generated based on the signature passed in.
384 var typeSection = [
385 0x01, // id: section,
386 0x00, // length: 0 (placeholder)
387 0x01, // count: 1
388 0x60, // form: func
389 ];
390 var sigRet = sig.slice(0, 1);
391 var sigParam = sig.slice(1);
392 var typeCodes = {
393 'i': 0x7f, // i32
394 'j': 0x7e, // i64
395 'f': 0x7d, // f32
396 'd': 0x7c, // f64
397 };
398
399 // Parameters, length + signatures
400 typeSection.push(sigParam.length);
401 for (var i = 0; i < sigParam.length; ++i) {
402 typeSection.push(typeCodes[sigParam[i]]);
403 }
404
405 // Return values, length + signatures
406 // With no multi-return in MVP, either 0 (void) or 1 (anything else)
407 if (sigRet == 'v') {
408 typeSection.push(0x00);
409 } else {
410 typeSection = typeSection.concat([0x01, typeCodes[sigRet]]);
411 }
412
413 // Write the overall length of the type section back into the section header
414 // (excepting the 2 bytes for the section id and length)
415 typeSection[1] = typeSection.length - 2;
416
417 // Rest of the module is static
418 var bytes = new Uint8Array([
419 0x00, 0x61, 0x73, 0x6d, // magic ("\0asm")
420 0x01, 0x00, 0x00, 0x00, // version: 1
421 ].concat(typeSection, [
422 0x02, 0x07, // import section
423 // (import "e" "f" (func 0 (type 0)))
424 0x01, 0x01, 0x65, 0x01, 0x66, 0x00, 0x00,
425 0x07, 0x05, // export section
426 // (export "f" (func 0 (type 0)))
427 0x01, 0x01, 0x66, 0x00, 0x00,
428 ]));
429
430 // We can compile this wasm module synchronously because it is very small.
431 // This accepts an import (at "e.f"), that it reroutes to an export (at "f")
432 var module = new WebAssembly.Module(bytes);
433 var instance = new WebAssembly.Instance(module, {
434 'e': {
435 'f': func
436 }
437 });
438 var wrappedFunc = instance.exports['f'];
439 return wrappedFunc;
440}
441
442var freeTableIndexes = [];
443
444// Weak map of functions in the table to their indexes, created on first use.
445var functionsInTableMap;
446
447// Add a wasm function to the table.
448function addFunctionWasm(func, sig) {
449 var table = wasmTable;
450
451 // Check if the function is already in the table, to ensure each function
452 // gets a unique index. First, create the map if this is the first use.
453 if (!functionsInTableMap) {
454 functionsInTableMap = new WeakMap();
455 for (var i = 0; i < table.length; i++) {
456 var item = table.get(i);
457 // Ignore null values.
458 if (item) {
459 functionsInTableMap.set(item, i);
460 }
461 }
462 }
463 if (functionsInTableMap.has(func)) {
464 return functionsInTableMap.get(func);
465 }
466
467 // It's not in the table, add it now.
468
469
470 var ret;
471 // Reuse a free index if there is one, otherwise grow.
472 if (freeTableIndexes.length) {
473 ret = freeTableIndexes.pop();
474 } else {
475 ret = table.length;
476 // Grow the table
477 try {
478 table.grow(1);
479 } catch (err) {
480 if (!(err instanceof RangeError)) {
481 throw err;
482 }
483 throw 'Unable to grow wasm table. Set ALLOW_TABLE_GROWTH.';
484 }
485 }
486
487 // Set the new value.
488 try {
489 // Attempting to call this with JS function will cause of table.set() to fail
490 table.set(ret, func);
491 } catch (err) {
492 if (!(err instanceof TypeError)) {
493 throw err;
494 }
495 assert(typeof sig !== 'undefined', 'Missing signature argument to addFunction');
496 var wrapped = convertJsFunctionToWasm(func, sig);
497 table.set(ret, wrapped);
498 }
499
500 functionsInTableMap.set(func, ret);
501
502 return ret;
503}
504
505function removeFunctionWasm(index) {
506 functionsInTableMap.delete(wasmTable.get(index));
507 freeTableIndexes.push(index);
508}
509
510// 'sig' parameter is required for the llvm backend but only when func is not
511// already a WebAssembly function.
512function addFunction(func, sig) {
513 assert(typeof func !== 'undefined');
514
515 return addFunctionWasm(func, sig);
516}
517
518function removeFunction(index) {
519 removeFunctionWasm(index);
520}
521
522
523
524var funcWrappers = {};
525
526function getFuncWrapper(func, sig) {
527 if (!func) return; // on null pointer, return undefined
528 assert(sig);
529 if (!funcWrappers[sig]) {
530 funcWrappers[sig] = {};
531 }
532 var sigCache = funcWrappers[sig];
533 if (!sigCache[func]) {
534 // optimize away arguments usage in common cases
535 if (sig.length === 1) {
536 sigCache[func] = function dynCall_wrapper() {
537 return dynCall(sig, func);
538 };
539 } else if (sig.length === 2) {
540 sigCache[func] = function dynCall_wrapper(arg) {
541 return dynCall(sig, func, [arg]);
542 };
543 } else {
544 // general case
545 sigCache[func] = function dynCall_wrapper() {
546 return dynCall(sig, func, Array.prototype.slice.call(arguments));
547 };
548 }
549 }
550 return sigCache[func];
551}
552
553
554
555
556
557
558
559function makeBigInt(low, high, unsigned) {
560 return unsigned ? ((+((low>>>0)))+((+((high>>>0)))*4294967296.0)) : ((+((low>>>0)))+((+((high|0)))*4294967296.0));
561}
562
563/** @param {Array=} args */
564function dynCall(sig, ptr, args) {
565 if (args && args.length) {
566 // j (64-bit integer) must be passed in as two numbers [low 32, high 32].
567 assert(args.length === sig.substring(1).replace(/j/g, '--').length);
568 assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
569 return Module['dynCall_' + sig].apply(null, [ptr].concat(args));
570 } else {
571 assert(sig.length == 1);
572 assert(('dynCall_' + sig) in Module, 'bad function pointer type - no table for sig \'' + sig + '\'');
573 return Module['dynCall_' + sig].call(null, ptr);
574 }
575}
576
577var tempRet0 = 0;
578
579var setTempRet0 = function(value) {
580 tempRet0 = value;
581};
582
583var getTempRet0 = function() {
584 return tempRet0;
585};
586
587function getCompilerSetting(name) {
588 throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for getCompilerSetting or emscripten_get_compiler_setting to work';
589}
590
591// The address globals begin at. Very low in memory, for code size and optimization opportunities.
592// Above 0 is static memory, starting with globals.
593// Then the stack.
594// Then 'dynamic' memory for sbrk.
595var GLOBAL_BASE = 1024;
596
597
598
599
600
601// === Preamble library stuff ===
602
603// Documentation for the public APIs defined in this file must be updated in:
604// site/source/docs/api_reference/preamble.js.rst
605// A prebuilt local version of the documentation is available at:
606// site/build/text/docs/api_reference/preamble.js.txt
607// You can also build docs locally as HTML or other formats in site/
608// An online HTML version (which may be of a different version of Emscripten)
609// is up at http://kripken.github.io/emscripten-site/docs/api_reference/preamble.js.html
610
611
612var wasmBinary;if (Module['wasmBinary']) wasmBinary = Module['wasmBinary'];if (!Object.getOwnPropertyDescriptor(Module, 'wasmBinary')) Object.defineProperty(Module, 'wasmBinary', { configurable: true, get: function() { abort('Module.wasmBinary has been replaced with plain wasmBinary (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
613var noExitRuntime;if (Module['noExitRuntime']) noExitRuntime = Module['noExitRuntime'];if (!Object.getOwnPropertyDescriptor(Module, 'noExitRuntime')) Object.defineProperty(Module, 'noExitRuntime', { configurable: true, get: function() { abort('Module.noExitRuntime has been replaced with plain noExitRuntime (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
614
615
616if (typeof WebAssembly !== 'object') {
617 abort('no native wasm support detected');
618}
619
620
621
622
623// In MINIMAL_RUNTIME, setValue() and getValue() are only available when building with safe heap enabled, for heap safety checking.
624// In traditional runtime, setValue() and getValue() are always available (although their use is highly discouraged due to perf penalties)
625
626/** @param {number} ptr
627 @param {number} value
628 @param {string} type
629 @param {number|boolean=} noSafe */
630function setValue(ptr, value, type, noSafe) {
631 type = type || 'i8';
632 if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
633 switch(type) {
634 case 'i1': HEAP8[((ptr)>>0)]=value; break;
635 case 'i8': HEAP8[((ptr)>>0)]=value; break;
636 case 'i16': HEAP16[((ptr)>>1)]=value; break;
637 case 'i32': HEAP32[((ptr)>>2)]=value; break;
638 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;
639 case 'float': HEAPF32[((ptr)>>2)]=value; break;
640 case 'double': HEAPF64[((ptr)>>3)]=value; break;
641 default: abort('invalid type for setValue: ' + type);
642 }
643}
644
645/** @param {number} ptr
646 @param {string} type
647 @param {number|boolean=} noSafe */
648function getValue(ptr, type, noSafe) {
649 type = type || 'i8';
650 if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
651 switch(type) {
652 case 'i1': return HEAP8[((ptr)>>0)];
653 case 'i8': return HEAP8[((ptr)>>0)];
654 case 'i16': return HEAP16[((ptr)>>1)];
655 case 'i32': return HEAP32[((ptr)>>2)];
656 case 'i64': return HEAP32[((ptr)>>2)];
657 case 'float': return HEAPF32[((ptr)>>2)];
658 case 'double': return HEAPF64[((ptr)>>3)];
659 default: abort('invalid type for getValue: ' + type);
660 }
661 return null;
662}
663
664
665
666
667
668
669// Wasm globals
670
671var wasmMemory;
672
673// In fastcomp asm.js, we don't need a wasm Table at all.
674// In the wasm backend, we polyfill the WebAssembly object,
675// so this creates a (non-native-wasm) table for us.
676var wasmTable = new WebAssembly.Table({
677 'initial': 336,
678 'maximum': 336 + 0,
679 'element': 'anyfunc'
680});
681
682
683//========================================
684// Runtime essentials
685//========================================
686
687// whether we are quitting the application. no code should run after this.
688// set in exit() and abort()
689var ABORT = false;
690
691// set by exit() and abort(). Passed to 'onExit' handler.
692// NOTE: This is also used as the process return code code in shell environments
693// but only when noExitRuntime is false.
694var EXITSTATUS = 0;
695
696/** @type {function(*, string=)} */
697function assert(condition, text) {
698 if (!condition) {
699 abort('Assertion failed: ' + text);
700 }
701}
702
703// Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
704function getCFunc(ident) {
705 var func = Module['_' + ident]; // closure exported function
706 assert(func, 'Cannot call unknown function ' + ident + ', make sure it is exported');
707 return func;
708}
709
710// C calling interface.
711/** @param {string|null=} returnType
712 @param {Array=} argTypes
713 @param {Arguments|Array=} args
714 @param {Object=} opts */
715function ccall(ident, returnType, argTypes, args, opts) {
716 // For fast lookup of conversion functions
717 var toC = {
718 'string': function(str) {
719 var ret = 0;
720 if (str !== null && str !== undefined && str !== 0) { // null string
721 // at most 4 bytes per UTF-8 code point, +1 for the trailing '\0'
722 var len = (str.length << 2) + 1;
723 ret = stackAlloc(len);
724 stringToUTF8(str, ret, len);
725 }
726 return ret;
727 },
728 'array': function(arr) {
729 var ret = stackAlloc(arr.length);
730 writeArrayToMemory(arr, ret);
731 return ret;
732 }
733 };
734
735 function convertReturnValue(ret) {
736 if (returnType === 'string') return UTF8ToString(ret);
737 if (returnType === 'boolean') return Boolean(ret);
738 return ret;
739 }
740
741 var func = getCFunc(ident);
742 var cArgs = [];
743 var stack = 0;
744 assert(returnType !== 'array', 'Return type should not be "array".');
745 if (args) {
746 for (var i = 0; i < args.length; i++) {
747 var converter = toC[argTypes[i]];
748 if (converter) {
749 if (stack === 0) stack = stackSave();
750 cArgs[i] = converter(args[i]);
751 } else {
752 cArgs[i] = args[i];
753 }
754 }
755 }
756 var ret = func.apply(null, cArgs);
757
758 ret = convertReturnValue(ret);
759 if (stack !== 0) stackRestore(stack);
760 return ret;
761}
762
763/** @param {string=} returnType
764 @param {Array=} argTypes
765 @param {Object=} opts */
766function cwrap(ident, returnType, argTypes, opts) {
767 return function() {
768 return ccall(ident, returnType, argTypes, arguments, opts);
769 }
770}
771
772var ALLOC_NORMAL = 0; // Tries to use _malloc()
773var ALLOC_STACK = 1; // Lives for the duration of the current function call
774var ALLOC_DYNAMIC = 2; // Cannot be freed except through sbrk
775var ALLOC_NONE = 3; // Do not allocate
776
777// allocate(): This is for internal use. You can use it yourself as well, but the interface
778// is a little tricky (see docs right below). The reason is that it is optimized
779// for multiple syntaxes to save space in generated code. So you should
780// normally not use allocate(), and instead allocate memory using _malloc(),
781// initialize it with setValue(), and so forth.
782// @slab: An array of data, or a number. If a number, then the size of the block to allocate,
783// in *bytes* (note that this is sometimes confusing: the next parameter does not
784// affect this!)
785// @types: Either an array of types, one for each byte (or 0 if no type at that position),
786// or a single type which is used for the entire block. This only matters if there
787// is initial data - if @slab is a number, then this does not matter at all and is
788// ignored.
789// @allocator: How to allocate memory, see ALLOC_*
790/** @type {function((TypedArray|Array<number>|number), string, number, number=)} */
791function allocate(slab, types, allocator, ptr) {
792 var zeroinit, size;
793 if (typeof slab === 'number') {
794 zeroinit = true;
795 size = slab;
796 } else {
797 zeroinit = false;
798 size = slab.length;
799 }
800
801 var singleType = typeof types === 'string' ? types : null;
802
803 var ret;
804 if (allocator == ALLOC_NONE) {
805 ret = ptr;
806 } else {
807 ret = [_malloc,
808 stackAlloc,
809 dynamicAlloc][allocator](Math.max(size, singleType ? 1 : types.length));
810 }
811
812 if (zeroinit) {
813 var stop;
814 ptr = ret;
815 assert((ret & 3) == 0);
816 stop = ret + (size & ~3);
817 for (; ptr < stop; ptr += 4) {
818 HEAP32[((ptr)>>2)]=0;
819 }
820 stop = ret + size;
821 while (ptr < stop) {
822 HEAP8[((ptr++)>>0)]=0;
823 }
824 return ret;
825 }
826
827 if (singleType === 'i8') {
828 if (slab.subarray || slab.slice) {
829 HEAPU8.set(/** @type {!Uint8Array} */ (slab), ret);
830 } else {
831 HEAPU8.set(new Uint8Array(slab), ret);
832 }
833 return ret;
834 }
835
836 var i = 0, type, typeSize, previousType;
837 while (i < size) {
838 var curr = slab[i];
839
840 type = singleType || types[i];
841 if (type === 0) {
842 i++;
843 continue;
844 }
845 assert(type, 'Must know what type to store in allocate!');
846
847 if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
848
849 setValue(ret+i, curr, type);
850
851 // no need to look up size unless type changes, so cache it
852 if (previousType !== type) {
853 typeSize = getNativeTypeSize(type);
854 previousType = type;
855 }
856 i += typeSize;
857 }
858
859 return ret;
860}
861
862// Allocate memory during any stage of startup - static memory early on, dynamic memory later, malloc when ready
863function getMemory(size) {
864 if (!runtimeInitialized) return dynamicAlloc(size);
865 return _malloc(size);
866}
867
868
869
870
871// runtime_strings.js: Strings related runtime functions that are part of both MINIMAL_RUNTIME and regular runtime.
872
873// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the given array that contains uint8 values, returns
874// a copy of that string as a Javascript String object.
875
876var UTF8Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf8') : undefined;
877
878/**
879 * @param {number} idx
880 * @param {number=} maxBytesToRead
881 * @return {string}
882 */
883function UTF8ArrayToString(heap, idx, maxBytesToRead) {
884 var endIdx = idx + maxBytesToRead;
885 var endPtr = idx;
886 // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
887 // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
888 // (As a tiny code save trick, compare endPtr against endIdx using a negation, so that undefined means Infinity)
889 while (heap[endPtr] && !(endPtr >= endIdx)) ++endPtr;
890
891 if (endPtr - idx > 16 && heap.subarray && UTF8Decoder) {
892 return UTF8Decoder.decode(heap.subarray(idx, endPtr));
893 } else {
894 var str = '';
895 // If building with TextDecoder, we have already computed the string length above, so test loop end condition against that
896 while (idx < endPtr) {
897 // For UTF8 byte structure, see:
898 // http://en.wikipedia.org/wiki/UTF-8#Description
899 // https://www.ietf.org/rfc/rfc2279.txt
900 // https://tools.ietf.org/html/rfc3629
901 var u0 = heap[idx++];
902 if (!(u0 & 0x80)) { str += String.fromCharCode(u0); continue; }
903 var u1 = heap[idx++] & 63;
904 if ((u0 & 0xE0) == 0xC0) { str += String.fromCharCode(((u0 & 31) << 6) | u1); continue; }
905 var u2 = heap[idx++] & 63;
906 if ((u0 & 0xF0) == 0xE0) {
907 u0 = ((u0 & 15) << 12) | (u1 << 6) | u2;
908 } else {
909 if ((u0 & 0xF8) != 0xF0) warnOnce('Invalid UTF-8 leading byte 0x' + u0.toString(16) + ' encountered when deserializing a UTF-8 string on the asm.js/wasm heap to a JS string!');
910 u0 = ((u0 & 7) << 18) | (u1 << 12) | (u2 << 6) | (heap[idx++] & 63);
911 }
912
913 if (u0 < 0x10000) {
914 str += String.fromCharCode(u0);
915 } else {
916 var ch = u0 - 0x10000;
917 str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
918 }
919 }
920 }
921 return str;
922}
923
924// Given a pointer 'ptr' to a null-terminated UTF8-encoded string in the emscripten HEAP, returns a
925// copy of that string as a Javascript String object.
926// maxBytesToRead: an optional length that specifies the maximum number of bytes to read. You can omit
927// this parameter to scan the string until the first \0 byte. If maxBytesToRead is
928// passed, and the string at [ptr, ptr+maxBytesToReadr[ contains a null byte in the
929// middle, then the string will cut short at that byte index (i.e. maxBytesToRead will
930// not produce a string of exact length [ptr, ptr+maxBytesToRead[)
931// N.B. mixing frequent uses of UTF8ToString() with and without maxBytesToRead may
932// throw JS JIT optimizations off, so it is worth to consider consistently using one
933// style or the other.
934/**
935 * @param {number} ptr
936 * @param {number=} maxBytesToRead
937 * @return {string}
938 */
939function UTF8ToString(ptr, maxBytesToRead) {
940 return ptr ? UTF8ArrayToString(HEAPU8, ptr, maxBytesToRead) : '';
941}
942
943// Copies the given Javascript String object 'str' to the given byte array at address 'outIdx',
944// encoded in UTF8 form and null-terminated. The copy will require at most str.length*4+1 bytes of space in the HEAP.
945// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
946// Parameters:
947// str: the Javascript string to copy.
948// heap: the array to copy to. Each index in this array is assumed to be one 8-byte element.
949// outIdx: The starting offset in the array to begin the copying.
950// maxBytesToWrite: The maximum number of bytes this function can write to the array.
951// This count should include the null terminator,
952// i.e. if maxBytesToWrite=1, only the null terminator will be written and nothing else.
953// maxBytesToWrite=0 does not write any bytes to the output, not even the null terminator.
954// Returns the number of bytes written, EXCLUDING the null terminator.
955
956function stringToUTF8Array(str, heap, outIdx, maxBytesToWrite) {
957 if (!(maxBytesToWrite > 0)) // Parameter maxBytesToWrite is not optional. Negative values, 0, null, undefined and false each don't write out any bytes.
958 return 0;
959
960 var startIdx = outIdx;
961 var endIdx = outIdx + maxBytesToWrite - 1; // -1 for string null terminator.
962 for (var i = 0; i < str.length; ++i) {
963 // 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.
964 // See http://unicode.org/faq/utf_bom.html#utf16-3
965 // 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
966 var u = str.charCodeAt(i); // possibly a lead surrogate
967 if (u >= 0xD800 && u <= 0xDFFF) {
968 var u1 = str.charCodeAt(++i);
969 u = 0x10000 + ((u & 0x3FF) << 10) | (u1 & 0x3FF);
970 }
971 if (u <= 0x7F) {
972 if (outIdx >= endIdx) break;
973 heap[outIdx++] = u;
974 } else if (u <= 0x7FF) {
975 if (outIdx + 1 >= endIdx) break;
976 heap[outIdx++] = 0xC0 | (u >> 6);
977 heap[outIdx++] = 0x80 | (u & 63);
978 } else if (u <= 0xFFFF) {
979 if (outIdx + 2 >= endIdx) break;
980 heap[outIdx++] = 0xE0 | (u >> 12);
981 heap[outIdx++] = 0x80 | ((u >> 6) & 63);
982 heap[outIdx++] = 0x80 | (u & 63);
983 } else {
984 if (outIdx + 3 >= endIdx) break;
985 if (u >= 0x200000) warnOnce('Invalid Unicode code point 0x' + u.toString(16) + ' encountered when serializing a JS string to an UTF-8 string on the asm.js/wasm heap! (Valid unicode code points should be in range 0-0x1FFFFF).');
986 heap[outIdx++] = 0xF0 | (u >> 18);
987 heap[outIdx++] = 0x80 | ((u >> 12) & 63);
988 heap[outIdx++] = 0x80 | ((u >> 6) & 63);
989 heap[outIdx++] = 0x80 | (u & 63);
990 }
991 }
992 // Null-terminate the pointer to the buffer.
993 heap[outIdx] = 0;
994 return outIdx - startIdx;
995}
996
997// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
998// null-terminated and encoded in UTF8 form. The copy will require at most str.length*4+1 bytes of space in the HEAP.
999// Use the function lengthBytesUTF8 to compute the exact number of bytes (excluding null terminator) that this function will write.
1000// Returns the number of bytes written, EXCLUDING the null terminator.
1001
1002function stringToUTF8(str, outPtr, maxBytesToWrite) {
1003 assert(typeof maxBytesToWrite == 'number', 'stringToUTF8(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1004 return stringToUTF8Array(str, HEAPU8,outPtr, maxBytesToWrite);
1005}
1006
1007// Returns the number of bytes the given Javascript string takes if encoded as a UTF8 byte array, EXCLUDING the null terminator byte.
1008function lengthBytesUTF8(str) {
1009 var len = 0;
1010 for (var i = 0; i < str.length; ++i) {
1011 // 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.
1012 // See http://unicode.org/faq/utf_bom.html#utf16-3
1013 var u = str.charCodeAt(i); // possibly a lead surrogate
1014 if (u >= 0xD800 && u <= 0xDFFF) u = 0x10000 + ((u & 0x3FF) << 10) | (str.charCodeAt(++i) & 0x3FF);
1015 if (u <= 0x7F) ++len;
1016 else if (u <= 0x7FF) len += 2;
1017 else if (u <= 0xFFFF) len += 3;
1018 else len += 4;
1019 }
1020 return len;
1021}
1022
1023
1024
1025
1026
1027// runtime_strings_extra.js: Strings related runtime functions that are available only in regular runtime.
1028
1029// Given a pointer 'ptr' to a null-terminated ASCII-encoded string in the emscripten HEAP, returns
1030// a copy of that string as a Javascript String object.
1031
1032function AsciiToString(ptr) {
1033 var str = '';
1034 while (1) {
1035 var ch = HEAPU8[((ptr++)>>0)];
1036 if (!ch) return str;
1037 str += String.fromCharCode(ch);
1038 }
1039}
1040
1041// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
1042// null-terminated and encoded in ASCII form. The copy will require at most str.length+1 bytes of space in the HEAP.
1043
1044function stringToAscii(str, outPtr) {
1045 return writeAsciiToMemory(str, outPtr, false);
1046}
1047
1048// Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
1049// a copy of that string as a Javascript String object.
1050
1051var UTF16Decoder = typeof TextDecoder !== 'undefined' ? new TextDecoder('utf-16le') : undefined;
1052
1053function UTF16ToString(ptr, maxBytesToRead) {
1054 assert(ptr % 2 == 0, 'Pointer passed to UTF16ToString must be aligned to two bytes!');
1055 var endPtr = ptr;
1056 // TextDecoder needs to know the byte length in advance, it doesn't stop on null terminator by itself.
1057 // Also, use the length info to avoid running tiny strings through TextDecoder, since .subarray() allocates garbage.
1058 var idx = endPtr >> 1;
1059 var maxIdx = idx + maxBytesToRead / 2;
1060 // If maxBytesToRead is not passed explicitly, it will be undefined, and this
1061 // will always evaluate to true. This saves on code size.
1062 while (!(idx >= maxIdx) && HEAPU16[idx]) ++idx;
1063 endPtr = idx << 1;
1064
1065 if (endPtr - ptr > 32 && UTF16Decoder) {
1066 return UTF16Decoder.decode(HEAPU8.subarray(ptr, endPtr));
1067 } else {
1068 var i = 0;
1069
1070 var str = '';
1071 while (1) {
1072 var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
1073 if (codeUnit == 0 || i == maxBytesToRead / 2) return str;
1074 ++i;
1075 // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
1076 str += String.fromCharCode(codeUnit);
1077 }
1078 }
1079}
1080
1081// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
1082// null-terminated and encoded in UTF16 form. The copy will require at most str.length*4+2 bytes of space in the HEAP.
1083// Use the function lengthBytesUTF16() to compute the exact number of bytes (excluding null terminator) that this function will write.
1084// Parameters:
1085// str: the Javascript string to copy.
1086// outPtr: Byte address in Emscripten HEAP where to write the string to.
1087// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
1088// terminator, i.e. if maxBytesToWrite=2, only the null terminator will be written and nothing else.
1089// maxBytesToWrite<2 does not write any bytes to the output, not even the null terminator.
1090// Returns the number of bytes written, EXCLUDING the null terminator.
1091
1092function stringToUTF16(str, outPtr, maxBytesToWrite) {
1093 assert(outPtr % 2 == 0, 'Pointer passed to stringToUTF16 must be aligned to two bytes!');
1094 assert(typeof maxBytesToWrite == 'number', 'stringToUTF16(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1095 // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
1096 if (maxBytesToWrite === undefined) {
1097 maxBytesToWrite = 0x7FFFFFFF;
1098 }
1099 if (maxBytesToWrite < 2) return 0;
1100 maxBytesToWrite -= 2; // Null terminator.
1101 var startPtr = outPtr;
1102 var numCharsToWrite = (maxBytesToWrite < str.length*2) ? (maxBytesToWrite / 2) : str.length;
1103 for (var i = 0; i < numCharsToWrite; ++i) {
1104 // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
1105 var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
1106 HEAP16[((outPtr)>>1)]=codeUnit;
1107 outPtr += 2;
1108 }
1109 // Null-terminate the pointer to the HEAP.
1110 HEAP16[((outPtr)>>1)]=0;
1111 return outPtr - startPtr;
1112}
1113
1114// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
1115
1116function lengthBytesUTF16(str) {
1117 return str.length*2;
1118}
1119
1120function UTF32ToString(ptr, maxBytesToRead) {
1121 assert(ptr % 4 == 0, 'Pointer passed to UTF32ToString must be aligned to four bytes!');
1122 var i = 0;
1123
1124 var str = '';
1125 // If maxBytesToRead is not passed explicitly, it will be undefined, and this
1126 // will always evaluate to true. This saves on code size.
1127 while (!(i >= maxBytesToRead / 4)) {
1128 var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
1129 if (utf32 == 0) break;
1130 ++i;
1131 // 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.
1132 // See http://unicode.org/faq/utf_bom.html#utf16-3
1133 if (utf32 >= 0x10000) {
1134 var ch = utf32 - 0x10000;
1135 str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
1136 } else {
1137 str += String.fromCharCode(utf32);
1138 }
1139 }
1140 return str;
1141}
1142
1143// Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
1144// null-terminated and encoded in UTF32 form. The copy will require at most str.length*4+4 bytes of space in the HEAP.
1145// Use the function lengthBytesUTF32() to compute the exact number of bytes (excluding null terminator) that this function will write.
1146// Parameters:
1147// str: the Javascript string to copy.
1148// outPtr: Byte address in Emscripten HEAP where to write the string to.
1149// maxBytesToWrite: The maximum number of bytes this function can write to the array. This count should include the null
1150// terminator, i.e. if maxBytesToWrite=4, only the null terminator will be written and nothing else.
1151// maxBytesToWrite<4 does not write any bytes to the output, not even the null terminator.
1152// Returns the number of bytes written, EXCLUDING the null terminator.
1153
1154function stringToUTF32(str, outPtr, maxBytesToWrite) {
1155 assert(outPtr % 4 == 0, 'Pointer passed to stringToUTF32 must be aligned to four bytes!');
1156 assert(typeof maxBytesToWrite == 'number', 'stringToUTF32(str, outPtr, maxBytesToWrite) is missing the third parameter that specifies the length of the output buffer!');
1157 // Backwards compatibility: if max bytes is not specified, assume unsafe unbounded write is allowed.
1158 if (maxBytesToWrite === undefined) {
1159 maxBytesToWrite = 0x7FFFFFFF;
1160 }
1161 if (maxBytesToWrite < 4) return 0;
1162 var startPtr = outPtr;
1163 var endPtr = startPtr + maxBytesToWrite - 4;
1164 for (var i = 0; i < str.length; ++i) {
1165 // 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.
1166 // See http://unicode.org/faq/utf_bom.html#utf16-3
1167 var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
1168 if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
1169 var trailSurrogate = str.charCodeAt(++i);
1170 codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
1171 }
1172 HEAP32[((outPtr)>>2)]=codeUnit;
1173 outPtr += 4;
1174 if (outPtr + 4 > endPtr) break;
1175 }
1176 // Null-terminate the pointer to the HEAP.
1177 HEAP32[((outPtr)>>2)]=0;
1178 return outPtr - startPtr;
1179}
1180
1181// Returns the number of bytes the given Javascript string takes if encoded as a UTF16 byte array, EXCLUDING the null terminator byte.
1182
1183function lengthBytesUTF32(str) {
1184 var len = 0;
1185 for (var i = 0; i < str.length; ++i) {
1186 // 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.
1187 // See http://unicode.org/faq/utf_bom.html#utf16-3
1188 var codeUnit = str.charCodeAt(i);
1189 if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) ++i; // possibly a lead surrogate, so skip over the tail surrogate.
1190 len += 4;
1191 }
1192
1193 return len;
1194}
1195
1196// Allocate heap space for a JS string, and write it there.
1197// It is the responsibility of the caller to free() that memory.
1198function allocateUTF8(str) {
1199 var size = lengthBytesUTF8(str) + 1;
1200 var ret = _malloc(size);
1201 if (ret) stringToUTF8Array(str, HEAP8, ret, size);
1202 return ret;
1203}
1204
1205// Allocate stack space for a JS string, and write it there.
1206function allocateUTF8OnStack(str) {
1207 var size = lengthBytesUTF8(str) + 1;
1208 var ret = stackAlloc(size);
1209 stringToUTF8Array(str, HEAP8, ret, size);
1210 return ret;
1211}
1212
1213// Deprecated: This function should not be called because it is unsafe and does not provide
1214// a maximum length limit of how many bytes it is allowed to write. Prefer calling the
1215// function stringToUTF8Array() instead, which takes in a maximum length that can be used
1216// to be secure from out of bounds writes.
1217/** @deprecated
1218 @param {boolean=} dontAddNull */
1219function writeStringToMemory(string, buffer, dontAddNull) {
1220 warnOnce('writeStringToMemory is deprecated and should not be called! Use stringToUTF8() instead!');
1221
1222 var /** @type {number} */ lastChar, /** @type {number} */ end;
1223 if (dontAddNull) {
1224 // stringToUTF8Array always appends null. If we don't want to do that, remember the
1225 // character that existed at the location where the null will be placed, and restore
1226 // that after the write (below).
1227 end = buffer + lengthBytesUTF8(string);
1228 lastChar = HEAP8[end];
1229 }
1230 stringToUTF8(string, buffer, Infinity);
1231 if (dontAddNull) HEAP8[end] = lastChar; // Restore the value under the null character.
1232}
1233
1234function writeArrayToMemory(array, buffer) {
1235 assert(array.length >= 0, 'writeArrayToMemory array must have a length (should be an array or typed array)')
1236 HEAP8.set(array, buffer);
1237}
1238
1239/** @param {boolean=} dontAddNull */
1240function writeAsciiToMemory(str, buffer, dontAddNull) {
1241 for (var i = 0; i < str.length; ++i) {
1242 assert(str.charCodeAt(i) === str.charCodeAt(i)&0xff);
1243 HEAP8[((buffer++)>>0)]=str.charCodeAt(i);
1244 }
1245 // Null-terminate the pointer to the HEAP.
1246 if (!dontAddNull) HEAP8[((buffer)>>0)]=0;
1247}
1248
1249
1250
1251// Memory management
1252
1253var PAGE_SIZE = 16384;
1254var WASM_PAGE_SIZE = 65536;
1255var ASMJS_PAGE_SIZE = 16777216;
1256
1257function alignUp(x, multiple) {
1258 if (x % multiple > 0) {
1259 x += multiple - (x % multiple);
1260 }
1261 return x;
1262}
1263
1264var HEAP,
1265/** @type {ArrayBuffer} */
1266 buffer,
1267/** @type {Int8Array} */
1268 HEAP8,
1269/** @type {Uint8Array} */
1270 HEAPU8,
1271/** @type {Int16Array} */
1272 HEAP16,
1273/** @type {Uint16Array} */
1274 HEAPU16,
1275/** @type {Int32Array} */
1276 HEAP32,
1277/** @type {Uint32Array} */
1278 HEAPU32,
1279/** @type {Float32Array} */
1280 HEAPF32,
1281/** @type {Float64Array} */
1282 HEAPF64;
1283
1284function updateGlobalBufferAndViews(buf) {
1285 buffer = buf;
1286 Module['HEAP8'] = HEAP8 = new Int8Array(buf);
1287 Module['HEAP16'] = HEAP16 = new Int16Array(buf);
1288 Module['HEAP32'] = HEAP32 = new Int32Array(buf);
1289 Module['HEAPU8'] = HEAPU8 = new Uint8Array(buf);
1290 Module['HEAPU16'] = HEAPU16 = new Uint16Array(buf);
1291 Module['HEAPU32'] = HEAPU32 = new Uint32Array(buf);
1292 Module['HEAPF32'] = HEAPF32 = new Float32Array(buf);
1293 Module['HEAPF64'] = HEAPF64 = new Float64Array(buf);
1294}
1295
1296var STATIC_BASE = 1024,
1297 STACK_BASE = 5322752,
1298 STACKTOP = STACK_BASE,
1299 STACK_MAX = 79872,
1300 DYNAMIC_BASE = 5322752,
1301 DYNAMICTOP_PTR = 79712;
1302
1303assert(STACK_BASE % 16 === 0, 'stack must start aligned');
1304assert(DYNAMIC_BASE % 16 === 0, 'heap must start aligned');
1305
1306
1307var TOTAL_STACK = 5242880;
1308if (Module['TOTAL_STACK']) assert(TOTAL_STACK === Module['TOTAL_STACK'], 'the stack size can no longer be determined at runtime')
1309
1310var INITIAL_INITIAL_MEMORY = Module['INITIAL_MEMORY'] || 16777216;if (!Object.getOwnPropertyDescriptor(Module, 'INITIAL_MEMORY')) Object.defineProperty(Module, 'INITIAL_MEMORY', { configurable: true, get: function() { abort('Module.INITIAL_MEMORY has been replaced with plain INITIAL_INITIAL_MEMORY (the initial value can be provided on Module, but after startup the value is only looked for on a local variable of that name)') } });
1311
1312assert(INITIAL_INITIAL_MEMORY >= TOTAL_STACK, 'INITIAL_MEMORY should be larger than TOTAL_STACK, was ' + INITIAL_INITIAL_MEMORY + '! (TOTAL_STACK=' + TOTAL_STACK + ')');
1313
1314// check for full engine support (use string 'subarray' to avoid closure compiler confusion)
1315assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && Int32Array.prototype.subarray !== undefined && Int32Array.prototype.set !== undefined,
1316 'JS engine does not provide full typed array support');
1317
1318
1319
1320
1321
1322
1323
1324
1325// In non-standalone/normal mode, we create the memory here.
1326
1327
1328
1329// Create the main memory. (Note: this isn't used in STANDALONE_WASM mode since the wasm
1330// memory is created in the wasm, not in JS.)
1331
1332 if (Module['wasmMemory']) {
1333 wasmMemory = Module['wasmMemory'];
1334 } else
1335 {
1336 wasmMemory = new WebAssembly.Memory({
1337 'initial': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
1338 ,
1339 'maximum': INITIAL_INITIAL_MEMORY / WASM_PAGE_SIZE
1340 });
1341 }
1342
1343
1344if (wasmMemory) {
1345 buffer = wasmMemory.buffer;
1346}
1347
1348// If the user provides an incorrect length, just use that length instead rather than providing the user to
1349// specifically provide the memory length with Module['INITIAL_MEMORY'].
1350INITIAL_INITIAL_MEMORY = buffer.byteLength;
1351assert(INITIAL_INITIAL_MEMORY % WASM_PAGE_SIZE === 0);
1352updateGlobalBufferAndViews(buffer);
1353
1354HEAP32[DYNAMICTOP_PTR>>2] = DYNAMIC_BASE;
1355
1356
1357
1358
1359
1360
1361// Initializes the stack cookie. Called at the startup of main and at the startup of each thread in pthreads mode.
1362function writeStackCookie() {
1363 assert((STACK_MAX & 3) == 0);
1364 // The stack grows downwards
1365 HEAPU32[(STACK_MAX >> 2)+1] = 0x2135467;
1366 HEAPU32[(STACK_MAX >> 2)+2] = 0x89BACDFE;
1367 // Also test the global address 0 for integrity.
1368 // We don't do this with ASan because ASan does its own checks for this.
1369 HEAP32[0] = 0x63736d65; /* 'emsc' */
1370}
1371
1372function checkStackCookie() {
1373 var cookie1 = HEAPU32[(STACK_MAX >> 2)+1];
1374 var cookie2 = HEAPU32[(STACK_MAX >> 2)+2];
1375 if (cookie1 != 0x2135467 || cookie2 != 0x89BACDFE) {
1376 abort('Stack overflow! Stack cookie has been overwritten, expected hex dwords 0x89BACDFE and 0x2135467, but received 0x' + cookie2.toString(16) + ' ' + cookie1.toString(16));
1377 }
1378 // Also test the global address 0 for integrity.
1379 // We don't do this with ASan because ASan does its own checks for this.
1380 if (HEAP32[0] !== 0x63736d65 /* 'emsc' */) abort('Runtime error: The application has corrupted its heap memory area (address zero)!');
1381}
1382
1383
1384
1385
1386
1387// Endianness check (note: assumes compiler arch was little-endian)
1388(function() {
1389 var h16 = new Int16Array(1);
1390 var h8 = new Int8Array(h16.buffer);
1391 h16[0] = 0x6373;
1392 if (h8[0] !== 0x73 || h8[1] !== 0x63) throw 'Runtime error: expected the system to be little-endian!';
1393})();
1394
1395function abortFnPtrError(ptr, sig) {
1396 abort("Invalid function pointer " + ptr + " called with signature '" + sig + "'. Perhaps this is an invalid value (e.g. caused by calling a virtual method on a NULL pointer)? Or calling a function with an incorrect type, which will fail? (it is worth building your source files with -Werror (warnings are errors), as warnings can indicate undefined behavior which can cause this). Build with ASSERTIONS=2 for more info.");
1397}
1398
1399
1400
1401function callRuntimeCallbacks(callbacks) {
1402 while(callbacks.length > 0) {
1403 var callback = callbacks.shift();
1404 if (typeof callback == 'function') {
1405 callback(Module); // Pass the module as the first argument.
1406 continue;
1407 }
1408 var func = callback.func;
1409 if (typeof func === 'number') {
1410 if (callback.arg === undefined) {
1411 Module['dynCall_v'](func);
1412 } else {
1413 Module['dynCall_vi'](func, callback.arg);
1414 }
1415 } else {
1416 func(callback.arg === undefined ? null : callback.arg);
1417 }
1418 }
1419}
1420
1421var __ATPRERUN__ = []; // functions called before the runtime is initialized
1422var __ATINIT__ = []; // functions called during startup
1423var __ATMAIN__ = []; // functions called when main() is to be run
1424var __ATEXIT__ = []; // functions called during shutdown
1425var __ATPOSTRUN__ = []; // functions called after the main() is called
1426
1427var runtimeInitialized = false;
1428var runtimeExited = false;
1429
1430
1431function preRun() {
1432
1433 if (Module['preRun']) {
1434 if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
1435 while (Module['preRun'].length) {
1436 addOnPreRun(Module['preRun'].shift());
1437 }
1438 }
1439
1440 callRuntimeCallbacks(__ATPRERUN__);
1441}
1442
1443function initRuntime() {
1444 checkStackCookie();
1445 assert(!runtimeInitialized);
1446 runtimeInitialized = true;
1447 if (!Module["noFSInit"] && !FS.init.initialized) FS.init();
1448TTY.init();
1449 callRuntimeCallbacks(__ATINIT__);
1450}
1451
1452function preMain() {
1453 checkStackCookie();
1454 FS.ignorePermissions = false;
1455 callRuntimeCallbacks(__ATMAIN__);
1456}
1457
1458function exitRuntime() {
1459 checkStackCookie();
1460 runtimeExited = true;
1461}
1462
1463function postRun() {
1464 checkStackCookie();
1465
1466 if (Module['postRun']) {
1467 if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
1468 while (Module['postRun'].length) {
1469 addOnPostRun(Module['postRun'].shift());
1470 }
1471 }
1472
1473 callRuntimeCallbacks(__ATPOSTRUN__);
1474}
1475
1476function addOnPreRun(cb) {
1477 __ATPRERUN__.unshift(cb);
1478}
1479
1480function addOnInit(cb) {
1481 __ATINIT__.unshift(cb);
1482}
1483
1484function addOnPreMain(cb) {
1485 __ATMAIN__.unshift(cb);
1486}
1487
1488function addOnExit(cb) {
1489}
1490
1491function addOnPostRun(cb) {
1492 __ATPOSTRUN__.unshift(cb);
1493}
1494
1495/** @param {number|boolean=} ignore */
1496function unSign(value, bits, ignore) {
1497 if (value >= 0) {
1498 return value;
1499 }
1500 return bits <= 32 ? 2*Math.abs(1 << (bits-1)) + value // Need some trickery, since if bits == 32, we are right at the limit of the bits JS uses in bitshifts
1501 : Math.pow(2, bits) + value;
1502}
1503/** @param {number|boolean=} ignore */
1504function reSign(value, bits, ignore) {
1505 if (value <= 0) {
1506 return value;
1507 }
1508 var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
1509 : Math.pow(2, bits-1);
1510 if (value >= half && (bits <= 32 || value > half)) { // for huge values, we can hit the precision limit and always get true here. so don't do that
1511 // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
1512 // TODO: In i64 mode 1, resign the two parts separately and safely
1513 value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
1514 }
1515 return value;
1516}
1517
1518
1519
1520
1521// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/imul
1522
1523// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/fround
1524
1525// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32
1526
1527// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
1528
1529assert(Math.imul, 'This browser does not support Math.imul(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
1530assert(Math.fround, 'This browser does not support Math.fround(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
1531assert(Math.clz32, 'This browser does not support Math.clz32(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
1532assert(Math.trunc, 'This browser does not support Math.trunc(), build with LEGACY_VM_SUPPORT or POLYFILL_OLD_MATH_FUNCTIONS to add in a polyfill');
1533
1534var Math_abs = Math.abs;
1535var Math_cos = Math.cos;
1536var Math_sin = Math.sin;
1537var Math_tan = Math.tan;
1538var Math_acos = Math.acos;
1539var Math_asin = Math.asin;
1540var Math_atan = Math.atan;
1541var Math_atan2 = Math.atan2;
1542var Math_exp = Math.exp;
1543var Math_log = Math.log;
1544var Math_sqrt = Math.sqrt;
1545var Math_ceil = Math.ceil;
1546var Math_floor = Math.floor;
1547var Math_pow = Math.pow;
1548var Math_imul = Math.imul;
1549var Math_fround = Math.fround;
1550var Math_round = Math.round;
1551var Math_min = Math.min;
1552var Math_max = Math.max;
1553var Math_clz32 = Math.clz32;
1554var Math_trunc = Math.trunc;
1555
1556
1557
1558// A counter of dependencies for calling run(). If we need to
1559// do asynchronous work before running, increment this and
1560// decrement it. Incrementing must happen in a place like
1561// Module.preRun (used by emcc to add file preloading).
1562// Note that you can add dependencies in preRun, even though
1563// it happens right before run - run will be postponed until
1564// the dependencies are met.
1565var runDependencies = 0;
1566var runDependencyWatcher = null;
1567var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
1568var runDependencyTracking = {};
1569
1570function getUniqueRunDependency(id) {
1571 var orig = id;
1572 while (1) {
1573 if (!runDependencyTracking[id]) return id;
1574 id = orig + Math.random();
1575 }
1576}
1577
1578function addRunDependency(id) {
1579 runDependencies++;
1580
1581 if (Module['monitorRunDependencies']) {
1582 Module['monitorRunDependencies'](runDependencies);
1583 }
1584
1585 if (id) {
1586 assert(!runDependencyTracking[id]);
1587 runDependencyTracking[id] = 1;
1588 if (runDependencyWatcher === null && typeof setInterval !== 'undefined') {
1589 // Check for missing dependencies every few seconds
1590 runDependencyWatcher = setInterval(function() {
1591 if (ABORT) {
1592 clearInterval(runDependencyWatcher);
1593 runDependencyWatcher = null;
1594 return;
1595 }
1596 var shown = false;
1597 for (var dep in runDependencyTracking) {
1598 if (!shown) {
1599 shown = true;
1600 err('still waiting on run dependencies:');
1601 }
1602 err('dependency: ' + dep);
1603 }
1604 if (shown) {
1605 err('(end of list)');
1606 }
1607 }, 10000);
1608 }
1609 } else {
1610 err('warning: run dependency added without ID');
1611 }
1612}
1613
1614function removeRunDependency(id) {
1615 runDependencies--;
1616
1617 if (Module['monitorRunDependencies']) {
1618 Module['monitorRunDependencies'](runDependencies);
1619 }
1620
1621 if (id) {
1622 assert(runDependencyTracking[id]);
1623 delete runDependencyTracking[id];
1624 } else {
1625 err('warning: run dependency removed without ID');
1626 }
1627 if (runDependencies == 0) {
1628 if (runDependencyWatcher !== null) {
1629 clearInterval(runDependencyWatcher);
1630 runDependencyWatcher = null;
1631 }
1632 if (dependenciesFulfilled) {
1633 var callback = dependenciesFulfilled;
1634 dependenciesFulfilled = null;
1635 callback(); // can add another dependenciesFulfilled
1636 }
1637 }
1638}
1639
1640Module["preloadedImages"] = {}; // maps url to image data
1641Module["preloadedAudios"] = {}; // maps url to audio data
1642
1643/** @param {string|number=} what */
1644function abort(what) {
1645 if (Module['onAbort']) {
1646 Module['onAbort'](what);
1647 }
1648
1649 what += '';
1650 out(what);
1651 err(what);
1652
1653 ABORT = true;
1654 EXITSTATUS = 1;
1655
1656 var output = 'abort(' + what + ') at ' + stackTrace();
1657 what = output;
1658
1659 // Throw a wasm runtime error, because a JS error might be seen as a foreign
1660 // exception, which means we'd run destructors on it. We need the error to
1661 // simply make the program stop.
1662 throw new WebAssembly.RuntimeError(what);
1663}
1664
1665
1666var memoryInitializer = null;
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679function hasPrefix(str, prefix) {
1680 return String.prototype.startsWith ?
1681 str.startsWith(prefix) :
1682 str.indexOf(prefix) === 0;
1683}
1684
1685// Prefix of data URIs emitted by SINGLE_FILE and related options.
1686var dataURIPrefix = 'data:application/octet-stream;base64,';
1687
1688// Indicates whether filename is a base64 data URI.
1689function isDataURI(filename) {
1690 return hasPrefix(filename, dataURIPrefix);
1691}
1692
1693var fileURIPrefix = "file://";
1694
1695// Indicates whether filename is delivered via file protocol (as opposed to http/https)
1696function isFileURI(filename) {
1697 return hasPrefix(filename, fileURIPrefix);
1698}
1699
1700
1701
1702function createExportWrapper(name, fixedasm) {
1703 return function() {
1704 var displayName = name;
1705 var asm = fixedasm;
1706 if (!fixedasm) {
1707 asm = Module['asm'];
1708 }
1709 assert(runtimeInitialized, 'native function `' + displayName + '` called before runtime initialization');
1710 assert(!runtimeExited, 'native function `' + displayName + '` called after runtime exit (use NO_EXIT_RUNTIME to keep it alive after main() exits)');
1711 if (!asm[name]) {
1712 assert(asm[name], 'exported native function `' + displayName + '` not found');
1713 }
1714 return asm[name].apply(null, arguments);
1715 };
1716}
1717
1718var wasmBinaryFile = 'mrbc.wasm';
1719if (!isDataURI(wasmBinaryFile)) {
1720 wasmBinaryFile = locateFile(wasmBinaryFile);
1721}
1722
1723function getBinary() {
1724 try {
1725 if (wasmBinary) {
1726 return new Uint8Array(wasmBinary);
1727 }
1728
1729 if (readBinary) {
1730 return readBinary(wasmBinaryFile);
1731 } else {
1732 throw "both async and sync fetching of the wasm failed";
1733 }
1734 }
1735 catch (err) {
1736 abort(err);
1737 }
1738}
1739
1740function getBinaryPromise() {
1741 // If we don't have the binary yet, and have the Fetch api, use that;
1742 // in some environments, like Electron's render process, Fetch api may be present, but have a different context than expected, let's only use it on the Web
1743 if (!wasmBinary && (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) && typeof fetch === 'function'
1744 // Let's not use fetch to get objects over file:// as it's most likely Cordova which doesn't support fetch for file://
1745 && !isFileURI(wasmBinaryFile)
1746 ) {
1747 return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function(response) {
1748 if (!response['ok']) {
1749 throw "failed to load wasm binary file at '" + wasmBinaryFile + "'";
1750 }
1751 return response['arrayBuffer']();
1752 }).catch(function () {
1753 return getBinary();
1754 });
1755 }
1756 // Otherwise, getBinary should be able to get it synchronously
1757 return new Promise(function(resolve, reject) {
1758 resolve(getBinary());
1759 });
1760}
1761
1762
1763
1764// Create the wasm instance.
1765// Receives the wasm imports, returns the exports.
1766function createWasm() {
1767 // prepare imports
1768 var info = {
1769 'env': asmLibraryArg,
1770 'wasi_snapshot_preview1': asmLibraryArg
1771 };
1772 // Load the wasm module and create an instance of using native support in the JS engine.
1773 // handle a generated wasm instance, receiving its exports and
1774 // performing other necessary setup
1775 /** @param {WebAssembly.Module=} module*/
1776 function receiveInstance(instance, module) {
1777 var exports = instance.exports;
1778 Module['asm'] = exports;
1779 removeRunDependency('wasm-instantiate');
1780 }
1781 // we can't run yet (except in a pthread, where we have a custom sync instantiator)
1782 addRunDependency('wasm-instantiate');
1783
1784
1785 // Async compilation can be confusing when an error on the page overwrites Module
1786 // (for example, if the order of elements is wrong, and the one defining Module is
1787 // later), so we save Module and check it later.
1788 var trueModule = Module;
1789 function receiveInstantiatedSource(output) {
1790 // 'output' is a WebAssemblyInstantiatedSource object which has both the module and instance.
1791 // receiveInstance() will swap in the exports (to Module.asm) so they can be called
1792 assert(Module === trueModule, 'the Module object should not be replaced during async compilation - perhaps the order of HTML elements is wrong?');
1793 trueModule = null;
1794 // 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.
1795 // When the regression is fixed, can restore the above USE_PTHREADS-enabled path.
1796 receiveInstance(output['instance']);
1797 }
1798
1799
1800 function instantiateArrayBuffer(receiver) {
1801 return getBinaryPromise().then(function(binary) {
1802 return WebAssembly.instantiate(binary, info);
1803 }).then(receiver, function(reason) {
1804 err('failed to asynchronously prepare wasm: ' + reason);
1805
1806
1807 abort(reason);
1808 });
1809 }
1810
1811 // Prefer streaming instantiation if available.
1812 function instantiateAsync() {
1813 if (!wasmBinary &&
1814 typeof WebAssembly.instantiateStreaming === 'function' &&
1815 !isDataURI(wasmBinaryFile) &&
1816 // Don't use streaming for file:// delivered objects in a webview, fetch them synchronously.
1817 !isFileURI(wasmBinaryFile) &&
1818 typeof fetch === 'function') {
1819 fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {
1820 var result = WebAssembly.instantiateStreaming(response, info);
1821 return result.then(receiveInstantiatedSource, function(reason) {
1822 // We expect the most common failure cause to be a bad MIME type for the binary,
1823 // in which case falling back to ArrayBuffer instantiation should work.
1824 err('wasm streaming compile failed: ' + reason);
1825 err('falling back to ArrayBuffer instantiation');
1826 return instantiateArrayBuffer(receiveInstantiatedSource);
1827 });
1828 });
1829 } else {
1830 return instantiateArrayBuffer(receiveInstantiatedSource);
1831 }
1832 }
1833 // User shell pages can write their own Module.instantiateWasm = function(imports, successCallback) callback
1834 // to manually instantiate the Wasm module themselves. This allows pages to run the instantiation parallel
1835 // to any other async startup actions they are performing.
1836 if (Module['instantiateWasm']) {
1837 try {
1838 var exports = Module['instantiateWasm'](info, receiveInstance);
1839 return exports;
1840 } catch(e) {
1841 err('Module.instantiateWasm callback failed with error: ' + e);
1842 return false;
1843 }
1844 }
1845
1846 instantiateAsync();
1847 return {}; // no exports yet; we'll fill them in later
1848}
1849
1850
1851// Globals used by JS i64 conversions
1852var tempDouble;
1853var tempI64;
1854
1855// === Body ===
1856
1857var ASM_CONSTS = {
1858
1859};
1860
1861
1862
1863
1864// STATICTOP = STATIC_BASE + 78848;
1865/* global initializers */ __ATINIT__.push({ func: function() { ___wasm_call_ctors() } });
1866
1867
1868
1869
1870/* no memory initializer */
1871// {{PRE_LIBRARY}}
1872
1873
1874
1875
1876 function _emscripten_set_main_loop_timing(mode, value) {
1877 Browser.mainLoop.timingMode = mode;
1878 Browser.mainLoop.timingValue = value;
1879
1880 if (!Browser.mainLoop.func) {
1881 console.error('emscripten_set_main_loop_timing: Cannot set timing mode for main loop since a main loop does not exist! Call emscripten_set_main_loop first to set one up.');
1882 return 1; // Return non-zero on failure, can't set timing mode when there is no main loop.
1883 }
1884
1885 if (mode == 0 /*EM_TIMING_SETTIMEOUT*/) {
1886 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setTimeout() {
1887 var timeUntilNextTick = Math.max(0, Browser.mainLoop.tickStartTime + value - _emscripten_get_now())|0;
1888 setTimeout(Browser.mainLoop.runner, timeUntilNextTick); // doing this each time means that on exception, we stop
1889 };
1890 Browser.mainLoop.method = 'timeout';
1891 } else if (mode == 1 /*EM_TIMING_RAF*/) {
1892 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_rAF() {
1893 Browser.requestAnimationFrame(Browser.mainLoop.runner);
1894 };
1895 Browser.mainLoop.method = 'rAF';
1896 } else if (mode == 2 /*EM_TIMING_SETIMMEDIATE*/) {
1897 if (typeof setImmediate === 'undefined') {
1898 // Emulate setImmediate. (note: not a complete polyfill, we don't emulate clearImmediate() to keep code size to minimum, since not needed)
1899 var setImmediates = [];
1900 var emscriptenMainLoopMessageId = 'setimmediate';
1901 var Browser_setImmediate_messageHandler = function(event) {
1902 // When called in current thread or Worker, the main loop ID is structured slightly different to accommodate for --proxy-to-worker runtime listening to Worker events,
1903 // so check for both cases.
1904 if (event.data === emscriptenMainLoopMessageId || event.data.target === emscriptenMainLoopMessageId) {
1905 event.stopPropagation();
1906 setImmediates.shift()();
1907 }
1908 }
1909 addEventListener("message", Browser_setImmediate_messageHandler, true);
1910 setImmediate = /** @type{function(function(): ?, ...?): number} */(function Browser_emulated_setImmediate(func) {
1911 setImmediates.push(func);
1912 if (ENVIRONMENT_IS_WORKER) {
1913 if (Module['setImmediates'] === undefined) Module['setImmediates'] = [];
1914 Module['setImmediates'].push(func);
1915 postMessage({target: emscriptenMainLoopMessageId}); // In --proxy-to-worker, route the message via proxyClient.js
1916 } else postMessage(emscriptenMainLoopMessageId, "*"); // On the main thread, can just send the message to itself.
1917 })
1918 }
1919 Browser.mainLoop.scheduler = function Browser_mainLoop_scheduler_setImmediate() {
1920 setImmediate(Browser.mainLoop.runner);
1921 };
1922 Browser.mainLoop.method = 'immediate';
1923 }
1924 return 0;
1925 }
1926
1927 var _emscripten_get_now;if (ENVIRONMENT_IS_NODE) {
1928 _emscripten_get_now = function() {
1929 var t = process['hrtime']();
1930 return t[0] * 1e3 + t[1] / 1e6;
1931 };
1932 } else if (typeof dateNow !== 'undefined') {
1933 _emscripten_get_now = dateNow;
1934 } else _emscripten_get_now = function() { return performance.now(); }
1935 ;/** @param {number|boolean=} noSetTiming */
1936 function _emscripten_set_main_loop(func, fps, simulateInfiniteLoop, arg, noSetTiming) {
1937 noExitRuntime = true;
1938
1939 assert(!Browser.mainLoop.func, 'emscripten_set_main_loop: there can only be one main loop function at once: call emscripten_cancel_main_loop to cancel the previous one before setting a new one with different parameters.');
1940
1941 Browser.mainLoop.func = func;
1942 Browser.mainLoop.arg = arg;
1943
1944 var browserIterationFunc;
1945 if (typeof arg !== 'undefined') {
1946 browserIterationFunc = function() {
1947 Module['dynCall_vi'](func, arg);
1948 };
1949 } else {
1950 browserIterationFunc = function() {
1951 Module['dynCall_v'](func);
1952 };
1953 }
1954
1955 var thisMainLoopId = Browser.mainLoop.currentlyRunningMainloop;
1956
1957 Browser.mainLoop.runner = function Browser_mainLoop_runner() {
1958 if (ABORT) return;
1959 if (Browser.mainLoop.queue.length > 0) {
1960 var start = Date.now();
1961 var blocker = Browser.mainLoop.queue.shift();
1962 blocker.func(blocker.arg);
1963 if (Browser.mainLoop.remainingBlockers) {
1964 var remaining = Browser.mainLoop.remainingBlockers;
1965 var next = remaining%1 == 0 ? remaining-1 : Math.floor(remaining);
1966 if (blocker.counted) {
1967 Browser.mainLoop.remainingBlockers = next;
1968 } else {
1969 // not counted, but move the progress along a tiny bit
1970 next = next + 0.5; // do not steal all the next one's progress
1971 Browser.mainLoop.remainingBlockers = (8*remaining + next)/9;
1972 }
1973 }
1974 console.log('main loop blocker "' + blocker.name + '" took ' + (Date.now() - start) + ' ms'); //, left: ' + Browser.mainLoop.remainingBlockers);
1975 Browser.mainLoop.updateStatus();
1976
1977 // catches pause/resume main loop from blocker execution
1978 if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
1979
1980 setTimeout(Browser.mainLoop.runner, 0);
1981 return;
1982 }
1983
1984 // catch pauses from non-main loop sources
1985 if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
1986
1987 // Implement very basic swap interval control
1988 Browser.mainLoop.currentFrameNumber = Browser.mainLoop.currentFrameNumber + 1 | 0;
1989 if (Browser.mainLoop.timingMode == 1/*EM_TIMING_RAF*/ && Browser.mainLoop.timingValue > 1 && Browser.mainLoop.currentFrameNumber % Browser.mainLoop.timingValue != 0) {
1990 // Not the scheduled time to render this frame - skip.
1991 Browser.mainLoop.scheduler();
1992 return;
1993 } else if (Browser.mainLoop.timingMode == 0/*EM_TIMING_SETTIMEOUT*/) {
1994 Browser.mainLoop.tickStartTime = _emscripten_get_now();
1995 }
1996
1997 // Signal GL rendering layer that processing of a new frame is about to start. This helps it optimize
1998 // VBO double-buffering and reduce GPU stalls.
1999
2000
2001
2002 if (Browser.mainLoop.method === 'timeout' && Module.ctx) {
2003 warnOnce('Looks like you are rendering without using requestAnimationFrame for the main loop. You should use 0 for the frame rate in emscripten_set_main_loop in order to use requestAnimationFrame, as that can greatly improve your frame rates!');
2004 Browser.mainLoop.method = ''; // just warn once per call to set main loop
2005 }
2006
2007 Browser.mainLoop.runIter(browserIterationFunc);
2008
2009 checkStackCookie();
2010
2011 // catch pauses from the main loop itself
2012 if (thisMainLoopId < Browser.mainLoop.currentlyRunningMainloop) return;
2013
2014 // Queue new audio data. This is important to be right after the main loop invocation, so that we will immediately be able
2015 // to queue the newest produced audio samples.
2016 // TODO: Consider adding pre- and post- rAF callbacks so that GL.newRenderingFrameStarted() and SDL.audio.queueNewAudioData()
2017 // do not need to be hardcoded into this function, but can be more generic.
2018 if (typeof SDL === 'object' && SDL.audio && SDL.audio.queueNewAudioData) SDL.audio.queueNewAudioData();
2019
2020 Browser.mainLoop.scheduler();
2021 }
2022
2023 if (!noSetTiming) {
2024 if (fps && fps > 0) _emscripten_set_main_loop_timing(0/*EM_TIMING_SETTIMEOUT*/, 1000.0 / fps);
2025 else _emscripten_set_main_loop_timing(1/*EM_TIMING_RAF*/, 1); // Do rAF by rendering each frame (no decimating)
2026
2027 Browser.mainLoop.scheduler();
2028 }
2029
2030 if (simulateInfiniteLoop) {
2031 throw 'unwind';
2032 }
2033 }var Browser={mainLoop:{scheduler:null,method:"",currentlyRunningMainloop:0,func:null,arg:0,timingMode:0,timingValue:0,currentFrameNumber:0,queue:[],pause:function() {
2034 Browser.mainLoop.scheduler = null;
2035 Browser.mainLoop.currentlyRunningMainloop++; // Incrementing this signals the previous main loop that it's now become old, and it must return.
2036 },resume:function() {
2037 Browser.mainLoop.currentlyRunningMainloop++;
2038 var timingMode = Browser.mainLoop.timingMode;
2039 var timingValue = Browser.mainLoop.timingValue;
2040 var func = Browser.mainLoop.func;
2041 Browser.mainLoop.func = null;
2042 _emscripten_set_main_loop(func, 0, false, Browser.mainLoop.arg, true /* do not set timing and call scheduler, we will do it on the next lines */);
2043 _emscripten_set_main_loop_timing(timingMode, timingValue);
2044 Browser.mainLoop.scheduler();
2045 },updateStatus:function() {
2046 if (Module['setStatus']) {
2047 var message = Module['statusMessage'] || 'Please wait...';
2048 var remaining = Browser.mainLoop.remainingBlockers;
2049 var expected = Browser.mainLoop.expectedBlockers;
2050 if (remaining) {
2051 if (remaining < expected) {
2052 Module['setStatus'](message + ' (' + (expected - remaining) + '/' + expected + ')');
2053 } else {
2054 Module['setStatus'](message);
2055 }
2056 } else {
2057 Module['setStatus']('');
2058 }
2059 }
2060 },runIter:function(func) {
2061 if (ABORT) return;
2062 if (Module['preMainLoop']) {
2063 var preRet = Module['preMainLoop']();
2064 if (preRet === false) {
2065 return; // |return false| skips a frame
2066 }
2067 }
2068 try {
2069 func();
2070 } catch (e) {
2071 if (e instanceof ExitStatus) {
2072 return;
2073 } else {
2074 if (e && typeof e === 'object' && e.stack) err('exception thrown: ' + [e, e.stack]);
2075 throw e;
2076 }
2077 }
2078 if (Module['postMainLoop']) Module['postMainLoop']();
2079 }},isFullscreen:false,pointerLock:false,moduleContextCreatedCallbacks:[],workers:[],init:function() {
2080 if (!Module["preloadPlugins"]) Module["preloadPlugins"] = []; // needs to exist even in workers
2081
2082 if (Browser.initted) return;
2083 Browser.initted = true;
2084
2085 try {
2086 new Blob();
2087 Browser.hasBlobConstructor = true;
2088 } catch(e) {
2089 Browser.hasBlobConstructor = false;
2090 console.log("warning: no blob constructor, cannot create blobs with mimetypes");
2091 }
2092 Browser.BlobBuilder = typeof MozBlobBuilder != "undefined" ? MozBlobBuilder : (typeof WebKitBlobBuilder != "undefined" ? WebKitBlobBuilder : (!Browser.hasBlobConstructor ? console.log("warning: no BlobBuilder") : null));
2093 Browser.URLObject = typeof window != "undefined" ? (window.URL ? window.URL : window.webkitURL) : undefined;
2094 if (!Module.noImageDecoding && typeof Browser.URLObject === 'undefined') {
2095 console.log("warning: Browser does not support creating object URLs. Built-in browser image decoding will not be available.");
2096 Module.noImageDecoding = true;
2097 }
2098
2099 // Support for plugins that can process preloaded files. You can add more of these to
2100 // your app by creating and appending to Module.preloadPlugins.
2101 //
2102 // Each plugin is asked if it can handle a file based on the file's name. If it can,
2103 // it is given the file's raw data. When it is done, it calls a callback with the file's
2104 // (possibly modified) data. For example, a plugin might decompress a file, or it
2105 // might create some side data structure for use later (like an Image element, etc.).
2106
2107 var imagePlugin = {};
2108 imagePlugin['canHandle'] = function imagePlugin_canHandle(name) {
2109 return !Module.noImageDecoding && /\.(jpg|jpeg|png|bmp)$/i.test(name);
2110 };
2111 imagePlugin['handle'] = function imagePlugin_handle(byteArray, name, onload, onerror) {
2112 var b = null;
2113 if (Browser.hasBlobConstructor) {
2114 try {
2115 b = new Blob([byteArray], { type: Browser.getMimetype(name) });
2116 if (b.size !== byteArray.length) { // Safari bug #118630
2117 // Safari's Blob can only take an ArrayBuffer
2118 b = new Blob([(new Uint8Array(byteArray)).buffer], { type: Browser.getMimetype(name) });
2119 }
2120 } catch(e) {
2121 warnOnce('Blob constructor present but fails: ' + e + '; falling back to blob builder');
2122 }
2123 }
2124 if (!b) {
2125 var bb = new Browser.BlobBuilder();
2126 bb.append((new Uint8Array(byteArray)).buffer); // we need to pass a buffer, and must copy the array to get the right data range
2127 b = bb.getBlob();
2128 }
2129 var url = Browser.URLObject.createObjectURL(b);
2130 assert(typeof url == 'string', 'createObjectURL must return a url as a string');
2131 var img = new Image();
2132 img.onload = function img_onload() {
2133 assert(img.complete, 'Image ' + name + ' could not be decoded');
2134 var canvas = document.createElement('canvas');
2135 canvas.width = img.width;
2136 canvas.height = img.height;
2137 var ctx = canvas.getContext('2d');
2138 ctx.drawImage(img, 0, 0);
2139 Module["preloadedImages"][name] = canvas;
2140 Browser.URLObject.revokeObjectURL(url);
2141 if (onload) onload(byteArray);
2142 };
2143 img.onerror = function img_onerror(event) {
2144 console.log('Image ' + url + ' could not be decoded');
2145 if (onerror) onerror();
2146 };
2147 img.src = url;
2148 };
2149 Module['preloadPlugins'].push(imagePlugin);
2150
2151 var audioPlugin = {};
2152 audioPlugin['canHandle'] = function audioPlugin_canHandle(name) {
2153 return !Module.noAudioDecoding && name.substr(-4) in { '.ogg': 1, '.wav': 1, '.mp3': 1 };
2154 };
2155 audioPlugin['handle'] = function audioPlugin_handle(byteArray, name, onload, onerror) {
2156 var done = false;
2157 function finish(audio) {
2158 if (done) return;
2159 done = true;
2160 Module["preloadedAudios"][name] = audio;
2161 if (onload) onload(byteArray);
2162 }
2163 function fail() {
2164 if (done) return;
2165 done = true;
2166 Module["preloadedAudios"][name] = new Audio(); // empty shim
2167 if (onerror) onerror();
2168 }
2169 if (Browser.hasBlobConstructor) {
2170 try {
2171 var b = new Blob([byteArray], { type: Browser.getMimetype(name) });
2172 } catch(e) {
2173 return fail();
2174 }
2175 var url = Browser.URLObject.createObjectURL(b); // XXX we never revoke this!
2176 assert(typeof url == 'string', 'createObjectURL must return a url as a string');
2177 var audio = new Audio();
2178 audio.addEventListener('canplaythrough', function() { finish(audio) }, false); // use addEventListener due to chromium bug 124926
2179 audio.onerror = function audio_onerror(event) {
2180 if (done) return;
2181 console.log('warning: browser could not fully decode audio ' + name + ', trying slower base64 approach');
2182 function encode64(data) {
2183 var BASE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
2184 var PAD = '=';
2185 var ret = '';
2186 var leftchar = 0;
2187 var leftbits = 0;
2188 for (var i = 0; i < data.length; i++) {
2189 leftchar = (leftchar << 8) | data[i];
2190 leftbits += 8;
2191 while (leftbits >= 6) {
2192 var curr = (leftchar >> (leftbits-6)) & 0x3f;
2193 leftbits -= 6;
2194 ret += BASE[curr];
2195 }
2196 }
2197 if (leftbits == 2) {
2198 ret += BASE[(leftchar&3) << 4];
2199 ret += PAD + PAD;
2200 } else if (leftbits == 4) {
2201 ret += BASE[(leftchar&0xf) << 2];
2202 ret += PAD;
2203 }
2204 return ret;
2205 }
2206 audio.src = 'data:audio/x-' + name.substr(-3) + ';base64,' + encode64(byteArray);
2207 finish(audio); // we don't wait for confirmation this worked - but it's worth trying
2208 };
2209 audio.src = url;
2210 // workaround for chrome bug 124926 - we do not always get oncanplaythrough or onerror
2211 Browser.safeSetTimeout(function() {
2212 finish(audio); // try to use it even though it is not necessarily ready to play
2213 }, 10000);
2214 } else {
2215 return fail();
2216 }
2217 };
2218 Module['preloadPlugins'].push(audioPlugin);
2219
2220
2221 // Canvas event setup
2222
2223 function pointerLockChange() {
2224 Browser.pointerLock = document['pointerLockElement'] === Module['canvas'] ||
2225 document['mozPointerLockElement'] === Module['canvas'] ||
2226 document['webkitPointerLockElement'] === Module['canvas'] ||
2227 document['msPointerLockElement'] === Module['canvas'];
2228 }
2229 var canvas = Module['canvas'];
2230 if (canvas) {
2231 // forced aspect ratio can be enabled by defining 'forcedAspectRatio' on Module
2232 // Module['forcedAspectRatio'] = 4 / 3;
2233
2234 canvas.requestPointerLock = canvas['requestPointerLock'] ||
2235 canvas['mozRequestPointerLock'] ||
2236 canvas['webkitRequestPointerLock'] ||
2237 canvas['msRequestPointerLock'] ||
2238 function(){};
2239 canvas.exitPointerLock = document['exitPointerLock'] ||
2240 document['mozExitPointerLock'] ||
2241 document['webkitExitPointerLock'] ||
2242 document['msExitPointerLock'] ||
2243 function(){}; // no-op if function does not exist
2244 canvas.exitPointerLock = canvas.exitPointerLock.bind(document);
2245
2246 document.addEventListener('pointerlockchange', pointerLockChange, false);
2247 document.addEventListener('mozpointerlockchange', pointerLockChange, false);
2248 document.addEventListener('webkitpointerlockchange', pointerLockChange, false);
2249 document.addEventListener('mspointerlockchange', pointerLockChange, false);
2250
2251 if (Module['elementPointerLock']) {
2252 canvas.addEventListener("click", function(ev) {
2253 if (!Browser.pointerLock && Module['canvas'].requestPointerLock) {
2254 Module['canvas'].requestPointerLock();
2255 ev.preventDefault();
2256 }
2257 }, false);
2258 }
2259 }
2260 },createContext:function(canvas, useWebGL, setInModule, webGLContextAttributes) {
2261 if (useWebGL && Module.ctx && canvas == Module.canvas) return Module.ctx; // no need to recreate GL context if it's already been created for this canvas.
2262
2263 var ctx;
2264 var contextHandle;
2265 if (useWebGL) {
2266 // For GLES2/desktop GL compatibility, adjust a few defaults to be different to WebGL defaults, so that they align better with the desktop defaults.
2267 var contextAttributes = {
2268 antialias: false,
2269 alpha: false,
2270 majorVersion: 1,
2271 };
2272
2273 if (webGLContextAttributes) {
2274 for (var attribute in webGLContextAttributes) {
2275 contextAttributes[attribute] = webGLContextAttributes[attribute];
2276 }
2277 }
2278
2279 // This check of existence of GL is here to satisfy Closure compiler, which yells if variable GL is referenced below but GL object is not
2280 // actually compiled in because application is not doing any GL operations. TODO: Ideally if GL is not being used, this function
2281 // Browser.createContext() should not even be emitted.
2282 if (typeof GL !== 'undefined') {
2283 contextHandle = GL.createContext(canvas, contextAttributes);
2284 if (contextHandle) {
2285 ctx = GL.getContext(contextHandle).GLctx;
2286 }
2287 }
2288 } else {
2289 ctx = canvas.getContext('2d');
2290 }
2291
2292 if (!ctx) return null;
2293
2294 if (setInModule) {
2295 if (!useWebGL) assert(typeof GLctx === 'undefined', 'cannot set in module if GLctx is used, but we are a non-GL context that would replace it');
2296
2297 Module.ctx = ctx;
2298 if (useWebGL) GL.makeContextCurrent(contextHandle);
2299 Module.useWebGL = useWebGL;
2300 Browser.moduleContextCreatedCallbacks.forEach(function(callback) { callback() });
2301 Browser.init();
2302 }
2303 return ctx;
2304 },destroyContext:function(canvas, useWebGL, setInModule) {},fullscreenHandlersInstalled:false,lockPointer:undefined,resizeCanvas:undefined,requestFullscreen:function(lockPointer, resizeCanvas) {
2305 Browser.lockPointer = lockPointer;
2306 Browser.resizeCanvas = resizeCanvas;
2307 if (typeof Browser.lockPointer === 'undefined') Browser.lockPointer = true;
2308 if (typeof Browser.resizeCanvas === 'undefined') Browser.resizeCanvas = false;
2309
2310 var canvas = Module['canvas'];
2311 function fullscreenChange() {
2312 Browser.isFullscreen = false;
2313 var canvasContainer = canvas.parentNode;
2314 if ((document['fullscreenElement'] || document['mozFullScreenElement'] ||
2315 document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
2316 document['webkitCurrentFullScreenElement']) === canvasContainer) {
2317 canvas.exitFullscreen = Browser.exitFullscreen;
2318 if (Browser.lockPointer) canvas.requestPointerLock();
2319 Browser.isFullscreen = true;
2320 if (Browser.resizeCanvas) {
2321 Browser.setFullscreenCanvasSize();
2322 } else {
2323 Browser.updateCanvasDimensions(canvas);
2324 }
2325 } else {
2326 // remove the full screen specific parent of the canvas again to restore the HTML structure from before going full screen
2327 canvasContainer.parentNode.insertBefore(canvas, canvasContainer);
2328 canvasContainer.parentNode.removeChild(canvasContainer);
2329
2330 if (Browser.resizeCanvas) {
2331 Browser.setWindowedCanvasSize();
2332 } else {
2333 Browser.updateCanvasDimensions(canvas);
2334 }
2335 }
2336 if (Module['onFullScreen']) Module['onFullScreen'](Browser.isFullscreen);
2337 if (Module['onFullscreen']) Module['onFullscreen'](Browser.isFullscreen);
2338 }
2339
2340 if (!Browser.fullscreenHandlersInstalled) {
2341 Browser.fullscreenHandlersInstalled = true;
2342 document.addEventListener('fullscreenchange', fullscreenChange, false);
2343 document.addEventListener('mozfullscreenchange', fullscreenChange, false);
2344 document.addEventListener('webkitfullscreenchange', fullscreenChange, false);
2345 document.addEventListener('MSFullscreenChange', fullscreenChange, false);
2346 }
2347
2348 // create a new parent to ensure the canvas has no siblings. this allows browsers to optimize full screen performance when its parent is the full screen root
2349 var canvasContainer = document.createElement("div");
2350 canvas.parentNode.insertBefore(canvasContainer, canvas);
2351 canvasContainer.appendChild(canvas);
2352
2353 // use parent of canvas as full screen root to allow aspect ratio correction (Firefox stretches the root to screen size)
2354 canvasContainer.requestFullscreen = canvasContainer['requestFullscreen'] ||
2355 canvasContainer['mozRequestFullScreen'] ||
2356 canvasContainer['msRequestFullscreen'] ||
2357 (canvasContainer['webkitRequestFullscreen'] ? function() { canvasContainer['webkitRequestFullscreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null) ||
2358 (canvasContainer['webkitRequestFullScreen'] ? function() { canvasContainer['webkitRequestFullScreen'](Element['ALLOW_KEYBOARD_INPUT']) } : null);
2359
2360 canvasContainer.requestFullscreen();
2361 },requestFullScreen:function() {
2362 abort('Module.requestFullScreen has been replaced by Module.requestFullscreen (without a capital S)');
2363 },exitFullscreen:function() {
2364 // This is workaround for chrome. Trying to exit from fullscreen
2365 // not in fullscreen state will cause "TypeError: Document not active"
2366 // in chrome. See https://github.com/emscripten-core/emscripten/pull/8236
2367 if (!Browser.isFullscreen) {
2368 return false;
2369 }
2370
2371 var CFS = document['exitFullscreen'] ||
2372 document['cancelFullScreen'] ||
2373 document['mozCancelFullScreen'] ||
2374 document['msExitFullscreen'] ||
2375 document['webkitCancelFullScreen'] ||
2376 (function() {});
2377 CFS.apply(document, []);
2378 return true;
2379 },nextRAF:0,fakeRequestAnimationFrame:function(func) {
2380 // try to keep 60fps between calls to here
2381 var now = Date.now();
2382 if (Browser.nextRAF === 0) {
2383 Browser.nextRAF = now + 1000/60;
2384 } else {
2385 while (now + 2 >= Browser.nextRAF) { // fudge a little, to avoid timer jitter causing us to do lots of delay:0
2386 Browser.nextRAF += 1000/60;
2387 }
2388 }
2389 var delay = Math.max(Browser.nextRAF - now, 0);
2390 setTimeout(func, delay);
2391 },requestAnimationFrame:function(func) {
2392 if (typeof requestAnimationFrame === 'function') {
2393 requestAnimationFrame(func);
2394 return;
2395 }
2396 var RAF = Browser.fakeRequestAnimationFrame;
2397 RAF(func);
2398 },safeCallback:function(func) {
2399 return function() {
2400 if (!ABORT) return func.apply(null, arguments);
2401 };
2402 },allowAsyncCallbacks:true,queuedAsyncCallbacks:[],pauseAsyncCallbacks:function() {
2403 Browser.allowAsyncCallbacks = false;
2404 },resumeAsyncCallbacks:function() { // marks future callbacks as ok to execute, and synchronously runs any remaining ones right now
2405 Browser.allowAsyncCallbacks = true;
2406 if (Browser.queuedAsyncCallbacks.length > 0) {
2407 var callbacks = Browser.queuedAsyncCallbacks;
2408 Browser.queuedAsyncCallbacks = [];
2409 callbacks.forEach(function(func) {
2410 func();
2411 });
2412 }
2413 },safeRequestAnimationFrame:function(func) {
2414 return Browser.requestAnimationFrame(function() {
2415 if (ABORT) return;
2416 if (Browser.allowAsyncCallbacks) {
2417 func();
2418 } else {
2419 Browser.queuedAsyncCallbacks.push(func);
2420 }
2421 });
2422 },safeSetTimeout:function(func, timeout) {
2423 noExitRuntime = true;
2424 return setTimeout(function() {
2425 if (ABORT) return;
2426 if (Browser.allowAsyncCallbacks) {
2427 func();
2428 } else {
2429 Browser.queuedAsyncCallbacks.push(func);
2430 }
2431 }, timeout);
2432 },safeSetInterval:function(func, timeout) {
2433 noExitRuntime = true;
2434 return setInterval(function() {
2435 if (ABORT) return;
2436 if (Browser.allowAsyncCallbacks) {
2437 func();
2438 } // drop it on the floor otherwise, next interval will kick in
2439 }, timeout);
2440 },getMimetype:function(name) {
2441 return {
2442 'jpg': 'image/jpeg',
2443 'jpeg': 'image/jpeg',
2444 'png': 'image/png',
2445 'bmp': 'image/bmp',
2446 'ogg': 'audio/ogg',
2447 'wav': 'audio/wav',
2448 'mp3': 'audio/mpeg'
2449 }[name.substr(name.lastIndexOf('.')+1)];
2450 },getUserMedia:function(func) {
2451 if(!window.getUserMedia) {
2452 window.getUserMedia = navigator['getUserMedia'] ||
2453 navigator['mozGetUserMedia'];
2454 }
2455 window.getUserMedia(func);
2456 },getMovementX:function(event) {
2457 return event['movementX'] ||
2458 event['mozMovementX'] ||
2459 event['webkitMovementX'] ||
2460 0;
2461 },getMovementY:function(event) {
2462 return event['movementY'] ||
2463 event['mozMovementY'] ||
2464 event['webkitMovementY'] ||
2465 0;
2466 },getMouseWheelDelta:function(event) {
2467 var delta = 0;
2468 switch (event.type) {
2469 case 'DOMMouseScroll':
2470 // 3 lines make up a step
2471 delta = event.detail / 3;
2472 break;
2473 case 'mousewheel':
2474 // 120 units make up a step
2475 delta = event.wheelDelta / 120;
2476 break;
2477 case 'wheel':
2478 delta = event.deltaY
2479 switch(event.deltaMode) {
2480 case 0:
2481 // DOM_DELTA_PIXEL: 100 pixels make up a step
2482 delta /= 100;
2483 break;
2484 case 1:
2485 // DOM_DELTA_LINE: 3 lines make up a step
2486 delta /= 3;
2487 break;
2488 case 2:
2489 // DOM_DELTA_PAGE: A page makes up 80 steps
2490 delta *= 80;
2491 break;
2492 default:
2493 throw 'unrecognized mouse wheel delta mode: ' + event.deltaMode;
2494 }
2495 break;
2496 default:
2497 throw 'unrecognized mouse wheel event: ' + event.type;
2498 }
2499 return delta;
2500 },mouseX:0,mouseY:0,mouseMovementX:0,mouseMovementY:0,touches:{},lastTouches:{},calculateMouseEvent:function(event) { // event should be mousemove, mousedown or mouseup
2501 if (Browser.pointerLock) {
2502 // When the pointer is locked, calculate the coordinates
2503 // based on the movement of the mouse.
2504 // Workaround for Firefox bug 764498
2505 if (event.type != 'mousemove' &&
2506 ('mozMovementX' in event)) {
2507 Browser.mouseMovementX = Browser.mouseMovementY = 0;
2508 } else {
2509 Browser.mouseMovementX = Browser.getMovementX(event);
2510 Browser.mouseMovementY = Browser.getMovementY(event);
2511 }
2512
2513 // check if SDL is available
2514 if (typeof SDL != "undefined") {
2515 Browser.mouseX = SDL.mouseX + Browser.mouseMovementX;
2516 Browser.mouseY = SDL.mouseY + Browser.mouseMovementY;
2517 } else {
2518 // just add the mouse delta to the current absolut mouse position
2519 // FIXME: ideally this should be clamped against the canvas size and zero
2520 Browser.mouseX += Browser.mouseMovementX;
2521 Browser.mouseY += Browser.mouseMovementY;
2522 }
2523 } else {
2524 // Otherwise, calculate the movement based on the changes
2525 // in the coordinates.
2526 var rect = Module["canvas"].getBoundingClientRect();
2527 var cw = Module["canvas"].width;
2528 var ch = Module["canvas"].height;
2529
2530 // Neither .scrollX or .pageXOffset are defined in a spec, but
2531 // we prefer .scrollX because it is currently in a spec draft.
2532 // (see: http://www.w3.org/TR/2013/WD-cssom-view-20131217/)
2533 var scrollX = ((typeof window.scrollX !== 'undefined') ? window.scrollX : window.pageXOffset);
2534 var scrollY = ((typeof window.scrollY !== 'undefined') ? window.scrollY : window.pageYOffset);
2535 // If this assert lands, it's likely because the browser doesn't support scrollX or pageXOffset
2536 // and we have no viable fallback.
2537 assert((typeof scrollX !== 'undefined') && (typeof scrollY !== 'undefined'), 'Unable to retrieve scroll position, mouse positions likely broken.');
2538
2539 if (event.type === 'touchstart' || event.type === 'touchend' || event.type === 'touchmove') {
2540 var touch = event.touch;
2541 if (touch === undefined) {
2542 return; // the "touch" property is only defined in SDL
2543
2544 }
2545 var adjustedX = touch.pageX - (scrollX + rect.left);
2546 var adjustedY = touch.pageY - (scrollY + rect.top);
2547
2548 adjustedX = adjustedX * (cw / rect.width);
2549 adjustedY = adjustedY * (ch / rect.height);
2550
2551 var coords = { x: adjustedX, y: adjustedY };
2552
2553 if (event.type === 'touchstart') {
2554 Browser.lastTouches[touch.identifier] = coords;
2555 Browser.touches[touch.identifier] = coords;
2556 } else if (event.type === 'touchend' || event.type === 'touchmove') {
2557 var last = Browser.touches[touch.identifier];
2558 if (!last) last = coords;
2559 Browser.lastTouches[touch.identifier] = last;
2560 Browser.touches[touch.identifier] = coords;
2561 }
2562 return;
2563 }
2564
2565 var x = event.pageX - (scrollX + rect.left);
2566 var y = event.pageY - (scrollY + rect.top);
2567
2568 // the canvas might be CSS-scaled compared to its backbuffer;
2569 // SDL-using content will want mouse coordinates in terms
2570 // of backbuffer units.
2571 x = x * (cw / rect.width);
2572 y = y * (ch / rect.height);
2573
2574 Browser.mouseMovementX = x - Browser.mouseX;
2575 Browser.mouseMovementY = y - Browser.mouseY;
2576 Browser.mouseX = x;
2577 Browser.mouseY = y;
2578 }
2579 },asyncLoad:function(url, onload, onerror, noRunDep) {
2580 var dep = !noRunDep ? getUniqueRunDependency('al ' + url) : '';
2581 readAsync(url, function(arrayBuffer) {
2582 assert(arrayBuffer, 'Loading data file "' + url + '" failed (no arrayBuffer).');
2583 onload(new Uint8Array(arrayBuffer));
2584 if (dep) removeRunDependency(dep);
2585 }, function(event) {
2586 if (onerror) {
2587 onerror();
2588 } else {
2589 throw 'Loading data file "' + url + '" failed.';
2590 }
2591 });
2592 if (dep) addRunDependency(dep);
2593 },resizeListeners:[],updateResizeListeners:function() {
2594 var canvas = Module['canvas'];
2595 Browser.resizeListeners.forEach(function(listener) {
2596 listener(canvas.width, canvas.height);
2597 });
2598 },setCanvasSize:function(width, height, noUpdates) {
2599 var canvas = Module['canvas'];
2600 Browser.updateCanvasDimensions(canvas, width, height);
2601 if (!noUpdates) Browser.updateResizeListeners();
2602 },windowedWidth:0,windowedHeight:0,setFullscreenCanvasSize:function() {
2603 // check if SDL is available
2604 if (typeof SDL != "undefined") {
2605 var flags = HEAPU32[((SDL.screen)>>2)];
2606 flags = flags | 0x00800000; // set SDL_FULLSCREEN flag
2607 HEAP32[((SDL.screen)>>2)]=flags
2608 }
2609 Browser.updateCanvasDimensions(Module['canvas']);
2610 Browser.updateResizeListeners();
2611 },setWindowedCanvasSize:function() {
2612 // check if SDL is available
2613 if (typeof SDL != "undefined") {
2614 var flags = HEAPU32[((SDL.screen)>>2)];
2615 flags = flags & ~0x00800000; // clear SDL_FULLSCREEN flag
2616 HEAP32[((SDL.screen)>>2)]=flags
2617 }
2618 Browser.updateCanvasDimensions(Module['canvas']);
2619 Browser.updateResizeListeners();
2620 },updateCanvasDimensions:function(canvas, wNative, hNative) {
2621 if (wNative && hNative) {
2622 canvas.widthNative = wNative;
2623 canvas.heightNative = hNative;
2624 } else {
2625 wNative = canvas.widthNative;
2626 hNative = canvas.heightNative;
2627 }
2628 var w = wNative;
2629 var h = hNative;
2630 if (Module['forcedAspectRatio'] && Module['forcedAspectRatio'] > 0) {
2631 if (w/h < Module['forcedAspectRatio']) {
2632 w = Math.round(h * Module['forcedAspectRatio']);
2633 } else {
2634 h = Math.round(w / Module['forcedAspectRatio']);
2635 }
2636 }
2637 if (((document['fullscreenElement'] || document['mozFullScreenElement'] ||
2638 document['msFullscreenElement'] || document['webkitFullscreenElement'] ||
2639 document['webkitCurrentFullScreenElement']) === canvas.parentNode) && (typeof screen != 'undefined')) {
2640 var factor = Math.min(screen.width / w, screen.height / h);
2641 w = Math.round(w * factor);
2642 h = Math.round(h * factor);
2643 }
2644 if (Browser.resizeCanvas) {
2645 if (canvas.width != w) canvas.width = w;
2646 if (canvas.height != h) canvas.height = h;
2647 if (typeof canvas.style != 'undefined') {
2648 canvas.style.removeProperty( "width");
2649 canvas.style.removeProperty("height");
2650 }
2651 } else {
2652 if (canvas.width != wNative) canvas.width = wNative;
2653 if (canvas.height != hNative) canvas.height = hNative;
2654 if (typeof canvas.style != 'undefined') {
2655 if (w != wNative || h != hNative) {
2656 canvas.style.setProperty( "width", w + "px", "important");
2657 canvas.style.setProperty("height", h + "px", "important");
2658 } else {
2659 canvas.style.removeProperty( "width");
2660 canvas.style.removeProperty("height");
2661 }
2662 }
2663 }
2664 },wgetRequests:{},nextWgetRequestHandle:0,getNextWgetRequestHandle:function() {
2665 var handle = Browser.nextWgetRequestHandle;
2666 Browser.nextWgetRequestHandle++;
2667 return handle;
2668 }};
2669
2670 function abortStackOverflow(allocSize) {
2671 abort('Stack overflow! Attempted to allocate ' + allocSize + ' bytes on the stack, but stack has only ' + (STACK_MAX - stackSave() + allocSize) + ' bytes available!');
2672 }
2673
2674 function demangle(func) {
2675 warnOnce('warning: build with -s DEMANGLE_SUPPORT=1 to link in libcxxabi demangling');
2676 return func;
2677 }
2678
2679 function demangleAll(text) {
2680 var regex =
2681 /\b_Z[\w\d_]+/g;
2682 return text.replace(regex,
2683 function(x) {
2684 var y = demangle(x);
2685 return x === y ? x : (y + ' [' + x + ']');
2686 });
2687 }
2688
2689 function jsStackTrace() {
2690 var err = new Error();
2691 if (!err.stack) {
2692 // IE10+ special cases: It does have callstack info, but it is only populated if an Error object is thrown,
2693 // so try that as a special-case.
2694 try {
2695 throw new Error();
2696 } catch(e) {
2697 err = e;
2698 }
2699 if (!err.stack) {
2700 return '(no stack trace available)';
2701 }
2702 }
2703 return err.stack.toString();
2704 }
2705
2706 function stackTrace() {
2707 var js = jsStackTrace();
2708 if (Module['extraStackTrace']) js += '\n' + Module['extraStackTrace']();
2709 return demangleAll(js);
2710 }
2711
2712 function ___handle_stack_overflow() {
2713 abort('stack overflow')
2714 }
2715
2716
2717 function setErrNo(value) {
2718 HEAP32[((___errno_location())>>2)]=value;
2719 return value;
2720 }
2721
2722
2723 var PATH={splitPath:function(filename) {
2724 var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
2725 return splitPathRe.exec(filename).slice(1);
2726 },normalizeArray:function(parts, allowAboveRoot) {
2727 // if the path tries to go above the root, `up` ends up > 0
2728 var up = 0;
2729 for (var i = parts.length - 1; i >= 0; i--) {
2730 var last = parts[i];
2731 if (last === '.') {
2732 parts.splice(i, 1);
2733 } else if (last === '..') {
2734 parts.splice(i, 1);
2735 up++;
2736 } else if (up) {
2737 parts.splice(i, 1);
2738 up--;
2739 }
2740 }
2741 // if the path is allowed to go above the root, restore leading ..s
2742 if (allowAboveRoot) {
2743 for (; up; up--) {
2744 parts.unshift('..');
2745 }
2746 }
2747 return parts;
2748 },normalize:function(path) {
2749 var isAbsolute = path.charAt(0) === '/',
2750 trailingSlash = path.substr(-1) === '/';
2751 // Normalize the path
2752 path = PATH.normalizeArray(path.split('/').filter(function(p) {
2753 return !!p;
2754 }), !isAbsolute).join('/');
2755 if (!path && !isAbsolute) {
2756 path = '.';
2757 }
2758 if (path && trailingSlash) {
2759 path += '/';
2760 }
2761 return (isAbsolute ? '/' : '') + path;
2762 },dirname:function(path) {
2763 var result = PATH.splitPath(path),
2764 root = result[0],
2765 dir = result[1];
2766 if (!root && !dir) {
2767 // No dirname whatsoever
2768 return '.';
2769 }
2770 if (dir) {
2771 // It has a dirname, strip trailing slash
2772 dir = dir.substr(0, dir.length - 1);
2773 }
2774 return root + dir;
2775 },basename:function(path) {
2776 // EMSCRIPTEN return '/'' for '/', not an empty string
2777 if (path === '/') return '/';
2778 var lastSlash = path.lastIndexOf('/');
2779 if (lastSlash === -1) return path;
2780 return path.substr(lastSlash+1);
2781 },extname:function(path) {
2782 return PATH.splitPath(path)[3];
2783 },join:function() {
2784 var paths = Array.prototype.slice.call(arguments, 0);
2785 return PATH.normalize(paths.join('/'));
2786 },join2:function(l, r) {
2787 return PATH.normalize(l + '/' + r);
2788 }};
2789
2790
2791 var PATH_FS={resolve:function() {
2792 var resolvedPath = '',
2793 resolvedAbsolute = false;
2794 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
2795 var path = (i >= 0) ? arguments[i] : FS.cwd();
2796 // Skip empty and invalid entries
2797 if (typeof path !== 'string') {
2798 throw new TypeError('Arguments to path.resolve must be strings');
2799 } else if (!path) {
2800 return ''; // an invalid portion invalidates the whole thing
2801 }
2802 resolvedPath = path + '/' + resolvedPath;
2803 resolvedAbsolute = path.charAt(0) === '/';
2804 }
2805 // At this point the path should be resolved to a full absolute path, but
2806 // handle relative paths to be safe (might happen when process.cwd() fails)
2807 resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
2808 return !!p;
2809 }), !resolvedAbsolute).join('/');
2810 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
2811 },relative:function(from, to) {
2812 from = PATH_FS.resolve(from).substr(1);
2813 to = PATH_FS.resolve(to).substr(1);
2814 function trim(arr) {
2815 var start = 0;
2816 for (; start < arr.length; start++) {
2817 if (arr[start] !== '') break;
2818 }
2819 var end = arr.length - 1;
2820 for (; end >= 0; end--) {
2821 if (arr[end] !== '') break;
2822 }
2823 if (start > end) return [];
2824 return arr.slice(start, end - start + 1);
2825 }
2826 var fromParts = trim(from.split('/'));
2827 var toParts = trim(to.split('/'));
2828 var length = Math.min(fromParts.length, toParts.length);
2829 var samePartsLength = length;
2830 for (var i = 0; i < length; i++) {
2831 if (fromParts[i] !== toParts[i]) {
2832 samePartsLength = i;
2833 break;
2834 }
2835 }
2836 var outputParts = [];
2837 for (var i = samePartsLength; i < fromParts.length; i++) {
2838 outputParts.push('..');
2839 }
2840 outputParts = outputParts.concat(toParts.slice(samePartsLength));
2841 return outputParts.join('/');
2842 }};
2843
2844 var TTY={ttys:[],init:function () {
2845 // https://github.com/emscripten-core/emscripten/pull/1555
2846 // if (ENVIRONMENT_IS_NODE) {
2847 // // currently, FS.init does not distinguish if process.stdin is a file or TTY
2848 // // device, it always assumes it's a TTY device. because of this, we're forcing
2849 // // process.stdin to UTF8 encoding to at least make stdin reading compatible
2850 // // with text files until FS.init can be refactored.
2851 // process['stdin']['setEncoding']('utf8');
2852 // }
2853 },shutdown:function() {
2854 // https://github.com/emscripten-core/emscripten/pull/1555
2855 // if (ENVIRONMENT_IS_NODE) {
2856 // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
2857 // // 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
2858 // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
2859 // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
2860 // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
2861 // process['stdin']['pause']();
2862 // }
2863 },register:function(dev, ops) {
2864 TTY.ttys[dev] = { input: [], output: [], ops: ops };
2865 FS.registerDevice(dev, TTY.stream_ops);
2866 },stream_ops:{open:function(stream) {
2867 var tty = TTY.ttys[stream.node.rdev];
2868 if (!tty) {
2869 throw new FS.ErrnoError(43);
2870 }
2871 stream.tty = tty;
2872 stream.seekable = false;
2873 },close:function(stream) {
2874 // flush any pending line data
2875 stream.tty.ops.flush(stream.tty);
2876 },flush:function(stream) {
2877 stream.tty.ops.flush(stream.tty);
2878 },read:function(stream, buffer, offset, length, pos /* ignored */) {
2879 if (!stream.tty || !stream.tty.ops.get_char) {
2880 throw new FS.ErrnoError(60);
2881 }
2882 var bytesRead = 0;
2883 for (var i = 0; i < length; i++) {
2884 var result;
2885 try {
2886 result = stream.tty.ops.get_char(stream.tty);
2887 } catch (e) {
2888 throw new FS.ErrnoError(29);
2889 }
2890 if (result === undefined && bytesRead === 0) {
2891 throw new FS.ErrnoError(6);
2892 }
2893 if (result === null || result === undefined) break;
2894 bytesRead++;
2895 buffer[offset+i] = result;
2896 }
2897 if (bytesRead) {
2898 stream.node.timestamp = Date.now();
2899 }
2900 return bytesRead;
2901 },write:function(stream, buffer, offset, length, pos) {
2902 if (!stream.tty || !stream.tty.ops.put_char) {
2903 throw new FS.ErrnoError(60);
2904 }
2905 try {
2906 for (var i = 0; i < length; i++) {
2907 stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
2908 }
2909 } catch (e) {
2910 throw new FS.ErrnoError(29);
2911 }
2912 if (length) {
2913 stream.node.timestamp = Date.now();
2914 }
2915 return i;
2916 }},default_tty_ops:{get_char:function(tty) {
2917 if (!tty.input.length) {
2918 var result = null;
2919 if (ENVIRONMENT_IS_NODE) {
2920 // we will read data by chunks of BUFSIZE
2921 var BUFSIZE = 256;
2922 var buf = Buffer.alloc ? Buffer.alloc(BUFSIZE) : new Buffer(BUFSIZE);
2923 var bytesRead = 0;
2924
2925 try {
2926 bytesRead = nodeFS.readSync(process.stdin.fd, buf, 0, BUFSIZE, null);
2927 } catch(e) {
2928 // Cross-platform differences: on Windows, reading EOF throws an exception, but on other OSes,
2929 // reading EOF returns 0. Uniformize behavior by treating the EOF exception to return 0.
2930 if (e.toString().indexOf('EOF') != -1) bytesRead = 0;
2931 else throw e;
2932 }
2933
2934 if (bytesRead > 0) {
2935 result = buf.slice(0, bytesRead).toString('utf-8');
2936 } else {
2937 result = null;
2938 }
2939 } else
2940 if (typeof window != 'undefined' &&
2941 typeof window.prompt == 'function') {
2942 // Browser.
2943 result = window.prompt('Input: '); // returns null on cancel
2944 if (result !== null) {
2945 result += '\n';
2946 }
2947 } else if (typeof readline == 'function') {
2948 // Command line.
2949 result = readline();
2950 if (result !== null) {
2951 result += '\n';
2952 }
2953 }
2954 if (!result) {
2955 return null;
2956 }
2957 tty.input = intArrayFromString(result, true);
2958 }
2959 return tty.input.shift();
2960 },put_char:function(tty, val) {
2961 if (val === null || val === 10) {
2962 out(UTF8ArrayToString(tty.output, 0));
2963 tty.output = [];
2964 } else {
2965 if (val != 0) tty.output.push(val); // val == 0 would cut text output off in the middle.
2966 }
2967 },flush:function(tty) {
2968 if (tty.output && tty.output.length > 0) {
2969 out(UTF8ArrayToString(tty.output, 0));
2970 tty.output = [];
2971 }
2972 }},default_tty1_ops:{put_char:function(tty, val) {
2973 if (val === null || val === 10) {
2974 err(UTF8ArrayToString(tty.output, 0));
2975 tty.output = [];
2976 } else {
2977 if (val != 0) tty.output.push(val);
2978 }
2979 },flush:function(tty) {
2980 if (tty.output && tty.output.length > 0) {
2981 err(UTF8ArrayToString(tty.output, 0));
2982 tty.output = [];
2983 }
2984 }}};
2985
2986 var MEMFS={ops_table:null,mount:function(mount) {
2987 return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
2988 },createNode:function(parent, name, mode, dev) {
2989 if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
2990 // no supported
2991 throw new FS.ErrnoError(63);
2992 }
2993 if (!MEMFS.ops_table) {
2994 MEMFS.ops_table = {
2995 dir: {
2996 node: {
2997 getattr: MEMFS.node_ops.getattr,
2998 setattr: MEMFS.node_ops.setattr,
2999 lookup: MEMFS.node_ops.lookup,
3000 mknod: MEMFS.node_ops.mknod,
3001 rename: MEMFS.node_ops.rename,
3002 unlink: MEMFS.node_ops.unlink,
3003 rmdir: MEMFS.node_ops.rmdir,
3004 readdir: MEMFS.node_ops.readdir,
3005 symlink: MEMFS.node_ops.symlink
3006 },
3007 stream: {
3008 llseek: MEMFS.stream_ops.llseek
3009 }
3010 },
3011 file: {
3012 node: {
3013 getattr: MEMFS.node_ops.getattr,
3014 setattr: MEMFS.node_ops.setattr
3015 },
3016 stream: {
3017 llseek: MEMFS.stream_ops.llseek,
3018 read: MEMFS.stream_ops.read,
3019 write: MEMFS.stream_ops.write,
3020 allocate: MEMFS.stream_ops.allocate,
3021 mmap: MEMFS.stream_ops.mmap,
3022 msync: MEMFS.stream_ops.msync
3023 }
3024 },
3025 link: {
3026 node: {
3027 getattr: MEMFS.node_ops.getattr,
3028 setattr: MEMFS.node_ops.setattr,
3029 readlink: MEMFS.node_ops.readlink
3030 },
3031 stream: {}
3032 },
3033 chrdev: {
3034 node: {
3035 getattr: MEMFS.node_ops.getattr,
3036 setattr: MEMFS.node_ops.setattr
3037 },
3038 stream: FS.chrdev_stream_ops
3039 }
3040 };
3041 }
3042 var node = FS.createNode(parent, name, mode, dev);
3043 if (FS.isDir(node.mode)) {
3044 node.node_ops = MEMFS.ops_table.dir.node;
3045 node.stream_ops = MEMFS.ops_table.dir.stream;
3046 node.contents = {};
3047 } else if (FS.isFile(node.mode)) {
3048 node.node_ops = MEMFS.ops_table.file.node;
3049 node.stream_ops = MEMFS.ops_table.file.stream;
3050 node.usedBytes = 0; // The actual number of bytes used in the typed array, as opposed to contents.length which gives the whole capacity.
3051 // 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
3052 // for performance, and used by default. However, typed arrays are not resizable like normal JS arrays are, so there is a small disk size
3053 // penalty involved for appending file writes that continuously grow a file similar to std::vector capacity vs used -scheme.
3054 node.contents = null;
3055 } else if (FS.isLink(node.mode)) {
3056 node.node_ops = MEMFS.ops_table.link.node;
3057 node.stream_ops = MEMFS.ops_table.link.stream;
3058 } else if (FS.isChrdev(node.mode)) {
3059 node.node_ops = MEMFS.ops_table.chrdev.node;
3060 node.stream_ops = MEMFS.ops_table.chrdev.stream;
3061 }
3062 node.timestamp = Date.now();
3063 // add the new node to the parent
3064 if (parent) {
3065 parent.contents[name] = node;
3066 }
3067 return node;
3068 },getFileDataAsRegularArray:function(node) {
3069 if (node.contents && node.contents.subarray) {
3070 var arr = [];
3071 for (var i = 0; i < node.usedBytes; ++i) arr.push(node.contents[i]);
3072 return arr; // Returns a copy of the original data.
3073 }
3074 return node.contents; // No-op, the file contents are already in a JS array. Return as-is.
3075 },getFileDataAsTypedArray:function(node) {
3076 if (!node.contents) return new Uint8Array(0);
3077 if (node.contents.subarray) return node.contents.subarray(0, node.usedBytes); // Make sure to not return excess unused bytes.
3078 return new Uint8Array(node.contents);
3079 },expandFileStorage:function(node, newCapacity) {
3080 var prevCapacity = node.contents ? node.contents.length : 0;
3081 if (prevCapacity >= newCapacity) return; // No need to expand, the storage was already large enough.
3082 // Don't expand strictly to the given requested limit if it's only a very small increase, but instead geometrically grow capacity.
3083 // For small filesizes (<1MB), perform size*2 geometric increase, but for large sizes, do a much more conservative size*1.125 increase to
3084 // avoid overshooting the allocation cap by a very large margin.
3085 var CAPACITY_DOUBLING_MAX = 1024 * 1024;
3086 newCapacity = Math.max(newCapacity, (prevCapacity * (prevCapacity < CAPACITY_DOUBLING_MAX ? 2.0 : 1.125)) >>> 0);
3087 if (prevCapacity != 0) newCapacity = Math.max(newCapacity, 256); // At minimum allocate 256b for each file when expanding.
3088 var oldContents = node.contents;
3089 node.contents = new Uint8Array(newCapacity); // Allocate new storage.
3090 if (node.usedBytes > 0) node.contents.set(oldContents.subarray(0, node.usedBytes), 0); // Copy old data over to the new storage.
3091 return;
3092 },resizeFileStorage:function(node, newSize) {
3093 if (node.usedBytes == newSize) return;
3094 if (newSize == 0) {
3095 node.contents = null; // Fully decommit when requesting a resize to zero.
3096 node.usedBytes = 0;
3097 return;
3098 }
3099 if (!node.contents || node.contents.subarray) { // Resize a typed array if that is being used as the backing store.
3100 var oldContents = node.contents;
3101 node.contents = new Uint8Array(newSize); // Allocate new storage.
3102 if (oldContents) {
3103 node.contents.set(oldContents.subarray(0, Math.min(newSize, node.usedBytes))); // Copy old data over to the new storage.
3104 }
3105 node.usedBytes = newSize;
3106 return;
3107 }
3108 // Backing with a JS array.
3109 if (!node.contents) node.contents = [];
3110 if (node.contents.length > newSize) node.contents.length = newSize;
3111 else while (node.contents.length < newSize) node.contents.push(0);
3112 node.usedBytes = newSize;
3113 },node_ops:{getattr:function(node) {
3114 var attr = {};
3115 // device numbers reuse inode numbers.
3116 attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
3117 attr.ino = node.id;
3118 attr.mode = node.mode;
3119 attr.nlink = 1;
3120 attr.uid = 0;
3121 attr.gid = 0;
3122 attr.rdev = node.rdev;
3123 if (FS.isDir(node.mode)) {
3124 attr.size = 4096;
3125 } else if (FS.isFile(node.mode)) {
3126 attr.size = node.usedBytes;
3127 } else if (FS.isLink(node.mode)) {
3128 attr.size = node.link.length;
3129 } else {
3130 attr.size = 0;
3131 }
3132 attr.atime = new Date(node.timestamp);
3133 attr.mtime = new Date(node.timestamp);
3134 attr.ctime = new Date(node.timestamp);
3135 // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
3136 // but this is not required by the standard.
3137 attr.blksize = 4096;
3138 attr.blocks = Math.ceil(attr.size / attr.blksize);
3139 return attr;
3140 },setattr:function(node, attr) {
3141 if (attr.mode !== undefined) {
3142 node.mode = attr.mode;
3143 }
3144 if (attr.timestamp !== undefined) {
3145 node.timestamp = attr.timestamp;
3146 }
3147 if (attr.size !== undefined) {
3148 MEMFS.resizeFileStorage(node, attr.size);
3149 }
3150 },lookup:function(parent, name) {
3151 throw FS.genericErrors[44];
3152 },mknod:function(parent, name, mode, dev) {
3153 return MEMFS.createNode(parent, name, mode, dev);
3154 },rename:function(old_node, new_dir, new_name) {
3155 // if we're overwriting a directory at new_name, make sure it's empty.
3156 if (FS.isDir(old_node.mode)) {
3157 var new_node;
3158 try {
3159 new_node = FS.lookupNode(new_dir, new_name);
3160 } catch (e) {
3161 }
3162 if (new_node) {
3163 for (var i in new_node.contents) {
3164 throw new FS.ErrnoError(55);
3165 }
3166 }
3167 }
3168 // do the internal rewiring
3169 delete old_node.parent.contents[old_node.name];
3170 old_node.name = new_name;
3171 new_dir.contents[new_name] = old_node;
3172 old_node.parent = new_dir;
3173 },unlink:function(parent, name) {
3174 delete parent.contents[name];
3175 },rmdir:function(parent, name) {
3176 var node = FS.lookupNode(parent, name);
3177 for (var i in node.contents) {
3178 throw new FS.ErrnoError(55);
3179 }
3180 delete parent.contents[name];
3181 },readdir:function(node) {
3182 var entries = ['.', '..'];
3183 for (var key in node.contents) {
3184 if (!node.contents.hasOwnProperty(key)) {
3185 continue;
3186 }
3187 entries.push(key);
3188 }
3189 return entries;
3190 },symlink:function(parent, newname, oldpath) {
3191 var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
3192 node.link = oldpath;
3193 return node;
3194 },readlink:function(node) {
3195 if (!FS.isLink(node.mode)) {
3196 throw new FS.ErrnoError(28);
3197 }
3198 return node.link;
3199 }},stream_ops:{read:function(stream, buffer, offset, length, position) {
3200 var contents = stream.node.contents;
3201 if (position >= stream.node.usedBytes) return 0;
3202 var size = Math.min(stream.node.usedBytes - position, length);
3203 assert(size >= 0);
3204 if (size > 8 && contents.subarray) { // non-trivial, and typed array
3205 buffer.set(contents.subarray(position, position + size), offset);
3206 } else {
3207 for (var i = 0; i < size; i++) buffer[offset + i] = contents[position + i];
3208 }
3209 return size;
3210 },write:function(stream, buffer, offset, length, position, canOwn) {
3211 // The data buffer should be a typed array view
3212 assert(!(buffer instanceof ArrayBuffer));
3213
3214 if (!length) return 0;
3215 var node = stream.node;
3216 node.timestamp = Date.now();
3217
3218 if (buffer.subarray && (!node.contents || node.contents.subarray)) { // This write is from a typed array to a typed array?
3219 if (canOwn) {
3220 assert(position === 0, 'canOwn must imply no weird position inside the file');
3221 node.contents = buffer.subarray(offset, offset + length);
3222 node.usedBytes = length;
3223 return length;
3224 } 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.
3225 node.contents = buffer.slice(offset, offset + length);
3226 node.usedBytes = length;
3227 return length;
3228 } else if (position + length <= node.usedBytes) { // Writing to an already allocated and used subrange of the file?
3229 node.contents.set(buffer.subarray(offset, offset + length), position);
3230 return length;
3231 }
3232 }
3233
3234 // Appending to an existing file and we need to reallocate, or source data did not come as a typed array.
3235 MEMFS.expandFileStorage(node, position+length);
3236 if (node.contents.subarray && buffer.subarray) node.contents.set(buffer.subarray(offset, offset + length), position); // Use typed array write if available.
3237 else {
3238 for (var i = 0; i < length; i++) {
3239 node.contents[position + i] = buffer[offset + i]; // Or fall back to manual write if not.
3240 }
3241 }
3242 node.usedBytes = Math.max(node.usedBytes, position + length);
3243 return length;
3244 },llseek:function(stream, offset, whence) {
3245 var position = offset;
3246 if (whence === 1) {
3247 position += stream.position;
3248 } else if (whence === 2) {
3249 if (FS.isFile(stream.node.mode)) {
3250 position += stream.node.usedBytes;
3251 }
3252 }
3253 if (position < 0) {
3254 throw new FS.ErrnoError(28);
3255 }
3256 return position;
3257 },allocate:function(stream, offset, length) {
3258 MEMFS.expandFileStorage(stream.node, offset + length);
3259 stream.node.usedBytes = Math.max(stream.node.usedBytes, offset + length);
3260 },mmap:function(stream, address, length, position, prot, flags) {
3261 // We don't currently support location hints for the address of the mapping
3262 assert(address === 0);
3263
3264 if (!FS.isFile(stream.node.mode)) {
3265 throw new FS.ErrnoError(43);
3266 }
3267 var ptr;
3268 var allocated;
3269 var contents = stream.node.contents;
3270 // Only make a new copy when MAP_PRIVATE is specified.
3271 if (!(flags & 2) && contents.buffer === buffer) {
3272 // We can't emulate MAP_SHARED when the file is not backed by the buffer
3273 // we're mapping to (e.g. the HEAP buffer).
3274 allocated = false;
3275 ptr = contents.byteOffset;
3276 } else {
3277 // Try to avoid unnecessary slices.
3278 if (position > 0 || position + length < contents.length) {
3279 if (contents.subarray) {
3280 contents = contents.subarray(position, position + length);
3281 } else {
3282 contents = Array.prototype.slice.call(contents, position, position + length);
3283 }
3284 }
3285 allocated = true;
3286 ptr = _malloc(length);
3287 if (!ptr) {
3288 throw new FS.ErrnoError(48);
3289 }
3290 HEAP8.set(contents, ptr);
3291 }
3292 return { ptr: ptr, allocated: allocated };
3293 },msync:function(stream, buffer, offset, length, mmapFlags) {
3294 if (!FS.isFile(stream.node.mode)) {
3295 throw new FS.ErrnoError(43);
3296 }
3297 if (mmapFlags & 2) {
3298 // MAP_PRIVATE calls need not to be synced back to underlying fs
3299 return 0;
3300 }
3301
3302 var bytesWritten = MEMFS.stream_ops.write(stream, buffer, 0, length, offset, false);
3303 // should we check if bytesWritten and length are the same?
3304 return 0;
3305 }}};
3306
3307 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"};
3308
3309 var ERRNO_CODES={EPERM:63,ENOENT:44,ESRCH:71,EINTR:27,EIO:29,ENXIO:60,E2BIG:1,ENOEXEC:45,EBADF:8,ECHILD:12,EAGAIN:6,EWOULDBLOCK:6,ENOMEM:48,EACCES:2,EFAULT:21,ENOTBLK:105,EBUSY:10,EEXIST:20,EXDEV:75,ENODEV:43,ENOTDIR:54,EISDIR:31,EINVAL:28,ENFILE:41,EMFILE:33,ENOTTY:59,ETXTBSY:74,EFBIG:22,ENOSPC:51,ESPIPE:70,EROFS:69,EMLINK:34,EPIPE:64,EDOM:18,ERANGE:68,ENOMSG:49,EIDRM:24,ECHRNG:106,EL2NSYNC:156,EL3HLT:107,EL3RST:108,ELNRNG:109,EUNATCH:110,ENOCSI:111,EL2HLT:112,EDEADLK:16,ENOLCK:46,EBADE:113,EBADR:114,EXFULL:115,ENOANO:104,EBADRQC:103,EBADSLT:102,EDEADLOCK:16,EBFONT:101,ENOSTR:100,ENODATA:116,ETIME:117,ENOSR:118,ENONET:119,ENOPKG:120,EREMOTE:121,ENOLINK:47,EADV:122,ESRMNT:123,ECOMM:124,EPROTO:65,EMULTIHOP:36,EDOTDOT:125,EBADMSG:9,ENOTUNIQ:126,EBADFD:127,EREMCHG:128,ELIBACC:129,ELIBBAD:130,ELIBSCN:131,ELIBMAX:132,ELIBEXEC:133,ENOSYS:52,ENOTEMPTY:55,ENAMETOOLONG:37,ELOOP:32,EOPNOTSUPP:138,EPFNOSUPPORT:139,ECONNRESET:15,ENOBUFS:42,EAFNOSUPPORT:5,EPROTOTYPE:67,ENOTSOCK:57,ENOPROTOOPT:50,ESHUTDOWN:140,ECONNREFUSED:14,EADDRINUSE:3,ECONNABORTED:13,ENETUNREACH:40,ENETDOWN:38,ETIMEDOUT:73,EHOSTDOWN:142,EHOSTUNREACH:23,EINPROGRESS:26,EALREADY:7,EDESTADDRREQ:17,EMSGSIZE:35,EPROTONOSUPPORT:66,ESOCKTNOSUPPORT:137,EADDRNOTAVAIL:4,ENETRESET:39,EISCONN:30,ENOTCONN:53,ETOOMANYREFS:141,EUSERS:136,EDQUOT:19,ESTALE:72,ENOTSUP:138,ENOMEDIUM:148,EILSEQ:25,EOVERFLOW:61,ECANCELED:11,ENOTRECOVERABLE:56,EOWNERDEAD:62,ESTRPIPE:135};var FS={root:null,mounts:[],devices:{},streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,trackingDelegate:{},tracking:{openFlags:{READ:1,WRITE:2}},ErrnoError:null,genericErrors:{},filesystems:null,syncFSRequests:0,handleFSError:function(e) {
3310 if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
3311 return setErrNo(e.errno);
3312 },lookupPath:function(path, opts) {
3313 path = PATH_FS.resolve(FS.cwd(), path);
3314 opts = opts || {};
3315
3316 if (!path) return { path: '', node: null };
3317
3318 var defaults = {
3319 follow_mount: true,
3320 recurse_count: 0
3321 };
3322 for (var key in defaults) {
3323 if (opts[key] === undefined) {
3324 opts[key] = defaults[key];
3325 }
3326 }
3327
3328 if (opts.recurse_count > 8) { // max recursive lookup of 8
3329 throw new FS.ErrnoError(32);
3330 }
3331
3332 // split the path
3333 var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
3334 return !!p;
3335 }), false);
3336
3337 // start at the root
3338 var current = FS.root;
3339 var current_path = '/';
3340
3341 for (var i = 0; i < parts.length; i++) {
3342 var islast = (i === parts.length-1);
3343 if (islast && opts.parent) {
3344 // stop resolving
3345 break;
3346 }
3347
3348 current = FS.lookupNode(current, parts[i]);
3349 current_path = PATH.join2(current_path, parts[i]);
3350
3351 // jump to the mount's root node if this is a mountpoint
3352 if (FS.isMountpoint(current)) {
3353 if (!islast || (islast && opts.follow_mount)) {
3354 current = current.mounted.root;
3355 }
3356 }
3357
3358 // by default, lookupPath will not follow a symlink if it is the final path component.
3359 // setting opts.follow = true will override this behavior.
3360 if (!islast || opts.follow) {
3361 var count = 0;
3362 while (FS.isLink(current.mode)) {
3363 var link = FS.readlink(current_path);
3364 current_path = PATH_FS.resolve(PATH.dirname(current_path), link);
3365
3366 var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
3367 current = lookup.node;
3368
3369 if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
3370 throw new FS.ErrnoError(32);
3371 }
3372 }
3373 }
3374 }
3375
3376 return { path: current_path, node: current };
3377 },getPath:function(node) {
3378 var path;
3379 while (true) {
3380 if (FS.isRoot(node)) {
3381 var mount = node.mount.mountpoint;
3382 if (!path) return mount;
3383 return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
3384 }
3385 path = path ? node.name + '/' + path : node.name;
3386 node = node.parent;
3387 }
3388 },hashName:function(parentid, name) {
3389 var hash = 0;
3390
3391
3392 for (var i = 0; i < name.length; i++) {
3393 hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
3394 }
3395 return ((parentid + hash) >>> 0) % FS.nameTable.length;
3396 },hashAddNode:function(node) {
3397 var hash = FS.hashName(node.parent.id, node.name);
3398 node.name_next = FS.nameTable[hash];
3399 FS.nameTable[hash] = node;
3400 },hashRemoveNode:function(node) {
3401 var hash = FS.hashName(node.parent.id, node.name);
3402 if (FS.nameTable[hash] === node) {
3403 FS.nameTable[hash] = node.name_next;
3404 } else {
3405 var current = FS.nameTable[hash];
3406 while (current) {
3407 if (current.name_next === node) {
3408 current.name_next = node.name_next;
3409 break;
3410 }
3411 current = current.name_next;
3412 }
3413 }
3414 },lookupNode:function(parent, name) {
3415 var errCode = FS.mayLookup(parent);
3416 if (errCode) {
3417 throw new FS.ErrnoError(errCode, parent);
3418 }
3419 var hash = FS.hashName(parent.id, name);
3420 for (var node = FS.nameTable[hash]; node; node = node.name_next) {
3421 var nodeName = node.name;
3422 if (node.parent.id === parent.id && nodeName === name) {
3423 return node;
3424 }
3425 }
3426 // if we failed to find it in the cache, call into the VFS
3427 return FS.lookup(parent, name);
3428 },createNode:function(parent, name, mode, rdev) {
3429 var node = new FS.FSNode(parent, name, mode, rdev);
3430
3431 FS.hashAddNode(node);
3432
3433 return node;
3434 },destroyNode:function(node) {
3435 FS.hashRemoveNode(node);
3436 },isRoot:function(node) {
3437 return node === node.parent;
3438 },isMountpoint:function(node) {
3439 return !!node.mounted;
3440 },isFile:function(mode) {
3441 return (mode & 61440) === 32768;
3442 },isDir:function(mode) {
3443 return (mode & 61440) === 16384;
3444 },isLink:function(mode) {
3445 return (mode & 61440) === 40960;
3446 },isChrdev:function(mode) {
3447 return (mode & 61440) === 8192;
3448 },isBlkdev:function(mode) {
3449 return (mode & 61440) === 24576;
3450 },isFIFO:function(mode) {
3451 return (mode & 61440) === 4096;
3452 },isSocket:function(mode) {
3453 return (mode & 49152) === 49152;
3454 },flagModes:{"r":0,"rs":1052672,"r+":2,"w":577,"wx":705,"xw":705,"w+":578,"wx+":706,"xw+":706,"a":1089,"ax":1217,"xa":1217,"a+":1090,"ax+":1218,"xa+":1218},modeStringToFlags:function(str) {
3455 var flags = FS.flagModes[str];
3456 if (typeof flags === 'undefined') {
3457 throw new Error('Unknown file open mode: ' + str);
3458 }
3459 return flags;
3460 },flagsToPermissionString:function(flag) {
3461 var perms = ['r', 'w', 'rw'][flag & 3];
3462 if ((flag & 512)) {
3463 perms += 'w';
3464 }
3465 return perms;
3466 },nodePermissions:function(node, perms) {
3467 if (FS.ignorePermissions) {
3468 return 0;
3469 }
3470 // return 0 if any user, group or owner bits are set.
3471 if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
3472 return 2;
3473 } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
3474 return 2;
3475 } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
3476 return 2;
3477 }
3478 return 0;
3479 },mayLookup:function(dir) {
3480 var errCode = FS.nodePermissions(dir, 'x');
3481 if (errCode) return errCode;
3482 if (!dir.node_ops.lookup) return 2;
3483 return 0;
3484 },mayCreate:function(dir, name) {
3485 try {
3486 var node = FS.lookupNode(dir, name);
3487 return 20;
3488 } catch (e) {
3489 }
3490 return FS.nodePermissions(dir, 'wx');
3491 },mayDelete:function(dir, name, isdir) {
3492 var node;
3493 try {
3494 node = FS.lookupNode(dir, name);
3495 } catch (e) {
3496 return e.errno;
3497 }
3498 var errCode = FS.nodePermissions(dir, 'wx');
3499 if (errCode) {
3500 return errCode;
3501 }
3502 if (isdir) {
3503 if (!FS.isDir(node.mode)) {
3504 return 54;
3505 }
3506 if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
3507 return 10;
3508 }
3509 } else {
3510 if (FS.isDir(node.mode)) {
3511 return 31;
3512 }
3513 }
3514 return 0;
3515 },mayOpen:function(node, flags) {
3516 if (!node) {
3517 return 44;
3518 }
3519 if (FS.isLink(node.mode)) {
3520 return 32;
3521 } else if (FS.isDir(node.mode)) {
3522 if (FS.flagsToPermissionString(flags) !== 'r' || // opening for write
3523 (flags & 512)) { // TODO: check for O_SEARCH? (== search for dir only)
3524 return 31;
3525 }
3526 }
3527 return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
3528 },MAX_OPEN_FDS:4096,nextfd:function(fd_start, fd_end) {
3529 fd_start = fd_start || 0;
3530 fd_end = fd_end || FS.MAX_OPEN_FDS;
3531 for (var fd = fd_start; fd <= fd_end; fd++) {
3532 if (!FS.streams[fd]) {
3533 return fd;
3534 }
3535 }
3536 throw new FS.ErrnoError(33);
3537 },getStream:function(fd) {
3538 return FS.streams[fd];
3539 },createStream:function(stream, fd_start, fd_end) {
3540 if (!FS.FSStream) {
3541 FS.FSStream = /** @constructor */ function(){};
3542 FS.FSStream.prototype = {
3543 object: {
3544 get: function() { return this.node; },
3545 set: function(val) { this.node = val; }
3546 },
3547 isRead: {
3548 get: function() { return (this.flags & 2097155) !== 1; }
3549 },
3550 isWrite: {
3551 get: function() { return (this.flags & 2097155) !== 0; }
3552 },
3553 isAppend: {
3554 get: function() { return (this.flags & 1024); }
3555 }
3556 };
3557 }
3558 // clone it, so we can return an instance of FSStream
3559 var newStream = new FS.FSStream();
3560 for (var p in stream) {
3561 newStream[p] = stream[p];
3562 }
3563 stream = newStream;
3564 var fd = FS.nextfd(fd_start, fd_end);
3565 stream.fd = fd;
3566 FS.streams[fd] = stream;
3567 return stream;
3568 },closeStream:function(fd) {
3569 FS.streams[fd] = null;
3570 },chrdev_stream_ops:{open:function(stream) {
3571 var device = FS.getDevice(stream.node.rdev);
3572 // override node's stream ops with the device's
3573 stream.stream_ops = device.stream_ops;
3574 // forward the open call
3575 if (stream.stream_ops.open) {
3576 stream.stream_ops.open(stream);
3577 }
3578 },llseek:function() {
3579 throw new FS.ErrnoError(70);
3580 }},major:function(dev) {
3581 return ((dev) >> 8);
3582 },minor:function(dev) {
3583 return ((dev) & 0xff);
3584 },makedev:function(ma, mi) {
3585 return ((ma) << 8 | (mi));
3586 },registerDevice:function(dev, ops) {
3587 FS.devices[dev] = { stream_ops: ops };
3588 },getDevice:function(dev) {
3589 return FS.devices[dev];
3590 },getMounts:function(mount) {
3591 var mounts = [];
3592 var check = [mount];
3593
3594 while (check.length) {
3595 var m = check.pop();
3596
3597 mounts.push(m);
3598
3599 check.push.apply(check, m.mounts);
3600 }
3601
3602 return mounts;
3603 },syncfs:function(populate, callback) {
3604 if (typeof(populate) === 'function') {
3605 callback = populate;
3606 populate = false;
3607 }
3608
3609 FS.syncFSRequests++;
3610
3611 if (FS.syncFSRequests > 1) {
3612 err('warning: ' + FS.syncFSRequests + ' FS.syncfs operations in flight at once, probably just doing extra work');
3613 }
3614
3615 var mounts = FS.getMounts(FS.root.mount);
3616 var completed = 0;
3617
3618 function doCallback(errCode) {
3619 assert(FS.syncFSRequests > 0);
3620 FS.syncFSRequests--;
3621 return callback(errCode);
3622 }
3623
3624 function done(errCode) {
3625 if (errCode) {
3626 if (!done.errored) {
3627 done.errored = true;
3628 return doCallback(errCode);
3629 }
3630 return;
3631 }
3632 if (++completed >= mounts.length) {
3633 doCallback(null);
3634 }
3635 };
3636
3637 // sync all mounts
3638 mounts.forEach(function (mount) {
3639 if (!mount.type.syncfs) {
3640 return done(null);
3641 }
3642 mount.type.syncfs(mount, populate, done);
3643 });
3644 },mount:function(type, opts, mountpoint) {
3645 if (typeof type === 'string') {
3646 // The filesystem was not included, and instead we have an error
3647 // message stored in the variable.
3648 throw type;
3649 }
3650 var root = mountpoint === '/';
3651 var pseudo = !mountpoint;
3652 var node;
3653
3654 if (root && FS.root) {
3655 throw new FS.ErrnoError(10);
3656 } else if (!root && !pseudo) {
3657 var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
3658
3659 mountpoint = lookup.path; // use the absolute path
3660 node = lookup.node;
3661
3662 if (FS.isMountpoint(node)) {
3663 throw new FS.ErrnoError(10);
3664 }
3665
3666 if (!FS.isDir(node.mode)) {
3667 throw new FS.ErrnoError(54);
3668 }
3669 }
3670
3671 var mount = {
3672 type: type,
3673 opts: opts,
3674 mountpoint: mountpoint,
3675 mounts: []
3676 };
3677
3678 // create a root node for the fs
3679 var mountRoot = type.mount(mount);
3680 mountRoot.mount = mount;
3681 mount.root = mountRoot;
3682
3683 if (root) {
3684 FS.root = mountRoot;
3685 } else if (node) {
3686 // set as a mountpoint
3687 node.mounted = mount;
3688
3689 // add the new mount to the current mount's children
3690 if (node.mount) {
3691 node.mount.mounts.push(mount);
3692 }
3693 }
3694
3695 return mountRoot;
3696 },unmount:function (mountpoint) {
3697 var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
3698
3699 if (!FS.isMountpoint(lookup.node)) {
3700 throw new FS.ErrnoError(28);
3701 }
3702
3703 // destroy the nodes for this mount, and all its child mounts
3704 var node = lookup.node;
3705 var mount = node.mounted;
3706 var mounts = FS.getMounts(mount);
3707
3708 Object.keys(FS.nameTable).forEach(function (hash) {
3709 var current = FS.nameTable[hash];
3710
3711 while (current) {
3712 var next = current.name_next;
3713
3714 if (mounts.indexOf(current.mount) !== -1) {
3715 FS.destroyNode(current);
3716 }
3717
3718 current = next;
3719 }
3720 });
3721
3722 // no longer a mountpoint
3723 node.mounted = null;
3724
3725 // remove this mount from the child mounts
3726 var idx = node.mount.mounts.indexOf(mount);
3727 assert(idx !== -1);
3728 node.mount.mounts.splice(idx, 1);
3729 },lookup:function(parent, name) {
3730 return parent.node_ops.lookup(parent, name);
3731 },mknod:function(path, mode, dev) {
3732 var lookup = FS.lookupPath(path, { parent: true });
3733 var parent = lookup.node;
3734 var name = PATH.basename(path);
3735 if (!name || name === '.' || name === '..') {
3736 throw new FS.ErrnoError(28);
3737 }
3738 var errCode = FS.mayCreate(parent, name);
3739 if (errCode) {
3740 throw new FS.ErrnoError(errCode);
3741 }
3742 if (!parent.node_ops.mknod) {
3743 throw new FS.ErrnoError(63);
3744 }
3745 return parent.node_ops.mknod(parent, name, mode, dev);
3746 },create:function(path, mode) {
3747 mode = mode !== undefined ? mode : 438 /* 0666 */;
3748 mode &= 4095;
3749 mode |= 32768;
3750 return FS.mknod(path, mode, 0);
3751 },mkdir:function(path, mode) {
3752 mode = mode !== undefined ? mode : 511 /* 0777 */;
3753 mode &= 511 | 512;
3754 mode |= 16384;
3755 return FS.mknod(path, mode, 0);
3756 },mkdirTree:function(path, mode) {
3757 var dirs = path.split('/');
3758 var d = '';
3759 for (var i = 0; i < dirs.length; ++i) {
3760 if (!dirs[i]) continue;
3761 d += '/' + dirs[i];
3762 try {
3763 FS.mkdir(d, mode);
3764 } catch(e) {
3765 if (e.errno != 20) throw e;
3766 }
3767 }
3768 },mkdev:function(path, mode, dev) {
3769 if (typeof(dev) === 'undefined') {
3770 dev = mode;
3771 mode = 438 /* 0666 */;
3772 }
3773 mode |= 8192;
3774 return FS.mknod(path, mode, dev);
3775 },symlink:function(oldpath, newpath) {
3776 if (!PATH_FS.resolve(oldpath)) {
3777 throw new FS.ErrnoError(44);
3778 }
3779 var lookup = FS.lookupPath(newpath, { parent: true });
3780 var parent = lookup.node;
3781 if (!parent) {
3782 throw new FS.ErrnoError(44);
3783 }
3784 var newname = PATH.basename(newpath);
3785 var errCode = FS.mayCreate(parent, newname);
3786 if (errCode) {
3787 throw new FS.ErrnoError(errCode);
3788 }
3789 if (!parent.node_ops.symlink) {
3790 throw new FS.ErrnoError(63);
3791 }
3792 return parent.node_ops.symlink(parent, newname, oldpath);
3793 },rename:function(old_path, new_path) {
3794 var old_dirname = PATH.dirname(old_path);
3795 var new_dirname = PATH.dirname(new_path);
3796 var old_name = PATH.basename(old_path);
3797 var new_name = PATH.basename(new_path);
3798 // parents must exist
3799 var lookup, old_dir, new_dir;
3800 try {
3801 lookup = FS.lookupPath(old_path, { parent: true });
3802 old_dir = lookup.node;
3803 lookup = FS.lookupPath(new_path, { parent: true });
3804 new_dir = lookup.node;
3805 } catch (e) {
3806 throw new FS.ErrnoError(10);
3807 }
3808 if (!old_dir || !new_dir) throw new FS.ErrnoError(44);
3809 // need to be part of the same mount
3810 if (old_dir.mount !== new_dir.mount) {
3811 throw new FS.ErrnoError(75);
3812 }
3813 // source must exist
3814 var old_node = FS.lookupNode(old_dir, old_name);
3815 // old path should not be an ancestor of the new path
3816 var relative = PATH_FS.relative(old_path, new_dirname);
3817 if (relative.charAt(0) !== '.') {
3818 throw new FS.ErrnoError(28);
3819 }
3820 // new path should not be an ancestor of the old path
3821 relative = PATH_FS.relative(new_path, old_dirname);
3822 if (relative.charAt(0) !== '.') {
3823 throw new FS.ErrnoError(55);
3824 }
3825 // see if the new path already exists
3826 var new_node;
3827 try {
3828 new_node = FS.lookupNode(new_dir, new_name);
3829 } catch (e) {
3830 // not fatal
3831 }
3832 // early out if nothing needs to change
3833 if (old_node === new_node) {
3834 return;
3835 }
3836 // we'll need to delete the old entry
3837 var isdir = FS.isDir(old_node.mode);
3838 var errCode = FS.mayDelete(old_dir, old_name, isdir);
3839 if (errCode) {
3840 throw new FS.ErrnoError(errCode);
3841 }
3842 // need delete permissions if we'll be overwriting.
3843 // need create permissions if new doesn't already exist.
3844 errCode = new_node ?
3845 FS.mayDelete(new_dir, new_name, isdir) :
3846 FS.mayCreate(new_dir, new_name);
3847 if (errCode) {
3848 throw new FS.ErrnoError(errCode);
3849 }
3850 if (!old_dir.node_ops.rename) {
3851 throw new FS.ErrnoError(63);
3852 }
3853 if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
3854 throw new FS.ErrnoError(10);
3855 }
3856 // if we are going to change the parent, check write permissions
3857 if (new_dir !== old_dir) {
3858 errCode = FS.nodePermissions(old_dir, 'w');
3859 if (errCode) {
3860 throw new FS.ErrnoError(errCode);
3861 }
3862 }
3863 try {
3864 if (FS.trackingDelegate['willMovePath']) {
3865 FS.trackingDelegate['willMovePath'](old_path, new_path);
3866 }
3867 } catch(e) {
3868 err("FS.trackingDelegate['willMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
3869 }
3870 // remove the node from the lookup hash
3871 FS.hashRemoveNode(old_node);
3872 // do the underlying fs rename
3873 try {
3874 old_dir.node_ops.rename(old_node, new_dir, new_name);
3875 } catch (e) {
3876 throw e;
3877 } finally {
3878 // add the node back to the hash (in case node_ops.rename
3879 // changed its name)
3880 FS.hashAddNode(old_node);
3881 }
3882 try {
3883 if (FS.trackingDelegate['onMovePath']) FS.trackingDelegate['onMovePath'](old_path, new_path);
3884 } catch(e) {
3885 err("FS.trackingDelegate['onMovePath']('"+old_path+"', '"+new_path+"') threw an exception: " + e.message);
3886 }
3887 },rmdir:function(path) {
3888 var lookup = FS.lookupPath(path, { parent: true });
3889 var parent = lookup.node;
3890 var name = PATH.basename(path);
3891 var node = FS.lookupNode(parent, name);
3892 var errCode = FS.mayDelete(parent, name, true);
3893 if (errCode) {
3894 throw new FS.ErrnoError(errCode);
3895 }
3896 if (!parent.node_ops.rmdir) {
3897 throw new FS.ErrnoError(63);
3898 }
3899 if (FS.isMountpoint(node)) {
3900 throw new FS.ErrnoError(10);
3901 }
3902 try {
3903 if (FS.trackingDelegate['willDeletePath']) {
3904 FS.trackingDelegate['willDeletePath'](path);
3905 }
3906 } catch(e) {
3907 err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
3908 }
3909 parent.node_ops.rmdir(parent, name);
3910 FS.destroyNode(node);
3911 try {
3912 if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
3913 } catch(e) {
3914 err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
3915 }
3916 },readdir:function(path) {
3917 var lookup = FS.lookupPath(path, { follow: true });
3918 var node = lookup.node;
3919 if (!node.node_ops.readdir) {
3920 throw new FS.ErrnoError(54);
3921 }
3922 return node.node_ops.readdir(node);
3923 },unlink:function(path) {
3924 var lookup = FS.lookupPath(path, { parent: true });
3925 var parent = lookup.node;
3926 var name = PATH.basename(path);
3927 var node = FS.lookupNode(parent, name);
3928 var errCode = FS.mayDelete(parent, name, false);
3929 if (errCode) {
3930 // According to POSIX, we should map EISDIR to EPERM, but
3931 // we instead do what Linux does (and we must, as we use
3932 // the musl linux libc).
3933 throw new FS.ErrnoError(errCode);
3934 }
3935 if (!parent.node_ops.unlink) {
3936 throw new FS.ErrnoError(63);
3937 }
3938 if (FS.isMountpoint(node)) {
3939 throw new FS.ErrnoError(10);
3940 }
3941 try {
3942 if (FS.trackingDelegate['willDeletePath']) {
3943 FS.trackingDelegate['willDeletePath'](path);
3944 }
3945 } catch(e) {
3946 err("FS.trackingDelegate['willDeletePath']('"+path+"') threw an exception: " + e.message);
3947 }
3948 parent.node_ops.unlink(parent, name);
3949 FS.destroyNode(node);
3950 try {
3951 if (FS.trackingDelegate['onDeletePath']) FS.trackingDelegate['onDeletePath'](path);
3952 } catch(e) {
3953 err("FS.trackingDelegate['onDeletePath']('"+path+"') threw an exception: " + e.message);
3954 }
3955 },readlink:function(path) {
3956 var lookup = FS.lookupPath(path);
3957 var link = lookup.node;
3958 if (!link) {
3959 throw new FS.ErrnoError(44);
3960 }
3961 if (!link.node_ops.readlink) {
3962 throw new FS.ErrnoError(28);
3963 }
3964 return PATH_FS.resolve(FS.getPath(link.parent), link.node_ops.readlink(link));
3965 },stat:function(path, dontFollow) {
3966 var lookup = FS.lookupPath(path, { follow: !dontFollow });
3967 var node = lookup.node;
3968 if (!node) {
3969 throw new FS.ErrnoError(44);
3970 }
3971 if (!node.node_ops.getattr) {
3972 throw new FS.ErrnoError(63);
3973 }
3974 return node.node_ops.getattr(node);
3975 },lstat:function(path) {
3976 return FS.stat(path, true);
3977 },chmod:function(path, mode, dontFollow) {
3978 var node;
3979 if (typeof path === 'string') {
3980 var lookup = FS.lookupPath(path, { follow: !dontFollow });
3981 node = lookup.node;
3982 } else {
3983 node = path;
3984 }
3985 if (!node.node_ops.setattr) {
3986 throw new FS.ErrnoError(63);
3987 }
3988 node.node_ops.setattr(node, {
3989 mode: (mode & 4095) | (node.mode & ~4095),
3990 timestamp: Date.now()
3991 });
3992 },lchmod:function(path, mode) {
3993 FS.chmod(path, mode, true);
3994 },fchmod:function(fd, mode) {
3995 var stream = FS.getStream(fd);
3996 if (!stream) {
3997 throw new FS.ErrnoError(8);
3998 }
3999 FS.chmod(stream.node, mode);
4000 },chown:function(path, uid, gid, dontFollow) {
4001 var node;
4002 if (typeof path === 'string') {
4003 var lookup = FS.lookupPath(path, { follow: !dontFollow });
4004 node = lookup.node;
4005 } else {
4006 node = path;
4007 }
4008 if (!node.node_ops.setattr) {
4009 throw new FS.ErrnoError(63);
4010 }
4011 node.node_ops.setattr(node, {
4012 timestamp: Date.now()
4013 // we ignore the uid / gid for now
4014 });
4015 },lchown:function(path, uid, gid) {
4016 FS.chown(path, uid, gid, true);
4017 },fchown:function(fd, uid, gid) {
4018 var stream = FS.getStream(fd);
4019 if (!stream) {
4020 throw new FS.ErrnoError(8);
4021 }
4022 FS.chown(stream.node, uid, gid);
4023 },truncate:function(path, len) {
4024 if (len < 0) {
4025 throw new FS.ErrnoError(28);
4026 }
4027 var node;
4028 if (typeof path === 'string') {
4029 var lookup = FS.lookupPath(path, { follow: true });
4030 node = lookup.node;
4031 } else {
4032 node = path;
4033 }
4034 if (!node.node_ops.setattr) {
4035 throw new FS.ErrnoError(63);
4036 }
4037 if (FS.isDir(node.mode)) {
4038 throw new FS.ErrnoError(31);
4039 }
4040 if (!FS.isFile(node.mode)) {
4041 throw new FS.ErrnoError(28);
4042 }
4043 var errCode = FS.nodePermissions(node, 'w');
4044 if (errCode) {
4045 throw new FS.ErrnoError(errCode);
4046 }
4047 node.node_ops.setattr(node, {
4048 size: len,
4049 timestamp: Date.now()
4050 });
4051 },ftruncate:function(fd, len) {
4052 var stream = FS.getStream(fd);
4053 if (!stream) {
4054 throw new FS.ErrnoError(8);
4055 }
4056 if ((stream.flags & 2097155) === 0) {
4057 throw new FS.ErrnoError(28);
4058 }
4059 FS.truncate(stream.node, len);
4060 },utime:function(path, atime, mtime) {
4061 var lookup = FS.lookupPath(path, { follow: true });
4062 var node = lookup.node;
4063 node.node_ops.setattr(node, {
4064 timestamp: Math.max(atime, mtime)
4065 });
4066 },open:function(path, flags, mode, fd_start, fd_end) {
4067 if (path === "") {
4068 throw new FS.ErrnoError(44);
4069 }
4070 flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
4071 mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
4072 if ((flags & 64)) {
4073 mode = (mode & 4095) | 32768;
4074 } else {
4075 mode = 0;
4076 }
4077 var node;
4078 if (typeof path === 'object') {
4079 node = path;
4080 } else {
4081 path = PATH.normalize(path);
4082 try {
4083 var lookup = FS.lookupPath(path, {
4084 follow: !(flags & 131072)
4085 });
4086 node = lookup.node;
4087 } catch (e) {
4088 // ignore
4089 }
4090 }
4091 // perhaps we need to create the node
4092 var created = false;
4093 if ((flags & 64)) {
4094 if (node) {
4095 // if O_CREAT and O_EXCL are set, error out if the node already exists
4096 if ((flags & 128)) {
4097 throw new FS.ErrnoError(20);
4098 }
4099 } else {
4100 // node doesn't exist, try to create it
4101 node = FS.mknod(path, mode, 0);
4102 created = true;
4103 }
4104 }
4105 if (!node) {
4106 throw new FS.ErrnoError(44);
4107 }
4108 // can't truncate a device
4109 if (FS.isChrdev(node.mode)) {
4110 flags &= ~512;
4111 }
4112 // if asked only for a directory, then this must be one
4113 if ((flags & 65536) && !FS.isDir(node.mode)) {
4114 throw new FS.ErrnoError(54);
4115 }
4116 // check permissions, if this is not a file we just created now (it is ok to
4117 // create and write to a file with read-only permissions; it is read-only
4118 // for later use)
4119 if (!created) {
4120 var errCode = FS.mayOpen(node, flags);
4121 if (errCode) {
4122 throw new FS.ErrnoError(errCode);
4123 }
4124 }
4125 // do truncation if necessary
4126 if ((flags & 512)) {
4127 FS.truncate(node, 0);
4128 }
4129 // we've already handled these, don't pass down to the underlying vfs
4130 flags &= ~(128 | 512 | 131072);
4131
4132 // register the stream with the filesystem
4133 var stream = FS.createStream({
4134 node: node,
4135 path: FS.getPath(node), // we want the absolute path to the node
4136 flags: flags,
4137 seekable: true,
4138 position: 0,
4139 stream_ops: node.stream_ops,
4140 // used by the file family libc calls (fopen, fwrite, ferror, etc.)
4141 ungotten: [],
4142 error: false
4143 }, fd_start, fd_end);
4144 // call the new stream's open function
4145 if (stream.stream_ops.open) {
4146 stream.stream_ops.open(stream);
4147 }
4148 if (Module['logReadFiles'] && !(flags & 1)) {
4149 if (!FS.readFiles) FS.readFiles = {};
4150 if (!(path in FS.readFiles)) {
4151 FS.readFiles[path] = 1;
4152 err("FS.trackingDelegate error on read file: " + path);
4153 }
4154 }
4155 try {
4156 if (FS.trackingDelegate['onOpenFile']) {
4157 var trackingFlags = 0;
4158 if ((flags & 2097155) !== 1) {
4159 trackingFlags |= FS.tracking.openFlags.READ;
4160 }
4161 if ((flags & 2097155) !== 0) {
4162 trackingFlags |= FS.tracking.openFlags.WRITE;
4163 }
4164 FS.trackingDelegate['onOpenFile'](path, trackingFlags);
4165 }
4166 } catch(e) {
4167 err("FS.trackingDelegate['onOpenFile']('"+path+"', flags) threw an exception: " + e.message);
4168 }
4169 return stream;
4170 },close:function(stream) {
4171 if (FS.isClosed(stream)) {
4172 throw new FS.ErrnoError(8);
4173 }
4174 if (stream.getdents) stream.getdents = null; // free readdir state
4175 try {
4176 if (stream.stream_ops.close) {
4177 stream.stream_ops.close(stream);
4178 }
4179 } catch (e) {
4180 throw e;
4181 } finally {
4182 FS.closeStream(stream.fd);
4183 }
4184 stream.fd = null;
4185 },isClosed:function(stream) {
4186 return stream.fd === null;
4187 },llseek:function(stream, offset, whence) {
4188 if (FS.isClosed(stream)) {
4189 throw new FS.ErrnoError(8);
4190 }
4191 if (!stream.seekable || !stream.stream_ops.llseek) {
4192 throw new FS.ErrnoError(70);
4193 }
4194 if (whence != 0 && whence != 1 && whence != 2) {
4195 throw new FS.ErrnoError(28);
4196 }
4197 stream.position = stream.stream_ops.llseek(stream, offset, whence);
4198 stream.ungotten = [];
4199 return stream.position;
4200 },read:function(stream, buffer, offset, length, position) {
4201 if (length < 0 || position < 0) {
4202 throw new FS.ErrnoError(28);
4203 }
4204 if (FS.isClosed(stream)) {
4205 throw new FS.ErrnoError(8);
4206 }
4207 if ((stream.flags & 2097155) === 1) {
4208 throw new FS.ErrnoError(8);
4209 }
4210 if (FS.isDir(stream.node.mode)) {
4211 throw new FS.ErrnoError(31);
4212 }
4213 if (!stream.stream_ops.read) {
4214 throw new FS.ErrnoError(28);
4215 }
4216 var seeking = typeof position !== 'undefined';
4217 if (!seeking) {
4218 position = stream.position;
4219 } else if (!stream.seekable) {
4220 throw new FS.ErrnoError(70);
4221 }
4222 var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
4223 if (!seeking) stream.position += bytesRead;
4224 return bytesRead;
4225 },write:function(stream, buffer, offset, length, position, canOwn) {
4226 if (length < 0 || position < 0) {
4227 throw new FS.ErrnoError(28);
4228 }
4229 if (FS.isClosed(stream)) {
4230 throw new FS.ErrnoError(8);
4231 }
4232 if ((stream.flags & 2097155) === 0) {
4233 throw new FS.ErrnoError(8);
4234 }
4235 if (FS.isDir(stream.node.mode)) {
4236 throw new FS.ErrnoError(31);
4237 }
4238 if (!stream.stream_ops.write) {
4239 throw new FS.ErrnoError(28);
4240 }
4241 if (stream.seekable && stream.flags & 1024) {
4242 // seek to the end before writing in append mode
4243 FS.llseek(stream, 0, 2);
4244 }
4245 var seeking = typeof position !== 'undefined';
4246 if (!seeking) {
4247 position = stream.position;
4248 } else if (!stream.seekable) {
4249 throw new FS.ErrnoError(70);
4250 }
4251 var bytesWritten = stream.stream_ops.write(stream, buffer, offset, length, position, canOwn);
4252 if (!seeking) stream.position += bytesWritten;
4253 try {
4254 if (stream.path && FS.trackingDelegate['onWriteToFile']) FS.trackingDelegate['onWriteToFile'](stream.path);
4255 } catch(e) {
4256 err("FS.trackingDelegate['onWriteToFile']('"+stream.path+"') threw an exception: " + e.message);
4257 }
4258 return bytesWritten;
4259 },allocate:function(stream, offset, length) {
4260 if (FS.isClosed(stream)) {
4261 throw new FS.ErrnoError(8);
4262 }
4263 if (offset < 0 || length <= 0) {
4264 throw new FS.ErrnoError(28);
4265 }
4266 if ((stream.flags & 2097155) === 0) {
4267 throw new FS.ErrnoError(8);
4268 }
4269 if (!FS.isFile(stream.node.mode) && !FS.isDir(stream.node.mode)) {
4270 throw new FS.ErrnoError(43);
4271 }
4272 if (!stream.stream_ops.allocate) {
4273 throw new FS.ErrnoError(138);
4274 }
4275 stream.stream_ops.allocate(stream, offset, length);
4276 },mmap:function(stream, address, length, position, prot, flags) {
4277 // User requests writing to file (prot & PROT_WRITE != 0).
4278 // Checking if we have permissions to write to the file unless
4279 // MAP_PRIVATE flag is set. According to POSIX spec it is possible
4280 // to write to file opened in read-only mode with MAP_PRIVATE flag,
4281 // as all modifications will be visible only in the memory of
4282 // the current process.
4283 if ((prot & 2) !== 0
4284 && (flags & 2) === 0
4285 && (stream.flags & 2097155) !== 2) {
4286 throw new FS.ErrnoError(2);
4287 }
4288 if ((stream.flags & 2097155) === 1) {
4289 throw new FS.ErrnoError(2);
4290 }
4291 if (!stream.stream_ops.mmap) {
4292 throw new FS.ErrnoError(43);
4293 }
4294 return stream.stream_ops.mmap(stream, address, length, position, prot, flags);
4295 },msync:function(stream, buffer, offset, length, mmapFlags) {
4296 if (!stream || !stream.stream_ops.msync) {
4297 return 0;
4298 }
4299 return stream.stream_ops.msync(stream, buffer, offset, length, mmapFlags);
4300 },munmap:function(stream) {
4301 return 0;
4302 },ioctl:function(stream, cmd, arg) {
4303 if (!stream.stream_ops.ioctl) {
4304 throw new FS.ErrnoError(59);
4305 }
4306 return stream.stream_ops.ioctl(stream, cmd, arg);
4307 },readFile:function(path, opts) {
4308 opts = opts || {};
4309 opts.flags = opts.flags || 'r';
4310 opts.encoding = opts.encoding || 'binary';
4311 if (opts.encoding !== 'utf8' && opts.encoding !== 'binary') {
4312 throw new Error('Invalid encoding type "' + opts.encoding + '"');
4313 }
4314 var ret;
4315 var stream = FS.open(path, opts.flags);
4316 var stat = FS.stat(path);
4317 var length = stat.size;
4318 var buf = new Uint8Array(length);
4319 FS.read(stream, buf, 0, length, 0);
4320 if (opts.encoding === 'utf8') {
4321 ret = UTF8ArrayToString(buf, 0);
4322 } else if (opts.encoding === 'binary') {
4323 ret = buf;
4324 }
4325 FS.close(stream);
4326 return ret;
4327 },writeFile:function(path, data, opts) {
4328 opts = opts || {};
4329 opts.flags = opts.flags || 'w';
4330 var stream = FS.open(path, opts.flags, opts.mode);
4331 if (typeof data === 'string') {
4332 var buf = new Uint8Array(lengthBytesUTF8(data)+1);
4333 var actualNumBytes = stringToUTF8Array(data, buf, 0, buf.length);
4334 FS.write(stream, buf, 0, actualNumBytes, undefined, opts.canOwn);
4335 } else if (ArrayBuffer.isView(data)) {
4336 FS.write(stream, data, 0, data.byteLength, undefined, opts.canOwn);
4337 } else {
4338 throw new Error('Unsupported data type');
4339 }
4340 FS.close(stream);
4341 },cwd:function() {
4342 return FS.currentPath;
4343 },chdir:function(path) {
4344 var lookup = FS.lookupPath(path, { follow: true });
4345 if (lookup.node === null) {
4346 throw new FS.ErrnoError(44);
4347 }
4348 if (!FS.isDir(lookup.node.mode)) {
4349 throw new FS.ErrnoError(54);
4350 }
4351 var errCode = FS.nodePermissions(lookup.node, 'x');
4352 if (errCode) {
4353 throw new FS.ErrnoError(errCode);
4354 }
4355 FS.currentPath = lookup.path;
4356 },createDefaultDirectories:function() {
4357 FS.mkdir('/tmp');
4358 FS.mkdir('/home');
4359 FS.mkdir('/home/web_user');
4360 },createDefaultDevices:function() {
4361 // create /dev
4362 FS.mkdir('/dev');
4363 // setup /dev/null
4364 FS.registerDevice(FS.makedev(1, 3), {
4365 read: function() { return 0; },
4366 write: function(stream, buffer, offset, length, pos) { return length; }
4367 });
4368 FS.mkdev('/dev/null', FS.makedev(1, 3));
4369 // setup /dev/tty and /dev/tty1
4370 // stderr needs to print output using Module['printErr']
4371 // so we register a second tty just for it.
4372 TTY.register(FS.makedev(5, 0), TTY.default_tty_ops);
4373 TTY.register(FS.makedev(6, 0), TTY.default_tty1_ops);
4374 FS.mkdev('/dev/tty', FS.makedev(5, 0));
4375 FS.mkdev('/dev/tty1', FS.makedev(6, 0));
4376 // setup /dev/[u]random
4377 var random_device;
4378 if (typeof crypto === 'object' && typeof crypto['getRandomValues'] === 'function') {
4379 // for modern web browsers
4380 var randomBuffer = new Uint8Array(1);
4381 random_device = function() { crypto.getRandomValues(randomBuffer); return randomBuffer[0]; };
4382 } else
4383 if (ENVIRONMENT_IS_NODE) {
4384 // for nodejs with or without crypto support included
4385 try {
4386 var crypto_module = require('crypto');
4387 // nodejs has crypto support
4388 random_device = function() { return crypto_module['randomBytes'](1)[0]; };
4389 } catch (e) {
4390 // nodejs doesn't have crypto support
4391 }
4392 } else
4393 {}
4394 if (!random_device) {
4395 // we couldn't find a proper implementation, as Math.random() is not suitable for /dev/random, see emscripten-core/emscripten/pull/7096
4396 random_device = function() { abort("no cryptographic support found for random_device. 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 } };"); };
4397 }
4398 FS.createDevice('/dev', 'random', random_device);
4399 FS.createDevice('/dev', 'urandom', random_device);
4400 // we're not going to emulate the actual shm device,
4401 // just create the tmp dirs that reside in it commonly
4402 FS.mkdir('/dev/shm');
4403 FS.mkdir('/dev/shm/tmp');
4404 },createSpecialDirectories:function() {
4405 // create /proc/self/fd which allows /proc/self/fd/6 => readlink gives the name of the stream for fd 6 (see test_unistd_ttyname)
4406 FS.mkdir('/proc');
4407 FS.mkdir('/proc/self');
4408 FS.mkdir('/proc/self/fd');
4409 FS.mount({
4410 mount: function() {
4411 var node = FS.createNode('/proc/self', 'fd', 16384 | 511 /* 0777 */, 73);
4412 node.node_ops = {
4413 lookup: function(parent, name) {
4414 var fd = +name;
4415 var stream = FS.getStream(fd);
4416 if (!stream) throw new FS.ErrnoError(8);
4417 var ret = {
4418 parent: null,
4419 mount: { mountpoint: 'fake' },
4420 node_ops: { readlink: function() { return stream.path } }
4421 };
4422 ret.parent = ret; // make it look like a simple root node
4423 return ret;
4424 }
4425 };
4426 return node;
4427 }
4428 }, {}, '/proc/self/fd');
4429 },createStandardStreams:function() {
4430 // TODO deprecate the old functionality of a single
4431 // input / output callback and that utilizes FS.createDevice
4432 // and instead require a unique set of stream ops
4433
4434 // by default, we symlink the standard streams to the
4435 // default tty devices. however, if the standard streams
4436 // have been overwritten we create a unique device for
4437 // them instead.
4438 if (Module['stdin']) {
4439 FS.createDevice('/dev', 'stdin', Module['stdin']);
4440 } else {
4441 FS.symlink('/dev/tty', '/dev/stdin');
4442 }
4443 if (Module['stdout']) {
4444 FS.createDevice('/dev', 'stdout', null, Module['stdout']);
4445 } else {
4446 FS.symlink('/dev/tty', '/dev/stdout');
4447 }
4448 if (Module['stderr']) {
4449 FS.createDevice('/dev', 'stderr', null, Module['stderr']);
4450 } else {
4451 FS.symlink('/dev/tty1', '/dev/stderr');
4452 }
4453
4454 // open default streams for the stdin, stdout and stderr devices
4455 var stdin = FS.open('/dev/stdin', 'r');
4456 var stdout = FS.open('/dev/stdout', 'w');
4457 var stderr = FS.open('/dev/stderr', 'w');
4458 assert(stdin.fd === 0, 'invalid handle for stdin (' + stdin.fd + ')');
4459 assert(stdout.fd === 1, 'invalid handle for stdout (' + stdout.fd + ')');
4460 assert(stderr.fd === 2, 'invalid handle for stderr (' + stderr.fd + ')');
4461 },ensureErrnoError:function() {
4462 if (FS.ErrnoError) return;
4463 FS.ErrnoError = /** @this{Object} */ function ErrnoError(errno, node) {
4464 this.node = node;
4465 this.setErrno = /** @this{Object} */ function(errno) {
4466 this.errno = errno;
4467 for (var key in ERRNO_CODES) {
4468 if (ERRNO_CODES[key] === errno) {
4469 this.code = key;
4470 break;
4471 }
4472 }
4473 };
4474 this.setErrno(errno);
4475 this.message = ERRNO_MESSAGES[errno];
4476
4477 // Try to get a maximally helpful stack trace. On Node.js, getting Error.stack
4478 // now ensures it shows what we want.
4479 if (this.stack) {
4480 // Define the stack property for Node.js 4, which otherwise errors on the next line.
4481 Object.defineProperty(this, "stack", { value: (new Error).stack, writable: true });
4482 this.stack = demangleAll(this.stack);
4483 }
4484 };
4485 FS.ErrnoError.prototype = new Error();
4486 FS.ErrnoError.prototype.constructor = FS.ErrnoError;
4487 // Some errors may happen quite a bit, to avoid overhead we reuse them (and suffer a lack of stack info)
4488 [44].forEach(function(code) {
4489 FS.genericErrors[code] = new FS.ErrnoError(code);
4490 FS.genericErrors[code].stack = '<generic error, no stack>';
4491 });
4492 },staticInit:function() {
4493 FS.ensureErrnoError();
4494
4495 FS.nameTable = new Array(4096);
4496
4497 FS.mount(MEMFS, {}, '/');
4498
4499 FS.createDefaultDirectories();
4500 FS.createDefaultDevices();
4501 FS.createSpecialDirectories();
4502
4503 FS.filesystems = {
4504 'MEMFS': MEMFS,
4505 };
4506 },init:function(input, output, error) {
4507 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)');
4508 FS.init.initialized = true;
4509
4510 FS.ensureErrnoError();
4511
4512 // Allow Module.stdin etc. to provide defaults, if none explicitly passed to us here
4513 Module['stdin'] = input || Module['stdin'];
4514 Module['stdout'] = output || Module['stdout'];
4515 Module['stderr'] = error || Module['stderr'];
4516
4517 FS.createStandardStreams();
4518 },quit:function() {
4519 FS.init.initialized = false;
4520 // force-flush all streams, so we get musl std streams printed out
4521 var fflush = Module['_fflush'];
4522 if (fflush) fflush(0);
4523 // close all of our streams
4524 for (var i = 0; i < FS.streams.length; i++) {
4525 var stream = FS.streams[i];
4526 if (!stream) {
4527 continue;
4528 }
4529 FS.close(stream);
4530 }
4531 },getMode:function(canRead, canWrite) {
4532 var mode = 0;
4533 if (canRead) mode |= 292 | 73;
4534 if (canWrite) mode |= 146;
4535 return mode;
4536 },joinPath:function(parts, forceRelative) {
4537 var path = PATH.join.apply(null, parts);
4538 if (forceRelative && path[0] == '/') path = path.substr(1);
4539 return path;
4540 },absolutePath:function(relative, base) {
4541 return PATH_FS.resolve(base, relative);
4542 },standardizePath:function(path) {
4543 return PATH.normalize(path);
4544 },findObject:function(path, dontResolveLastLink) {
4545 var ret = FS.analyzePath(path, dontResolveLastLink);
4546 if (ret.exists) {
4547 return ret.object;
4548 } else {
4549 setErrNo(ret.error);
4550 return null;
4551 }
4552 },analyzePath:function(path, dontResolveLastLink) {
4553 // operate from within the context of the symlink's target
4554 try {
4555 var lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
4556 path = lookup.path;
4557 } catch (e) {
4558 }
4559 var ret = {
4560 isRoot: false, exists: false, error: 0, name: null, path: null, object: null,
4561 parentExists: false, parentPath: null, parentObject: null
4562 };
4563 try {
4564 var lookup = FS.lookupPath(path, { parent: true });
4565 ret.parentExists = true;
4566 ret.parentPath = lookup.path;
4567 ret.parentObject = lookup.node;
4568 ret.name = PATH.basename(path);
4569 lookup = FS.lookupPath(path, { follow: !dontResolveLastLink });
4570 ret.exists = true;
4571 ret.path = lookup.path;
4572 ret.object = lookup.node;
4573 ret.name = lookup.node.name;
4574 ret.isRoot = lookup.path === '/';
4575 } catch (e) {
4576 ret.error = e.errno;
4577 };
4578 return ret;
4579 },createFolder:function(parent, name, canRead, canWrite) {
4580 var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
4581 var mode = FS.getMode(canRead, canWrite);
4582 return FS.mkdir(path, mode);
4583 },createPath:function(parent, path, canRead, canWrite) {
4584 parent = typeof parent === 'string' ? parent : FS.getPath(parent);
4585 var parts = path.split('/').reverse();
4586 while (parts.length) {
4587 var part = parts.pop();
4588 if (!part) continue;
4589 var current = PATH.join2(parent, part);
4590 try {
4591 FS.mkdir(current);
4592 } catch (e) {
4593 // ignore EEXIST
4594 }
4595 parent = current;
4596 }
4597 return current;
4598 },createFile:function(parent, name, properties, canRead, canWrite) {
4599 var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
4600 var mode = FS.getMode(canRead, canWrite);
4601 return FS.create(path, mode);
4602 },createDataFile:function(parent, name, data, canRead, canWrite, canOwn) {
4603 var path = name ? PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name) : parent;
4604 var mode = FS.getMode(canRead, canWrite);
4605 var node = FS.create(path, mode);
4606 if (data) {
4607 if (typeof data === 'string') {
4608 var arr = new Array(data.length);
4609 for (var i = 0, len = data.length; i < len; ++i) arr[i] = data.charCodeAt(i);
4610 data = arr;
4611 }
4612 // make sure we can write to the file
4613 FS.chmod(node, mode | 146);
4614 var stream = FS.open(node, 'w');
4615 FS.write(stream, data, 0, data.length, 0, canOwn);
4616 FS.close(stream);
4617 FS.chmod(node, mode);
4618 }
4619 return node;
4620 },createDevice:function(parent, name, input, output) {
4621 var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
4622 var mode = FS.getMode(!!input, !!output);
4623 if (!FS.createDevice.major) FS.createDevice.major = 64;
4624 var dev = FS.makedev(FS.createDevice.major++, 0);
4625 // Create a fake device that a set of stream ops to emulate
4626 // the old behavior.
4627 FS.registerDevice(dev, {
4628 open: function(stream) {
4629 stream.seekable = false;
4630 },
4631 close: function(stream) {
4632 // flush any pending line data
4633 if (output && output.buffer && output.buffer.length) {
4634 output(10);
4635 }
4636 },
4637 read: function(stream, buffer, offset, length, pos /* ignored */) {
4638 var bytesRead = 0;
4639 for (var i = 0; i < length; i++) {
4640 var result;
4641 try {
4642 result = input();
4643 } catch (e) {
4644 throw new FS.ErrnoError(29);
4645 }
4646 if (result === undefined && bytesRead === 0) {
4647 throw new FS.ErrnoError(6);
4648 }
4649 if (result === null || result === undefined) break;
4650 bytesRead++;
4651 buffer[offset+i] = result;
4652 }
4653 if (bytesRead) {
4654 stream.node.timestamp = Date.now();
4655 }
4656 return bytesRead;
4657 },
4658 write: function(stream, buffer, offset, length, pos) {
4659 for (var i = 0; i < length; i++) {
4660 try {
4661 output(buffer[offset+i]);
4662 } catch (e) {
4663 throw new FS.ErrnoError(29);
4664 }
4665 }
4666 if (length) {
4667 stream.node.timestamp = Date.now();
4668 }
4669 return i;
4670 }
4671 });
4672 return FS.mkdev(path, mode, dev);
4673 },createLink:function(parent, name, target, canRead, canWrite) {
4674 var path = PATH.join2(typeof parent === 'string' ? parent : FS.getPath(parent), name);
4675 return FS.symlink(target, path);
4676 },forceLoadFile:function(obj) {
4677 if (obj.isDevice || obj.isFolder || obj.link || obj.contents) return true;
4678 var success = true;
4679 if (typeof XMLHttpRequest !== 'undefined') {
4680 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.");
4681 } else if (read_) {
4682 // Command-line.
4683 try {
4684 // WARNING: Can't read binary files in V8's d8 or tracemonkey's js, as
4685 // read() will try to parse UTF8.
4686 obj.contents = intArrayFromString(read_(obj.url), true);
4687 obj.usedBytes = obj.contents.length;
4688 } catch (e) {
4689 success = false;
4690 }
4691 } else {
4692 throw new Error('Cannot load without read() or XMLHttpRequest.');
4693 }
4694 if (!success) setErrNo(29);
4695 return success;
4696 },createLazyFile:function(parent, name, url, canRead, canWrite) {
4697 // Lazy chunked Uint8Array (implements get and length from Uint8Array). Actual getting is abstracted away for eventual reuse.
4698 /** @constructor */
4699 function LazyUint8Array() {
4700 this.lengthKnown = false;
4701 this.chunks = []; // Loaded chunks. Index is the chunk number
4702 }
4703 LazyUint8Array.prototype.get = /** @this{Object} */ function LazyUint8Array_get(idx) {
4704 if (idx > this.length-1 || idx < 0) {
4705 return undefined;
4706 }
4707 var chunkOffset = idx % this.chunkSize;
4708 var chunkNum = (idx / this.chunkSize)|0;
4709 return this.getter(chunkNum)[chunkOffset];
4710 };
4711 LazyUint8Array.prototype.setDataGetter = function LazyUint8Array_setDataGetter(getter) {
4712 this.getter = getter;
4713 };
4714 LazyUint8Array.prototype.cacheLength = function LazyUint8Array_cacheLength() {
4715 // Find length
4716 var xhr = new XMLHttpRequest();
4717 xhr.open('HEAD', url, false);
4718 xhr.send(null);
4719 if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
4720 var datalength = Number(xhr.getResponseHeader("Content-length"));
4721 var header;
4722 var hasByteServing = (header = xhr.getResponseHeader("Accept-Ranges")) && header === "bytes";
4723 var usesGzip = (header = xhr.getResponseHeader("Content-Encoding")) && header === "gzip";
4724
4725 var chunkSize = 1024*1024; // Chunk size in bytes
4726
4727 if (!hasByteServing) chunkSize = datalength;
4728
4729 // Function to get a range from the remote URL.
4730 var doXHR = (function(from, to) {
4731 if (from > to) throw new Error("invalid range (" + from + ", " + to + ") or no bytes requested!");
4732 if (to > datalength-1) throw new Error("only " + datalength + " bytes available! programmer error!");
4733
4734 // TODO: Use mozResponseArrayBuffer, responseStream, etc. if available.
4735 var xhr = new XMLHttpRequest();
4736 xhr.open('GET', url, false);
4737 if (datalength !== chunkSize) xhr.setRequestHeader("Range", "bytes=" + from + "-" + to);
4738
4739 // Some hints to the browser that we want binary data.
4740 if (typeof Uint8Array != 'undefined') xhr.responseType = 'arraybuffer';
4741 if (xhr.overrideMimeType) {
4742 xhr.overrideMimeType('text/plain; charset=x-user-defined');
4743 }
4744
4745 xhr.send(null);
4746 if (!(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304)) throw new Error("Couldn't load " + url + ". Status: " + xhr.status);
4747 if (xhr.response !== undefined) {
4748 return new Uint8Array(/** @type{Array<number>} */(xhr.response || []));
4749 } else {
4750 return intArrayFromString(xhr.responseText || '', true);
4751 }
4752 });
4753 var lazyArray = this;
4754 lazyArray.setDataGetter(function(chunkNum) {
4755 var start = chunkNum * chunkSize;
4756 var end = (chunkNum+1) * chunkSize - 1; // including this byte
4757 end = Math.min(end, datalength-1); // if datalength-1 is selected, this is the last block
4758 if (typeof(lazyArray.chunks[chunkNum]) === "undefined") {
4759 lazyArray.chunks[chunkNum] = doXHR(start, end);
4760 }
4761 if (typeof(lazyArray.chunks[chunkNum]) === "undefined") throw new Error("doXHR failed!");
4762 return lazyArray.chunks[chunkNum];
4763 });
4764
4765 if (usesGzip || !datalength) {
4766 // if the server uses gzip or doesn't supply the length, we have to download the whole file to get the (uncompressed) length
4767 chunkSize = datalength = 1; // this will force getter(0)/doXHR do download the whole file
4768 datalength = this.getter(0).length;
4769 chunkSize = datalength;
4770 out("LazyFiles on gzip forces download of the whole file when length is accessed");
4771 }
4772
4773 this._length = datalength;
4774 this._chunkSize = chunkSize;
4775 this.lengthKnown = true;
4776 };
4777 if (typeof XMLHttpRequest !== 'undefined') {
4778 if (!ENVIRONMENT_IS_WORKER) throw 'Cannot do synchronous binary XHRs outside webworkers in modern browsers. Use --embed-file or --preload-file in emcc';
4779 var lazyArray = new LazyUint8Array();
4780 Object.defineProperties(lazyArray, {
4781 length: {
4782 get: /** @this{Object} */ function() {
4783 if(!this.lengthKnown) {
4784 this.cacheLength();
4785 }
4786 return this._length;
4787 }
4788 },
4789 chunkSize: {
4790 get: /** @this{Object} */ function() {
4791 if(!this.lengthKnown) {
4792 this.cacheLength();
4793 }
4794 return this._chunkSize;
4795 }
4796 }
4797 });
4798
4799 var properties = { isDevice: false, contents: lazyArray };
4800 } else {
4801 var properties = { isDevice: false, url: url };
4802 }
4803
4804 var node = FS.createFile(parent, name, properties, canRead, canWrite);
4805 // This is a total hack, but I want to get this lazy file code out of the
4806 // core of MEMFS. If we want to keep this lazy file concept I feel it should
4807 // be its own thin LAZYFS proxying calls to MEMFS.
4808 if (properties.contents) {
4809 node.contents = properties.contents;
4810 } else if (properties.url) {
4811 node.contents = null;
4812 node.url = properties.url;
4813 }
4814 // Add a function that defers querying the file size until it is asked the first time.
4815 Object.defineProperties(node, {
4816 usedBytes: {
4817 get: /** @this {FSNode} */ function() { return this.contents.length; }
4818 }
4819 });
4820 // override each stream op with one that tries to force load the lazy file first
4821 var stream_ops = {};
4822 var keys = Object.keys(node.stream_ops);
4823 keys.forEach(function(key) {
4824 var fn = node.stream_ops[key];
4825 stream_ops[key] = function forceLoadLazyFile() {
4826 if (!FS.forceLoadFile(node)) {
4827 throw new FS.ErrnoError(29);
4828 }
4829 return fn.apply(null, arguments);
4830 };
4831 });
4832 // use a custom read function
4833 stream_ops.read = function stream_ops_read(stream, buffer, offset, length, position) {
4834 if (!FS.forceLoadFile(node)) {
4835 throw new FS.ErrnoError(29);
4836 }
4837 var contents = stream.node.contents;
4838 if (position >= contents.length)
4839 return 0;
4840 var size = Math.min(contents.length - position, length);
4841 assert(size >= 0);
4842 if (contents.slice) { // normal array
4843 for (var i = 0; i < size; i++) {
4844 buffer[offset + i] = contents[position + i];
4845 }
4846 } else {
4847 for (var i = 0; i < size; i++) { // LazyUint8Array from sync binary XHR
4848 buffer[offset + i] = contents.get(position + i);
4849 }
4850 }
4851 return size;
4852 };
4853 node.stream_ops = stream_ops;
4854 return node;
4855 },createPreloadedFile:function(parent, name, url, canRead, canWrite, onload, onerror, dontCreateFile, canOwn, preFinish) {
4856 Browser.init(); // XXX perhaps this method should move onto Browser?
4857 // TODO we should allow people to just pass in a complete filename instead
4858 // of parent and name being that we just join them anyways
4859 var fullname = name ? PATH_FS.resolve(PATH.join2(parent, name)) : parent;
4860 var dep = getUniqueRunDependency('cp ' + fullname); // might have several active requests for the same fullname
4861 function processData(byteArray) {
4862 function finish(byteArray) {
4863 if (preFinish) preFinish();
4864 if (!dontCreateFile) {
4865 FS.createDataFile(parent, name, byteArray, canRead, canWrite, canOwn);
4866 }
4867 if (onload) onload();
4868 removeRunDependency(dep);
4869 }
4870 var handled = false;
4871 Module['preloadPlugins'].forEach(function(plugin) {
4872 if (handled) return;
4873 if (plugin['canHandle'](fullname)) {
4874 plugin['handle'](byteArray, fullname, finish, function() {
4875 if (onerror) onerror();
4876 removeRunDependency(dep);
4877 });
4878 handled = true;
4879 }
4880 });
4881 if (!handled) finish(byteArray);
4882 }
4883 addRunDependency(dep);
4884 if (typeof url == 'string') {
4885 Browser.asyncLoad(url, function(byteArray) {
4886 processData(byteArray);
4887 }, onerror);
4888 } else {
4889 processData(url);
4890 }
4891 },indexedDB:function() {
4892 return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
4893 },DB_NAME:function() {
4894 return 'EM_FS_' + window.location.pathname;
4895 },DB_VERSION:20,DB_STORE_NAME:"FILE_DATA",saveFilesToDB:function(paths, onload, onerror) {
4896 onload = onload || function(){};
4897 onerror = onerror || function(){};
4898 var indexedDB = FS.indexedDB();
4899 try {
4900 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
4901 } catch (e) {
4902 return onerror(e);
4903 }
4904 openRequest.onupgradeneeded = function openRequest_onupgradeneeded() {
4905 out('creating db');
4906 var db = openRequest.result;
4907 db.createObjectStore(FS.DB_STORE_NAME);
4908 };
4909 openRequest.onsuccess = function openRequest_onsuccess() {
4910 var db = openRequest.result;
4911 var transaction = db.transaction([FS.DB_STORE_NAME], 'readwrite');
4912 var files = transaction.objectStore(FS.DB_STORE_NAME);
4913 var ok = 0, fail = 0, total = paths.length;
4914 function finish() {
4915 if (fail == 0) onload(); else onerror();
4916 }
4917 paths.forEach(function(path) {
4918 var putRequest = files.put(FS.analyzePath(path).object.contents, path);
4919 putRequest.onsuccess = function putRequest_onsuccess() { ok++; if (ok + fail == total) finish() };
4920 putRequest.onerror = function putRequest_onerror() { fail++; if (ok + fail == total) finish() };
4921 });
4922 transaction.onerror = onerror;
4923 };
4924 openRequest.onerror = onerror;
4925 },loadFilesFromDB:function(paths, onload, onerror) {
4926 onload = onload || function(){};
4927 onerror = onerror || function(){};
4928 var indexedDB = FS.indexedDB();
4929 try {
4930 var openRequest = indexedDB.open(FS.DB_NAME(), FS.DB_VERSION);
4931 } catch (e) {
4932 return onerror(e);
4933 }
4934 openRequest.onupgradeneeded = onerror; // no database to load from
4935 openRequest.onsuccess = function openRequest_onsuccess() {
4936 var db = openRequest.result;
4937 try {
4938 var transaction = db.transaction([FS.DB_STORE_NAME], 'readonly');
4939 } catch(e) {
4940 onerror(e);
4941 return;
4942 }
4943 var files = transaction.objectStore(FS.DB_STORE_NAME);
4944 var ok = 0, fail = 0, total = paths.length;
4945 function finish() {
4946 if (fail == 0) onload(); else onerror();
4947 }
4948 paths.forEach(function(path) {
4949 var getRequest = files.get(path);
4950 getRequest.onsuccess = function getRequest_onsuccess() {
4951 if (FS.analyzePath(path).exists) {
4952 FS.unlink(path);
4953 }
4954 FS.createDataFile(PATH.dirname(path), PATH.basename(path), getRequest.result, true, true, true);
4955 ok++;
4956 if (ok + fail == total) finish();
4957 };
4958 getRequest.onerror = function getRequest_onerror() { fail++; if (ok + fail == total) finish() };
4959 });
4960 transaction.onerror = onerror;
4961 };
4962 openRequest.onerror = onerror;
4963 }};var SYSCALLS={mappings:{},DEFAULT_POLLMASK:5,umask:511,calculateAt:function(dirfd, path) {
4964 if (path[0] !== '/') {
4965 // relative path
4966 var dir;
4967 if (dirfd === -100) {
4968 dir = FS.cwd();
4969 } else {
4970 var dirstream = FS.getStream(dirfd);
4971 if (!dirstream) throw new FS.ErrnoError(8);
4972 dir = dirstream.path;
4973 }
4974 path = PATH.join2(dir, path);
4975 }
4976 return path;
4977 },doStat:function(func, path, buf) {
4978 try {
4979 var stat = func(path);
4980 } catch (e) {
4981 if (e && e.node && PATH.normalize(path) !== PATH.normalize(FS.getPath(e.node))) {
4982 // an error occurred while trying to look up the path; we should just report ENOTDIR
4983 return -54;
4984 }
4985 throw e;
4986 }
4987 HEAP32[((buf)>>2)]=stat.dev;
4988 HEAP32[(((buf)+(4))>>2)]=0;
4989 HEAP32[(((buf)+(8))>>2)]=stat.ino;
4990 HEAP32[(((buf)+(12))>>2)]=stat.mode;
4991 HEAP32[(((buf)+(16))>>2)]=stat.nlink;
4992 HEAP32[(((buf)+(20))>>2)]=stat.uid;
4993 HEAP32[(((buf)+(24))>>2)]=stat.gid;
4994 HEAP32[(((buf)+(28))>>2)]=stat.rdev;
4995 HEAP32[(((buf)+(32))>>2)]=0;
4996 (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]);
4997 HEAP32[(((buf)+(48))>>2)]=4096;
4998 HEAP32[(((buf)+(52))>>2)]=stat.blocks;
4999 HEAP32[(((buf)+(56))>>2)]=(stat.atime.getTime() / 1000)|0;
5000 HEAP32[(((buf)+(60))>>2)]=0;
5001 HEAP32[(((buf)+(64))>>2)]=(stat.mtime.getTime() / 1000)|0;
5002 HEAP32[(((buf)+(68))>>2)]=0;
5003 HEAP32[(((buf)+(72))>>2)]=(stat.ctime.getTime() / 1000)|0;
5004 HEAP32[(((buf)+(76))>>2)]=0;
5005 (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]);
5006 return 0;
5007 },doMsync:function(addr, stream, len, flags, offset) {
5008 var buffer = HEAPU8.slice(addr, addr + len);
5009 FS.msync(stream, buffer, offset, len, flags);
5010 },doMkdir:function(path, mode) {
5011 // remove a trailing slash, if one - /a/b/ has basename of '', but
5012 // we want to create b in the context of this function
5013 path = PATH.normalize(path);
5014 if (path[path.length-1] === '/') path = path.substr(0, path.length-1);
5015 FS.mkdir(path, mode, 0);
5016 return 0;
5017 },doMknod:function(path, mode, dev) {
5018 // we don't want this in the JS API as it uses mknod to create all nodes.
5019 switch (mode & 61440) {
5020 case 32768:
5021 case 8192:
5022 case 24576:
5023 case 4096:
5024 case 49152:
5025 break;
5026 default: return -28;
5027 }
5028 FS.mknod(path, mode, dev);
5029 return 0;
5030 },doReadlink:function(path, buf, bufsize) {
5031 if (bufsize <= 0) return -28;
5032 var ret = FS.readlink(path);
5033
5034 var len = Math.min(bufsize, lengthBytesUTF8(ret));
5035 var endChar = HEAP8[buf+len];
5036 stringToUTF8(ret, buf, bufsize+1);
5037 // readlink is one of the rare functions that write out a C string, but does never append a null to the output buffer(!)
5038 // stringToUTF8() always appends a null byte, so restore the character under the null byte after the write.
5039 HEAP8[buf+len] = endChar;
5040
5041 return len;
5042 },doAccess:function(path, amode) {
5043 if (amode & ~7) {
5044 // need a valid mode
5045 return -28;
5046 }
5047 var node;
5048 var lookup = FS.lookupPath(path, { follow: true });
5049 node = lookup.node;
5050 if (!node) {
5051 return -44;
5052 }
5053 var perms = '';
5054 if (amode & 4) perms += 'r';
5055 if (amode & 2) perms += 'w';
5056 if (amode & 1) perms += 'x';
5057 if (perms /* otherwise, they've just passed F_OK */ && FS.nodePermissions(node, perms)) {
5058 return -2;
5059 }
5060 return 0;
5061 },doDup:function(path, flags, suggestFD) {
5062 var suggest = FS.getStream(suggestFD);
5063 if (suggest) FS.close(suggest);
5064 return FS.open(path, flags, 0, suggestFD, suggestFD).fd;
5065 },doReadv:function(stream, iov, iovcnt, offset) {
5066 var ret = 0;
5067 for (var i = 0; i < iovcnt; i++) {
5068 var ptr = HEAP32[(((iov)+(i*8))>>2)];
5069 var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
5070 var curr = FS.read(stream, HEAP8,ptr, len, offset);
5071 if (curr < 0) return -1;
5072 ret += curr;
5073 if (curr < len) break; // nothing more to read
5074 }
5075 return ret;
5076 },doWritev:function(stream, iov, iovcnt, offset) {
5077 var ret = 0;
5078 for (var i = 0; i < iovcnt; i++) {
5079 var ptr = HEAP32[(((iov)+(i*8))>>2)];
5080 var len = HEAP32[(((iov)+(i*8 + 4))>>2)];
5081 var curr = FS.write(stream, HEAP8,ptr, len, offset);
5082 if (curr < 0) return -1;
5083 ret += curr;
5084 }
5085 return ret;
5086 },varargs:undefined,get:function() {
5087 assert(SYSCALLS.varargs != undefined);
5088 SYSCALLS.varargs += 4;
5089 var ret = HEAP32[(((SYSCALLS.varargs)-(4))>>2)];
5090 return ret;
5091 },getStr:function(ptr) {
5092 var ret = UTF8ToString(ptr);
5093 return ret;
5094 },getStreamFromFD:function(fd) {
5095 var stream = FS.getStream(fd);
5096 if (!stream) throw new FS.ErrnoError(8);
5097 return stream;
5098 },get64:function(low, high) {
5099 if (low >= 0) assert(high === 0);
5100 else assert(high === -1);
5101 return low;
5102 }};function ___sys_fcntl64(fd, cmd, varargs) {SYSCALLS.varargs = varargs;
5103 try {
5104
5105 var stream = SYSCALLS.getStreamFromFD(fd);
5106 switch (cmd) {
5107 case 0: {
5108 var arg = SYSCALLS.get();
5109 if (arg < 0) {
5110 return -28;
5111 }
5112 var newStream;
5113 newStream = FS.open(stream.path, stream.flags, 0, arg);
5114 return newStream.fd;
5115 }
5116 case 1:
5117 case 2:
5118 return 0; // FD_CLOEXEC makes no sense for a single process.
5119 case 3:
5120 return stream.flags;
5121 case 4: {
5122 var arg = SYSCALLS.get();
5123 stream.flags |= arg;
5124 return 0;
5125 }
5126 case 12:
5127 /* case 12: Currently in musl F_GETLK64 has same value as F_GETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */ {
5128
5129 var arg = SYSCALLS.get();
5130 var offset = 0;
5131 // We're always unlocked.
5132 HEAP16[(((arg)+(offset))>>1)]=2;
5133 return 0;
5134 }
5135 case 13:
5136 case 14:
5137 /* case 13: Currently in musl F_SETLK64 has same value as F_SETLK, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
5138 /* case 14: Currently in musl F_SETLKW64 has same value as F_SETLKW, so omitted to avoid duplicate case blocks. If that changes, uncomment this */
5139
5140
5141 return 0; // Pretend that the locking is successful.
5142 case 16:
5143 case 8:
5144 return -28; // These are for sockets. We don't have them fully implemented yet.
5145 case 9:
5146 // musl trusts getown return values, due to a bug where they must be, as they overlap with errors. just return -1 here, so fnctl() returns that, and we set errno ourselves.
5147 setErrNo(28);
5148 return -1;
5149 default: {
5150 return -28;
5151 }
5152 }
5153 } catch (e) {
5154 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5155 return -e.errno;
5156 }
5157 }
5158
5159 function ___sys_ioctl(fd, op, varargs) {SYSCALLS.varargs = varargs;
5160 try {
5161
5162 var stream = SYSCALLS.getStreamFromFD(fd);
5163 switch (op) {
5164 case 21509:
5165 case 21505: {
5166 if (!stream.tty) return -59;
5167 return 0;
5168 }
5169 case 21510:
5170 case 21511:
5171 case 21512:
5172 case 21506:
5173 case 21507:
5174 case 21508: {
5175 if (!stream.tty) return -59;
5176 return 0; // no-op, not actually adjusting terminal settings
5177 }
5178 case 21519: {
5179 if (!stream.tty) return -59;
5180 var argp = SYSCALLS.get();
5181 HEAP32[((argp)>>2)]=0;
5182 return 0;
5183 }
5184 case 21520: {
5185 if (!stream.tty) return -59;
5186 return -28; // not supported
5187 }
5188 case 21531: {
5189 var argp = SYSCALLS.get();
5190 return FS.ioctl(stream, op, argp);
5191 }
5192 case 21523: {
5193 // TODO: in theory we should write to the winsize struct that gets
5194 // passed in, but for now musl doesn't read anything on it
5195 if (!stream.tty) return -59;
5196 return 0;
5197 }
5198 case 21524: {
5199 // TODO: technically, this ioctl call should change the window size.
5200 // but, since emscripten doesn't have any concept of a terminal window
5201 // yet, we'll just silently throw it away as we do TIOCGWINSZ
5202 if (!stream.tty) return -59;
5203 return 0;
5204 }
5205 default: abort('bad ioctl syscall ' + op);
5206 }
5207 } catch (e) {
5208 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5209 return -e.errno;
5210 }
5211 }
5212
5213 function ___sys_open(path, flags, varargs) {SYSCALLS.varargs = varargs;
5214 try {
5215
5216 var pathname = SYSCALLS.getStr(path);
5217 var mode = SYSCALLS.get();
5218 var stream = FS.open(pathname, flags, mode);
5219 return stream.fd;
5220 } catch (e) {
5221 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5222 return -e.errno;
5223 }
5224 }
5225
5226 function _abort() {
5227 abort();
5228 }
5229
5230 function _emscripten_get_sbrk_ptr() {
5231 return 79712;
5232 }
5233
5234
5235 function _longjmp(env, value) {
5236 _setThrew(env, value || 1);
5237 throw 'longjmp';
5238 }function _emscripten_longjmp(env, value) {
5239 _longjmp(env, value);
5240 }
5241
5242 function _emscripten_memcpy_big(dest, src, num) {
5243 HEAPU8.copyWithin(dest, src, src + num);
5244 }
5245
5246
5247 function _emscripten_get_heap_size() {
5248 return HEAPU8.length;
5249 }
5250
5251 function abortOnCannotGrowMemory(requestedSize) {
5252 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 ');
5253 }function _emscripten_resize_heap(requestedSize) {
5254 requestedSize = requestedSize >>> 0;
5255 abortOnCannotGrowMemory(requestedSize);
5256 }
5257
5258 function _exit(status) {
5259 // void _exit(int status);
5260 // http://pubs.opengroup.org/onlinepubs/000095399/functions/exit.html
5261 exit(status);
5262 }
5263
5264 function _fd_close(fd) {try {
5265
5266 var stream = SYSCALLS.getStreamFromFD(fd);
5267 FS.close(stream);
5268 return 0;
5269 } catch (e) {
5270 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5271 return e.errno;
5272 }
5273 }
5274
5275 function _fd_read(fd, iov, iovcnt, pnum) {try {
5276
5277 var stream = SYSCALLS.getStreamFromFD(fd);
5278 var num = SYSCALLS.doReadv(stream, iov, iovcnt);
5279 HEAP32[((pnum)>>2)]=num
5280 return 0;
5281 } catch (e) {
5282 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5283 return e.errno;
5284 }
5285 }
5286
5287 function _fd_seek(fd, offset_low, offset_high, whence, newOffset) {try {
5288
5289
5290 var stream = SYSCALLS.getStreamFromFD(fd);
5291 var HIGH_OFFSET = 0x100000000; // 2^32
5292 // use an unsigned operator on low and shift high by 32-bits
5293 var offset = offset_high * HIGH_OFFSET + (offset_low >>> 0);
5294
5295 var DOUBLE_LIMIT = 0x20000000000000; // 2^53
5296 // we also check for equality since DOUBLE_LIMIT + 1 == DOUBLE_LIMIT
5297 if (offset <= -DOUBLE_LIMIT || offset >= DOUBLE_LIMIT) {
5298 return -61;
5299 }
5300
5301 FS.llseek(stream, offset, whence);
5302 (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]);
5303 if (stream.getdents && offset === 0 && whence === 0) stream.getdents = null; // reset readdir state
5304 return 0;
5305 } catch (e) {
5306 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5307 return e.errno;
5308 }
5309 }
5310
5311 function _fd_write(fd, iov, iovcnt, pnum) {try {
5312
5313 var stream = SYSCALLS.getStreamFromFD(fd);
5314 var num = SYSCALLS.doWritev(stream, iov, iovcnt);
5315 HEAP32[((pnum)>>2)]=num
5316 return 0;
5317 } catch (e) {
5318 if (typeof FS === 'undefined' || !(e instanceof FS.ErrnoError)) abort(e);
5319 return e.errno;
5320 }
5321 }
5322
5323 function _getTempRet0() {
5324 return (getTempRet0() | 0);
5325 }
5326
5327
5328 function _round(d) {
5329 d = +d;
5330 return d >= +0 ? +Math_floor(d + +0.5) : +Math_ceil(d - +0.5);
5331 }
5332
5333 function _setTempRet0($i) {
5334 setTempRet0(($i) | 0);
5335 }
5336
5337Module["requestFullscreen"] = function Module_requestFullscreen(lockPointer, resizeCanvas) { Browser.requestFullscreen(lockPointer, resizeCanvas) };
5338 Module["requestFullScreen"] = function Module_requestFullScreen() { Browser.requestFullScreen() };
5339 Module["requestAnimationFrame"] = function Module_requestAnimationFrame(func) { Browser.requestAnimationFrame(func) };
5340 Module["setCanvasSize"] = function Module_setCanvasSize(width, height, noUpdates) { Browser.setCanvasSize(width, height, noUpdates) };
5341 Module["pauseMainLoop"] = function Module_pauseMainLoop() { Browser.mainLoop.pause() };
5342 Module["resumeMainLoop"] = function Module_resumeMainLoop() { Browser.mainLoop.resume() };
5343 Module["getUserMedia"] = function Module_getUserMedia() { Browser.getUserMedia() }
5344 Module["createContext"] = function Module_createContext(canvas, useWebGL, setInModule, webGLContextAttributes) { return Browser.createContext(canvas, useWebGL, setInModule, webGLContextAttributes) };
5345var FSNode = /** @constructor */ function(parent, name, mode, rdev) {
5346 if (!parent) {
5347 parent = this; // root node sets parent to itself
5348 }
5349 this.parent = parent;
5350 this.mount = parent.mount;
5351 this.mounted = null;
5352 this.id = FS.nextInode++;
5353 this.name = name;
5354 this.mode = mode;
5355 this.node_ops = {};
5356 this.stream_ops = {};
5357 this.rdev = rdev;
5358 };
5359 var readMode = 292/*292*/ | 73/*73*/;
5360 var writeMode = 146/*146*/;
5361 Object.defineProperties(FSNode.prototype, {
5362 read: {
5363 get: /** @this{FSNode} */function() {
5364 return (this.mode & readMode) === readMode;
5365 },
5366 set: /** @this{FSNode} */function(val) {
5367 val ? this.mode |= readMode : this.mode &= ~readMode;
5368 }
5369 },
5370 write: {
5371 get: /** @this{FSNode} */function() {
5372 return (this.mode & writeMode) === writeMode;
5373 },
5374 set: /** @this{FSNode} */function(val) {
5375 val ? this.mode |= writeMode : this.mode &= ~writeMode;
5376 }
5377 },
5378 isFolder: {
5379 get: /** @this{FSNode} */function() {
5380 return FS.isDir(this.mode);
5381 }
5382 },
5383 isDevice: {
5384 get: /** @this{FSNode} */function() {
5385 return FS.isChrdev(this.mode);
5386 }
5387 }
5388 });
5389 FS.FSNode = FSNode;
5390 FS.staticInit();Module["FS_createFolder"] = FS.createFolder;Module["FS_createPath"] = FS.createPath;Module["FS_createDataFile"] = FS.createDataFile;Module["FS_createPreloadedFile"] = FS.createPreloadedFile;Module["FS_createLazyFile"] = FS.createLazyFile;Module["FS_createLink"] = FS.createLink;Module["FS_createDevice"] = FS.createDevice;Module["FS_unlink"] = FS.unlink;;
5391var ASSERTIONS = true;
5392
5393
5394
5395/** @type {function(string, boolean=, number=)} */
5396function intArrayFromString(stringy, dontAddNull, length) {
5397 var len = length > 0 ? length : lengthBytesUTF8(stringy)+1;
5398 var u8array = new Array(len);
5399 var numBytesWritten = stringToUTF8Array(stringy, u8array, 0, u8array.length);
5400 if (dontAddNull) u8array.length = numBytesWritten;
5401 return u8array;
5402}
5403
5404function intArrayToString(array) {
5405 var ret = [];
5406 for (var i = 0; i < array.length; i++) {
5407 var chr = array[i];
5408 if (chr > 0xFF) {
5409 if (ASSERTIONS) {
5410 assert(false, 'Character code ' + chr + ' (' + String.fromCharCode(chr) + ') at offset ' + i + ' not in 0x00-0xFF.');
5411 }
5412 chr &= 0xFF;
5413 }
5414 ret.push(String.fromCharCode(chr));
5415 }
5416 return ret.join('');
5417}
5418
5419
5420// ASM_LIBRARY EXTERN PRIMITIVES: Math_floor,Math_ceil
5421
5422var asmGlobalArg = {};
5423var asmLibraryArg = { "__handle_stack_overflow": ___handle_stack_overflow, "__sys_fcntl64": ___sys_fcntl64, "__sys_ioctl": ___sys_ioctl, "__sys_open": ___sys_open, "abort": _abort, "emscripten_get_sbrk_ptr": _emscripten_get_sbrk_ptr, "emscripten_longjmp": _emscripten_longjmp, "emscripten_memcpy_big": _emscripten_memcpy_big, "emscripten_resize_heap": _emscripten_resize_heap, "exit": _exit, "fd_close": _fd_close, "fd_read": _fd_read, "fd_seek": _fd_seek, "fd_write": _fd_write, "getTempRet0": _getTempRet0, "invoke_ii": invoke_ii, "invoke_iii": invoke_iii, "invoke_iiii": invoke_iiii, "invoke_iiiii": invoke_iiiii, "invoke_vi": invoke_vi, "invoke_vii": invoke_vii, "invoke_viii": invoke_viii, "invoke_viiii": invoke_viiii, "invoke_viiiii": invoke_viiiii, "invoke_viiiiii": invoke_viiiiii, "invoke_viiiiiii": invoke_viiiiiii, "memory": wasmMemory, "round": _round, "setTempRet0": _setTempRet0, "table": wasmTable };
5424var asm = createWasm();
5425/** @type {function(...*):?} */
5426var ___wasm_call_ctors = Module["___wasm_call_ctors"] = createExportWrapper("__wasm_call_ctors");
5427
5428/** @type {function(...*):?} */
5429var _main = Module["_main"] = createExportWrapper("main");
5430
5431/** @type {function(...*):?} */
5432var ___errno_location = Module["___errno_location"] = createExportWrapper("__errno_location");
5433
5434/** @type {function(...*):?} */
5435var _malloc = Module["_malloc"] = createExportWrapper("malloc");
5436
5437/** @type {function(...*):?} */
5438var _testSetjmp = Module["_testSetjmp"] = createExportWrapper("testSetjmp");
5439
5440/** @type {function(...*):?} */
5441var _saveSetjmp = Module["_saveSetjmp"] = createExportWrapper("saveSetjmp");
5442
5443/** @type {function(...*):?} */
5444var _free = Module["_free"] = createExportWrapper("free");
5445
5446/** @type {function(...*):?} */
5447var _realloc = Module["_realloc"] = createExportWrapper("realloc");
5448
5449/** @type {function(...*):?} */
5450var _fflush = Module["_fflush"] = createExportWrapper("fflush");
5451
5452/** @type {function(...*):?} */
5453var _setThrew = Module["_setThrew"] = createExportWrapper("setThrew");
5454
5455/** @type {function(...*):?} */
5456var stackSave = Module["stackSave"] = createExportWrapper("stackSave");
5457
5458/** @type {function(...*):?} */
5459var stackRestore = Module["stackRestore"] = createExportWrapper("stackRestore");
5460
5461/** @type {function(...*):?} */
5462var stackAlloc = Module["stackAlloc"] = createExportWrapper("stackAlloc");
5463
5464/** @type {function(...*):?} */
5465var dynCall_vi = Module["dynCall_vi"] = createExportWrapper("dynCall_vi");
5466
5467/** @type {function(...*):?} */
5468var dynCall_vii = Module["dynCall_vii"] = createExportWrapper("dynCall_vii");
5469
5470/** @type {function(...*):?} */
5471var dynCall_viii = Module["dynCall_viii"] = createExportWrapper("dynCall_viii");
5472
5473/** @type {function(...*):?} */
5474var dynCall_viiii = Module["dynCall_viiii"] = createExportWrapper("dynCall_viiii");
5475
5476/** @type {function(...*):?} */
5477var dynCall_viiiii = Module["dynCall_viiiii"] = createExportWrapper("dynCall_viiiii");
5478
5479/** @type {function(...*):?} */
5480var dynCall_viiiiii = Module["dynCall_viiiiii"] = createExportWrapper("dynCall_viiiiii");
5481
5482/** @type {function(...*):?} */
5483var dynCall_viiiiiii = Module["dynCall_viiiiiii"] = createExportWrapper("dynCall_viiiiiii");
5484
5485/** @type {function(...*):?} */
5486var dynCall_ii = Module["dynCall_ii"] = createExportWrapper("dynCall_ii");
5487
5488/** @type {function(...*):?} */
5489var dynCall_iii = Module["dynCall_iii"] = createExportWrapper("dynCall_iii");
5490
5491/** @type {function(...*):?} */
5492var dynCall_iiii = Module["dynCall_iiii"] = createExportWrapper("dynCall_iiii");
5493
5494/** @type {function(...*):?} */
5495var dynCall_iiiii = Module["dynCall_iiiii"] = createExportWrapper("dynCall_iiiii");
5496
5497/** @type {function(...*):?} */
5498var ___set_stack_limit = Module["___set_stack_limit"] = createExportWrapper("__set_stack_limit");
5499
5500/** @type {function(...*):?} */
5501var __growWasmMemory = Module["__growWasmMemory"] = createExportWrapper("__growWasmMemory");
5502
5503/** @type {function(...*):?} */
5504var dynCall_jiji = Module["dynCall_jiji"] = createExportWrapper("dynCall_jiji");
5505
5506/** @type {function(...*):?} */
5507var dynCall_iidiiii = Module["dynCall_iidiiii"] = createExportWrapper("dynCall_iidiiii");
5508
5509
5510function invoke_vi(index,a1) {
5511 var sp = stackSave();
5512 try {
5513 dynCall_vi(index,a1);
5514 } catch(e) {
5515 stackRestore(sp);
5516 if (e !== e+0 && e !== 'longjmp') throw e;
5517 _setThrew(1, 0);
5518 }
5519}
5520
5521function invoke_vii(index,a1,a2) {
5522 var sp = stackSave();
5523 try {
5524 dynCall_vii(index,a1,a2);
5525 } catch(e) {
5526 stackRestore(sp);
5527 if (e !== e+0 && e !== 'longjmp') throw e;
5528 _setThrew(1, 0);
5529 }
5530}
5531
5532function invoke_iiii(index,a1,a2,a3) {
5533 var sp = stackSave();
5534 try {
5535 return dynCall_iiii(index,a1,a2,a3);
5536 } catch(e) {
5537 stackRestore(sp);
5538 if (e !== e+0 && e !== 'longjmp') throw e;
5539 _setThrew(1, 0);
5540 }
5541}
5542
5543function invoke_iii(index,a1,a2) {
5544 var sp = stackSave();
5545 try {
5546 return dynCall_iii(index,a1,a2);
5547 } catch(e) {
5548 stackRestore(sp);
5549 if (e !== e+0 && e !== 'longjmp') throw e;
5550 _setThrew(1, 0);
5551 }
5552}
5553
5554function invoke_viiii(index,a1,a2,a3,a4) {
5555 var sp = stackSave();
5556 try {
5557 dynCall_viiii(index,a1,a2,a3,a4);
5558 } catch(e) {
5559 stackRestore(sp);
5560 if (e !== e+0 && e !== 'longjmp') throw e;
5561 _setThrew(1, 0);
5562 }
5563}
5564
5565function invoke_viiiii(index,a1,a2,a3,a4,a5) {
5566 var sp = stackSave();
5567 try {
5568 dynCall_viiiii(index,a1,a2,a3,a4,a5);
5569 } catch(e) {
5570 stackRestore(sp);
5571 if (e !== e+0 && e !== 'longjmp') throw e;
5572 _setThrew(1, 0);
5573 }
5574}
5575
5576function invoke_viii(index,a1,a2,a3) {
5577 var sp = stackSave();
5578 try {
5579 dynCall_viii(index,a1,a2,a3);
5580 } catch(e) {
5581 stackRestore(sp);
5582 if (e !== e+0 && e !== 'longjmp') throw e;
5583 _setThrew(1, 0);
5584 }
5585}
5586
5587function invoke_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7) {
5588 var sp = stackSave();
5589 try {
5590 dynCall_viiiiiii(index,a1,a2,a3,a4,a5,a6,a7);
5591 } catch(e) {
5592 stackRestore(sp);
5593 if (e !== e+0 && e !== 'longjmp') throw e;
5594 _setThrew(1, 0);
5595 }
5596}
5597
5598function invoke_iiiii(index,a1,a2,a3,a4) {
5599 var sp = stackSave();
5600 try {
5601 return dynCall_iiiii(index,a1,a2,a3,a4);
5602 } catch(e) {
5603 stackRestore(sp);
5604 if (e !== e+0 && e !== 'longjmp') throw e;
5605 _setThrew(1, 0);
5606 }
5607}
5608
5609function invoke_viiiiii(index,a1,a2,a3,a4,a5,a6) {
5610 var sp = stackSave();
5611 try {
5612 dynCall_viiiiii(index,a1,a2,a3,a4,a5,a6);
5613 } catch(e) {
5614 stackRestore(sp);
5615 if (e !== e+0 && e !== 'longjmp') throw e;
5616 _setThrew(1, 0);
5617 }
5618}
5619
5620function invoke_ii(index,a1) {
5621 var sp = stackSave();
5622 try {
5623 return dynCall_ii(index,a1);
5624 } catch(e) {
5625 stackRestore(sp);
5626 if (e !== e+0 && e !== 'longjmp') throw e;
5627 _setThrew(1, 0);
5628 }
5629}
5630
5631
5632
5633
5634// === Auto-generated postamble setup entry stuff ===
5635
5636
5637if (!Object.getOwnPropertyDescriptor(Module, "intArrayFromString")) Module["intArrayFromString"] = function() { abort("'intArrayFromString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5638if (!Object.getOwnPropertyDescriptor(Module, "intArrayToString")) Module["intArrayToString"] = function() { abort("'intArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5639if (!Object.getOwnPropertyDescriptor(Module, "ccall")) Module["ccall"] = function() { abort("'ccall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5640if (!Object.getOwnPropertyDescriptor(Module, "cwrap")) Module["cwrap"] = function() { abort("'cwrap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5641if (!Object.getOwnPropertyDescriptor(Module, "setValue")) Module["setValue"] = function() { abort("'setValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5642if (!Object.getOwnPropertyDescriptor(Module, "getValue")) Module["getValue"] = function() { abort("'getValue' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5643if (!Object.getOwnPropertyDescriptor(Module, "allocate")) Module["allocate"] = function() { abort("'allocate' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5644Module["getMemory"] = getMemory;
5645if (!Object.getOwnPropertyDescriptor(Module, "UTF8ArrayToString")) Module["UTF8ArrayToString"] = function() { abort("'UTF8ArrayToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5646if (!Object.getOwnPropertyDescriptor(Module, "UTF8ToString")) Module["UTF8ToString"] = function() { abort("'UTF8ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5647if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8Array")) Module["stringToUTF8Array"] = function() { abort("'stringToUTF8Array' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5648if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF8")) Module["stringToUTF8"] = function() { abort("'stringToUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5649if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF8")) Module["lengthBytesUTF8"] = function() { abort("'lengthBytesUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5650if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5651if (!Object.getOwnPropertyDescriptor(Module, "addOnPreRun")) Module["addOnPreRun"] = function() { abort("'addOnPreRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5652if (!Object.getOwnPropertyDescriptor(Module, "addOnInit")) Module["addOnInit"] = function() { abort("'addOnInit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5653if (!Object.getOwnPropertyDescriptor(Module, "addOnPreMain")) Module["addOnPreMain"] = function() { abort("'addOnPreMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5654if (!Object.getOwnPropertyDescriptor(Module, "addOnExit")) Module["addOnExit"] = function() { abort("'addOnExit' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5655if (!Object.getOwnPropertyDescriptor(Module, "addOnPostRun")) Module["addOnPostRun"] = function() { abort("'addOnPostRun' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5656if (!Object.getOwnPropertyDescriptor(Module, "writeStringToMemory")) Module["writeStringToMemory"] = function() { abort("'writeStringToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5657if (!Object.getOwnPropertyDescriptor(Module, "writeArrayToMemory")) Module["writeArrayToMemory"] = function() { abort("'writeArrayToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5658if (!Object.getOwnPropertyDescriptor(Module, "writeAsciiToMemory")) Module["writeAsciiToMemory"] = function() { abort("'writeAsciiToMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5659Module["addRunDependency"] = addRunDependency;
5660Module["removeRunDependency"] = removeRunDependency;
5661Module["FS_createFolder"] = FS.createFolder;
5662Module["FS_createPath"] = FS.createPath;
5663Module["FS_createDataFile"] = FS.createDataFile;
5664Module["FS_createPreloadedFile"] = FS.createPreloadedFile;
5665Module["FS_createLazyFile"] = FS.createLazyFile;
5666Module["FS_createLink"] = FS.createLink;
5667Module["FS_createDevice"] = FS.createDevice;
5668Module["FS_unlink"] = FS.unlink;
5669if (!Object.getOwnPropertyDescriptor(Module, "dynamicAlloc")) Module["dynamicAlloc"] = function() { abort("'dynamicAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5670if (!Object.getOwnPropertyDescriptor(Module, "loadDynamicLibrary")) Module["loadDynamicLibrary"] = function() { abort("'loadDynamicLibrary' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5671if (!Object.getOwnPropertyDescriptor(Module, "loadWebAssemblyModule")) Module["loadWebAssemblyModule"] = function() { abort("'loadWebAssemblyModule' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5672if (!Object.getOwnPropertyDescriptor(Module, "getLEB")) Module["getLEB"] = function() { abort("'getLEB' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5673if (!Object.getOwnPropertyDescriptor(Module, "getFunctionTables")) Module["getFunctionTables"] = function() { abort("'getFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5674if (!Object.getOwnPropertyDescriptor(Module, "alignFunctionTables")) Module["alignFunctionTables"] = function() { abort("'alignFunctionTables' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5675if (!Object.getOwnPropertyDescriptor(Module, "registerFunctions")) Module["registerFunctions"] = function() { abort("'registerFunctions' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5676if (!Object.getOwnPropertyDescriptor(Module, "addFunction")) Module["addFunction"] = function() { abort("'addFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5677if (!Object.getOwnPropertyDescriptor(Module, "removeFunction")) Module["removeFunction"] = function() { abort("'removeFunction' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5678if (!Object.getOwnPropertyDescriptor(Module, "getFuncWrapper")) Module["getFuncWrapper"] = function() { abort("'getFuncWrapper' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5679if (!Object.getOwnPropertyDescriptor(Module, "prettyPrint")) Module["prettyPrint"] = function() { abort("'prettyPrint' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5680if (!Object.getOwnPropertyDescriptor(Module, "makeBigInt")) Module["makeBigInt"] = function() { abort("'makeBigInt' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5681if (!Object.getOwnPropertyDescriptor(Module, "dynCall")) Module["dynCall"] = function() { abort("'dynCall' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5682if (!Object.getOwnPropertyDescriptor(Module, "getCompilerSetting")) Module["getCompilerSetting"] = function() { abort("'getCompilerSetting' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5683if (!Object.getOwnPropertyDescriptor(Module, "print")) Module["print"] = function() { abort("'print' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5684if (!Object.getOwnPropertyDescriptor(Module, "printErr")) Module["printErr"] = function() { abort("'printErr' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5685if (!Object.getOwnPropertyDescriptor(Module, "getTempRet0")) Module["getTempRet0"] = function() { abort("'getTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5686if (!Object.getOwnPropertyDescriptor(Module, "setTempRet0")) Module["setTempRet0"] = function() { abort("'setTempRet0' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5687if (!Object.getOwnPropertyDescriptor(Module, "callMain")) Module["callMain"] = function() { abort("'callMain' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5688if (!Object.getOwnPropertyDescriptor(Module, "abort")) Module["abort"] = function() { abort("'abort' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5689if (!Object.getOwnPropertyDescriptor(Module, "stringToNewUTF8")) Module["stringToNewUTF8"] = function() { abort("'stringToNewUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5690if (!Object.getOwnPropertyDescriptor(Module, "abortOnCannotGrowMemory")) Module["abortOnCannotGrowMemory"] = function() { abort("'abortOnCannotGrowMemory' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5691if (!Object.getOwnPropertyDescriptor(Module, "emscripten_realloc_buffer")) Module["emscripten_realloc_buffer"] = function() { abort("'emscripten_realloc_buffer' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5692if (!Object.getOwnPropertyDescriptor(Module, "ENV")) Module["ENV"] = function() { abort("'ENV' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5693if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_CODES")) Module["ERRNO_CODES"] = function() { abort("'ERRNO_CODES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5694if (!Object.getOwnPropertyDescriptor(Module, "ERRNO_MESSAGES")) Module["ERRNO_MESSAGES"] = function() { abort("'ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5695if (!Object.getOwnPropertyDescriptor(Module, "setErrNo")) Module["setErrNo"] = function() { abort("'setErrNo' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5696if (!Object.getOwnPropertyDescriptor(Module, "DNS")) Module["DNS"] = function() { abort("'DNS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5697if (!Object.getOwnPropertyDescriptor(Module, "GAI_ERRNO_MESSAGES")) Module["GAI_ERRNO_MESSAGES"] = function() { abort("'GAI_ERRNO_MESSAGES' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5698if (!Object.getOwnPropertyDescriptor(Module, "Protocols")) Module["Protocols"] = function() { abort("'Protocols' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5699if (!Object.getOwnPropertyDescriptor(Module, "Sockets")) Module["Sockets"] = function() { abort("'Sockets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5700if (!Object.getOwnPropertyDescriptor(Module, "UNWIND_CACHE")) Module["UNWIND_CACHE"] = function() { abort("'UNWIND_CACHE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5701if (!Object.getOwnPropertyDescriptor(Module, "readAsmConstArgs")) Module["readAsmConstArgs"] = function() { abort("'readAsmConstArgs' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5702if (!Object.getOwnPropertyDescriptor(Module, "jstoi_q")) Module["jstoi_q"] = function() { abort("'jstoi_q' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5703if (!Object.getOwnPropertyDescriptor(Module, "jstoi_s")) Module["jstoi_s"] = function() { abort("'jstoi_s' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5704if (!Object.getOwnPropertyDescriptor(Module, "listenOnce")) Module["listenOnce"] = function() { abort("'listenOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5705if (!Object.getOwnPropertyDescriptor(Module, "autoResumeAudioContext")) Module["autoResumeAudioContext"] = function() { abort("'autoResumeAudioContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5706if (!Object.getOwnPropertyDescriptor(Module, "abortStackOverflow")) Module["abortStackOverflow"] = function() { abort("'abortStackOverflow' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5707if (!Object.getOwnPropertyDescriptor(Module, "reallyNegative")) Module["reallyNegative"] = function() { abort("'reallyNegative' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5708if (!Object.getOwnPropertyDescriptor(Module, "formatString")) Module["formatString"] = function() { abort("'formatString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5709if (!Object.getOwnPropertyDescriptor(Module, "PATH")) Module["PATH"] = function() { abort("'PATH' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5710if (!Object.getOwnPropertyDescriptor(Module, "PATH_FS")) Module["PATH_FS"] = function() { abort("'PATH_FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5711if (!Object.getOwnPropertyDescriptor(Module, "SYSCALLS")) Module["SYSCALLS"] = function() { abort("'SYSCALLS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5712if (!Object.getOwnPropertyDescriptor(Module, "syscallMmap2")) Module["syscallMmap2"] = function() { abort("'syscallMmap2' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5713if (!Object.getOwnPropertyDescriptor(Module, "syscallMunmap")) Module["syscallMunmap"] = function() { abort("'syscallMunmap' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5714if (!Object.getOwnPropertyDescriptor(Module, "JSEvents")) Module["JSEvents"] = function() { abort("'JSEvents' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5715if (!Object.getOwnPropertyDescriptor(Module, "specialHTMLTargets")) Module["specialHTMLTargets"] = function() { abort("'specialHTMLTargets' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5716if (!Object.getOwnPropertyDescriptor(Module, "demangle")) Module["demangle"] = function() { abort("'demangle' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5717if (!Object.getOwnPropertyDescriptor(Module, "demangleAll")) Module["demangleAll"] = function() { abort("'demangleAll' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5718if (!Object.getOwnPropertyDescriptor(Module, "jsStackTrace")) Module["jsStackTrace"] = function() { abort("'jsStackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5719if (!Object.getOwnPropertyDescriptor(Module, "stackTrace")) Module["stackTrace"] = function() { abort("'stackTrace' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5720if (!Object.getOwnPropertyDescriptor(Module, "getEnvStrings")) Module["getEnvStrings"] = function() { abort("'getEnvStrings' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5721if (!Object.getOwnPropertyDescriptor(Module, "checkWasiClock")) Module["checkWasiClock"] = function() { abort("'checkWasiClock' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5722if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64")) Module["writeI53ToI64"] = function() { abort("'writeI53ToI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5723if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Clamped")) Module["writeI53ToI64Clamped"] = function() { abort("'writeI53ToI64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5724if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToI64Signaling")) Module["writeI53ToI64Signaling"] = function() { abort("'writeI53ToI64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5725if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Clamped")) Module["writeI53ToU64Clamped"] = function() { abort("'writeI53ToU64Clamped' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5726if (!Object.getOwnPropertyDescriptor(Module, "writeI53ToU64Signaling")) Module["writeI53ToU64Signaling"] = function() { abort("'writeI53ToU64Signaling' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5727if (!Object.getOwnPropertyDescriptor(Module, "readI53FromI64")) Module["readI53FromI64"] = function() { abort("'readI53FromI64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5728if (!Object.getOwnPropertyDescriptor(Module, "readI53FromU64")) Module["readI53FromU64"] = function() { abort("'readI53FromU64' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5729if (!Object.getOwnPropertyDescriptor(Module, "convertI32PairToI53")) Module["convertI32PairToI53"] = function() { abort("'convertI32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5730if (!Object.getOwnPropertyDescriptor(Module, "convertU32PairToI53")) Module["convertU32PairToI53"] = function() { abort("'convertU32PairToI53' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5731if (!Object.getOwnPropertyDescriptor(Module, "Browser")) Module["Browser"] = function() { abort("'Browser' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5732if (!Object.getOwnPropertyDescriptor(Module, "FS")) Module["FS"] = function() { abort("'FS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5733if (!Object.getOwnPropertyDescriptor(Module, "MEMFS")) Module["MEMFS"] = function() { abort("'MEMFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5734if (!Object.getOwnPropertyDescriptor(Module, "TTY")) Module["TTY"] = function() { abort("'TTY' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5735if (!Object.getOwnPropertyDescriptor(Module, "PIPEFS")) Module["PIPEFS"] = function() { abort("'PIPEFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5736if (!Object.getOwnPropertyDescriptor(Module, "SOCKFS")) Module["SOCKFS"] = function() { abort("'SOCKFS' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5737if (!Object.getOwnPropertyDescriptor(Module, "GL")) Module["GL"] = function() { abort("'GL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5738if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGet")) Module["emscriptenWebGLGet"] = function() { abort("'emscriptenWebGLGet' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5739if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetTexPixelData")) Module["emscriptenWebGLGetTexPixelData"] = function() { abort("'emscriptenWebGLGetTexPixelData' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5740if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetUniform")) Module["emscriptenWebGLGetUniform"] = function() { abort("'emscriptenWebGLGetUniform' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5741if (!Object.getOwnPropertyDescriptor(Module, "emscriptenWebGLGetVertexAttrib")) Module["emscriptenWebGLGetVertexAttrib"] = function() { abort("'emscriptenWebGLGetVertexAttrib' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5742if (!Object.getOwnPropertyDescriptor(Module, "writeGLArray")) Module["writeGLArray"] = function() { abort("'writeGLArray' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5743if (!Object.getOwnPropertyDescriptor(Module, "AL")) Module["AL"] = function() { abort("'AL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5744if (!Object.getOwnPropertyDescriptor(Module, "SDL_unicode")) Module["SDL_unicode"] = function() { abort("'SDL_unicode' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5745if (!Object.getOwnPropertyDescriptor(Module, "SDL_ttfContext")) Module["SDL_ttfContext"] = function() { abort("'SDL_ttfContext' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5746if (!Object.getOwnPropertyDescriptor(Module, "SDL_audio")) Module["SDL_audio"] = function() { abort("'SDL_audio' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5747if (!Object.getOwnPropertyDescriptor(Module, "SDL")) Module["SDL"] = function() { abort("'SDL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5748if (!Object.getOwnPropertyDescriptor(Module, "SDL_gfx")) Module["SDL_gfx"] = function() { abort("'SDL_gfx' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5749if (!Object.getOwnPropertyDescriptor(Module, "GLUT")) Module["GLUT"] = function() { abort("'GLUT' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5750if (!Object.getOwnPropertyDescriptor(Module, "EGL")) Module["EGL"] = function() { abort("'EGL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5751if (!Object.getOwnPropertyDescriptor(Module, "GLFW_Window")) Module["GLFW_Window"] = function() { abort("'GLFW_Window' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5752if (!Object.getOwnPropertyDescriptor(Module, "GLFW")) Module["GLFW"] = function() { abort("'GLFW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5753if (!Object.getOwnPropertyDescriptor(Module, "GLEW")) Module["GLEW"] = function() { abort("'GLEW' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5754if (!Object.getOwnPropertyDescriptor(Module, "IDBStore")) Module["IDBStore"] = function() { abort("'IDBStore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5755if (!Object.getOwnPropertyDescriptor(Module, "runAndAbortIfError")) Module["runAndAbortIfError"] = function() { abort("'runAndAbortIfError' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5756if (!Object.getOwnPropertyDescriptor(Module, "warnOnce")) Module["warnOnce"] = function() { abort("'warnOnce' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5757if (!Object.getOwnPropertyDescriptor(Module, "stackSave")) Module["stackSave"] = function() { abort("'stackSave' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5758if (!Object.getOwnPropertyDescriptor(Module, "stackRestore")) Module["stackRestore"] = function() { abort("'stackRestore' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5759if (!Object.getOwnPropertyDescriptor(Module, "stackAlloc")) Module["stackAlloc"] = function() { abort("'stackAlloc' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5760if (!Object.getOwnPropertyDescriptor(Module, "AsciiToString")) Module["AsciiToString"] = function() { abort("'AsciiToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5761if (!Object.getOwnPropertyDescriptor(Module, "stringToAscii")) Module["stringToAscii"] = function() { abort("'stringToAscii' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5762if (!Object.getOwnPropertyDescriptor(Module, "UTF16ToString")) Module["UTF16ToString"] = function() { abort("'UTF16ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5763if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF16")) Module["stringToUTF16"] = function() { abort("'stringToUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5764if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF16")) Module["lengthBytesUTF16"] = function() { abort("'lengthBytesUTF16' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5765if (!Object.getOwnPropertyDescriptor(Module, "UTF32ToString")) Module["UTF32ToString"] = function() { abort("'UTF32ToString' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5766if (!Object.getOwnPropertyDescriptor(Module, "stringToUTF32")) Module["stringToUTF32"] = function() { abort("'stringToUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5767if (!Object.getOwnPropertyDescriptor(Module, "lengthBytesUTF32")) Module["lengthBytesUTF32"] = function() { abort("'lengthBytesUTF32' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5768if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8")) Module["allocateUTF8"] = function() { abort("'allocateUTF8' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5769if (!Object.getOwnPropertyDescriptor(Module, "allocateUTF8OnStack")) Module["allocateUTF8OnStack"] = function() { abort("'allocateUTF8OnStack' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") };
5770Module["writeStackCookie"] = writeStackCookie;
5771Module["checkStackCookie"] = checkStackCookie;if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_NORMAL")) Object.defineProperty(Module, "ALLOC_NORMAL", { configurable: true, get: function() { abort("'ALLOC_NORMAL' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
5772if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_STACK")) Object.defineProperty(Module, "ALLOC_STACK", { configurable: true, get: function() { abort("'ALLOC_STACK' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
5773if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_DYNAMIC")) Object.defineProperty(Module, "ALLOC_DYNAMIC", { configurable: true, get: function() { abort("'ALLOC_DYNAMIC' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
5774if (!Object.getOwnPropertyDescriptor(Module, "ALLOC_NONE")) Object.defineProperty(Module, "ALLOC_NONE", { configurable: true, get: function() { abort("'ALLOC_NONE' was not exported. add it to EXTRA_EXPORTED_RUNTIME_METHODS (see the FAQ)") } });
5775
5776
5777
5778var calledRun;
5779
5780/**
5781 * @constructor
5782 * @this {ExitStatus}
5783 */
5784function ExitStatus(status) {
5785 this.name = "ExitStatus";
5786 this.message = "Program terminated with exit(" + status + ")";
5787 this.status = status;
5788}
5789
5790var calledMain = false;
5791
5792
5793dependenciesFulfilled = function runCaller() {
5794 // If run has never been called, and we should call run (INVOKE_RUN is true, and Module.noInitialRun is not false)
5795 if (!calledRun) run();
5796 if (!calledRun) dependenciesFulfilled = runCaller; // try this again later, after new deps are fulfilled
5797};
5798
5799function callMain(args) {
5800 assert(runDependencies == 0, 'cannot call main when async dependencies remain! (listen on Module["onRuntimeInitialized"])');
5801 assert(__ATPRERUN__.length == 0, 'cannot call main when preRun functions remain to be called');
5802
5803 var entryFunction = Module['_main'];
5804
5805
5806 args = args || [];
5807
5808 var argc = args.length+1;
5809 var argv = stackAlloc((argc + 1) * 4);
5810 HEAP32[argv >> 2] = allocateUTF8OnStack(thisProgram);
5811 for (var i = 1; i < argc; i++) {
5812 HEAP32[(argv >> 2) + i] = allocateUTF8OnStack(args[i - 1]);
5813 }
5814 HEAP32[(argv >> 2) + argc] = 0;
5815
5816 try {
5817
5818 Module['___set_stack_limit'](STACK_MAX);
5819
5820 var ret = entryFunction(argc, argv);
5821
5822
5823 // In PROXY_TO_PTHREAD builds, we should never exit the runtime below, as execution is asynchronously handed
5824 // off to a pthread.
5825 // if we're not running an evented main loop, it's time to exit
5826 exit(ret, /* implicit = */ true);
5827 }
5828 catch(e) {
5829 if (e instanceof ExitStatus) {
5830 // exit() throws this once it's done to make sure execution
5831 // has been stopped completely
5832 return;
5833 } else if (e == 'unwind') {
5834 // running an evented main loop, don't immediately exit
5835 noExitRuntime = true;
5836 return;
5837 } else {
5838 var toLog = e;
5839 if (e && typeof e === 'object' && e.stack) {
5840 toLog = [e, e.stack];
5841 }
5842 err('exception thrown: ' + toLog);
5843 quit_(1, e);
5844 }
5845 } finally {
5846 calledMain = true;
5847 }
5848}
5849
5850
5851
5852
5853/** @type {function(Array=)} */
5854function run(args) {
5855 args = args || arguments_;
5856
5857 if (runDependencies > 0) {
5858 return;
5859 }
5860
5861 writeStackCookie();
5862
5863 preRun();
5864
5865 if (runDependencies > 0) return; // a preRun added a dependency, run will be called later
5866
5867 function doRun() {
5868 // run may have just been called through dependencies being fulfilled just in this very frame,
5869 // or while the async setStatus time below was happening
5870 if (calledRun) return;
5871 calledRun = true;
5872 Module['calledRun'] = true;
5873
5874 if (ABORT) return;
5875
5876 initRuntime();
5877
5878 preMain();
5879
5880 if (Module['onRuntimeInitialized']) Module['onRuntimeInitialized']();
5881
5882 if (shouldRunNow) callMain(args);
5883
5884 postRun();
5885 }
5886
5887 if (Module['setStatus']) {
5888 Module['setStatus']('Running...');
5889 setTimeout(function() {
5890 setTimeout(function() {
5891 Module['setStatus']('');
5892 }, 1);
5893 doRun();
5894 }, 1);
5895 } else
5896 {
5897 doRun();
5898 }
5899 checkStackCookie();
5900}
5901Module['run'] = run;
5902
5903function checkUnflushedContent() {
5904 // Compiler settings do not allow exiting the runtime, so flushing
5905 // the streams is not possible. but in ASSERTIONS mode we check
5906 // if there was something to flush, and if so tell the user they
5907 // should request that the runtime be exitable.
5908 // Normally we would not even include flush() at all, but in ASSERTIONS
5909 // builds we do so just for this check, and here we see if there is any
5910 // content to flush, that is, we check if there would have been
5911 // something a non-ASSERTIONS build would have not seen.
5912 // How we flush the streams depends on whether we are in SYSCALLS_REQUIRE_FILESYSTEM=0
5913 // mode (which has its own special function for this; otherwise, all
5914 // the code is inside libc)
5915 var print = out;
5916 var printErr = err;
5917 var has = false;
5918 out = err = function(x) {
5919 has = true;
5920 }
5921 try { // it doesn't matter if it fails
5922 var flush = Module['_fflush'];
5923 if (flush) flush(0);
5924 // also flush in the JS FS layer
5925 ['stdout', 'stderr'].forEach(function(name) {
5926 var info = FS.analyzePath('/dev/' + name);
5927 if (!info) return;
5928 var stream = info.object;
5929 var rdev = stream.rdev;
5930 var tty = TTY.ttys[rdev];
5931 if (tty && tty.output && tty.output.length) {
5932 has = true;
5933 }
5934 });
5935 } catch(e) {}
5936 out = print;
5937 err = printErr;
5938 if (has) {
5939 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.');
5940 }
5941}
5942
5943/** @param {boolean|number=} implicit */
5944function exit(status, implicit) {
5945 checkUnflushedContent();
5946
5947 // if this is just main exit-ing implicitly, and the status is 0, then we
5948 // don't need to do anything here and can just leave. if the status is
5949 // non-zero, though, then we need to report it.
5950 // (we may have warned about this earlier, if a situation justifies doing so)
5951 if (implicit && noExitRuntime && status === 0) {
5952 return;
5953 }
5954
5955 if (noExitRuntime) {
5956 // if exit() was called, we may warn the user if the runtime isn't actually being shut down
5957 if (!implicit) {
5958 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)';
5959 err(msg);
5960 }
5961 } else {
5962
5963 ABORT = true;
5964 EXITSTATUS = status;
5965
5966 exitRuntime();
5967
5968 if (Module['onExit']) Module['onExit'](status);
5969 }
5970
5971 quit_(status, new ExitStatus(status));
5972}
5973
5974if (Module['preInit']) {
5975 if (typeof Module['preInit'] == 'function') Module['preInit'] = [Module['preInit']];
5976 while (Module['preInit'].length > 0) {
5977 Module['preInit'].pop()();
5978 }
5979}
5980
5981// shouldRunNow refers to calling main(), not run().
5982var shouldRunNow = true;
5983
5984if (Module['noInitialRun']) shouldRunNow = false;
5985
5986
5987 noExitRuntime = true;
5988
5989run();
5990
5991
5992
5993
5994
5995
5996// {{MODULE_ADDITIONS}}
5997
5998
5999
6000};
6001
Note: See TracBrowser for help on using the repository browser.