1 // The Module object: Our interface to the outside world. We import
2 // and export values on it, and do the work to get that through
3 // closure compiler if necessary. There are various ways Module can be used:
4 // 1. Not defined. We create it here
5 // 2. A function parameter, function(Module) { ..generated code.. }
6 // 3. pre-run appended it, var Module = {}; ..generated code..
7 // 4. External script tag defines var Module.
8 // We need to do an eval in order to handle the closure compiler
9 // case, where this code here is minified but Module was defined
10 // elsewhere (e.g. case 4 above). We also need to check if Module
11 // already exists (e.g. case 3 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.
17 if (!Module) Module = eval('(function() { try { return Module || {} } catch(e) { return {} } })()');
19 // Sometimes an existing Module object exists with properties
20 // meant to overwrite the default module functionality. Here
21 // we collect those properties and reapply _after_ we configure
22 // the current environment's defaults to avoid having to be so
23 // defensive during initialization.
24 var moduleOverrides = {};
25 for (var key in Module) {
26 if (Module.hasOwnProperty(key)) {
27 moduleOverrides[key] = Module[key];
31 // The environment setup code below is customized to use Module.
32 // *** Environment setup code ***
33 var ENVIRONMENT_IS_NODE = typeof process === 'object' && typeof require === 'function';
34 var ENVIRONMENT_IS_WEB = typeof window === 'object';
35 var ENVIRONMENT_IS_WORKER = typeof importScripts === 'function';
36 var ENVIRONMENT_IS_SHELL = !ENVIRONMENT_IS_WEB && !ENVIRONMENT_IS_NODE && !ENVIRONMENT_IS_WORKER;
38 if (ENVIRONMENT_IS_NODE) {
39 // Expose functionality in the same simple way that the shells work
40 // Note that we pollute the global namespace here, otherwise we break in node
41 if (!Module['print']) Module['print'] = function print(x) {
42 process['stdout'].write(x + '\n');
44 if (!Module['printErr']) Module['printErr'] = function printErr(x) {
45 process['stderr'].write(x + '\n');
48 var nodeFS = require('fs');
49 var nodePath = require('path');
51 Module['read'] = function read(filename, binary) {
52 filename = nodePath['normalize'](filename);
53 var ret = nodeFS['readFileSync'](filename);
54 // The path is absolute if the normalized version is the same as the resolved.
55 if (!ret && filename != nodePath['resolve'](filename)) {
56 filename = path.join(__dirname, '..', 'src', filename);
57 ret = nodeFS['readFileSync'](filename);
59 if (ret && !binary) ret = ret.toString();
63 Module['readBinary'] = function readBinary(filename) { return Module['read'](filename, true) };
65 Module['load'] = function load(f) {
69 Module['arguments'] = process['argv'].slice(2);
71 module['exports'] = Module;
73 else if (ENVIRONMENT_IS_SHELL) {
74 if (!Module['print']) Module['print'] = print;
75 if (typeof printErr != 'undefined') Module['printErr'] = printErr; // not present in v8 or older sm
77 if (typeof read != 'undefined') {
78 Module['read'] = read;
80 Module['read'] = function read() { throw 'no read() available (jsc?)' };
83 Module['readBinary'] = function readBinary(f) {
84 return read(f, 'binary');
87 if (typeof scriptArgs != 'undefined') {
88 Module['arguments'] = scriptArgs;
89 } else if (typeof arguments != 'undefined') {
90 Module['arguments'] = arguments;
93 this['Module'] = Module;
95 eval("if (typeof gc === 'function' && gc.toString().indexOf('[native code]') > 0) var gc = undefined"); // wipe out the SpiderMonkey shell 'gc' function, which can confuse closure (uses it as a minified name, and it is then initted to a non-falsey value unexpectedly)
97 else if (ENVIRONMENT_IS_WEB || ENVIRONMENT_IS_WORKER) {
98 Module['read'] = function read(url) {
99 var xhr = new XMLHttpRequest();
100 xhr.open('GET', url, false);
102 return xhr.responseText;
105 if (typeof arguments != 'undefined') {
106 Module['arguments'] = arguments;
109 if (typeof console !== 'undefined') {
110 if (!Module['print']) Module['print'] = function print(x) {
113 if (!Module['printErr']) Module['printErr'] = function printErr(x) {
117 // Probably a worker, and without console.log. We can do very little here...
118 var TRY_USE_DUMP = false;
119 if (!Module['print']) Module['print'] = (TRY_USE_DUMP && (typeof(dump) !== "undefined") ? (function(x) {
122 // self.postMessage(x); // enable this if you want stdout to be sent as messages
126 if (ENVIRONMENT_IS_WEB) {
127 this['Module'] = Module;
129 Module['load'] = importScripts;
133 // Unreachable because SHELL is dependant on the others
134 throw 'Unknown runtime environment. Where are we?';
137 function globalEval(x) {
140 if (!Module['load'] == 'undefined' && Module['read']) {
141 Module['load'] = function load(f) {
142 globalEval(Module['read'](f));
145 if (!Module['print']) {
146 Module['print'] = function(){};
148 if (!Module['printErr']) {
149 Module['printErr'] = Module['print'];
151 if (!Module['arguments']) {
152 Module['arguments'] = [];
154 // *** Environment setup code ***
157 Module.print = Module['print'];
158 Module.printErr = Module['printErr'];
161 Module['preRun'] = [];
162 Module['postRun'] = [];
164 // Merge back in the overrides
165 for (var key in moduleOverrides) {
166 if (moduleOverrides.hasOwnProperty(key)) {
167 Module[key] = moduleOverrides[key];
173 // === Auto-generated preamble library stuff ===
175 //========================================
176 // Runtime code shared with compiler
177 //========================================
180 stackSave: function () {
183 stackRestore: function (stackTop) {
186 forceAlign: function (target, quantum) {
187 quantum = quantum || 4;
188 if (quantum == 1) return target;
189 if (isNumber(target) && isNumber(quantum)) {
190 return Math.ceil(target/quantum)*quantum;
191 } else if (isNumber(quantum) && isPowerOfTwo(quantum)) {
192 return '(((' +target + ')+' + (quantum-1) + ')&' + -quantum + ')';
194 return 'Math.ceil((' + target + ')/' + quantum + ')*' + quantum;
196 isNumberType: function (type) {
197 return type in Runtime.INT_TYPES || type in Runtime.FLOAT_TYPES;
199 isPointerType: function isPointerType(type) {
200 return type[type.length-1] == '*';
202 isStructType: function isStructType(type) {
203 if (isPointerType(type)) return false;
204 if (isArrayType(type)) return true;
205 if (/<?\{ ?[^}]* ?\}>?/.test(type)) return true; // { i32, i8 } etc. - anonymous struct types
206 // See comment in isStructPointerType()
207 return type[0] == '%';
209 INT_TYPES: {"i1":0,"i8":0,"i16":0,"i32":0,"i64":0},
210 FLOAT_TYPES: {"float":0,"double":0},
211 or64: function (x, y) {
212 var l = (x | 0) | (y | 0);
213 var h = (Math.round(x / 4294967296) | Math.round(y / 4294967296)) * 4294967296;
216 and64: function (x, y) {
217 var l = (x | 0) & (y | 0);
218 var h = (Math.round(x / 4294967296) & Math.round(y / 4294967296)) * 4294967296;
221 xor64: function (x, y) {
222 var l = (x | 0) ^ (y | 0);
223 var h = (Math.round(x / 4294967296) ^ Math.round(y / 4294967296)) * 4294967296;
226 getNativeTypeSize: function (type) {
228 case 'i1': case 'i8': return 1;
229 case 'i16': return 2;
230 case 'i32': return 4;
231 case 'i64': return 8;
232 case 'float': return 4;
233 case 'double': return 8;
235 if (type[type.length-1] === '*') {
236 return Runtime.QUANTUM_SIZE; // A pointer
237 } else if (type[0] === 'i') {
238 var bits = parseInt(type.substr(1));
239 assert(bits % 8 === 0);
247 getNativeFieldSize: function (type) {
248 return Math.max(Runtime.getNativeTypeSize(type), Runtime.QUANTUM_SIZE);
250 dedup: function dedup(items, ident) {
253 return items.filter(function(item) {
254 if (seen[item[ident]]) return false;
255 seen[item[ident]] = true;
259 return items.filter(function(item) {
260 if (seen[item]) return false;
266 set: function set() {
267 var args = typeof arguments[0] === 'object' ? arguments[0] : arguments;
269 for (var i = 0; i < args.length; i++) {
275 getAlignSize: function (type, size, vararg) {
276 // we align i64s and doubles on 64-bit boundaries, unlike x86
277 if (!vararg && (type == 'i64' || type == 'double')) return 8;
278 if (!type) return Math.min(size, 8); // align structures internally to 64 bits
279 return Math.min(size || (type ? Runtime.getNativeFieldSize(type) : 0), Runtime.QUANTUM_SIZE);
281 calculateStructAlignment: function calculateStructAlignment(type) {
287 type.flatIndexes = type.fields.map(function(field) {
290 if (Runtime.isNumberType(field) || Runtime.isPointerType(field)) {
291 size = Runtime.getNativeTypeSize(field); // pack char; char; in structs, also char[X]s.
292 alignSize = Runtime.getAlignSize(field, size);
293 } else if (Runtime.isStructType(field)) {
294 if (field[1] === '0') {
295 // this is [0 x something]. When inside another structure like here, it must be at the end,
296 // and it adds no size
297 // XXX this happens in java-nbody for example... assert(index === type.fields.length, 'zero-length in the middle!');
299 if (Types.types[field]) {
300 alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
302 alignSize = type.alignSize || QUANTUM_SIZE;
305 size = Types.types[field].flatSize;
306 alignSize = Runtime.getAlignSize(null, Types.types[field].alignSize);
308 } else if (field[0] == 'b') {
309 // bN, large number field, like a [N x i8]
310 size = field.substr(1)|0;
312 } else if (field[0] === '<') {
314 size = alignSize = Types.types[field].flatSize; // fully aligned
315 } else if (field[0] === 'i') {
316 // illegal integer field, that could not be legalized because it is an internal structure field
317 // it is ok to have such fields, if we just use them as markers of field size and nothing more complex
318 size = alignSize = parseInt(field.substr(1))/8;
319 assert(size % 1 === 0, 'cannot handle non-byte-size field ' + field);
321 assert(false, 'invalid type for calculateStructAlignment');
323 if (type.packed) alignSize = 1;
324 type.alignSize = Math.max(type.alignSize, alignSize);
325 var curr = Runtime.alignMemory(type.flatSize, alignSize); // if necessary, place this on aligned memory
326 type.flatSize = curr + size;
328 diffs.push(curr-prev);
333 if (type.name_ && type.name_[0] === '[') {
334 // arrays have 2 elements, so we get the proper difference. then we scale here. that way we avoid
335 // allocating a potentially huge array for [999999 x i8] etc.
336 type.flatSize = parseInt(type.name_.substr(1))*type.flatSize/2;
338 type.flatSize = Runtime.alignMemory(type.flatSize, type.alignSize);
339 if (diffs.length == 0) {
340 type.flatFactor = type.flatSize;
341 } else if (Runtime.dedup(diffs).length == 1) {
342 type.flatFactor = diffs[0];
344 type.needsFlattening = (type.flatFactor != 1);
345 return type.flatIndexes;
347 generateStructInfo: function (struct, typeName, offset) {
350 offset = offset || 0;
351 type = (typeof Types === 'undefined' ? Runtime.typeInfo : Types.types)[typeName];
352 if (!type) return null;
353 if (type.fields.length != struct.length) {
354 printErr('Number of named fields must match the type for ' + typeName + ': possibly duplicate struct names. Cannot return structInfo');
357 alignment = type.flatIndexes;
359 var type = { fields: struct.map(function(item) { return item[0] }) };
360 alignment = Runtime.calculateStructAlignment(type);
363 __size__: type.flatSize
366 struct.forEach(function(item, i) {
367 if (typeof item === 'string') {
368 ret[item] = alignment[i] + offset;
372 for (var k in item) key = k;
373 ret[key] = Runtime.generateStructInfo(item[key], type.fields[i], alignment[i]);
377 struct.forEach(function(item, i) {
378 ret[item[1]] = alignment[i];
383 dynCall: function (sig, ptr, args) {
384 if (args && args.length) {
385 if (!args.splice) args = Array.prototype.slice.call(args);
386 args.splice(0, 0, ptr);
387 return Module['dynCall_' + sig].apply(null, args);
389 return Module['dynCall_' + sig].call(null, ptr);
392 functionPointers: [],
393 addFunction: function (func) {
394 for (var i = 0; i < Runtime.functionPointers.length; i++) {
395 if (!Runtime.functionPointers[i]) {
396 Runtime.functionPointers[i] = func;
400 throw 'Finished up all reserved function pointers. Use a higher value for RESERVED_FUNCTION_POINTERS.';
402 removeFunction: function (index) {
403 Runtime.functionPointers[(index-2)/2] = null;
405 getAsmConst: function (code, numArgs) {
406 // code is a constant string on the heap, so we can cache these
407 if (!Runtime.asmConstCache) Runtime.asmConstCache = {};
408 var func = Runtime.asmConstCache[code];
409 if (func) return func;
411 for (var i = 0; i < numArgs; i++) {
412 args.push(String.fromCharCode(36) + i); // $0, $1 etc
414 code = Pointer_stringify(code);
415 if (code[0] === '"') {
416 // tolerate EM_ASM("..code..") even though EM_ASM(..code..) is correct
417 if (code.indexOf('"', 1) === code.length-1) {
418 code = code.substr(1, code.length-2);
420 // something invalid happened, e.g. EM_ASM("..code($0)..", input)
421 abort('invalid EM_ASM input |' + code + '|. Please use EM_ASM(..code..) (no quotes) or EM_ASM({ ..code($0).. }, input) (to input values)');
424 return Runtime.asmConstCache[code] = eval('(function(' + args.join(',') + '){ ' + code + ' })'); // new Function does not allow upvars in node
426 warnOnce: function (text) {
427 if (!Runtime.warnOnce.shown) Runtime.warnOnce.shown = {};
428 if (!Runtime.warnOnce.shown[text]) {
429 Runtime.warnOnce.shown[text] = 1;
430 Module.printErr(text);
434 getFuncWrapper: function (func, sig) {
436 if (!Runtime.funcWrappers[func]) {
437 Runtime.funcWrappers[func] = function dynCall_wrapper() {
438 return Runtime.dynCall(sig, func, arguments);
441 return Runtime.funcWrappers[func];
443 UTF8Processor: function () {
446 this.processCChar = function (code) {
449 if (buffer.length == 0) {
450 if ((code & 0x80) == 0x00) { // 0xxxxxxx
451 return String.fromCharCode(code);
454 if ((code & 0xE0) == 0xC0) { // 110xxxxx
456 } else if ((code & 0xF0) == 0xE0) { // 1110xxxx
467 if (needed > 0) return '';
475 if (buffer.length == 2) {
476 ret = String.fromCharCode(((c1 & 0x1F) << 6) | (c2 & 0x3F));
477 } else if (buffer.length == 3) {
478 ret = String.fromCharCode(((c1 & 0x0F) << 12) | ((c2 & 0x3F) << 6) | (c3 & 0x3F));
480 // http://mathiasbynens.be/notes/javascript-encoding#surrogate-formulae
481 var codePoint = ((c1 & 0x07) << 18) | ((c2 & 0x3F) << 12) |
482 ((c3 & 0x3F) << 6) | (c4 & 0x3F);
483 ret = String.fromCharCode(
484 Math.floor((codePoint - 0x10000) / 0x400) + 0xD800,
485 (codePoint - 0x10000) % 0x400 + 0xDC00);
490 this.processJSString = function processJSString(string) {
491 string = unescape(encodeURIComponent(string));
493 for (var i = 0; i < string.length; i++) {
494 ret.push(string.charCodeAt(i));
499 getCompilerSetting: function (name) {
500 throw 'You must build with -s RETAIN_COMPILER_SETTINGS=1 for Runtime.getCompilerSetting or emscripten_get_compiler_setting to work';
502 stackAlloc: function (size) { var ret = STACKTOP;STACKTOP = (STACKTOP + size)|0;STACKTOP = (((STACKTOP)+7)&-8); return ret; },
503 staticAlloc: function (size) { var ret = STATICTOP;STATICTOP = (STATICTOP + size)|0;STATICTOP = (((STATICTOP)+7)&-8); return ret; },
504 dynamicAlloc: function (size) { var ret = DYNAMICTOP;DYNAMICTOP = (DYNAMICTOP + size)|0;DYNAMICTOP = (((DYNAMICTOP)+7)&-8); if (DYNAMICTOP >= TOTAL_MEMORY) enlargeMemory();; return ret; },
505 alignMemory: function (size,quantum) { var ret = size = Math.ceil((size)/(quantum ? quantum : 8))*(quantum ? quantum : 8); return ret; },
506 makeBigInt: function (low,high,unsigned) { var ret = (unsigned ? ((+((low>>>0)))+((+((high>>>0)))*(+4294967296))) : ((+((low>>>0)))+((+((high|0)))*(+4294967296)))); return ret; },
513 Module['Runtime'] = Runtime;
523 //========================================
524 // Runtime essentials
525 //========================================
527 var __THREW__ = 0; // Used in checking for thrown exceptions.
529 var ABORT = false; // whether we are quitting the application. no code should run after this. set in exit() and abort()
533 // tempInt is used for 32-bit signed values or smaller. tempBigInt is used
534 // for 32-bit unsigned values or more than 32 bits. TODO: audit all uses of tempInt
535 var tempValue, tempInt, tempBigInt, tempInt2, tempBigInt2, tempPair, tempBigIntI, tempBigIntR, tempBigIntS, tempBigIntP, tempBigIntD, tempDouble, tempFloat;
536 var tempI64, tempI64b;
537 var tempRet0, tempRet1, tempRet2, tempRet3, tempRet4, tempRet5, tempRet6, tempRet7, tempRet8, tempRet9;
539 function assert(condition, text) {
541 abort('Assertion failed: ' + text);
545 var globalScope = this;
547 // C calling interface. A convenient way to call C functions (in C files, or
548 // defined with extern "C").
550 // Note: LLVM optimizations can inline and remove functions, after which you will not be
551 // able to call them. Closure can also do so. To avoid that, add your function to
552 // the exports using something like
554 // -s EXPORTED_FUNCTIONS='["_main", "_myfunc"]'
556 // @param ident The name of the C function (note that C++ functions will be name-mangled - use extern "C")
557 // @param returnType The return type of the function, one of the JS types 'number', 'string' or 'array' (use 'number' for any C pointer, and
558 // 'array' for JavaScript arrays and typed arrays; note that arrays are 8-bit).
559 // @param argTypes An array of the types of arguments for the function (if there are no arguments, this can be ommitted). Types are as in returnType,
560 // except that 'array' is not possible (there is no way for us to know the length of the array)
561 // @param args An array of the arguments to the function, as native JS values (as in returnType)
562 // Note that string arguments will be stored on the stack (the JS string will become a C string on the stack).
563 // @return The return value, as a native JS value (as in returnType)
564 function ccall(ident, returnType, argTypes, args) {
565 return ccallFunc(getCFunc(ident), returnType, argTypes, args);
567 Module["ccall"] = ccall;
569 // Returns the C function with a specified identifier (for C++, you need to do manual name mangling)
570 function getCFunc(ident) {
572 var func = Module['_' + ident]; // closure exported function
573 if (!func) func = eval('_' + ident); // explicit lookup
576 assert(func, 'Cannot call unknown function ' + ident + ' (perhaps LLVM optimizations or closure removed it?)');
580 // Internal function that does a C call using a function, not an identifier
581 function ccallFunc(func, returnType, argTypes, args) {
583 function toC(value, type) {
584 if (type == 'string') {
585 if (value === null || value === undefined || value === 0) return 0; // null string
586 value = intArrayFromString(value);
589 if (type == 'array') {
590 if (!stack) stack = Runtime.stackSave();
591 var ret = Runtime.stackAlloc(value.length);
592 writeArrayToMemory(value, ret);
597 function fromC(value, type) {
598 if (type == 'string') {
599 return Pointer_stringify(value);
601 assert(type != 'array');
605 var cArgs = args ? args.map(function(arg) {
606 return toC(arg, argTypes[i++]);
608 var ret = fromC(func.apply(null, cArgs), returnType);
609 if (stack) Runtime.stackRestore(stack);
613 // Returns a native JS wrapper for a C function. This is similar to ccall, but
614 // returns a function you can call repeatedly in a normal way. For example:
616 // var my_function = cwrap('my_c_function', 'number', ['number', 'number']);
617 // alert(my_function(5, 22));
618 // alert(my_function(99, 12));
620 function cwrap(ident, returnType, argTypes) {
621 var func = getCFunc(ident);
623 return ccallFunc(func, returnType, argTypes, Array.prototype.slice.call(arguments));
626 Module["cwrap"] = cwrap;
628 // Sets a value in memory in a dynamic way at run-time. Uses the
629 // type data. This is the same as makeSetValue, except that
630 // makeSetValue is done at compile-time and generates the needed
631 // code then, whereas this function picks the right code at
633 // Note that setValue and getValue only do *aligned* writes and reads!
634 // Note that ccall uses JS types as for defining types, while setValue and
635 // getValue need LLVM types ('i8', 'i32') - this is a lower-level operation
636 function setValue(ptr, value, type, noSafe) {
638 if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
640 case 'i1': HEAP8[(ptr)]=value; break;
641 case 'i8': HEAP8[(ptr)]=value; break;
642 case 'i16': HEAP16[((ptr)>>1)]=value; break;
643 case 'i32': HEAP32[((ptr)>>2)]=value; break;
644 case 'i64': (tempI64 = [value>>>0,(tempDouble=value,(+(Math_abs(tempDouble))) >= (+1) ? (tempDouble > (+0) ? ((Math_min((+(Math_floor((tempDouble)/(+4294967296)))), (+4294967295)))|0)>>>0 : (~~((+(Math_ceil((tempDouble - +(((~~(tempDouble)))>>>0))/(+4294967296))))))>>>0) : 0)],HEAP32[((ptr)>>2)]=tempI64[0],HEAP32[(((ptr)+(4))>>2)]=tempI64[1]); break;
645 case 'float': HEAPF32[((ptr)>>2)]=value; break;
646 case 'double': HEAPF64[((ptr)>>3)]=value; break;
647 default: abort('invalid type for setValue: ' + type);
650 Module['setValue'] = setValue;
652 // Parallel to setValue.
653 function getValue(ptr, type, noSafe) {
655 if (type.charAt(type.length-1) === '*') type = 'i32'; // pointers are 32-bit
657 case 'i1': return HEAP8[(ptr)];
658 case 'i8': return HEAP8[(ptr)];
659 case 'i16': return HEAP16[((ptr)>>1)];
660 case 'i32': return HEAP32[((ptr)>>2)];
661 case 'i64': return HEAP32[((ptr)>>2)];
662 case 'float': return HEAPF32[((ptr)>>2)];
663 case 'double': return HEAPF64[((ptr)>>3)];
664 default: abort('invalid type for setValue: ' + type);
668 Module['getValue'] = getValue;
670 var ALLOC_NORMAL = 0; // Tries to use _malloc()
671 var ALLOC_STACK = 1; // Lives for the duration of the current function call
672 var ALLOC_STATIC = 2; // Cannot be freed
673 var ALLOC_DYNAMIC = 3; // Cannot be freed except through sbrk
674 var ALLOC_NONE = 4; // Do not allocate
675 Module['ALLOC_NORMAL'] = ALLOC_NORMAL;
676 Module['ALLOC_STACK'] = ALLOC_STACK;
677 Module['ALLOC_STATIC'] = ALLOC_STATIC;
678 Module['ALLOC_DYNAMIC'] = ALLOC_DYNAMIC;
679 Module['ALLOC_NONE'] = ALLOC_NONE;
681 // allocate(): This is for internal use. You can use it yourself as well, but the interface
682 // is a little tricky (see docs right below). The reason is that it is optimized
683 // for multiple syntaxes to save space in generated code. So you should
684 // normally not use allocate(), and instead allocate memory using _malloc(),
685 // initialize it with setValue(), and so forth.
686 // @slab: An array of data, or a number. If a number, then the size of the block to allocate,
687 // in *bytes* (note that this is sometimes confusing: the next parameter does not
689 // @types: Either an array of types, one for each byte (or 0 if no type at that position),
690 // or a single type which is used for the entire block. This only matters if there
691 // is initial data - if @slab is a number, then this does not matter at all and is
693 // @allocator: How to allocate memory, see ALLOC_*
694 function allocate(slab, types, allocator, ptr) {
696 if (typeof slab === 'number') {
704 var singleType = typeof types === 'string' ? types : null;
707 if (allocator == ALLOC_NONE) {
710 ret = [_malloc, Runtime.stackAlloc, Runtime.staticAlloc, Runtime.dynamicAlloc][allocator === undefined ? ALLOC_STATIC : allocator](Math.max(size, singleType ? 1 : types.length));
715 assert((ret & 3) == 0);
716 stop = ret + (size & ~3);
717 for (; ptr < stop; ptr += 4) {
718 HEAP32[((ptr)>>2)]=0;
722 HEAP8[((ptr++)|0)]=0;
727 if (singleType === 'i8') {
728 if (slab.subarray || slab.slice) {
729 HEAPU8.set(slab, ret);
731 HEAPU8.set(new Uint8Array(slab), ret);
736 var i = 0, type, typeSize, previousType;
740 if (typeof curr === 'function') {
741 curr = Runtime.getFunctionIndex(curr);
744 type = singleType || types[i];
750 if (type == 'i64') type = 'i32'; // special case: we have one i32 here, and one i32 later
752 setValue(ret+i, curr, type);
754 // no need to look up size unless type changes, so cache it
755 if (previousType !== type) {
756 typeSize = Runtime.getNativeTypeSize(type);
764 Module['allocate'] = allocate;
766 function Pointer_stringify(ptr, /* optional */ length) {
767 // TODO: use TextDecoder
768 // Find the length, and check for UTF while doing so
773 t = HEAPU8[(((ptr)+(i))|0)];
774 if (t >= 128) hasUtf = true;
775 else if (t == 0 && !length) break;
777 if (length && i == length) break;
779 if (!length) length = i;
784 var MAX_CHUNK = 1024; // split up into chunks, because .apply on a huge string can overflow the stack
787 curr = String.fromCharCode.apply(String, HEAPU8.subarray(ptr, ptr + Math.min(length, MAX_CHUNK)));
788 ret = ret ? ret + curr : curr;
795 var utf8 = new Runtime.UTF8Processor();
796 for (i = 0; i < length; i++) {
797 t = HEAPU8[(((ptr)+(i))|0)];
798 ret += utf8.processCChar(t);
802 Module['Pointer_stringify'] = Pointer_stringify;
804 // Given a pointer 'ptr' to a null-terminated UTF16LE-encoded string in the emscripten HEAP, returns
805 // a copy of that string as a Javascript String object.
806 function UTF16ToString(ptr) {
811 var codeUnit = HEAP16[(((ptr)+(i*2))>>1)];
815 // fromCharCode constructs a character from a UTF-16 code unit, so we can pass the UTF16 string right through.
816 str += String.fromCharCode(codeUnit);
819 Module['UTF16ToString'] = UTF16ToString;
821 // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
822 // null-terminated and encoded in UTF16LE form. The copy will require at most (str.length*2+1)*2 bytes of space in the HEAP.
823 function stringToUTF16(str, outPtr) {
824 for(var i = 0; i < str.length; ++i) {
825 // charCodeAt returns a UTF-16 encoded code unit, so it can be directly written to the HEAP.
826 var codeUnit = str.charCodeAt(i); // possibly a lead surrogate
827 HEAP16[(((outPtr)+(i*2))>>1)]=codeUnit;
829 // Null-terminate the pointer to the HEAP.
830 HEAP16[(((outPtr)+(str.length*2))>>1)]=0;
832 Module['stringToUTF16'] = stringToUTF16;
834 // Given a pointer 'ptr' to a null-terminated UTF32LE-encoded string in the emscripten HEAP, returns
835 // a copy of that string as a Javascript String object.
836 function UTF32ToString(ptr) {
841 var utf32 = HEAP32[(((ptr)+(i*4))>>2)];
845 // 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.
846 if (utf32 >= 0x10000) {
847 var ch = utf32 - 0x10000;
848 str += String.fromCharCode(0xD800 | (ch >> 10), 0xDC00 | (ch & 0x3FF));
850 str += String.fromCharCode(utf32);
854 Module['UTF32ToString'] = UTF32ToString;
856 // Copies the given Javascript String object 'str' to the emscripten HEAP at address 'outPtr',
857 // null-terminated and encoded in UTF32LE form. The copy will require at most (str.length+1)*4 bytes of space in the HEAP,
858 // but can use less, since str.length does not return the number of characters in the string, but the number of UTF-16 code units in the string.
859 function stringToUTF32(str, outPtr) {
861 for(var iCodeUnit = 0; iCodeUnit < str.length; ++iCodeUnit) {
862 // 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.
863 var codeUnit = str.charCodeAt(iCodeUnit); // possibly a lead surrogate
864 if (codeUnit >= 0xD800 && codeUnit <= 0xDFFF) {
865 var trailSurrogate = str.charCodeAt(++iCodeUnit);
866 codeUnit = 0x10000 + ((codeUnit & 0x3FF) << 10) | (trailSurrogate & 0x3FF);
868 HEAP32[(((outPtr)+(iChar*4))>>2)]=codeUnit;
871 // Null-terminate the pointer to the HEAP.
872 HEAP32[(((outPtr)+(iChar*4))>>2)]=0;
874 Module['stringToUTF32'] = stringToUTF32;
876 function demangle(func) {
890 'h': 'unsigned char',
891 't': 'unsigned short',
893 'm': 'unsigned long',
895 'y': 'unsigned long long',
902 if (x) Module.print(x);
905 for (var a = 0; a < i; a++) pre += ' ';
906 Module.print (pre + '^');
908 function parseNested() {
910 if (func[i] === 'K') i++; // ignore const
912 while (func[i] !== 'E') {
913 if (func[i] === 'S') { // substitution
915 var next = func.indexOf('_', i);
916 var num = func.substring(i, next) || 0;
917 parts.push(subs[num] || '?');
921 if (func[i] === 'C') { // constructor
922 parts.push(parts[parts.length-1]);
926 var size = parseInt(func.substr(i));
927 var pre = size.toString().length;
928 if (!size || !pre) { i--; break; } // counter i++ below us
929 var curr = func.substr(i + pre, size);
937 function parse(rawList, limit, allowVoid) { // main parser
938 limit = limit || Infinity;
939 var ret = '', list = [];
940 function flushList() {
941 return '(' + list.join(', ') + ')';
944 if (func[i] === 'N') {
946 name = parseNested().join('::');
948 if (limit === 0) return rawList ? [name] : name;
951 if (func[i] === 'K' || (first && func[i] === 'L')) i++; // ignore const and first 'L'
952 var size = parseInt(func.substr(i));
954 var pre = size.toString().length;
955 name = func.substr(i + pre, size);
960 if (func[i] === 'I') {
962 var iList = parse(true);
963 var iRet = parse(true, 1, true);
964 ret += iRet[0] + ' ' + name + '<' + iList.join(', ') + '>';
968 paramLoop: while (i < func.length && limit-- > 0) {
971 if (c in basicTypes) {
972 list.push(basicTypes[c]);
975 case 'P': list.push(parse(true, 1, true)[0] + '*'); break; // pointer
976 case 'R': list.push(parse(true, 1, true)[0] + '&'); break; // reference
977 case 'L': { // literal
978 i++; // skip basic type
979 var end = func.indexOf('E', i);
981 list.push(func.substr(i, size));
982 i += size + 2; // size + 'EE'
986 var size = parseInt(func.substr(i));
987 i += size.toString().length;
988 if (func[i] !== '_') throw '?';
990 list.push(parse(true, 1, true)[0] + ' [' + size + ']');
993 case 'E': break paramLoop;
994 default: ret += '?' + c; break paramLoop;
998 if (!allowVoid && list.length === 1 && list[0] === 'void') list = []; // avoid (void)
999 return rawList ? list : ret + flushList();
1002 // Special-case the entry point, since its name differs from other name mangling.
1003 if (func == 'Object._main' || func == '_main') {
1006 if (typeof func === 'number') func = Pointer_stringify(func);
1007 if (func[0] !== '_') return func;
1008 if (func[1] !== '_') return func; // C function
1009 if (func[2] !== 'Z') return func;
1011 case 'n': return 'operator new()';
1012 case 'd': return 'operator delete()';
1020 function demangleAll(text) {
1021 return text.replace(/__Z[\w\d_]+/g, function(x) { var y = demangle(x); return x === y ? x : (x + ' [' + y + ']') });
1024 function stackTrace() {
1025 var stack = new Error().stack;
1026 return stack ? demangleAll(stack) : '(no stack trace available)'; // Stack trace is not available at least on IE10 and Safari 6.
1029 // Memory management
1031 var PAGE_SIZE = 4096;
1032 function alignMemoryPage(x) {
1033 return (x+4095)&-4096;
1037 var HEAP8, HEAPU8, HEAP16, HEAPU16, HEAP32, HEAPU32, HEAPF32, HEAPF64;
1039 var STATIC_BASE = 0, STATICTOP = 0, staticSealed = false; // static area
1040 var STACK_BASE = 0, STACKTOP = 0, STACK_MAX = 0; // stack area
1041 var DYNAMIC_BASE = 0, DYNAMICTOP = 0; // dynamic area handled by sbrk
1043 function enlargeMemory() {
1044 abort('Cannot enlarge memory arrays. Either (1) compile with -s TOTAL_MEMORY=X with X higher than the current value ' + TOTAL_MEMORY + ', (2) compile with ALLOW_MEMORY_GROWTH which adjusts the size at runtime but prevents some optimizations, or (3) set Module.TOTAL_MEMORY before the program runs.');
1047 var TOTAL_STACK = Module['TOTAL_STACK'] || 5242880;
1048 var TOTAL_MEMORY = Module['TOTAL_MEMORY'] || 16777216;
1049 var FAST_MEMORY = Module['FAST_MEMORY'] || 2097152;
1051 var totalMemory = 4096;
1052 while (totalMemory < TOTAL_MEMORY || totalMemory < 2*TOTAL_STACK) {
1053 if (totalMemory < 16*1024*1024) {
1056 totalMemory += 16*1024*1024
1059 if (totalMemory !== TOTAL_MEMORY) {
1060 Module.printErr('increasing TOTAL_MEMORY to ' + totalMemory + ' to be more reasonable');
1061 TOTAL_MEMORY = totalMemory;
1064 // Initialize the runtime's memory
1065 // check for full engine support (use string 'subarray' to avoid closure compiler confusion)
1066 assert(typeof Int32Array !== 'undefined' && typeof Float64Array !== 'undefined' && !!(new Int32Array(1)['subarray']) && !!(new Int32Array(1)['set']),
1067 'JS engine does not provide full typed array support');
1069 var buffer = new ArrayBuffer(TOTAL_MEMORY);
1070 HEAP8 = new Int8Array(buffer);
1071 HEAP16 = new Int16Array(buffer);
1072 HEAP32 = new Int32Array(buffer);
1073 HEAPU8 = new Uint8Array(buffer);
1074 HEAPU16 = new Uint16Array(buffer);
1075 HEAPU32 = new Uint32Array(buffer);
1076 HEAPF32 = new Float32Array(buffer);
1077 HEAPF64 = new Float64Array(buffer);
1079 // Endianness check (note: assumes compiler arch was little-endian)
1081 assert(HEAPU8[0] === 255 && HEAPU8[3] === 0, 'Typed arrays 2 must be run on a little-endian system');
1083 Module['HEAP'] = HEAP;
1084 Module['HEAP8'] = HEAP8;
1085 Module['HEAP16'] = HEAP16;
1086 Module['HEAP32'] = HEAP32;
1087 Module['HEAPU8'] = HEAPU8;
1088 Module['HEAPU16'] = HEAPU16;
1089 Module['HEAPU32'] = HEAPU32;
1090 Module['HEAPF32'] = HEAPF32;
1091 Module['HEAPF64'] = HEAPF64;
1093 function callRuntimeCallbacks(callbacks) {
1094 while(callbacks.length > 0) {
1095 var callback = callbacks.shift();
1096 if (typeof callback == 'function') {
1100 var func = callback.func;
1101 if (typeof func === 'number') {
1102 if (callback.arg === undefined) {
1103 Runtime.dynCall('v', func);
1105 Runtime.dynCall('vi', func, [callback.arg]);
1108 func(callback.arg === undefined ? null : callback.arg);
1113 var __ATPRERUN__ = []; // functions called before the runtime is initialized
1114 var __ATINIT__ = []; // functions called during startup
1115 var __ATMAIN__ = []; // functions called when main() is to be run
1116 var __ATEXIT__ = []; // functions called during shutdown
1117 var __ATPOSTRUN__ = []; // functions called after the runtime has exited
1119 var runtimeInitialized = false;
1122 // compatibility - merge in anything from Module['preRun'] at this time
1123 if (Module['preRun']) {
1124 if (typeof Module['preRun'] == 'function') Module['preRun'] = [Module['preRun']];
1125 while (Module['preRun'].length) {
1126 addOnPreRun(Module['preRun'].shift());
1129 callRuntimeCallbacks(__ATPRERUN__);
1132 function ensureInitRuntime() {
1133 if (runtimeInitialized) return;
1134 runtimeInitialized = true;
1135 callRuntimeCallbacks(__ATINIT__);
1138 function preMain() {
1139 callRuntimeCallbacks(__ATMAIN__);
1142 function exitRuntime() {
1143 callRuntimeCallbacks(__ATEXIT__);
1146 function postRun() {
1147 // compatibility - merge in anything from Module['postRun'] at this time
1148 if (Module['postRun']) {
1149 if (typeof Module['postRun'] == 'function') Module['postRun'] = [Module['postRun']];
1150 while (Module['postRun'].length) {
1151 addOnPostRun(Module['postRun'].shift());
1154 callRuntimeCallbacks(__ATPOSTRUN__);
1157 function addOnPreRun(cb) {
1158 __ATPRERUN__.unshift(cb);
1160 Module['addOnPreRun'] = Module.addOnPreRun = addOnPreRun;
1162 function addOnInit(cb) {
1163 __ATINIT__.unshift(cb);
1165 Module['addOnInit'] = Module.addOnInit = addOnInit;
1167 function addOnPreMain(cb) {
1168 __ATMAIN__.unshift(cb);
1170 Module['addOnPreMain'] = Module.addOnPreMain = addOnPreMain;
1172 function addOnExit(cb) {
1173 __ATEXIT__.unshift(cb);
1175 Module['addOnExit'] = Module.addOnExit = addOnExit;
1177 function addOnPostRun(cb) {
1178 __ATPOSTRUN__.unshift(cb);
1180 Module['addOnPostRun'] = Module.addOnPostRun = addOnPostRun;
1184 // This processes a JS string into a C-line array of numbers, 0-terminated.
1185 // For LLVM-originating strings, see parser.js:parseLLVMString function
1186 function intArrayFromString(stringy, dontAddNull, length /* optional */) {
1187 var ret = (new Runtime.UTF8Processor()).processJSString(stringy);
1189 ret.length = length;
1196 Module['intArrayFromString'] = intArrayFromString;
1198 function intArrayToString(array) {
1200 for (var i = 0; i < array.length; i++) {
1205 ret.push(String.fromCharCode(chr));
1207 return ret.join('');
1209 Module['intArrayToString'] = intArrayToString;
1211 // Write a Javascript array to somewhere in the heap
1212 function writeStringToMemory(string, buffer, dontAddNull) {
1213 var array = intArrayFromString(string, dontAddNull);
1215 while (i < array.length) {
1217 HEAP8[(((buffer)+(i))|0)]=chr;
1221 Module['writeStringToMemory'] = writeStringToMemory;
1223 function writeArrayToMemory(array, buffer) {
1224 for (var i = 0; i < array.length; i++) {
1225 HEAP8[(((buffer)+(i))|0)]=array[i];
1228 Module['writeArrayToMemory'] = writeArrayToMemory;
1230 function writeAsciiToMemory(str, buffer, dontAddNull) {
1231 for (var i = 0; i < str.length; i++) {
1232 HEAP8[(((buffer)+(i))|0)]=str.charCodeAt(i);
1234 if (!dontAddNull) HEAP8[(((buffer)+(str.length))|0)]=0;
1236 Module['writeAsciiToMemory'] = writeAsciiToMemory;
1238 function unSign(value, bits, ignore) {
1242 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
1243 : Math.pow(2, bits) + value;
1245 function reSign(value, bits, ignore) {
1249 var half = bits <= 32 ? Math.abs(1 << (bits-1)) // abs is needed if bits == 32
1250 : Math.pow(2, bits-1);
1251 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
1252 // but, in general there is no perfect solution here. With 64-bit ints, we get rounding and errors
1253 // TODO: In i64 mode 1, resign the two parts separately and safely
1254 value = -2*half + value; // Cannot bitshift half, as it may be at the limit of the bits JS uses in bitshifts
1259 // check for imul support, and also for correctness ( https://bugs.webkit.org/show_bug.cgi?id=126345 )
1260 if (!Math['imul'] || Math['imul'](0xffffffff, 5) !== -5) Math['imul'] = function imul(a, b) {
1262 var al = a & 0xffff;
1264 var bl = b & 0xffff;
1265 return (al*bl + ((ah*bl + al*bh) << 16))|0;
1267 Math.imul = Math['imul'];
1270 var Math_abs = Math.abs;
1271 var Math_cos = Math.cos;
1272 var Math_sin = Math.sin;
1273 var Math_tan = Math.tan;
1274 var Math_acos = Math.acos;
1275 var Math_asin = Math.asin;
1276 var Math_atan = Math.atan;
1277 var Math_atan2 = Math.atan2;
1278 var Math_exp = Math.exp;
1279 var Math_log = Math.log;
1280 var Math_sqrt = Math.sqrt;
1281 var Math_ceil = Math.ceil;
1282 var Math_floor = Math.floor;
1283 var Math_pow = Math.pow;
1284 var Math_imul = Math.imul;
1285 var Math_fround = Math.fround;
1286 var Math_min = Math.min;
1288 // A counter of dependencies for calling run(). If we need to
1289 // do asynchronous work before running, increment this and
1290 // decrement it. Incrementing must happen in a place like
1291 // PRE_RUN_ADDITIONS (used by emcc to add file preloading).
1292 // Note that you can add dependencies in preRun, even though
1293 // it happens right before run - run will be postponed until
1294 // the dependencies are met.
1295 var runDependencies = 0;
1296 var runDependencyWatcher = null;
1297 var dependenciesFulfilled = null; // overridden to take different actions when all run dependencies are fulfilled
1299 function addRunDependency(id) {
1301 if (Module['monitorRunDependencies']) {
1302 Module['monitorRunDependencies'](runDependencies);
1305 Module['addRunDependency'] = addRunDependency;
1306 function removeRunDependency(id) {
1308 if (Module['monitorRunDependencies']) {
1309 Module['monitorRunDependencies'](runDependencies);
1311 if (runDependencies == 0) {
1312 if (runDependencyWatcher !== null) {
1313 clearInterval(runDependencyWatcher);
1314 runDependencyWatcher = null;
1316 if (dependenciesFulfilled) {
1317 var callback = dependenciesFulfilled;
1318 dependenciesFulfilled = null;
1319 callback(); // can add another dependenciesFulfilled
1323 Module['removeRunDependency'] = removeRunDependency;
1325 Module["preloadedImages"] = {}; // maps url to image data
1326 Module["preloadedAudios"] = {}; // maps url to audio data
1329 var memoryInitializer = null;
1339 STATICTOP = STATIC_BASE + Runtime.alignMemory(283);
1340 /* global initializers */ __ATINIT__.push();
1343 /* memory initializer */ allocate([32,69,114,114,111,114,32,105,110,32,84,111,119,101,114,115,58,32,37,115,10,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,111,117,116,32,111,102,32,115,112,97,99,101,32,32,32,0,100,105,115,99,32,115,105,122,101,32,101,114,114,111,114,0,110,111,116,104,105,110,103,32,116,111,32,112,111,112,32,0,0,0,0,0,0,0,0,0,32,69,114,114,111,114,32,105,110,32,84,111,119,101,114,115,46,0,0,0,0,0,0,0], "i8", ALLOC_NONE, Runtime.GLOBAL_BASE);
1348 var tempDoublePtr = Runtime.alignMemory(allocate(12, "i8", ALLOC_STATIC), 8);
1350 assert(tempDoublePtr % 8 == 0);
1352 function copyTempFloat(ptr) { // functions, because inlining this code increases code size too much
1354 HEAP8[tempDoublePtr] = HEAP8[ptr];
1356 HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
1358 HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
1360 HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
1364 function copyTempDouble(ptr) {
1366 HEAP8[tempDoublePtr] = HEAP8[ptr];
1368 HEAP8[tempDoublePtr+1] = HEAP8[ptr+1];
1370 HEAP8[tempDoublePtr+2] = HEAP8[ptr+2];
1372 HEAP8[tempDoublePtr+3] = HEAP8[ptr+3];
1374 HEAP8[tempDoublePtr+4] = HEAP8[ptr+4];
1376 HEAP8[tempDoublePtr+5] = HEAP8[ptr+5];
1378 HEAP8[tempDoublePtr+6] = HEAP8[ptr+6];
1380 HEAP8[tempDoublePtr+7] = HEAP8[ptr+7];
1385 function _llvm_lifetime_end() {}
1387 function _malloc(bytes) {
1388 /* Over-allocate to make sure it is byte-aligned by 8.
1389 * This will leak memory, but this is only the dummy
1390 * implementation (replaced by dlmalloc normally) so
1393 var ptr = Runtime.dynamicAlloc(bytes + 8);
1394 return (ptr+8) & 0xFFFFFFF8;
1396 Module["_malloc"] = _malloc;
1402 var ERRNO_CODES={EPERM:1,ENOENT:2,ESRCH:3,EINTR:4,EIO:5,ENXIO:6,E2BIG:7,ENOEXEC:8,EBADF:9,ECHILD:10,EAGAIN:11,EWOULDBLOCK:11,ENOMEM:12,EACCES:13,EFAULT:14,ENOTBLK:15,EBUSY:16,EEXIST:17,EXDEV:18,ENODEV:19,ENOTDIR:20,EISDIR:21,EINVAL:22,ENFILE:23,EMFILE:24,ENOTTY:25,ETXTBSY:26,EFBIG:27,ENOSPC:28,ESPIPE:29,EROFS:30,EMLINK:31,EPIPE:32,EDOM:33,ERANGE:34,ENOMSG:42,EIDRM:43,ECHRNG:44,EL2NSYNC:45,EL3HLT:46,EL3RST:47,ELNRNG:48,EUNATCH:49,ENOCSI:50,EL2HLT:51,EDEADLK:35,ENOLCK:37,EBADE:52,EBADR:53,EXFULL:54,ENOANO:55,EBADRQC:56,EBADSLT:57,EDEADLOCK:35,EBFONT:59,ENOSTR:60,ENODATA:61,ETIME:62,ENOSR:63,ENONET:64,ENOPKG:65,EREMOTE:66,ENOLINK:67,EADV:68,ESRMNT:69,ECOMM:70,EPROTO:71,EMULTIHOP:72,EDOTDOT:73,EBADMSG:74,ENOTUNIQ:76,EBADFD:77,EREMCHG:78,ELIBACC:79,ELIBBAD:80,ELIBSCN:81,ELIBMAX:82,ELIBEXEC:83,ENOSYS:38,ENOTEMPTY:39,ENAMETOOLONG:36,ELOOP:40,EOPNOTSUPP:95,EPFNOSUPPORT:96,ECONNRESET:104,ENOBUFS:105,EAFNOSUPPORT:97,EPROTOTYPE:91,ENOTSOCK:88,ENOPROTOOPT:92,ESHUTDOWN:108,ECONNREFUSED:111,EADDRINUSE:98,ECONNABORTED:103,ENETUNREACH:101,ENETDOWN:100,ETIMEDOUT:110,EHOSTDOWN:112,EHOSTUNREACH:113,EINPROGRESS:115,EALREADY:114,EDESTADDRREQ:89,EMSGSIZE:90,EPROTONOSUPPORT:93,ESOCKTNOSUPPORT:94,EADDRNOTAVAIL:99,ENETRESET:102,EISCONN:106,ENOTCONN:107,ETOOMANYREFS:109,EUSERS:87,EDQUOT:122,ESTALE:116,ENOTSUP:95,ENOMEDIUM:123,EILSEQ:84,EOVERFLOW:75,ECANCELED:125,ENOTRECOVERABLE:131,EOWNERDEAD:130,ESTRPIPE:86};
1404 var ERRNO_MESSAGES={0:"Success",1:"Not super-user",2:"No such file or directory",3:"No such process",4:"Interrupted system call",5:"I/O error",6:"No such device or address",7:"Arg list too long",8:"Exec format error",9:"Bad file number",10:"No children",11:"No more processes",12:"Not enough core",13:"Permission denied",14:"Bad address",15:"Block device required",16:"Mount device busy",17:"File exists",18:"Cross-device link",19:"No such device",20:"Not a directory",21:"Is a directory",22:"Invalid argument",23:"Too many open files in system",24:"Too many open files",25:"Not a typewriter",26:"Text file busy",27:"File too large",28:"No space left on device",29:"Illegal seek",30:"Read only file system",31:"Too many links",32:"Broken pipe",33:"Math arg out of domain of func",34:"Math result not representable",35:"File locking deadlock error",36:"File or path name too long",37:"No record locks available",38:"Function not implemented",39:"Directory not empty",40:"Too many symbolic links",42:"No message of desired type",43:"Identifier removed",44:"Channel number out of range",45:"Level 2 not synchronized",46:"Level 3 halted",47:"Level 3 reset",48:"Link number out of range",49:"Protocol driver not attached",50:"No CSI structure available",51:"Level 2 halted",52:"Invalid exchange",53:"Invalid request descriptor",54:"Exchange full",55:"No anode",56:"Invalid request code",57:"Invalid slot",59:"Bad font file fmt",60:"Device not a stream",61:"No data (for no delay io)",62:"Timer expired",63:"Out of streams resources",64:"Machine is not on the network",65:"Package not installed",66:"The object is remote",67:"The link has been severed",68:"Advertise error",69:"Srmount error",70:"Communication error on send",71:"Protocol error",72:"Multihop attempted",73:"Cross mount point (not really error)",74:"Trying to read unreadable message",75:"Value too large for defined data type",76:"Given log. name not unique",77:"f.d. invalid for this operation",78:"Remote address changed",79:"Can access a needed shared lib",80:"Accessing a corrupted shared lib",81:".lib section in a.out corrupted",82:"Attempting to link in too many libs",83:"Attempting to exec a shared library",84:"Illegal byte sequence",86:"Streams pipe error",87:"Too many users",88:"Socket operation on non-socket",89:"Destination address required",90:"Message too long",91:"Protocol wrong type for socket",92:"Protocol not available",93:"Unknown protocol",94:"Socket type not supported",95:"Not supported",96:"Protocol family not supported",97:"Address family not supported by protocol family",98:"Address already in use",99:"Address not available",100:"Network interface is not configured",101:"Network is unreachable",102:"Connection reset by network",103:"Connection aborted",104:"Connection reset by peer",105:"No buffer space available",106:"Socket is already connected",107:"Socket is not connected",108:"Can't send after socket shutdown",109:"Too many references",110:"Connection timed out",111:"Connection refused",112:"Host is down",113:"Host is unreachable",114:"Socket already connected",115:"Connection already in progress",116:"Stale file handle",122:"Quota exceeded",123:"No medium (in tape drive)",125:"Operation canceled",130:"Previous owner died",131:"State not recoverable"};
1407 var ___errno_state=0;function ___setErrNo(value) {
1408 // For convenient setting and returning of errno.
1409 HEAP32[((___errno_state)>>2)]=value;
1413 var PATH={splitPath:function (filename) {
1414 var splitPathRe = /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/;
1415 return splitPathRe.exec(filename).slice(1);
1416 },normalizeArray:function (parts, allowAboveRoot) {
1417 // if the path tries to go above the root, `up` ends up > 0
1419 for (var i = parts.length - 1; i >= 0; i--) {
1420 var last = parts[i];
1423 } else if (last === '..') {
1431 // if the path is allowed to go above the root, restore leading ..s
1432 if (allowAboveRoot) {
1434 parts.unshift('..');
1438 },normalize:function (path) {
1439 var isAbsolute = path.charAt(0) === '/',
1440 trailingSlash = path.substr(-1) === '/';
1441 // Normalize the path
1442 path = PATH.normalizeArray(path.split('/').filter(function(p) {
1444 }), !isAbsolute).join('/');
1445 if (!path && !isAbsolute) {
1448 if (path && trailingSlash) {
1451 return (isAbsolute ? '/' : '') + path;
1452 },dirname:function (path) {
1453 var result = PATH.splitPath(path),
1456 if (!root && !dir) {
1457 // No dirname whatsoever
1461 // It has a dirname, strip trailing slash
1462 dir = dir.substr(0, dir.length - 1);
1465 },basename:function (path) {
1466 // EMSCRIPTEN return '/'' for '/', not an empty string
1467 if (path === '/') return '/';
1468 var lastSlash = path.lastIndexOf('/');
1469 if (lastSlash === -1) return path;
1470 return path.substr(lastSlash+1);
1471 },extname:function (path) {
1472 return PATH.splitPath(path)[3];
1473 },join:function () {
1474 var paths = Array.prototype.slice.call(arguments, 0);
1475 return PATH.normalize(paths.join('/'));
1476 },join2:function (l, r) {
1477 return PATH.normalize(l + '/' + r);
1478 },resolve:function () {
1479 var resolvedPath = '',
1480 resolvedAbsolute = false;
1481 for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) {
1482 var path = (i >= 0) ? arguments[i] : FS.cwd();
1483 // Skip empty and invalid entries
1484 if (typeof path !== 'string') {
1485 throw new TypeError('Arguments to path.resolve must be strings');
1489 resolvedPath = path + '/' + resolvedPath;
1490 resolvedAbsolute = path.charAt(0) === '/';
1492 // At this point the path should be resolved to a full absolute path, but
1493 // handle relative paths to be safe (might happen when process.cwd() fails)
1494 resolvedPath = PATH.normalizeArray(resolvedPath.split('/').filter(function(p) {
1496 }), !resolvedAbsolute).join('/');
1497 return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.';
1498 },relative:function (from, to) {
1499 from = PATH.resolve(from).substr(1);
1500 to = PATH.resolve(to).substr(1);
1501 function trim(arr) {
1503 for (; start < arr.length; start++) {
1504 if (arr[start] !== '') break;
1506 var end = arr.length - 1;
1507 for (; end >= 0; end--) {
1508 if (arr[end] !== '') break;
1510 if (start > end) return [];
1511 return arr.slice(start, end - start + 1);
1513 var fromParts = trim(from.split('/'));
1514 var toParts = trim(to.split('/'));
1515 var length = Math.min(fromParts.length, toParts.length);
1516 var samePartsLength = length;
1517 for (var i = 0; i < length; i++) {
1518 if (fromParts[i] !== toParts[i]) {
1519 samePartsLength = i;
1523 var outputParts = [];
1524 for (var i = samePartsLength; i < fromParts.length; i++) {
1525 outputParts.push('..');
1527 outputParts = outputParts.concat(toParts.slice(samePartsLength));
1528 return outputParts.join('/');
1531 var TTY={ttys:[],init:function () {
1532 // https://github.com/kripken/emscripten/pull/1555
1533 // if (ENVIRONMENT_IS_NODE) {
1534 // // currently, FS.init does not distinguish if process.stdin is a file or TTY
1535 // // device, it always assumes it's a TTY device. because of this, we're forcing
1536 // // process.stdin to UTF8 encoding to at least make stdin reading compatible
1537 // // with text files until FS.init can be refactored.
1538 // process['stdin']['setEncoding']('utf8');
1540 },shutdown:function () {
1541 // https://github.com/kripken/emscripten/pull/1555
1542 // if (ENVIRONMENT_IS_NODE) {
1543 // // inolen: any idea as to why node -e 'process.stdin.read()' wouldn't exit immediately (with process.stdin being a tty)?
1544 // // 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
1545 // // inolen: I thought read() in that case was a synchronous operation that just grabbed some amount of buffered data if it exists?
1546 // // isaacs: it is. but it also triggers a _read() call, which calls readStart() on the handle
1547 // // isaacs: do process.stdin.pause() and i'd think it'd probably close the pending call
1548 // process['stdin']['pause']();
1550 },register:function (dev, ops) {
1551 TTY.ttys[dev] = { input: [], output: [], ops: ops };
1552 FS.registerDevice(dev, TTY.stream_ops);
1553 },stream_ops:{open:function (stream) {
1554 var tty = TTY.ttys[stream.node.rdev];
1556 throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
1559 stream.seekable = false;
1560 },close:function (stream) {
1561 // flush any pending line data
1562 if (stream.tty.output.length) {
1563 stream.tty.ops.put_char(stream.tty, 10);
1565 },read:function (stream, buffer, offset, length, pos /* ignored */) {
1566 if (!stream.tty || !stream.tty.ops.get_char) {
1567 throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
1570 for (var i = 0; i < length; i++) {
1573 result = stream.tty.ops.get_char(stream.tty);
1575 throw new FS.ErrnoError(ERRNO_CODES.EIO);
1577 if (result === undefined && bytesRead === 0) {
1578 throw new FS.ErrnoError(ERRNO_CODES.EAGAIN);
1580 if (result === null || result === undefined) break;
1582 buffer[offset+i] = result;
1585 stream.node.timestamp = Date.now();
1588 },write:function (stream, buffer, offset, length, pos) {
1589 if (!stream.tty || !stream.tty.ops.put_char) {
1590 throw new FS.ErrnoError(ERRNO_CODES.ENXIO);
1592 for (var i = 0; i < length; i++) {
1594 stream.tty.ops.put_char(stream.tty, buffer[offset+i]);
1596 throw new FS.ErrnoError(ERRNO_CODES.EIO);
1600 stream.node.timestamp = Date.now();
1603 }},default_tty_ops:{get_char:function (tty) {
1604 if (!tty.input.length) {
1606 if (ENVIRONMENT_IS_NODE) {
1607 result = process['stdin']['read']();
1609 if (process['stdin']['_readableState'] && process['stdin']['_readableState']['ended']) {
1612 return undefined; // no data available
1614 } else if (typeof window != 'undefined' &&
1615 typeof window.prompt == 'function') {
1617 result = window.prompt('Input: '); // returns null on cancel
1618 if (result !== null) {
1621 } else if (typeof readline == 'function') {
1623 result = readline();
1624 if (result !== null) {
1631 tty.input = intArrayFromString(result, true);
1633 return tty.input.shift();
1634 },put_char:function (tty, val) {
1635 if (val === null || val === 10) {
1636 Module['print'](tty.output.join(''));
1639 tty.output.push(TTY.utf8.processCChar(val));
1641 }},default_tty1_ops:{put_char:function (tty, val) {
1642 if (val === null || val === 10) {
1643 Module['printErr'](tty.output.join(''));
1646 tty.output.push(TTY.utf8.processCChar(val));
1650 var MEMFS={ops_table:null,CONTENT_OWNING:1,CONTENT_FLEXIBLE:2,CONTENT_FIXED:3,mount:function (mount) {
1651 return MEMFS.createNode(null, '/', 16384 | 511 /* 0777 */, 0);
1652 },createNode:function (parent, name, mode, dev) {
1653 if (FS.isBlkdev(mode) || FS.isFIFO(mode)) {
1655 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
1657 if (!MEMFS.ops_table) {
1661 getattr: MEMFS.node_ops.getattr,
1662 setattr: MEMFS.node_ops.setattr,
1663 lookup: MEMFS.node_ops.lookup,
1664 mknod: MEMFS.node_ops.mknod,
1665 rename: MEMFS.node_ops.rename,
1666 unlink: MEMFS.node_ops.unlink,
1667 rmdir: MEMFS.node_ops.rmdir,
1668 readdir: MEMFS.node_ops.readdir,
1669 symlink: MEMFS.node_ops.symlink
1672 llseek: MEMFS.stream_ops.llseek
1677 getattr: MEMFS.node_ops.getattr,
1678 setattr: MEMFS.node_ops.setattr
1681 llseek: MEMFS.stream_ops.llseek,
1682 read: MEMFS.stream_ops.read,
1683 write: MEMFS.stream_ops.write,
1684 allocate: MEMFS.stream_ops.allocate,
1685 mmap: MEMFS.stream_ops.mmap
1690 getattr: MEMFS.node_ops.getattr,
1691 setattr: MEMFS.node_ops.setattr,
1692 readlink: MEMFS.node_ops.readlink
1698 getattr: MEMFS.node_ops.getattr,
1699 setattr: MEMFS.node_ops.setattr
1701 stream: FS.chrdev_stream_ops
1705 var node = FS.createNode(parent, name, mode, dev);
1706 if (FS.isDir(node.mode)) {
1707 node.node_ops = MEMFS.ops_table.dir.node;
1708 node.stream_ops = MEMFS.ops_table.dir.stream;
1710 } else if (FS.isFile(node.mode)) {
1711 node.node_ops = MEMFS.ops_table.file.node;
1712 node.stream_ops = MEMFS.ops_table.file.stream;
1714 node.contentMode = MEMFS.CONTENT_FLEXIBLE;
1715 } else if (FS.isLink(node.mode)) {
1716 node.node_ops = MEMFS.ops_table.link.node;
1717 node.stream_ops = MEMFS.ops_table.link.stream;
1718 } else if (FS.isChrdev(node.mode)) {
1719 node.node_ops = MEMFS.ops_table.chrdev.node;
1720 node.stream_ops = MEMFS.ops_table.chrdev.stream;
1722 node.timestamp = Date.now();
1723 // add the new node to the parent
1725 parent.contents[name] = node;
1728 },ensureFlexible:function (node) {
1729 if (node.contentMode !== MEMFS.CONTENT_FLEXIBLE) {
1730 var contents = node.contents;
1731 node.contents = Array.prototype.slice.call(contents);
1732 node.contentMode = MEMFS.CONTENT_FLEXIBLE;
1734 },node_ops:{getattr:function (node) {
1736 // device numbers reuse inode numbers.
1737 attr.dev = FS.isChrdev(node.mode) ? node.id : 1;
1739 attr.mode = node.mode;
1743 attr.rdev = node.rdev;
1744 if (FS.isDir(node.mode)) {
1746 } else if (FS.isFile(node.mode)) {
1747 attr.size = node.contents.length;
1748 } else if (FS.isLink(node.mode)) {
1749 attr.size = node.link.length;
1753 attr.atime = new Date(node.timestamp);
1754 attr.mtime = new Date(node.timestamp);
1755 attr.ctime = new Date(node.timestamp);
1756 // NOTE: In our implementation, st_blocks = Math.ceil(st_size/st_blksize),
1757 // but this is not required by the standard.
1758 attr.blksize = 4096;
1759 attr.blocks = Math.ceil(attr.size / attr.blksize);
1761 },setattr:function (node, attr) {
1762 if (attr.mode !== undefined) {
1763 node.mode = attr.mode;
1765 if (attr.timestamp !== undefined) {
1766 node.timestamp = attr.timestamp;
1768 if (attr.size !== undefined) {
1769 MEMFS.ensureFlexible(node);
1770 var contents = node.contents;
1771 if (attr.size < contents.length) contents.length = attr.size;
1772 else while (attr.size > contents.length) contents.push(0);
1774 },lookup:function (parent, name) {
1775 throw FS.genericErrors[ERRNO_CODES.ENOENT];
1776 },mknod:function (parent, name, mode, dev) {
1777 return MEMFS.createNode(parent, name, mode, dev);
1778 },rename:function (old_node, new_dir, new_name) {
1779 // if we're overwriting a directory at new_name, make sure it's empty.
1780 if (FS.isDir(old_node.mode)) {
1783 new_node = FS.lookupNode(new_dir, new_name);
1787 for (var i in new_node.contents) {
1788 throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
1792 // do the internal rewiring
1793 delete old_node.parent.contents[old_node.name];
1794 old_node.name = new_name;
1795 new_dir.contents[new_name] = old_node;
1796 old_node.parent = new_dir;
1797 },unlink:function (parent, name) {
1798 delete parent.contents[name];
1799 },rmdir:function (parent, name) {
1800 var node = FS.lookupNode(parent, name);
1801 for (var i in node.contents) {
1802 throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
1804 delete parent.contents[name];
1805 },readdir:function (node) {
1806 var entries = ['.', '..']
1807 for (var key in node.contents) {
1808 if (!node.contents.hasOwnProperty(key)) {
1814 },symlink:function (parent, newname, oldpath) {
1815 var node = MEMFS.createNode(parent, newname, 511 /* 0777 */ | 40960, 0);
1816 node.link = oldpath;
1818 },readlink:function (node) {
1819 if (!FS.isLink(node.mode)) {
1820 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
1823 }},stream_ops:{read:function (stream, buffer, offset, length, position) {
1824 var contents = stream.node.contents;
1825 if (position >= contents.length)
1827 var size = Math.min(contents.length - position, length);
1829 if (size > 8 && contents.subarray) { // non-trivial, and typed array
1830 buffer.set(contents.subarray(position, position + size), offset);
1833 for (var i = 0; i < size; i++) {
1834 buffer[offset + i] = contents[position + i];
1838 },write:function (stream, buffer, offset, length, position, canOwn) {
1839 var node = stream.node;
1840 node.timestamp = Date.now();
1841 var contents = node.contents;
1842 if (length && contents.length === 0 && position === 0 && buffer.subarray) {
1843 // just replace it with the new data
1844 if (canOwn && offset === 0) {
1845 node.contents = buffer; // this could be a subarray of Emscripten HEAP, or allocated from some other source.
1846 node.contentMode = (buffer.buffer === HEAP8.buffer) ? MEMFS.CONTENT_OWNING : MEMFS.CONTENT_FIXED;
1848 node.contents = new Uint8Array(buffer.subarray(offset, offset+length));
1849 node.contentMode = MEMFS.CONTENT_FIXED;
1853 MEMFS.ensureFlexible(node);
1854 var contents = node.contents;
1855 while (contents.length < position) contents.push(0);
1856 for (var i = 0; i < length; i++) {
1857 contents[position + i] = buffer[offset + i];
1860 },llseek:function (stream, offset, whence) {
1861 var position = offset;
1862 if (whence === 1) { // SEEK_CUR.
1863 position += stream.position;
1864 } else if (whence === 2) { // SEEK_END.
1865 if (FS.isFile(stream.node.mode)) {
1866 position += stream.node.contents.length;
1870 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
1872 stream.ungotten = [];
1873 stream.position = position;
1875 },allocate:function (stream, offset, length) {
1876 MEMFS.ensureFlexible(stream.node);
1877 var contents = stream.node.contents;
1878 var limit = offset + length;
1879 while (limit > contents.length) contents.push(0);
1880 },mmap:function (stream, buffer, offset, length, position, prot, flags) {
1881 if (!FS.isFile(stream.node.mode)) {
1882 throw new FS.ErrnoError(ERRNO_CODES.ENODEV);
1886 var contents = stream.node.contents;
1887 // Only make a new copy when MAP_PRIVATE is specified.
1888 if ( !(flags & 2) &&
1889 (contents.buffer === buffer || contents.buffer === buffer.buffer) ) {
1890 // We can't emulate MAP_SHARED when the file is not backed by the buffer
1891 // we're mapping to (e.g. the HEAP buffer).
1893 ptr = contents.byteOffset;
1895 // Try to avoid unnecessary slices.
1896 if (position > 0 || position + length < contents.length) {
1897 if (contents.subarray) {
1898 contents = contents.subarray(position, position + length);
1900 contents = Array.prototype.slice.call(contents, position, position + length);
1904 ptr = _malloc(length);
1906 throw new FS.ErrnoError(ERRNO_CODES.ENOMEM);
1908 buffer.set(contents, ptr);
1910 return { ptr: ptr, allocated: allocated };
1913 var IDBFS={dbs:{},indexedDB:function () {
1914 return window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
1915 },DB_VERSION:21,DB_STORE_NAME:"FILE_DATA",mount:function (mount) {
1916 // reuse all of the core MEMFS functionality
1917 return MEMFS.mount.apply(null, arguments);
1918 },syncfs:function (mount, populate, callback) {
1919 IDBFS.getLocalSet(mount, function(err, local) {
1920 if (err) return callback(err);
1922 IDBFS.getRemoteSet(mount, function(err, remote) {
1923 if (err) return callback(err);
1925 var src = populate ? remote : local;
1926 var dst = populate ? local : remote;
1928 IDBFS.reconcile(src, dst, callback);
1931 },getDB:function (name, callback) {
1932 // check the cache first
1933 var db = IDBFS.dbs[name];
1935 return callback(null, db);
1940 req = IDBFS.indexedDB().open(name, IDBFS.DB_VERSION);
1944 req.onupgradeneeded = function(e) {
1945 var db = e.target.result;
1946 var transaction = e.target.transaction;
1950 if (db.objectStoreNames.contains(IDBFS.DB_STORE_NAME)) {
1951 fileStore = transaction.objectStore(IDBFS.DB_STORE_NAME);
1953 fileStore = db.createObjectStore(IDBFS.DB_STORE_NAME);
1956 fileStore.createIndex('timestamp', 'timestamp', { unique: false });
1958 req.onsuccess = function() {
1962 IDBFS.dbs[name] = db;
1965 req.onerror = function() {
1966 callback(this.error);
1968 },getLocalSet:function (mount, callback) {
1971 function isRealDir(p) {
1972 return p !== '.' && p !== '..';
1974 function toAbsolute(root) {
1975 return function(p) {
1976 return PATH.join2(root, p);
1980 var check = FS.readdir(mount.mountpoint).filter(isRealDir).map(toAbsolute(mount.mountpoint));
1982 while (check.length) {
1983 var path = check.pop();
1987 stat = FS.stat(path);
1992 if (FS.isDir(stat.mode)) {
1993 check.push.apply(check, FS.readdir(path).filter(isRealDir).map(toAbsolute(path)));
1996 entries[path] = { timestamp: stat.mtime };
1999 return callback(null, { type: 'local', entries: entries });
2000 },getRemoteSet:function (mount, callback) {
2003 IDBFS.getDB(mount.mountpoint, function(err, db) {
2004 if (err) return callback(err);
2006 var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readonly');
2007 transaction.onerror = function() { callback(this.error); };
2009 var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
2010 var index = store.index('timestamp');
2012 index.openKeyCursor().onsuccess = function(event) {
2013 var cursor = event.target.result;
2016 return callback(null, { type: 'remote', db: db, entries: entries });
2019 entries[cursor.primaryKey] = { timestamp: cursor.key };
2024 },loadLocalEntry:function (path, callback) {
2028 var lookup = FS.lookupPath(path);
2030 stat = FS.stat(path);
2035 if (FS.isDir(stat.mode)) {
2036 return callback(null, { timestamp: stat.mtime, mode: stat.mode });
2037 } else if (FS.isFile(stat.mode)) {
2038 return callback(null, { timestamp: stat.mtime, mode: stat.mode, contents: node.contents });
2040 return callback(new Error('node type not supported'));
2042 },storeLocalEntry:function (path, entry, callback) {
2044 if (FS.isDir(entry.mode)) {
2045 FS.mkdir(path, entry.mode);
2046 } else if (FS.isFile(entry.mode)) {
2047 FS.writeFile(path, entry.contents, { encoding: 'binary', canOwn: true });
2049 return callback(new Error('node type not supported'));
2052 FS.utime(path, entry.timestamp, entry.timestamp);
2058 },removeLocalEntry:function (path, callback) {
2060 var lookup = FS.lookupPath(path);
2061 var stat = FS.stat(path);
2063 if (FS.isDir(stat.mode)) {
2065 } else if (FS.isFile(stat.mode)) {
2073 },loadRemoteEntry:function (store, path, callback) {
2074 var req = store.get(path);
2075 req.onsuccess = function(event) { callback(null, event.target.result); };
2076 req.onerror = function() { callback(this.error); };
2077 },storeRemoteEntry:function (store, path, entry, callback) {
2078 var req = store.put(entry, path);
2079 req.onsuccess = function() { callback(null); };
2080 req.onerror = function() { callback(this.error); };
2081 },removeRemoteEntry:function (store, path, callback) {
2082 var req = store.delete(path);
2083 req.onsuccess = function() { callback(null); };
2084 req.onerror = function() { callback(this.error); };
2085 },reconcile:function (src, dst, callback) {
2089 Object.keys(src.entries).forEach(function (key) {
2090 var e = src.entries[key];
2091 var e2 = dst.entries[key];
2092 if (!e2 || e.timestamp > e2.timestamp) {
2099 Object.keys(dst.entries).forEach(function (key) {
2100 var e = dst.entries[key];
2101 var e2 = src.entries[key];
2109 return callback(null);
2112 var errored = false;
2114 var db = src.type === 'remote' ? src.db : dst.db;
2115 var transaction = db.transaction([IDBFS.DB_STORE_NAME], 'readwrite');
2116 var store = transaction.objectStore(IDBFS.DB_STORE_NAME);
2118 function done(err) {
2120 if (!done.errored) {
2121 done.errored = true;
2122 return callback(err);
2126 if (++completed >= total) {
2127 return callback(null);
2131 transaction.onerror = function() { done(this.error); };
2133 // sort paths in ascending order so directory entries are created
2134 // before the files inside them
2135 create.sort().forEach(function (path) {
2136 if (dst.type === 'local') {
2137 IDBFS.loadRemoteEntry(store, path, function (err, entry) {
2138 if (err) return done(err);
2139 IDBFS.storeLocalEntry(path, entry, done);
2142 IDBFS.loadLocalEntry(path, function (err, entry) {
2143 if (err) return done(err);
2144 IDBFS.storeRemoteEntry(store, path, entry, done);
2149 // sort paths in descending order so files are deleted before their
2150 // parent directories
2151 remove.sort().reverse().forEach(function(path) {
2152 if (dst.type === 'local') {
2153 IDBFS.removeLocalEntry(path, done);
2155 IDBFS.removeRemoteEntry(store, path, done);
2160 var NODEFS={isWindows:false,staticInit:function () {
2161 NODEFS.isWindows = !!process.platform.match(/^win/);
2162 },mount:function (mount) {
2163 assert(ENVIRONMENT_IS_NODE);
2164 return NODEFS.createNode(null, '/', NODEFS.getMode(mount.opts.root), 0);
2165 },createNode:function (parent, name, mode, dev) {
2166 if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) {
2167 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2169 var node = FS.createNode(parent, name, mode);
2170 node.node_ops = NODEFS.node_ops;
2171 node.stream_ops = NODEFS.stream_ops;
2173 },getMode:function (path) {
2176 stat = fs.lstatSync(path);
2177 if (NODEFS.isWindows) {
2178 // On Windows, directories return permission bits 'rw-rw-rw-', even though they have 'rwxrwxrwx', so
2179 // propagate write bits to execute bits.
2180 stat.mode = stat.mode | ((stat.mode & 146) >> 1);
2183 if (!e.code) throw e;
2184 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2187 },realPath:function (node) {
2189 while (node.parent !== node) {
2190 parts.push(node.name);
2193 parts.push(node.mount.opts.root);
2195 return PATH.join.apply(null, parts);
2196 },flagsToPermissionStringMap:{0:"r",1:"r+",2:"r+",64:"r",65:"r+",66:"r+",129:"rx+",193:"rx+",514:"w+",577:"w",578:"w+",705:"wx",706:"wx+",1024:"a",1025:"a",1026:"a+",1089:"a",1090:"a+",1153:"ax",1154:"ax+",1217:"ax",1218:"ax+",4096:"rs",4098:"rs+"},flagsToPermissionString:function (flags) {
2197 if (flags in NODEFS.flagsToPermissionStringMap) {
2198 return NODEFS.flagsToPermissionStringMap[flags];
2202 },node_ops:{getattr:function (node) {
2203 var path = NODEFS.realPath(node);
2206 stat = fs.lstatSync(path);
2208 if (!e.code) throw e;
2209 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2211 // node.js v0.10.20 doesn't report blksize and blocks on Windows. Fake them with default blksize of 4096.
2212 // See http://support.microsoft.com/kb/140365
2213 if (NODEFS.isWindows && !stat.blksize) {
2214 stat.blksize = 4096;
2216 if (NODEFS.isWindows && !stat.blocks) {
2217 stat.blocks = (stat.size+stat.blksize-1)/stat.blksize|0;
2231 blksize: stat.blksize,
2234 },setattr:function (node, attr) {
2235 var path = NODEFS.realPath(node);
2237 if (attr.mode !== undefined) {
2238 fs.chmodSync(path, attr.mode);
2239 // update the common node structure mode as well
2240 node.mode = attr.mode;
2242 if (attr.timestamp !== undefined) {
2243 var date = new Date(attr.timestamp);
2244 fs.utimesSync(path, date, date);
2246 if (attr.size !== undefined) {
2247 fs.truncateSync(path, attr.size);
2250 if (!e.code) throw e;
2251 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2253 },lookup:function (parent, name) {
2254 var path = PATH.join2(NODEFS.realPath(parent), name);
2255 var mode = NODEFS.getMode(path);
2256 return NODEFS.createNode(parent, name, mode);
2257 },mknod:function (parent, name, mode, dev) {
2258 var node = NODEFS.createNode(parent, name, mode, dev);
2259 // create the backing node for this in the fs root as well
2260 var path = NODEFS.realPath(node);
2262 if (FS.isDir(node.mode)) {
2263 fs.mkdirSync(path, node.mode);
2265 fs.writeFileSync(path, '', { mode: node.mode });
2268 if (!e.code) throw e;
2269 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2272 },rename:function (oldNode, newDir, newName) {
2273 var oldPath = NODEFS.realPath(oldNode);
2274 var newPath = PATH.join2(NODEFS.realPath(newDir), newName);
2276 fs.renameSync(oldPath, newPath);
2278 if (!e.code) throw e;
2279 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2281 },unlink:function (parent, name) {
2282 var path = PATH.join2(NODEFS.realPath(parent), name);
2284 fs.unlinkSync(path);
2286 if (!e.code) throw e;
2287 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2289 },rmdir:function (parent, name) {
2290 var path = PATH.join2(NODEFS.realPath(parent), name);
2294 if (!e.code) throw e;
2295 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2297 },readdir:function (node) {
2298 var path = NODEFS.realPath(node);
2300 return fs.readdirSync(path);
2302 if (!e.code) throw e;
2303 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2305 },symlink:function (parent, newName, oldPath) {
2306 var newPath = PATH.join2(NODEFS.realPath(parent), newName);
2308 fs.symlinkSync(oldPath, newPath);
2310 if (!e.code) throw e;
2311 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2313 },readlink:function (node) {
2314 var path = NODEFS.realPath(node);
2316 return fs.readlinkSync(path);
2318 if (!e.code) throw e;
2319 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2321 }},stream_ops:{open:function (stream) {
2322 var path = NODEFS.realPath(stream.node);
2324 if (FS.isFile(stream.node.mode)) {
2325 stream.nfd = fs.openSync(path, NODEFS.flagsToPermissionString(stream.flags));
2328 if (!e.code) throw e;
2329 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2331 },close:function (stream) {
2333 if (FS.isFile(stream.node.mode) && stream.nfd) {
2334 fs.closeSync(stream.nfd);
2337 if (!e.code) throw e;
2338 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2340 },read:function (stream, buffer, offset, length, position) {
2341 // FIXME this is terrible.
2342 var nbuffer = new Buffer(length);
2345 res = fs.readSync(stream.nfd, nbuffer, 0, length, position);
2347 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2350 for (var i = 0; i < res; i++) {
2351 buffer[offset + i] = nbuffer[i];
2355 },write:function (stream, buffer, offset, length, position) {
2356 // FIXME this is terrible.
2357 var nbuffer = new Buffer(buffer.subarray(offset, offset + length));
2360 res = fs.writeSync(stream.nfd, nbuffer, 0, length, position);
2362 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2365 },llseek:function (stream, offset, whence) {
2366 var position = offset;
2367 if (whence === 1) { // SEEK_CUR.
2368 position += stream.position;
2369 } else if (whence === 2) { // SEEK_END.
2370 if (FS.isFile(stream.node.mode)) {
2372 var stat = fs.fstatSync(stream.nfd);
2373 position += stat.size;
2375 throw new FS.ErrnoError(ERRNO_CODES[e.code]);
2381 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2384 stream.position = position;
2388 var _stdin=allocate(1, "i32*", ALLOC_STATIC);
2390 var _stdout=allocate(1, "i32*", ALLOC_STATIC);
2392 var _stderr=allocate(1, "i32*", ALLOC_STATIC);
2394 function _fflush(stream) {
2395 // int fflush(FILE *stream);
2396 // http://pubs.opengroup.org/onlinepubs/000095399/functions/fflush.html
2397 // we don't currently perform any user-space buffering of data
2398 }var FS={root:null,mounts:[],devices:[null],streams:[],nextInode:1,nameTable:null,currentPath:"/",initialized:false,ignorePermissions:true,ErrnoError:null,genericErrors:{},handleFSError:function (e) {
2399 if (!(e instanceof FS.ErrnoError)) throw e + ' : ' + stackTrace();
2400 return ___setErrNo(e.errno);
2401 },lookupPath:function (path, opts) {
2402 path = PATH.resolve(FS.cwd(), path);
2409 for (var key in defaults) {
2410 if (opts[key] === undefined) {
2411 opts[key] = defaults[key];
2415 if (opts.recurse_count > 8) { // max recursive lookup of 8
2416 throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
2420 var parts = PATH.normalizeArray(path.split('/').filter(function(p) {
2424 // start at the root
2425 var current = FS.root;
2426 var current_path = '/';
2428 for (var i = 0; i < parts.length; i++) {
2429 var islast = (i === parts.length-1);
2430 if (islast && opts.parent) {
2435 current = FS.lookupNode(current, parts[i]);
2436 current_path = PATH.join2(current_path, parts[i]);
2438 // jump to the mount's root node if this is a mountpoint
2439 if (FS.isMountpoint(current)) {
2440 if (!islast || (islast && opts.follow_mount)) {
2441 current = current.mounted.root;
2445 // by default, lookupPath will not follow a symlink if it is the final path component.
2446 // setting opts.follow = true will override this behavior.
2447 if (!islast || opts.follow) {
2449 while (FS.isLink(current.mode)) {
2450 var link = FS.readlink(current_path);
2451 current_path = PATH.resolve(PATH.dirname(current_path), link);
2453 var lookup = FS.lookupPath(current_path, { recurse_count: opts.recurse_count });
2454 current = lookup.node;
2456 if (count++ > 40) { // limit max consecutive symlinks to 40 (SYMLOOP_MAX).
2457 throw new FS.ErrnoError(ERRNO_CODES.ELOOP);
2463 return { path: current_path, node: current };
2464 },getPath:function (node) {
2467 if (FS.isRoot(node)) {
2468 var mount = node.mount.mountpoint;
2469 if (!path) return mount;
2470 return mount[mount.length-1] !== '/' ? mount + '/' + path : mount + path;
2472 path = path ? node.name + '/' + path : node.name;
2475 },hashName:function (parentid, name) {
2479 for (var i = 0; i < name.length; i++) {
2480 hash = ((hash << 5) - hash + name.charCodeAt(i)) | 0;
2482 return ((parentid + hash) >>> 0) % FS.nameTable.length;
2483 },hashAddNode:function (node) {
2484 var hash = FS.hashName(node.parent.id, node.name);
2485 node.name_next = FS.nameTable[hash];
2486 FS.nameTable[hash] = node;
2487 },hashRemoveNode:function (node) {
2488 var hash = FS.hashName(node.parent.id, node.name);
2489 if (FS.nameTable[hash] === node) {
2490 FS.nameTable[hash] = node.name_next;
2492 var current = FS.nameTable[hash];
2494 if (current.name_next === node) {
2495 current.name_next = node.name_next;
2498 current = current.name_next;
2501 },lookupNode:function (parent, name) {
2502 var err = FS.mayLookup(parent);
2504 throw new FS.ErrnoError(err);
2506 var hash = FS.hashName(parent.id, name);
2507 for (var node = FS.nameTable[hash]; node; node = node.name_next) {
2508 var nodeName = node.name;
2509 if (node.parent.id === parent.id && nodeName === name) {
2513 // if we failed to find it in the cache, call into the VFS
2514 return FS.lookup(parent, name);
2515 },createNode:function (parent, name, mode, rdev) {
2517 FS.FSNode = function(parent, name, mode, rdev) {
2519 parent = this; // root node sets parent to itself
2521 this.parent = parent;
2522 this.mount = parent.mount;
2523 this.mounted = null;
2524 this.id = FS.nextInode++;
2528 this.stream_ops = {};
2532 FS.FSNode.prototype = {};
2535 var readMode = 292 | 73;
2536 var writeMode = 146;
2538 // NOTE we must use Object.defineProperties instead of individual calls to
2539 // Object.defineProperty in order to make closure compiler happy
2540 Object.defineProperties(FS.FSNode.prototype, {
2542 get: function() { return (this.mode & readMode) === readMode; },
2543 set: function(val) { val ? this.mode |= readMode : this.mode &= ~readMode; }
2546 get: function() { return (this.mode & writeMode) === writeMode; },
2547 set: function(val) { val ? this.mode |= writeMode : this.mode &= ~writeMode; }
2550 get: function() { return FS.isDir(this.mode); },
2553 get: function() { return FS.isChrdev(this.mode); },
2558 var node = new FS.FSNode(parent, name, mode, rdev);
2560 FS.hashAddNode(node);
2563 },destroyNode:function (node) {
2564 FS.hashRemoveNode(node);
2565 },isRoot:function (node) {
2566 return node === node.parent;
2567 },isMountpoint:function (node) {
2568 return !!node.mounted;
2569 },isFile:function (mode) {
2570 return (mode & 61440) === 32768;
2571 },isDir:function (mode) {
2572 return (mode & 61440) === 16384;
2573 },isLink:function (mode) {
2574 return (mode & 61440) === 40960;
2575 },isChrdev:function (mode) {
2576 return (mode & 61440) === 8192;
2577 },isBlkdev:function (mode) {
2578 return (mode & 61440) === 24576;
2579 },isFIFO:function (mode) {
2580 return (mode & 61440) === 4096;
2581 },isSocket:function (mode) {
2582 return (mode & 49152) === 49152;
2583 },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) {
2584 var flags = FS.flagModes[str];
2585 if (typeof flags === 'undefined') {
2586 throw new Error('Unknown file open mode: ' + str);
2589 },flagsToPermissionString:function (flag) {
2590 var accmode = flag & 2097155;
2591 var perms = ['r', 'w', 'rw'][accmode];
2596 },nodePermissions:function (node, perms) {
2597 if (FS.ignorePermissions) {
2600 // return 0 if any user, group or owner bits are set.
2601 if (perms.indexOf('r') !== -1 && !(node.mode & 292)) {
2602 return ERRNO_CODES.EACCES;
2603 } else if (perms.indexOf('w') !== -1 && !(node.mode & 146)) {
2604 return ERRNO_CODES.EACCES;
2605 } else if (perms.indexOf('x') !== -1 && !(node.mode & 73)) {
2606 return ERRNO_CODES.EACCES;
2609 },mayLookup:function (dir) {
2610 return FS.nodePermissions(dir, 'x');
2611 },mayCreate:function (dir, name) {
2613 var node = FS.lookupNode(dir, name);
2614 return ERRNO_CODES.EEXIST;
2617 return FS.nodePermissions(dir, 'wx');
2618 },mayDelete:function (dir, name, isdir) {
2621 node = FS.lookupNode(dir, name);
2625 var err = FS.nodePermissions(dir, 'wx');
2630 if (!FS.isDir(node.mode)) {
2631 return ERRNO_CODES.ENOTDIR;
2633 if (FS.isRoot(node) || FS.getPath(node) === FS.cwd()) {
2634 return ERRNO_CODES.EBUSY;
2637 if (FS.isDir(node.mode)) {
2638 return ERRNO_CODES.EISDIR;
2642 },mayOpen:function (node, flags) {
2644 return ERRNO_CODES.ENOENT;
2646 if (FS.isLink(node.mode)) {
2647 return ERRNO_CODES.ELOOP;
2648 } else if (FS.isDir(node.mode)) {
2649 if ((flags & 2097155) !== 0 || // opening for write
2651 return ERRNO_CODES.EISDIR;
2654 return FS.nodePermissions(node, FS.flagsToPermissionString(flags));
2655 },MAX_OPEN_FDS:4096,nextfd:function (fd_start, fd_end) {
2656 fd_start = fd_start || 0;
2657 fd_end = fd_end || FS.MAX_OPEN_FDS;
2658 for (var fd = fd_start; fd <= fd_end; fd++) {
2659 if (!FS.streams[fd]) {
2663 throw new FS.ErrnoError(ERRNO_CODES.EMFILE);
2664 },getStream:function (fd) {
2665 return FS.streams[fd];
2666 },createStream:function (stream, fd_start, fd_end) {
2668 FS.FSStream = function(){};
2669 FS.FSStream.prototype = {};
2671 Object.defineProperties(FS.FSStream.prototype, {
2673 get: function() { return this.node; },
2674 set: function(val) { this.node = val; }
2677 get: function() { return (this.flags & 2097155) !== 1; }
2680 get: function() { return (this.flags & 2097155) !== 0; }
2683 get: function() { return (this.flags & 1024); }
2687 if (stream.__proto__) {
2689 stream.__proto__ = FS.FSStream.prototype;
2691 var newStream = new FS.FSStream();
2692 for (var p in stream) {
2693 newStream[p] = stream[p];
2697 var fd = FS.nextfd(fd_start, fd_end);
2699 FS.streams[fd] = stream;
2701 },closeStream:function (fd) {
2702 FS.streams[fd] = null;
2703 },getStreamFromPtr:function (ptr) {
2704 return FS.streams[ptr - 1];
2705 },getPtrForStream:function (stream) {
2706 return stream ? stream.fd + 1 : 0;
2707 },chrdev_stream_ops:{open:function (stream) {
2708 var device = FS.getDevice(stream.node.rdev);
2709 // override node's stream ops with the device's
2710 stream.stream_ops = device.stream_ops;
2711 // forward the open call
2712 if (stream.stream_ops.open) {
2713 stream.stream_ops.open(stream);
2715 },llseek:function () {
2716 throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
2717 }},major:function (dev) {
2718 return ((dev) >> 8);
2719 },minor:function (dev) {
2720 return ((dev) & 0xff);
2721 },makedev:function (ma, mi) {
2722 return ((ma) << 8 | (mi));
2723 },registerDevice:function (dev, ops) {
2724 FS.devices[dev] = { stream_ops: ops };
2725 },getDevice:function (dev) {
2726 return FS.devices[dev];
2727 },getMounts:function (mount) {
2729 var check = [mount];
2731 while (check.length) {
2732 var m = check.pop();
2736 check.push.apply(check, m.mounts);
2740 },syncfs:function (populate, callback) {
2741 if (typeof(populate) === 'function') {
2742 callback = populate;
2746 var mounts = FS.getMounts(FS.root.mount);
2749 function done(err) {
2751 if (!done.errored) {
2752 done.errored = true;
2753 return callback(err);
2757 if (++completed >= mounts.length) {
2763 mounts.forEach(function (mount) {
2764 if (!mount.type.syncfs) {
2767 mount.type.syncfs(mount, populate, done);
2769 },mount:function (type, opts, mountpoint) {
2770 var root = mountpoint === '/';
2771 var pseudo = !mountpoint;
2774 if (root && FS.root) {
2775 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2776 } else if (!root && !pseudo) {
2777 var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
2779 mountpoint = lookup.path; // use the absolute path
2782 if (FS.isMountpoint(node)) {
2783 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2786 if (!FS.isDir(node.mode)) {
2787 throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
2794 mountpoint: mountpoint,
2798 // create a root node for the fs
2799 var mountRoot = type.mount(mount);
2800 mountRoot.mount = mount;
2801 mount.root = mountRoot;
2804 FS.root = mountRoot;
2806 // set as a mountpoint
2807 node.mounted = mount;
2809 // add the new mount to the current mount's children
2811 node.mount.mounts.push(mount);
2816 },unmount:function (mountpoint) {
2817 var lookup = FS.lookupPath(mountpoint, { follow_mount: false });
2819 if (!FS.isMountpoint(lookup.node)) {
2820 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2823 // destroy the nodes for this mount, and all its child mounts
2824 var node = lookup.node;
2825 var mount = node.mounted;
2826 var mounts = FS.getMounts(mount);
2828 Object.keys(FS.nameTable).forEach(function (hash) {
2829 var current = FS.nameTable[hash];
2832 var next = current.name_next;
2834 if (mounts.indexOf(current.mount) !== -1) {
2835 FS.destroyNode(current);
2842 // no longer a mountpoint
2843 node.mounted = null;
2845 // remove this mount from the child mounts
2846 var idx = node.mount.mounts.indexOf(mount);
2848 node.mount.mounts.splice(idx, 1);
2849 },lookup:function (parent, name) {
2850 return parent.node_ops.lookup(parent, name);
2851 },mknod:function (path, mode, dev) {
2852 var lookup = FS.lookupPath(path, { parent: true });
2853 var parent = lookup.node;
2854 var name = PATH.basename(path);
2855 var err = FS.mayCreate(parent, name);
2857 throw new FS.ErrnoError(err);
2859 if (!parent.node_ops.mknod) {
2860 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2862 return parent.node_ops.mknod(parent, name, mode, dev);
2863 },create:function (path, mode) {
2864 mode = mode !== undefined ? mode : 438 /* 0666 */;
2867 return FS.mknod(path, mode, 0);
2868 },mkdir:function (path, mode) {
2869 mode = mode !== undefined ? mode : 511 /* 0777 */;
2872 return FS.mknod(path, mode, 0);
2873 },mkdev:function (path, mode, dev) {
2874 if (typeof(dev) === 'undefined') {
2876 mode = 438 /* 0666 */;
2879 return FS.mknod(path, mode, dev);
2880 },symlink:function (oldpath, newpath) {
2881 var lookup = FS.lookupPath(newpath, { parent: true });
2882 var parent = lookup.node;
2883 var newname = PATH.basename(newpath);
2884 var err = FS.mayCreate(parent, newname);
2886 throw new FS.ErrnoError(err);
2888 if (!parent.node_ops.symlink) {
2889 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2891 return parent.node_ops.symlink(parent, newname, oldpath);
2892 },rename:function (old_path, new_path) {
2893 var old_dirname = PATH.dirname(old_path);
2894 var new_dirname = PATH.dirname(new_path);
2895 var old_name = PATH.basename(old_path);
2896 var new_name = PATH.basename(new_path);
2897 // parents must exist
2898 var lookup, old_dir, new_dir;
2900 lookup = FS.lookupPath(old_path, { parent: true });
2901 old_dir = lookup.node;
2902 lookup = FS.lookupPath(new_path, { parent: true });
2903 new_dir = lookup.node;
2905 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2907 // need to be part of the same mount
2908 if (old_dir.mount !== new_dir.mount) {
2909 throw new FS.ErrnoError(ERRNO_CODES.EXDEV);
2911 // source must exist
2912 var old_node = FS.lookupNode(old_dir, old_name);
2913 // old path should not be an ancestor of the new path
2914 var relative = PATH.relative(old_path, new_dirname);
2915 if (relative.charAt(0) !== '.') {
2916 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
2918 // new path should not be an ancestor of the old path
2919 relative = PATH.relative(new_path, old_dirname);
2920 if (relative.charAt(0) !== '.') {
2921 throw new FS.ErrnoError(ERRNO_CODES.ENOTEMPTY);
2923 // see if the new path already exists
2926 new_node = FS.lookupNode(new_dir, new_name);
2930 // early out if nothing needs to change
2931 if (old_node === new_node) {
2934 // we'll need to delete the old entry
2935 var isdir = FS.isDir(old_node.mode);
2936 var err = FS.mayDelete(old_dir, old_name, isdir);
2938 throw new FS.ErrnoError(err);
2940 // need delete permissions if we'll be overwriting.
2941 // need create permissions if new doesn't already exist.
2943 FS.mayDelete(new_dir, new_name, isdir) :
2944 FS.mayCreate(new_dir, new_name);
2946 throw new FS.ErrnoError(err);
2948 if (!old_dir.node_ops.rename) {
2949 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2951 if (FS.isMountpoint(old_node) || (new_node && FS.isMountpoint(new_node))) {
2952 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2954 // if we are going to change the parent, check write permissions
2955 if (new_dir !== old_dir) {
2956 err = FS.nodePermissions(old_dir, 'w');
2958 throw new FS.ErrnoError(err);
2961 // remove the node from the lookup hash
2962 FS.hashRemoveNode(old_node);
2963 // do the underlying fs rename
2965 old_dir.node_ops.rename(old_node, new_dir, new_name);
2969 // add the node back to the hash (in case node_ops.rename
2970 // changed its name)
2971 FS.hashAddNode(old_node);
2973 },rmdir:function (path) {
2974 var lookup = FS.lookupPath(path, { parent: true });
2975 var parent = lookup.node;
2976 var name = PATH.basename(path);
2977 var node = FS.lookupNode(parent, name);
2978 var err = FS.mayDelete(parent, name, true);
2980 throw new FS.ErrnoError(err);
2982 if (!parent.node_ops.rmdir) {
2983 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
2985 if (FS.isMountpoint(node)) {
2986 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
2988 parent.node_ops.rmdir(parent, name);
2989 FS.destroyNode(node);
2990 },readdir:function (path) {
2991 var lookup = FS.lookupPath(path, { follow: true });
2992 var node = lookup.node;
2993 if (!node.node_ops.readdir) {
2994 throw new FS.ErrnoError(ERRNO_CODES.ENOTDIR);
2996 return node.node_ops.readdir(node);
2997 },unlink:function (path) {
2998 var lookup = FS.lookupPath(path, { parent: true });
2999 var parent = lookup.node;
3000 var name = PATH.basename(path);
3001 var node = FS.lookupNode(parent, name);
3002 var err = FS.mayDelete(parent, name, false);
3004 // POSIX says unlink should set EPERM, not EISDIR
3005 if (err === ERRNO_CODES.EISDIR) err = ERRNO_CODES.EPERM;
3006 throw new FS.ErrnoError(err);
3008 if (!parent.node_ops.unlink) {
3009 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
3011 if (FS.isMountpoint(node)) {
3012 throw new FS.ErrnoError(ERRNO_CODES.EBUSY);
3014 parent.node_ops.unlink(parent, name);
3015 FS.destroyNode(node);
3016 },readlink:function (path) {
3017 var lookup = FS.lookupPath(path);
3018 var link = lookup.node;
3019 if (!link.node_ops.readlink) {
3020 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3022 return link.node_ops.readlink(link);
3023 },stat:function (path, dontFollow) {
3024 var lookup = FS.lookupPath(path, { follow: !dontFollow });
3025 var node = lookup.node;
3026 if (!node.node_ops.getattr) {
3027 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
3029 return node.node_ops.getattr(node);
3030 },lstat:function (path) {
3031 return FS.stat(path, true);
3032 },chmod:function (path, mode, dontFollow) {
3034 if (typeof path === 'string') {
3035 var lookup = FS.lookupPath(path, { follow: !dontFollow });
3040 if (!node.node_ops.setattr) {
3041 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
3043 node.node_ops.setattr(node, {
3044 mode: (mode & 4095) | (node.mode & ~4095),
3045 timestamp: Date.now()
3047 },lchmod:function (path, mode) {
3048 FS.chmod(path, mode, true);
3049 },fchmod:function (fd, mode) {
3050 var stream = FS.getStream(fd);
3052 throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3054 FS.chmod(stream.node, mode);
3055 },chown:function (path, uid, gid, dontFollow) {
3057 if (typeof path === 'string') {
3058 var lookup = FS.lookupPath(path, { follow: !dontFollow });
3063 if (!node.node_ops.setattr) {
3064 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
3066 node.node_ops.setattr(node, {
3067 timestamp: Date.now()
3068 // we ignore the uid / gid for now
3070 },lchown:function (path, uid, gid) {
3071 FS.chown(path, uid, gid, true);
3072 },fchown:function (fd, uid, gid) {
3073 var stream = FS.getStream(fd);
3075 throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3077 FS.chown(stream.node, uid, gid);
3078 },truncate:function (path, len) {
3080 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3083 if (typeof path === 'string') {
3084 var lookup = FS.lookupPath(path, { follow: true });
3089 if (!node.node_ops.setattr) {
3090 throw new FS.ErrnoError(ERRNO_CODES.EPERM);
3092 if (FS.isDir(node.mode)) {
3093 throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
3095 if (!FS.isFile(node.mode)) {
3096 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3098 var err = FS.nodePermissions(node, 'w');
3100 throw new FS.ErrnoError(err);
3102 node.node_ops.setattr(node, {
3104 timestamp: Date.now()
3106 },ftruncate:function (fd, len) {
3107 var stream = FS.getStream(fd);
3109 throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3111 if ((stream.flags & 2097155) === 0) {
3112 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3114 FS.truncate(stream.node, len);
3115 },utime:function (path, atime, mtime) {
3116 var lookup = FS.lookupPath(path, { follow: true });
3117 var node = lookup.node;
3118 node.node_ops.setattr(node, {
3119 timestamp: Math.max(atime, mtime)
3121 },open:function (path, flags, mode, fd_start, fd_end) {
3122 flags = typeof flags === 'string' ? FS.modeStringToFlags(flags) : flags;
3123 mode = typeof mode === 'undefined' ? 438 /* 0666 */ : mode;
3125 mode = (mode & 4095) | 32768;
3130 if (typeof path === 'object') {
3133 path = PATH.normalize(path);
3135 var lookup = FS.lookupPath(path, {
3136 follow: !(flags & 131072)
3143 // perhaps we need to create the node
3146 // if O_CREAT and O_EXCL are set, error out if the node already exists
3147 if ((flags & 128)) {
3148 throw new FS.ErrnoError(ERRNO_CODES.EEXIST);
3151 // node doesn't exist, try to create it
3152 node = FS.mknod(path, mode, 0);
3156 throw new FS.ErrnoError(ERRNO_CODES.ENOENT);
3158 // can't truncate a device
3159 if (FS.isChrdev(node.mode)) {
3162 // check permissions
3163 var err = FS.mayOpen(node, flags);
3165 throw new FS.ErrnoError(err);
3167 // do truncation if necessary
3168 if ((flags & 512)) {
3169 FS.truncate(node, 0);
3171 // we've already handled these, don't pass down to the underlying vfs
3172 flags &= ~(128 | 512);
3174 // register the stream with the filesystem
3175 var stream = FS.createStream({
3177 path: FS.getPath(node), // we want the absolute path to the node
3181 stream_ops: node.stream_ops,
3182 // used by the file family libc calls (fopen, fwrite, ferror, etc.)
3185 }, fd_start, fd_end);
3186 // call the new stream's open function
3187 if (stream.stream_ops.open) {
3188 stream.stream_ops.open(stream);
3190 if (Module['logReadFiles'] && !(flags & 1)) {
3191 if (!FS.readFiles) FS.readFiles = {};
3192 if (!(path in FS.readFiles)) {
3193 FS.readFiles[path] = 1;
3194 Module['printErr']('read file: ' + path);
3198 },close:function (stream) {
3200 if (stream.stream_ops.close) {
3201 stream.stream_ops.close(stream);
3206 FS.closeStream(stream.fd);
3208 },llseek:function (stream, offset, whence) {
3209 if (!stream.seekable || !stream.stream_ops.llseek) {
3210 throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
3212 return stream.stream_ops.llseek(stream, offset, whence);
3213 },read:function (stream, buffer, offset, length, position) {
3214 if (length < 0 || position < 0) {
3215 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3217 if ((stream.flags & 2097155) === 1) {
3218 throw new FS.ErrnoError(ERRNO_CODES.EBADF);
3220 if (FS.isDir(stream.node.mode)) {
3221 throw new FS.ErrnoError(ERRNO_CODES.EISDIR);
3223 if (!stream.stream_ops.read) {
3224 throw new FS.ErrnoError(ERRNO_CODES.EINVAL);
3227 if (typeof position === 'undefined') {
3228 position = stream.position;
3230 } else if (!stream.seekable) {
3231 throw new FS.ErrnoError(ERRNO_CODES.ESPIPE);
3233 var bytesRead = stream.stream_ops.read(stream, buffer, offset, length, position);
3234 if (!seeking) stream.position += bytesRead;
3236 },write:function (stream, buffer, offset, length, position, canOwn) {