diff --git a/emscripten/browserfs.js b/emscripten/browserfs.js new file mode 100644 index 0000000000..9f4989497b --- /dev/null +++ b/emscripten/browserfs.js @@ -0,0 +1,11847 @@ +(function() { +/** +* This file installs all of the polyfills that BrowserFS requires. +*/ +// IE < 9 does not define this function. +if (!Date.now) { + Date.now = function now() { + return new Date().getTime(); + }; +} + +// IE < 9 does not define this function. +if (!Array.isArray) { + Array.isArray = function (vArg) { + return Object.prototype.toString.call(vArg) === "[object Array]"; + }; +} + +// IE < 9 does not define this function. +// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys +if (!Object.keys) { + Object.keys = (function () { + + var hasOwnProperty = Object.prototype.hasOwnProperty, hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], dontEnumsLength = dontEnums.length; + + return function (obj) { + if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = [], prop, i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + return result; + }; + }()); +} + +// IE substr does not support negative indices +if ('ab'.substr(-1) !== 'b') { + String.prototype.substr = function (substr) { + return function (start, length) { + // did we get a negative start, calculate how much it is from the + // beginning of the string + if (start < 0) + start = this.length + start; + + // call the original function + return substr.call(this, start, length); + }; + }(String.prototype.substr); +} + +// IE < 9 does not support forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, scope) { + for (var i = 0; i < this.length; ++i) { + if (i in this) { + fn.call(scope, this[i], i, this); + } + } + }; +} + +// Only IE10 has setImmediate. +// @todo: Determine viability of switching to the 'proper' polyfill for this. +if (typeof setImmediate === 'undefined') { + // XXX avoid importing the global module. + var gScope = typeof window !== 'undefined' ? window : typeof self !== 'undefined' ? self : global; + var timeouts = []; + var messageName = "zero-timeout-message"; + var canUsePostMessage = function () { + if (typeof gScope.importScripts !== 'undefined' || !gScope.postMessage) { + return false; + } + var postMessageIsAsync = true; + var oldOnMessage = gScope.onmessage; + gScope.onmessage = function () { + postMessageIsAsync = false; + }; + gScope.postMessage('', '*'); + gScope.onmessage = oldOnMessage; + return postMessageIsAsync; + }; + if (canUsePostMessage()) { + gScope.setImmediate = function (fn) { + timeouts.push(fn); + gScope.postMessage(messageName, "*"); + }; + var handleMessage = function (event) { + if (event.source === self && event.data === messageName) { + if (event.stopPropagation) { + event.stopPropagation(); + } else { + event.cancelBubble = true; + } + if (timeouts.length > 0) { + var fn = timeouts.shift(); + return fn(); + } + } + }; + if (gScope.addEventListener) { + gScope.addEventListener('message', handleMessage, true); + } else { + gScope.attachEvent('onmessage', handleMessage); + } + } else if (gScope.MessageChannel) { + // WebWorker MessageChannel + var channel = new gScope.MessageChannel(); + channel.port1.onmessage = function (event) { + if (timeouts.length > 0) { + return timeouts.shift()(); + } + }; + gScope.setImmediate = function (fn) { + timeouts.push(fn); + channel.port2.postMessage(''); + }; + } else { + gScope.setImmediate = function (fn) { + return setTimeout(fn, 0); + var scriptEl = window.document.createElement("script"); + scriptEl.onreadystatechange = function () { + fn(); + scriptEl.onreadystatechange = null; + scriptEl.parentNode.removeChild(scriptEl); + return scriptEl = null; + }; + gScope.document.documentElement.appendChild(scriptEl); + }; + } +} + +// IE<9 does not define indexOf. +// From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/indexOf +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function (searchElement, fromIndex) { + if (typeof fromIndex === "undefined") { fromIndex = 0; } + if (!this) { + throw new TypeError(); + } + + var length = this.length; + if (length === 0 || pivot >= length) { + return -1; + } + + var pivot = fromIndex; + if (pivot < 0) { + pivot = length + pivot; + } + + for (var i = pivot; i < length; i++) { + if (this[i] === searchElement) { + return i; + } + } + return -1; + }; +} + +// IE<9 does not support forEach +// From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach +if (!Array.prototype.forEach) { + Array.prototype.forEach = function (fn, scope) { + var i, len; + for (i = 0, len = this.length; i < len; ++i) { + if (i in this) { + fn.call(scope, this[i], i, this); + } + } + }; +} + +// IE<9 does not support map +// From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map +if (!Array.prototype.map) { + Array.prototype.map = function (callback, thisArg) { + var T, A, k; + if (this == null) { + throw new TypeError(" this is null or not defined"); + } + + // 1. Let O be the result of calling ToObject passing the |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + " is not a function"); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (thisArg) { + T = thisArg; + } + + // 6. Let A be a new array created as if by the expression new Array(len) where Array is + // the standard built-in constructor with that name and len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + while (k < len) { + var kValue, mappedValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + // i. Let kValue be the result of calling the Get internal method of O with argument Pk. + kValue = O[k]; + + // ii. Let mappedValue be the result of calling the Call internal method of callback + // with T as the this value and argument list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); + + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true}, + // and false. + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true }); + // For best browser support, use the following: + A[k] = mappedValue; + } + + // d. Increase k by 1. + k++; + } + + // 9. return A + return A; + }; +} + +/** +* IE9 and below only: Injects a VBScript function that converts the +* 'responseBody' attribute of an XMLHttpRequest into a bytestring. +* From: http://miskun.com/javascript/internet-explorer-and-binary-files-data-access/#comment-17 +* +* This must be performed *before* the page finishes loading, otherwise +* document.write will refresh the page. :( +* +* This is harmless to inject into non-IE browsers. +*/ +if (typeof document !== 'undefined' && window['chrome'] === undefined) { + document.write("\r\n" + "\r\n"); +} +//# sourceMappingURL=polyfills.js.map + + + +/** + * @license almond 0.3.0 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/almond for details + */ +//Going sloppy to avoid 'use strict' string cost, but strict practices should +//be followed. +/*jslint sloppy: true */ +/*global setTimeout: false */ + +var requirejs, require, define; +(function (undef) { + var main, req, makeMap, handlers, + defined = {}, + waiting = {}, + config = {}, + defining = {}, + hasOwn = Object.prototype.hasOwnProperty, + aps = [].slice, + jsSuffixRegExp = /\.js$/; + + function hasProp(obj, prop) { + return hasOwn.call(obj, prop); + } + + /** + * Given a relative module name, like ./something, normalize it to + * a real name that can be mapped to a path. + * @param {String} name the relative name + * @param {String} baseName a real name that the name arg is relative + * to. + * @returns {String} normalized name + */ + function normalize(name, baseName) { + var nameParts, nameSegment, mapValue, foundMap, lastIndex, + foundI, foundStarMap, starI, i, j, part, + baseParts = baseName && baseName.split("/"), + map = config.map, + starMap = (map && map['*']) || {}; + + //Adjust any relative paths. + if (name && name.charAt(0) === ".") { + //If have a base name, try to normalize against it, + //otherwise, assume it is a top-level require that will + //be relative to baseUrl in the end. + if (baseName) { + //Convert baseName to array, and lop off the last part, + //so that . matches that "directory" and not name of the baseName's + //module. For instance, baseName of "one/two/three", maps to + //"one/two/three.js", but we want the directory, "one/two" for + //this normalization. + baseParts = baseParts.slice(0, baseParts.length - 1); + name = name.split('/'); + lastIndex = name.length - 1; + + // Node .js allowance: + if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) { + name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, ''); + } + + name = baseParts.concat(name); + + //start trimDots + for (i = 0; i < name.length; i += 1) { + part = name[i]; + if (part === ".") { + name.splice(i, 1); + i -= 1; + } else if (part === "..") { + if (i === 1 && (name[2] === '..' || name[0] === '..')) { + //End of the line. Keep at least one non-dot + //path segment at the front so it can be mapped + //correctly to disk. Otherwise, there is likely + //no path mapping for a path starting with '..'. + //This can still fail, but catches the most reasonable + //uses of .. + break; + } else if (i > 0) { + name.splice(i - 1, 2); + i -= 2; + } + } + } + //end trimDots + + name = name.join("/"); + } else if (name.indexOf('./') === 0) { + // No baseName, so this is ID is resolved relative + // to baseUrl, pull off the leading dot. + name = name.substring(2); + } + } + + //Apply map config if available. + if ((baseParts || starMap) && map) { + nameParts = name.split('/'); + + for (i = nameParts.length; i > 0; i -= 1) { + nameSegment = nameParts.slice(0, i).join("/"); + + if (baseParts) { + //Find the longest baseName segment match in the config. + //So, do joins on the biggest to smallest lengths of baseParts. + for (j = baseParts.length; j > 0; j -= 1) { + mapValue = map[baseParts.slice(0, j).join('/')]; + + //baseName segment has config, find if it has one for + //this name. + if (mapValue) { + mapValue = mapValue[nameSegment]; + if (mapValue) { + //Match, update name to the new value. + foundMap = mapValue; + foundI = i; + break; + } + } + } + } + + if (foundMap) { + break; + } + + //Check for a star map match, but just hold on to it, + //if there is a shorter segment match later in a matching + //config, then favor over this star map. + if (!foundStarMap && starMap && starMap[nameSegment]) { + foundStarMap = starMap[nameSegment]; + starI = i; + } + } + + if (!foundMap && foundStarMap) { + foundMap = foundStarMap; + foundI = starI; + } + + if (foundMap) { + nameParts.splice(0, foundI, foundMap); + name = nameParts.join('/'); + } + } + + return name; + } + + function makeRequire(relName, forceSync) { + return function () { + //A version of a require function that passes a moduleName + //value for items that may need to + //look up paths relative to the moduleName + var args = aps.call(arguments, 0); + + //If first arg is not require('string'), and there is only + //one arg, it is the array form without a callback. Insert + //a null so that the following concat is correct. + if (typeof args[0] !== 'string' && args.length === 1) { + args.push(null); + } + return req.apply(undef, args.concat([relName, forceSync])); + }; + } + + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(depName) { + return function (value) { + defined[depName] = value; + }; + } + + function callDep(name) { + if (hasProp(waiting, name)) { + var args = waiting[name]; + delete waiting[name]; + defining[name] = true; + main.apply(undef, args); + } + + if (!hasProp(defined, name) && !hasProp(defining, name)) { + throw new Error('No ' + name); + } + return defined[name]; + } + + //Turns a plugin!resource to [plugin, resource] + //with the plugin being undefined if the name + //did not have a plugin prefix. + function splitPrefix(name) { + var prefix, + index = name ? name.indexOf('!') : -1; + if (index > -1) { + prefix = name.substring(0, index); + name = name.substring(index + 1, name.length); + } + return [prefix, name]; + } + + /** + * Makes a name map, normalizing the name, and using a plugin + * for normalization if necessary. Grabs a ref to plugin + * too, as an optimization. + */ + makeMap = function (name, relName) { + var plugin, + parts = splitPrefix(name), + prefix = parts[0]; + + name = parts[1]; + + if (prefix) { + prefix = normalize(prefix, relName); + plugin = callDep(prefix); + } + + //Normalize according + if (prefix) { + if (plugin && plugin.normalize) { + name = plugin.normalize(name, makeNormalize(relName)); + } else { + name = normalize(name, relName); + } + } else { + name = normalize(name, relName); + parts = splitPrefix(name); + prefix = parts[0]; + name = parts[1]; + if (prefix) { + plugin = callDep(prefix); + } + } + + //Using ridiculous property names for space reasons + return { + f: prefix ? prefix + '!' + name : name, //fullName + n: name, + pr: prefix, + p: plugin + }; + }; + + function makeConfig(name) { + return function () { + return (config && config.config && config.config[name]) || {}; + }; + } + + handlers = { + require: function (name) { + return makeRequire(name); + }, + exports: function (name) { + var e = defined[name]; + if (typeof e !== 'undefined') { + return e; + } else { + return (defined[name] = {}); + } + }, + module: function (name) { + return { + id: name, + uri: '', + exports: defined[name], + config: makeConfig(name) + }; + } + }; + + main = function (name, deps, callback, relName) { + var cjsModule, depName, ret, map, i, + args = [], + callbackType = typeof callback, + usingExports; + + //Use name if no relName + relName = relName || name; + + //Call the callback to define the module, if necessary. + if (callbackType === 'undefined' || callbackType === 'function') { + //Pull out the defined dependencies and pass the ordered + //values to the callback. + //Default to [require, exports, module] if no deps + deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps; + for (i = 0; i < deps.length; i += 1) { + map = makeMap(deps[i], relName); + depName = map.f; + + //Fast path CommonJS standard dependencies. + if (depName === "require") { + args[i] = handlers.require(name); + } else if (depName === "exports") { + //CommonJS module spec 1.1 + args[i] = handlers.exports(name); + usingExports = true; + } else if (depName === "module") { + //CommonJS module spec 1.1 + cjsModule = args[i] = handlers.module(name); + } else if (hasProp(defined, depName) || + hasProp(waiting, depName) || + hasProp(defining, depName)) { + args[i] = callDep(depName); + } else if (map.p) { + map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {}); + args[i] = defined[depName]; + } else { + throw new Error(name + ' missing ' + depName); + } + } + + ret = callback ? callback.apply(defined[name], args) : undefined; + + if (name) { + //If setting exports via "module" is in play, + //favor that over return value and exports. After that, + //favor a non-undefined return value over exports use. + if (cjsModule && cjsModule.exports !== undef && + cjsModule.exports !== defined[name]) { + defined[name] = cjsModule.exports; + } else if (ret !== undef || !usingExports) { + //Use the return value from the function. + defined[name] = ret; + } + } + } else if (name) { + //May just be an object definition for the module. Only + //worry about defining if have a module name. + defined[name] = callback; + } + }; + + requirejs = require = req = function (deps, callback, relName, forceSync, alt) { + if (typeof deps === "string") { + if (handlers[deps]) { + //callback in this case is really relName + return handlers[deps](callback); + } + //Just return the module wanted. In this scenario, the + //deps arg is the module name, and second arg (if passed) + //is just the relName. + //Normalize module name, if it contains . or .. + return callDep(makeMap(deps, callback).f); + } else if (!deps.splice) { + //deps is a config object, not an array. + config = deps; + if (config.deps) { + req(config.deps, config.callback); + } + if (!callback) { + return; + } + + if (callback.splice) { + //callback is an array, which means it is a dependency list. + //Adjust args if there are dependencies + deps = callback; + callback = relName; + relName = null; + } else { + deps = undef; + } + } + + //Support require(['a']) + callback = callback || function () {}; + + //If relName is a function, it is an errback handler, + //so remove it. + if (typeof relName === 'function') { + relName = forceSync; + forceSync = alt; + } + + //Simulate async callback; + if (forceSync) { + main(undef, deps, callback, relName); + } else { + //Using a non-zero value because of concern for what old browsers + //do, and latest browsers "upgrade" to 4 if lower value is used: + //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout: + //If want a value immediately, use require('id') instead -- something + //that works in almond on the global level, but not guaranteed and + //unlikely to work in other AMD implementations. + setTimeout(function () { + main(undef, deps, callback, relName); + }, 4); + } + + return req; + }; + + /** + * Just drops the config on the floor, but returns req in case + * the config return value is used. + */ + req.config = function (cfg) { + return req(cfg); + }; + + /** + * Expose module registry for debugging and tooling + */ + requirejs._defined = defined; + + define = function (name, deps, callback) { + + //This module may not have dependencies + if (!deps.splice) { + //deps is not an array, so probably means + //an object literal or factory function for + //the value. Adjust args. + callback = deps; + deps = []; + } + + if (!hasProp(defined, name) && !hasProp(waiting, name)) { + waiting[name] = [name, deps, callback]; + } + }; + + define.amd = { + jQuery: true + }; +}()); + +define("../../vendor/almond/almond", function(){}); + +/** +* @module core/api_error +*/ +define('core/api_error',["require", "exports"], function(require, exports) { + /** + * Standard libc error codes. Add more to this enum and ErrorStrings as they are + * needed. + * @url http://www.gnu.org/software/libc/manual/html_node/Error-Codes.html + */ + (function (ErrorCode) { + ErrorCode[ErrorCode["EPERM"] = 0] = "EPERM"; + ErrorCode[ErrorCode["ENOENT"] = 1] = "ENOENT"; + ErrorCode[ErrorCode["EIO"] = 2] = "EIO"; + ErrorCode[ErrorCode["EBADF"] = 3] = "EBADF"; + ErrorCode[ErrorCode["EACCES"] = 4] = "EACCES"; + ErrorCode[ErrorCode["EBUSY"] = 5] = "EBUSY"; + ErrorCode[ErrorCode["EEXIST"] = 6] = "EEXIST"; + ErrorCode[ErrorCode["ENOTDIR"] = 7] = "ENOTDIR"; + ErrorCode[ErrorCode["EISDIR"] = 8] = "EISDIR"; + ErrorCode[ErrorCode["EINVAL"] = 9] = "EINVAL"; + ErrorCode[ErrorCode["EFBIG"] = 10] = "EFBIG"; + ErrorCode[ErrorCode["ENOSPC"] = 11] = "ENOSPC"; + ErrorCode[ErrorCode["EROFS"] = 12] = "EROFS"; + ErrorCode[ErrorCode["ENOTEMPTY"] = 13] = "ENOTEMPTY"; + ErrorCode[ErrorCode["ENOTSUP"] = 14] = "ENOTSUP"; + })(exports.ErrorCode || (exports.ErrorCode = {})); + var ErrorCode = exports.ErrorCode; + + /** + * Strings associated with each error code. + */ + var ErrorStrings = {}; + ErrorStrings[0 /* EPERM */] = 'Operation not permitted.'; + ErrorStrings[1 /* ENOENT */] = 'No such file or directory.'; + ErrorStrings[2 /* EIO */] = 'Input/output error.'; + ErrorStrings[3 /* EBADF */] = 'Bad file descriptor.'; + ErrorStrings[4 /* EACCES */] = 'Permission denied.'; + ErrorStrings[5 /* EBUSY */] = 'Resource busy or locked.'; + ErrorStrings[6 /* EEXIST */] = 'File exists.'; + ErrorStrings[7 /* ENOTDIR */] = 'File is not a directory.'; + ErrorStrings[8 /* EISDIR */] = 'File is a directory.'; + ErrorStrings[9 /* EINVAL */] = 'Invalid argument.'; + ErrorStrings[10 /* EFBIG */] = 'File is too big.'; + ErrorStrings[11 /* ENOSPC */] = 'No space left on disk.'; + ErrorStrings[12 /* EROFS */] = 'Cannot modify a read-only file system.'; + ErrorStrings[13 /* ENOTEMPTY */] = 'Directory is not empty.'; + ErrorStrings[14 /* ENOTSUP */] = 'Operation is not supported.'; + + /** + * Represents a BrowserFS error. Passed back to applications after a failed + * call to the BrowserFS API. + */ + var ApiError = (function () { + /** + * Represents a BrowserFS error. Passed back to applications after a failed + * call to the BrowserFS API. + * + * Error codes mirror those returned by regular Unix file operations, which is + * what Node returns. + * @constructor ApiError + * @param type The type of the error. + * @param [message] A descriptive error message. + */ + function ApiError(type, message) { + this.type = type; + this.code = ErrorCode[type]; + if (message != null) { + this.message = message; + } else { + this.message = ErrorStrings[type]; + } + } + /** + * @return A friendly error message. + */ + ApiError.prototype.toString = function () { + return this.code + ": " + ErrorStrings[this.type] + " " + this.message; + }; + + ApiError.FileError = function (code, p) { + return new ApiError(code, p + ": " + ErrorStrings[code]); + }; + ApiError.ENOENT = function (path) { + return this.FileError(1 /* ENOENT */, path); + }; + + ApiError.EEXIST = function (path) { + return this.FileError(6 /* EEXIST */, path); + }; + + ApiError.EISDIR = function (path) { + return this.FileError(8 /* EISDIR */, path); + }; + + ApiError.ENOTDIR = function (path) { + return this.FileError(7 /* ENOTDIR */, path); + }; + + ApiError.EPERM = function (path) { + return this.FileError(0 /* EPERM */, path); + }; + return ApiError; + })(); + exports.ApiError = ApiError; +}); +//# sourceMappingURL=api_error.js.map +; +define('core/buffer_core',["require", "exports", './api_error'], function(require, exports, api_error) { + var FLOAT_POS_INFINITY = Math.pow(2, 128); + var FLOAT_NEG_INFINITY = -1 * FLOAT_POS_INFINITY; + var FLOAT_POS_INFINITY_AS_INT = 0x7F800000; + var FLOAT_NEG_INFINITY_AS_INT = -8388608; + var FLOAT_NaN_AS_INT = 0x7fc00000; + + + + /** + * Contains common definitions for most of the BufferCore classes. + * Subclasses only need to implement write/readUInt8 for full functionality. + */ + var BufferCoreCommon = (function () { + function BufferCoreCommon() { + } + BufferCoreCommon.prototype.getLength = function () { + throw new api_error.ApiError(14 /* ENOTSUP */, 'BufferCore implementations should implement getLength.'); + }; + BufferCoreCommon.prototype.writeInt8 = function (i, data) { + // Pack the sign bit as the highest bit. + // Note that we keep the highest bit in the value byte as the sign bit if it + // exists. + this.writeUInt8(i, (data & 0xFF) | ((data & 0x80000000) >>> 24)); + }; + BufferCoreCommon.prototype.writeInt16LE = function (i, data) { + this.writeUInt8(i, data & 0xFF); + + // Pack the sign bit as the highest bit. + // Note that we keep the highest bit in the value byte as the sign bit if it + // exists. + this.writeUInt8(i + 1, ((data >>> 8) & 0xFF) | ((data & 0x80000000) >>> 24)); + }; + BufferCoreCommon.prototype.writeInt16BE = function (i, data) { + this.writeUInt8(i + 1, data & 0xFF); + + // Pack the sign bit as the highest bit. + // Note that we keep the highest bit in the value byte as the sign bit if it + // exists. + this.writeUInt8(i, ((data >>> 8) & 0xFF) | ((data & 0x80000000) >>> 24)); + }; + BufferCoreCommon.prototype.writeInt32LE = function (i, data) { + this.writeUInt8(i, data & 0xFF); + this.writeUInt8(i + 1, (data >>> 8) & 0xFF); + this.writeUInt8(i + 2, (data >>> 16) & 0xFF); + this.writeUInt8(i + 3, (data >>> 24) & 0xFF); + }; + BufferCoreCommon.prototype.writeInt32BE = function (i, data) { + this.writeUInt8(i + 3, data & 0xFF); + this.writeUInt8(i + 2, (data >>> 8) & 0xFF); + this.writeUInt8(i + 1, (data >>> 16) & 0xFF); + this.writeUInt8(i, (data >>> 24) & 0xFF); + }; + BufferCoreCommon.prototype.writeUInt8 = function (i, data) { + throw new api_error.ApiError(14 /* ENOTSUP */, 'BufferCore implementations should implement writeUInt8.'); + }; + BufferCoreCommon.prototype.writeUInt16LE = function (i, data) { + this.writeUInt8(i, data & 0xFF); + this.writeUInt8(i + 1, (data >> 8) & 0xFF); + }; + BufferCoreCommon.prototype.writeUInt16BE = function (i, data) { + this.writeUInt8(i + 1, data & 0xFF); + this.writeUInt8(i, (data >> 8) & 0xFF); + }; + BufferCoreCommon.prototype.writeUInt32LE = function (i, data) { + this.writeInt32LE(i, data | 0); + }; + BufferCoreCommon.prototype.writeUInt32BE = function (i, data) { + this.writeInt32BE(i, data | 0); + }; + BufferCoreCommon.prototype.writeFloatLE = function (i, data) { + this.writeInt32LE(i, this.float2intbits(data)); + }; + BufferCoreCommon.prototype.writeFloatBE = function (i, data) { + this.writeInt32BE(i, this.float2intbits(data)); + }; + BufferCoreCommon.prototype.writeDoubleLE = function (i, data) { + var doubleBits = this.double2longbits(data); + this.writeInt32LE(i, doubleBits[0]); + this.writeInt32LE(i + 4, doubleBits[1]); + }; + BufferCoreCommon.prototype.writeDoubleBE = function (i, data) { + var doubleBits = this.double2longbits(data); + this.writeInt32BE(i + 4, doubleBits[0]); + this.writeInt32BE(i, doubleBits[1]); + }; + BufferCoreCommon.prototype.readInt8 = function (i) { + var val = this.readUInt8(i); + if (val & 0x80) { + // Sign bit is set, so perform sign extension. + return val | 0xFFFFFF80; + } else { + return val; + } + }; + BufferCoreCommon.prototype.readInt16LE = function (i) { + var val = this.readUInt16LE(i); + if (val & 0x8000) { + // Sign bit is set, so perform sign extension. + return val | 0xFFFF8000; + } else { + return val; + } + }; + BufferCoreCommon.prototype.readInt16BE = function (i) { + var val = this.readUInt16BE(i); + if (val & 0x8000) { + // Sign bit is set, so perform sign extension. + return val | 0xFFFF8000; + } else { + return val; + } + }; + BufferCoreCommon.prototype.readInt32LE = function (i) { + return this.readUInt32LE(i) | 0; + }; + BufferCoreCommon.prototype.readInt32BE = function (i) { + return this.readUInt32BE(i) | 0; + }; + BufferCoreCommon.prototype.readUInt8 = function (i) { + throw new api_error.ApiError(14 /* ENOTSUP */, 'BufferCore implementations should implement readUInt8.'); + }; + BufferCoreCommon.prototype.readUInt16LE = function (i) { + return (this.readUInt8(i + 1) << 8) | this.readUInt8(i); + }; + BufferCoreCommon.prototype.readUInt16BE = function (i) { + return (this.readUInt8(i) << 8) | this.readUInt8(i + 1); + }; + BufferCoreCommon.prototype.readUInt32LE = function (i) { + return ((this.readUInt8(i + 3) << 24) | (this.readUInt8(i + 2) << 16) | (this.readUInt8(i + 1) << 8) | this.readUInt8(i)) >>> 0; + }; + BufferCoreCommon.prototype.readUInt32BE = function (i) { + return ((this.readUInt8(i) << 24) | (this.readUInt8(i + 1) << 16) | (this.readUInt8(i + 2) << 8) | this.readUInt8(i + 3)) >>> 0; + }; + BufferCoreCommon.prototype.readFloatLE = function (i) { + return this.intbits2float(this.readInt32LE(i)); + }; + BufferCoreCommon.prototype.readFloatBE = function (i) { + return this.intbits2float(this.readInt32BE(i)); + }; + BufferCoreCommon.prototype.readDoubleLE = function (i) { + return this.longbits2double(this.readInt32LE(i + 4), this.readInt32LE(i)); + }; + BufferCoreCommon.prototype.readDoubleBE = function (i) { + return this.longbits2double(this.readInt32BE(i), this.readInt32BE(i + 4)); + }; + BufferCoreCommon.prototype.copy = function (start, end) { + throw new api_error.ApiError(14 /* ENOTSUP */, 'BufferCore implementations should implement copy.'); + }; + BufferCoreCommon.prototype.fill = function (value, start, end) { + for (var i = start; i < end; i++) { + this.writeUInt8(i, value); + } + }; + + BufferCoreCommon.prototype.float2intbits = function (f_val) { + var exp, f_view, i_view, sig, sign; + + // Special cases! + if (f_val === 0) { + return 0; + } + + // We map the infinities to JavaScript infinities. Map them back. + if (f_val === Number.POSITIVE_INFINITY) { + return FLOAT_POS_INFINITY_AS_INT; + } + if (f_val === Number.NEGATIVE_INFINITY) { + return FLOAT_NEG_INFINITY_AS_INT; + } + + // Convert JavaScript NaN to Float NaN value. + if (isNaN(f_val)) { + return FLOAT_NaN_AS_INT; + } + + // We have more bits of precision than a float, so below we round to + // the nearest significand. This appears to be what the x86 + // Java does for normal floating point operations. + sign = f_val < 0 ? 1 : 0; + f_val = Math.abs(f_val); + + // Subnormal zone! + // (−1)^signbits×2^−126×0.significandbits + // Largest subnormal magnitude: + // 0000 0000 0111 1111 1111 1111 1111 1111 + // Smallest subnormal magnitude: + // 0000 0000 0000 0000 0000 0000 0000 0001 + if (f_val <= 1.1754942106924411e-38 && f_val >= 1.4012984643248170e-45) { + exp = 0; + sig = Math.round((f_val / Math.pow(2, -126)) * Math.pow(2, 23)); + return (sign << 31) | (exp << 23) | sig; + } else { + // Regular FP numbers + exp = Math.floor(Math.log(f_val) / Math.LN2); + sig = Math.round((f_val / Math.pow(2, exp) - 1) * Math.pow(2, 23)); + return (sign << 31) | ((exp + 127) << 23) | sig; + } + }; + + BufferCoreCommon.prototype.double2longbits = function (d_val) { + var d_view, exp, high_bits, i_view, sig, sign; + + // Special cases + if (d_val === 0) { + return [0, 0]; + } + if (d_val === Number.POSITIVE_INFINITY) { + // High bits: 0111 1111 1111 0000 0000 0000 0000 0000 + // Low bits: 0000 0000 0000 0000 0000 0000 0000 0000 + return [0, 2146435072]; + } else if (d_val === Number.NEGATIVE_INFINITY) { + // High bits: 1111 1111 1111 0000 0000 0000 0000 0000 + // Low bits: 0000 0000 0000 0000 0000 0000 0000 0000 + return [0, -1048576]; + } else if (isNaN(d_val)) { + // High bits: 0111 1111 1111 1000 0000 0000 0000 0000 + // Low bits: 0000 0000 0000 0000 0000 0000 0000 0000 + return [0, 2146959360]; + } + sign = d_val < 0 ? 1 << 31 : 0; + d_val = Math.abs(d_val); + + // Check if it is a subnormal number. + // (-1)s × 0.f × 2-1022 + // Largest subnormal magnitude: + // 0000 0000 0000 1111 1111 1111 1111 1111 + // 1111 1111 1111 1111 1111 1111 1111 1111 + // Smallest subnormal magnitude: + // 0000 0000 0000 0000 0000 0000 0000 0000 + // 0000 0000 0000 0000 0000 0000 0000 0001 + if (d_val <= 2.2250738585072010e-308 && d_val >= 5.0000000000000000e-324) { + exp = 0; + sig = (d_val / Math.pow(2, -1022)) * Math.pow(2, 52); + } else { + exp = Math.floor(Math.log(d_val) / Math.LN2); + + // If d_val is close to a power of two, there's a chance that exp + // will be 1 greater than it should due to loss of accuracy in the + // log result. + if (d_val < Math.pow(2, exp)) { + exp = exp - 1; + } + sig = (d_val / Math.pow(2, exp) - 1) * Math.pow(2, 52); + exp = (exp + 1023) << 20; + } + + // Simulate >> 32 + high_bits = ((sig * Math.pow(2, -32)) | 0) | sign | exp; + return [sig & 0xFFFF, high_bits]; + }; + + BufferCoreCommon.prototype.intbits2float = function (int32) { + // Map +/- infinity to JavaScript equivalents + if (int32 === FLOAT_POS_INFINITY_AS_INT) { + return Number.POSITIVE_INFINITY; + } else if (int32 === FLOAT_NEG_INFINITY_AS_INT) { + return Number.NEGATIVE_INFINITY; + } + var sign = (int32 & 0x80000000) >>> 31; + var exponent = (int32 & 0x7F800000) >>> 23; + var significand = int32 & 0x007FFFFF; + var value; + if (exponent === 0) { + value = Math.pow(-1, sign) * significand * Math.pow(2, -149); + } else { + value = Math.pow(-1, sign) * (1 + significand * Math.pow(2, -23)) * Math.pow(2, exponent - 127); + } + + // NaN check + if (value < FLOAT_NEG_INFINITY || value > FLOAT_POS_INFINITY) { + value = NaN; + } + return value; + }; + + BufferCoreCommon.prototype.longbits2double = function (uint32_a, uint32_b) { + var sign = (uint32_a & 0x80000000) >>> 31; + var exponent = (uint32_a & 0x7FF00000) >>> 20; + var significand = ((uint32_a & 0x000FFFFF) * Math.pow(2, 32)) + uint32_b; + + // Special values! + if (exponent === 0 && significand === 0) { + return 0; + } + if (exponent === 2047) { + if (significand === 0) { + if (sign === 1) { + return Number.NEGATIVE_INFINITY; + } + return Number.POSITIVE_INFINITY; + } else { + return NaN; + } + } + if (exponent === 0) + return Math.pow(-1, sign) * significand * Math.pow(2, -1074); + return Math.pow(-1, sign) * (1 + significand * Math.pow(2, -52)) * Math.pow(2, exponent - 1023); + }; + return BufferCoreCommon; + })(); + exports.BufferCoreCommon = BufferCoreCommon; +}); +//# sourceMappingURL=buffer_core.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/buffer_core_array',["require", "exports", './buffer_core'], function(require, exports, buffer_core) { + // Used to clear segments of an array index. + var clearMasks = [0xFFFFFF00, 0xFFFF00FF, 0xFF00FFFF, 0x00FFFFFF]; + + /** + * Implementation of BufferCore that is backed by an array of 32-bit ints. + * Data is stored little endian. + * Example: Bytes 0 through 3 are present in the first int: + * BYTE 3 BYTE 2 BYTE 1 BYTE 0 + * 0000 0000 | 0000 0000 | 0000 0000 | 0000 0000 + */ + var BufferCoreArray = (function (_super) { + __extends(BufferCoreArray, _super); + function BufferCoreArray(length) { + _super.call(this); + this.length = length; + this.buff = new Array(Math.ceil(length / 4)); + + // Zero-fill the array. + var bufflen = this.buff.length; + for (var i = 0; i < bufflen; i++) { + this.buff[i] = 0; + } + } + BufferCoreArray.isAvailable = function () { + return true; + }; + + BufferCoreArray.prototype.getLength = function () { + return this.length; + }; + BufferCoreArray.prototype.writeUInt8 = function (i, data) { + data &= 0xFF; + + // Which int? (Equivalent to (i/4)|0) + var arrIdx = i >> 2; + + // Which offset? (Equivalent to i - arrIdx*4) + var intIdx = i & 3; + this.buff[arrIdx] = this.buff[arrIdx] & clearMasks[intIdx]; + this.buff[arrIdx] = this.buff[arrIdx] | (data << (intIdx << 3)); + }; + BufferCoreArray.prototype.readUInt8 = function (i) { + // Which int? + var arrIdx = i >> 2; + + // Which offset? + var intIdx = i & 3; + + // Bring the data we want into the lowest 8 bits, and truncate. + return (this.buff[arrIdx] >> (intIdx << 3)) & 0xFF; + }; + BufferCoreArray.prototype.copy = function (start, end) { + // Stupid unoptimized copy. Later, we could do optimizations when aligned. + var newBC = new BufferCoreArray(end - start); + for (var i = start; i < end; i++) { + newBC.writeUInt8(i - start, this.readUInt8(i)); + } + return newBC; + }; + return BufferCoreArray; + })(buffer_core.BufferCoreCommon); + exports.BufferCoreArray = BufferCoreArray; + + // Type-check the class. + var _ = BufferCoreArray; +}); +//# sourceMappingURL=buffer_core_array.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/buffer_core_arraybuffer',["require", "exports", './buffer_core'], function(require, exports, buffer_core) { + /** + * Represents data using an ArrayBuffer. + */ + var BufferCoreArrayBuffer = (function (_super) { + __extends(BufferCoreArrayBuffer, _super); + function BufferCoreArrayBuffer(arg1) { + _super.call(this); + if (typeof arg1 === 'number') { + this.buff = new DataView(new ArrayBuffer(arg1)); + } else if (arg1 instanceof DataView) { + this.buff = arg1; + } else { + this.buff = new DataView(arg1); + } + this.length = this.buff.byteLength; + } + BufferCoreArrayBuffer.isAvailable = function () { + return typeof DataView !== 'undefined'; + }; + + BufferCoreArrayBuffer.prototype.getLength = function () { + return this.length; + }; + BufferCoreArrayBuffer.prototype.writeInt8 = function (i, data) { + this.buff.setInt8(i, data); + }; + BufferCoreArrayBuffer.prototype.writeInt16LE = function (i, data) { + this.buff.setInt16(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeInt16BE = function (i, data) { + this.buff.setInt16(i, data, false); + }; + BufferCoreArrayBuffer.prototype.writeInt32LE = function (i, data) { + this.buff.setInt32(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeInt32BE = function (i, data) { + this.buff.setInt32(i, data, false); + }; + BufferCoreArrayBuffer.prototype.writeUInt8 = function (i, data) { + this.buff.setUint8(i, data); + }; + BufferCoreArrayBuffer.prototype.writeUInt16LE = function (i, data) { + this.buff.setUint16(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeUInt16BE = function (i, data) { + this.buff.setUint16(i, data, false); + }; + BufferCoreArrayBuffer.prototype.writeUInt32LE = function (i, data) { + this.buff.setUint32(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeUInt32BE = function (i, data) { + this.buff.setUint32(i, data, false); + }; + BufferCoreArrayBuffer.prototype.writeFloatLE = function (i, data) { + this.buff.setFloat32(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeFloatBE = function (i, data) { + this.buff.setFloat32(i, data, false); + }; + BufferCoreArrayBuffer.prototype.writeDoubleLE = function (i, data) { + this.buff.setFloat64(i, data, true); + }; + BufferCoreArrayBuffer.prototype.writeDoubleBE = function (i, data) { + this.buff.setFloat64(i, data, false); + }; + BufferCoreArrayBuffer.prototype.readInt8 = function (i) { + return this.buff.getInt8(i); + }; + BufferCoreArrayBuffer.prototype.readInt16LE = function (i) { + return this.buff.getInt16(i, true); + }; + BufferCoreArrayBuffer.prototype.readInt16BE = function (i) { + return this.buff.getInt16(i, false); + }; + BufferCoreArrayBuffer.prototype.readInt32LE = function (i) { + return this.buff.getInt32(i, true); + }; + BufferCoreArrayBuffer.prototype.readInt32BE = function (i) { + return this.buff.getInt32(i, false); + }; + BufferCoreArrayBuffer.prototype.readUInt8 = function (i) { + return this.buff.getUint8(i); + }; + BufferCoreArrayBuffer.prototype.readUInt16LE = function (i) { + return this.buff.getUint16(i, true); + }; + BufferCoreArrayBuffer.prototype.readUInt16BE = function (i) { + return this.buff.getUint16(i, false); + }; + BufferCoreArrayBuffer.prototype.readUInt32LE = function (i) { + return this.buff.getUint32(i, true); + }; + BufferCoreArrayBuffer.prototype.readUInt32BE = function (i) { + return this.buff.getUint32(i, false); + }; + BufferCoreArrayBuffer.prototype.readFloatLE = function (i) { + return this.buff.getFloat32(i, true); + }; + BufferCoreArrayBuffer.prototype.readFloatBE = function (i) { + return this.buff.getFloat32(i, false); + }; + BufferCoreArrayBuffer.prototype.readDoubleLE = function (i) { + return this.buff.getFloat64(i, true); + }; + BufferCoreArrayBuffer.prototype.readDoubleBE = function (i) { + return this.buff.getFloat64(i, false); + }; + BufferCoreArrayBuffer.prototype.copy = function (start, end) { + var aBuff = this.buff.buffer; + var newBuff; + + // Some ArrayBuffer implementations (IE10) do not have 'slice'. + // XXX: Type hacks - the typings don't have slice either. + if (ArrayBuffer.prototype.slice) { + // ArrayBuffer.slice is copying; exactly what we want. + newBuff = aBuff.slice(start, end); + } else { + var len = end - start; + newBuff = new ArrayBuffer(len); + + // Copy the old contents in. + var newUintArray = new Uint8Array(newBuff); + var oldUintArray = new Uint8Array(aBuff); + newUintArray.set(oldUintArray.subarray(start, end)); + } + return new BufferCoreArrayBuffer(newBuff); + }; + BufferCoreArrayBuffer.prototype.fill = function (value, start, end) { + // Value must be a byte wide. + value = value & 0xFF; + var i; + var len = end - start; + var intBytes = (((len) / 4) | 0) * 4; + + // Optimization: Write 4 bytes at a time. + // TODO: Could we copy 8 bytes at a time using Float64, or could we + // lose precision? + var intVal = (value << 24) | (value << 16) | (value << 8) | value; + for (i = 0; i < intBytes; i += 4) { + this.writeInt32LE(i + start, intVal); + } + for (i = intBytes; i < len; i++) { + this.writeUInt8(i + start, value); + } + }; + + /** + * Custom method for this buffer core. Get the backing object. + */ + BufferCoreArrayBuffer.prototype.getDataView = function () { + return this.buff; + }; + return BufferCoreArrayBuffer; + })(buffer_core.BufferCoreCommon); + exports.BufferCoreArrayBuffer = BufferCoreArrayBuffer; + + // Type-check the class. + var _ = BufferCoreArrayBuffer; +}); +//# sourceMappingURL=buffer_core_arraybuffer.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/buffer_core_imagedata',["require", "exports", './buffer_core'], function(require, exports, buffer_core) { + + + /** + * Implementation of BufferCore that is backed by an ImageData object. + * Useful in browsers with HTML5 canvas support, but no TypedArray support + * (IE9). + */ + var BufferCoreImageData = (function (_super) { + __extends(BufferCoreImageData, _super); + function BufferCoreImageData(length) { + _super.call(this); + this.length = length; + this.buff = BufferCoreImageData.getCanvasPixelArray(length); + } + /** + * Constructs a CanvasPixelArray that represents the given amount of bytes. + */ + BufferCoreImageData.getCanvasPixelArray = function (bytes) { + var ctx = BufferCoreImageData.imageDataFactory; + + // Lazily initialize, otherwise every browser (even those that will never + // use this code) will create a canvas on script load. + if (ctx === undefined) { + BufferCoreImageData.imageDataFactory = ctx = document.createElement('canvas').getContext('2d'); + } + + // You cannot create image data with size 0, so up it to size 1. + if (bytes === 0) + bytes = 1; + return ctx.createImageData(Math.ceil(bytes / 4), 1).data; + }; + BufferCoreImageData.isAvailable = function () { + // Modern browsers have removed this deprecated API, so it is not always around. + return typeof CanvasPixelArray !== 'undefined'; + }; + + BufferCoreImageData.prototype.getLength = function () { + return this.length; + }; + BufferCoreImageData.prototype.writeUInt8 = function (i, data) { + this.buff[i] = data; + }; + BufferCoreImageData.prototype.readUInt8 = function (i) { + return this.buff[i]; + }; + BufferCoreImageData.prototype.copy = function (start, end) { + // AFAIK, there's no efficient way to clone ImageData. + var newBC = new BufferCoreImageData(end - start); + for (var i = start; i < end; i++) { + newBC.writeUInt8(i - start, this.buff[i]); + } + return newBC; + }; + return BufferCoreImageData; + })(buffer_core.BufferCoreCommon); + exports.BufferCoreImageData = BufferCoreImageData; + + // Type-check the class. + var _ = BufferCoreImageData; +}); +//# sourceMappingURL=buffer_core_imagedata.js.map +; +define('core/string_util',["require", "exports"], function(require, exports) { + + + /** + * Find the 'utility' object for the given string encoding. Throws an exception + * if the encoding is invalid. + * @param [String] encoding a string encoding + * @return [BrowserFS.StringUtil.*] The StringUtil object for the given encoding + */ + function FindUtil(encoding) { + encoding = (function () { + switch (typeof encoding) { + case 'object': + return "" + encoding; + case 'string': + return encoding; + default: + throw new Error('Invalid encoding argument specified'); + } + })(); + encoding = encoding.toLowerCase(); + + switch (encoding) { + case 'utf8': + case 'utf-8': + return UTF8; + case 'ascii': + return ASCII; + case 'binary': + return BINARY; + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + return UCS2; + case 'hex': + return HEX; + case 'base64': + return BASE64; + + case 'binary_string': + return BINSTR; + case 'binary_string_ie': + return BINSTRIE; + case 'extended_ascii': + return ExtendedASCII; + + default: + throw new Error("Unknown encoding: " + encoding); + } + } + exports.FindUtil = FindUtil; + + /** + * String utility functions for UTF-8. Note that some UTF-8 strings *cannot* be + * expressed in terms of JavaScript UTF-16 strings. + * @see http://en.wikipedia.org/wiki/UTF-8 + */ + var UTF8 = (function () { + function UTF8() { + } + UTF8.str2byte = function (str, buf) { + var length = buf.length; + var i = 0; + var j = 0; + var maxJ = length; + var rv = []; + var numChars = 0; + while (i < str.length && j < maxJ) { + var code = str.charCodeAt(i++); + var next = str.charCodeAt(i); + if (0xD800 <= code && code <= 0xDBFF && 0xDC00 <= next && next <= 0xDFFF) { + // 4 bytes: Surrogate pairs! UTF-16 fun time. + if (j + 3 >= maxJ) { + break; + } else { + numChars++; + } + + // First pair: 10 bits of data, with an implicitly set 11th bit + // Second pair: 10 bits of data + var codePoint = (((code & 0x3FF) | 0x400) << 10) | (next & 0x3FF); + + // Highest 3 bits in first byte + buf.writeUInt8((codePoint >> 18) | 0xF0, j++); + + // Rest are all 6 bits + buf.writeUInt8(((codePoint >> 12) & 0x3F) | 0x80, j++); + buf.writeUInt8(((codePoint >> 6) & 0x3F) | 0x80, j++); + buf.writeUInt8((codePoint & 0x3F) | 0x80, j++); + i++; + } else if (code < 0x80) { + // One byte + buf.writeUInt8(code, j++); + numChars++; + } else if (code < 0x800) { + // Two bytes + if (j + 1 >= maxJ) { + break; + } else { + numChars++; + } + + // Highest 5 bits in first byte + buf.writeUInt8((code >> 6) | 0xC0, j++); + + // Lower 6 bits in second byte + buf.writeUInt8((code & 0x3F) | 0x80, j++); + } else if (code < 0x10000) { + // Three bytes + if (j + 2 >= maxJ) { + break; + } else { + numChars++; + } + + // Highest 4 bits in first byte + buf.writeUInt8((code >> 12) | 0xE0, j++); + + // Middle 6 bits in second byte + buf.writeUInt8(((code >> 6) & 0x3F) | 0x80, j++); + + // Lowest 6 bits in third byte + buf.writeUInt8((code & 0x3F) | 0x80, j++); + } + } + return j; + }; + + UTF8.byte2str = function (buff) { + var chars = []; + var i = 0; + while (i < buff.length) { + var code = buff.readUInt8(i++); + if (code < 0x80) { + chars.push(String.fromCharCode(code)); + } else if (code < 0xC0) { + throw new Error('Found incomplete part of character in string.'); + } else if (code < 0xE0) { + // 2 bytes: 5 and 6 bits + chars.push(String.fromCharCode(((code & 0x1F) << 6) | (buff.readUInt8(i++) & 0x3F))); + } else if (code < 0xF0) { + // 3 bytes: 4, 6, and 6 bits + chars.push(String.fromCharCode(((code & 0xF) << 12) | ((buff.readUInt8(i++) & 0x3F) << 6) | (buff.readUInt8(i++) & 0x3F))); + } else if (code < 0xF8) { + // 4 bytes: 3, 6, 6, 6 bits; surrogate pairs time! + // First 11 bits; remove 11th bit as per UTF-16 standard + var byte3 = buff.readUInt8(i + 2); + chars.push(String.fromCharCode(((((code & 0x7) << 8) | ((buff.readUInt8(i++) & 0x3F) << 2) | ((buff.readUInt8(i++) & 0x3F) >> 4)) & 0x3FF) | 0xD800)); + + // Final 10 bits + chars.push(String.fromCharCode((((byte3 & 0xF) << 6) | (buff.readUInt8(i++) & 0x3F)) | 0xDC00)); + } else { + throw new Error('Unable to represent UTF-8 string as UTF-16 JavaScript string.'); + } + } + return chars.join(''); + }; + + UTF8.byteLength = function (str) { + // Matches only the 10.. bytes that are non-initial characters in a + // multi-byte sequence. + // @todo This may be slower than iterating through the string in some cases. + var m = encodeURIComponent(str).match(/%[89ABab]/g); + return str.length + (m ? m.length : 0); + }; + return UTF8; + })(); + exports.UTF8 = UTF8; + + /** + * String utility functions for 8-bit ASCII. Like Node, we mask the high bits of + * characters in JavaScript UTF-16 strings. + * @see http://en.wikipedia.org/wiki/ASCII + */ + var ASCII = (function () { + function ASCII() { + } + ASCII.str2byte = function (str, buf) { + var length = str.length > buf.length ? buf.length : str.length; + for (var i = 0; i < length; i++) { + buf.writeUInt8(str.charCodeAt(i) % 256, i); + } + return length; + }; + + ASCII.byte2str = function (buff) { + var chars = new Array(buff.length); + for (var i = 0; i < buff.length; i++) { + chars[i] = String.fromCharCode(buff.readUInt8(i) & 0x7F); + } + return chars.join(''); + }; + + ASCII.byteLength = function (str) { + return str.length; + }; + return ASCII; + })(); + exports.ASCII = ASCII; + + /** + * (Nonstandard) String utility function for 8-bit ASCII with the extended + * character set. Unlike the ASCII above, we do not mask the high bits. + * @see http://en.wikipedia.org/wiki/Extended_ASCII + */ + var ExtendedASCII = (function () { + function ExtendedASCII() { + } + ExtendedASCII.str2byte = function (str, buf) { + var length = str.length > buf.length ? buf.length : str.length; + for (var i = 0; i < length; i++) { + var charCode = str.charCodeAt(i); + if (charCode > 0x7F) { + // Check if extended ASCII. + var charIdx = ExtendedASCII.extendedChars.indexOf(str.charAt(i)); + if (charIdx > -1) { + charCode = charIdx + 0x80; + } + // Otherwise, keep it as-is. + } + buf.writeUInt8(charCode, i); + } + return length; + }; + + ExtendedASCII.byte2str = function (buff) { + var chars = new Array(buff.length); + for (var i = 0; i < buff.length; i++) { + var charCode = buff.readUInt8(i); + if (charCode > 0x7F) { + chars[i] = ExtendedASCII.extendedChars[charCode - 128]; + } else { + chars[i] = String.fromCharCode(charCode); + } + } + return chars.join(''); + }; + + ExtendedASCII.byteLength = function (str) { + return str.length; + }; + ExtendedASCII.extendedChars = [ + '\u00C7', '\u00FC', '\u00E9', '\u00E2', '\u00E4', + '\u00E0', '\u00E5', '\u00E7', '\u00EA', '\u00EB', '\u00E8', '\u00EF', + '\u00EE', '\u00EC', '\u00C4', '\u00C5', '\u00C9', '\u00E6', '\u00C6', + '\u00F4', '\u00F6', '\u00F2', '\u00FB', '\u00F9', '\u00FF', '\u00D6', + '\u00DC', '\u00F8', '\u00A3', '\u00D8', '\u00D7', '\u0192', '\u00E1', + '\u00ED', '\u00F3', '\u00FA', '\u00F1', '\u00D1', '\u00AA', '\u00BA', + '\u00BF', '\u00AE', '\u00AC', '\u00BD', '\u00BC', '\u00A1', '\u00AB', + '\u00BB', '_', '_', '_', '\u00A6', '\u00A6', '\u00C1', '\u00C2', '\u00C0', + '\u00A9', '\u00A6', '\u00A6', '+', '+', '\u00A2', '\u00A5', '+', '+', '-', + '-', '+', '-', '+', '\u00E3', '\u00C3', '+', '+', '-', '-', '\u00A6', '-', + '+', '\u00A4', '\u00F0', '\u00D0', '\u00CA', '\u00CB', '\u00C8', 'i', + '\u00CD', '\u00CE', '\u00CF', '+', '+', '_', '_', '\u00A6', '\u00CC', '_', + '\u00D3', '\u00DF', '\u00D4', '\u00D2', '\u00F5', '\u00D5', '\u00B5', + '\u00FE', '\u00DE', '\u00DA', '\u00DB', '\u00D9', '\u00FD', '\u00DD', + '\u00AF', '\u00B4', '\u00AD', '\u00B1', '_', '\u00BE', '\u00B6', '\u00A7', + '\u00F7', '\u00B8', '\u00B0', '\u00A8', '\u00B7', '\u00B9', '\u00B3', + '\u00B2', '_', ' ']; + return ExtendedASCII; + })(); + exports.ExtendedASCII = ExtendedASCII; + + /** + * String utility functions for Node's BINARY strings, which represent a single + * byte per character. + */ + var BINARY = (function () { + function BINARY() { + } + BINARY.str2byte = function (str, buf) { + var length = str.length > buf.length ? buf.length : str.length; + for (var i = 0; i < length; i++) { + buf.writeUInt8(str.charCodeAt(i) & 0xFF, i); + } + return length; + }; + + BINARY.byte2str = function (buff) { + var chars = new Array(buff.length); + for (var i = 0; i < buff.length; i++) { + chars[i] = String.fromCharCode(buff.readUInt8(i) & 0xFF); + } + return chars.join(''); + }; + + BINARY.byteLength = function (str) { + return str.length; + }; + return BINARY; + })(); + exports.BINARY = BINARY; + + /** + * Contains string utility functions for base-64 encoding. + * + * Adapted from the StackOverflow comment linked below. + * @see http://stackoverflow.com/questions/246801/how-can-you-encode-to-base64-using-javascript#246813 + * @see http://en.wikipedia.org/wiki/Base64 + * @todo Bake in support for btoa() and atob() if available. + */ + var BASE64 = (function () { + function BASE64() { + } + BASE64.byte2str = function (buff) { + var output = ''; + var i = 0; + while (i < buff.length) { + var chr1 = buff.readUInt8(i++); + var chr2 = i < buff.length ? buff.readUInt8(i++) : NaN; + var chr3 = i < buff.length ? buff.readUInt8(i++) : NaN; + var enc1 = chr1 >> 2; + var enc2 = ((chr1 & 3) << 4) | (chr2 >> 4); + var enc3 = ((chr2 & 15) << 2) | (chr3 >> 6); + var enc4 = chr3 & 63; + if (isNaN(chr2)) { + enc3 = enc4 = 64; + } else if (isNaN(chr3)) { + enc4 = 64; + } + output = output + BASE64.num2b64[enc1] + BASE64.num2b64[enc2] + BASE64.num2b64[enc3] + BASE64.num2b64[enc4]; + } + return output; + }; + + BASE64.str2byte = function (str, buf) { + var length = buf.length; + var output = ''; + var i = 0; + str = str.replace(/[^A-Za-z0-9\+\/\=\-\_]/g, ''); + var j = 0; + while (i < str.length) { + var enc1 = BASE64.b642num[str.charAt(i++)]; + var enc2 = BASE64.b642num[str.charAt(i++)]; + var enc3 = BASE64.b642num[str.charAt(i++)]; + var enc4 = BASE64.b642num[str.charAt(i++)]; + var chr1 = (enc1 << 2) | (enc2 >> 4); + var chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + var chr3 = ((enc3 & 3) << 6) | enc4; + buf.writeUInt8(chr1, j++); + if (j === length) { + break; + } + if (enc3 !== 64) { + output += buf.writeUInt8(chr2, j++); + } + if (j === length) { + break; + } + if (enc4 !== 64) { + output += buf.writeUInt8(chr3, j++); + } + if (j === length) { + break; + } + } + return j; + }; + + BASE64.byteLength = function (str) { + return Math.floor(((str.replace(/[^A-Za-z0-9\+\/\-\_]/g, '')).length * 6) / 8); + }; + BASE64.b64chars = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '=']; + BASE64.num2b64 = (function () { + var obj = new Array(BASE64.b64chars.length); + for (var idx = 0; idx < BASE64.b64chars.length; idx++) { + var i = BASE64.b64chars[idx]; + obj[idx] = i; + } + return obj; + })(); + + BASE64.b642num = (function () { + var obj = {}; + for (var idx = 0; idx < BASE64.b64chars.length; idx++) { + var i = BASE64.b64chars[idx]; + obj[i] = idx; + } + obj['-'] = 62; + obj['_'] = 63; + return obj; + })(); + return BASE64; + })(); + exports.BASE64 = BASE64; + + /** + * String utility functions for the UCS-2 encoding. Note that our UCS-2 handling + * is identical to our UTF-16 handling. + * + * Note: UCS-2 handling is identical to UTF-16. + * @see http://en.wikipedia.org/wiki/UCS2 + */ + var UCS2 = (function () { + function UCS2() { + } + UCS2.str2byte = function (str, buf) { + var len = str.length; + + // Clip length to longest string of valid characters that can fit in the + // byte range. + if (len * 2 > buf.length) { + len = buf.length % 2 === 1 ? (buf.length - 1) / 2 : buf.length / 2; + } + for (var i = 0; i < len; i++) { + buf.writeUInt16LE(str.charCodeAt(i), i * 2); + } + return len * 2; + }; + + UCS2.byte2str = function (buff) { + if (buff.length % 2 !== 0) { + throw new Error('Invalid UCS2 byte array.'); + } + var chars = new Array(buff.length / 2); + for (var i = 0; i < buff.length; i += 2) { + chars[i / 2] = String.fromCharCode(buff.readUInt8(i) | (buff.readUInt8(i + 1) << 8)); + } + return chars.join(''); + }; + + UCS2.byteLength = function (str) { + return str.length * 2; + }; + return UCS2; + })(); + exports.UCS2 = UCS2; + + /** + * Contains string utility functions for hex encoding. + * @see http://en.wikipedia.org/wiki/Hexadecimal + */ + var HEX = (function () { + function HEX() { + } + HEX.str2byte = function (str, buf) { + if (str.length % 2 === 1) { + throw new Error('Invalid hex string'); + } + + // Each character is 1 byte encoded as two hex characters; so 1 byte becomes + // 2 bytes. + var numBytes = str.length >> 1; + if (numBytes > buf.length) { + numBytes = buf.length; + } + for (var i = 0; i < numBytes; i++) { + var char1 = this.hex2num[str.charAt(i << 1)]; + var char2 = this.hex2num[str.charAt((i << 1) + 1)]; + buf.writeUInt8((char1 << 4) | char2, i); + } + return numBytes; + }; + + HEX.byte2str = function (buff) { + var len = buff.length; + var chars = new Array(len << 1); + var j = 0; + for (var i = 0; i < len; i++) { + var hex2 = buff.readUInt8(i) & 0xF; + var hex1 = buff.readUInt8(i) >> 4; + chars[j++] = this.num2hex[hex1]; + chars[j++] = this.num2hex[hex2]; + } + return chars.join(''); + }; + + HEX.byteLength = function (str) { + // Assuming a valid string. + return str.length >> 1; + }; + HEX.HEXCHARS = '0123456789abcdef'; + + HEX.num2hex = (function () { + var obj = new Array(HEX.HEXCHARS.length); + for (var idx = 0; idx < HEX.HEXCHARS.length; idx++) { + var i = HEX.HEXCHARS[idx]; + obj[idx] = i; + } + return obj; + })(); + + HEX.hex2num = (function () { + var idx, i; + var obj = {}; + for (idx = 0; idx < HEX.HEXCHARS.length; idx++) { + i = HEX.HEXCHARS[idx]; + obj[i] = idx; + } + var capitals = 'ABCDEF'; + for (idx = 0; idx < capitals.length; idx++) { + i = capitals[idx]; + obj[i] = idx + 10; + } + return obj; + })(); + return HEX; + })(); + exports.HEX = HEX; + + /** + * Contains string utility functions for binary string encoding. This is where we + * pack arbitrary binary data as a UTF-16 string. + * + * Each character in the string is two bytes. The first character in the string + * is special: The first byte specifies if the binary data is of odd byte length. + * If it is, then it is a 1 and the second byte is the first byte of data; if + * not, it is a 0 and the second byte is 0. + * + * Everything is little endian. + */ + var BINSTR = (function () { + function BINSTR() { + } + BINSTR.str2byte = function (str, buf) { + // Special case: Empty string + if (str.length === 0) { + return 0; + } + var numBytes = BINSTR.byteLength(str); + if (numBytes > buf.length) { + numBytes = buf.length; + } + var j = 0; + var startByte = 0; + var endByte = startByte + numBytes; + + // Handle first character separately + var firstChar = str.charCodeAt(j++); + if (firstChar !== 0) { + buf.writeUInt8(firstChar & 0xFF, 0); + startByte = 1; + } + for (var i = startByte; i < endByte; i += 2) { + var chr = str.charCodeAt(j++); + if (endByte - i === 1) { + // Write first byte of character + buf.writeUInt8(chr >> 8, i); + } + if (endByte - i >= 2) { + // Write both bytes in character + buf.writeUInt16BE(chr, i); + } + } + return numBytes; + }; + + BINSTR.byte2str = function (buff) { + var len = buff.length; + + // Special case: Empty string + if (len === 0) { + return ''; + } + var chars = new Array((len >> 1) + 1); + var j = 0; + for (var i = 0; i < chars.length; i++) { + if (i === 0) { + if (len % 2 === 1) { + chars[i] = String.fromCharCode((1 << 8) | buff.readUInt8(j++)); + } else { + chars[i] = String.fromCharCode(0); + } + } else { + chars[i] = String.fromCharCode((buff.readUInt8(j++) << 8) | buff.readUInt8(j++)); + } + } + return chars.join(''); + }; + + BINSTR.byteLength = function (str) { + if (str.length === 0) { + // Special case: Empty string. + return 0; + } + var firstChar = str.charCodeAt(0); + var bytelen = (str.length - 1) << 1; + if (firstChar !== 0) { + bytelen++; + } + return bytelen; + }; + return BINSTR; + })(); + exports.BINSTR = BINSTR; + + /** + * IE/older FF version of binary string. One byte per character, offset by 0x20. + */ + var BINSTRIE = (function () { + function BINSTRIE() { + } + BINSTRIE.str2byte = function (str, buf) { + var length = str.length > buf.length ? buf.length : str.length; + for (var i = 0; i < length; i++) { + buf.writeUInt8(str.charCodeAt(i) - 0x20, i); + } + return length; + }; + + BINSTRIE.byte2str = function (buff) { + var chars = new Array(buff.length); + for (var i = 0; i < buff.length; i++) { + chars[i] = String.fromCharCode(buff.readUInt8(i) + 0x20); + } + return chars.join(''); + }; + + BINSTRIE.byteLength = function (str) { + return str.length; + }; + return BINSTRIE; + })(); + exports.BINSTRIE = BINSTRIE; +}); +//# sourceMappingURL=string_util.js.map +; +define('core/buffer',["require", "exports", './buffer_core', './buffer_core_array', './buffer_core_arraybuffer', './buffer_core_imagedata', './string_util'], function(require, exports, buffer_core, buffer_core_array, buffer_core_arraybuffer, buffer_core_imagedata, string_util) { + // BC implementations earlier in the array are preferred. + var BufferCorePreferences = [ + buffer_core_arraybuffer.BufferCoreArrayBuffer, + buffer_core_imagedata.BufferCoreImageData, + buffer_core_array.BufferCoreArray + ]; + + var PreferredBufferCore = (function () { + var i, bci; + for (i = 0; i < BufferCorePreferences.length; i++) { + bci = BufferCorePreferences[i]; + if (bci.isAvailable()) + return bci; + } + + throw new Error("This browser does not support any available BufferCore implementations."); + })(); + + + + + + /** + * Emulates Node's Buffer API. Wraps a BufferCore object that is responsible + * for actually writing/reading data from some data representation in memory. + */ + var Buffer = (function () { + function Buffer(arg1, arg2, arg3) { + if (typeof arg2 === "undefined") { arg2 = 'utf8'; } + this.offset = 0; + var i; + + // Node apparently allows you to construct buffers w/o 'new'. + if (!(this instanceof Buffer)) { + return new Buffer(arg1, arg2); + } + + if (arg1 instanceof buffer_core.BufferCoreCommon) { + // constructor (data: buffer_core.BufferCore, start?: number, end?: number) + this.data = arg1; + var start = typeof arg2 === 'number' ? arg2 : 0; + var end = typeof arg3 === 'number' ? arg3 : this.data.getLength(); + this.offset = start; + this.length = end - start; + } else if (typeof arg1 === 'number') { + // constructor (size: number); + if (arg1 !== (arg1 >>> 0)) { + throw new TypeError('Buffer size must be a uint32.'); + } + this.length = arg1; + this.data = new PreferredBufferCore(arg1); + } else if (typeof DataView !== 'undefined' && arg1 instanceof DataView) { + // constructor (data: DataView); + this.data = new buffer_core_arraybuffer.BufferCoreArrayBuffer(arg1); + this.length = arg1.byteLength; + } else if (typeof ArrayBuffer !== 'undefined' && arg1 instanceof ArrayBuffer) { + // constructor (data: ArrayBuffer); + this.data = new buffer_core_arraybuffer.BufferCoreArrayBuffer(arg1); + this.length = arg1.byteLength; + } else if (arg1 instanceof Buffer) { + // constructor (data: Buffer); + var argBuff = arg1; + this.data = new PreferredBufferCore(arg1.length); + this.length = arg1.length; + argBuff.copy(this); + } else if (Array.isArray(arg1) || (arg1 != null && typeof arg1 === 'object' && typeof arg1[0] === 'number')) { + // constructor (data: number[]); + this.data = new PreferredBufferCore(arg1.length); + for (i = 0; i < arg1.length; i++) { + this.data.writeUInt8(i, arg1[i]); + } + this.length = arg1.length; + } else if (typeof arg1 === 'string') { + // constructor (data: string, encoding?: string); + this.length = Buffer.byteLength(arg1, arg2); + this.data = new PreferredBufferCore(this.length); + this.write(arg1, 0, this.length, arg2); + } else { + throw new Error("Invalid argument to Buffer constructor: " + arg1); + } + } + Buffer.prototype.getBufferCore = function () { + return this.data; + }; + + Buffer.prototype.getOffset = function () { + return this.offset; + }; + + /** + * **NONSTANDARD**: Set the octet at index. Emulates NodeJS buffer's index + * operation. Octet can be signed or unsigned. + * @param {number} index - the index to set the value at + * @param {number} value - the value to set at the given index + */ + Buffer.prototype.set = function (index, value) { + // In Node, the following happens: + // buffer[0] = -1; + // buffer[0]; // 255 + if (value < 0) { + return this.writeInt8(value, index); + } else { + return this.writeUInt8(value, index); + } + }; + + /** + * **NONSTANDARD**: Get the octet at index. + * @param {number} index - index to fetch the value at + * @return {number} the value at the given index + */ + Buffer.prototype.get = function (index) { + return this.readUInt8(index); + }; + + /** + * Writes string to the buffer at offset using the given encoding. + * If buffer did not contain enough space to fit the entire string, it will + * write a partial amount of the string. + * @param {string} str - Data to be written to buffer + * @param {number} [offset=0] - Offset in the buffer to write to + * @param {number} [length=this.length] - Number of bytes to write + * @param {string} [encoding=utf8] - Character encoding + * @return {number} Number of octets written. + */ + Buffer.prototype.write = function (str, offset, length, encoding) { + if (typeof offset === "undefined") { offset = 0; } + if (typeof length === "undefined") { length = this.length; } + if (typeof encoding === "undefined") { encoding = 'utf8'; } + // I hate Node's optional arguments. + if (typeof offset === 'string') { + // 'str' and 'encoding' specified + encoding = "" + offset; + offset = 0; + length = this.length; + } else if (typeof length === 'string') { + // 'str', 'offset', and 'encoding' specified + encoding = "" + length; + length = this.length; + } + + // Don't waste our time if the offset is beyond the buffer length + if (offset >= this.length) { + return 0; + } + var strUtil = string_util.FindUtil(encoding); + + // Are we trying to write past the buffer? + length = length + offset > this.length ? this.length - offset : length; + offset += this.offset; + return strUtil.str2byte(str, offset === 0 && length === this.length ? this : new Buffer(this.data, offset, length + offset)); + }; + + /** + * Decodes a portion of the Buffer into a String. + * @param {string} encoding - Character encoding to decode to + * @param {number} [start=0] - Start position in the buffer + * @param {number} [end=this.length] - Ending position in the buffer + * @return {string} A string from buffer data encoded with encoding, beginning + * at start, and ending at end. + */ + Buffer.prototype.toString = function (encoding, start, end) { + if (typeof encoding === "undefined") { encoding = 'utf8'; } + if (typeof start === "undefined") { start = 0; } + if (typeof end === "undefined") { end = this.length; } + if (!(start <= end)) { + throw new Error("Invalid start/end positions: " + start + " - " + end); + } + if (start === end) { + return ''; + } + if (end > this.length) { + end = this.length; + } + var strUtil = string_util.FindUtil(encoding); + + // Get the string representation of the given slice. Create a new buffer + // if need be. + return strUtil.byte2str(start === 0 && end === this.length ? this : new Buffer(this.data, start + this.offset, end + this.offset)); + }; + + /** + * Returns a JSON-representation of the Buffer instance, which is identical to + * the output for JSON Arrays. JSON.stringify implicitly calls this function + * when stringifying a Buffer instance. + * @return {object} An object that can be used for JSON stringification. + */ + Buffer.prototype.toJSON = function () { + // Construct a byte array for the JSON 'data'. + var len = this.length; + var byteArr = new Array(len); + for (var i = 0; i < len; i++) { + byteArr[i] = this.readUInt8(i); + } + return { + type: 'Buffer', + data: byteArr + }; + }; + + /** + * Does copy between buffers. The source and target regions can be overlapped. + * All values passed that are undefined/NaN or are out of bounds are set equal + * to their respective defaults. + * @param {Buffer} target - Buffer to copy into + * @param {number} [targetStart=0] - Index to start copying to in the targetBuffer + * @param {number} [sourceStart=0] - Index in this buffer to start copying from + * @param {number} [sourceEnd=this.length] - Index in this buffer stop copying at + * @return {number} The number of bytes copied into the target buffer. + */ + Buffer.prototype.copy = function (target, targetStart, sourceStart, sourceEnd) { + if (typeof targetStart === "undefined") { targetStart = 0; } + if (typeof sourceStart === "undefined") { sourceStart = 0; } + if (typeof sourceEnd === "undefined") { sourceEnd = this.length; } + // The Node code is weird. It sets some out-of-bounds args to their defaults + // and throws exceptions for others (sourceEnd). + targetStart = targetStart < 0 ? 0 : targetStart; + sourceStart = sourceStart < 0 ? 0 : sourceStart; + + // Need to sanity check all of the input. Node has really odd rules regarding + // when to apply default arguments. I decided to copy Node's logic. + if (sourceEnd < sourceStart) { + throw new RangeError('sourceEnd < sourceStart'); + } + if (sourceEnd === sourceStart) { + return 0; + } + if (targetStart >= target.length) { + throw new RangeError('targetStart out of bounds'); + } + if (sourceStart >= this.length) { + throw new RangeError('sourceStart out of bounds'); + } + if (sourceEnd > this.length) { + throw new RangeError('sourceEnd out of bounds'); + } + var bytesCopied = Math.min(sourceEnd - sourceStart, target.length - targetStart, this.length - sourceStart); + + for (var i = 0; i < bytesCopied; i++) { + target.writeUInt8(this.readUInt8(sourceStart + i), targetStart + i); + } + return bytesCopied; + }; + + /** + * Returns a slice of this buffer. + * @param {number} [start=0] - Index to start slicing from + * @param {number} [end=this.length] - Index to stop slicing at + * @return {Buffer} A new buffer which references the same + * memory as the old, but offset and cropped by the start (defaults to 0) and + * end (defaults to buffer.length) indexes. Negative indexes start from the end + * of the buffer. + */ + Buffer.prototype.slice = function (start, end) { + if (typeof start === "undefined") { start = 0; } + if (typeof end === "undefined") { end = this.length; } + // Translate negative indices to positive ones. + if (start < 0) { + start += this.length; + if (start < 0) { + start = 0; + } + } + if (end < 0) { + end += this.length; + if (end < 0) { + end = 0; + } + } + if (end > this.length) { + end = this.length; + } + if (start > end) { + start = end; + } + + // Sanity check. + if (start < 0 || end < 0 || start >= this.length || end > this.length) { + throw new Error("Invalid slice indices."); + } + + // Create a new buffer backed by the same BufferCore. + return new Buffer(this.data, start + this.offset, end + this.offset); + }; + + /** + * [NONSTANDARD] A copy-based version of Buffer.slice. + */ + Buffer.prototype.sliceCopy = function (start, end) { + if (typeof start === "undefined") { start = 0; } + if (typeof end === "undefined") { end = this.length; } + // Translate negative indices to positive ones. + if (start < 0) { + start += this.length; + if (start < 0) { + start = 0; + } + } + if (end < 0) { + end += this.length; + if (end < 0) { + end = 0; + } + } + if (end > this.length) { + end = this.length; + } + if (start > end) { + start = end; + } + + // Sanity check. + if (start < 0 || end < 0 || start >= this.length || end > this.length) { + throw new Error("Invalid slice indices."); + } + + // Copy the BufferCore. + return new Buffer(this.data.copy(start + this.offset, end + this.offset)); + }; + + /** + * Fills the buffer with the specified value. If the offset and end are not + * given it will fill the entire buffer. + * @param {(string|number)} value - The value to fill the buffer with + * @param {number} [offset=0] + * @param {number} [end=this.length] + */ + Buffer.prototype.fill = function (value, offset, end) { + if (typeof offset === "undefined") { offset = 0; } + if (typeof end === "undefined") { end = this.length; } + var i; + var valType = typeof value; + switch (valType) { + case "string": + // Trim to a byte. + value = value.charCodeAt(0) & 0xFF; + break; + case "number": + break; + default: + throw new Error('Invalid argument to fill.'); + } + offset += this.offset; + end += this.offset; + this.data.fill(value, offset, end); + }; + + Buffer.prototype.readUInt8 = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readUInt8(offset); + }; + + Buffer.prototype.readUInt16LE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readUInt16LE(offset); + }; + + Buffer.prototype.readUInt16BE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readUInt16BE(offset); + }; + + Buffer.prototype.readUInt32LE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readUInt32LE(offset); + }; + + Buffer.prototype.readUInt32BE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readUInt32BE(offset); + }; + + Buffer.prototype.readInt8 = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readInt8(offset); + }; + + Buffer.prototype.readInt16LE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readInt16LE(offset); + }; + + Buffer.prototype.readInt16BE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readInt16BE(offset); + }; + + Buffer.prototype.readInt32LE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readInt32LE(offset); + }; + + Buffer.prototype.readInt32BE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readInt32BE(offset); + }; + + Buffer.prototype.readFloatLE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readFloatLE(offset); + }; + + Buffer.prototype.readFloatBE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readFloatBE(offset); + }; + + Buffer.prototype.readDoubleLE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readDoubleLE(offset); + }; + + Buffer.prototype.readDoubleBE = function (offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + return this.data.readDoubleBE(offset); + }; + + Buffer.prototype.writeUInt8 = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeUInt8(offset, value); + }; + + Buffer.prototype.writeUInt16LE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeUInt16LE(offset, value); + }; + + Buffer.prototype.writeUInt16BE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeUInt16BE(offset, value); + }; + + Buffer.prototype.writeUInt32LE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeUInt32LE(offset, value); + }; + + Buffer.prototype.writeUInt32BE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeUInt32BE(offset, value); + }; + + Buffer.prototype.writeInt8 = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeInt8(offset, value); + }; + + Buffer.prototype.writeInt16LE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeInt16LE(offset, value); + }; + + Buffer.prototype.writeInt16BE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeInt16BE(offset, value); + }; + + Buffer.prototype.writeInt32LE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeInt32LE(offset, value); + }; + + Buffer.prototype.writeInt32BE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeInt32BE(offset, value); + }; + + Buffer.prototype.writeFloatLE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeFloatLE(offset, value); + }; + + Buffer.prototype.writeFloatBE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeFloatBE(offset, value); + }; + + Buffer.prototype.writeDoubleLE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeDoubleLE(offset, value); + }; + + Buffer.prototype.writeDoubleBE = function (value, offset, noAssert) { + if (typeof noAssert === "undefined") { noAssert = false; } + offset += this.offset; + this.data.writeDoubleBE(offset, value); + }; + + ///**************************STATIC METHODS********************************/// + /** + * Checks if enc is a valid string encoding type. + * @param {string} enc - Name of a string encoding type. + * @return {boolean} Whether or not enc is a valid encoding type. + */ + Buffer.isEncoding = function (enc) { + try { + string_util.FindUtil(enc); + } catch (e) { + return false; + } + return true; + }; + + /** + * Tests if obj is a Buffer. + * @param {object} obj - An arbitrary object + * @return {boolean} True if this object is a Buffer. + */ + Buffer.isBuffer = function (obj) { + return obj instanceof Buffer; + }; + + /** + * Gives the actual byte length of a string. This is not the same as + * String.prototype.length since that returns the number of characters in a + * string. + * @param {string} str - The string to get the byte length of + * @param {string} [encoding=utf8] - Character encoding of the string + * @return {number} The number of bytes in the string + */ + Buffer.byteLength = function (str, encoding) { + if (typeof encoding === "undefined") { encoding = 'utf8'; } + var strUtil = string_util.FindUtil(encoding); + return strUtil.byteLength(str); + }; + + /** + * Returns a buffer which is the result of concatenating all the buffers in the + * list together. + * If the list has no items, or if the totalLength is 0, then it returns a + * zero-length buffer. + * If the list has exactly one item, then the first item of the list is + * returned. + * If the list has more than one item, then a new Buffer is created. + * If totalLength is not provided, it is read from the buffers in the list. + * However, this adds an additional loop to the function, so it is faster to + * provide the length explicitly. + * @param {Buffer[]} list - List of Buffer objects to concat + * @param {number} [totalLength] - Total length of the buffers when concatenated + * @return {Buffer} + */ + Buffer.concat = function (list, totalLength) { + var item; + if (list.length === 0 || totalLength === 0) { + return new Buffer(0); + } else if (list.length === 1) { + return list[0]; + } else { + if (totalLength == null) { + // Calculate totalLength + totalLength = 0; + for (var i = 0; i < list.length; i++) { + item = list[i]; + totalLength += item.length; + } + } + var buf = new Buffer(totalLength); + var curPos = 0; + for (var j = 0; j < list.length; j++) { + item = list[j]; + curPos += item.copy(buf, curPos); + } + return buf; + } + }; + return Buffer; + })(); + exports.Buffer = Buffer; + + // Type-check the class. + var _ = Buffer; +}); +//# sourceMappingURL=buffer.js.map +; +define('core/file_flag',["require", "exports", './api_error'], function(require, exports, api_error) { + /** + * @class + */ + (function (ActionType) { + // Indicates that the code should not do anything. + ActionType[ActionType["NOP"] = 0] = "NOP"; + + // Indicates that the code should throw an exception. + ActionType[ActionType["THROW_EXCEPTION"] = 1] = "THROW_EXCEPTION"; + + // Indicates that the code should truncate the file, but only if it is a file. + ActionType[ActionType["TRUNCATE_FILE"] = 2] = "TRUNCATE_FILE"; + + // Indicates that the code should create the file. + ActionType[ActionType["CREATE_FILE"] = 3] = "CREATE_FILE"; + })(exports.ActionType || (exports.ActionType = {})); + var ActionType = exports.ActionType; + + /** + * Represents one of the following file flags. A convenience object. + * + * * `'r'` - Open file for reading. An exception occurs if the file does not exist. + * * `'r+'` - Open file for reading and writing. An exception occurs if the file does not exist. + * * `'rs'` - Open file for reading in synchronous mode. Instructs the filesystem to not cache writes. + * * `'rs+'` - Open file for reading and writing, and opens the file in synchronous mode. + * * `'w'` - Open file for writing. The file is created (if it does not exist) or truncated (if it exists). + * * `'wx'` - Like 'w' but opens the file in exclusive mode. + * * `'w+'` - Open file for reading and writing. The file is created (if it does not exist) or truncated (if it exists). + * * `'wx+'` - Like 'w+' but opens the file in exclusive mode. + * * `'a'` - Open file for appending. The file is created if it does not exist. + * * `'ax'` - Like 'a' but opens the file in exclusive mode. + * * `'a+'` - Open file for reading and appending. The file is created if it does not exist. + * * `'ax+'` - Like 'a+' but opens the file in exclusive mode. + * + * Exclusive mode ensures that the file path is newly created. + * @class + */ + var FileFlag = (function () { + /** + * This should never be called directly. + * @param [String] modeStr The string representing the mode + * @throw [BrowserFS.ApiError] when the mode string is invalid + */ + function FileFlag(flagStr) { + this.flagStr = flagStr; + if (FileFlag.validFlagStrs.indexOf(flagStr) < 0) { + throw new api_error.ApiError(9 /* EINVAL */, "Invalid flag: " + flagStr); + } + } + /** + * Get an object representing the given file mode. + * @param [String] modeStr The string representing the mode + * @return [BrowserFS.FileMode] The FileMode object representing the mode + * @throw [BrowserFS.ApiError] when the mode string is invalid + */ + FileFlag.getFileFlag = function (flagStr) { + // Check cache first. + if (FileFlag.flagCache.hasOwnProperty(flagStr)) { + return FileFlag.flagCache[flagStr]; + } + return FileFlag.flagCache[flagStr] = new FileFlag(flagStr); + }; + + /** + * Returns true if the file is readable. + * @return [Boolean] + */ + FileFlag.prototype.isReadable = function () { + return this.flagStr.indexOf('r') !== -1 || this.flagStr.indexOf('+') !== -1; + }; + + /** + * Returns true if the file is writeable. + * @return [Boolean] + */ + FileFlag.prototype.isWriteable = function () { + return this.flagStr.indexOf('w') !== -1 || this.flagStr.indexOf('a') !== -1 || this.flagStr.indexOf('+') !== -1; + }; + + /** + * Returns true if the file mode should truncate. + * @return [Boolean] + */ + FileFlag.prototype.isTruncating = function () { + return this.flagStr.indexOf('w') !== -1; + }; + + /** + * Returns true if the file is appendable. + * @return [Boolean] + */ + FileFlag.prototype.isAppendable = function () { + return this.flagStr.indexOf('a') !== -1; + }; + + /** + * Returns true if the file is open in synchronous mode. + * @return [Boolean] + */ + FileFlag.prototype.isSynchronous = function () { + return this.flagStr.indexOf('s') !== -1; + }; + + /** + * Returns true if the file is open in exclusive mode. + * @return [Boolean] + */ + FileFlag.prototype.isExclusive = function () { + return this.flagStr.indexOf('x') !== -1; + }; + + /** + * Returns one of the static fields on this object that indicates the + * appropriate response to the path existing. + * @return [Number] + */ + FileFlag.prototype.pathExistsAction = function () { + if (this.isExclusive()) { + return 1 /* THROW_EXCEPTION */; + } else if (this.isTruncating()) { + return 2 /* TRUNCATE_FILE */; + } else { + return 0 /* NOP */; + } + }; + + /** + * Returns one of the static fields on this object that indicates the + * appropriate response to the path not existing. + * @return [Number] + */ + FileFlag.prototype.pathNotExistsAction = function () { + if ((this.isWriteable() || this.isAppendable()) && this.flagStr !== 'r+') { + return 3 /* CREATE_FILE */; + } else { + return 1 /* THROW_EXCEPTION */; + } + }; + FileFlag.flagCache = {}; + + FileFlag.validFlagStrs = ['r', 'r+', 'rs', 'rs+', 'w', 'wx', 'w+', 'wx+', 'a', 'ax', 'a+', 'ax+']; + return FileFlag; + })(); + exports.FileFlag = FileFlag; +}); +//# sourceMappingURL=file_flag.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/node_eventemitter',["require", "exports", './buffer', './api_error'], function(require, exports, buffer, api_error) { + var Buffer = buffer.Buffer; + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + + /** + * Internal class. Represents a buffered event. + */ + var BufferedEvent = (function () { + function BufferedEvent(data, encoding, cb) { + this.data = data; + this.encoding = encoding; + this.cb = cb; + this.size = typeof (data) !== 'string' ? data.length : Buffer.byteLength(data, encoding != null ? encoding : undefined); + + // If data is a buffer, we need to copy it. + if (typeof (this.data) !== 'string') { + this.data = this.data.sliceCopy(); + } + } + BufferedEvent.prototype.getData = function (encoding) { + if (encoding == null) { + if (typeof (this.data) === 'string') { + return new Buffer(this.data, this.encoding != null ? this.encoding : undefined); + } else { + return this.data; + } + } else { + if (typeof (this.data) === 'string') { + if (encoding === this.encoding) { + return this.data; + } else { + return (new Buffer(this.data, this.encoding != null ? this.encoding : undefined)).toString(encoding); + } + } else { + return this.data.toString(encoding); + } + } + }; + return BufferedEvent; + })(); + + /** + * Provides an abstract implementation of the EventEmitter interface. + */ + var AbstractEventEmitter = (function () { + function AbstractEventEmitter() { + this._listeners = {}; + this.maxListeners = 10; + } + /** + * Adds a listener for the particular event. + */ + AbstractEventEmitter.prototype.addListener = function (event, listener) { + if (typeof (this._listeners[event]) === 'undefined') { + this._listeners[event] = []; + } + if (this._listeners[event].push(listener) > this.maxListeners) { + process.stdout.write("Warning: Event " + event + " has more than " + this.maxListeners + " listeners.\n"); + } + this.emit('newListener', event, listener); + return this; + }; + + /** + * Adds a listener for the particular event. + */ + AbstractEventEmitter.prototype.on = function (event, listener) { + return this.addListener(event, listener); + }; + + /** + * Adds a listener for the particular event that fires only once. + */ + AbstractEventEmitter.prototype.once = function (event, listener) { + // Create a new callback that will only fire once. + var fired = false, newListener = function () { + this.removeListener(event, newListener); + + if (!fired) { + fired = true; + listener.apply(this, arguments); + } + }; + return this.addListener(event, newListener); + }; + + /** + * Emits the 'removeListener' event for the specified listeners. + */ + AbstractEventEmitter.prototype._emitRemoveListener = function (event, listeners) { + var i; + + // Only emit the event if someone is listening. + if (this._listeners['removeListener'] && this._listeners['removeListener'].length > 0) { + for (i = 0; i < listeners.length; i++) { + this.emit('removeListener', event, listeners[i]); + } + } + }; + + /** + * Removes the particular listener for the given event. + */ + AbstractEventEmitter.prototype.removeListener = function (event, listener) { + var listeners = this._listeners[event]; + if (typeof (listeners) !== 'undefined') { + // Remove listener, if present. + var idx = listeners.indexOf(listener); + if (idx > -1) { + listeners.splice(idx, 1); + } + } + this.emit('removeListener', event, listener); + return this; + }; + + /** + * Removes all listeners, or those of the specified event. + */ + AbstractEventEmitter.prototype.removeAllListeners = function (event) { + var removed, keys, i; + if (typeof (event) !== 'undefined') { + removed = this._listeners[event]; + + // Clear one event. + this._listeners[event] = []; + this._emitRemoveListener(event, removed); + } else { + // Clear all events. + keys = Object.keys(this._listeners); + for (i = 0; i < keys.length; i++) { + this.removeAllListeners(keys[i]); + } + } + return this; + }; + + /** + * EventEmitters print a warning when an event has greater than this specified + * number of listeners. + */ + AbstractEventEmitter.prototype.setMaxListeners = function (n) { + this.maxListeners = n; + }; + + /** + * Returns the listeners for the given event. + */ + AbstractEventEmitter.prototype.listeners = function (event) { + if (typeof (this._listeners[event]) === 'undefined') { + this._listeners[event] = []; + } + + // Return a *copy* of our internal structure. + return this._listeners[event].slice(0); + }; + + /** + * Emits the specified event to all listeners of the particular event. + */ + AbstractEventEmitter.prototype.emit = function (event) { + var args = []; + for (var _i = 0; _i < (arguments.length - 1); _i++) { + args[_i] = arguments[_i + 1]; + } + var listeners = this._listeners[event], rv = false; + if (typeof (listeners) !== 'undefined') { + var i; + for (i = 0; i < listeners.length; i++) { + rv = true; + listeners[i].apply(this, args); + } + } + return rv; + }; + return AbstractEventEmitter; + })(); + exports.AbstractEventEmitter = AbstractEventEmitter; + + /** + * Provides an abstract implementation of the WritableStream and ReadableStream + * interfaces. + * @todo: Check readable/writable status. + */ + var AbstractDuplexStream = (function (_super) { + __extends(AbstractDuplexStream, _super); + /** + * Abstract stream implementation that can be configured to be readable and/or + * writable. + */ + function AbstractDuplexStream(writable, readable) { + _super.call(this); + this.writable = writable; + this.readable = readable; + /** + * How should the data output be encoded? 'null' means 'Buffer'. + */ + this.encoding = null; + /** + * Is this stream currently flowing (resumed) or non-flowing (paused)? + */ + this.flowing = false; + /** + * Event buffer. Simply queues up all write requests. + */ + this.buffer = []; + /** + * Once set, the stream is closed. Emitted once 'buffer' is empty. + */ + this.endEvent = null; + /** + * Has the stream ended? + */ + this.ended = false; + /** + * The last time we checked, was the buffer empty? + * We emit 'readable' events when this transitions from 'true' -> 'false'. + */ + this.drained = true; + } + /** + * Adds a listener for the particular event. + * Implemented here so that we can capture data EventListeners, which trigger + * us to 'resume'. + */ + AbstractDuplexStream.prototype.addListener = function (event, listener) { + var rv = _super.prototype.addListener.call(this, event, listener), _this = this; + if (event === 'data' && !this.flowing) { + this.resume(); + } else if (event === 'readable' && this.buffer.length > 0) { + setTimeout(function () { + _this.emit('readable'); + }, 0); + } + return rv; + }; + + /** + * Helper function for 'write' and 'end' functions. + */ + AbstractDuplexStream.prototype._processArgs = function (data, arg2, arg3) { + if (typeof (arg2) === 'string') { + // data, encoding, cb? + return new BufferedEvent(data, arg2, arg3); + } else { + // data, cb? + return new BufferedEvent(data, null, arg2); + } + }; + + /** + * If flowing, this will process pending events. + */ + AbstractDuplexStream.prototype._processEvents = function () { + var drained = this.buffer.length === 0; + if (this.drained !== drained) { + if (this.drained) { + // Went from drained to not drained. New stuff is available. + // @todo: Is this event relevant in flowing mode? + this.emit('readable'); + } + } + + if (this.flowing && this.buffer.length !== 0) { + this.emit('data', this.read()); + } + + // Are we drained? Check. + this.drained = this.buffer.length === 0; + }; + + /** + * Emits the given buffered event. + */ + AbstractDuplexStream.prototype.emitEvent = function (type, event) { + this.emit(type, event.getData(this.encoding)); + if (event.cb) { + event.cb(); + } + }; + + AbstractDuplexStream.prototype.write = function (data, arg2, arg3) { + if (this.ended) { + throw new ApiError(0 /* EPERM */, 'Cannot write to an ended stream.'); + } + var event = this._processArgs(data, arg2, arg3); + this._push(event); + return this.flowing; + }; + + AbstractDuplexStream.prototype.end = function (data, arg2, arg3) { + if (this.ended) { + throw new ApiError(0 /* EPERM */, 'Stream is already closed.'); + } + var event = this._processArgs(data, arg2, arg3); + this.ended = true; + this.endEvent = event; + this._processEvents(); + }; + + /**** Readable Interface ****/ + /** + * Read a given number of bytes from the buffer. Should only be called in + * non-flowing mode. + * If we do not have `size` bytes available, return null. + */ + AbstractDuplexStream.prototype.read = function (size) { + var events = [], eventsCbs = [], lastCb, eventsSize = 0, event, buff, trueSize, i = 0, sizeUnspecified = typeof (size) !== 'number'; + + // I do this so I do not need to specialize the loop below. + if (sizeUnspecified) + size = 4294967295; + + for (i = 0; i < this.buffer.length && eventsSize < size; i++) { + event = this.buffer[i]; + events.push(event.getData()); + if (event.cb) { + eventsCbs.push(event.cb); + } + eventsSize += event.size; + lastCb = event.cb; + } + + if (!sizeUnspecified && eventsSize < size) { + // For some reason, the Node stream API specifies that we either return + // 'size' bytes of data, or nothing at all. + return null; + } + + // Remove all of the events we are processing from the buffer. + this.buffer = this.buffer.slice(events.length); + + // The 'true size' of the final event we're going to send out. + trueSize = eventsSize > size ? size : eventsSize; + + // Concat at all of the events into one buffer. + buff = Buffer.concat(events); + if (eventsSize > size) { + // If last event had a cb, ignore it -- we trigger it when that *entire* + // write finishes. + if (lastCb) + eventsCbs.pop(); + + // Make a new event for the remaining data. + this._push(new BufferedEvent(buff.slice(size), null, lastCb)); + } + + // Schedule the relevant cbs to fire *after* we've returned these values. + if (eventsCbs.length > 0) { + setTimeout(function () { + var i; + for (i = 0; i < eventsCbs.length; i++) { + eventsCbs[i](); + } + }, 0); + } + + // If we're at the end of the buffer and an endEvent is specified, schedule + // the event to fire. + if (this.ended && this.buffer.length === 0 && this.endEvent !== null) { + var endEvent = this.endEvent, _this = this; + + // Erase it so we don't accidentally trigger it again. + this.endEvent = null; + setTimeout(function () { + _this.emitEvent('end', endEvent); + }, 0); + } + + // Return in correct encoding. + if (events.length === 0) { + // Buffer was empty. We're supposed to return 'null', as opposed to an + // empty buffer or string. + // [BFS] Emit a '_read' event to signal that maybe the write-end of this + // should push some data into the pipe. + this.emit('_read'); + return null; + } else if (this.encoding === null) { + return buff.slice(0, trueSize); + } else { + return buff.toString(this.encoding, 0, trueSize); + } + }; + + /** + * Set the encoding for the 'data' event. + */ + AbstractDuplexStream.prototype.setEncoding = function (encoding) { + this.encoding = encoding; + }; + + /** + * Pause the stream. + */ + AbstractDuplexStream.prototype.pause = function () { + this.flowing = false; + }; + + /** + * Resume the stream. + */ + AbstractDuplexStream.prototype.resume = function () { + this.flowing = true; + + // Process any buffered writes. + this._processEvents(); + }; + + /** + * Pipe a readable stream into a writable stream. Currently unimplemented. + */ + AbstractDuplexStream.prototype.pipe = function (destination, options) { + throw new ApiError(0 /* EPERM */, "Unimplemented."); + }; + AbstractDuplexStream.prototype.unpipe = function (destination) { + }; + + AbstractDuplexStream.prototype.unshift = function (chunk) { + if (this.ended) { + throw new ApiError(0 /* EPERM */, "Stream has ended."); + } + this.buffer.unshift(new BufferedEvent(chunk, this.encoding)); + this._processEvents(); + }; + + /** + * 'Push' the given piece of data to the back of the buffer. + * Returns true if the event was sent out, false if buffered. + */ + AbstractDuplexStream.prototype._push = function (event) { + this.buffer.push(event); + this._processEvents(); + }; + + /** + * Enables backwards-compatibility with older versions of Node and their + * stream interface. Unimplemented. + */ + AbstractDuplexStream.prototype.wrap = function (stream) { + throw new ApiError(0 /* EPERM */, "Unimplemented."); + }; + return AbstractDuplexStream; + })(AbstractEventEmitter); + exports.AbstractDuplexStream = AbstractDuplexStream; +}); +//# sourceMappingURL=node_eventemitter.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/node_process',["require", "exports", './node_eventemitter'], function(require, exports, eventemitter) { + var path = null; + + var TTY = (function (_super) { + __extends(TTY, _super); + function TTY() { + _super.call(this, true, true); + this.isRaw = false; + this.columns = 80; + this.rows = 120; + this.isTTY = true; + } + /** + * Set read mode to 'true' to enable raw mode. + */ + TTY.prototype.setReadMode = function (mode) { + if (this.isRaw !== mode) { + this.isRaw = mode; + + // [BFS] TTY implementations can use this to change their event emitting + // patterns. + this.emit('modeChange'); + } + }; + + /** + * [BFS] Update the number of columns available on the terminal. + */ + TTY.prototype.changeColumns = function (columns) { + if (columns !== this.columns) { + this.columns = columns; + + // Resize event. + this.emit('resize'); + } + }; + + /** + * [BFS] Update the number of rows available on the terminal. + */ + TTY.prototype.changeRows = function (rows) { + if (rows !== this.rows) { + this.rows = rows; + + // Resize event. + this.emit('resize'); + } + }; + + /** + * Returns 'true' if the given object is a TTY. + */ + TTY.isatty = function (fd) { + return fd instanceof TTY; + }; + return TTY; + })(eventemitter.AbstractDuplexStream); + exports.TTY = TTY; + + /** + * Partial implementation of Node's `process` module. + * We implement the portions that are relevant for the filesystem. + * @see http://nodejs.org/api/process.html + * @class + */ + var Process = (function () { + function Process() { + this.startTime = Date.now(); + this._cwd = '/'; + /** + * Returns what platform you are running on. + * @return [String] + */ + this.platform = 'browser'; + this.argv = []; + this.stdout = new TTY(); + this.stderr = new TTY(); + this.stdin = new TTY(); + } + /** + * Changes the current working directory. + * + * **Note**: BrowserFS does not validate that the directory actually exists. + * + * @example Usage example + * console.log('Starting directory: ' + process.cwd()); + * process.chdir('/tmp'); + * console.log('New directory: ' + process.cwd()); + * @param [String] dir The directory to change to. + */ + Process.prototype.chdir = function (dir) { + // XXX: Circular dependency hack. + if (path === null) { + path = require('./node_path').path; + } + this._cwd = path.resolve(dir); + }; + + /** + * Returns the current working directory. + * @example Usage example + * console.log('Current directory: ' + process.cwd()); + * @return [String] The current working directory. + */ + Process.prototype.cwd = function () { + return this._cwd; + }; + + /** + * Number of seconds BrowserFS has been running. + * @return [Number] + */ + Process.prototype.uptime = function () { + return ((Date.now() - this.startTime) / 1000) | 0; + }; + return Process; + })(); + exports.Process = Process; + + // process is a singleton. + exports.process = new Process(); +}); +//# sourceMappingURL=node_process.js.map +; +define('core/node_path',["require", "exports", './node_process'], function(require, exports, node_process) { + var process = node_process.process; + + /** + * Emulates Node's `path` module. This module contains utilities for handling and + * transforming file paths. **All** of these methods perform only string + * transformations. The file system is not consulted to check whether paths are + * valid. + * @see http://nodejs.org/api/path.html + * @class + */ + var path = (function () { + function path() { + } + /** + * Normalize a string path, taking care of '..' and '.' parts. + * + * When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used. + * @example Usage example + * path.normalize('/foo/bar//baz/asdf/quux/..') + * // returns + * '/foo/bar/baz/asdf' + * @param [String] p The path to normalize. + * @return [String] + */ + path.normalize = function (p) { + // Special case: '' -> '.' + if (p === '') { + p = '.'; + } + + // It's very important to know if the path is relative or not, since it + // changes how we process .. and reconstruct the split string. + var absolute = p.charAt(0) === path.sep; + + // Remove repeated //s + p = path._removeDuplicateSeps(p); + + // Try to remove as many '../' as possible, and remove '.' completely. + var components = p.split(path.sep); + var goodComponents = []; + for (var idx = 0; idx < components.length; idx++) { + var c = components[idx]; + if (c === '.') { + continue; + } else if (c === '..' && (absolute || (!absolute && goodComponents.length > 0 && goodComponents[0] !== '..'))) { + // In the absolute case: Path is relative to root, so we may pop even if + // goodComponents is empty (e.g. /../ => /) + // In the relative case: We're getting rid of a directory that preceded + // it (e.g. /foo/../bar -> /bar) + goodComponents.pop(); + } else { + goodComponents.push(c); + } + } + + // Add in '.' when it's a relative path with no other nonempty components. + // Possible results: '.' and './' (input: [''] or []) + // @todo Can probably simplify this logic. + if (!absolute && goodComponents.length < 2) { + switch (goodComponents.length) { + case 1: + if (goodComponents[0] === '') { + goodComponents.unshift('.'); + } + break; + default: + goodComponents.push('.'); + } + } + p = goodComponents.join(path.sep); + if (absolute && p.charAt(0) !== path.sep) { + p = path.sep + p; + } + return p; + }; + + /** + * Join all arguments together and normalize the resulting path. + * + * Arguments must be strings. + * @example Usage + * path.join('/foo', 'bar', 'baz/asdf', 'quux', '..') + * // returns + * '/foo/bar/baz/asdf' + * + * path.join('foo', {}, 'bar') + * // throws exception + * TypeError: Arguments to path.join must be strings + * @param [String,...] paths Each component of the path + * @return [String] + */ + path.join = function () { + var paths = []; + for (var _i = 0; _i < (arguments.length - 0); _i++) { + paths[_i] = arguments[_i + 0]; + } + // Required: Prune any non-strings from the path. I also prune empty segments + // so we can do a simple join of the array. + var processed = []; + for (var i = 0; i < paths.length; i++) { + var segment = paths[i]; + if (typeof segment !== 'string') { + throw new TypeError("Invalid argument type to path.join: " + (typeof segment)); + } else if (segment !== '') { + processed.push(segment); + } + } + return path.normalize(processed.join(path.sep)); + }; + + /** + * Resolves to to an absolute path. + * + * If to isn't already absolute from arguments are prepended in right to left + * order, until an absolute path is found. If after using all from paths still + * no absolute path is found, the current working directory is used as well. + * The resulting path is normalized, and trailing slashes are removed unless + * the path gets resolved to the root directory. Non-string arguments are + * ignored. + * + * Another way to think of it is as a sequence of cd commands in a shell. + * + * path.resolve('foo/bar', '/tmp/file/', '..', 'a/../subfile') + * + * Is similar to: + * + * cd foo/bar + * cd /tmp/file/ + * cd .. + * cd a/../subfile + * pwd + * + * The difference is that the different paths don't need to exist and may also + * be files. + * @example Usage example + * path.resolve('/foo/bar', './baz') + * // returns + * '/foo/bar/baz' + * + * path.resolve('/foo/bar', '/tmp/file/') + * // returns + * '/tmp/file' + * + * path.resolve('wwwroot', 'static_files/png/', '../gif/image.gif') + * // if currently in /home/myself/node, it returns + * '/home/myself/node/wwwroot/static_files/gif/image.gif' + * @param [String,...] paths + * @return [String] + */ + path.resolve = function () { + var paths = []; + for (var _i = 0; _i < (arguments.length - 0); _i++) { + paths[_i] = arguments[_i + 0]; + } + // Monitor for invalid paths, throw out empty paths, and look for the *last* + // absolute path that we see. + var processed = []; + for (var i = 0; i < paths.length; i++) { + var p = paths[i]; + if (typeof p !== 'string') { + throw new TypeError("Invalid argument type to path.join: " + (typeof p)); + } else if (p !== '') { + // Remove anything that has occurred before this absolute path, as it + // doesn't matter. + if (p.charAt(0) === path.sep) { + processed = []; + } + processed.push(p); + } + } + + // Special: Remove trailing slash unless it's the root + var resolved = path.normalize(processed.join(path.sep)); + if (resolved.length > 1 && resolved.charAt(resolved.length - 1) === path.sep) { + return resolved.substr(0, resolved.length - 1); + } + + // Special: If it doesn't start with '/', it's relative and we need to append + // the current directory. + if (resolved.charAt(0) !== path.sep) { + // Remove ./, since we're going to append the current directory. + if (resolved.charAt(0) === '.' && (resolved.length === 1 || resolved.charAt(1) === path.sep)) { + resolved = resolved.length === 1 ? '' : resolved.substr(2); + } + + // Append the current directory, which *must* be an absolute path. + var cwd = process.cwd(); + if (resolved !== '') { + // cwd will never end in a /... unless it's the root. + resolved = this.normalize(cwd + (cwd !== '/' ? path.sep : '') + resolved); + } else { + resolved = cwd; + } + } + return resolved; + }; + + /** + * Solve the relative path from from to to. + * + * At times we have two absolute paths, and we need to derive the relative path + * from one to the other. This is actually the reverse transform of + * path.resolve, which means we see that: + * + * path.resolve(from, path.relative(from, to)) == path.resolve(to) + * + * @example Usage example + * path.relative('C:\\orandea\\test\\aaa', 'C:\\orandea\\impl\\bbb') + * // returns + * '..\\..\\impl\\bbb' + * + * path.relative('/data/orandea/test/aaa', '/data/orandea/impl/bbb') + * // returns + * '../../impl/bbb' + * @param [String] from + * @param [String] to + * @return [String] + */ + path.relative = function (from, to) { + var i; + + // Alright. Let's resolve these two to absolute paths and remove any + // weirdness. + from = path.resolve(from); + to = path.resolve(to); + var fromSegs = from.split(path.sep); + var toSegs = to.split(path.sep); + + // Remove the first segment on both, as it's '' (both are absolute paths) + toSegs.shift(); + fromSegs.shift(); + + // There are two segments to this path: + // * Going *up* the directory hierarchy with '..' + // * Going *down* the directory hierarchy with foo/baz/bat. + var upCount = 0; + var downSegs = []; + + for (i = 0; i < fromSegs.length; i++) { + var seg = fromSegs[i]; + if (seg === toSegs[i]) { + continue; + } + + // The rest of 'from', including the current element, indicates how many + // directories we need to go up. + upCount = fromSegs.length - i; + break; + } + + // The rest of 'to' indicates where we need to change to. We place this + // outside of the loop, as toSegs.length may be greater than fromSegs.length. + downSegs = toSegs.slice(i); + + // Special case: If 'from' is '/' + if (fromSegs.length === 1 && fromSegs[0] === '') { + upCount = 0; + } + + // upCount can't be greater than the number of fromSegs + // (cd .. from / is still /) + if (upCount > fromSegs.length) { + upCount = fromSegs.length; + } + + // Create the final string! + var rv = ''; + for (i = 0; i < upCount; i++) { + rv += '../'; + } + rv += downSegs.join(path.sep); + + // Special case: Remove trailing '/'. Happens if it's all up and no down. + if (rv.length > 1 && rv.charAt(rv.length - 1) === path.sep) { + rv = rv.substr(0, rv.length - 1); + } + return rv; + }; + + /** + * Return the directory name of a path. Similar to the Unix `dirname` command. + * + * Note that BrowserFS does not validate if the path is actually a valid + * directory. + * @example Usage example + * path.dirname('/foo/bar/baz/asdf/quux') + * // returns + * '/foo/bar/baz/asdf' + * @param [String] p The path to get the directory name of. + * @return [String] + */ + path.dirname = function (p) { + // We get rid of //, but we don't modify anything else (e.g. any extraneous . + // and ../ are kept intact) + p = path._removeDuplicateSeps(p); + var absolute = p.charAt(0) === path.sep; + var sections = p.split(path.sep); + + // Do 1 if it's /foo/bar, 2 if it's /foo/bar/ + if (sections.pop() === '' && sections.length > 0) { + sections.pop(); + } + if (sections.length > 1) { + return sections.join(path.sep); + } else if (absolute) { + return path.sep; + } else { + return '.'; + } + }; + + /** + * Return the last portion of a path. Similar to the Unix basename command. + * @example Usage example + * path.basename('/foo/bar/baz/asdf/quux.html') + * // returns + * 'quux.html' + * + * path.basename('/foo/bar/baz/asdf/quux.html', '.html') + * // returns + * 'quux' + * @param [String] p + * @param [String?] ext + * @return [String] + */ + path.basename = function (p, ext) { + if (typeof ext === "undefined") { ext = ""; } + // Special case: Normalize will modify this to '.' + if (p === '') { + return p; + } + + // Normalize the string first to remove any weirdness. + p = path.normalize(p); + + // Get the last part of the string. + var sections = p.split(path.sep); + var lastPart = sections[sections.length - 1]; + + // Special case: If it's empty, then we have a string like so: foo/ + // Meaning, 'foo' is guaranteed to be a directory. + if (lastPart === '' && sections.length > 1) { + return sections[sections.length - 2]; + } + + // Remove the extension, if need be. + if (ext.length > 0) { + var lastPartExt = lastPart.substr(lastPart.length - ext.length); + if (lastPartExt === ext) { + return lastPart.substr(0, lastPart.length - ext.length); + } + } + return lastPart; + }; + + /** + * Return the extension of the path, from the last '.' to end of string in the + * last portion of the path. If there is no '.' in the last portion of the path + * or the first character of it is '.', then it returns an empty string. + * @example Usage example + * path.extname('index.html') + * // returns + * '.html' + * + * path.extname('index.') + * // returns + * '.' + * + * path.extname('index') + * // returns + * '' + * @param [String] p + * @return [String] + */ + path.extname = function (p) { + p = path.normalize(p); + var sections = p.split(path.sep); + p = sections.pop(); + + // Special case: foo/file.ext/ should return '.ext' + if (p === '' && sections.length > 0) { + p = sections.pop(); + } + if (p === '..') { + return ''; + } + var i = p.lastIndexOf('.'); + if (i === -1 || i === 0) { + return ''; + } + return p.substr(i); + }; + + /** + * Checks if the given path is an absolute path. + * + * Despite not being documented, this is a tested part of Node's path API. + * @param [String] p + * @return [Boolean] True if the path appears to be an absolute path. + */ + path.isAbsolute = function (p) { + return p.length > 0 && p.charAt(0) === path.sep; + }; + + /** + * Unknown. Undocumented. + */ + path._makeLong = function (p) { + return p; + }; + + path._removeDuplicateSeps = function (p) { + p = p.replace(this._replaceRegex, this.sep); + return p; + }; + path.sep = '/'; + + path._replaceRegex = new RegExp("//+", 'g'); + + path.delimiter = ':'; + return path; + })(); + exports.path = path; +}); +//# sourceMappingURL=node_path.js.map +; +define('core/node_fs',["require", "exports", './api_error', './file_flag', './buffer', './node_path'], function(require, exports, api_error, file_flag, buffer, node_path) { + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + var FileFlag = file_flag.FileFlag; + var Buffer = buffer.Buffer; + var path = node_path.path; + + /** + * Wraps a callback with a setImmediate call. + * @param [Function] cb The callback to wrap. + * @param [Number] numArgs The number of arguments that the callback takes. + * @return [Function] The wrapped callback. + */ + function wrapCb(cb, numArgs) { + if (typeof cb !== 'function') { + throw new ApiError(9 /* EINVAL */, 'Callback must be a function.'); + } + + // @todo This is used for unit testing. Maybe we should inject this logic + // dynamically rather than bundle it in 'production' code. + if (typeof __numWaiting === 'undefined') { + __numWaiting = 0; + } + __numWaiting++; + + switch (numArgs) { + case 1: + return function (arg1) { + setImmediate(function () { + __numWaiting--; + return cb(arg1); + }); + }; + case 2: + return function (arg1, arg2) { + setImmediate(function () { + __numWaiting--; + return cb(arg1, arg2); + }); + }; + case 3: + return function (arg1, arg2, arg3) { + setImmediate(function () { + __numWaiting--; + return cb(arg1, arg2, arg3); + }); + }; + default: + throw new Error('Invalid invocation of wrapCb.'); + } + } + + /** + * Checks if the fd is valid. + * @param [BrowserFS.File] fd A file descriptor (in BrowserFS, it's a File object) + * @return [Boolean, BrowserFS.ApiError] Returns `true` if the FD is OK, + * otherwise returns an ApiError. + */ + function checkFd(fd) { + if (typeof fd['write'] !== 'function') { + throw new ApiError(3 /* EBADF */, 'Invalid file descriptor.'); + } + } + + function normalizeMode(mode, def) { + switch (typeof mode) { + case 'number': + // (path, flag, mode, cb?) + return mode; + case 'string': + // (path, flag, modeString, cb?) + var trueMode = parseInt(mode, 8); + if (trueMode !== NaN) { + return trueMode; + } + + default: + return def; + } + } + + function normalizePath(p) { + // Node doesn't allow null characters in paths. + if (p.indexOf('\u0000') >= 0) { + throw new ApiError(9 /* EINVAL */, 'Path must be a string without null bytes.'); + } else if (p === '') { + throw new ApiError(9 /* EINVAL */, 'Path must not be empty.'); + } + return path.resolve(p); + } + + function normalizeOptions(options, defEnc, defFlag, defMode) { + switch (typeof options) { + case 'object': + return { + encoding: typeof options['encoding'] !== 'undefined' ? options['encoding'] : defEnc, + flag: typeof options['flag'] !== 'undefined' ? options['flag'] : defFlag, + mode: normalizeMode(options['mode'], defMode) + }; + case 'string': + return { + encoding: options, + flag: defFlag, + mode: defMode + }; + default: + return { + encoding: defEnc, + flag: defFlag, + mode: defMode + }; + } + } + + // The default callback is a NOP. + function nopCb() { + } + ; + + /** + * The node frontend to all filesystems. + * This layer handles: + * + * * Sanity checking inputs. + * * Normalizing paths. + * * Resetting stack depth for asynchronous operations which may not go through + * the browser by wrapping all input callbacks using `setImmediate`. + * * Performing the requested operation through the filesystem or the file + * descriptor, as appropriate. + * * Handling optional arguments and setting default arguments. + * @see http://nodejs.org/api/fs.html + * @class + */ + var fs = (function () { + function fs() { + } + fs._initialize = function (rootFS) { + if (!rootFS.constructor.isAvailable()) { + throw new ApiError(9 /* EINVAL */, 'Tried to instantiate BrowserFS with an unavailable file system.'); + } + return fs.root = rootFS; + }; + + fs._toUnixTimestamp = function (time) { + if (typeof time === 'number') { + return time; + } else if (time instanceof Date) { + return time.getTime() / 1000; + } + throw new Error("Cannot parse time: " + time); + }; + + /** + * **NONSTANDARD**: Grab the FileSystem instance that backs this API. + * @return [BrowserFS.FileSystem | null] Returns null if the file system has + * not been initialized. + */ + fs.getRootFS = function () { + if (fs.root) { + return fs.root; + } else { + return null; + } + }; + + // FILE OR DIRECTORY METHODS + /** + * Asynchronous rename. No arguments other than a possible exception are given + * to the completion callback. + * @param [String] oldPath + * @param [String] newPath + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.rename = function (oldPath, newPath, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + fs.root.rename(normalizePath(oldPath), normalizePath(newPath), newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous rename. + * @param [String] oldPath + * @param [String] newPath + */ + fs.renameSync = function (oldPath, newPath) { + fs.root.renameSync(normalizePath(oldPath), normalizePath(newPath)); + }; + + /** + * Test whether or not the given path exists by checking with the file system. + * Then call the callback argument with either true or false. + * @example Sample invocation + * fs.exists('/etc/passwd', function (exists) { + * util.debug(exists ? "it's there" : "no passwd!"); + * }); + * @param [String] path + * @param [Function(Boolean)] callback + */ + fs.exists = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + return fs.root.exists(normalizePath(path), newCb); + } catch (e) { + // Doesn't return an error. If something bad happens, we assume it just + // doesn't exist. + return newCb(false); + } + }; + + /** + * Test whether or not the given path exists by checking with the file system. + * @param [String] path + * @return [boolean] + */ + fs.existsSync = function (path) { + try { + return fs.root.existsSync(normalizePath(path)); + } catch (e) { + // Doesn't return an error. If something bad happens, we assume it just + // doesn't exist. + return false; + } + }; + + /** + * Asynchronous `stat`. + * @param [String] path + * @param [Function(BrowserFS.ApiError, BrowserFS.node.fs.Stats)] callback + */ + fs.stat = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 2); + try { + return fs.root.stat(normalizePath(path), false, newCb); + } catch (e) { + return newCb(e, null); + } + }; + + /** + * Synchronous `stat`. + * @param [String] path + * @return [BrowserFS.node.fs.Stats] + */ + fs.statSync = function (path) { + return fs.root.statSync(normalizePath(path), false); + }; + + /** + * Asynchronous `lstat`. + * `lstat()` is identical to `stat()`, except that if path is a symbolic link, + * then the link itself is stat-ed, not the file that it refers to. + * @param [String] path + * @param [Function(BrowserFS.ApiError, BrowserFS.node.fs.Stats)] callback + */ + fs.lstat = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 2); + try { + return fs.root.stat(normalizePath(path), true, newCb); + } catch (e) { + return newCb(e, null); + } + }; + + /** + * Synchronous `lstat`. + * `lstat()` is identical to `stat()`, except that if path is a symbolic link, + * then the link itself is stat-ed, not the file that it refers to. + * @param [String] path + * @return [BrowserFS.node.fs.Stats] + */ + fs.lstatSync = function (path) { + return fs.root.statSync(normalizePath(path), true); + }; + + fs.truncate = function (path, arg2, cb) { + if (typeof arg2 === "undefined") { arg2 = 0; } + if (typeof cb === "undefined") { cb = nopCb; } + var len = 0; + if (typeof arg2 === 'function') { + cb = arg2; + } else if (typeof arg2 === 'number') { + len = arg2; + } + + var newCb = wrapCb(cb, 1); + try { + if (len < 0) { + throw new ApiError(9 /* EINVAL */); + } + return fs.root.truncate(normalizePath(path), len, newCb); + } catch (e) { + return newCb(e); + } + }; + + /** + * Synchronous `truncate`. + * @param [String] path + * @param [Number] len + */ + fs.truncateSync = function (path, len) { + if (typeof len === "undefined") { len = 0; } + if (len < 0) { + throw new ApiError(9 /* EINVAL */); + } + return fs.root.truncateSync(normalizePath(path), len); + }; + + /** + * Asynchronous `unlink`. + * @param [String] path + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.unlink = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + return fs.root.unlink(normalizePath(path), newCb); + } catch (e) { + return newCb(e); + } + }; + + /** + * Synchronous `unlink`. + * @param [String] path + */ + fs.unlinkSync = function (path) { + return fs.root.unlinkSync(normalizePath(path)); + }; + + fs.open = function (path, flag, arg2, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var mode = normalizeMode(arg2, 0x1a4); + cb = typeof arg2 === 'function' ? arg2 : cb; + var newCb = wrapCb(cb, 2); + try { + return fs.root.open(normalizePath(path), FileFlag.getFileFlag(flag), mode, newCb); + } catch (e) { + return newCb(e, null); + } + }; + + fs.openSync = function (path, flag, mode) { + if (typeof mode === "undefined") { mode = 0x1a4; } + return fs.root.openSync(normalizePath(path), FileFlag.getFileFlag(flag), mode); + }; + + fs.readFile = function (filename, arg2, cb) { + if (typeof arg2 === "undefined") { arg2 = {}; } + if (typeof cb === "undefined") { cb = nopCb; } + var options = normalizeOptions(arg2, null, 'r', null); + cb = typeof arg2 === 'function' ? arg2 : cb; + var newCb = wrapCb(cb, 2); + try { + var flag = FileFlag.getFileFlag(options['flag']); + if (!flag.isReadable()) { + return newCb(new ApiError(9 /* EINVAL */, 'Flag passed to readFile must allow for reading.')); + } + return fs.root.readFile(normalizePath(filename), options.encoding, flag, newCb); + } catch (e) { + return newCb(e, null); + } + }; + + fs.readFileSync = function (filename, arg2) { + if (typeof arg2 === "undefined") { arg2 = {}; } + var options = normalizeOptions(arg2, null, 'r', null); + var flag = FileFlag.getFileFlag(options.flag); + if (!flag.isReadable()) { + throw new ApiError(9 /* EINVAL */, 'Flag passed to readFile must allow for reading.'); + } + return fs.root.readFileSync(normalizePath(filename), options.encoding, flag); + }; + + fs.writeFile = function (filename, data, arg3, cb) { + if (typeof arg3 === "undefined") { arg3 = {}; } + if (typeof cb === "undefined") { cb = nopCb; } + var options = normalizeOptions(arg3, 'utf8', 'w', 0x1a4); + cb = typeof arg3 === 'function' ? arg3 : cb; + var newCb = wrapCb(cb, 1); + try { + var flag = FileFlag.getFileFlag(options.flag); + if (!flag.isWriteable()) { + return newCb(new ApiError(9 /* EINVAL */, 'Flag passed to writeFile must allow for writing.')); + } + return fs.root.writeFile(normalizePath(filename), data, options.encoding, flag, options.mode, newCb); + } catch (e) { + return newCb(e); + } + }; + + fs.writeFileSync = function (filename, data, arg3) { + var options = normalizeOptions(arg3, 'utf8', 'w', 0x1a4); + var flag = FileFlag.getFileFlag(options.flag); + if (!flag.isWriteable()) { + throw new ApiError(9 /* EINVAL */, 'Flag passed to writeFile must allow for writing.'); + } + return fs.root.writeFileSync(normalizePath(filename), data, options.encoding, flag, options.mode); + }; + + fs.appendFile = function (filename, data, arg3, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var options = normalizeOptions(arg3, 'utf8', 'a', 0x1a4); + cb = typeof arg3 === 'function' ? arg3 : cb; + var newCb = wrapCb(cb, 1); + try { + var flag = FileFlag.getFileFlag(options.flag); + if (!flag.isAppendable()) { + return newCb(new ApiError(9 /* EINVAL */, 'Flag passed to appendFile must allow for appending.')); + } + fs.root.appendFile(normalizePath(filename), data, options.encoding, flag, options.mode, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.appendFileSync = function (filename, data, arg3) { + var options = normalizeOptions(arg3, 'utf8', 'a', 0x1a4); + var flag = FileFlag.getFileFlag(options.flag); + if (!flag.isAppendable()) { + throw new ApiError(9 /* EINVAL */, 'Flag passed to appendFile must allow for appending.'); + } + return fs.root.appendFileSync(normalizePath(filename), data, options.encoding, flag, options.mode); + }; + + // FILE DESCRIPTOR METHODS + /** + * Asynchronous `fstat`. + * `fstat()` is identical to `stat()`, except that the file to be stat-ed is + * specified by the file descriptor `fd`. + * @param [BrowserFS.File] fd + * @param [Function(BrowserFS.ApiError, BrowserFS.node.fs.Stats)] callback + */ + fs.fstat = function (fd, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 2); + try { + checkFd(fd); + fd.stat(newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `fstat`. + * `fstat()` is identical to `stat()`, except that the file to be stat-ed is + * specified by the file descriptor `fd`. + * @param [BrowserFS.File] fd + * @return [BrowserFS.node.fs.Stats] + */ + fs.fstatSync = function (fd) { + checkFd(fd); + return fd.statSync(); + }; + + /** + * Asynchronous close. + * @param [BrowserFS.File] fd + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.close = function (fd, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + checkFd(fd); + fd.close(newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous close. + * @param [BrowserFS.File] fd + */ + fs.closeSync = function (fd) { + checkFd(fd); + return fd.closeSync(); + }; + + fs.ftruncate = function (fd, arg2, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var length = typeof arg2 === 'number' ? arg2 : 0; + cb = typeof arg2 === 'function' ? arg2 : cb; + var newCb = wrapCb(cb, 1); + try { + checkFd(fd); + if (length < 0) { + throw new ApiError(9 /* EINVAL */); + } + fd.truncate(length, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous ftruncate. + * @param [BrowserFS.File] fd + * @param [Number] len + */ + fs.ftruncateSync = function (fd, len) { + if (typeof len === "undefined") { len = 0; } + checkFd(fd); + return fd.truncateSync(len); + }; + + /** + * Asynchronous fsync. + * @param [BrowserFS.File] fd + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.fsync = function (fd, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + checkFd(fd); + fd.sync(newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous fsync. + * @param [BrowserFS.File] fd + */ + fs.fsyncSync = function (fd) { + checkFd(fd); + return fd.syncSync(); + }; + + /** + * Asynchronous fdatasync. + * @param [BrowserFS.File] fd + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.fdatasync = function (fd, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + checkFd(fd); + fd.datasync(newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous fdatasync. + * @param [BrowserFS.File] fd + */ + fs.fdatasyncSync = function (fd) { + checkFd(fd); + fd.datasyncSync(); + }; + + fs.write = function (fd, arg2, arg3, arg4, arg5, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var buffer, offset, length, position = null; + if (typeof arg2 === 'string') { + // Signature 1: (fd, string, [position?, [encoding?]], cb?) + var encoding = 'utf8'; + switch (typeof arg3) { + case 'function': + // (fd, string, cb) + cb = arg3; + break; + case 'number': + // (fd, string, position, encoding?, cb?) + position = arg3; + encoding = typeof arg4 === 'string' ? arg4 : 'utf8'; + cb = typeof arg5 === 'function' ? arg5 : cb; + break; + default: + // ...try to find the callback and get out of here! + cb = typeof arg4 === 'function' ? arg4 : typeof arg5 === 'function' ? arg5 : cb; + return cb(new ApiError(9 /* EINVAL */, 'Invalid arguments.')); + } + buffer = new Buffer(arg2, encoding); + offset = 0; + length = buffer.length; + } else { + // Signature 2: (fd, buffer, offset, length, position?, cb?) + buffer = arg2; + offset = arg3; + length = arg4; + position = typeof arg5 === 'number' ? arg5 : null; + cb = typeof arg5 === 'function' ? arg5 : cb; + } + + var newCb = wrapCb(cb, 3); + try { + checkFd(fd); + if (position == null) { + position = fd.getPos(); + } + fd.write(buffer, offset, length, position, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.writeSync = function (fd, arg2, arg3, arg4, arg5) { + var buffer, offset = 0, length, position; + if (typeof arg2 === 'string') { + // Signature 1: (fd, string, [position?, [encoding?]]) + position = typeof arg3 === 'number' ? arg3 : null; + var encoding = typeof arg4 === 'string' ? arg4 : 'utf8'; + offset = 0; + buffer = new Buffer(arg2, encoding); + length = buffer.length; + } else { + // Signature 2: (fd, buffer, offset, length, position?) + buffer = arg2; + offset = arg3; + length = arg4; + position = typeof arg5 === 'number' ? arg5 : null; + } + + checkFd(fd); + if (position == null) { + position = fd.getPos(); + } + return fd.writeSync(buffer, offset, length, position); + }; + + fs.read = function (fd, arg2, arg3, arg4, arg5, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var position, offset, length, buffer, newCb; + if (typeof arg2 === 'number') { + // legacy interface + // (fd, length, position, encoding, callback) + length = arg2; + position = arg3; + var encoding = arg4; + cb = typeof arg5 === 'function' ? arg5 : cb; + offset = 0; + buffer = new Buffer(length); + + // XXX: Inefficient. + // Wrap the cb so we shelter upper layers of the API from these + // shenanigans. + newCb = wrapCb((function (err, bytesRead, buf) { + if (err) { + return cb(err); + } + cb(err, buf.toString(encoding), bytesRead); + }), 3); + } else { + buffer = arg2; + offset = arg3; + length = arg4; + position = arg5; + newCb = wrapCb(cb, 3); + } + + try { + checkFd(fd); + if (position == null) { + position = fd.getPos(); + } + fd.read(buffer, offset, length, position, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.readSync = function (fd, arg2, arg3, arg4, arg5) { + var shenanigans = false; + var buffer, offset, length, position; + if (typeof arg2 === 'number') { + length = arg2; + position = arg3; + var encoding = arg4; + offset = 0; + buffer = new Buffer(length); + shenanigans = true; + } else { + buffer = arg2; + offset = arg3; + length = arg4; + position = arg5; + } + checkFd(fd); + if (position == null) { + position = fd.getPos(); + } + + var rv = fd.readSync(buffer, offset, length, position); + if (!shenanigans) { + return rv; + } else { + return [buffer.toString(encoding), rv]; + } + }; + + /** + * Asynchronous `fchown`. + * @param [BrowserFS.File] fd + * @param [Number] uid + * @param [Number] gid + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.fchown = function (fd, uid, gid, callback) { + if (typeof callback === "undefined") { callback = nopCb; } + var newCb = wrapCb(callback, 1); + try { + checkFd(fd); + fd.chown(uid, gid, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `fchown`. + * @param [BrowserFS.File] fd + * @param [Number] uid + * @param [Number] gid + */ + fs.fchownSync = function (fd, uid, gid) { + checkFd(fd); + return fd.chownSync(uid, gid); + }; + + fs.fchmod = function (fd, mode, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + checkFd(fd); + fd.chmod(mode, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.fchmodSync = function (fd, mode) { + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + checkFd(fd); + return fd.chmodSync(mode); + }; + + fs.futimes = function (fd, atime, mtime, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + checkFd(fd); + if (typeof atime === 'number') { + atime = new Date(atime * 1000); + } + if (typeof mtime === 'number') { + mtime = new Date(mtime * 1000); + } + fd.utimes(atime, mtime, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.futimesSync = function (fd, atime, mtime) { + checkFd(fd); + if (typeof atime === 'number') { + atime = new Date(atime * 1000); + } + if (typeof mtime === 'number') { + mtime = new Date(mtime * 1000); + } + return fd.utimesSync(atime, mtime); + }; + + // DIRECTORY-ONLY METHODS + /** + * Asynchronous `rmdir`. + * @param [String] path + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.rmdir = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + path = normalizePath(path); + fs.root.rmdir(path, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `rmdir`. + * @param [String] path + */ + fs.rmdirSync = function (path) { + path = normalizePath(path); + return fs.root.rmdirSync(path); + }; + + /** + * Asynchronous `mkdir`. + * @param [String] path + * @param [Number?] mode defaults to `0777` + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.mkdir = function (path, mode, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + if (typeof mode === 'function') { + cb = mode; + mode = 0x1ff; + } + var newCb = wrapCb(cb, 1); + try { + path = normalizePath(path); + fs.root.mkdir(path, mode, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.mkdirSync = function (path, mode) { + if (typeof mode === "undefined") { mode = 0x1ff; } + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + path = normalizePath(path); + return fs.root.mkdirSync(path, mode); + }; + + /** + * Asynchronous `readdir`. Reads the contents of a directory. + * The callback gets two arguments `(err, files)` where `files` is an array of + * the names of the files in the directory excluding `'.'` and `'..'`. + * @param [String] path + * @param [Function(BrowserFS.ApiError, String[])] callback + */ + fs.readdir = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 2); + try { + path = normalizePath(path); + fs.root.readdir(path, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `readdir`. Reads the contents of a directory. + * @param [String] path + * @return [String[]] + */ + fs.readdirSync = function (path) { + path = normalizePath(path); + return fs.root.readdirSync(path); + }; + + // SYMLINK METHODS + /** + * Asynchronous `link`. + * @param [String] srcpath + * @param [String] dstpath + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.link = function (srcpath, dstpath, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + srcpath = normalizePath(srcpath); + dstpath = normalizePath(dstpath); + fs.root.link(srcpath, dstpath, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `link`. + * @param [String] srcpath + * @param [String] dstpath + */ + fs.linkSync = function (srcpath, dstpath) { + srcpath = normalizePath(srcpath); + dstpath = normalizePath(dstpath); + return fs.root.linkSync(srcpath, dstpath); + }; + + fs.symlink = function (srcpath, dstpath, arg3, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var type = typeof arg3 === 'string' ? arg3 : 'file'; + cb = typeof arg3 === 'function' ? arg3 : cb; + var newCb = wrapCb(cb, 1); + try { + if (type !== 'file' && type !== 'dir') { + return newCb(new ApiError(9 /* EINVAL */, "Invalid type: " + type)); + } + srcpath = normalizePath(srcpath); + dstpath = normalizePath(dstpath); + fs.root.symlink(srcpath, dstpath, type, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `symlink`. + * @param [String] srcpath + * @param [String] dstpath + * @param [String?] type can be either `'dir'` or `'file'` (default is `'file'`) + */ + fs.symlinkSync = function (srcpath, dstpath, type) { + if (type == null) { + type = 'file'; + } else if (type !== 'file' && type !== 'dir') { + throw new ApiError(9 /* EINVAL */, "Invalid type: " + type); + } + srcpath = normalizePath(srcpath); + dstpath = normalizePath(dstpath); + return fs.root.symlinkSync(srcpath, dstpath, type); + }; + + /** + * Asynchronous readlink. + * @param [String] path + * @param [Function(BrowserFS.ApiError, String)] callback + */ + fs.readlink = function (path, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 2); + try { + path = normalizePath(path); + fs.root.readlink(path, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous readlink. + * @param [String] path + * @return [String] + */ + fs.readlinkSync = function (path) { + path = normalizePath(path); + return fs.root.readlinkSync(path); + }; + + // PROPERTY OPERATIONS + /** + * Asynchronous `chown`. + * @param [String] path + * @param [Number] uid + * @param [Number] gid + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.chown = function (path, uid, gid, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + path = normalizePath(path); + fs.root.chown(path, false, uid, gid, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `chown`. + * @param [String] path + * @param [Number] uid + * @param [Number] gid + */ + fs.chownSync = function (path, uid, gid) { + path = normalizePath(path); + fs.root.chownSync(path, false, uid, gid); + }; + + /** + * Asynchronous `lchown`. + * @param [String] path + * @param [Number] uid + * @param [Number] gid + * @param [Function(BrowserFS.ApiError)] callback + */ + fs.lchown = function (path, uid, gid, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + path = normalizePath(path); + fs.root.chown(path, true, uid, gid, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `lchown`. + * @param [String] path + * @param [Number] uid + * @param [Number] gid + */ + fs.lchownSync = function (path, uid, gid) { + path = normalizePath(path); + return fs.root.chownSync(path, true, uid, gid); + }; + + fs.chmod = function (path, mode, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + path = normalizePath(path); + fs.root.chmod(path, false, mode, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.chmodSync = function (path, mode) { + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + path = normalizePath(path); + return fs.root.chmodSync(path, false, mode); + }; + + fs.lchmod = function (path, mode, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + path = normalizePath(path); + fs.root.chmod(path, true, mode, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.lchmodSync = function (path, mode) { + path = normalizePath(path); + mode = typeof mode === 'string' ? parseInt(mode, 8) : mode; + return fs.root.chmodSync(path, true, mode); + }; + + fs.utimes = function (path, atime, mtime, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var newCb = wrapCb(cb, 1); + try { + path = normalizePath(path); + if (typeof atime === 'number') { + atime = new Date(atime * 1000); + } + if (typeof mtime === 'number') { + mtime = new Date(mtime * 1000); + } + fs.root.utimes(path, atime, mtime, newCb); + } catch (e) { + newCb(e); + } + }; + + fs.utimesSync = function (path, atime, mtime) { + path = normalizePath(path); + if (typeof atime === 'number') { + atime = new Date(atime * 1000); + } + if (typeof mtime === 'number') { + mtime = new Date(mtime * 1000); + } + return fs.root.utimesSync(path, atime, mtime); + }; + + fs.realpath = function (path, arg2, cb) { + if (typeof cb === "undefined") { cb = nopCb; } + var cache = typeof arg2 === 'object' ? arg2 : {}; + cb = typeof arg2 === 'function' ? arg2 : nopCb; + var newCb = wrapCb(cb, 2); + try { + path = normalizePath(path); + fs.root.realpath(path, cache, newCb); + } catch (e) { + newCb(e); + } + }; + + /** + * Synchronous `realpath`. + * @param [String] path + * @param [Object?] cache An object literal of mapped paths that can be used to + * force a specific path resolution or avoid additional `fs.stat` calls for + * known real paths. + * @return [String] + */ + fs.realpathSync = function (path, cache) { + if (typeof cache === "undefined") { cache = {}; } + path = normalizePath(path); + return fs.root.realpathSync(path, cache); + }; + fs.root = null; + return fs; + })(); + exports.fs = fs; +}); +//# sourceMappingURL=node_fs.js.map +; +define('core/browserfs',["require", "exports", './buffer', './node_fs', './node_path', './node_process'], function(require, exports, buffer, node_fs, node_path, node_process) { + /** + * Installs BrowserFS onto the given object. + * We recommend that you run install with the 'window' object to make things + * global, as in Node. + * + * Properties installed: + * + * * Buffer + * * process + * * require (we monkey-patch it) + * + * This allows you to write code as if you were running inside Node. + * @param {object} obj - The object to install things onto (e.g. window) + */ + function install(obj) { + obj.Buffer = buffer.Buffer; + obj.process = node_process.process; + var oldRequire = obj.require != null ? obj.require : null; + + // Monkey-patch require for Node-style code. + obj.require = function (arg) { + var rv = exports.BFSRequire(arg); + if (rv == null) { + return oldRequire.apply(null, Array.prototype.slice.call(arguments, 0)); + } else { + return rv; + } + }; + } + exports.install = install; + + exports.FileSystem = {}; + function registerFileSystem(name, fs) { + exports.FileSystem[name] = fs; + } + exports.registerFileSystem = registerFileSystem; + + function BFSRequire(module) { + switch (module) { + case 'fs': + return node_fs.fs; + case 'path': + return node_path.path; + case 'buffer': + // The 'buffer' module has 'Buffer' as a property. + return buffer; + case 'process': + return node_process.process; + default: + return exports.FileSystem[module]; + } + } + exports.BFSRequire = BFSRequire; + + /** + * You must call this function with a properly-instantiated root file system + * before using any file system API method. + * @param {BrowserFS.FileSystem} rootFS - The root filesystem to use for the + * entire BrowserFS file system. + */ + function initialize(rootfs) { + return node_fs.fs._initialize(rootfs); + } + exports.initialize = initialize; +}); +//# sourceMappingURL=browserfs.js.map +; +define('generic/emscripten_fs',["require", "exports", '../core/browserfs', '../core/node_fs', '../core/buffer', '../core/buffer_core_arraybuffer'], function(require, exports, BrowserFS, node_fs, buffer, buffer_core_arraybuffer) { + var Buffer = buffer.Buffer; + var BufferCoreArrayBuffer = buffer_core_arraybuffer.BufferCoreArrayBuffer; + var fs = node_fs.fs; + + var BFSEmscriptenStreamOps = (function () { + function BFSEmscriptenStreamOps(fs) { + this.fs = fs; + } + BFSEmscriptenStreamOps.prototype.open = function (stream) { + var path = this.fs.realPath(stream.node); + try { + if (FS.isFile(stream.node.mode)) { + stream.nfd = fs.openSync(path, this.fs.flagsToPermissionString(stream.flags)); + } + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenStreamOps.prototype.close = function (stream) { + try { + if (FS.isFile(stream.node.mode) && stream.nfd) { + fs.closeSync(stream.nfd); + } + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenStreamOps.prototype.read = function (stream, buffer, offset, length, position) { + // Avoid copying overhead by reading directly into buffer. + var bcore = new BufferCoreArrayBuffer(buffer.buffer); + var nbuffer = new Buffer(bcore, buffer.byteOffset + offset, buffer.byteOffset + offset + length); + var res; + try { + res = fs.readSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + + // No copying needed, since we wrote directly into UintArray. + return res; + }; + + BFSEmscriptenStreamOps.prototype.write = function (stream, buffer, offset, length, position) { + // Avoid copying overhead; plug the buffer directly into a BufferCore. + var bcore = new BufferCoreArrayBuffer(buffer.buffer); + var nbuffer = new Buffer(bcore, buffer.byteOffset + offset, buffer.byteOffset + offset + length); + var res; + try { + res = fs.writeSync(stream.nfd, nbuffer, 0, length, position); + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return res; + }; + + BFSEmscriptenStreamOps.prototype.llseek = function (stream, offset, whence) { + var position = offset; + if (whence === 1) { + position += stream.position; + } else if (whence === 2) { + if (FS.isFile(stream.node.mode)) { + try { + var stat = fs.fstatSync(stream.nfd); + position += stat.size; + } catch (e) { + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + } + } + + if (position < 0) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + + stream.position = position; + return position; + }; + return BFSEmscriptenStreamOps; + })(); + + var BFSEmscriptenNodeOps = (function () { + function BFSEmscriptenNodeOps(fs) { + this.fs = fs; + } + BFSEmscriptenNodeOps.prototype.getattr = function (node) { + var path = this.fs.realPath(node); + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return { + dev: stat.dev, + ino: stat.ino, + mode: stat.mode, + nlink: stat.nlink, + uid: stat.uid, + gid: stat.gid, + rdev: stat.rdev, + size: stat.size, + atime: stat.atime, + mtime: stat.mtime, + ctime: stat.ctime, + blksize: stat.blksize, + blocks: stat.blocks + }; + }; + + BFSEmscriptenNodeOps.prototype.setattr = function (node, attr) { + var path = this.fs.realPath(node); + try { + if (attr.mode !== undefined) { + fs.chmodSync(path, attr.mode); + + // update the common node structure mode as well + node.mode = attr.mode; + } + if (attr.timestamp !== undefined) { + var date = new Date(attr.timestamp); + fs.utimesSync(path, date, date); + } + if (attr.size !== undefined) { + fs.truncateSync(path, attr.size); + } + } catch (e) { + if (!e.code) + throw e; + if (e.code === "ENOTSUP") { + // Ignore not supported errors. Emscripten does utimesSync when it + // writes files, but never really requires the value to be set. + return; + } + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.lookup = function (parent, name) { + var path = PATH.join2(this.fs.realPath(parent), name); + var mode = this.fs.getMode(path); + return this.fs.createNode(parent, name, mode); + }; + + BFSEmscriptenNodeOps.prototype.mknod = function (parent, name, mode, dev) { + var node = this.fs.createNode(parent, name, mode, dev); + + // create the backing node for this in the fs root as well + var path = this.fs.realPath(node); + try { + if (FS.isDir(node.mode)) { + fs.mkdirSync(path, node.mode); + } else { + fs.writeFileSync(path, '', { mode: node.mode }); + } + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return node; + }; + + BFSEmscriptenNodeOps.prototype.rename = function (oldNode, newDir, newName) { + var oldPath = this.fs.realPath(oldNode); + var newPath = PATH.join2(this.fs.realPath(newDir), newName); + try { + fs.renameSync(oldPath, newPath); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.unlink = function (parent, name) { + var path = PATH.join2(this.fs.realPath(parent), name); + try { + fs.unlinkSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.rmdir = function (parent, name) { + var path = PATH.join2(this.fs.realPath(parent), name); + try { + fs.rmdirSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.readdir = function (node) { + var path = this.fs.realPath(node); + try { + return fs.readdirSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.symlink = function (parent, newName, oldPath) { + var newPath = PATH.join2(this.fs.realPath(parent), newName); + try { + fs.symlinkSync(oldPath, newPath); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + + BFSEmscriptenNodeOps.prototype.readlink = function (node) { + var path = this.fs.realPath(node); + try { + return fs.readlinkSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + }; + return BFSEmscriptenNodeOps; + })(); + + var BFSEmscriptenFS = (function () { + function BFSEmscriptenFS() { + // This maps the integer permission modes from http://linux.die.net/man/3/open + // to node.js-specific file open permission strings at http://nodejs.org/api/fs.html#fs_fs_open_path_flags_mode_callback + this.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+' + }; + this.node_ops = new BFSEmscriptenNodeOps(this); + this.stream_ops = new BFSEmscriptenStreamOps(this); + if (typeof BrowserFS === 'undefined') { + throw new Error("BrowserFS is not loaded. Please load it before this library."); + } + } + BFSEmscriptenFS.prototype.mount = function (mount) { + return this.createNode(null, '/', this.getMode(mount.opts.root), 0); + }; + + BFSEmscriptenFS.prototype.createNode = function (parent, name, mode, dev) { + if (!FS.isDir(mode) && !FS.isFile(mode) && !FS.isLink(mode)) { + throw new FS.ErrnoError(ERRNO_CODES.EINVAL); + } + var node = FS.createNode(parent, name, mode); + node.node_ops = this.node_ops; + node.stream_ops = this.stream_ops; + return node; + }; + + BFSEmscriptenFS.prototype.getMode = function (path) { + var stat; + try { + stat = fs.lstatSync(path); + } catch (e) { + if (!e.code) + throw e; + throw new FS.ErrnoError(ERRNO_CODES[e.code]); + } + return stat.mode; + }; + + BFSEmscriptenFS.prototype.realPath = function (node) { + var parts = []; + while (node.parent !== node) { + parts.push(node.name); + node = node.parent; + } + parts.push(node.mount.opts.root); + parts.reverse(); + return PATH.join.apply(null, parts); + }; + + BFSEmscriptenFS.prototype.flagsToPermissionString = function (flags) { + if (flags in this.flagsToPermissionStringMap) { + return this.flagsToPermissionStringMap[flags]; + } else { + return flags; + } + }; + return BFSEmscriptenFS; + })(); + exports.BFSEmscriptenFS = BFSEmscriptenFS; + + // Make it available on the global BrowserFS object. + BrowserFS['EmscriptenFS'] = BFSEmscriptenFS; +}); +//# sourceMappingURL=emscripten_fs.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('core/file_system',["require", "exports", './api_error', './file_flag', './node_path', './buffer'], function(require, exports, api_error, file_flag, node_path, buffer) { + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + var path = node_path.path; + var Buffer = buffer.Buffer; + var ActionType = file_flag.ActionType; + + + + + + /** + * Basic filesystem class. Most filesystems should extend this class, as it + * provides default implementations for a handful of methods. + */ + var BaseFileSystem = (function () { + function BaseFileSystem() { + } + BaseFileSystem.prototype.supportsLinks = function () { + return false; + }; + BaseFileSystem.prototype.diskSpace = function (p, cb) { + cb(0, 0); + }; + + /** + * Opens the file at path p with the given flag. The file must exist. + * @param p The path to open. + * @param flag The flag to use when opening the file. + */ + BaseFileSystem.prototype.openFile = function (p, flag, cb) { + throw new ApiError(14 /* ENOTSUP */); + }; + + /** + * Create the file at path p with the given mode. Then, open it with the given + * flag. + */ + BaseFileSystem.prototype.createFile = function (p, flag, mode, cb) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.open = function (p, flag, mode, cb) { + var _this = this; + var must_be_file = function (e, stats) { + if (e) { + switch (flag.pathNotExistsAction()) { + case 3 /* CREATE_FILE */: + // Ensure parent exists. + return _this.stat(path.dirname(p), false, function (e, parentStats) { + if (e) { + cb(e); + } else if (!parentStats.isDirectory()) { + cb(new ApiError(7 /* ENOTDIR */, path.dirname(p) + " is not a directory.")); + } else { + _this.createFile(p, flag, mode, cb); + } + }); + case 1 /* THROW_EXCEPTION */: + return cb(new ApiError(1 /* ENOENT */, "" + p + " doesn't exist.")); + default: + return cb(new ApiError(9 /* EINVAL */, 'Invalid FileFlag object.')); + } + } else { + // File exists. + if (stats.isDirectory()) { + return cb(new ApiError(8 /* EISDIR */, p + " is a directory.")); + } + switch (flag.pathExistsAction()) { + case 1 /* THROW_EXCEPTION */: + return cb(new ApiError(6 /* EEXIST */, p + " already exists.")); + case 2 /* TRUNCATE_FILE */: + // NOTE: In a previous implementation, we deleted the file and + // re-created it. However, this created a race condition if another + // asynchronous request was trying to read the file, as the file + // would not exist for a small period of time. + return _this.openFile(p, flag, function (e, fd) { + if (e) { + cb(e); + } else { + fd.truncate(0, function () { + fd.sync(function () { + cb(null, fd); + }); + }); + } + }); + case 0 /* NOP */: + return _this.openFile(p, flag, cb); + default: + return cb(new ApiError(9 /* EINVAL */, 'Invalid FileFlag object.')); + } + } + }; + this.stat(p, false, must_be_file); + }; + BaseFileSystem.prototype.rename = function (oldPath, newPath, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.renameSync = function (oldPath, newPath) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.stat = function (p, isLstat, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.statSync = function (p, isLstat) { + throw new ApiError(14 /* ENOTSUP */); + }; + + /** + * Opens the file at path p with the given flag. The file must exist. + * @param p The path to open. + * @param flag The flag to use when opening the file. + * @return A File object corresponding to the opened file. + */ + BaseFileSystem.prototype.openFileSync = function (p, flag) { + throw new ApiError(14 /* ENOTSUP */); + }; + + /** + * Create the file at path p with the given mode. Then, open it with the given + * flag. + */ + BaseFileSystem.prototype.createFileSync = function (p, flag, mode) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.openSync = function (p, flag, mode) { + // Check if the path exists, and is a file. + var stats; + try { + stats = this.statSync(p, false); + } catch (e) { + switch (flag.pathNotExistsAction()) { + case 3 /* CREATE_FILE */: + // Ensure parent exists. + var parentStats = this.statSync(path.dirname(p), false); + if (!parentStats.isDirectory()) { + throw new ApiError(7 /* ENOTDIR */, path.dirname(p) + " is not a directory."); + } + return this.createFileSync(p, flag, mode); + case 1 /* THROW_EXCEPTION */: + throw new ApiError(1 /* ENOENT */, "" + p + " doesn't exist."); + default: + throw new ApiError(9 /* EINVAL */, 'Invalid FileFlag object.'); + } + } + + // File exists. + if (stats.isDirectory()) { + throw new ApiError(8 /* EISDIR */, p + " is a directory."); + } + switch (flag.pathExistsAction()) { + case 1 /* THROW_EXCEPTION */: + throw new ApiError(6 /* EEXIST */, p + " already exists."); + case 2 /* TRUNCATE_FILE */: + // Delete file. + this.unlinkSync(p); + + // Create file. Use the same mode as the old file. + // Node itself modifies the ctime when this occurs, so this action + // will preserve that behavior if the underlying file system + // supports those properties. + return this.createFileSync(p, flag, stats.mode); + case 0 /* NOP */: + return this.openFileSync(p, flag); + default: + throw new ApiError(9 /* EINVAL */, 'Invalid FileFlag object.'); + } + }; + BaseFileSystem.prototype.unlink = function (p, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.unlinkSync = function (p) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.rmdir = function (p, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.rmdirSync = function (p) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.mkdir = function (p, mode, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.mkdirSync = function (p, mode) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.readdir = function (p, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.readdirSync = function (p) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.exists = function (p, cb) { + this.stat(p, null, function (err) { + cb(err == null); + }); + }; + BaseFileSystem.prototype.existsSync = function (p) { + try { + this.statSync(p, true); + return true; + } catch (e) { + return false; + } + }; + BaseFileSystem.prototype.realpath = function (p, cache, cb) { + if (this.supportsLinks()) { + // The path could contain symlinks. Split up the path, + // resolve any symlinks, return the resolved string. + var splitPath = p.split(path.sep); + + for (var i = 0; i < splitPath.length; i++) { + var addPaths = splitPath.slice(0, i + 1); + splitPath[i] = path.join.apply(null, addPaths); + } + } else { + // No symlinks. We just need to verify that it exists. + this.exists(p, function (doesExist) { + if (doesExist) { + cb(null, p); + } else { + cb(new ApiError(1 /* ENOENT */, "File " + p + " not found.")); + } + }); + } + }; + BaseFileSystem.prototype.realpathSync = function (p, cache) { + if (this.supportsLinks()) { + // The path could contain symlinks. Split up the path, + // resolve any symlinks, return the resolved string. + var splitPath = p.split(path.sep); + + for (var i = 0; i < splitPath.length; i++) { + var addPaths = splitPath.slice(0, i + 1); + splitPath[i] = path.join.apply(null, addPaths); + } + } else { + // No symlinks. We just need to verify that it exists. + if (this.existsSync(p)) { + return p; + } else { + throw new ApiError(1 /* ENOENT */, "File " + p + " not found."); + } + } + }; + BaseFileSystem.prototype.truncate = function (p, len, cb) { + this.open(p, file_flag.FileFlag.getFileFlag('r+'), 0x1a4, (function (er, fd) { + if (er) { + return cb(er); + } + fd.truncate(len, (function (er) { + fd.close((function (er2) { + cb(er || er2); + })); + })); + })); + }; + BaseFileSystem.prototype.truncateSync = function (p, len) { + var fd = this.openSync(p, file_flag.FileFlag.getFileFlag('r+'), 0x1a4); + + try { + fd.truncateSync(len); + } catch (e) { + throw e; + } finally { + fd.closeSync(); + } + }; + BaseFileSystem.prototype.readFile = function (fname, encoding, flag, cb) { + // Wrap cb in file closing code. + var oldCb = cb; + + // Get file. + this.open(fname, flag, 0x1a4, function (err, fd) { + if (err) { + return cb(err); + } + cb = function (err, arg) { + fd.close(function (err2) { + if (err == null) { + err = err2; + } + return oldCb(err, arg); + }); + }; + fd.stat(function (err, stat) { + if (err != null) { + return cb(err); + } + + // Allocate buffer. + var buf = new Buffer(stat.size); + fd.read(buf, 0, stat.size, 0, function (err) { + if (err != null) { + return cb(err); + } else if (encoding === null) { + return cb(err, buf); + } + try { + cb(null, buf.toString(encoding)); + } catch (e) { + cb(e); + } + }); + }); + }); + }; + BaseFileSystem.prototype.readFileSync = function (fname, encoding, flag) { + // Get file. + var fd = this.openSync(fname, flag, 0x1a4); + try { + var stat = fd.statSync(); + + // Allocate buffer. + var buf = new Buffer(stat.size); + fd.readSync(buf, 0, stat.size, 0); + fd.closeSync(); + if (encoding === null) { + return buf; + } + return buf.toString(encoding); + } finally { + fd.closeSync(); + } + }; + BaseFileSystem.prototype.writeFile = function (fname, data, encoding, flag, mode, cb) { + // Wrap cb in file closing code. + var oldCb = cb; + + // Get file. + this.open(fname, flag, 0x1a4, function (err, fd) { + if (err != null) { + return cb(err); + } + cb = function (err) { + fd.close(function (err2) { + oldCb(err != null ? err : err2); + }); + }; + + try { + if (typeof data === 'string') { + data = new Buffer(data, encoding); + } + } catch (e) { + return cb(e); + } + + // Write into file. + fd.write(data, 0, data.length, 0, cb); + }); + }; + BaseFileSystem.prototype.writeFileSync = function (fname, data, encoding, flag, mode) { + // Get file. + var fd = this.openSync(fname, flag, mode); + try { + if (typeof data === 'string') { + data = new Buffer(data, encoding); + } + + // Write into file. + fd.writeSync(data, 0, data.length, 0); + } finally { + fd.closeSync(); + } + }; + BaseFileSystem.prototype.appendFile = function (fname, data, encoding, flag, mode, cb) { + // Wrap cb in file closing code. + var oldCb = cb; + this.open(fname, flag, mode, function (err, fd) { + if (err != null) { + return cb(err); + } + cb = function (err) { + fd.close(function (err2) { + oldCb(err != null ? err : err2); + }); + }; + if (typeof data === 'string') { + data = new Buffer(data, encoding); + } + fd.write(data, 0, data.length, null, cb); + }); + }; + BaseFileSystem.prototype.appendFileSync = function (fname, data, encoding, flag, mode) { + var fd = this.openSync(fname, flag, mode); + try { + if (typeof data === 'string') { + data = new Buffer(data, encoding); + } + fd.writeSync(data, 0, data.length, null); + } finally { + fd.closeSync(); + } + }; + BaseFileSystem.prototype.chmod = function (p, isLchmod, mode, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.chmodSync = function (p, isLchmod, mode) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.chown = function (p, isLchown, uid, gid, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.chownSync = function (p, isLchown, uid, gid) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.utimes = function (p, atime, mtime, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.utimesSync = function (p, atime, mtime) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.link = function (srcpath, dstpath, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.linkSync = function (srcpath, dstpath) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.symlink = function (srcpath, dstpath, type, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.symlinkSync = function (srcpath, dstpath, type) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFileSystem.prototype.readlink = function (p, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFileSystem.prototype.readlinkSync = function (p) { + throw new ApiError(14 /* ENOTSUP */); + }; + return BaseFileSystem; + })(); + exports.BaseFileSystem = BaseFileSystem; + + /** + * Implements the asynchronous API in terms of the synchronous API. + * @class SynchronousFileSystem + */ + var SynchronousFileSystem = (function (_super) { + __extends(SynchronousFileSystem, _super); + function SynchronousFileSystem() { + _super.apply(this, arguments); + } + SynchronousFileSystem.prototype.supportsSynch = function () { + return true; + }; + + SynchronousFileSystem.prototype.rename = function (oldPath, newPath, cb) { + try { + this.renameSync(oldPath, newPath); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.stat = function (p, isLstat, cb) { + try { + cb(null, this.statSync(p, isLstat)); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.open = function (p, flags, mode, cb) { + try { + cb(null, this.openSync(p, flags, mode)); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.unlink = function (p, cb) { + try { + this.unlinkSync(p); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.rmdir = function (p, cb) { + try { + this.rmdirSync(p); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.mkdir = function (p, mode, cb) { + try { + this.mkdirSync(p, mode); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.readdir = function (p, cb) { + try { + cb(null, this.readdirSync(p)); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.chmod = function (p, isLchmod, mode, cb) { + try { + this.chmodSync(p, isLchmod, mode); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.chown = function (p, isLchown, uid, gid, cb) { + try { + this.chownSync(p, isLchown, uid, gid); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.utimes = function (p, atime, mtime, cb) { + try { + this.utimesSync(p, atime, mtime); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.link = function (srcpath, dstpath, cb) { + try { + this.linkSync(srcpath, dstpath); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.symlink = function (srcpath, dstpath, type, cb) { + try { + this.symlinkSync(srcpath, dstpath, type); + cb(); + } catch (e) { + cb(e); + } + }; + + SynchronousFileSystem.prototype.readlink = function (p, cb) { + try { + cb(null, this.readlinkSync(p)); + } catch (e) { + cb(e); + } + }; + return SynchronousFileSystem; + })(BaseFileSystem); + exports.SynchronousFileSystem = SynchronousFileSystem; +}); +//# sourceMappingURL=file_system.js.map +; +define('core/node_fs_stats',["require", "exports"], function(require, exports) { + /** + * Indicates the type of the given file. Applied to 'mode'. + */ + (function (FileType) { + FileType[FileType["FILE"] = 0x8000] = "FILE"; + FileType[FileType["DIRECTORY"] = 0x4000] = "DIRECTORY"; + FileType[FileType["SYMLINK"] = 0xA000] = "SYMLINK"; + })(exports.FileType || (exports.FileType = {})); + var FileType = exports.FileType; + + /** + * Emulation of Node's `fs.Stats` object. + * + * Attribute descriptions are from `man 2 stat' + * @see http://nodejs.org/api/fs.html#fs_class_fs_stats + * @see http://man7.org/linux/man-pages/man2/stat.2.html + * @class + */ + var Stats = (function () { + /** + * Provides information about a particular entry in the file system. + * @param [Number] item_type type of the item (FILE, DIRECTORY, SYMLINK, or SOCKET) + * @param [Number] size Size of the item in bytes. For directories/symlinks, + * this is normally the size of the struct that represents the item. + * @param [Number] mode Unix-style file mode (e.g. 0o644) + * @param [Date?] atime time of last access + * @param [Date?] mtime time of last modification + * @param [Date?] ctime time of creation + */ + function Stats(item_type, size, mode, atime, mtime, ctime) { + if (typeof atime === "undefined") { atime = new Date(); } + if (typeof mtime === "undefined") { mtime = new Date(); } + if (typeof ctime === "undefined") { ctime = new Date(); } + this.size = size; + this.mode = mode; + this.atime = atime; + this.mtime = mtime; + this.ctime = ctime; + /** + * UNSUPPORTED ATTRIBUTES + * I assume no one is going to need these details, although we could fake + * appropriate values if need be. + */ + // ID of device containing file + this.dev = 0; + // inode number + this.ino = 0; + // device ID (if special file) + this.rdev = 0; + // number of hard links + this.nlink = 1; + // blocksize for file system I/O + this.blksize = 4096; + // @todo Maybe support these? atm, it's a one-user filesystem. + // user ID of owner + this.uid = 0; + // group ID of owner + this.gid = 0; + if (this.mode == null) { + switch (item_type) { + case 32768 /* FILE */: + this.mode = 0x1a4; + break; + case 16384 /* DIRECTORY */: + default: + this.mode = 0x1ff; + } + } + + // number of 512B blocks allocated + this.blocks = Math.ceil(size / 512); + + // Check if mode also includes top-most bits, which indicate the file's + // type. + if (this.mode < 0x1000) { + this.mode |= item_type; + } + } + /** + * **Nonstandard**: Clone the stats object. + * @return [BrowserFS.node.fs.Stats] + */ + Stats.prototype.clone = function () { + return new Stats(this.mode & 0xF000, this.size, this.mode & 0xFFF, this.atime, this.mtime, this.ctime); + }; + + /** + * @return [Boolean] True if this item is a file. + */ + Stats.prototype.isFile = function () { + return (this.mode & 0xF000) === 32768 /* FILE */; + }; + + /** + * @return [Boolean] True if this item is a directory. + */ + Stats.prototype.isDirectory = function () { + return (this.mode & 0xF000) === 16384 /* DIRECTORY */; + }; + + /** + * @return [Boolean] True if this item is a symbolic link (only valid through lstat) + */ + Stats.prototype.isSymbolicLink = function () { + return (this.mode & 0xF000) === 40960 /* SYMLINK */; + }; + + /** + * Change the mode of the file. We use this helper function to prevent messing + * up the type of the file, which is encoded in mode. + */ + Stats.prototype.chmod = function (mode) { + this.mode = (this.mode & 0xF000) | mode; + }; + + // We don't support the following types of files. + Stats.prototype.isSocket = function () { + return false; + }; + + Stats.prototype.isBlockDevice = function () { + return false; + }; + + Stats.prototype.isCharacterDevice = function () { + return false; + }; + + Stats.prototype.isFIFO = function () { + return false; + }; + return Stats; + })(); + exports.Stats = Stats; +}); +//# sourceMappingURL=node_fs_stats.js.map +; +define('generic/inode',["require", "exports", '../core/node_fs_stats', '../core/buffer'], function(require, exports, node_fs_stats, buffer) { + /** + * Generic inode definition that can easily be serialized. + */ + var Inode = (function () { + function Inode(id, size, mode, atime, mtime, ctime) { + this.id = id; + this.size = size; + this.mode = mode; + this.atime = atime; + this.mtime = mtime; + this.ctime = ctime; + } + /** + * Handy function that converts the Inode to a Node Stats object. + */ + Inode.prototype.toStats = function () { + return new node_fs_stats.Stats((this.mode & 0xF000) === 16384 /* DIRECTORY */ ? 16384 /* DIRECTORY */ : 32768 /* FILE */, this.size, this.mode, new Date(this.atime), new Date(this.mtime), new Date(this.ctime)); + }; + + /** + * Get the size of this Inode, in bytes. + */ + Inode.prototype.getSize = function () { + // ASSUMPTION: ID is ASCII (1 byte per char). + return 30 + this.id.length; + }; + + /** + * Writes the inode into the start of the buffer. + */ + Inode.prototype.toBuffer = function (buff) { + if (typeof buff === "undefined") { buff = new buffer.Buffer(this.getSize()); } + buff.writeUInt32LE(this.size, 0); + buff.writeUInt16LE(this.mode, 4); + buff.writeDoubleLE(this.atime, 6); + buff.writeDoubleLE(this.mtime, 14); + buff.writeDoubleLE(this.ctime, 22); + buff.write(this.id, 30, this.id.length, 'ascii'); + return buff; + }; + + /** + * Updates the Inode using information from the stats object. Used by file + * systems at sync time, e.g.: + * - Program opens file and gets a File object. + * - Program mutates file. File object is responsible for maintaining + * metadata changes locally -- typically in a Stats object. + * - Program closes file. File object's metadata changes are synced with the + * file system. + * @return True if any changes have occurred. + */ + Inode.prototype.update = function (stats) { + var hasChanged = false; + if (this.size !== stats.size) { + this.size = stats.size; + hasChanged = true; + } + + if (this.mode !== stats.mode) { + this.mode = stats.mode; + hasChanged = true; + } + + var atimeMs = stats.atime.getTime(); + if (this.atime !== atimeMs) { + this.atime = atimeMs; + hasChanged = true; + } + + var mtimeMs = stats.mtime.getTime(); + if (this.mtime !== mtimeMs) { + this.mtime = mtimeMs; + hasChanged = true; + } + + var ctimeMs = stats.ctime.getTime(); + if (this.ctime !== ctimeMs) { + this.ctime = ctimeMs; + hasChanged = true; + } + + return hasChanged; + }; + + /** + * Converts the buffer into an Inode. + */ + Inode.fromBuffer = function (buffer) { + if (buffer === undefined) { + throw new Error("NO"); + } + return new Inode(buffer.toString('ascii', 30), buffer.readUInt32LE(0), buffer.readUInt16LE(4), buffer.readDoubleLE(6), buffer.readDoubleLE(14), buffer.readDoubleLE(22)); + }; + + // XXX: Copied from Stats. Should reconcile these two into something more + // compact. + /** + * @return [Boolean] True if this item is a file. + */ + Inode.prototype.isFile = function () { + return (this.mode & 0xF000) === 32768 /* FILE */; + }; + + /** + * @return [Boolean] True if this item is a directory. + */ + Inode.prototype.isDirectory = function () { + return (this.mode & 0xF000) === 16384 /* DIRECTORY */; + }; + return Inode; + })(); + + + return Inode; +}); +//# sourceMappingURL=inode.js.map +; +define('core/file',["require", "exports", './api_error'], function(require, exports, api_error) { + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + + /** + * Base class that contains shared implementations of functions for the file + * object. + * @class + */ + var BaseFile = (function () { + function BaseFile() { + } + BaseFile.prototype.sync = function (cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFile.prototype.syncSync = function () { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFile.prototype.datasync = function (cb) { + this.sync(cb); + }; + BaseFile.prototype.datasyncSync = function () { + return this.syncSync(); + }; + BaseFile.prototype.chown = function (uid, gid, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFile.prototype.chownSync = function (uid, gid) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFile.prototype.chmod = function (mode, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFile.prototype.chmodSync = function (mode) { + throw new ApiError(14 /* ENOTSUP */); + }; + BaseFile.prototype.utimes = function (atime, mtime, cb) { + cb(new ApiError(14 /* ENOTSUP */)); + }; + BaseFile.prototype.utimesSync = function (atime, mtime) { + throw new ApiError(14 /* ENOTSUP */); + }; + return BaseFile; + })(); + exports.BaseFile = BaseFile; +}); +//# sourceMappingURL=file.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('generic/preload_file',["require", "exports", '../core/file', '../core/buffer', '../core/api_error', '../core/node_fs'], function(require, exports, file, buffer, api_error, node_fs) { + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + var fs = node_fs.fs; + var Buffer = buffer.Buffer; + + /** + * An implementation of the File interface that operates on a file that is + * completely in-memory. PreloadFiles are backed by a Buffer. + * + * This is also an abstract class, as it lacks an implementation of 'sync' and + * 'close'. Each filesystem that wishes to use this file representation must + * extend this class and implement those two methods. + * @todo 'close' lever that disables functionality once closed. + */ + var PreloadFile = (function (_super) { + __extends(PreloadFile, _super); + /** + * Creates a file with the given path and, optionally, the given contents. Note + * that, if contents is specified, it will be mutated by the file! + * @param [BrowserFS.FileSystem] _fs The file system that created the file. + * @param [String] _path + * @param [BrowserFS.FileMode] _mode The mode that the file was opened using. + * Dictates permissions and where the file pointer starts. + * @param [BrowserFS.node.fs.Stats] _stat The stats object for the given file. + * PreloadFile will mutate this object. Note that this object must contain + * the appropriate mode that the file was opened as. + * @param [BrowserFS.node.Buffer?] contents A buffer containing the entire + * contents of the file. PreloadFile will mutate this buffer. If not + * specified, we assume it is a new file. + */ + function PreloadFile(_fs, _path, _flag, _stat, contents) { + _super.call(this); + this._pos = 0; + this._fs = _fs; + this._path = _path; + this._flag = _flag; + this._stat = _stat; + if (contents != null) { + this._buffer = contents; + } else { + // Empty buffer. It'll expand once we write stuff to it. + this._buffer = new Buffer(0); + } + + // Note: This invariant is *not* maintained once the file starts getting + // modified. + if (this._stat.size !== this._buffer.length) { + throw new Error("Invalid buffer: Buffer is " + this._buffer.length + " long, yet Stats object specifies that file is " + this._stat.size + " long."); + } + } + /** + * Get the path to this file. + * @return [String] The path to the file. + */ + PreloadFile.prototype.getPath = function () { + return this._path; + }; + + /** + * Get the current file position. + * + * We emulate the following bug mentioned in the Node documentation: + * > On Linux, positional writes don't work when the file is opened in append + * mode. The kernel ignores the position argument and always appends the data + * to the end of the file. + * @return [Number] The current file position. + */ + PreloadFile.prototype.getPos = function () { + if (this._flag.isAppendable()) { + return this._stat.size; + } + return this._pos; + }; + + /** + * Advance the current file position by the indicated number of positions. + * @param [Number] delta + */ + PreloadFile.prototype.advancePos = function (delta) { + return this._pos += delta; + }; + + /** + * Set the file position. + * @param [Number] newPos + */ + PreloadFile.prototype.setPos = function (newPos) { + return this._pos = newPos; + }; + + /** + * **Core**: Asynchronous sync. Must be implemented by subclasses of this + * class. + * @param [Function(BrowserFS.ApiError)] cb + */ + PreloadFile.prototype.sync = function (cb) { + try { + this.syncSync(); + cb(); + } catch (e) { + cb(e); + } + }; + + /** + * **Core**: Synchronous sync. + */ + PreloadFile.prototype.syncSync = function () { + throw new ApiError(14 /* ENOTSUP */); + }; + + /** + * **Core**: Asynchronous close. Must be implemented by subclasses of this + * class. + * @param [Function(BrowserFS.ApiError)] cb + */ + PreloadFile.prototype.close = function (cb) { + try { + this.closeSync(); + cb(); + } catch (e) { + cb(e); + } + }; + + /** + * **Core**: Synchronous close. + */ + PreloadFile.prototype.closeSync = function () { + throw new ApiError(14 /* ENOTSUP */); + }; + + /** + * Asynchronous `stat`. + * @param [Function(BrowserFS.ApiError, BrowserFS.node.fs.Stats)] cb + */ + PreloadFile.prototype.stat = function (cb) { + try { + cb(null, this._stat.clone()); + } catch (e) { + cb(e); + } + }; + + /** + * Synchronous `stat`. + */ + PreloadFile.prototype.statSync = function () { + return this._stat.clone(); + }; + + /** + * Asynchronous truncate. + * @param [Number] len + * @param [Function(BrowserFS.ApiError)] cb + */ + PreloadFile.prototype.truncate = function (len, cb) { + try { + this.truncateSync(len); + if (this._flag.isSynchronous() && !fs.getRootFS().supportsSynch()) { + this.sync(cb); + } + cb(); + } catch (e) { + return cb(e); + } + }; + + /** + * Synchronous truncate. + * @param [Number] len + */ + PreloadFile.prototype.truncateSync = function (len) { + if (!this._flag.isWriteable()) { + throw new ApiError(0 /* EPERM */, 'File not opened with a writeable mode.'); + } + this._stat.mtime = new Date(); + if (len > this._buffer.length) { + var buf = new Buffer(len - this._buffer.length); + buf.fill(0); + + // Write will set @_stat.size for us. + this.writeSync(buf, 0, buf.length, this._buffer.length); + if (this._flag.isSynchronous() && fs.getRootFS().supportsSynch()) { + this.syncSync(); + } + return; + } + this._stat.size = len; + + // Truncate buffer to 'len'. + var newBuff = new Buffer(len); + this._buffer.copy(newBuff, 0, 0, len); + this._buffer = newBuff; + if (this._flag.isSynchronous() && fs.getRootFS().supportsSynch()) { + this.syncSync(); + } + }; + + /** + * Write buffer to the file. + * Note that it is unsafe to use fs.write multiple times on the same file + * without waiting for the callback. + * @param [BrowserFS.node.Buffer] buffer Buffer containing the data to write to + * the file. + * @param [Number] offset Offset in the buffer to start reading data from. + * @param [Number] length The amount of bytes to write to the file. + * @param [Number] position Offset from the beginning of the file where this + * data should be written. If position is null, the data will be written at + * the current position. + * @param [Function(BrowserFS.ApiError, Number, BrowserFS.node.Buffer)] + * cb The number specifies the number of bytes written into the file. + */ + PreloadFile.prototype.write = function (buffer, offset, length, position, cb) { + try { + cb(null, this.writeSync(buffer, offset, length, position), buffer); + } catch (e) { + cb(e); + } + }; + + /** + * Write buffer to the file. + * Note that it is unsafe to use fs.writeSync multiple times on the same file + * without waiting for the callback. + * @param [BrowserFS.node.Buffer] buffer Buffer containing the data to write to + * the file. + * @param [Number] offset Offset in the buffer to start reading data from. + * @param [Number] length The amount of bytes to write to the file. + * @param [Number] position Offset from the beginning of the file where this + * data should be written. If position is null, the data will be written at + * the current position. + * @return [Number] + */ + PreloadFile.prototype.writeSync = function (buffer, offset, length, position) { + if (position == null) { + position = this.getPos(); + } + if (!this._flag.isWriteable()) { + throw new ApiError(0 /* EPERM */, 'File not opened with a writeable mode.'); + } + var endFp = position + length; + if (endFp > this._stat.size) { + this._stat.size = endFp; + if (endFp > this._buffer.length) { + // Extend the buffer! + var newBuff = new Buffer(endFp); + this._buffer.copy(newBuff); + this._buffer = newBuff; + } + } + var len = buffer.copy(this._buffer, position, offset, offset + length); + this._stat.mtime = new Date(); + if (this._flag.isSynchronous()) { + this.syncSync(); + return len; + } + this.setPos(position + len); + return len; + }; + + /** + * Read data from the file. + * @param [BrowserFS.node.Buffer] buffer The buffer that the data will be + * written to. + * @param [Number] offset The offset within the buffer where writing will + * start. + * @param [Number] length An integer specifying the number of bytes to read. + * @param [Number] position An integer specifying where to begin reading from + * in the file. If position is null, data will be read from the current file + * position. + * @param [Function(BrowserFS.ApiError, Number, BrowserFS.node.Buffer)] cb The + * number is the number of bytes read + */ + PreloadFile.prototype.read = function (buffer, offset, length, position, cb) { + try { + cb(null, this.readSync(buffer, offset, length, position), buffer); + } catch (e) { + cb(e); + } + }; + + /** + * Read data from the file. + * @param [BrowserFS.node.Buffer] buffer The buffer that the data will be + * written to. + * @param [Number] offset The offset within the buffer where writing will + * start. + * @param [Number] length An integer specifying the number of bytes to read. + * @param [Number] position An integer specifying where to begin reading from + * in the file. If position is null, data will be read from the current file + * position. + * @return [Number] + */ + PreloadFile.prototype.readSync = function (buffer, offset, length, position) { + if (!this._flag.isReadable()) { + throw new ApiError(0 /* EPERM */, 'File not opened with a readable mode.'); + } + if (position == null) { + position = this.getPos(); + } + var endRead = position + length; + if (endRead > this._stat.size) { + length = this._stat.size - position; + } + var rv = this._buffer.copy(buffer, offset, position, position + length); + this._stat.atime = new Date(); + this._pos = position + length; + return rv; + }; + + /** + * Asynchronous `fchmod`. + * @param [Number|String] mode + * @param [Function(BrowserFS.ApiError)] cb + */ + PreloadFile.prototype.chmod = function (mode, cb) { + try { + this.chmodSync(mode); + cb(); + } catch (e) { + cb(e); + } + }; + + /** + * Asynchronous `fchmod`. + * @param [Number] mode + */ + PreloadFile.prototype.chmodSync = function (mode) { + if (!this._fs.supportsProps()) { + throw new ApiError(14 /* ENOTSUP */); + } + this._stat.chmod(mode); + this.syncSync(); + }; + return PreloadFile; + })(file.BaseFile); + exports.PreloadFile = PreloadFile; + + /** + * File class for the InMemory and XHR file systems. + * Doesn't sync to anything, so it works nicely for memory-only files. + */ + var NoSyncFile = (function (_super) { + __extends(NoSyncFile, _super); + function NoSyncFile(_fs, _path, _flag, _stat, contents) { + _super.call(this, _fs, _path, _flag, _stat, contents); + } + /** + * Asynchronous sync. Doesn't do anything, simply calls the cb. + * @param [Function(BrowserFS.ApiError)] cb + */ + NoSyncFile.prototype.sync = function (cb) { + cb(); + }; + + /** + * Synchronous sync. Doesn't do anything. + */ + NoSyncFile.prototype.syncSync = function () { + }; + + /** + * Asynchronous close. Doesn't do anything, simply calls the cb. + * @param [Function(BrowserFS.ApiError)] cb + */ + NoSyncFile.prototype.close = function (cb) { + cb(); + }; + + /** + * Synchronous close. Doesn't do anything. + */ + NoSyncFile.prototype.closeSync = function () { + }; + return NoSyncFile; + })(PreloadFile); + exports.NoSyncFile = NoSyncFile; +}); +//# sourceMappingURL=preload_file.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('generic/key_value_filesystem',["require", "exports", '../core/file_system', '../core/api_error', '../core/node_fs_stats', '../core/node_path', '../generic/inode', '../core/buffer', '../generic/preload_file'], function(require, exports, file_system, api_error, node_fs_stats, node_path, Inode, buffer, preload_file) { + var ROOT_NODE_ID = "/", path = node_path.path, ApiError = api_error.ApiError, Buffer = buffer.Buffer; + + /** + * Generates a random ID. + */ + function GenerateRandomID() { + // From http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { + var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + + /** + * Helper function. Checks if 'e' is defined. If so, it triggers the callback + * with 'e' and returns false. Otherwise, returns true. + */ + function noError(e, cb) { + if (e) { + cb(e); + return false; + } + return true; + } + + /** + * Helper function. Checks if 'e' is defined. If so, it aborts the transaction, + * triggers the callback with 'e', and returns false. Otherwise, returns true. + */ + function noErrorTx(e, tx, cb) { + if (e) { + tx.abort(function () { + cb(e); + }); + return false; + } + return true; + } + + + + + + + + + + /** + * A simple RW transaction for simple synchronous key-value stores. + */ + var SimpleSyncRWTransaction = (function () { + function SimpleSyncRWTransaction(store) { + this.store = store; + /** + * Stores data in the keys we modify prior to modifying them. + * Allows us to roll back commits. + */ + this.originalData = {}; + /** + * List of keys modified in this transaction, if any. + */ + this.modifiedKeys = []; + } + /** + * Stashes given key value pair into `originalData` if it doesn't already + * exist. Allows us to stash values the program is requesting anyway to + * prevent needless `get` requests if the program modifies the data later + * on during the transaction. + */ + SimpleSyncRWTransaction.prototype.stashOldValue = function (key, value) { + // Keep only the earliest value in the transaction. + if (!this.originalData.hasOwnProperty(key)) { + this.originalData[key] = value; + } + }; + + /** + * Marks the given key as modified, and stashes its value if it has not been + * stashed already. + */ + SimpleSyncRWTransaction.prototype.markModified = function (key) { + if (this.modifiedKeys.indexOf(key) === -1) { + this.modifiedKeys.push(key); + if (!this.originalData.hasOwnProperty(key)) { + this.originalData[key] = this.store.get(key); + } + } + }; + + SimpleSyncRWTransaction.prototype.get = function (key) { + var val = this.store.get(key); + this.stashOldValue(key, val); + return val; + }; + + SimpleSyncRWTransaction.prototype.put = function (key, data, overwrite) { + this.markModified(key); + return this.store.put(key, data, overwrite); + }; + + SimpleSyncRWTransaction.prototype.delete = function (key) { + this.markModified(key); + this.store.delete(key); + }; + + SimpleSyncRWTransaction.prototype.commit = function () { + }; + SimpleSyncRWTransaction.prototype.abort = function () { + // Rollback old values. + var i, key, value; + for (i = 0; i < this.modifiedKeys.length; i++) { + key = this.modifiedKeys[i]; + value = this.originalData[key]; + if (value === null) { + // Key didn't exist. + this.store.delete(key); + } else { + // Key existed. Store old value. + this.store.put(key, value, true); + } + } + }; + return SimpleSyncRWTransaction; + })(); + exports.SimpleSyncRWTransaction = SimpleSyncRWTransaction; + + var SyncKeyValueFile = (function (_super) { + __extends(SyncKeyValueFile, _super); + function SyncKeyValueFile(_fs, _path, _flag, _stat, contents) { + _super.call(this, _fs, _path, _flag, _stat, contents); + } + SyncKeyValueFile.prototype.syncSync = function () { + this._fs._syncSync(this._path, this._buffer, this._stat); + }; + + SyncKeyValueFile.prototype.closeSync = function () { + this.syncSync(); + }; + return SyncKeyValueFile; + })(preload_file.PreloadFile); + exports.SyncKeyValueFile = SyncKeyValueFile; + + /** + * A "Synchronous key-value file system". Stores data to/retrieves data from an + * underlying key-value store. + * + * We use a unique ID for each node in the file system. The root node has a + * fixed ID. + * @todo Introduce Node ID caching. + * @todo Check modes. + */ + var SyncKeyValueFileSystem = (function (_super) { + __extends(SyncKeyValueFileSystem, _super); + function SyncKeyValueFileSystem(options) { + _super.call(this); + this.store = options.store; + + // INVARIANT: Ensure that the root exists. + this.makeRootDirectory(); + } + SyncKeyValueFileSystem.isAvailable = function () { + return true; + }; + SyncKeyValueFileSystem.prototype.getName = function () { + return this.store.name(); + }; + SyncKeyValueFileSystem.prototype.isReadOnly = function () { + return false; + }; + SyncKeyValueFileSystem.prototype.supportsSymlinks = function () { + return false; + }; + SyncKeyValueFileSystem.prototype.supportsProps = function () { + return false; + }; + SyncKeyValueFileSystem.prototype.supportsSynch = function () { + return true; + }; + + /** + * Checks if the root directory exists. Creates it if it doesn't. + */ + SyncKeyValueFileSystem.prototype.makeRootDirectory = function () { + var tx = this.store.beginTransaction('readwrite'); + if (tx.get(ROOT_NODE_ID) === undefined) { + // Create new inode. + var currTime = (new Date()).getTime(), dirInode = new Inode(GenerateRandomID(), 4096, 511 | 16384 /* DIRECTORY */, currTime, currTime, currTime); + + // If the root doesn't exist, the first random ID shouldn't exist, + // either. + tx.put(dirInode.id, new Buffer("{}"), false); + tx.put(ROOT_NODE_ID, dirInode.toBuffer(), false); + tx.commit(); + } + }; + + /** + * Helper function for findINode. + * @param parent The parent directory of the file we are attempting to find. + * @param filename The filename of the inode we are attempting to find, minus + * the parent. + * @return string The ID of the file's inode in the file system. + */ + SyncKeyValueFileSystem.prototype._findINode = function (tx, parent, filename) { + var _this = this; + var read_directory = function (inode) { + // Get the root's directory listing. + var dirList = _this.getDirListing(tx, parent, inode); + + // Get the file's ID. + if (dirList[filename]) { + return dirList[filename]; + } else { + throw ApiError.ENOENT(path.resolve(parent, filename)); + } + }; + if (parent === '/') { + if (filename === '') { + // BASE CASE #1: Return the root's ID. + return ROOT_NODE_ID; + } else { + // BASE CASE #2: Find the item in the root ndoe. + return read_directory(this.getINode(tx, parent, ROOT_NODE_ID)); + } + } else { + return read_directory(this.getINode(tx, parent + path.sep + filename, this._findINode(tx, path.dirname(parent), path.basename(parent)))); + } + }; + + /** + * Finds the Inode of the given path. + * @param p The path to look up. + * @return The Inode of the path p. + * @todo memoize/cache + */ + SyncKeyValueFileSystem.prototype.findINode = function (tx, p) { + return this.getINode(tx, p, this._findINode(tx, path.dirname(p), path.basename(p))); + }; + + /** + * Given the ID of a node, retrieves the corresponding Inode. + * @param tx The transaction to use. + * @param p The corresponding path to the file (used for error messages). + * @param id The ID to look up. + */ + SyncKeyValueFileSystem.prototype.getINode = function (tx, p, id) { + var inode = tx.get(id); + if (inode === undefined) { + throw ApiError.ENOENT(p); + } + return Inode.fromBuffer(inode); + }; + + /** + * Given the Inode of a directory, retrieves the corresponding directory + * listing. + */ + SyncKeyValueFileSystem.prototype.getDirListing = function (tx, p, inode) { + if (!inode.isDirectory()) { + throw ApiError.ENOTDIR(p); + } + var data = tx.get(inode.id); + if (data === undefined) { + throw ApiError.ENOENT(p); + } + return JSON.parse(data.toString()); + }; + + /** + * Creates a new node under a random ID. Retries 5 times before giving up in + * the exceedingly unlikely chance that we try to reuse a random GUID. + * @return The GUID that the data was stored under. + */ + SyncKeyValueFileSystem.prototype.addNewNode = function (tx, data) { + var retries = 0, currId; + while (retries < 5) { + try { + currId = GenerateRandomID(); + tx.put(currId, data, false); + return currId; + } catch (e) { + // Ignore and reroll. + } + } + throw new ApiError(2 /* EIO */, 'Unable to commit data to key-value store.'); + }; + + /** + * Commits a new file (well, a FILE or a DIRECTORY) to the file system with + * the given mode. + * Note: This will commit the transaction. + * @param p The path to the new file. + * @param type The type of the new file. + * @param mode The mode to create the new file with. + * @param data The data to store at the file's data node. + * @return The Inode for the new file. + */ + SyncKeyValueFileSystem.prototype.commitNewFile = function (tx, p, type, mode, data) { + var parentDir = path.dirname(p), fname = path.basename(p), parentNode = this.findINode(tx, parentDir), dirListing = this.getDirListing(tx, parentDir, parentNode), currTime = (new Date()).getTime(); + + // Invariant: The root always exists. + // If we don't check this prior to taking steps below, we will create a + // file with name '' in root should p == '/'. + if (p === '/') { + throw ApiError.EEXIST(p); + } + + // Check if file already exists. + if (dirListing[fname]) { + throw ApiError.EEXIST(p); + } + + try { + // Commit data. + var dataId = this.addNewNode(tx, data), fileNode = new Inode(dataId, data.length, mode | type, currTime, currTime, currTime), fileNodeId = this.addNewNode(tx, fileNode.toBuffer()); + + // Update and commit parent directory listing. + dirListing[fname] = fileNodeId; + tx.put(parentNode.id, new Buffer(JSON.stringify(dirListing)), true); + } catch (e) { + tx.abort(); + throw e; + } + tx.commit(); + return fileNode; + }; + + /** + * Delete all contents stored in the file system. + */ + SyncKeyValueFileSystem.prototype.empty = function () { + this.store.clear(); + + // INVARIANT: Root always exists. + this.makeRootDirectory(); + }; + + SyncKeyValueFileSystem.prototype.renameSync = function (oldPath, newPath) { + var tx = this.store.beginTransaction('readwrite'), oldParent = path.dirname(oldPath), oldName = path.basename(oldPath), newParent = path.dirname(newPath), newName = path.basename(newPath), oldDirNode = this.findINode(tx, oldParent), oldDirList = this.getDirListing(tx, oldParent, oldDirNode); + if (!oldDirList[oldName]) { + throw ApiError.ENOENT(oldPath); + } + var nodeId = oldDirList[oldName]; + delete oldDirList[oldName]; + + // Invariant: Can't move a folder inside itself. + // This funny little hack ensures that the check passes only if oldPath + // is a subpath of newParent. We append '/' to avoid matching folders that + // are a substring of the bottom-most folder in the path. + if ((newParent + '/').indexOf(oldPath + '/') === 0) { + throw new ApiError(5 /* EBUSY */, oldParent); + } + + // Add newPath to parent's directory listing. + var newDirNode, newDirList; + if (newParent === oldParent) { + // Prevent us from re-grabbing the same directory listing, which still + // contains oldName. + newDirNode = oldDirNode; + newDirList = oldDirList; + } else { + newDirNode = this.findINode(tx, newParent); + newDirList = this.getDirListing(tx, newParent, newDirNode); + } + + if (newDirList[newName]) { + // If it's a file, delete it. + var newNameNode = this.getINode(tx, newPath, newDirList[newName]); + if (newNameNode.isFile()) { + try { + tx.delete(newNameNode.id); + tx.delete(newDirList[newName]); + } catch (e) { + tx.abort(); + throw e; + } + } else { + throw ApiError.EPERM(newPath); + } + } + newDirList[newName] = nodeId; + + try { + tx.put(oldDirNode.id, new Buffer(JSON.stringify(oldDirList)), true); + tx.put(newDirNode.id, new Buffer(JSON.stringify(newDirList)), true); + } catch (e) { + tx.abort(); + throw e; + } + + tx.commit(); + }; + + SyncKeyValueFileSystem.prototype.statSync = function (p, isLstat) { + // Get the inode to the item, convert it into a Stats object. + return this.findINode(this.store.beginTransaction('readonly'), p).toStats(); + }; + + SyncKeyValueFileSystem.prototype.createFileSync = function (p, flag, mode) { + var tx = this.store.beginTransaction('readwrite'), data = new Buffer(0), newFile = this.commitNewFile(tx, p, 32768 /* FILE */, mode, data); + + // Open the file. + return new SyncKeyValueFile(this, p, flag, newFile.toStats(), data); + }; + + SyncKeyValueFileSystem.prototype.openFileSync = function (p, flag) { + var tx = this.store.beginTransaction('readonly'), node = this.findINode(tx, p), data = tx.get(node.id); + if (data === undefined) { + throw ApiError.ENOENT(p); + } + return new SyncKeyValueFile(this, p, flag, node.toStats(), data); + }; + + /** + * Remove all traces of the given path from the file system. + * @param p The path to remove from the file system. + * @param isDir Does the path belong to a directory, or a file? + * @todo Update mtime. + */ + SyncKeyValueFileSystem.prototype.removeEntry = function (p, isDir) { + var tx = this.store.beginTransaction('readwrite'), parent = path.dirname(p), parentNode = this.findINode(tx, parent), parentListing = this.getDirListing(tx, parent, parentNode), fileName = path.basename(p); + + if (!parentListing[fileName]) { + throw ApiError.ENOENT(p); + } + + // Remove from directory listing of parent. + var fileNodeId = parentListing[fileName]; + delete parentListing[fileName]; + + // Get file inode. + var fileNode = this.getINode(tx, p, fileNodeId); + if (!isDir && fileNode.isDirectory()) { + throw ApiError.EISDIR(p); + } else if (isDir && !fileNode.isDirectory()) { + throw ApiError.ENOTDIR(p); + } + + try { + // Delete data. + tx.delete(fileNode.id); + + // Delete node. + tx.delete(fileNodeId); + + // Update directory listing. + tx.put(parentNode.id, new Buffer(JSON.stringify(parentListing)), true); + } catch (e) { + tx.abort(); + throw e; + } + + // Success. + tx.commit(); + }; + + SyncKeyValueFileSystem.prototype.unlinkSync = function (p) { + this.removeEntry(p, false); + }; + + SyncKeyValueFileSystem.prototype.rmdirSync = function (p) { + this.removeEntry(p, true); + }; + + SyncKeyValueFileSystem.prototype.mkdirSync = function (p, mode) { + var tx = this.store.beginTransaction('readwrite'), data = new Buffer('{}'); + this.commitNewFile(tx, p, 16384 /* DIRECTORY */, mode, data); + }; + + SyncKeyValueFileSystem.prototype.readdirSync = function (p) { + var tx = this.store.beginTransaction('readonly'); + return Object.keys(this.getDirListing(tx, p, this.findINode(tx, p))); + }; + + SyncKeyValueFileSystem.prototype._syncSync = function (p, data, stats) { + // @todo Ensure mtime updates properly, and use that to determine if a data + // update is required. + var tx = this.store.beginTransaction('readwrite'), fileInodeId = this._findINode(tx, path.dirname(p), path.basename(p)), fileInode = this.getINode(tx, p, fileInodeId), inodeChanged = fileInode.update(stats); + + try { + // Sync data. + tx.put(fileInode.id, data, true); + + // Sync metadata. + if (inodeChanged) { + tx.put(fileInodeId, fileInode.toBuffer(), true); + } + } catch (e) { + tx.abort(); + throw e; + } + tx.commit(); + }; + return SyncKeyValueFileSystem; + })(file_system.SynchronousFileSystem); + exports.SyncKeyValueFileSystem = SyncKeyValueFileSystem; + + + + + + + + var AsyncKeyValueFile = (function (_super) { + __extends(AsyncKeyValueFile, _super); + function AsyncKeyValueFile(_fs, _path, _flag, _stat, contents) { + _super.call(this, _fs, _path, _flag, _stat, contents); + } + AsyncKeyValueFile.prototype.sync = function (cb) { + this._fs._sync(this._path, this._buffer, this._stat, cb); + }; + + AsyncKeyValueFile.prototype.close = function (cb) { + this.sync(cb); + }; + return AsyncKeyValueFile; + })(preload_file.PreloadFile); + exports.AsyncKeyValueFile = AsyncKeyValueFile; + + /** + * An "Asynchronous key-value file system". Stores data to/retrieves data from + * an underlying asynchronous key-value store. + */ + var AsyncKeyValueFileSystem = (function (_super) { + __extends(AsyncKeyValueFileSystem, _super); + function AsyncKeyValueFileSystem() { + _super.apply(this, arguments); + } + /** + * Initializes the file system. Typically called by subclasses' async + * constructors. + */ + AsyncKeyValueFileSystem.prototype.init = function (store, cb) { + this.store = store; + + // INVARIANT: Ensure that the root exists. + this.makeRootDirectory(cb); + }; + + AsyncKeyValueFileSystem.isAvailable = function () { + return true; + }; + AsyncKeyValueFileSystem.prototype.getName = function () { + return this.store.name(); + }; + AsyncKeyValueFileSystem.prototype.isReadOnly = function () { + return false; + }; + AsyncKeyValueFileSystem.prototype.supportsSymlinks = function () { + return false; + }; + AsyncKeyValueFileSystem.prototype.supportsProps = function () { + return false; + }; + AsyncKeyValueFileSystem.prototype.supportsSynch = function () { + return false; + }; + + /** + * Checks if the root directory exists. Creates it if it doesn't. + */ + AsyncKeyValueFileSystem.prototype.makeRootDirectory = function (cb) { + var tx = this.store.beginTransaction('readwrite'); + tx.get(ROOT_NODE_ID, function (e, data) { + if (e || data === undefined) { + // Create new inode. + var currTime = (new Date()).getTime(), dirInode = new Inode(GenerateRandomID(), 4096, 511 | 16384 /* DIRECTORY */, currTime, currTime, currTime); + + // If the root doesn't exist, the first random ID shouldn't exist, + // either. + tx.put(dirInode.id, new Buffer("{}"), false, function (e) { + if (noErrorTx(e, tx, cb)) { + tx.put(ROOT_NODE_ID, dirInode.toBuffer(), false, function (e) { + if (e) { + tx.abort(function () { + cb(e); + }); + } else { + tx.commit(cb); + } + }); + } + }); + } else { + // We're good. + tx.commit(cb); + } + }); + }; + + /** + * Helper function for findINode. + * @param parent The parent directory of the file we are attempting to find. + * @param filename The filename of the inode we are attempting to find, minus + * the parent. + * @param cb Passed an error or the ID of the file's inode in the file system. + */ + AsyncKeyValueFileSystem.prototype._findINode = function (tx, parent, filename, cb) { + var _this = this; + var handle_directory_listings = function (e, inode, dirList) { + if (e) { + cb(e); + } else if (dirList[filename]) { + cb(null, dirList[filename]); + } else { + cb(ApiError.ENOENT(path.resolve(parent, filename))); + } + }; + + if (parent === '/') { + if (filename === '') { + // BASE CASE #1: Return the root's ID. + cb(null, ROOT_NODE_ID); + } else { + // BASE CASE #2: Find the item in the root node. + this.getINode(tx, parent, ROOT_NODE_ID, function (e, inode) { + if (noError(e, cb)) { + _this.getDirListing(tx, parent, inode, function (e, dirList) { + // handle_directory_listings will handle e for us. + handle_directory_listings(e, inode, dirList); + }); + } + }); + } + } else { + // Get the parent directory's INode, and find the file in its directory + // listing. + this.findINodeAndDirListing(tx, parent, handle_directory_listings); + } + }; + + /** + * Finds the Inode of the given path. + * @param p The path to look up. + * @param cb Passed an error or the Inode of the path p. + * @todo memoize/cache + */ + AsyncKeyValueFileSystem.prototype.findINode = function (tx, p, cb) { + var _this = this; + this._findINode(tx, path.dirname(p), path.basename(p), function (e, id) { + if (noError(e, cb)) { + _this.getINode(tx, p, id, cb); + } + }); + }; + + /** + * Given the ID of a node, retrieves the corresponding Inode. + * @param tx The transaction to use. + * @param p The corresponding path to the file (used for error messages). + * @param id The ID to look up. + * @param cb Passed an error or the inode under the given id. + */ + AsyncKeyValueFileSystem.prototype.getINode = function (tx, p, id, cb) { + tx.get(id, function (e, data) { + if (noError(e, cb)) { + if (data === undefined) { + cb(ApiError.ENOENT(p)); + } else { + cb(null, Inode.fromBuffer(data)); + } + } + }); + }; + + /** + * Given the Inode of a directory, retrieves the corresponding directory + * listing. + */ + AsyncKeyValueFileSystem.prototype.getDirListing = function (tx, p, inode, cb) { + if (!inode.isDirectory()) { + cb(ApiError.ENOTDIR(p)); + } else { + tx.get(inode.id, function (e, data) { + if (noError(e, cb)) { + try { + cb(null, JSON.parse(data.toString())); + } catch (e) { + // Occurs when data is undefined, or corresponds to something other + // than a directory listing. The latter should never occur unless + // the file system is corrupted. + cb(ApiError.ENOENT(p)); + } + } + }); + } + }; + + /** + * Given a path to a directory, retrieves the corresponding INode and + * directory listing. + */ + AsyncKeyValueFileSystem.prototype.findINodeAndDirListing = function (tx, p, cb) { + var _this = this; + this.findINode(tx, p, function (e, inode) { + if (noError(e, cb)) { + _this.getDirListing(tx, p, inode, function (e, listing) { + if (noError(e, cb)) { + cb(null, inode, listing); + } + }); + } + }); + }; + + /** + * Adds a new node under a random ID. Retries 5 times before giving up in + * the exceedingly unlikely chance that we try to reuse a random GUID. + * @param cb Passed an error or the GUID that the data was stored under. + */ + AsyncKeyValueFileSystem.prototype.addNewNode = function (tx, data, cb) { + var retries = 0, currId, reroll = function () { + if (++retries === 5) { + // Max retries hit. Return with an error. + cb(new ApiError(2 /* EIO */, 'Unable to commit data to key-value store.')); + } else { + // Try again. + currId = GenerateRandomID(); + tx.put(currId, data, false, function (e, committed) { + if (e || !committed) { + reroll(); + } else { + // Successfully stored under 'currId'. + cb(null, currId); + } + }); + } + }; + reroll(); + }; + + /** + * Commits a new file (well, a FILE or a DIRECTORY) to the file system with + * the given mode. + * Note: This will commit the transaction. + * @param p The path to the new file. + * @param type The type of the new file. + * @param mode The mode to create the new file with. + * @param data The data to store at the file's data node. + * @param cb Passed an error or the Inode for the new file. + */ + AsyncKeyValueFileSystem.prototype.commitNewFile = function (tx, p, type, mode, data, cb) { + var _this = this; + var parentDir = path.dirname(p), fname = path.basename(p), currTime = (new Date()).getTime(); + + // Invariant: The root always exists. + // If we don't check this prior to taking steps below, we will create a + // file with name '' in root should p == '/'. + if (p === '/') { + return cb(ApiError.EEXIST(p)); + } + + // Let's build a pyramid of code! + // Step 1: Get the parent directory's inode and directory listing + this.findINodeAndDirListing(tx, parentDir, function (e, parentNode, dirListing) { + if (noErrorTx(e, tx, cb)) { + if (dirListing[fname]) { + // File already exists. + tx.abort(function () { + cb(ApiError.EEXIST(p)); + }); + } else { + // Step 2: Commit data to store. + _this.addNewNode(tx, data, function (e, dataId) { + if (noErrorTx(e, tx, cb)) { + // Step 3: Commit the file's inode to the store. + var fileInode = new Inode(dataId, data.length, mode | type, currTime, currTime, currTime); + _this.addNewNode(tx, fileInode.toBuffer(), function (e, fileInodeId) { + if (noErrorTx(e, tx, cb)) { + // Step 4: Update parent directory's listing. + dirListing[fname] = fileInodeId; + tx.put(parentNode.id, new Buffer(JSON.stringify(dirListing)), true, function (e) { + if (noErrorTx(e, tx, cb)) { + // Step 5: Commit and return the new inode. + tx.commit(function (e) { + if (noErrorTx(e, tx, cb)) { + cb(null, fileInode); + } + }); + } + }); + } + }); + } + }); + } + } + }); + }; + + /** + * Delete all contents stored in the file system. + */ + AsyncKeyValueFileSystem.prototype.empty = function (cb) { + var _this = this; + this.store.clear(function (e) { + if (noError(e, cb)) { + // INVARIANT: Root always exists. + _this.makeRootDirectory(cb); + } + }); + }; + + AsyncKeyValueFileSystem.prototype.rename = function (oldPath, newPath, cb) { + var _this = this; + var tx = this.store.beginTransaction('readwrite'), oldParent = path.dirname(oldPath), oldName = path.basename(oldPath), newParent = path.dirname(newPath), newName = path.basename(newPath), inodes = {}, lists = {}, errorOccurred = false; + + // Invariant: Can't move a folder inside itself. + // This funny little hack ensures that the check passes only if oldPath + // is a subpath of newParent. We append '/' to avoid matching folders that + // are a substring of the bottom-most folder in the path. + if ((newParent + '/').indexOf(oldPath + '/') === 0) { + return cb(new ApiError(5 /* EBUSY */, oldParent)); + } + + /** + * Responsible for Phase 2 of the rename operation: Modifying and + * committing the directory listings. Called once we have successfully + * retrieved both the old and new parent's inodes and listings. + */ + var theOleSwitcharoo = function () { + // Sanity check: Ensure both paths are present, and no error has occurred. + if (errorOccurred || !lists.hasOwnProperty(oldParent) || !lists.hasOwnProperty(newParent)) { + return; + } + var oldParentList = lists[oldParent], oldParentINode = inodes[oldParent], newParentList = lists[newParent], newParentINode = inodes[newParent]; + + // Delete file from old parent. + if (!oldParentList[oldName]) { + cb(ApiError.ENOENT(oldPath)); + } else { + var fileId = oldParentList[oldName]; + delete oldParentList[oldName]; + + // Finishes off the renaming process by adding the file to the new + // parent. + var completeRename = function () { + newParentList[newName] = fileId; + + // Commit old parent's list. + tx.put(oldParentINode.id, new Buffer(JSON.stringify(oldParentList)), true, function (e) { + if (noErrorTx(e, tx, cb)) { + if (oldParent === newParent) { + // DONE! + tx.commit(cb); + } else { + // Commit new parent's list. + tx.put(newParentINode.id, new Buffer(JSON.stringify(newParentList)), true, function (e) { + if (noErrorTx(e, tx, cb)) { + tx.commit(cb); + } + }); + } + } + }); + }; + + if (newParentList[newName]) { + // 'newPath' already exists. Check if it's a file or a directory, and + // act accordingly. + _this.getINode(tx, newPath, newParentList[newName], function (e, inode) { + if (noErrorTx(e, tx, cb)) { + if (inode.isFile()) { + // Delete the file and continue. + tx.delete(inode.id, function (e) { + if (noErrorTx(e, tx, cb)) { + tx.delete(newParentList[newName], function (e) { + if (noErrorTx(e, tx, cb)) { + completeRename(); + } + }); + } + }); + } else { + // Can't overwrite a directory using rename. + tx.abort(function (e) { + cb(ApiError.EPERM(newPath)); + }); + } + } + }); + } else { + completeRename(); + } + } + }; + + /** + * Grabs a path's inode and directory listing, and shoves it into the + * inodes and lists hashes. + */ + var processInodeAndListings = function (p) { + _this.findINodeAndDirListing(tx, p, function (e, node, dirList) { + if (e) { + if (!errorOccurred) { + errorOccurred = true; + tx.abort(function () { + cb(e); + }); + } + // If error has occurred already, just stop here. + } else { + inodes[p] = node; + lists[p] = dirList; + theOleSwitcharoo(); + } + }); + }; + + processInodeAndListings(oldParent); + if (oldParent !== newParent) { + processInodeAndListings(newParent); + } + }; + + AsyncKeyValueFileSystem.prototype.stat = function (p, isLstat, cb) { + var tx = this.store.beginTransaction('readonly'); + this.findINode(tx, p, function (e, inode) { + if (noError(e, cb)) { + cb(null, inode.toStats()); + } + }); + }; + + AsyncKeyValueFileSystem.prototype.createFile = function (p, flag, mode, cb) { + var _this = this; + var tx = this.store.beginTransaction('readwrite'), data = new Buffer(0); + + this.commitNewFile(tx, p, 32768 /* FILE */, mode, data, function (e, newFile) { + if (noError(e, cb)) { + cb(null, new AsyncKeyValueFile(_this, p, flag, newFile.toStats(), data)); + } + }); + }; + + AsyncKeyValueFileSystem.prototype.openFile = function (p, flag, cb) { + var _this = this; + var tx = this.store.beginTransaction('readonly'); + + // Step 1: Grab the file's inode. + this.findINode(tx, p, function (e, inode) { + if (noError(e, cb)) { + // Step 2: Grab the file's data. + tx.get(inode.id, function (e, data) { + if (noError(e, cb)) { + if (data === undefined) { + cb(ApiError.ENOENT(p)); + } else { + cb(null, new AsyncKeyValueFile(_this, p, flag, inode.toStats(), data)); + } + } + }); + } + }); + }; + + /** + * Remove all traces of the given path from the file system. + * @param p The path to remove from the file system. + * @param isDir Does the path belong to a directory, or a file? + * @todo Update mtime. + */ + AsyncKeyValueFileSystem.prototype.removeEntry = function (p, isDir, cb) { + var _this = this; + var tx = this.store.beginTransaction('readwrite'), parent = path.dirname(p), fileName = path.basename(p); + + // Step 1: Get parent directory's node and directory listing. + this.findINodeAndDirListing(tx, parent, function (e, parentNode, parentListing) { + if (noErrorTx(e, tx, cb)) { + if (!parentListing[fileName]) { + tx.abort(function () { + cb(ApiError.ENOENT(p)); + }); + } else { + // Remove from directory listing of parent. + var fileNodeId = parentListing[fileName]; + delete parentListing[fileName]; + + // Step 2: Get file inode. + _this.getINode(tx, p, fileNodeId, function (e, fileNode) { + if (noErrorTx(e, tx, cb)) { + if (!isDir && fileNode.isDirectory()) { + tx.abort(function () { + cb(ApiError.EISDIR(p)); + }); + } else if (isDir && !fileNode.isDirectory()) { + tx.abort(function () { + cb(ApiError.ENOTDIR(p)); + }); + } else { + // Step 3: Delete data. + tx.delete(fileNode.id, function (e) { + if (noErrorTx(e, tx, cb)) { + // Step 4: Delete node. + tx.delete(fileNodeId, function (e) { + if (noErrorTx(e, tx, cb)) { + // Step 5: Update directory listing. + tx.put(parentNode.id, new Buffer(JSON.stringify(parentListing)), true, function (e) { + if (noErrorTx(e, tx, cb)) { + tx.commit(cb); + } + }); + } + }); + } + }); + } + } + }); + } + } + }); + }; + + AsyncKeyValueFileSystem.prototype.unlink = function (p, cb) { + this.removeEntry(p, false, cb); + }; + + AsyncKeyValueFileSystem.prototype.rmdir = function (p, cb) { + this.removeEntry(p, true, cb); + }; + + AsyncKeyValueFileSystem.prototype.mkdir = function (p, mode, cb) { + var tx = this.store.beginTransaction('readwrite'), data = new Buffer('{}'); + this.commitNewFile(tx, p, 16384 /* DIRECTORY */, mode, data, cb); + }; + + AsyncKeyValueFileSystem.prototype.readdir = function (p, cb) { + var _this = this; + var tx = this.store.beginTransaction('readonly'); + this.findINode(tx, p, function (e, inode) { + if (noError(e, cb)) { + _this.getDirListing(tx, p, inode, function (e, dirListing) { + if (noError(e, cb)) { + cb(null, Object.keys(dirListing)); + } + }); + } + }); + }; + + AsyncKeyValueFileSystem.prototype._sync = function (p, data, stats, cb) { + var _this = this; + // @todo Ensure mtime updates properly, and use that to determine if a data + // update is required. + var tx = this.store.beginTransaction('readwrite'); + + // Step 1: Get the file node's ID. + this._findINode(tx, path.dirname(p), path.basename(p), function (e, fileInodeId) { + if (noErrorTx(e, tx, cb)) { + // Step 2: Get the file inode. + _this.getINode(tx, p, fileInodeId, function (e, fileInode) { + if (noErrorTx(e, tx, cb)) { + var inodeChanged = fileInode.update(stats); + + // Step 3: Sync the data. + tx.put(fileInode.id, data, true, function (e) { + if (noErrorTx(e, tx, cb)) { + // Step 4: Sync the metadata (if it changed)! + if (inodeChanged) { + tx.put(fileInodeId, fileInode.toBuffer(), true, function (e) { + if (noErrorTx(e, tx, cb)) { + tx.commit(cb); + } + }); + } else { + // No need to sync metadata; return. + tx.commit(cb); + } + } + }); + } + }); + } + }); + }; + return AsyncKeyValueFileSystem; + })(file_system.BaseFileSystem); + exports.AsyncKeyValueFileSystem = AsyncKeyValueFileSystem; +}); +//# sourceMappingURL=key_value_filesystem.js.map +; +define('core/global',["require", "exports"], function(require, exports) { + /** + * Exports the global scope variable. + * In the main browser thread, this is "window". + * In a WebWorker, this is "self". + * In Node, this is "global". + */ + var toExport; + if (typeof (window) !== 'undefined') { + toExport = window; + } else if (typeof (self) !== 'undefined') { + toExport = self; + } else { + toExport = global; + } + + return toExport; +}); +//# sourceMappingURL=global.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('backend/IndexedDB',["require", "exports", '../core/buffer', '../core/browserfs', '../generic/key_value_filesystem', '../core/api_error', '../core/buffer_core_arraybuffer', '../core/global'], function(require, exports, buffer, browserfs, kvfs, api_error, buffer_core_arraybuffer, global) { + var Buffer = buffer.Buffer, ApiError = api_error.ApiError, ErrorCode = api_error.ErrorCode, indexedDB = global.indexedDB || global.mozIndexedDB || global.webkitIndexedDB || global.msIndexedDB; + + /** + * Converts a DOMException or a DOMError from an IndexedDB event into a + * standardized BrowserFS API error. + */ + function convertError(e, message) { + if (typeof message === "undefined") { message = e.toString(); } + switch (e.name) { + case "NotFoundError": + return new ApiError(1 /* ENOENT */, message); + case "QuotaExceededError": + return new ApiError(11 /* ENOSPC */, message); + default: + // The rest do not seem to map cleanly to standard error codes. + return new ApiError(2 /* EIO */, message); + } + } + + /** + * Produces a new onerror handler for IDB. Our errors are always fatal, so we + * handle them generically: Call the user-supplied callback with a translated + * version of the error, and let the error bubble up. + */ + function onErrorHandler(cb, code, message) { + if (typeof code === "undefined") { code = 2 /* EIO */; } + if (typeof message === "undefined") { message = null; } + return function (e) { + // Prevent the error from canceling the transaction. + e.preventDefault(); + cb(new ApiError(code, message)); + }; + } + + /** + * Converts a NodeBuffer into an ArrayBuffer. + */ + function buffer2arraybuffer(buffer) { + // XXX: Typing hack. + var backing_mem = buffer.getBufferCore(); + if (!(backing_mem instanceof buffer_core_arraybuffer.BufferCoreArrayBuffer)) { + // Copy into an ArrayBuffer-backed Buffer. + buffer = new Buffer(this._buffer.length); + this._buffer.copy(buffer); + backing_mem = buffer.getBufferCore(); + } + + // Reach into the BC, grab the DV. + var dv = backing_mem.getDataView(); + return dv.buffer; + } + + var IndexedDBROTransaction = (function () { + function IndexedDBROTransaction(tx, store) { + this.tx = tx; + this.store = store; + } + IndexedDBROTransaction.prototype.get = function (key, cb) { + try { + var r = this.store.get(key); + r.onerror = onErrorHandler(cb); + r.onsuccess = function (event) { + // IDB returns the value 'undefined' when you try to get keys that + // don't exist. The caller expects this behavior. + var result = event.target.result; + if (result === undefined) { + cb(null, result); + } else { + // IDB data is stored as an ArrayBuffer + cb(null, new Buffer(result)); + } + }; + } catch (e) { + cb(convertError(e)); + } + }; + return IndexedDBROTransaction; + })(); + exports.IndexedDBROTransaction = IndexedDBROTransaction; + + var IndexedDBRWTransaction = (function (_super) { + __extends(IndexedDBRWTransaction, _super); + function IndexedDBRWTransaction(tx, store) { + _super.call(this, tx, store); + } + IndexedDBRWTransaction.prototype.put = function (key, data, overwrite, cb) { + try { + var arraybuffer = buffer2arraybuffer(data), r; + if (overwrite) { + r = this.store.put(arraybuffer, key); + } else { + // 'add' will never overwrite an existing key. + r = this.store.add(arraybuffer, key); + } + + // XXX: NEED TO RETURN FALSE WHEN ADD HAS A KEY CONFLICT. NO ERROR. + r.onerror = onErrorHandler(cb); + r.onsuccess = function (event) { + cb(null, true); + }; + } catch (e) { + cb(convertError(e)); + } + }; + + IndexedDBRWTransaction.prototype.delete = function (key, cb) { + try { + var r = this.store.delete(key); + r.onerror = onErrorHandler(cb); + r.onsuccess = function (event) { + cb(); + }; + } catch (e) { + cb(convertError(e)); + } + }; + + IndexedDBRWTransaction.prototype.commit = function (cb) { + // Return to the event loop to commit the transaction. + setTimeout(cb, 0); + }; + + IndexedDBRWTransaction.prototype.abort = function (cb) { + var _e; + try { + this.tx.abort(); + } catch (e) { + _e = convertError(e); + } finally { + cb(_e); + } + }; + return IndexedDBRWTransaction; + })(IndexedDBROTransaction); + exports.IndexedDBRWTransaction = IndexedDBRWTransaction; + + var IndexedDBStore = (function () { + /** + * Constructs an IndexedDB file system. + * @param cb Called once the database is instantiated and ready for use. + * Passes an error if there was an issue instantiating the database. + * @param objectStoreName The name of this file system. You can have + * multiple IndexedDB file systems operating at once, but each must have + * a different name. + */ + function IndexedDBStore(cb, storeName) { + if (typeof storeName === "undefined") { storeName = 'browserfs'; } + var _this = this; + this.storeName = storeName; + var openReq = indexedDB.open(this.storeName, 1); + + openReq.onupgradeneeded = function (event) { + var db = event.target.result; + + // Huh. This should never happen; we're at version 1. Why does another + // database exist? + if (db.objectStoreNames.contains(_this.storeName)) { + db.deleteObjectStore(_this.storeName); + } + db.createObjectStore(_this.storeName); + }; + + openReq.onsuccess = function (event) { + _this.db = event.target.result; + cb(null, _this); + }; + + openReq.onerror = onErrorHandler(cb, 4 /* EACCES */); + } + IndexedDBStore.prototype.name = function () { + return "IndexedDB - " + this.storeName; + }; + + IndexedDBStore.prototype.clear = function (cb) { + try { + var tx = this.db.transaction(this.storeName, 'readwrite'), objectStore = tx.objectStore(this.storeName), r = objectStore.clear(); + r.onsuccess = function (event) { + // Use setTimeout to commit transaction. + setTimeout(cb, 0); + }; + r.onerror = onErrorHandler(cb); + } catch (e) { + cb(convertError(e)); + } + }; + + IndexedDBStore.prototype.beginTransaction = function (type) { + if (typeof type === "undefined") { type = 'readonly'; } + var tx = this.db.transaction(this.storeName, type), objectStore = tx.objectStore(this.storeName); + if (type === 'readwrite') { + return new IndexedDBRWTransaction(tx, objectStore); + } else if (type === 'readonly') { + return new IndexedDBROTransaction(tx, objectStore); + } else { + throw new ApiError(9 /* EINVAL */, 'Invalid transaction type.'); + } + }; + return IndexedDBStore; + })(); + exports.IndexedDBStore = IndexedDBStore; + + /** + * A file system that uses the IndexedDB key value file system. + */ + var IndexedDBFileSystem = (function (_super) { + __extends(IndexedDBFileSystem, _super); + function IndexedDBFileSystem(cb, storeName) { + var _this = this; + _super.call(this); + new IndexedDBStore(function (e, store) { + if (e) { + cb(e); + } else { + _this.init(store, function (e) { + cb(e, _this); + }); + } + }, storeName); + } + IndexedDBFileSystem.isAvailable = function () { + return typeof indexedDB !== 'undefined'; + }; + return IndexedDBFileSystem; + })(kvfs.AsyncKeyValueFileSystem); + exports.IndexedDBFileSystem = IndexedDBFileSystem; + + browserfs.registerFileSystem('IndexedDB', IndexedDBFileSystem); +}); +//# sourceMappingURL=IndexedDB.js.map +; +define('generic/file_index',["require", "exports", '../core/node_fs_stats', '../core/node_path'], function(require, exports, node_fs_stats, node_path) { + var Stats = node_fs_stats.Stats; + var path = node_path.path; + + /** + * A simple class for storing a filesystem index. Assumes that all paths passed + * to it are *absolute* paths. + * + * Can be used as a partial or a full index, although care must be taken if used + * for the former purpose, especially when directories are concerned. + */ + var FileIndex = (function () { + /** + * Constructs a new FileIndex. + */ + function FileIndex() { + // _index is a single-level key,value store that maps *directory* paths to + // DirInodes. File information is only contained in DirInodes themselves. + this._index = {}; + + // Create the root directory. + this.addPath('/', new DirInode()); + } + /** + * Split into a (directory path, item name) pair + */ + FileIndex.prototype._split_path = function (p) { + var dirpath = path.dirname(p); + var itemname = p.substr(dirpath.length + (dirpath === "/" ? 0 : 1)); + return [dirpath, itemname]; + }; + + /** + * Runs the given function over all files in the index. + */ + FileIndex.prototype.fileIterator = function (cb) { + for (var path in this._index) { + var dir = this._index[path]; + var files = dir.getListing(); + for (var i = 0; i < files.length; i++) { + var item = dir.getItem(files[i]); + if (item.isFile()) { + cb(item.getData()); + } + } + } + }; + + /** + * Adds the given absolute path to the index if it is not already in the index. + * Creates any needed parent directories. + * @param [String] path The path to add to the index. + * @param [BrowserFS.FileInode | BrowserFS.DirInode] inode The inode for the + * path to add. + * @return [Boolean] 'True' if it was added or already exists, 'false' if there + * was an issue adding it (e.g. item in path is a file, item exists but is + * different). + * @todo If adding fails and implicitly creates directories, we do not clean up + * the new empty directories. + */ + FileIndex.prototype.addPath = function (path, inode) { + if (inode == null) { + throw new Error('Inode must be specified'); + } + if (path[0] !== '/') { + throw new Error('Path must be absolute, got: ' + path); + } + + // Check if it already exists. + if (this._index.hasOwnProperty(path)) { + return this._index[path] === inode; + } + + var splitPath = this._split_path(path); + var dirpath = splitPath[0]; + var itemname = splitPath[1]; + + // Try to add to its parent directory first. + var parent = this._index[dirpath]; + if (parent === undefined && path !== '/') { + // Create parent. + parent = new DirInode(); + if (!this.addPath(dirpath, parent)) { + return false; + } + } + + // Add myself to my parent. + if (path !== '/') { + if (!parent.addItem(itemname, inode)) { + return false; + } + } + + // If I'm a directory, add myself to the index. + if (!inode.isFile()) { + this._index[path] = inode; + } + return true; + }; + + /** + * Removes the given path. Can be a file or a directory. + * @return [BrowserFS.FileInode | BrowserFS.DirInode | null] The removed item, + * or null if it did not exist. + */ + FileIndex.prototype.removePath = function (path) { + var splitPath = this._split_path(path); + var dirpath = splitPath[0]; + var itemname = splitPath[1]; + + // Try to remove it from its parent directory first. + var parent = this._index[dirpath]; + if (parent === undefined) { + return null; + } + + // Remove myself from my parent. + var inode = parent.remItem(itemname); + if (inode === null) { + return null; + } + + // If I'm a directory, remove myself from the index, and remove my children. + if (!inode.isFile()) { + var dirInode = inode; + var children = dirInode.getListing(); + for (var i = 0; i < children.length; i++) { + this.removePath(path + '/' + children[i]); + } + + // Remove the directory from the index, unless it's the root. + if (path !== '/') { + delete this._index[path]; + } + } + return inode; + }; + + /** + * Retrieves the directory listing of the given path. + * @return [String[]] An array of files in the given path, or 'null' if it does + * not exist. + */ + FileIndex.prototype.ls = function (path) { + var item = this._index[path]; + if (item === undefined) { + return null; + } + return item.getListing(); + }; + + /** + * Returns the inode of the given item. + * @param [String] path + * @return [BrowserFS.FileInode | BrowserFS.DirInode | null] Returns null if + * the item does not exist. + */ + FileIndex.prototype.getInode = function (path) { + var splitPath = this._split_path(path); + var dirpath = splitPath[0]; + var itemname = splitPath[1]; + + // Retrieve from its parent directory. + var parent = this._index[dirpath]; + if (parent === undefined) { + return null; + } + + // Root case + if (dirpath === path) { + return parent; + } + return parent.getItem(itemname); + }; + + /** + * Static method for constructing indices from a JSON listing. + * @param [Object] listing Directory listing generated by tools/XHRIndexer.coffee + * @return [BrowserFS.FileIndex] A new FileIndex object. + */ + FileIndex.from_listing = function (listing) { + var idx = new FileIndex(); + + // Add a root DirNode. + var rootInode = new DirInode(); + idx._index['/'] = rootInode; + var queue = [['', listing, rootInode]]; + while (queue.length > 0) { + var inode; + var next = queue.pop(); + var pwd = next[0]; + var tree = next[1]; + var parent = next[2]; + for (var node in tree) { + var children = tree[node]; + var name = "" + pwd + "/" + node; + if (children != null) { + idx._index[name] = inode = new DirInode(); + queue.push([name, children, inode]); + } else { + // This inode doesn't have correct size information, noted with -1. + inode = new FileInode(new Stats(32768 /* FILE */, -1, 0x16D)); + } + if (parent != null) { + parent._ls[node] = inode; + } + } + } + return idx; + }; + return FileIndex; + })(); + exports.FileIndex = FileIndex; + + + + /** + * Inode for a file. Stores an arbitrary (filesystem-specific) data payload. + */ + var FileInode = (function () { + function FileInode(data) { + this.data = data; + } + FileInode.prototype.isFile = function () { + return true; + }; + FileInode.prototype.isDir = function () { + return false; + }; + FileInode.prototype.getData = function () { + return this.data; + }; + FileInode.prototype.setData = function (data) { + this.data = data; + }; + return FileInode; + })(); + exports.FileInode = FileInode; + + /** + * Inode for a directory. Currently only contains the directory listing. + */ + var DirInode = (function () { + /** + * Constructs an inode for a directory. + */ + function DirInode() { + this._ls = {}; + } + DirInode.prototype.isFile = function () { + return false; + }; + DirInode.prototype.isDir = function () { + return true; + }; + + /** + * Return a Stats object for this inode. + * @todo Should probably remove this at some point. This isn't the + * responsibility of the FileIndex. + * @return [BrowserFS.node.fs.Stats] + */ + DirInode.prototype.getStats = function () { + return new Stats(16384 /* DIRECTORY */, 4096, 0x16D); + }; + + /** + * Returns the directory listing for this directory. Paths in the directory are + * relative to the directory's path. + * @return [String[]] The directory listing for this directory. + */ + DirInode.prototype.getListing = function () { + return Object.keys(this._ls); + }; + + /** + * Returns the inode for the indicated item, or null if it does not exist. + * @param [String] p Name of item in this directory. + * @return [BrowserFS.FileInode | BrowserFS.DirInode | null] + */ + DirInode.prototype.getItem = function (p) { + var _ref; + return (_ref = this._ls[p]) != null ? _ref : null; + }; + + /** + * Add the given item to the directory listing. Note that the given inode is + * not copied, and will be mutated by the DirInode if it is a DirInode. + * @param [String] p Item name to add to the directory listing. + * @param [BrowserFS.FileInode | BrowserFS.DirInode] inode The inode for the + * item to add to the directory inode. + * @return [Boolean] True if it was added, false if it already existed. + */ + DirInode.prototype.addItem = function (p, inode) { + if (p in this._ls) { + return false; + } + this._ls[p] = inode; + return true; + }; + + /** + * Removes the given item from the directory listing. + * @param [String] p Name of item to remove from the directory listing. + * @return [BrowserFS.FileInode | BrowserFS.DirInode | null] Returns the item + * removed, or null if the item did not exist. + */ + DirInode.prototype.remItem = function (p) { + var item = this._ls[p]; + if (item === undefined) { + return null; + } + delete this._ls[p]; + return item; + }; + return DirInode; + })(); + exports.DirInode = DirInode; +}); +//# sourceMappingURL=file_index.js.map +; +/** +* Grab bag of utility functions used across the code. +*/ +define('core/util',["require", "exports"], function(require, exports) { + /** + * Estimates the size of a JS object. + * @param {Object} object - the object to measure. + * @return {Number} estimated object size. + * @see http://stackoverflow.com/a/11900218/10601 + */ + function roughSizeOfObject(object) { + var bytes, key, objectList, prop, stack, value; + objectList = []; + stack = [object]; + bytes = 0; + while (stack.length !== 0) { + value = stack.pop(); + if (typeof value === 'boolean') { + bytes += 4; + } else if (typeof value === 'string') { + bytes += value.length * 2; + } else if (typeof value === 'number') { + bytes += 8; + } else if (typeof value === 'object' && objectList.indexOf(value) < 0) { + objectList.push(value); + bytes += 4; + for (key in value) { + prop = value[key]; + bytes += key.length * 2; + stack.push(prop); + } + } + } + return bytes; + } + exports.roughSizeOfObject = roughSizeOfObject; + + /** + * Checks for any IE version, including IE11 which removed MSIE from the + * userAgent string. + */ + exports.isIE = (/(msie) ([\w.]+)/.exec(navigator.userAgent.toLowerCase()) != null || navigator.userAgent.indexOf('Trident') !== -1); +}); +//# sourceMappingURL=util.js.map +; +/** +* Contains utility methods for performing a variety of tasks with +* XmlHttpRequest across browsers. +*/ +define('generic/xhr',["require", "exports", '../core/util', '../core/buffer', '../core/api_error'], function(require, exports, util, buffer, api_error) { + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + var Buffer = buffer.Buffer; + + + + // Converts 'responseBody' in IE into the equivalent 'responseText' that other + // browsers would generate. + function getIEByteArray(IEByteArray) { + var rawBytes = IEBinaryToArray_ByteStr(IEByteArray); + var lastChr = IEBinaryToArray_ByteStr_Last(IEByteArray); + var data_str = rawBytes.replace(/[\s\S]/g, function (match) { + var v = match.charCodeAt(0); + return String.fromCharCode(v & 0xff, v >> 8); + }) + lastChr; + var data_array = new Array(data_str.length); + for (var i = 0; i < data_str.length; i++) { + data_array[i] = data_str.charCodeAt(i); + } + return data_array; + } + + function downloadFileIE(async, p, type, cb) { + switch (type) { + case 'buffer': + + case 'json': + break; + default: + return cb(new ApiError(9 /* EINVAL */, "Invalid download type: " + type)); + } + + var req = new XMLHttpRequest(); + req.open('GET', p, async); + req.setRequestHeader("Accept-Charset", "x-user-defined"); + req.onreadystatechange = function (e) { + var data_array; + if (req.readyState === 4) { + if (req.status === 200) { + switch (type) { + case 'buffer': + data_array = getIEByteArray(req.responseBody); + return cb(null, new Buffer(data_array)); + case 'json': + return cb(null, JSON.parse(req.responseText)); + } + } else { + return cb(new ApiError(req.status, "XHR error.")); + } + } + }; + req.send(); + } + + function asyncDownloadFileIE(p, type, cb) { + downloadFileIE(true, p, type, cb); + } + + function syncDownloadFileIE(p, type) { + var rv; + downloadFileIE(false, p, type, function (err, data) { + if (err) + throw err; + rv = data; + }); + return rv; + } + + function asyncDownloadFileModern(p, type, cb) { + var req = new XMLHttpRequest(); + req.open('GET', p, true); + var jsonSupported = true; + switch (type) { + case 'buffer': + req.responseType = 'arraybuffer'; + break; + case 'json': + try { + req.responseType = 'json'; + jsonSupported = req.responseType === 'json'; + } catch (e) { + jsonSupported = false; + } + break; + default: + return cb(new ApiError(9 /* EINVAL */, "Invalid download type: " + type)); + } + req.onreadystatechange = function (e) { + if (req.readyState === 4) { + if (req.status === 200) { + switch (type) { + case 'buffer': + // XXX: WebKit-based browsers return *null* when XHRing an empty file. + return cb(null, new Buffer(req.response ? req.response : 0)); + case 'json': + if (jsonSupported) { + return cb(null, req.response); + } else { + return cb(null, JSON.parse(req.responseText)); + } + } + } else { + return cb(new ApiError(req.status, "XHR error.")); + } + } + }; + req.send(); + } + + function syncDownloadFileModern(p, type) { + var req = new XMLHttpRequest(); + req.open('GET', p, false); + + // On most platforms, we cannot set the responseType of synchronous downloads. + // @todo Test for this; IE10 allows this, as do older versions of Chrome/FF. + var data = null; + var err = null; + + // Classic hack to download binary data as a string. + req.overrideMimeType('text/plain; charset=x-user-defined'); + req.onreadystatechange = function (e) { + if (req.readyState === 4) { + if (req.status === 200) { + switch (type) { + case 'buffer': + // Convert the text into a buffer. + var text = req.responseText; + data = new Buffer(text.length); + + for (var i = 0; i < text.length; i++) { + // This will automatically throw away the upper bit of each + // character for us. + data.writeUInt8(text.charCodeAt(i), i); + } + return; + case 'json': + data = JSON.parse(req.responseText); + return; + } + } else { + err = new ApiError(req.status, "XHR error."); + return; + } + } + }; + req.send(); + if (err) { + throw err; + } + return data; + } + + + + function syncDownloadFileIE10(p, type) { + var req = new XMLHttpRequest(); + req.open('GET', p, false); + switch (type) { + case 'buffer': + req.responseType = 'arraybuffer'; + break; + case 'json': + break; + default: + throw new ApiError(9 /* EINVAL */, "Invalid download type: " + type); + } + var data; + var err; + req.onreadystatechange = function (e) { + if (req.readyState === 4) { + if (req.status === 200) { + switch (type) { + case 'buffer': + data = new Buffer(req.response); + break; + case 'json': + data = JSON.parse(req.response); + break; + } + } else { + err = new ApiError(req.status, "XHR error."); + } + } + }; + req.send(); + if (err) { + throw err; + } + return data; + } + + function getFileSize(async, p, cb) { + var req = new XMLHttpRequest(); + req.open('HEAD', p, async); + req.onreadystatechange = function (e) { + if (req.readyState === 4) { + if (req.status == 200) { + try { + return cb(null, parseInt(req.getResponseHeader('Content-Length'), 10)); + } catch (e) { + // In the event that the header isn't present or there is an error... + return cb(new ApiError(2 /* EIO */, "XHR HEAD error: Could not read content-length.")); + } + } else { + return cb(new ApiError(req.status, "XHR HEAD error.")); + } + } + }; + req.send(); + } + + /** + * Asynchronously download a file as a buffer or a JSON object. + * Note that the third function signature with a non-specialized type is + * invalid, but TypeScript requires it when you specialize string arguments to + * constants. + */ + exports.asyncDownloadFile = (util.isIE && typeof Blob === 'undefined') ? asyncDownloadFileIE : asyncDownloadFileModern; + + /** + * Synchronously download a file as a buffer or a JSON object. + * Note that the third function signature with a non-specialized type is + * invalid, but TypeScript requires it when you specialize string arguments to + * constants. + */ + exports.syncDownloadFile = (util.isIE && typeof Blob === 'undefined') ? syncDownloadFileIE : (util.isIE && typeof Blob !== 'undefined') ? syncDownloadFileIE10 : syncDownloadFileModern; + + /** + * Synchronously retrieves the size of the given file in bytes. + */ + function getFileSizeSync(p) { + var rv; + getFileSize(false, p, function (err, size) { + if (err) { + throw err; + } + rv = size; + }); + return rv; + } + exports.getFileSizeSync = getFileSizeSync; + + /** + * Asynchronously retrieves the size of the given file in bytes. + */ + function getFileSizeAsync(p, cb) { + getFileSize(true, p, cb); + } + exports.getFileSizeAsync = getFileSizeAsync; +}); +//# sourceMappingURL=xhr.js.map +; +var __extends = this.__extends || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + __.prototype = b.prototype; + d.prototype = new __(); +}; +define('backend/XmlHttpRequest',["require", "exports", '../core/file_system', '../generic/file_index', '../core/buffer', '../core/api_error', '../core/file_flag', '../generic/preload_file', '../core/browserfs', '../generic/xhr'], function(require, exports, file_system, file_index, buffer, api_error, file_flag, preload_file, browserfs, xhr) { + var Buffer = buffer.Buffer; + var ApiError = api_error.ApiError; + var ErrorCode = api_error.ErrorCode; + var FileFlag = file_flag.FileFlag; + var ActionType = file_flag.ActionType; + + /** + * A simple filesystem backed by XmlHttpRequests. + */ + var XmlHttpRequest = (function (_super) { + __extends(XmlHttpRequest, _super); + /** + * Constructs the file system. + * @param [String] listing_url The path to the JSON file index generated by + * tools/XHRIndexer.coffee. This can be relative to the current webpage URL + * or absolutely specified. + * @param [String] prefix_url The url prefix to use for all web-server requests. + */ + function XmlHttpRequest(listing_url, prefix_url) { + if (typeof prefix_url === "undefined") { prefix_url = ''; } + _super.call(this); + this.prefix_url = prefix_url; + if (listing_url == null) { + listing_url = 'index.json'; + } + + // prefix_url must end in a directory separator. + if (prefix_url.length > 0 && prefix_url.charAt(prefix_url.length - 1) !== '/') { + prefix_url = prefix_url + '/'; + } + var listing = this._requestFileSync(listing_url, 'json'); + if (listing == null) { + throw new Error("Unable to find listing at URL: " + listing_url); + } + this._index = file_index.FileIndex.from_listing(listing); + } + XmlHttpRequest.prototype.empty = function () { + this._index.fileIterator(function (file) { + file.file_data = null; + }); + }; + + XmlHttpRequest.prototype.getXhrPath = function (filePath) { + if (filePath.charAt(0) === '/') { + filePath = filePath.slice(1); + } + return this.prefix_url + filePath; + }; + + /** + * Only requests the HEAD content, for the file size. + */ + XmlHttpRequest.prototype._requestFileSizeAsync = function (path, cb) { + xhr.getFileSizeAsync(this.getXhrPath(path), cb); + }; + XmlHttpRequest.prototype._requestFileSizeSync = function (path) { + return xhr.getFileSizeSync(this.getXhrPath(path)); + }; + + XmlHttpRequest.prototype._requestFileAsync = function (p, type, cb) { + xhr.asyncDownloadFile(this.getXhrPath(p), type, cb); + }; + + XmlHttpRequest.prototype._requestFileSync = function (p, type) { + return xhr.syncDownloadFile(this.getXhrPath(p), type); + }; + + XmlHttpRequest.prototype.getName = function () { + return 'XmlHttpRequest'; + }; + + XmlHttpRequest.isAvailable = function () { + // @todo Older browsers use a different name for XHR, iirc. + return typeof XMLHttpRequest !== "undefined" && XMLHttpRequest !== null; + }; + + XmlHttpRequest.prototype.diskSpace = function (path, cb) { + // Read-only file system. We could calculate the total space, but that's not + // important right now. + cb(0, 0); + }; + + XmlHttpRequest.prototype.isReadOnly = function () { + return true; + }; + + XmlHttpRequest.prototype.supportsLinks = function () { + return false; + }; + + XmlHttpRequest.prototype.supportsProps = function () { + return false; + }; + + XmlHttpRequest.prototype.supportsSynch = function () { + return true; + }; + + /** + * Special XHR function: Preload the given file into the index. + * @param [String] path + * @param [BrowserFS.Buffer] buffer + */ + XmlHttpRequest.prototype.preloadFile = function (path, buffer) { + var inode = this._index.getInode(path); + if (inode === null) { + throw ApiError.ENOENT(path); + } + var stats = inode.getData(); + stats.size = buffer.length; + stats.file_data = buffer; + }; + + XmlHttpRequest.prototype.stat = function (path, isLstat, cb) { + var inode = this._index.getInode(path); + if (inode === null) { + return cb(ApiError.ENOENT(path)); + } + var stats; + if (inode.isFile()) { + stats = inode.getData(); + + // At this point, a non-opened file will still have default stats from the listing. + if (stats.size < 0) { + this._requestFileSizeAsync(path, function (e, size) { + if (e) { + return cb(e); + } + stats.size = size; + cb(null, stats.clone()); + }); + } else { + cb(null, stats.clone()); + } + } else { + stats = inode.getStats(); + cb(null, stats); + } + }; + + XmlHttpRequest.prototype.statSync = function (path, isLstat) { + var inode = this._index.getInode(path); + if (inode === null) { + throw ApiError.ENOENT(path); + } + var stats; + if (inode.isFile()) { + stats = inode.getData(); + + // At this point, a non-opened file will still have default stats from the listing. + if (stats.size < 0) { + stats.size = this._requestFileSizeSync(path); + } + } else { + stats = inode.getStats(); + } + return stats; + }; + + XmlHttpRequest.prototype.open = function (path, flags, mode, cb) { + // INVARIANT: You can't write to files on this file system. + if (flags.isWriteable()) { + return cb(new ApiError(0 /* EPERM */, path)); + } + var _this = this; + + // Check if the path exists, and is a file. + var inode = this._index.getInode(path); + if (inode === null) { + return cb(ApiError.ENOENT(path)); + } + if (inode.isDir()) { + return cb(ApiError.EISDIR(path)); + } + var stats = inode.getData(); + switch (flags.pathExistsAction()) { + case 1 /* THROW_EXCEPTION */: + case 2 /* TRUNCATE_FILE */: + return cb(ApiError.EEXIST(path)); + case 0 /* NOP */: + // Use existing file contents. + // XXX: Uh, this maintains the previously-used flag. + if (stats.file_data != null) { + return cb(null, new preload_file.NoSyncFile(_this, path, flags, stats.clone(), stats.file_data)); + } + + // @todo be lazier about actually requesting the file + this._requestFileAsync(path, 'buffer', function (err, buffer) { + if (err) { + return cb(err); + } + + // we don't initially have file sizes + stats.size = buffer.length; + stats.file_data = buffer; + return cb(null, new preload_file.NoSyncFile(_this, path, flags, stats.clone(), buffer)); + }); + break; + default: + return cb(new ApiError(9 /* EINVAL */, 'Invalid FileMode object.')); + } + }; + + XmlHttpRequest.prototype.openSync = function (path, flags, mode) { + // INVARIANT: You can't write to files on this file system. + if (flags.isWriteable()) { + throw new ApiError(0 /* EPERM */, path); + } + + // Check if the path exists, and is a file. + var inode = this._index.getInode(path); + if (inode === null) { + throw ApiError.ENOENT(path); + } + if (inode.isDir()) { + throw ApiError.EISDIR(path); + } + var stats = inode.getData(); + switch (flags.pathExistsAction()) { + case 1 /* THROW_EXCEPTION */: + case 2 /* TRUNCATE_FILE */: + throw ApiError.EEXIST(path); + case 0 /* NOP */: + // Use existing file contents. + // XXX: Uh, this maintains the previously-used flag. + if (stats.file_data != null) { + return new preload_file.NoSyncFile(this, path, flags, stats.clone(), stats.file_data); + } + + // @todo be lazier about actually requesting the file + var buffer = this._requestFileSync(path, 'buffer'); + + // we don't initially have file sizes + stats.size = buffer.length; + stats.file_data = buffer; + return new preload_file.NoSyncFile(this, path, flags, stats.clone(), buffer); + default: + throw new ApiError(9 /* EINVAL */, 'Invalid FileMode object.'); + } + }; + + XmlHttpRequest.prototype.readdir = function (path, cb) { + try { + cb(null, this.readdirSync(path)); + } catch (e) { + cb(e); + } + }; + + XmlHttpRequest.prototype.readdirSync = function (path) { + // Check if it exists. + var inode = this._index.getInode(path); + if (inode === null) { + throw ApiError.ENOENT(path); + } else if (inode.isFile()) { + throw ApiError.ENOTDIR(path); + } + return inode.getListing(); + }; + + /** + * We have the entire file as a buffer; optimize readFile. + */ + XmlHttpRequest.prototype.readFile = function (fname, encoding, flag, cb) { + // Wrap cb in file closing code. + var oldCb = cb; + + // Get file. + this.open(fname, flag, 0x1a4, function (err, fd) { + if (err) { + return cb(err); + } + cb = function (err, arg) { + fd.close(function (err2) { + if (err == null) { + err = err2; + } + return oldCb(err, arg); + }); + }; + var fdCast = fd; + var fdBuff = fdCast._buffer; + if (encoding === null) { + if (fdBuff.length > 0) { + return cb(err, fdBuff.sliceCopy()); + } else { + return cb(err, new buffer.Buffer(0)); + } + } + try { + cb(null, fdBuff.toString(encoding)); + } catch (e) { + cb(e); + } + }); + }; + + /** + * Specially-optimized readfile. + */ + XmlHttpRequest.prototype.readFileSync = function (fname, encoding, flag) { + // Get file. + var fd = this.openSync(fname, flag, 0x1a4); + try { + var fdCast = fd; + var fdBuff = fdCast._buffer; + if (encoding === null) { + if (fdBuff.length > 0) { + return fdBuff.sliceCopy(); + } else { + return new buffer.Buffer(0); + } + } + return fdBuff.toString(encoding); + } finally { + fd.closeSync(); + } + }; + return XmlHttpRequest; + })(file_system.BaseFileSystem); + exports.XmlHttpRequest = XmlHttpRequest; + + browserfs.registerFileSystem('XmlHttpRequest', XmlHttpRequest); +}); +//# sourceMappingURL=XmlHttpRequest.js.map +; +/*global setImmediate: false, setTimeout: false, console: false */ +(function () { + + var async = {}; + + // global on the server, window in the browser + var root, previous_async; + + root = this; + if (root != null) { + previous_async = root.async; + } + + async.noConflict = function () { + root.async = previous_async; + return async; + }; + + function only_once(fn) { + var called = false; + return function() { + if (called) throw new Error("Callback was already called."); + called = true; + fn.apply(root, arguments); + } + } + + //// cross-browser compatiblity functions //// + + var _each = function (arr, iterator) { + if (arr.forEach) { + return arr.forEach(iterator); + } + for (var i = 0; i < arr.length; i += 1) { + iterator(arr[i], i, arr); + } + }; + + var _map = function (arr, iterator) { + if (arr.map) { + return arr.map(iterator); + } + var results = []; + _each(arr, function (x, i, a) { + results.push(iterator(x, i, a)); + }); + return results; + }; + + var _reduce = function (arr, iterator, memo) { + if (arr.reduce) { + return arr.reduce(iterator, memo); + } + _each(arr, function (x, i, a) { + memo = iterator(memo, x, i, a); + }); + return memo; + }; + + var _keys = function (obj) { + if (Object.keys) { + return Object.keys(obj); + } + var keys = []; + for (var k in obj) { + if (obj.hasOwnProperty(k)) { + keys.push(k); + } + } + return keys; + }; + + //// exported async module functions //// + + //// nextTick implementation with browser-compatible fallback //// + if (typeof process === 'undefined' || !(process.nextTick)) { + if (typeof setImmediate === 'function') { + async.nextTick = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + async.setImmediate = async.nextTick; + } + else { + async.nextTick = function (fn) { + setTimeout(fn, 0); + }; + async.setImmediate = async.nextTick; + } + } + else { + async.nextTick = process.nextTick; + if (typeof setImmediate !== 'undefined') { + async.setImmediate = function (fn) { + // not a direct alias for IE10 compatibility + setImmediate(fn); + }; + } + else { + async.setImmediate = async.nextTick; + } + } + + async.each = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + _each(arr, function (x) { + iterator(x, only_once(function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + } + })); + }); + }; + async.forEach = async.each; + + async.eachSeries = function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length) { + return callback(); + } + var completed = 0; + var iterate = function () { + iterator(arr[completed], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + if (completed >= arr.length) { + callback(null); + } + else { + iterate(); + } + } + }); + }; + iterate(); + }; + async.forEachSeries = async.eachSeries; + + async.eachLimit = function (arr, limit, iterator, callback) { + var fn = _eachLimit(limit); + fn.apply(null, [arr, iterator, callback]); + }; + async.forEachLimit = async.eachLimit; + + var _eachLimit = function (limit) { + + return function (arr, iterator, callback) { + callback = callback || function () {}; + if (!arr.length || limit <= 0) { + return callback(); + } + var completed = 0; + var started = 0; + var running = 0; + + (function replenish () { + if (completed >= arr.length) { + return callback(); + } + + while (running < limit && started < arr.length) { + started += 1; + running += 1; + iterator(arr[started - 1], function (err) { + if (err) { + callback(err); + callback = function () {}; + } + else { + completed += 1; + running -= 1; + if (completed >= arr.length) { + callback(); + } + else { + replenish(); + } + } + }); + } + })(); + }; + }; + + + var doParallel = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.each].concat(args)); + }; + }; + var doParallelLimit = function(limit, fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [_eachLimit(limit)].concat(args)); + }; + }; + var doSeries = function (fn) { + return function () { + var args = Array.prototype.slice.call(arguments); + return fn.apply(null, [async.eachSeries].concat(args)); + }; + }; + + + var _asyncMap = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (err, v) { + results[x.index] = v; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + }; + async.map = doParallel(_asyncMap); + async.mapSeries = doSeries(_asyncMap); + async.mapLimit = function (arr, limit, iterator, callback) { + return _mapLimit(limit)(arr, iterator, callback); + }; + + var _mapLimit = function(limit) { + return doParallelLimit(limit, _asyncMap); + }; + + // reduce only has a series version, as doing reduce in parallel won't + // work in many situations. + async.reduce = function (arr, memo, iterator, callback) { + async.eachSeries(arr, function (x, callback) { + iterator(memo, x, function (err, v) { + memo = v; + callback(err); + }); + }, function (err) { + callback(err, memo); + }); + }; + // inject alias + async.inject = async.reduce; + // foldl alias + async.foldl = async.reduce; + + async.reduceRight = function (arr, memo, iterator, callback) { + var reversed = _map(arr, function (x) { + return x; + }).reverse(); + async.reduce(reversed, memo, iterator, callback); + }; + // foldr alias + async.foldr = async.reduceRight; + + var _filter = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.filter = doParallel(_filter); + async.filterSeries = doSeries(_filter); + // select alias + async.select = async.filter; + async.selectSeries = async.filterSeries; + + var _reject = function (eachfn, arr, iterator, callback) { + var results = []; + arr = _map(arr, function (x, i) { + return {index: i, value: x}; + }); + eachfn(arr, function (x, callback) { + iterator(x.value, function (v) { + if (!v) { + results.push(x); + } + callback(); + }); + }, function (err) { + callback(_map(results.sort(function (a, b) { + return a.index - b.index; + }), function (x) { + return x.value; + })); + }); + }; + async.reject = doParallel(_reject); + async.rejectSeries = doSeries(_reject); + + var _detect = function (eachfn, arr, iterator, main_callback) { + eachfn(arr, function (x, callback) { + iterator(x, function (result) { + if (result) { + main_callback(x); + main_callback = function () {}; + } + else { + callback(); + } + }); + }, function (err) { + main_callback(); + }); + }; + async.detect = doParallel(_detect); + async.detectSeries = doSeries(_detect); + + async.some = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (v) { + main_callback(true); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(false); + }); + }; + // any alias + async.any = async.some; + + async.every = function (arr, iterator, main_callback) { + async.each(arr, function (x, callback) { + iterator(x, function (v) { + if (!v) { + main_callback(false); + main_callback = function () {}; + } + callback(); + }); + }, function (err) { + main_callback(true); + }); + }; + // all alias + async.all = async.every; + + async.sortBy = function (arr, iterator, callback) { + async.map(arr, function (x, callback) { + iterator(x, function (err, criteria) { + if (err) { + callback(err); + } + else { + callback(null, {value: x, criteria: criteria}); + } + }); + }, function (err, results) { + if (err) { + return callback(err); + } + else { + var fn = function (left, right) { + var a = left.criteria, b = right.criteria; + return a < b ? -1 : a > b ? 1 : 0; + }; + callback(null, _map(results.sort(fn), function (x) { + return x.value; + })); + } + }); + }; + + async.auto = function (tasks, callback) { + callback = callback || function () {}; + var keys = _keys(tasks); + if (!keys.length) { + return callback(null); + } + + var results = {}; + + var listeners = []; + var addListener = function (fn) { + listeners.unshift(fn); + }; + var removeListener = function (fn) { + for (var i = 0; i < listeners.length; i += 1) { + if (listeners[i] === fn) { + listeners.splice(i, 1); + return; + } + } + }; + var taskComplete = function () { + _each(listeners.slice(0), function (fn) { + fn(); + }); + }; + + addListener(function () { + if (_keys(results).length === keys.length) { + callback(null, results); + callback = function () {}; + } + }); + + _each(keys, function (k) { + var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k]; + var taskCallback = function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + if (err) { + var safeResults = {}; + _each(_keys(results), function(rkey) { + safeResults[rkey] = results[rkey]; + }); + safeResults[k] = args; + callback(err, safeResults); + // stop subsequent errors hitting callback multiple times + callback = function () {}; + } + else { + results[k] = args; + async.setImmediate(taskComplete); + } + }; + var requires = task.slice(0, Math.abs(task.length - 1)) || []; + var ready = function () { + return _reduce(requires, function (a, x) { + return (a && results.hasOwnProperty(x)); + }, true) && !results.hasOwnProperty(k); + }; + if (ready()) { + task[task.length - 1](taskCallback, results); + } + else { + var listener = function () { + if (ready()) { + removeListener(listener); + task[task.length - 1](taskCallback, results); + } + }; + addListener(listener); + } + }); + }; + + async.waterfall = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor !== Array) { + var err = new Error('First argument to waterfall must be an array of functions'); + return callback(err); + } + if (!tasks.length) { + return callback(); + } + var wrapIterator = function (iterator) { + return function (err) { + if (err) { + callback.apply(null, arguments); + callback = function () {}; + } + else { + var args = Array.prototype.slice.call(arguments, 1); + var next = iterator.next(); + if (next) { + args.push(wrapIterator(next)); + } + else { + args.push(callback); + } + async.setImmediate(function () { + iterator.apply(null, args); + }); + } + }; + }; + wrapIterator(async.iterator(tasks))(); + }; + + var _parallel = function(eachfn, tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + eachfn.map(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + eachfn.each(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.parallel = function (tasks, callback) { + _parallel({ map: async.map, each: async.each }, tasks, callback); + }; + + async.parallelLimit = function(tasks, limit, callback) { + _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback); + }; + + async.series = function (tasks, callback) { + callback = callback || function () {}; + if (tasks.constructor === Array) { + async.mapSeries(tasks, function (fn, callback) { + if (fn) { + fn(function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + callback.call(null, err, args); + }); + } + }, callback); + } + else { + var results = {}; + async.eachSeries(_keys(tasks), function (k, callback) { + tasks[k](function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (args.length <= 1) { + args = args[0]; + } + results[k] = args; + callback(err); + }); + }, function (err) { + callback(err, results); + }); + } + }; + + async.iterator = function (tasks) { + var makeCallback = function (index) { + var fn = function () { + if (tasks.length) { + tasks[index].apply(null, arguments); + } + return fn.next(); + }; + fn.next = function () { + return (index < tasks.length - 1) ? makeCallback(index + 1): null; + }; + return fn; + }; + return makeCallback(0); + }; + + async.apply = function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + return function () { + return fn.apply( + null, args.concat(Array.prototype.slice.call(arguments)) + ); + }; + }; + + var _concat = function (eachfn, arr, fn, callback) { + var r = []; + eachfn(arr, function (x, cb) { + fn(x, function (err, y) { + r = r.concat(y || []); + cb(err); + }); + }, function (err) { + callback(err, r); + }); + }; + async.concat = doParallel(_concat); + async.concatSeries = doSeries(_concat); + + async.whilst = function (test, iterator, callback) { + if (test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.whilst(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doWhilst = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (test()) { + async.doWhilst(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.until = function (test, iterator, callback) { + if (!test()) { + iterator(function (err) { + if (err) { + return callback(err); + } + async.until(test, iterator, callback); + }); + } + else { + callback(); + } + }; + + async.doUntil = function (iterator, test, callback) { + iterator(function (err) { + if (err) { + return callback(err); + } + if (!test()) { + async.doUntil(iterator, test, callback); + } + else { + callback(); + } + }); + }; + + async.queue = function (worker, concurrency) { + if (concurrency === undefined) { + concurrency = 1; + } + function _insert(q, data, pos, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + var item = { + data: task, + callback: typeof callback === 'function' ? callback : null + }; + + if (pos) { + q.tasks.unshift(item); + } else { + q.tasks.push(item); + } + + if (q.saturated && q.tasks.length === concurrency) { + q.saturated(); + } + async.setImmediate(q.process); + }); + } + + var workers = 0; + var q = { + tasks: [], + concurrency: concurrency, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + _insert(q, data, false, callback); + }, + unshift: function (data, callback) { + _insert(q, data, true, callback); + }, + process: function () { + if (workers < q.concurrency && q.tasks.length) { + var task = q.tasks.shift(); + if (q.empty && q.tasks.length === 0) { + q.empty(); + } + workers += 1; + var next = function () { + workers -= 1; + if (task.callback) { + task.callback.apply(task, arguments); + } + if (q.drain && q.tasks.length + workers === 0) { + q.drain(); + } + q.process(); + }; + var cb = only_once(next); + worker(task.data, cb); + } + }, + length: function () { + return q.tasks.length; + }, + running: function () { + return workers; + } + }; + return q; + }; + + async.cargo = function (worker, payload) { + var working = false, + tasks = []; + + var cargo = { + tasks: tasks, + payload: payload, + saturated: null, + empty: null, + drain: null, + push: function (data, callback) { + if(data.constructor !== Array) { + data = [data]; + } + _each(data, function(task) { + tasks.push({ + data: task, + callback: typeof callback === 'function' ? callback : null + }); + if (cargo.saturated && tasks.length === payload) { + cargo.saturated(); + } + }); + async.setImmediate(cargo.process); + }, + process: function process() { + if (working) return; + if (tasks.length === 0) { + if(cargo.drain) cargo.drain(); + return; + } + + var ts = typeof payload === 'number' + ? tasks.splice(0, payload) + : tasks.splice(0); + + var ds = _map(ts, function (task) { + return task.data; + }); + + if(cargo.empty) cargo.empty(); + working = true; + worker(ds, function () { + working = false; + + var args = arguments; + _each(ts, function (data) { + if (data.callback) { + data.callback.apply(null, args); + } + }); + + process(); + }); + }, + length: function () { + return tasks.length; + }, + running: function () { + return working; + } + }; + return cargo; + }; + + var _console_fn = function (name) { + return function (fn) { + var args = Array.prototype.slice.call(arguments, 1); + fn.apply(null, args.concat([function (err) { + var args = Array.prototype.slice.call(arguments, 1); + if (typeof console !== 'undefined') { + if (err) { + if (console.error) { + console.error(err); + } + } + else if (console[name]) { + _each(args, function (x) { + console[name](x); + }); + } + } + }])); + }; + }; + async.log = _console_fn('log'); + async.dir = _console_fn('dir'); + /*async.info = _console_fn('info'); + async.warn = _console_fn('warn'); + async.error = _console_fn('error');*/ + + async.memoize = function (fn, hasher) { + var memo = {}; + var queues = {}; + hasher = hasher || function (x) { + return x; + }; + var memoized = function () { + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + var key = hasher.apply(null, args); + if (key in memo) { + callback.apply(null, memo[key]); + } + else if (key in queues) { + queues[key].push(callback); + } + else { + queues[key] = [callback]; + fn.apply(null, args.concat([function () { + memo[key] = arguments; + var q = queues[key]; + delete queues[key]; + for (var i = 0, l = q.length; i < l; i++) { + q[i].apply(null, arguments); + } + }])); + } + }; + memoized.memo = memo; + memoized.unmemoized = fn; + return memoized; + }; + + async.unmemoize = function (fn) { + return function () { + return (fn.unmemoized || fn).apply(null, arguments); + }; + }; + + async.times = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.map(counter, iterator, callback); + }; + + async.timesSeries = function (count, iterator, callback) { + var counter = []; + for (var i = 0; i < count; i++) { + counter.push(i); + } + return async.mapSeries(counter, iterator, callback); + }; + + async.compose = function (/* functions... */) { + var fns = Array.prototype.reverse.call(arguments); + return function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + async.reduce(fns, args, function (newargs, fn, cb) { + fn.apply(that, newargs.concat([function () { + var err = arguments[0]; + var nextargs = Array.prototype.slice.call(arguments, 1); + cb(err, nextargs); + }])) + }, + function (err, results) { + callback.apply(that, [err].concat(results)); + }); + }; + }; + + var _applyEach = function (eachfn, fns /*args...*/) { + var go = function () { + var that = this; + var args = Array.prototype.slice.call(arguments); + var callback = args.pop(); + return eachfn(fns, function (fn, cb) { + fn.apply(that, args.concat([cb])); + }, + callback); + }; + if (arguments.length > 2) { + var args = Array.prototype.slice.call(arguments, 2); + return go.apply(this, args); + } + else { + return go; + } + }; + async.applyEach = doParallel(_applyEach); + async.applyEachSeries = doSeries(_applyEach); + + async.forever = function (fn, callback) { + function next(err) { + if (err) { + if (callback) { + return callback(err); + } + throw err; + } + fn(next); + } + next(); + }; + + // AMD / RequireJS + if (typeof define !== 'undefined' && define.amd) { + define('async',[], function () { + return async; + }); + } + // Node.js + else if (typeof module !== 'undefined' && module.exports) { + module.exports = async; + } + // included directly via \r\n");var a,s,u;!function(t){function e(t,e){return b.call(t,e)}function n(t,e){var n,r,i,o,a,s,u,f,c,p,h,l=e&&e.split("/"),d=m.map,y=d&&d["*"]||{};if(t&&"."===t.charAt(0))if(e){for(l=l.slice(0,l.length-1),t=t.split("/"),a=t.length-1,m.nodeIdCompat&&S.test(t[a])&&(t[a]=t[a].replace(S,"")),t=l.concat(t),c=0;c0&&(t.splice(c-1,2),c-=2)}t=t.join("/")}else 0===t.indexOf("./")&&(t=t.substring(2));if((l||y)&&d){for(n=t.split("/"),c=n.length;c>0;c-=1){if(r=n.slice(0,c).join("/"),l)for(p=l.length;p>0;p-=1)if(i=d[l.slice(0,p).join("/")],i&&(i=i[r])){o=i,s=c;break}if(o)break;!u&&y&&y[r]&&(u=y[r],f=c)}!o&&u&&(o=u,s=f),o&&(n.splice(0,s,o),t=n.join("/"))}return t}function r(e,n){return function(){var r=E.call(arguments,0);return"string"!=typeof r[0]&&1===r.length&&r.push(null),l.apply(t,r.concat([e,n]))}}function i(t){return function(e){return n(e,t)}}function o(t){return function(e){g[t]=e}}function f(n){if(e(w,n)){var r=w[n];delete w[n],v[n]=!0,h.apply(t,r)}if(!e(g,n)&&!e(v,n))throw new Error("No "+n);return g[n]}function c(t){var e,n=t?t.indexOf("!"):-1;return n>-1&&(e=t.substring(0,n),t=t.substring(n+1,t.length)),[e,t]}function p(t){return function(){return m&&m.config&&m.config[t]||{}}}var h,l,d,y,g={},w={},m={},v={},b=Object.prototype.hasOwnProperty,E=[].slice,S=/\.js$/;d=function(t,e){var r,o=c(t),a=o[0];return t=o[1],a&&(a=n(a,e),r=f(a)),a?t=r&&r.normalize?r.normalize(t,i(e)):n(t,e):(t=n(t,e),o=c(t),a=o[0],t=o[1],a&&(r=f(a))),{f:a?a+"!"+t:t,n:t,pr:a,p:r}},y={require:function(t){return r(t)},exports:function(t){var e=g[t];return"undefined"!=typeof e?e:g[t]={}},module:function(t){return{id:t,uri:"",exports:g[t],config:p(t)}}},h=function(n,i,a,s){var u,c,p,h,l,m,b=[],E=typeof a;if(s=s||n,"undefined"===E||"function"===E){for(i=!i.length&&a.length?["require","exports","module"]:i,l=0;l>>24)},t.prototype.writeInt16LE=function(t,e){this.writeUInt8(t,255&e),this.writeUInt8(t+1,255&e>>>8|(2147483648&e)>>>24)},t.prototype.writeInt16BE=function(t,e){this.writeUInt8(t+1,255&e),this.writeUInt8(t,255&e>>>8|(2147483648&e)>>>24)},t.prototype.writeInt32LE=function(t,e){this.writeUInt8(t,255&e),this.writeUInt8(t+1,255&e>>>8),this.writeUInt8(t+2,255&e>>>16),this.writeUInt8(t+3,255&e>>>24)},t.prototype.writeInt32BE=function(t,e){this.writeUInt8(t+3,255&e),this.writeUInt8(t+2,255&e>>>8),this.writeUInt8(t+1,255&e>>>16),this.writeUInt8(t,255&e>>>24)},t.prototype.writeUInt8=function(){throw new n.ApiError(14,"BufferCore implementations should implement writeUInt8.")},t.prototype.writeUInt16LE=function(t,e){this.writeUInt8(t,255&e),this.writeUInt8(t+1,255&e>>8)},t.prototype.writeUInt16BE=function(t,e){this.writeUInt8(t+1,255&e),this.writeUInt8(t,255&e>>8)},t.prototype.writeUInt32LE=function(t,e){this.writeInt32LE(t,0|e)},t.prototype.writeUInt32BE=function(t,e){this.writeInt32BE(t,0|e)},t.prototype.writeFloatLE=function(t,e){this.writeInt32LE(t,this.float2intbits(e))},t.prototype.writeFloatBE=function(t,e){this.writeInt32BE(t,this.float2intbits(e))},t.prototype.writeDoubleLE=function(t,e){var n=this.double2longbits(e);this.writeInt32LE(t,n[0]),this.writeInt32LE(t+4,n[1])},t.prototype.writeDoubleBE=function(t,e){var n=this.double2longbits(e);this.writeInt32BE(t+4,n[0]),this.writeInt32BE(t,n[1])},t.prototype.readInt8=function(t){var e=this.readUInt8(t);return 128&e?4294967168|e:e},t.prototype.readInt16LE=function(t){var e=this.readUInt16LE(t);return 32768&e?4294934528|e:e},t.prototype.readInt16BE=function(t){var e=this.readUInt16BE(t);return 32768&e?4294934528|e:e},t.prototype.readInt32LE=function(t){return 0|this.readUInt32LE(t)},t.prototype.readInt32BE=function(t){return 0|this.readUInt32BE(t)},t.prototype.readUInt8=function(){throw new n.ApiError(14,"BufferCore implementations should implement readUInt8.")},t.prototype.readUInt16LE=function(t){return this.readUInt8(t+1)<<8|this.readUInt8(t)},t.prototype.readUInt16BE=function(t){return this.readUInt8(t)<<8|this.readUInt8(t+1)},t.prototype.readUInt32LE=function(t){return(this.readUInt8(t+3)<<24|this.readUInt8(t+2)<<16|this.readUInt8(t+1)<<8|this.readUInt8(t))>>>0},t.prototype.readUInt32BE=function(t){return(this.readUInt8(t)<<24|this.readUInt8(t+1)<<16|this.readUInt8(t+2)<<8|this.readUInt8(t+3))>>>0},t.prototype.readFloatLE=function(t){return this.intbits2float(this.readInt32LE(t))},t.prototype.readFloatBE=function(t){return this.intbits2float(this.readInt32BE(t))},t.prototype.readDoubleLE=function(t){return this.longbits2double(this.readInt32LE(t+4),this.readInt32LE(t))},t.prototype.readDoubleBE=function(t){return this.longbits2double(this.readInt32BE(t),this.readInt32BE(t+4))},t.prototype.copy=function(){throw new n.ApiError(14,"BufferCore implementations should implement copy.")},t.prototype.fill=function(t,e,n){for(var r=e;n>r;r++)this.writeUInt8(r,t)},t.prototype.float2intbits=function(t){var e,n,r;return 0===t?0:t===Number.POSITIVE_INFINITY?o:t===Number.NEGATIVE_INFINITY?a:isNaN(t)?s:(r=0>t?1:0,t=Math.abs(t),1.1754942106924411e-38>=t&&t>=1.401298464324817e-45?(e=0,n=Math.round(t/Math.pow(2,-126)*Math.pow(2,23)),r<<31|e<<23|n):(e=Math.floor(Math.log(t)/Math.LN2),n=Math.round((t/Math.pow(2,e)-1)*Math.pow(2,23)),r<<31|e+127<<23|n))},t.prototype.double2longbits=function(t){var e,n,r,i;return 0===t?[0,0]:t===Number.POSITIVE_INFINITY?[0,2146435072]:t===Number.NEGATIVE_INFINITY?[0,-1048576]:isNaN(t)?[0,2146959360]:(i=0>t?1<<31:0,t=Math.abs(t),2.225073858507201e-308>=t&&t>=5e-324?(e=0,r=t/Math.pow(2,-1022)*Math.pow(2,52)):(e=Math.floor(Math.log(t)/Math.LN2),t>>31,s=(2139095040&t)>>>23,u=8388607&t;return e=0===s?Math.pow(-1,n)*u*Math.pow(2,-149):Math.pow(-1,n)*(1+u*Math.pow(2,-23))*Math.pow(2,s-127),(i>e||e>r)&&(e=0/0),e},t.prototype.longbits2double=function(t,e){var n=(2147483648&t)>>>31,r=(2146435072&t)>>>20,i=(1048575&t)*Math.pow(2,32)+e;return 0===r&&0===i?0:2047===r?0===i?1===n?Number.NEGATIVE_INFINITY:Number.POSITIVE_INFINITY:0/0:0===r?Math.pow(-1,n)*i*Math.pow(2,-1074):Math.pow(-1,n)*(1+i*Math.pow(2,-52))*Math.pow(2,r-1023)},t}();e.BufferCoreCommon=u});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("core/buffer_core_array",["require","exports","./buffer_core"],function(t,e,n){var r=[4294967040,4294902015,4278255615,16777215],i=function(t){function e(e){t.call(this),this.length=e,this.buff=new Array(Math.ceil(e/4));for(var n=this.buff.length,r=0;n>r;r++)this.buff[r]=0}return f(e,t),e.isAvailable=function(){return!0},e.prototype.getLength=function(){return this.length},e.prototype.writeUInt8=function(t,e){e&=255;var n=t>>2,i=3&t;this.buff[n]=this.buff[n]&r[i],this.buff[n]=this.buff[n]|e<<(i<<3)},e.prototype.readUInt8=function(t){var e=t>>2,n=3&t;return 255&this.buff[e]>>(n<<3)},e.prototype.copy=function(t,n){for(var r=new e(n-t),i=t;n>i;i++)r.writeUInt8(i-t,this.readUInt8(i));return r},e}(n.BufferCoreCommon);e.BufferCoreArray=i});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("core/buffer_core_arraybuffer",["require","exports","./buffer_core"],function(t,e,n){var r=function(t){function e(e){t.call(this),this.buff="number"==typeof e?new DataView(new ArrayBuffer(e)):e instanceof DataView?e:new DataView(e),this.length=this.buff.byteLength}return f(e,t),e.isAvailable=function(){return"undefined"!=typeof DataView},e.prototype.getLength=function(){return this.length},e.prototype.writeInt8=function(t,e){this.buff.setInt8(t,e)},e.prototype.writeInt16LE=function(t,e){this.buff.setInt16(t,e,!0)},e.prototype.writeInt16BE=function(t,e){this.buff.setInt16(t,e,!1)},e.prototype.writeInt32LE=function(t,e){this.buff.setInt32(t,e,!0)},e.prototype.writeInt32BE=function(t,e){this.buff.setInt32(t,e,!1)},e.prototype.writeUInt8=function(t,e){this.buff.setUint8(t,e)},e.prototype.writeUInt16LE=function(t,e){this.buff.setUint16(t,e,!0)},e.prototype.writeUInt16BE=function(t,e){this.buff.setUint16(t,e,!1)},e.prototype.writeUInt32LE=function(t,e){this.buff.setUint32(t,e,!0)},e.prototype.writeUInt32BE=function(t,e){this.buff.setUint32(t,e,!1)},e.prototype.writeFloatLE=function(t,e){this.buff.setFloat32(t,e,!0)},e.prototype.writeFloatBE=function(t,e){this.buff.setFloat32(t,e,!1)},e.prototype.writeDoubleLE=function(t,e){this.buff.setFloat64(t,e,!0)},e.prototype.writeDoubleBE=function(t,e){this.buff.setFloat64(t,e,!1)},e.prototype.readInt8=function(t){return this.buff.getInt8(t)},e.prototype.readInt16LE=function(t){return this.buff.getInt16(t,!0)},e.prototype.readInt16BE=function(t){return this.buff.getInt16(t,!1)},e.prototype.readInt32LE=function(t){return this.buff.getInt32(t,!0)},e.prototype.readInt32BE=function(t){return this.buff.getInt32(t,!1)},e.prototype.readUInt8=function(t){return this.buff.getUint8(t)},e.prototype.readUInt16LE=function(t){return this.buff.getUint16(t,!0)},e.prototype.readUInt16BE=function(t){return this.buff.getUint16(t,!1)},e.prototype.readUInt32LE=function(t){return this.buff.getUint32(t,!0)},e.prototype.readUInt32BE=function(t){return this.buff.getUint32(t,!1)},e.prototype.readFloatLE=function(t){return this.buff.getFloat32(t,!0)},e.prototype.readFloatBE=function(t){return this.buff.getFloat32(t,!1)},e.prototype.readDoubleLE=function(t){return this.buff.getFloat64(t,!0)},e.prototype.readDoubleBE=function(t){return this.buff.getFloat64(t,!1)},e.prototype.copy=function(t,n){var r,i=this.buff.buffer;if(ArrayBuffer.prototype.slice)r=i.slice(t,n);else{var o=n-t;r=new ArrayBuffer(o);var a=new Uint8Array(r),s=new Uint8Array(i);a.set(s.subarray(t,n))}return new e(r)},e.prototype.fill=function(t,e,n){t=255&t;var r,i=n-e,o=4*(0|i/4),a=t<<24|t<<16|t<<8|t;for(r=0;o>r;r+=4)this.writeInt32LE(r+e,a);for(r=o;i>r;r++)this.writeUInt8(r+e,t)},e.prototype.getDataView=function(){return this.buff},e}(n.BufferCoreCommon);e.BufferCoreArrayBuffer=r});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("core/buffer_core_imagedata",["require","exports","./buffer_core"],function(t,e,n){var r=function(t){function e(n){t.call(this),this.length=n,this.buff=e.getCanvasPixelArray(n)}return f(e,t),e.getCanvasPixelArray=function(t){var n=e.imageDataFactory;return void 0===n&&(e.imageDataFactory=n=document.createElement("canvas").getContext("2d")),0===t&&(t=1),n.createImageData(Math.ceil(t/4),1).data},e.isAvailable=function(){return"undefined"!=typeof CanvasPixelArray},e.prototype.getLength=function(){return this.length},e.prototype.writeUInt8=function(t,e){this.buff[t]=e},e.prototype.readUInt8=function(t){return this.buff[t]},e.prototype.copy=function(t,n){for(var r=new e(n-t),i=t;n>i;i++)r.writeUInt8(i-t,this.buff[i]);return r},e}(n.BufferCoreCommon);e.BufferCoreImageData=r}),u("core/string_util",["require","exports"],function(t,e){function n(t){switch(t=function(){switch(typeof t){case"object":return""+t;case"string":return t;default:throw new Error("Invalid encoding argument specified")}}(),t=t.toLowerCase()){case"utf8":case"utf-8":return r;case"ascii":return i;case"binary":return a;case"ucs2":case"ucs-2":case"utf16le":case"utf-16le":return u;case"hex":return f;case"base64":return s;case"binary_string":return c;case"binary_string_ie":return p;case"extended_ascii":return o;default:throw new Error("Unknown encoding: "+t)}}e.FindUtil=n;var r=function(){function t(){}return t.str2byte=function(t,e){for(var n=e.length,r=0,i=0,o=n,a=0;ri;){var s=t.charCodeAt(r++),u=t.charCodeAt(r);if(s>=55296&&56319>=s&&u>=56320&&57343>=u){if(i+3>=o)break;a++;var f=(1024|1023&s)<<10|1023&u;e.writeUInt8(240|f>>18,i++),e.writeUInt8(128|63&f>>12,i++),e.writeUInt8(128|63&f>>6,i++),e.writeUInt8(128|63&f,i++),r++}else if(128>s)e.writeUInt8(s,i++),a++;else if(2048>s){if(i+1>=o)break;a++,e.writeUInt8(192|s>>6,i++),e.writeUInt8(128|63&s,i++)}else if(65536>s){if(i+2>=o)break;a++,e.writeUInt8(224|s>>12,i++),e.writeUInt8(128|63&s>>6,i++),e.writeUInt8(128|63&s,i++)}}return i},t.byte2str=function(t){for(var e=[],n=0;nr)e.push(String.fromCharCode(r));else{if(192>r)throw new Error("Found incomplete part of character in string.");if(224>r)e.push(String.fromCharCode((31&r)<<6|63&t.readUInt8(n++)));else if(240>r)e.push(String.fromCharCode((15&r)<<12|(63&t.readUInt8(n++))<<6|63&t.readUInt8(n++)));else{if(!(248>r))throw new Error("Unable to represent UTF-8 string as UTF-16 JavaScript string.");var i=t.readUInt8(n+2);e.push(String.fromCharCode(55296|1023&((7&r)<<8|(63&t.readUInt8(n++))<<2|(63&t.readUInt8(n++))>>4))),e.push(String.fromCharCode(56320|((15&i)<<6|63&t.readUInt8(n++))))}}}return e.join("")},t.byteLength=function(t){var e=encodeURIComponent(t).match(/%[89ABab]/g);return t.length+(e?e.length:0)},t}();e.UTF8=r;var i=function(){function t(){}return t.str2byte=function(t,e){for(var n=t.length>e.length?e.length:t.length,r=0;n>r;r++)e.writeUInt8(t.charCodeAt(r)%256,r);return n},t.byte2str=function(t){for(var e=new Array(t.length),n=0;nn.length?n.length:e.length,i=0;r>i;i++){var o=e.charCodeAt(i);if(o>127){var a=t.extendedChars.indexOf(e.charAt(i));a>-1&&(o=a+128)}n.writeUInt8(o,i)}return r},t.byte2str=function(e){for(var n=new Array(e.length),r=0;r127?t.extendedChars[i-128]:String.fromCharCode(i)}return n.join("")},t.byteLength=function(t){return t.length},t.extendedChars=["Ç","ü","é","â","ä","à","å","ç","ê","ë","è","ï","î","ì","Ä","Å","É","æ","Æ","ô","ö","ò","û","ù","ÿ","Ö","Ü","ø","£","Ø","×","ƒ","á","í","ó","ú","ñ","Ñ","ª","º","¿","®","¬","½","¼","¡","«","»","_","_","_","¦","¦","Á","Â","À","©","¦","¦","+","+","¢","¥","+","+","-","-","+","-","+","ã","Ã","+","+","-","-","¦","-","+","¤","ð","Ð","Ê","Ë","È","i","Í","Î","Ï","+","+","_","_","¦","Ì","_","Ó","ß","Ô","Ò","õ","Õ","µ","þ","Þ","Ú","Û","Ù","ý","Ý","¯","´","­","±","_","¾","¶","§","÷","¸","°","¨","·","¹","³","²","_"," "],t}();e.ExtendedASCII=o;var a=function(){function t(){}return t.str2byte=function(t,e){for(var n=t.length>e.length?e.length:t.length,r=0;n>r;r++)e.writeUInt8(255&t.charCodeAt(r),r);return n},t.byte2str=function(t){for(var e=new Array(t.length),n=0;n>2,u=(3&i)<<4|o>>4,f=(15&o)<<2|a>>6,c=63&a;isNaN(o)?f=c=64:isNaN(a)&&(c=64),n=n+t.num2b64[s]+t.num2b64[u]+t.num2b64[f]+t.num2b64[c]}return n},t.str2byte=function(e,n){var r=n.length,i="",o=0;e=e.replace(/[^A-Za-z0-9\+\/\=\-\_]/g,"");for(var a=0;o>4,h=(15&u)<<4|f>>2,l=(3&f)<<6|c;if(n.writeUInt8(p,a++),a===r)break;if(64!==f&&(i+=n.writeUInt8(h,a++)),a===r)break;if(64!==c&&(i+=n.writeUInt8(l,a++)),a===r)break}return a},t.byteLength=function(t){return Math.floor(6*t.replace(/[^A-Za-z0-9\+\/\-\_]/g,"").length/8)},t.b64chars=["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","+","/","="],t.num2b64=function(){for(var e=new Array(t.b64chars.length),n=0;ne.length&&(n=1===e.length%2?(e.length-1)/2:e.length/2);for(var r=0;n>r;r++)e.writeUInt16LE(t.charCodeAt(r),2*r);return 2*n},t.byte2str=function(t){if(0!==t.length%2)throw new Error("Invalid UCS2 byte array.");for(var e=new Array(t.length/2),n=0;n>1;n>e.length&&(n=e.length);for(var r=0;n>r;r++){var i=this.hex2num[t.charAt(r<<1)],o=this.hex2num[t.charAt((r<<1)+1)];e.writeUInt8(i<<4|o,r)}return n},t.byte2str=function(t){for(var e=t.length,n=new Array(e<<1),r=0,i=0;e>i;i++){var o=15&t.readUInt8(i),a=t.readUInt8(i)>>4;n[r++]=this.num2hex[a],n[r++]=this.num2hex[o]}return n.join("")},t.byteLength=function(t){return t.length>>1},t.HEXCHARS="0123456789abcdef",t.num2hex=function(){for(var e=new Array(t.HEXCHARS.length),n=0;nn.length&&(r=n.length);var i=0,o=0,a=o+r,s=e.charCodeAt(i++);0!==s&&(n.writeUInt8(255&s,0),o=1);for(var u=o;a>u;u+=2){var f=e.charCodeAt(i++);1===a-u&&n.writeUInt8(f>>8,u),a-u>=2&&n.writeUInt16BE(f,u)}return r},t.byte2str=function(t){var e=t.length;if(0===e)return"";for(var n=new Array((e>>1)+1),r=0,i=0;ie.length?e.length:t.length,r=0;n>r;r++)e.writeUInt8(t.charCodeAt(r)-32,r);return n},t.byte2str=function(t){for(var e=new Array(t.length),n=0;n>>0)throw new TypeError("Buffer size must be a uint32.");this.length=e,this.data=new u(e)}else if("undefined"!=typeof DataView&&e instanceof DataView)this.data=new i.BufferCoreArrayBuffer(e),this.length=e.byteLength;else if("undefined"!=typeof ArrayBuffer&&e instanceof ArrayBuffer)this.data=new i.BufferCoreArrayBuffer(e),this.length=e.byteLength;else if(e instanceof t){var c=e;this.data=new u(e.length),this.length=e.length,c.copy(this)}else if(Array.isArray(e)||null!=e&&"object"==typeof e&&"number"==typeof e[0]){for(this.data=new u(e.length),a=0;ae?this.writeInt8(e,t):this.writeUInt8(e,t)},t.prototype.get=function(t){return this.readUInt8(t)},t.prototype.write=function(e,n,r,i){if("undefined"==typeof n&&(n=0),"undefined"==typeof r&&(r=this.length),"undefined"==typeof i&&(i="utf8"),"string"==typeof n?(i=""+n,n=0,r=this.length):"string"==typeof r&&(i=""+r,r=this.length),n>=this.length)return 0;var o=a.FindUtil(i);return r=r+n>this.length?this.length-n:r,n+=this.offset,o.str2byte(e,0===n&&r===this.length?this:new t(this.data,n,r+n))},t.prototype.toString=function(e,n,r){if("undefined"==typeof e&&(e="utf8"),"undefined"==typeof n&&(n=0),"undefined"==typeof r&&(r=this.length),!(r>=n))throw new Error("Invalid start/end positions: "+n+" - "+r);if(n===r)return"";r>this.length&&(r=this.length);var i=a.FindUtil(e);return i.byte2str(0===n&&r===this.length?this:new t(this.data,n+this.offset,r+this.offset))},t.prototype.toJSON=function(){for(var t=this.length,e=new Array(t),n=0;t>n;n++)e[n]=this.readUInt8(n);return{type:"Buffer",data:e}},t.prototype.copy=function(t,e,n,r){if("undefined"==typeof e&&(e=0),"undefined"==typeof n&&(n=0),"undefined"==typeof r&&(r=this.length),e=0>e?0:e,n=0>n?0:n,n>r)throw new RangeError("sourceEnd < sourceStart");if(r===n)return 0;if(e>=t.length)throw new RangeError("targetStart out of bounds");if(n>=this.length)throw new RangeError("sourceStart out of bounds");if(r>this.length)throw new RangeError("sourceEnd out of bounds");for(var i=Math.min(r-n,t.length-e,this.length-n),o=0;i>o;o++)t.writeUInt8(this.readUInt8(n+o),e+o);return i},t.prototype.slice=function(e,n){if("undefined"==typeof e&&(e=0),"undefined"==typeof n&&(n=this.length),0>e&&(e+=this.length,0>e&&(e=0)),0>n&&(n+=this.length,0>n&&(n=0)),n>this.length&&(n=this.length),e>n&&(e=n),0>e||0>n||e>=this.length||n>this.length)throw new Error("Invalid slice indices.");return new t(this.data,e+this.offset,n+this.offset)},t.prototype.sliceCopy=function(e,n){if("undefined"==typeof e&&(e=0),"undefined"==typeof n&&(n=this.length),0>e&&(e+=this.length,0>e&&(e=0)),0>n&&(n+=this.length,0>n&&(n=0)),n>this.length&&(n=this.length),e>n&&(e=n),0>e||0>n||e>=this.length||n>this.length)throw new Error("Invalid slice indices.");return new t(this.data.copy(e+this.offset,n+this.offset))},t.prototype.fill=function(t,e,n){"undefined"==typeof e&&(e=0),"undefined"==typeof n&&(n=this.length);var r=typeof t;switch(r){case"string":t=255&t.charCodeAt(0);break;case"number":break;default:throw new Error("Invalid argument to fill.")}e+=this.offset,n+=this.offset,this.data.fill(t,e,n)},t.prototype.readUInt8=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readUInt8(t)},t.prototype.readUInt16LE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readUInt16LE(t)},t.prototype.readUInt16BE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readUInt16BE(t)},t.prototype.readUInt32LE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readUInt32LE(t)},t.prototype.readUInt32BE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readUInt32BE(t)},t.prototype.readInt8=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readInt8(t)},t.prototype.readInt16LE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readInt16LE(t)},t.prototype.readInt16BE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readInt16BE(t)},t.prototype.readInt32LE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readInt32LE(t)},t.prototype.readInt32BE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readInt32BE(t)},t.prototype.readFloatLE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readFloatLE(t)},t.prototype.readFloatBE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readFloatBE(t)},t.prototype.readDoubleLE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readDoubleLE(t)},t.prototype.readDoubleBE=function(t,e){return"undefined"==typeof e&&(e=!1),t+=this.offset,this.data.readDoubleBE(t)},t.prototype.writeUInt8=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeUInt8(e,t)},t.prototype.writeUInt16LE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeUInt16LE(e,t)},t.prototype.writeUInt16BE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeUInt16BE(e,t)},t.prototype.writeUInt32LE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeUInt32LE(e,t)},t.prototype.writeUInt32BE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeUInt32BE(e,t)},t.prototype.writeInt8=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeInt8(e,t)},t.prototype.writeInt16LE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeInt16LE(e,t)},t.prototype.writeInt16BE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeInt16BE(e,t)},t.prototype.writeInt32LE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeInt32LE(e,t)},t.prototype.writeInt32BE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeInt32BE(e,t)},t.prototype.writeFloatLE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeFloatLE(e,t)},t.prototype.writeFloatBE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeFloatBE(e,t)},t.prototype.writeDoubleLE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeDoubleLE(e,t)},t.prototype.writeDoubleBE=function(t,e,n){"undefined"==typeof n&&(n=!1),e+=this.offset,this.data.writeDoubleBE(e,t)},t.isEncoding=function(t){try{a.FindUtil(t)}catch(e){return!1}return!0},t.isBuffer=function(e){return e instanceof t},t.byteLength=function(t,e){"undefined"==typeof e&&(e="utf8");var n=a.FindUtil(e); +return n.byteLength(t)},t.concat=function(e,n){var r;if(0===e.length||0===n)return new t(0);if(1===e.length)return e[0];if(null==n){n=0;for(var i=0;ithis.maxListeners&&process.stdout.write("Warning: Event "+t+" has more than "+this.maxListeners+" listeners.\n"),this.emit("newListener",t,e),this},t.prototype.on=function(t,e){return this.addListener(t,e)},t.prototype.once=function(t,e){var n=!1,r=function(){this.removeListener(t,r),n||(n=!0,e.apply(this,arguments))};return this.addListener(t,r)},t.prototype._emitRemoveListener=function(t,e){var n;if(this._listeners.removeListener&&this._listeners.removeListener.length>0)for(n=0;n-1&&n.splice(r,1)}return this.emit("removeListener",t,e),this},t.prototype.removeAllListeners=function(t){var e,n,r;if("undefined"!=typeof t)e=this._listeners[t],this._listeners[t]=[],this._emitRemoveListener(t,e);else for(n=Object.keys(this._listeners),r=0;r0&&setTimeout(function(){i.emit("readable")},0):this.resume(),r},e.prototype._processArgs=function(t,e,n){return"string"==typeof e?new a(t,e,n):new a(t,null,e)},e.prototype._processEvents=function(){var t=0===this.buffer.length;this.drained!==t&&this.drained&&this.emit("readable"),this.flowing&&0!==this.buffer.length&&this.emit("data",this.read()),this.drained=0===this.buffer.length},e.prototype.emitEvent=function(t,e){this.emit(t,e.getData(this.encoding)),e.cb&&e.cb()},e.prototype.write=function(t,e,n){if(this.ended)throw new o(0,"Cannot write to an ended stream.");var r=this._processArgs(t,e,n);return this._push(r),this.flowing},e.prototype.end=function(t,e,n){if(this.ended)throw new o(0,"Stream is already closed.");var r=this._processArgs(t,e,n);this.ended=!0,this.endEvent=r,this._processEvents()},e.prototype.read=function(t){var e,n,r,o,s=[],u=[],f=0,c=0,p="number"!=typeof t;for(p&&(t=4294967295),c=0;cf;c++)n=this.buffer[c],s.push(n.getData()),n.cb&&u.push(n.cb),f+=n.size,e=n.cb;if(!p&&t>f)return null;if(this.buffer=this.buffer.slice(s.length),o=f>t?t:f,r=i.concat(s),f>t&&(e&&u.pop(),this._push(new a(r.slice(t),null,e))),u.length>0&&setTimeout(function(){var t;for(t=0;t0&&".."!==i[0])?i.pop():i.push(a))}if(!n&&i.length<2)switch(i.length){case 1:""===i[0]&&i.unshift(".");break;default:i.push(".")}return e=i.join(t.sep),n&&e.charAt(0)!==t.sep&&(e=t.sep+e),e},t.join=function(){for(var e=[],n=0;n1&&s.charAt(s.length-1)===t.sep)return s.substr(0,s.length-1);if(s.charAt(0)!==t.sep){"."!==s.charAt(0)||1!==s.length&&s.charAt(1)!==t.sep||(s=1===s.length?"":s.substr(2));var u=r.cwd();s=""!==s?this.normalize(u+("/"!==u?t.sep:"")+s):u}return s},t.relative=function(e,n){var r;e=t.resolve(e),n=t.resolve(n);var i=e.split(t.sep),o=n.split(t.sep);o.shift(),i.shift();var a=0,s=[];for(r=0;ri.length&&(a=i.length);var f="";for(r=0;a>r;r++)f+="../";return f+=s.join(t.sep),f.length>1&&f.charAt(f.length-1)===t.sep&&(f=f.substr(0,f.length-1)),f},t.dirname=function(e){e=t._removeDuplicateSeps(e);var n=e.charAt(0)===t.sep,r=e.split(t.sep);return""===r.pop()&&r.length>0&&r.pop(),r.length>1?r.join(t.sep):n?t.sep:"."},t.basename=function(e,n){if("undefined"==typeof n&&(n=""),""===e)return e;e=t.normalize(e);var r=e.split(t.sep),i=r[r.length-1];if(""===i&&r.length>1)return r[r.length-2];if(n.length>0){var o=i.substr(i.length-n.length);if(o===n)return i.substr(0,i.length-n.length)}return i},t.extname=function(e){e=t.normalize(e);var n=e.split(t.sep);if(e=n.pop(),""===e&&n.length>0&&(e=n.pop()),".."===e)return"";var r=e.lastIndexOf(".");return-1===r||0===r?"":e.substr(r)},t.isAbsolute=function(e){return e.length>0&&e.charAt(0)===t.sep},t._makeLong=function(t){return t},t._removeDuplicateSeps=function(t){return t=t.replace(this._replaceRegex,this.sep)},t.sep="/",t._replaceRegex=new RegExp("//+","g"),t.delimiter=":",t}();e.path=i}),u("core/node_fs",["require","exports","./api_error","./file_flag","./buffer","./node_path"],function(t,e,n,r,i,o){function a(t,e){if("function"!=typeof t)throw new h(9,"Callback must be a function.");switch("undefined"==typeof __numWaiting&&(__numWaiting=0),__numWaiting++,e){case 1:return function(e){setImmediate(function(){return __numWaiting--,t(e)})};case 2:return function(e,n){setImmediate(function(){return __numWaiting--,t(e,n)})};case 3:return function(e,n,r){setImmediate(function(){return __numWaiting--,t(e,n,r)})};default:throw new Error("Invalid invocation of wrapCb.")}}function s(t){if("function"!=typeof t.write)throw new h(3,"Invalid file descriptor.")}function u(t,e){switch(typeof t){case"number":return t;case"string":var n=parseInt(t,8);if(0/0!==n)return n;default:return e}}function f(t){if(t.indexOf("\x00")>=0)throw new h(9,"Path must be a string without null bytes.");if(""===t)throw new h(9,"Path must not be empty.");return y.resolve(t)}function c(t,e,n,r){switch(typeof t){case"object":return{encoding:"undefined"!=typeof t.encoding?t.encoding:e,flag:"undefined"!=typeof t.flag?t.flag:n,mode:u(t.mode,r)};case"string":return{encoding:t,flag:n,mode:r};default:return{encoding:e,flag:n,mode:r}}}function p(){}var h=n.ApiError;n.ErrorCode;var l=r.FileFlag,d=i.Buffer,y=o.path,g=function(){function t(){}return t._initialize=function(e){if(!e.constructor.isAvailable())throw new h(9,"Tried to instantiate BrowserFS with an unavailable file system.");return t.root=e},t._toUnixTimestamp=function(t){if("number"==typeof t)return t;if(t instanceof Date)return t.getTime()/1e3;throw new Error("Cannot parse time: "+t)},t.getRootFS=function(){return t.root?t.root:null},t.rename=function(e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{t.root.rename(f(e),f(n),i)}catch(o){i(o)}},t.renameSync=function(e,n){t.root.renameSync(f(e),f(n))},t.exists=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,1);try{return t.root.exists(f(e),r)}catch(i){return r(!1)}},t.existsSync=function(e){try{return t.root.existsSync(f(e))}catch(n){return!1}},t.stat=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,2);try{return t.root.stat(f(e),!1,r)}catch(i){return r(i,null)}},t.statSync=function(e){return t.root.statSync(f(e),!1)},t.lstat=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,2);try{return t.root.stat(f(e),!0,r)}catch(i){return r(i,null)}},t.lstatSync=function(e){return t.root.statSync(f(e),!0)},t.truncate=function(e,n,r){"undefined"==typeof n&&(n=0),"undefined"==typeof r&&(r=p);var i=0;"function"==typeof n?r=n:"number"==typeof n&&(i=n);var o=a(r,1);try{if(0>i)throw new h(9);return t.root.truncate(f(e),i,o)}catch(s){return o(s)}},t.truncateSync=function(e,n){if("undefined"==typeof n&&(n=0),0>n)throw new h(9);return t.root.truncateSync(f(e),n)},t.unlink=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,1);try{return t.root.unlink(f(e),r)}catch(i){return r(i)}},t.unlinkSync=function(e){return t.root.unlinkSync(f(e))},t.open=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o=u(r,420);i="function"==typeof r?r:i;var s=a(i,2);try{return t.root.open(f(e),l.getFileFlag(n),o,s)}catch(c){return s(c,null)}},t.openSync=function(e,n,r){return"undefined"==typeof r&&(r=420),t.root.openSync(f(e),l.getFileFlag(n),r)},t.readFile=function(e,n,r){"undefined"==typeof n&&(n={}),"undefined"==typeof r&&(r=p);var i=c(n,null,"r",null);r="function"==typeof n?n:r;var o=a(r,2);try{var s=l.getFileFlag(i.flag);return s.isReadable()?t.root.readFile(f(e),i.encoding,s,o):o(new h(9,"Flag passed to readFile must allow for reading."))}catch(u){return o(u,null)}},t.readFileSync=function(e,n){"undefined"==typeof n&&(n={});var r=c(n,null,"r",null),i=l.getFileFlag(r.flag);if(!i.isReadable())throw new h(9,"Flag passed to readFile must allow for reading.");return t.root.readFileSync(f(e),r.encoding,i)},t.writeFile=function(e,n,r,i){"undefined"==typeof r&&(r={}),"undefined"==typeof i&&(i=p);var o=c(r,"utf8","w",420);i="function"==typeof r?r:i;var s=a(i,1);try{var u=l.getFileFlag(o.flag);return u.isWriteable()?t.root.writeFile(f(e),n,o.encoding,u,o.mode,s):s(new h(9,"Flag passed to writeFile must allow for writing."))}catch(d){return s(d)}},t.writeFileSync=function(e,n,r){var i=c(r,"utf8","w",420),o=l.getFileFlag(i.flag);if(!o.isWriteable())throw new h(9,"Flag passed to writeFile must allow for writing.");return t.root.writeFileSync(f(e),n,i.encoding,o,i.mode)},t.appendFile=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o=c(r,"utf8","a",420);i="function"==typeof r?r:i;var s=a(i,1);try{var u=l.getFileFlag(o.flag);if(!u.isAppendable())return s(new h(9,"Flag passed to appendFile must allow for appending."));t.root.appendFile(f(e),n,o.encoding,u,o.mode,s)}catch(d){s(d)}},t.appendFileSync=function(e,n,r){var i=c(r,"utf8","a",420),o=l.getFileFlag(i.flag);if(!o.isAppendable())throw new h(9,"Flag passed to appendFile must allow for appending.");return t.root.appendFileSync(f(e),n,i.encoding,o,i.mode)},t.fstat=function(t,e){"undefined"==typeof e&&(e=p);var n=a(e,2);try{s(t),t.stat(n)}catch(r){n(r)}},t.fstatSync=function(t){return s(t),t.statSync()},t.close=function(t,e){"undefined"==typeof e&&(e=p);var n=a(e,1);try{s(t),t.close(n)}catch(r){n(r)}},t.closeSync=function(t){return s(t),t.closeSync()},t.ftruncate=function(t,e,n){"undefined"==typeof n&&(n=p);var r="number"==typeof e?e:0;n="function"==typeof e?e:n;var i=a(n,1);try{if(s(t),0>r)throw new h(9);t.truncate(r,i)}catch(o){i(o)}},t.ftruncateSync=function(t,e){return"undefined"==typeof e&&(e=0),s(t),t.truncateSync(e)},t.fsync=function(t,e){"undefined"==typeof e&&(e=p);var n=a(e,1);try{s(t),t.sync(n)}catch(r){n(r)}},t.fsyncSync=function(t){return s(t),t.syncSync()},t.fdatasync=function(t,e){"undefined"==typeof e&&(e=p);var n=a(e,1);try{s(t),t.datasync(n)}catch(r){n(r)}},t.fdatasyncSync=function(t){s(t),t.datasyncSync()},t.write=function(t,e,n,r,i,o){"undefined"==typeof o&&(o=p);var u,f,c,l=null;if("string"==typeof e){var y="utf8";switch(typeof n){case"function":o=n;break;case"number":l=n,y="string"==typeof r?r:"utf8",o="function"==typeof i?i:o;break;default:return o="function"==typeof r?r:"function"==typeof i?i:o,o(new h(9,"Invalid arguments."))}u=new d(e,y),f=0,c=u.length}else u=e,f=n,c=r,l="number"==typeof i?i:null,o="function"==typeof i?i:o;var g=a(o,3);try{s(t),null==l&&(l=t.getPos()),t.write(u,f,c,l,g)}catch(w){g(w)}},t.writeSync=function(t,e,n,r,i){var o,a,u,f=0;if("string"==typeof e){u="number"==typeof n?n:null;var c="string"==typeof r?r:"utf8";f=0,o=new d(e,c),a=o.length}else o=e,f=n,a=r,u="number"==typeof i?i:null;return s(t),null==u&&(u=t.getPos()),t.writeSync(o,f,a,u)},t.read=function(t,e,n,r,i,o){"undefined"==typeof o&&(o=p);var u,f,c,h,l;if("number"==typeof e){c=e,u=n;var y=r;o="function"==typeof i?i:o,f=0,h=new d(c),l=a(function(t,e,n){return t?o(t):(o(t,n.toString(y),e),void 0)},3)}else h=e,f=n,c=r,u=i,l=a(o,3);try{s(t),null==u&&(u=t.getPos()),t.read(h,f,c,u,l)}catch(g){l(g)}},t.readSync=function(t,e,n,r,i){var o,a,u,f,c=!1;if("number"==typeof e){u=e,f=n;var p=r;a=0,o=new d(u),c=!0}else o=e,a=n,u=r,f=i;s(t),null==f&&(f=t.getPos());var h=t.readSync(o,a,u,f);return c?[o.toString(p),h]:h},t.fchown=function(t,e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{s(t),t.chown(e,n,i)}catch(o){i(o)}},t.fchownSync=function(t,e,n){return s(t),t.chownSync(e,n)},t.fchmod=function(t,e,n){"undefined"==typeof n&&(n=p);var r=a(n,1);try{e="string"==typeof e?parseInt(e,8):e,s(t),t.chmod(e,r)}catch(i){r(i)}},t.fchmodSync=function(t,e){return e="string"==typeof e?parseInt(e,8):e,s(t),t.chmodSync(e)},t.futimes=function(t,e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{s(t),"number"==typeof e&&(e=new Date(1e3*e)),"number"==typeof n&&(n=new Date(1e3*n)),t.utimes(e,n,i)}catch(o){i(o)}},t.futimesSync=function(t,e,n){return s(t),"number"==typeof e&&(e=new Date(1e3*e)),"number"==typeof n&&(n=new Date(1e3*n)),t.utimesSync(e,n)},t.rmdir=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,1);try{e=f(e),t.root.rmdir(e,r)}catch(i){r(i)}},t.rmdirSync=function(e){return e=f(e),t.root.rmdirSync(e)},t.mkdir=function(e,n,r){"undefined"==typeof r&&(r=p),"function"==typeof n&&(r=n,n=511);var i=a(r,1);try{e=f(e),t.root.mkdir(e,n,i)}catch(o){i(o)}},t.mkdirSync=function(e,n){return"undefined"==typeof n&&(n=511),n="string"==typeof n?parseInt(n,8):n,e=f(e),t.root.mkdirSync(e,n)},t.readdir=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,2);try{e=f(e),t.root.readdir(e,r)}catch(i){r(i)}},t.readdirSync=function(e){return e=f(e),t.root.readdirSync(e)},t.link=function(e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{e=f(e),n=f(n),t.root.link(e,n,i)}catch(o){i(o)}},t.linkSync=function(e,n){return e=f(e),n=f(n),t.root.linkSync(e,n)},t.symlink=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o="string"==typeof r?r:"file";i="function"==typeof r?r:i;var s=a(i,1);try{if("file"!==o&&"dir"!==o)return s(new h(9,"Invalid type: "+o));e=f(e),n=f(n),t.root.symlink(e,n,o,s)}catch(u){s(u)}},t.symlinkSync=function(e,n,r){if(null==r)r="file";else if("file"!==r&&"dir"!==r)throw new h(9,"Invalid type: "+r);return e=f(e),n=f(n),t.root.symlinkSync(e,n,r)},t.readlink=function(e,n){"undefined"==typeof n&&(n=p);var r=a(n,2);try{e=f(e),t.root.readlink(e,r)}catch(i){r(i)}},t.readlinkSync=function(e){return e=f(e),t.root.readlinkSync(e)},t.chown=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o=a(i,1);try{e=f(e),t.root.chown(e,!1,n,r,o)}catch(s){o(s)}},t.chownSync=function(e,n,r){e=f(e),t.root.chownSync(e,!1,n,r)},t.lchown=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o=a(i,1);try{e=f(e),t.root.chown(e,!0,n,r,o)}catch(s){o(s)}},t.lchownSync=function(e,n,r){return e=f(e),t.root.chownSync(e,!0,n,r)},t.chmod=function(e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{n="string"==typeof n?parseInt(n,8):n,e=f(e),t.root.chmod(e,!1,n,i)}catch(o){i(o)}},t.chmodSync=function(e,n){return n="string"==typeof n?parseInt(n,8):n,e=f(e),t.root.chmodSync(e,!1,n)},t.lchmod=function(e,n,r){"undefined"==typeof r&&(r=p);var i=a(r,1);try{n="string"==typeof n?parseInt(n,8):n,e=f(e),t.root.chmod(e,!0,n,i)}catch(o){i(o)}},t.lchmodSync=function(e,n){return e=f(e),n="string"==typeof n?parseInt(n,8):n,t.root.chmodSync(e,!0,n)},t.utimes=function(e,n,r,i){"undefined"==typeof i&&(i=p);var o=a(i,1);try{e=f(e),"number"==typeof n&&(n=new Date(1e3*n)),"number"==typeof r&&(r=new Date(1e3*r)),t.root.utimes(e,n,r,o)}catch(s){o(s)}},t.utimesSync=function(e,n,r){return e=f(e),"number"==typeof n&&(n=new Date(1e3*n)),"number"==typeof r&&(r=new Date(1e3*r)),t.root.utimesSync(e,n,r)},t.realpath=function(e,n,r){"undefined"==typeof r&&(r=p);var i="object"==typeof n?n:{};r="function"==typeof n?n:p;var o=a(r,2);try{e=f(e),t.root.realpath(e,i,o)}catch(s){o(s)}},t.realpathSync=function(e,n){return"undefined"==typeof n&&(n={}),e=f(e),t.root.realpathSync(e,n)},t.root=null,t}();e.fs=g}),u("core/browserfs",["require","exports","./buffer","./node_fs","./node_path","./node_process"],function(t,e,n,r,i,o){function a(t){t.Buffer=n.Buffer,t.process=o.process;var r=null!=t.require?t.require:null;t.require=function(t){var n=e.BFSRequire(t);return null==n?r.apply(null,Array.prototype.slice.call(arguments,0)):n}}function s(t,n){e.FileSystem[t]=n}function u(t){switch(t){case"fs":return r.fs;case"path":return i.path;case"buffer":return n;case"process":return o.process;default:return e.FileSystem[t]}}function f(t){return r.fs._initialize(t)}e.install=a,e.FileSystem={},e.registerFileSystem=s,e.BFSRequire=u,e.initialize=f}),u("generic/emscripten_fs",["require","exports","../core/browserfs","../core/node_fs","../core/buffer","../core/buffer_core_arraybuffer"],function(t,e,n,r,i,o){var a=i.Buffer,s=o.BufferCoreArrayBuffer,u=r.fs,f=function(){function t(t){this.fs=t}return t.prototype.open=function(t){var e=this.fs.realPath(t.node);try{FS.isFile(t.node.mode)&&(t.nfd=u.openSync(e,this.fs.flagsToPermissionString(t.flags)))}catch(n){if(!n.code)throw n;throw new FS.ErrnoError(ERRNO_CODES[n.code])}},t.prototype.close=function(t){try{FS.isFile(t.node.mode)&&t.nfd&&u.closeSync(t.nfd)}catch(e){if(!e.code)throw e;throw new FS.ErrnoError(ERRNO_CODES[e.code])}},t.prototype.read=function(t,e,n,r,i){var o,f=new s(e.buffer),c=new a(f,e.byteOffset+n,e.byteOffset+n+r);try{o=u.readSync(t.nfd,c,0,r,i)}catch(p){throw new FS.ErrnoError(ERRNO_CODES[p.code])}return o},t.prototype.write=function(t,e,n,r,i){var o,f=new s(e.buffer),c=new a(f,e.byteOffset+n,e.byteOffset+n+r);try{o=u.writeSync(t.nfd,c,0,r,i)}catch(p){throw new FS.ErrnoError(ERRNO_CODES[p.code])}return o},t.prototype.llseek=function(t,e,n){var r=e;if(1===n)r+=t.position;else if(2===n&&FS.isFile(t.node.mode))try{var i=u.fstatSync(t.nfd);r+=i.size}catch(o){throw new FS.ErrnoError(ERRNO_CODES[o.code])}if(0>r)throw new FS.ErrnoError(ERRNO_CODES.EINVAL);return t.position=r,r},t}(),c=function(){function t(t){this.fs=t}return t.prototype.getattr=function(t){var e,n=this.fs.realPath(t);try{e=u.lstatSync(n)}catch(r){if(!r.code)throw r;throw new FS.ErrnoError(ERRNO_CODES[r.code])}return{dev:e.dev,ino:e.ino,mode:e.mode,nlink:e.nlink,uid:e.uid,gid:e.gid,rdev:e.rdev,size:e.size,atime:e.atime,mtime:e.mtime,ctime:e.ctime,blksize:e.blksize,blocks:e.blocks}},t.prototype.setattr=function(t,e){var n=this.fs.realPath(t);try{if(void 0!==e.mode&&(u.chmodSync(n,e.mode),t.mode=e.mode),void 0!==e.timestamp){var r=new Date(e.timestamp);u.utimesSync(n,r,r)}void 0!==e.size&&u.truncateSync(n,e.size)}catch(i){if(!i.code)throw i;if("ENOTSUP"===i.code)return;throw new FS.ErrnoError(ERRNO_CODES[i.code])}},t.prototype.lookup=function(t,e){var n=PATH.join2(this.fs.realPath(t),e),r=this.fs.getMode(n);return this.fs.createNode(t,e,r)},t.prototype.mknod=function(t,e,n,r){var i=this.fs.createNode(t,e,n,r),o=this.fs.realPath(i);try{FS.isDir(i.mode)?u.mkdirSync(o,i.mode):u.writeFileSync(o,"",{mode:i.mode})}catch(a){if(!a.code)throw a;throw new FS.ErrnoError(ERRNO_CODES[a.code])}return i},t.prototype.rename=function(t,e,n){var r=this.fs.realPath(t),i=PATH.join2(this.fs.realPath(e),n);try{u.renameSync(r,i)}catch(o){if(!o.code)throw o;throw new FS.ErrnoError(ERRNO_CODES[o.code])}},t.prototype.unlink=function(t,e){var n=PATH.join2(this.fs.realPath(t),e);try{u.unlinkSync(n)}catch(r){if(!r.code)throw r;throw new FS.ErrnoError(ERRNO_CODES[r.code])}},t.prototype.rmdir=function(t,e){var n=PATH.join2(this.fs.realPath(t),e);try{u.rmdirSync(n)}catch(r){if(!r.code)throw r;throw new FS.ErrnoError(ERRNO_CODES[r.code])}},t.prototype.readdir=function(t){var e=this.fs.realPath(t);try{return u.readdirSync(e)}catch(n){if(!n.code)throw n;throw new FS.ErrnoError(ERRNO_CODES[n.code])}},t.prototype.symlink=function(t,e,n){var r=PATH.join2(this.fs.realPath(t),e);try{u.symlinkSync(n,r)}catch(i){if(!i.code)throw i;throw new FS.ErrnoError(ERRNO_CODES[i.code])}},t.prototype.readlink=function(t){var e=this.fs.realPath(t);try{return u.readlinkSync(e)}catch(n){if(!n.code)throw n;throw new FS.ErrnoError(ERRNO_CODES[n.code])}},t}(),p=function(){function t(){if(this.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+"},this.node_ops=new c(this),this.stream_ops=new f(this),"undefined"==typeof n)throw new Error("BrowserFS is not loaded. Please load it before this library.")}return t.prototype.mount=function(t){return this.createNode(null,"/",this.getMode(t.opts.root),0)},t.prototype.createNode=function(t,e,n){if(!FS.isDir(n)&&!FS.isFile(n)&&!FS.isLink(n))throw new FS.ErrnoError(ERRNO_CODES.EINVAL);var r=FS.createNode(t,e,n);return r.node_ops=this.node_ops,r.stream_ops=this.stream_ops,r},t.prototype.getMode=function(t){var e;try{e=u.lstatSync(t)}catch(n){if(!n.code)throw n;throw new FS.ErrnoError(ERRNO_CODES[n.code])}return e.mode},t.prototype.realPath=function(t){for(var e=[];t.parent!==t;)e.push(t.name),t=t.parent;return e.push(t.mount.opts.root),e.reverse(),PATH.join.apply(null,e)},t.prototype.flagsToPermissionString=function(t){return t in this.flagsToPermissionStringMap?this.flagsToPermissionStringMap[t]:t},t}();e.BFSEmscriptenFS=p,n.EmscriptenFS=p});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("core/file_system",["require","exports","./api_error","./file_flag","./node_path","./buffer"],function(t,e,n,r,i,o){var a=n.ApiError;n.ErrorCode;var s=i.path,u=o.Buffer;r.ActionType;var c=function(){function t(){}return t.prototype.supportsLinks=function(){return!1},t.prototype.diskSpace=function(t,e){e(0,0)},t.prototype.openFile=function(){throw new a(14)},t.prototype.createFile=function(){throw new a(14)},t.prototype.open=function(t,e,n,r){var i=this,o=function(o,u){if(o)switch(e.pathNotExistsAction()){case 3:return i.stat(s.dirname(t),!1,function(o,u){o?r(o):u.isDirectory()?i.createFile(t,e,n,r):r(new a(7,s.dirname(t)+" is not a directory."))});case 1:return r(new a(1,""+t+" doesn't exist."));default:return r(new a(9,"Invalid FileFlag object."))}else{if(u.isDirectory())return r(new a(8,t+" is a directory."));switch(e.pathExistsAction()){case 1:return r(new a(6,t+" already exists."));case 2:return i.openFile(t,e,function(t,e){t?r(t):e.truncate(0,function(){e.sync(function(){r(null,e)})})});case 0:return i.openFile(t,e,r);default:return r(new a(9,"Invalid FileFlag object."))}}};this.stat(t,!1,o)},t.prototype.rename=function(t,e,n){n(new a(14))},t.prototype.renameSync=function(){throw new a(14)},t.prototype.stat=function(t,e,n){n(new a(14))},t.prototype.statSync=function(){throw new a(14)},t.prototype.openFileSync=function(){throw new a(14)},t.prototype.createFileSync=function(){throw new a(14)},t.prototype.openSync=function(t,e,n){var r;try{r=this.statSync(t,!1)}catch(i){switch(e.pathNotExistsAction()){case 3:var o=this.statSync(s.dirname(t),!1);if(!o.isDirectory())throw new a(7,s.dirname(t)+" is not a directory.");return this.createFileSync(t,e,n);case 1:throw new a(1,""+t+" doesn't exist.");default:throw new a(9,"Invalid FileFlag object.")}}if(r.isDirectory())throw new a(8,t+" is a directory.");switch(e.pathExistsAction()){case 1:throw new a(6,t+" already exists.");case 2:return this.unlinkSync(t),this.createFileSync(t,e,r.mode);case 0:return this.openFileSync(t,e);default:throw new a(9,"Invalid FileFlag object.")}},t.prototype.unlink=function(t,e){e(new a(14))},t.prototype.unlinkSync=function(){throw new a(14)},t.prototype.rmdir=function(t,e){e(new a(14))},t.prototype.rmdirSync=function(){throw new a(14)},t.prototype.mkdir=function(t,e,n){n(new a(14))},t.prototype.mkdirSync=function(){throw new a(14)},t.prototype.readdir=function(t,e){e(new a(14))},t.prototype.readdirSync=function(){throw new a(14)},t.prototype.exists=function(t,e){this.stat(t,null,function(t){e(null==t)})},t.prototype.existsSync=function(t){try{return this.statSync(t,!0),!0}catch(e){return!1}},t.prototype.realpath=function(t,e,n){if(this.supportsLinks())for(var r=t.split(s.sep),i=0;ithis._buffer.length){var e=new u(t-this._buffer.length);return e.fill(0),this.writeSync(e,0,e.length,this._buffer.length),this._flag.isSynchronous()&&s.getRootFS().supportsSynch()&&this.syncSync(),void 0}this._stat.size=t;var n=new u(t);this._buffer.copy(n,0,0,t),this._buffer=n,this._flag.isSynchronous()&&s.getRootFS().supportsSynch()&&this.syncSync()},e.prototype.write=function(t,e,n,r,i){try{i(null,this.writeSync(t,e,n,r),t)}catch(o){i(o)}},e.prototype.writeSync=function(t,e,n,r){if(null==r&&(r=this.getPos()),!this._flag.isWriteable())throw new a(0,"File not opened with a writeable mode.");var i=r+n;if(i>this._stat.size&&(this._stat.size=i,i>this._buffer.length)){var o=new u(i);this._buffer.copy(o),this._buffer=o}var s=t.copy(this._buffer,r,e,e+n);return this._stat.mtime=new Date,this._flag.isSynchronous()?(this.syncSync(),s):(this.setPos(r+s),s)},e.prototype.read=function(t,e,n,r,i){try{i(null,this.readSync(t,e,n,r),t)}catch(o){i(o)}},e.prototype.readSync=function(t,e,n,r){if(!this._flag.isReadable())throw new a(0,"File not opened with a readable mode.");null==r&&(r=this.getPos());var i=r+n;i>this._stat.size&&(n=this._stat.size-r);var o=this._buffer.copy(t,e,r,r+n);return this._stat.atime=new Date,this._pos=r+n,o},e.prototype.chmod=function(t,e){try{this.chmodSync(t),e()}catch(n){e(n)}},e.prototype.chmodSync=function(t){if(!this._fs.supportsProps())throw new a(14);this._stat.chmod(t),this.syncSync()},e}(n.BaseFile);e.PreloadFile=c;var p=function(t){function e(e,n,r,i,o){t.call(this,e,n,r,i,o)}return f(e,t),e.prototype.sync=function(t){t()},e.prototype.syncSync=function(){},e.prototype.close=function(t){t()},e.prototype.closeSync=function(){},e}(c);e.NoSyncFile=p});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("generic/key_value_filesystem",["require","exports","../core/file_system","../core/api_error","../core/node_fs_stats","../core/node_path","../generic/inode","../core/buffer","../generic/preload_file"],function(t,e,n,r,i,o,a,s,u){function c(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(t){var e=0|16*Math.random(),n="x"==t?e:8|3&e;return n.toString(16)})}function p(t,e){return t?(e(t),!1):!0}function h(t,e,n){return t?(e.abort(function(){n(t)}),!1):!0}var l="/",d=o.path,y=r.ApiError,g=s.Buffer,w=function(){function t(t){this.store=t,this.originalData={},this.modifiedKeys=[]}return t.prototype.stashOldValue=function(t,e){this.originalData.hasOwnProperty(t)||(this.originalData[t]=e)},t.prototype.markModified=function(t){-1===this.modifiedKeys.indexOf(t)&&(this.modifiedKeys.push(t),this.originalData.hasOwnProperty(t)||(this.originalData[t]=this.store.get(t)))},t.prototype.get=function(t){var e=this.store.get(t);return this.stashOldValue(t,e),e},t.prototype.put=function(t,e,n){return this.markModified(t),this.store.put(t,e,n)},t.prototype.delete=function(t){this.markModified(t),this.store.delete(t)},t.prototype.commit=function(){},t.prototype.abort=function(){var t,e,n;for(t=0;tr;)try{return n=c(),t.put(n,e,!1),n}catch(i){}throw new y(2,"Unable to commit data to key-value store.")},e.prototype.commitNewFile=function(t,e,n,r,i){var o=d.dirname(e),s=d.basename(e),u=this.findINode(t,o),f=this.getDirListing(t,o,u),c=(new Date).getTime();if("/"===e)throw y.EEXIST(e);if(f[s])throw y.EEXIST(e);try{var p=this.addNewNode(t,i),h=new a(p,i.length,r|n,c,c,c),l=this.addNewNode(t,h.toBuffer());f[s]=l,t.put(u.id,new g(JSON.stringify(f)),!0)}catch(w){throw t.abort(),w}return t.commit(),h},e.prototype.empty=function(){this.store.clear(),this.makeRootDirectory()},e.prototype.renameSync=function(t,e){var n=this.store.beginTransaction("readwrite"),r=d.dirname(t),i=d.basename(t),o=d.dirname(e),a=d.basename(e),s=this.findINode(n,r),u=this.getDirListing(n,r,s);if(!u[i])throw y.ENOENT(t);var f=u[i];if(delete u[i],0===(o+"/").indexOf(t+"/"))throw new y(5,r);var c,p;if(o===r?(c=s,p=u):(c=this.findINode(n,o),p=this.getDirListing(n,o,c)),p[a]){var h=this.getINode(n,e,p[a]);if(!h.isFile())throw y.EPERM(e);try{n.delete(h.id),n.delete(p[a])}catch(l){throw n.abort(),l}}p[a]=f;try{n.put(s.id,new g(JSON.stringify(u)),!0),n.put(c.id,new g(JSON.stringify(p)),!0)}catch(l){throw n.abort(),l}n.commit()},e.prototype.statSync=function(t){return this.findINode(this.store.beginTransaction("readonly"),t).toStats()},e.prototype.createFileSync=function(t,e,n){var r=this.store.beginTransaction("readwrite"),i=new g(0),o=this.commitNewFile(r,t,32768,n,i);return new m(this,t,e,o.toStats(),i)},e.prototype.openFileSync=function(t,e){var n=this.store.beginTransaction("readonly"),r=this.findINode(n,t),i=n.get(r.id);if(void 0===i)throw y.ENOENT(t);return new m(this,t,e,r.toStats(),i)},e.prototype.removeEntry=function(t,e){var n=this.store.beginTransaction("readwrite"),r=d.dirname(t),i=this.findINode(n,r),o=this.getDirListing(n,r,i),a=d.basename(t);if(!o[a])throw y.ENOENT(t);var s=o[a];delete o[a];var u=this.getINode(n,t,s);if(!e&&u.isDirectory())throw y.EISDIR(t);if(e&&!u.isDirectory())throw y.ENOTDIR(t);try{n.delete(u.id),n.delete(s),n.put(i.id,new g(JSON.stringify(o)),!0)}catch(f){throw n.abort(),f}n.commit()},e.prototype.unlinkSync=function(t){this.removeEntry(t,!1)},e.prototype.rmdirSync=function(t){this.removeEntry(t,!0)},e.prototype.mkdirSync=function(t,e){var n=this.store.beginTransaction("readwrite"),r=new g("{}");this.commitNewFile(n,t,16384,e,r)},e.prototype.readdirSync=function(t){var e=this.store.beginTransaction("readonly");return Object.keys(this.getDirListing(e,t,this.findINode(e,t)))},e.prototype._syncSync=function(t,e,n){var r=this.store.beginTransaction("readwrite"),i=this._findINode(r,d.dirname(t),d.basename(t)),o=this.getINode(r,t,i),a=o.update(n);try{r.put(o.id,e,!0),a&&r.put(i,o.toBuffer(),!0)}catch(s){throw r.abort(),s}r.commit()},e}(n.SynchronousFileSystem);e.SyncKeyValueFileSystem=v;var b=function(t){function e(e,n,r,i,o){t.call(this,e,n,r,i,o)}return f(e,t),e.prototype.sync=function(t){this._fs._sync(this._path,this._buffer,this._stat,t)},e.prototype.close=function(t){this.sync(t)},e}(u.PreloadFile);e.AsyncKeyValueFile=b;var E=function(t){function e(){t.apply(this,arguments)}return f(e,t),e.prototype.init=function(t,e){this.store=t,this.makeRootDirectory(e)},e.isAvailable=function(){return!0},e.prototype.getName=function(){return this.store.name()},e.prototype.isReadOnly=function(){return!1},e.prototype.supportsSymlinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!1},e.prototype.makeRootDirectory=function(t){var e=this.store.beginTransaction("readwrite");e.get(l,function(n,r){if(n||void 0===r){var i=(new Date).getTime(),o=new a(c(),4096,16895,i,i,i);e.put(o.id,new g("{}"),!1,function(n){h(n,e,t)&&e.put(l,o.toBuffer(),!1,function(n){n?e.abort(function(){t(n)}):e.commit(t)})})}else e.commit(t)})},e.prototype._findINode=function(t,e,n,r){var i=this,o=function(t,i,o){t?r(t):o[n]?r(null,o[n]):r(y.ENOENT(d.resolve(e,n)))};"/"===e?""===n?r(null,l):this.getINode(t,e,l,function(n,a){p(n,r)&&i.getDirListing(t,e,a,function(t,e){o(t,a,e)})}):this.findINodeAndDirListing(t,e,o)},e.prototype.findINode=function(t,e,n){var r=this;this._findINode(t,d.dirname(e),d.basename(e),function(i,o){p(i,n)&&r.getINode(t,e,o,n)})},e.prototype.getINode=function(t,e,n,r){t.get(n,function(t,n){p(t,r)&&(void 0===n?r(y.ENOENT(e)):r(null,a.fromBuffer(n)))})},e.prototype.getDirListing=function(t,e,n,r){n.isDirectory()?t.get(n.id,function(t,n){if(p(t,r))try{r(null,JSON.parse(n.toString()))}catch(t){r(y.ENOENT(e))}}):r(y.ENOTDIR(e))},e.prototype.findINodeAndDirListing=function(t,e,n){var r=this;this.findINode(t,e,function(i,o){p(i,n)&&r.getDirListing(t,e,o,function(t,e){p(t,n)&&n(null,o,e)})})},e.prototype.addNewNode=function(t,e,n){var r,i=0,o=function(){5===++i?n(new y(2,"Unable to commit data to key-value store.")):(r=c(),t.put(r,e,!1,function(t,e){t||!e?o():n(null,r)}))};o()},e.prototype.commitNewFile=function(t,e,n,r,i,o){var s=this,u=d.dirname(e),f=d.basename(e),c=(new Date).getTime();return"/"===e?o(y.EEXIST(e)):(this.findINodeAndDirListing(t,u,function(u,p,l){h(u,t,o)&&(l[f]?t.abort(function(){o(y.EEXIST(e))}):s.addNewNode(t,i,function(e,u){if(h(e,t,o)){var d=new a(u,i.length,r|n,c,c,c);s.addNewNode(t,d.toBuffer(),function(e,n){h(e,t,o)&&(l[f]=n,t.put(p.id,new g(JSON.stringify(l)),!0,function(e){h(e,t,o)&&t.commit(function(e){h(e,t,o)&&o(null,d)})}))})}}))}),void 0)},e.prototype.empty=function(t){var e=this;this.store.clear(function(n){p(n,t)&&e.makeRootDirectory(t)})},e.prototype.rename=function(t,e,n){var r=this,i=this.store.beginTransaction("readwrite"),o=d.dirname(t),a=d.basename(t),s=d.dirname(e),u=d.basename(e),f={},c={},p=!1;if(0===(s+"/").indexOf(t+"/"))return n(new y(5,o));var l=function(){if(!p&&c.hasOwnProperty(o)&&c.hasOwnProperty(s)){var l=c[o],d=f[o],w=c[s],m=f[s];if(l[a]){var v=l[a];delete l[a];var b=function(){w[u]=v,i.put(d.id,new g(JSON.stringify(l)),!0,function(t){h(t,i,n)&&(o===s?i.commit(n):i.put(m.id,new g(JSON.stringify(w)),!0,function(t){h(t,i,n)&&i.commit(n)}))})};w[u]?r.getINode(i,e,w[u],function(t,r){h(t,i,n)&&(r.isFile()?i.delete(r.id,function(t){h(t,i,n)&&i.delete(w[u],function(t){h(t,i,n)&&b()})}):i.abort(function(){n(y.EPERM(e))}))}):b()}else n(y.ENOENT(t))}},w=function(t){r.findINodeAndDirListing(i,t,function(e,r,o){e?p||(p=!0,i.abort(function(){n(e)})):(f[t]=r,c[t]=o,l())})};w(o),o!==s&&w(s)},e.prototype.stat=function(t,e,n){var r=this.store.beginTransaction("readonly");this.findINode(r,t,function(t,e){p(t,n)&&n(null,e.toStats())})},e.prototype.createFile=function(t,e,n,r){var i=this,o=this.store.beginTransaction("readwrite"),a=new g(0);this.commitNewFile(o,t,32768,n,a,function(n,o){p(n,r)&&r(null,new b(i,t,e,o.toStats(),a))})},e.prototype.openFile=function(t,e,n){var r=this,i=this.store.beginTransaction("readonly");this.findINode(i,t,function(o,a){p(o,n)&&i.get(a.id,function(i,o){p(i,n)&&(void 0===o?n(y.ENOENT(t)):n(null,new b(r,t,e,a.toStats(),o)))})})},e.prototype.removeEntry=function(t,e,n){var r=this,i=this.store.beginTransaction("readwrite"),o=d.dirname(t),a=d.basename(t);this.findINodeAndDirListing(i,o,function(o,s,u){if(h(o,i,n))if(u[a]){var f=u[a];delete u[a],r.getINode(i,t,f,function(r,o){h(r,i,n)&&(!e&&o.isDirectory()?i.abort(function(){n(y.EISDIR(t))}):e&&!o.isDirectory()?i.abort(function(){n(y.ENOTDIR(t))}):i.delete(o.id,function(t){h(t,i,n)&&i.delete(f,function(t){h(t,i,n)&&i.put(s.id,new g(JSON.stringify(u)),!0,function(t){h(t,i,n)&&i.commit(n)})})}))})}else i.abort(function(){n(y.ENOENT(t))})})},e.prototype.unlink=function(t,e){this.removeEntry(t,!1,e)},e.prototype.rmdir=function(t,e){this.removeEntry(t,!0,e)},e.prototype.mkdir=function(t,e,n){var r=this.store.beginTransaction("readwrite"),i=new g("{}");this.commitNewFile(r,t,16384,e,i,n)},e.prototype.readdir=function(t,e){var n=this,r=this.store.beginTransaction("readonly");this.findINode(r,t,function(i,o){p(i,e)&&n.getDirListing(r,t,o,function(t,n){p(t,e)&&e(null,Object.keys(n))})})},e.prototype._sync=function(t,e,n,r){var i=this,o=this.store.beginTransaction("readwrite");this._findINode(o,d.dirname(t),d.basename(t),function(a,s){h(a,o,r)&&i.getINode(o,t,s,function(t,i){if(h(t,o,r)){var a=i.update(n);o.put(i.id,e,!0,function(t){h(t,o,r)&&(a?o.put(s,i.toBuffer(),!0,function(t){h(t,o,r)&&o.commit(r)}):o.commit(r))})}})})},e}(n.BaseFileSystem);e.AsyncKeyValueFileSystem=E}),u("core/global",["require","exports"],function(){var t;return t="undefined"!=typeof window?window:"undefined"!=typeof self?self:global});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("backend/IndexedDB",["require","exports","../core/buffer","../core/browserfs","../generic/key_value_filesystem","../core/api_error","../core/buffer_core_arraybuffer","../core/global"],function(t,e,n,r,i,o,a,s){function u(t,e){switch("undefined"==typeof e&&(e=t.toString()),t.name){case"NotFoundError":return new l(1,e);case"QuotaExceededError":return new l(11,e);default:return new l(2,e)}}function c(t,e,n){return"undefined"==typeof e&&(e=2),"undefined"==typeof n&&(n=null),function(r){r.preventDefault(),t(new l(e,n))}}function p(t){var e=t.getBufferCore();e instanceof a.BufferCoreArrayBuffer||(t=new h(this._buffer.length),this._buffer.copy(t),e=t.getBufferCore());var n=e.getDataView();return n.buffer}var h=n.Buffer,l=o.ApiError,d=(o.ErrorCode,s.indexedDB||s.mozIndexedDB||s.webkitIndexedDB||s.msIndexedDB),y=function(){function t(t,e){this.tx=t,this.store=e}return t.prototype.get=function(t,e){try{var n=this.store.get(t);n.onerror=c(e),n.onsuccess=function(t){var n=t.target.result;void 0===n?e(null,n):e(null,new h(n))}}catch(r){e(u(r))}},t}();e.IndexedDBROTransaction=y;var g=function(t){function e(e,n){t.call(this,e,n)}return f(e,t),e.prototype.put=function(t,e,n,r){try{var i,o=p(e);i=n?this.store.put(o,t):this.store.add(o,t),i.onerror=c(r),i.onsuccess=function(){r(null,!0)}}catch(a){r(u(a))}},e.prototype.delete=function(t,e){try{var n=this.store.delete(t);n.onerror=c(e),n.onsuccess=function(){e()}}catch(r){e(u(r))}},e.prototype.commit=function(t){setTimeout(t,0)},e.prototype.abort=function(t){var e;try{this.tx.abort()}catch(n){e=u(n)}finally{t(e)}},e}(y);e.IndexedDBRWTransaction=g;var w=function(){function t(t,e){"undefined"==typeof e&&(e="browserfs");var n=this;this.storeName=e;var r=d.open(this.storeName,1);r.onupgradeneeded=function(t){var e=t.target.result;e.objectStoreNames.contains(n.storeName)&&e.deleteObjectStore(n.storeName),e.createObjectStore(n.storeName)},r.onsuccess=function(e){n.db=e.target.result,t(null,n)},r.onerror=c(t,4)}return t.prototype.name=function(){return"IndexedDB - "+this.storeName},t.prototype.clear=function(t){try{var e=this.db.transaction(this.storeName,"readwrite"),n=e.objectStore(this.storeName),r=n.clear();r.onsuccess=function(){setTimeout(t,0)},r.onerror=c(t)}catch(i){t(u(i))}},t.prototype.beginTransaction=function(t){"undefined"==typeof t&&(t="readonly");var e=this.db.transaction(this.storeName,t),n=e.objectStore(this.storeName);if("readwrite"===t)return new g(e,n);if("readonly"===t)return new y(e,n);throw new l(9,"Invalid transaction type.")},t}();e.IndexedDBStore=w;var m=function(t){function e(e,n){var r=this;t.call(this),new w(function(t,n){t?e(t):r.init(n,function(t){e(t,r)})},n)}return f(e,t),e.isAvailable=function(){return"undefined"!=typeof d},e}(i.AsyncKeyValueFileSystem);e.IndexedDBFileSystem=m,r.registerFileSystem("IndexedDB",m)}),u("generic/file_index",["require","exports","../core/node_fs_stats","../core/node_path"],function(t,e,n,r){var i=n.Stats,o=r.path,a=function(){function t(){this._index={},this.addPath("/",new u)}return t.prototype._split_path=function(t){var e=o.dirname(t),n=t.substr(e.length+("/"===e?0:1));return[e,n]},t.prototype.fileIterator=function(t){for(var e in this._index)for(var n=this._index[e],r=n.getListing(),i=0;i0;){var a,f=o.pop(),c=f[0],p=f[1],h=f[2];for(var l in p){var d=p[l],y=""+c+"/"+l;null!=d?(n._index[y]=a=new u,o.push([y,d,a])):a=new s(new i(32768,-1,365)),null!=h&&(h._ls[l]=a)}}return n},t}();e.FileIndex=a;var s=function(){function t(t){this.data=t}return t.prototype.isFile=function(){return!0},t.prototype.isDir=function(){return!1},t.prototype.getData=function(){return this.data},t.prototype.setData=function(t){this.data=t},t}();e.FileInode=s;var u=function(){function t(){this._ls={}}return t.prototype.isFile=function(){return!1},t.prototype.isDir=function(){return!0},t.prototype.getStats=function(){return new i(16384,4096,365)},t.prototype.getListing=function(){return Object.keys(this._ls)},t.prototype.getItem=function(t){var e;return null!=(e=this._ls[t])?e:null},t.prototype.addItem=function(t,e){return t in this._ls?!1:(this._ls[t]=e,!0)},t.prototype.remItem=function(t){var e=this._ls[t];return void 0===e?null:(delete this._ls[t],e)},t}();e.DirInode=u}),u("core/util",["require","exports"],function(t,e){function n(t){var e,n,r,i,o,a;for(r=[],o=[t],e=0;0!==o.length;)if(a=o.pop(),"boolean"==typeof a)e+=4;else if("string"==typeof a)e+=2*a.length;else if("number"==typeof a)e+=8;else if("object"==typeof a&&r.indexOf(a)<0){r.push(a),e+=4;for(n in a)i=a[n],e+=2*n.length,o.push(i)}return e}e.roughSizeOfObject=n,e.isIE=null!=/(msie) ([\w.]+)/.exec(navigator.userAgent.toLowerCase())||-1!==navigator.userAgent.indexOf("Trident")}),u("generic/xhr",["require","exports","../core/util","../core/buffer","../core/api_error"],function(t,e,n,r,i){function o(t){for(var e=IEBinaryToArray_ByteStr(t),n=IEBinaryToArray_ByteStr_Last(t),r=e.replace(/[\s\S]/g,function(t){var e=t.charCodeAt(0);return String.fromCharCode(255&e,e>>8)})+n,i=new Array(r.length),o=0;o0&&"/"!==n.charAt(n.length-1)&&(n+="/");var i=this._requestFileSync(e,"json");if(null==i)throw new Error("Unable to find listing at URL: "+e);this._index=r.FileIndex.from_listing(i)}return f(e,t),e.prototype.empty=function(){this._index.fileIterator(function(t){t.file_data=null})},e.prototype.getXhrPath=function(t){return"/"===t.charAt(0)&&(t=t.slice(1)),this.prefix_url+t},e.prototype._requestFileSizeAsync=function(t,e){c.getFileSizeAsync(this.getXhrPath(t),e)},e.prototype._requestFileSizeSync=function(t){return c.getFileSizeSync(this.getXhrPath(t))},e.prototype._requestFileAsync=function(t,e,n){c.asyncDownloadFile(this.getXhrPath(t),e,n)},e.prototype._requestFileSync=function(t,e){return c.syncDownloadFile(this.getXhrPath(t),e)},e.prototype.getName=function(){return"XmlHttpRequest"},e.isAvailable=function(){return"undefined"!=typeof XMLHttpRequest&&null!==XMLHttpRequest},e.prototype.diskSpace=function(t,e){e(0,0)},e.prototype.isReadOnly=function(){return!0},e.prototype.supportsLinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!0},e.prototype.preloadFile=function(t,e){var n=this._index.getInode(t);if(null===n)throw p.ENOENT(t);var r=n.getData();r.size=e.length,r.file_data=e},e.prototype.stat=function(t,e,n){var r=this._index.getInode(t);if(null===r)return n(p.ENOENT(t));var i;r.isFile()?(i=r.getData(),i.size<0?this._requestFileSizeAsync(t,function(t,e){return t?n(t):(i.size=e,n(null,i.clone()),void 0)}):n(null,i.clone())):(i=r.getStats(),n(null,i))},e.prototype.statSync=function(t){var e=this._index.getInode(t);if(null===e)throw p.ENOENT(t);var n;return e.isFile()?(n=e.getData(),n.size<0&&(n.size=this._requestFileSizeSync(t))):n=e.getStats(),n},e.prototype.open=function(t,e,n,r){if(e.isWriteable())return r(new p(0,t));var i=this,o=this._index.getInode(t);if(null===o)return r(p.ENOENT(t));if(o.isDir())return r(p.EISDIR(t));var a=o.getData();switch(e.pathExistsAction()){case 1:case 2:return r(p.EEXIST(t));case 0:if(null!=a.file_data)return r(null,new s.NoSyncFile(i,t,e,a.clone(),a.file_data));this._requestFileAsync(t,"buffer",function(n,o){return n?r(n):(a.size=o.length,a.file_data=o,r(null,new s.NoSyncFile(i,t,e,a.clone(),o)))});break;default:return r(new p(9,"Invalid FileMode object."))}},e.prototype.openSync=function(t,e){if(e.isWriteable())throw new p(0,t);var n=this._index.getInode(t);if(null===n)throw p.ENOENT(t);if(n.isDir())throw p.EISDIR(t);var r=n.getData();switch(e.pathExistsAction()){case 1:case 2:throw p.EEXIST(t);case 0:if(null!=r.file_data)return new s.NoSyncFile(this,t,e,r.clone(),r.file_data);var i=this._requestFileSync(t,"buffer");return r.size=i.length,r.file_data=i,new s.NoSyncFile(this,t,e,r.clone(),i);default:throw new p(9,"Invalid FileMode object.")}},e.prototype.readdir=function(t,e){try{e(null,this.readdirSync(t))}catch(n){e(n)}},e.prototype.readdirSync=function(t){var e=this._index.getInode(t);if(null===e)throw p.ENOENT(t);if(e.isFile())throw p.ENOTDIR(t);return e.getListing()},e.prototype.readFile=function(t,e,n,r){var o=r;this.open(t,n,420,function(t,n){if(t)return r(t);r=function(t,e){n.close(function(n){return null==t&&(t=n),o(t,e)})}; +var a=n,s=a._buffer;if(null===e)return s.length>0?r(t,s.sliceCopy()):r(t,new i.Buffer(0));try{r(null,s.toString(e))}catch(u){r(u)}})},e.prototype.readFileSync=function(t,e,n){var r=this.openSync(t,n,420);try{var o=r,a=o._buffer;return null===e?a.length>0?a.sliceCopy():new i.Buffer(0):a.toString(e)}finally{r.closeSync()}},e}(n.BaseFileSystem);e.XmlHttpRequest=h,u.registerFileSystem("XmlHttpRequest",h)}),function(){function t(t){var n=!1;return function(){if(n)throw new Error("Callback was already called.");n=!0,t.apply(e,arguments)}}var e,n,r={};e=this,null!=e&&(n=e.async),r.noConflict=function(){return e.async=n,r};var i=function(t,e){if(t.forEach)return t.forEach(e);for(var n=0;n=e.length&&r(null))}))})},r.forEach=r.each,r.eachSeries=function(t,e,n){if(n=n||function(){},!t.length)return n();var r=0,i=function(){e(t[r],function(e){e?(n(e),n=function(){}):(r+=1,r>=t.length?n(null):i())})};i()},r.forEachSeries=r.eachSeries,r.eachLimit=function(t,e,n,r){var i=f(e);i.apply(null,[t,n,r])},r.forEachLimit=r.eachLimit;var f=function(t){return function(e,n,r){if(r=r||function(){},!e.length||0>=t)return r();var i=0,o=0,a=0;!function s(){if(i>=e.length)return r();for(;t>a&&o=e.length?r():s())})}()}},c=function(t){return function(){var e=Array.prototype.slice.call(arguments);return t.apply(null,[r.each].concat(e))}},p=function(t,e){return function(){var n=Array.prototype.slice.call(arguments);return e.apply(null,[f(t)].concat(n))}},h=function(t){return function(){var e=Array.prototype.slice.call(arguments);return t.apply(null,[r.eachSeries].concat(e))}},l=function(t,e,n,r){var i=[];e=o(e,function(t,e){return{index:e,value:t}}),t(e,function(t,e){n(t.value,function(n,r){i[t.index]=r,e(n)})},function(t){r(t,i)})};r.map=c(l),r.mapSeries=h(l),r.mapLimit=function(t,e,n,r){return d(e)(t,n,r)};var d=function(t){return p(t,l)};r.reduce=function(t,e,n,i){r.eachSeries(t,function(t,r){n(e,t,function(t,n){e=n,r(t)})},function(t){i(t,e)})},r.inject=r.reduce,r.foldl=r.reduce,r.reduceRight=function(t,e,n,i){var a=o(t,function(t){return t}).reverse();r.reduce(a,e,n,i)},r.foldr=r.reduceRight;var y=function(t,e,n,r){var i=[];e=o(e,function(t,e){return{index:e,value:t}}),t(e,function(t,e){n(t.value,function(n){n&&i.push(t),e()})},function(){r(o(i.sort(function(t,e){return t.index-e.index}),function(t){return t.value}))})};r.filter=c(y),r.filterSeries=h(y),r.select=r.filter,r.selectSeries=r.filterSeries;var g=function(t,e,n,r){var i=[];e=o(e,function(t,e){return{index:e,value:t}}),t(e,function(t,e){n(t.value,function(n){n||i.push(t),e()})},function(){r(o(i.sort(function(t,e){return t.index-e.index}),function(t){return t.value}))})};r.reject=c(g),r.rejectSeries=h(g);var w=function(t,e,n,r){t(e,function(t,e){n(t,function(n){n?(r(t),r=function(){}):e()})},function(){r()})};r.detect=c(w),r.detectSeries=h(w),r.some=function(t,e,n){r.each(t,function(t,r){e(t,function(t){t&&(n(!0),n=function(){}),r()})},function(){n(!1)})},r.any=r.some,r.every=function(t,e,n){r.each(t,function(t,r){e(t,function(t){t||(n(!1),n=function(){}),r()})},function(){n(!0)})},r.all=r.every,r.sortBy=function(t,e,n){r.map(t,function(t,n){e(t,function(e,r){e?n(e):n(null,{value:t,criteria:r})})},function(t,e){if(t)return n(t);var r=function(t,e){var n=t.criteria,r=e.criteria;return r>n?-1:n>r?1:0};n(null,o(e.sort(r),function(t){return t.value}))})},r.auto=function(t,e){e=e||function(){};var n=s(t);if(!n.length)return e(null);var o={},u=[],f=function(t){u.unshift(t)},c=function(t){for(var e=0;ee;e++)t[e].apply(null,arguments)}])))};return i.memo=n,i.unmemoized=t,i},r.unmemoize=function(t){return function(){return(t.unmemoized||t).apply(null,arguments)}},r.times=function(t,e,n){for(var i=[],o=0;t>o;o++)i.push(o);return r.map(i,e,n)},r.timesSeries=function(t,e,n){for(var i=[],o=0;t>o;o++)i.push(o);return r.mapSeries(i,e,n)},r.compose=function(){var t=Array.prototype.reverse.call(arguments);return function(){var e=this,n=Array.prototype.slice.call(arguments),i=n.pop();r.reduce(t,n,function(t,n,r){n.apply(e,t.concat([function(){var t=arguments[0],e=Array.prototype.slice.call(arguments,1);r(t,e)}]))},function(t,n){i.apply(e,[t].concat(n))})}};var E=function(t,e){var n=function(){var n=this,r=Array.prototype.slice.call(arguments),i=r.pop();return t(e,function(t,e){t.apply(n,r.concat([e]))},i)};if(arguments.length>2){var r=Array.prototype.slice.call(arguments,2);return n.apply(this,r)}return n};r.applyEach=c(E),r.applyEachSeries=h(E),r.forever=function(t,e){function n(r){if(r){if(e)return e(r);throw r}t(n)}n()},"undefined"!=typeof u&&u.amd?u("async",[],function(){return r}):"undefined"!=typeof module&&module.exports?module.exports=r:e.async=r}();var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("backend/dropbox",["require","exports","../generic/preload_file","../core/file_system","../core/node_fs_stats","../core/buffer","../core/api_error","../core/node_path","../core/browserfs","../core/buffer_core_arraybuffer","async"],function(t,e,n,r,i,o,a,s,u,c){var p=o.Buffer,h=i.Stats,l=a.ApiError;a.ErrorCode;var d=s.path;i.FileType;var y=t("async"),p=o.Buffer,g=function(t){function e(e,n,r,i,o){t.call(this,e,n,r,i,o)}return f(e,t),e.prototype.sync=function(t){var e=this._buffer,n=this._buffer.getBufferCore();n instanceof c.BufferCoreArrayBuffer||(e=new p(this._buffer.length),this._buffer.copy(e),n=e.getBufferCore());var r=n.getDataView(),i=new DataView(r.buffer,r.byteOffset+e.getOffset(),e.length);this._fs._writeFileStrict(this._path,i,t)},e.prototype.close=function(t){this.sync(t)},e}(n.PreloadFile);e.DropboxFile=g;var w=function(t){function e(e){t.call(this),this.client=e}return f(e,t),e.prototype.getName=function(){return"Dropbox"},e.isAvailable=function(){return"undefined"!=typeof Dropbox},e.prototype.isReadOnly=function(){return!1},e.prototype.supportsSymlinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!1},e.prototype.empty=function(t){var e=this;this.client.readdir("/",function(n,r,i,o){if(n)t(e.convert(n));else{var a=function(t,n){e.client.remove(t.path,function(t){n(t?e.convert(t):t)})},s=function(n){n?t(e.convert(n)):t()};y.each(o,a,s)}})},e.prototype.rename=function(t,e,n){this.client.move(t,e,function(r){if(r){var i=r.response.error.indexOf(t)>-1?t:e;n(new l(1,i+" doesn't exist"))}else n()})},e.prototype.stat=function(t,e,n){var r=this;this.client.stat(t,function(e,i){if(!(e||null!=i&&i.isRemoved)){var o=new h(r._statType(i),i.size);return n(null,o)}n(new l(1,t+" doesn't exist"))})},e.prototype.open=function(t,e,n,r){var i=this;this.client.readFile(t,{arrayBuffer:!0},function(n,o,a){if(!n){var s;s=null===o?new p(0):new p(o);var u=i._makeFile(t,e,a,s);return r(null,u)}if(e.isReadable())r(new l(1,t+" doesn't exist"));else switch(n.status){case 0:return console.error("No connection");case 404:var f=new ArrayBuffer(0);return i._writeFileStrict(t,f,function(n,o){if(n)r(n);else{var a=i._makeFile(t,e,o,new p(f));r(null,a)}});default:return console.log("Unhandled error: "+n)}})},e.prototype._writeFileStrict=function(t,e,n){var r=this,i=d.dirname(t);this.stat(i,!1,function(o){o?n(new l(1,"Can't create "+t+" because "+i+" doesn't exist")):r.client.writeFile(t,e,function(t,e){t?n(r.convert(t)):n(null,e)})})},e.prototype._statType=function(t){return t.isFile?32768:16384},e.prototype._makeFile=function(t,e,n,r){var i=this._statType(n),o=new h(i,n.size);return new g(this,t,e,o,r)},e.prototype._remove=function(t,e,n){var r=this;this.client.stat(t,function(i,o){i?e(new l(1,t+" doesn't exist")):o.isFile&&!n?e(new l(7,t+" is a file.")):!o.isFile&&n?e(new l(8,t+" is a directory.")):r.client.remove(t,function(n){n?e(new l(2,"Failed to remove "+t)):e(null)})})},e.prototype.unlink=function(t,e){this._remove(t,e,!0)},e.prototype.rmdir=function(t,e){this._remove(t,e,!1)},e.prototype.mkdir=function(t,e,n){var r=this,i=d.dirname(t);this.client.stat(i,function(e){e?n(new l(1,"Can't create "+t+" because "+i+" doesn't exist")):r.client.mkdir(t,function(e){e?n(new l(6,t+" already exists")):n(null)})})},e.prototype.readdir=function(t,e){var n=this;this.client.readdir(t,function(t,r){return t?e(n.convert(t)):e(null,r)})},e.prototype.convert=function(t,e){switch("undefined"==typeof e&&(e=""),t.status){case 400:return new l(9,e);case 401:case 403:return new l(2,e);case 404:return new l(1,e);case 405:return new l(14,e);case 0:case 304:case 406:case 409:default:return new l(2,e)}},e}(r.BaseFileSystem);e.DropboxFileSystem=w,u.registerFileSystem("Dropbox",w)});var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("backend/html5fs",["require","exports","../generic/preload_file","../core/file_system","../core/api_error","../core/file_flag","../core/node_fs_stats","../core/buffer","../core/browserfs","../core/buffer_core_arraybuffer","../core/node_path","../core/global","async"],function(t,e,n,r,i,o,a,s,u,c,p,h){function l(t,e,n,r){if("undefined"!=typeof navigator.webkitPersistentStorage)switch(t){case h.PERSISTENT:navigator.webkitPersistentStorage.requestQuota(e,n,r);break;case h.TEMPORARY:navigator.webkitTemporaryStorage.requestQuota(e,n,r);break;default:r(null)}else h.webkitStorageInfo.requestQuota(t,e,n,r)}function d(t){return Array.prototype.slice.call(t||[],0)}var y=s.Buffer,g=a.Stats;a.FileType;var w=i.ApiError;i.ErrorCode,o.ActionType;var m=t("async"),v=h.webkitRequestFileSystem||h.requestFileSystem||null,b=function(t){function e(e,n,r,i,o){t.call(this,e,n,r,i,o)}return f(e,t),e.prototype.sync=function(t){var e=this,n={create:!1},r=this._fs,i=function(n){n.createWriter(function(n){var i=e._buffer,o=e._buffer.getBufferCore();o instanceof c.BufferCoreArrayBuffer||(i=new y(e._buffer.length),e._buffer.copy(i),o=i.getBufferCore());var a=o.getDataView(),s=new DataView(a.buffer,a.byteOffset+i.getOffset(),i.length),u=new Blob([s]),f=u.size;n.onwriteend=function(){n.onwriteend=null,n.truncate(f),t()},n.onerror=function(e){t(r.convert(e))},n.write(u)})},o=function(e){t(r.convert(e))};r.fs.root.getFile(this._path,n,i,o)},e.prototype.close=function(t){this.sync(t)},e}(n.PreloadFile);e.HTML5FSFile=b;var E=function(t){function e(e,n){t.call(this),this.size=null!=e?e:5,this.type=null!=n?n:h.PERSISTENT;var r=1024,i=r*r;this.size*=i}return f(e,t),e.prototype.getName=function(){return"HTML5 FileSystem"},e.isAvailable=function(){return null!=v},e.prototype.isReadOnly=function(){return!1},e.prototype.supportsSymlinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!1},e.prototype.convert=function(t,e){switch("undefined"==typeof e&&(e=""),t.name){case"QuotaExceededError":return new w(11,e);case"NotFoundError":return new w(1,e);case"SecurityError":return new w(4,e);case"InvalidModificationError":return new w(0,e);case"SyntaxError":case"TypeMismatchError":return new w(9,e);default:return new w(9,e)}},e.prototype.convertErrorEvent=function(t,e){return"undefined"==typeof e&&(e=""),new w(1,t.message+"; "+e)},e.prototype.allocate=function(t){var e=this;"undefined"==typeof t&&(t=function(){});var n=function(n){e.fs=n,t()},r=function(n){t(e.convert(n))};this.type===h.PERSISTENT?l(this.type,this.size,function(t){v(e.type,t,n,r)},r):v(this.type,this.size,n,r)},e.prototype.empty=function(t){var e=this;this._readdir("/",function(n,r){if(n)console.error("Failed to empty FS"),t(n);else{var i=function(){n?(console.error("Failed to empty FS"),t(n)):t()},o=function(t,n){var r=function(){n()},i=function(r){n(e.convert(r,t.fullPath))};t.isFile?t.remove(r,i):t.removeRecursively(r,i)};m.each(r,o,i)}})},e.prototype.rename=function(t,e,n){var r=this,i=2,o=0,a=this.fs.root,s=function(o){0===--i&&n(r.convert(o,"Failed to rename "+t+" to "+e+"."))},u=function(i){return 2===++o?(console.error("Something was identified as both a file and a directory. This should never happen."),void 0):t===e?n():(a.getDirectory(p.path.dirname(e),{},function(o){i.moveTo(o,p.path.basename(e),function(){n()},function(o){i.isDirectory?r.unlink(e,function(i){i?s(o):r.rename(t,e,n)}):s(o)})},s),void 0)};a.getFile(t,{},u,s),a.getDirectory(t,{},u,s)},e.prototype.stat=function(t,e,n){var r=this,i={create:!1},o=function(t){var e=function(t){var e=new g(32768,t.size);n(null,e)};t.file(e,s)},a=function(){var t=4096,e=new g(16384,t);n(null,e)},s=function(e){n(r.convert(e,t))},u=function(){r.fs.root.getDirectory(t,i,a,s)};this.fs.root.getFile(t,i,o,u)},e.prototype.open=function(t,e,n,r){var i=this,o={create:3===e.pathNotExistsAction(),exclusive:e.isExclusive()},a=function(e){r(i.convertErrorEvent(e,t))},s=function(e){r(i.convert(e,t))},u=function(n){var o=function(n){var o=new FileReader;o.onloadend=function(){var a=i._makeFile(t,e,n,o.result);r(null,a)},o.onerror=a,o.readAsArrayBuffer(n)};n.file(o,s)};this.fs.root.getFile(t,o,u,a)},e.prototype._statType=function(t){return t.isFile?32768:16384},e.prototype._makeFile=function(t,e,n,r){"undefined"==typeof r&&(r=new ArrayBuffer(0));var i=new g(32768,n.size),o=new y(r);return new b(this,t,e,i,o)},e.prototype._remove=function(t,e,n){var r=this,i=function(n){var i=function(){e()},o=function(n){e(r.convert(n,t))};n.remove(i,o)},o=function(n){e(r.convert(n,t))},a={create:!1};n?this.fs.root.getFile(t,a,i,o):this.fs.root.getDirectory(t,a,i,o)},e.prototype.unlink=function(t,e){this._remove(t,e,!0)},e.prototype.rmdir=function(t,e){this._remove(t,e,!1)},e.prototype.mkdir=function(t,e,n){var r=this,i={create:!0,exclusive:!0},o=function(){n()},a=function(e){n(r.convert(e,t))};this.fs.root.getDirectory(t,i,o,a)},e.prototype._readdir=function(t,e){var n=this;this.fs.root.getDirectory(t,{create:!1},function(r){var i=r.createReader(),o=[],a=function(r){e(n.convert(r,t))},s=function(){i.readEntries(function(t){t.length?(o=o.concat(d(t)),s()):e(null,o)},a)};s()})},e.prototype.readdir=function(t,e){this._readdir(t,function(t,n){if(null!=t)return e(t);for(var r=[],i=0;i0&&t[0]instanceof i.ApiError&&s.standardizeError(t[0],o.path,r),a.apply(null,t)}}return o.fs[t].apply(o.fs,e)}}var u=i.ApiError;i.ErrorCode;var c=o.fs,p=function(t){function e(){t.call(this),this.mntMap={},this.rootFs=new r.InMemoryFileSystem}return f(e,t),e.prototype.mount=function(t,e){if(this.mntMap[t])throw new u(9,"Mount point "+t+" is already taken.");this.rootFs.mkdirSync(t,511),this.mntMap[t]=e},e.prototype.umount=function(t){if(!this.mntMap[t])throw new u(9,"Mount point "+t+" is already unmounted.");delete this.mntMap[t],this.rootFs.rmdirSync(t)},e.prototype._get_fs=function(t){for(var e in this.mntMap){var n=this.mntMap[e];if(0===t.indexOf(e))return t=t.substr(e.length>1?e.length:0),""===t&&(t="/"),{fs:n,path:t}}return{fs:this.rootFs,path:t}},e.prototype.getName=function(){return"MountableFileSystem"},e.isAvailable=function(){return!0},e.prototype.diskSpace=function(t,e){e(0,0)},e.prototype.isReadOnly=function(){return!1},e.prototype.supportsLinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!0},e.prototype.standardizeError=function(t,e,n){var r;return-1!==(r=t.message.indexOf(e))&&(t.message=t.message.substr(0,r)+n+t.message.substr(r+e.length)),t},e.prototype.rename=function(t,e,n){var r=this._get_fs(t),i=this._get_fs(e);if(r.fs===i.fs){var o=this;return r.fs.rename(r.path,i.path,function(a){a&&o.standardizeError(o.standardizeError(a,r.path,t),i.path,e),n(a)})}return c.readFile(t,function(r,i){return r?n(r):(c.writeFile(e,i,function(e){return e?n(e):(c.unlink(t,n),void 0)}),void 0)})},e.prototype.renameSync=function(t,e){var n=this._get_fs(t),r=this._get_fs(e);if(n.fs===r.fs)try{return n.fs.renameSync(n.path,r.path)}catch(i){throw this.standardizeError(this.standardizeError(i,n.path,t),r.path,e),i}var o=c.readFileSync(t);return c.writeFileSync(e,o),c.unlinkSync(t)},e}(n.BaseFileSystem);e.MountableFileSystem=p;for(var h=[["readdir","exists","unlink","rmdir","readlink"],["stat","mkdir","realpath","truncate"],["open","readFile","chmod","utimes"],["chown"],["writeFile","appendFile"]],l=0;lf;++f)t[f]>h&&(h=t[f]),t[f]=r;){for(f=0;p>f;++f)if(t[f]===r){for(a=0,s=i,c=0;r>c;++c)a=a<<1|1&s,s>>=1;for(c=a;e>c;c+=o)n[c]=r<<16|f;++i}++r,i<<=1,o<<=1}return[n,h,l]}function n(t,e){switch(this.g=[],this.h=32768,this.c=this.f=this.d=this.k=0,this.input=u?new Uint8Array(t):t,this.l=!1,this.i=c,this.p=!1,(e||!(e={}))&&(e.index&&(this.d=e.index),e.bufferSize&&(this.h=e.bufferSize),e.bufferType&&(this.i=e.bufferType),e.resize&&(this.p=e.resize)),this.i){case f:this.a=32768,this.b=new(u?Uint8Array:Array)(32768+this.h+258);break;case c:this.a=0,this.b=new(u?Uint8Array:Array)(this.h),this.e=this.u,this.m=this.r,this.j=this.s;break;default:throw Error("invalid inflate mode")}}function r(t,e){for(var n,r=t.f,i=t.c,o=t.input,s=t.d;e>i;){if(n=o[s++],n===a)throw Error("input buffer is broken");r|=n<>>e,t.c=i-e,t.d=s,n}function i(t,e){for(var n,r,i,o=t.f,s=t.c,u=t.input,f=t.d,c=e[0],p=e[1];p>s&&(n=u[f++],n!==a);)o|=n<>>16,t.f=o>>i,t.c=s-i,t.d=f,65535&r}function o(t){function n(t,e,n){var o,a,s,u;for(u=0;t>u;)switch(o=i(this,e)){case 16:for(s=3+r(this,2);s--;)n[u++]=a;break;case 17:for(s=3+r(this,3);s--;)n[u++]=0;a=0;break;case 18:for(s=11+r(this,7);s--;)n[u++]=0;a=0;break;default:a=n[u++]=o}return n}var o,a,s,f,c=r(t,5)+257,p=r(t,5)+1,h=r(t,4)+4,l=new(u?Uint8Array:Array)(d.length);for(f=0;h>f;++f)l[d[f]]=r(t,3);o=e(l),a=new(u?Uint8Array:Array)(c),s=new(u?Uint8Array:Array)(p),t.j(e(n.call(t,c,o,a)),e(n.call(t,p,o,s)))}var a=void 0,s=this,u="undefined"!=typeof Uint8Array&&"undefined"!=typeof Uint16Array&&"undefined"!=typeof Uint32Array,f=0,c=1;n.prototype.t=function(){for(;!this.l;){var t=r(this,3);switch(1&t&&(this.l=!0),t>>>=1){case 0:var e=this.input,n=this.d,i=this.b,s=this.a,p=a,h=a,l=a,d=i.length,y=a;if(this.c=this.f=0,p=e[n++],p===a)throw Error("invalid uncompressed block header: LEN (first byte)");if(h=p,p=e[n++],p===a)throw Error("invalid uncompressed block header: LEN (second byte)");if(h|=p<<8,p=e[n++],p===a)throw Error("invalid uncompressed block header: NLEN (first byte)");if(l=p,p=e[n++],p===a)throw Error("invalid uncompressed block header: NLEN (second byte)");if(l|=p<<8,h===~l)throw Error("invalid uncompressed block header: length verify");if(n+h>e.length)throw Error("input buffer is broken");switch(this.i){case f:for(;s+h>i.length;){if(y=d-s,h-=y,u)i.set(e.subarray(n,n+y),s),s+=y,n+=y;else for(;y--;)i[s++]=e[n++];this.a=s,i=this.e(),s=this.a}break;case c:for(;s+h>i.length;)i=this.e({o:2});break;default:throw Error("invalid inflate mode")}if(u)i.set(e.subarray(n,n+h),s),s+=h,n+=h;else for(;h--;)i[s++]=e[n++];this.d=n,this.a=s,this.b=i;break;case 1:this.j(A,N);break;case 2:o(this);break;default:throw Error("unknown BTYPE: "+t)}}return this.m()};var p,h,l=[16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15],d=u?new Uint16Array(l):l,y=[3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,258,258,258],g=u?new Uint16Array(y):y,w=[0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0],m=u?new Uint8Array(w):w,v=[1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193,257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577],b=u?new Uint16Array(v):v,E=[0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13],S=u?new Uint8Array(E):E,I=new(u?Uint8Array:Array)(288);for(p=0,h=I.length;h>p;++p)I[p]=143>=p?8:255>=p?9:279>=p?7:8;var _,F,A=e(I),x=new(u?Uint8Array:Array)(30);for(_=0,F=x.length;F>_;++_)x[_]=5;var N=e(x);n.prototype.j=function(t,e){var n=this.b,o=this.a;this.n=t;for(var a,s,u,f,c=n.length-258;256!==(a=i(this,t));)if(256>a)o>=c&&(this.a=o,n=this.e(),o=this.a),n[o++]=a;else for(s=a-257,f=g[s],0=c&&(this.a=o,n=this.e(),o=this.a);f--;)n[o]=n[o++-u];for(;8<=this.c;)this.c-=8,this.d--;this.a=o},n.prototype.s=function(t,e){var n=this.b,o=this.a;this.n=t;for(var a,s,u,f,c=n.length;256!==(a=i(this,t));)if(256>a)o>=c&&(n=this.e(),c=n.length),n[o++]=a;else for(s=a-257,f=g[s],0c&&(n=this.e(),c=n.length);f--;)n[o]=n[o++-u];for(;8<=this.c;)this.c-=8,this.d--;this.a=o},n.prototype.e=function(){var t,e,n=new(u?Uint8Array:Array)(this.a-32768),r=this.a-32768,i=this.b;if(u)n.set(i.subarray(32768,n.length));else for(t=0,e=n.length;e>t;++t)n[t]=i[t+32768];if(this.g.push(n),this.k+=n.length,u)i.set(i.subarray(r,r+32768));else for(t=0;32768>t;++t)i[t]=i[r+t];return this.a=32768,i},n.prototype.u=function(t){var e,n,r,i,o=0|this.input.length/this.d+1,a=this.input,s=this.b;return t&&("number"==typeof t.o&&(o=t.o),"number"==typeof t.q&&(o+=t.q)),2>o?(n=(a.length-this.d)/this.n[2],i=0|258*(n/2),r=ie;++e)for(t=s[e],r=0,i=t.length;i>r;++r)f[o++]=t[r];for(e=32768,n=this.a;n>e;++e)f[o++]=a[e];return this.g=[],this.buffer=f},n.prototype.r=function(){var t,e=this.a;return u?this.p?(t=new Uint8Array(e),t.set(this.b.subarray(0,e))):t=this.b.subarray(0,e):(this.b.length>e&&(this.b.length=e),t=this.b),this.buffer=t},t("Zlib.RawInflate",n),t("Zlib.RawInflate.prototype.decompress",n.prototype.t);var L,U,D,T,O={ADAPTIVE:c,BLOCK:f};if(Object.keys)L=Object.keys(O);else for(U in L=[],D=0,O)L[D++]=U;for(D=0,T=L.length;T>D;++D)U=L[D],t("Zlib.RawInflate.BufferType."+U,O[U])}.call(this),u("zlib",function(t){return function(){var e;return e||t.Zlib.RawInflate}}(this));var f=this.__extends||function(t,e){function n(){this.constructor=t}for(var r in e)e.hasOwnProperty(r)&&(t[r]=e[r]);n.prototype=e.prototype,t.prototype=new n};u("backend/zipfs",["require","exports","../core/buffer","../core/api_error","../generic/file_index","../core/browserfs","../core/node_fs_stats","../core/file_system","../core/file_flag","../core/buffer_core_arraybuffer","../generic/preload_file","zlib"],function(t,e,n,r,i,o,a,s,u,c,p){function h(t,e){var n=31&e,r=(15&e>>5)-1,i=(e>>9)+1980,o=31&t,a=63&t>>5,s=t>>11;return new Date(i,r,n,s,a,o)}function l(t,e,n,r){return 0===r?"":t.toString(e?"utf8":"extended_ascii",n,n+r)}var d=r.ApiError;r.ErrorCode,u.ActionType;var y=Zlib.RawInflate;!function(t){t[t.MSDOS=0]="MSDOS",t[t.AMIGA=1]="AMIGA",t[t.OPENVMS=2]="OPENVMS",t[t.UNIX=3]="UNIX",t[t.VM_CMS=4]="VM_CMS",t[t.ATARI_ST=5]="ATARI_ST",t[t.OS2_HPFS=6]="OS2_HPFS",t[t.MAC=7]="MAC",t[t.Z_SYSTEM=8]="Z_SYSTEM",t[t.CP_M=9]="CP_M",t[t.NTFS=10]="NTFS",t[t.MVS=11]="MVS",t[t.VSE=12]="VSE",t[t.ACORN_RISC=13]="ACORN_RISC",t[t.VFAT=14]="VFAT",t[t.ALT_MVS=15]="ALT_MVS",t[t.BEOS=16]="BEOS",t[t.TANDEM=17]="TANDEM",t[t.OS_400=18]="OS_400",t[t.OSX=19]="OSX" +}(e.ExternalFileAttributeType||(e.ExternalFileAttributeType={})),e.ExternalFileAttributeType,function(t){t[t.STORED=0]="STORED",t[t.SHRUNK=1]="SHRUNK",t[t.REDUCED_1=2]="REDUCED_1",t[t.REDUCED_2=3]="REDUCED_2",t[t.REDUCED_3=4]="REDUCED_3",t[t.REDUCED_4=5]="REDUCED_4",t[t.IMPLODE=6]="IMPLODE",t[t.DEFLATE=8]="DEFLATE",t[t.DEFLATE64=9]="DEFLATE64",t[t.TERSE_OLD=10]="TERSE_OLD",t[t.BZIP2=12]="BZIP2",t[t.LZMA=14]="LZMA",t[t.TERSE_NEW=18]="TERSE_NEW",t[t.LZ77=19]="LZ77",t[t.WAVPACK=97]="WAVPACK",t[t.PPMD=98]="PPMD"}(e.CompressionMethod||(e.CompressionMethod={}));var g=e.CompressionMethod,w=function(){function t(t){if(this.data=t,67324752!==t.readUInt32LE(0))throw new d(9,"Invalid Zip file: Local file header has invalid signature: "+this.data.readUInt32LE(0))}return t.prototype.versionNeeded=function(){return this.data.readUInt16LE(4)},t.prototype.flags=function(){return this.data.readUInt16LE(6)},t.prototype.compressionMethod=function(){return this.data.readUInt16LE(8)},t.prototype.lastModFileTime=function(){return h(this.data.readUInt16LE(10),this.data.readUInt16LE(12))},t.prototype.crc32=function(){return this.data.readUInt32LE(14)},t.prototype.fileNameLength=function(){return this.data.readUInt16LE(26)},t.prototype.extraFieldLength=function(){return this.data.readUInt16LE(28)},t.prototype.fileName=function(){return l(this.data,this.useUTF8(),30,this.fileNameLength())},t.prototype.extraField=function(){var t=30+this.fileNameLength();return this.data.slice(t,t+this.extraFieldLength())},t.prototype.totalSize=function(){return 30+this.fileNameLength()+this.extraFieldLength()},t.prototype.useUTF8=function(){return 2048===(2048&this.flags())},t}();e.FileHeader=w;var m=function(){function t(t,e,n){this.header=t,this.record=e,this.data=n}return t.prototype.decompress=function(){var t=this.data,e=this.header.compressionMethod();switch(e){case 8:if(t.getBufferCore()instanceof c.BufferCoreArrayBuffer){var r=t.getBufferCore(),i=r.getDataView(),o=i.byteOffset+t.getOffset(),a=new Uint8Array(i.buffer).subarray(o,o+this.record.compressedSize()),s=new y(a).decompress();return new n.Buffer(new c.BufferCoreArrayBuffer(s.buffer),s.byteOffset,s.byteOffset+s.length)}var u=t.slice(0,this.record.compressedSize());return new n.Buffer(new y(u.toJSON().data).decompress());case 0:return t.sliceCopy(0,this.record.uncompressedSize());default:var f=g[e];throw f=f?f:"Unknown: "+e,new d(9,"Invalid compression method on file '"+this.header.fileName()+"': "+f)}},t}();e.FileData=m;var v=function(){function t(t){this.data=t}return t.prototype.crc32=function(){return this.data.readUInt32LE(0)},t.prototype.compressedSize=function(){return this.data.readUInt32LE(4)},t.prototype.uncompressedSize=function(){return this.data.readUInt32LE(8)},t}();e.DataDescriptor=v;var b=function(){function t(t){if(this.data=t,134630224!==this.data.readUInt32LE(0))throw new d(9,"Invalid archive extra data record signature: "+this.data.readUInt32LE(0))}return t.prototype.length=function(){return this.data.readUInt32LE(4)},t.prototype.extraFieldData=function(){return this.data.slice(8,8+this.length())},t}();e.ArchiveExtraDataRecord=b;var E=function(){function t(t){if(this.data=t,84233040!==this.data.readUInt32LE(0))throw new d(9,"Invalid digital signature signature: "+this.data.readUInt32LE(0))}return t.prototype.size=function(){return this.data.readUInt16LE(4)},t.prototype.signatureData=function(){return this.data.slice(6,6+this.size())},t}();e.DigitalSignature=E;var S=function(){function t(t,e){if(this.zipData=t,this.data=e,33639248!==this.data.readUInt32LE(0))throw new d(9,"Invalid Zip file: Central directory record has invalid signature: "+this.data.readUInt32LE(0))}return t.prototype.versionMadeBy=function(){return this.data.readUInt16LE(4)},t.prototype.versionNeeded=function(){return this.data.readUInt16LE(6)},t.prototype.flag=function(){return this.data.readUInt16LE(8)},t.prototype.compressionMethod=function(){return this.data.readUInt16LE(10)},t.prototype.lastModFileTime=function(){return h(this.data.readUInt16LE(12),this.data.readUInt16LE(14))},t.prototype.crc32=function(){return this.data.readUInt32LE(16)},t.prototype.compressedSize=function(){return this.data.readUInt32LE(20)},t.prototype.uncompressedSize=function(){return this.data.readUInt32LE(24)},t.prototype.fileNameLength=function(){return this.data.readUInt16LE(28)},t.prototype.extraFieldLength=function(){return this.data.readUInt16LE(30)},t.prototype.fileCommentLength=function(){return this.data.readUInt16LE(32)},t.prototype.diskNumberStart=function(){return this.data.readUInt16LE(34)},t.prototype.internalAttributes=function(){return this.data.readUInt16LE(36)},t.prototype.externalAttributes=function(){return this.data.readUInt32LE(38)},t.prototype.headerRelativeOffset=function(){return this.data.readUInt32LE(42)},t.prototype.fileName=function(){var t=l(this.data,this.useUTF8(),46,this.fileNameLength());return t.replace(/\\/g,"/")},t.prototype.extraField=function(){var t=44+this.fileNameLength();return this.data.slice(t,t+this.extraFieldLength())},t.prototype.fileComment=function(){var t=46+this.fileNameLength()+this.extraFieldLength();return l(this.data,this.useUTF8(),t,this.fileCommentLength())},t.prototype.totalSize=function(){return 46+this.fileNameLength()+this.extraFieldLength()+this.fileCommentLength()},t.prototype.isDirectory=function(){var t=this.fileName();return(16&this.externalAttributes()?!0:!1)||"/"===t.charAt(t.length-1)},t.prototype.isFile=function(){return!this.isDirectory()},t.prototype.useUTF8=function(){return 2048===(2048&this.flag())},t.prototype.isEncrypted=function(){return 1===(1&this.flag())},t.prototype.getData=function(){var t=this.headerRelativeOffset(),e=new w(this.zipData.slice(t)),n=new m(e,this,this.zipData.slice(t+e.totalSize()));return n.decompress()},t.prototype.getStats=function(){return new a.Stats(32768,this.uncompressedSize(),365,new Date,this.lastModFileTime())},t}();e.CentralDirectory=S;var I=function(){function t(t){if(this.data=t,101010256!==this.data.readUInt32LE(0))throw new d(9,"Invalid Zip file: End of central directory record has invalid signature: "+this.data.readUInt32LE(0))}return t.prototype.diskNumber=function(){return this.data.readUInt16LE(4)},t.prototype.cdDiskNumber=function(){return this.data.readUInt16LE(6)},t.prototype.cdDiskEntryCount=function(){return this.data.readUInt16LE(8)},t.prototype.cdTotalEntryCount=function(){return this.data.readUInt16LE(10)},t.prototype.cdSize=function(){return this.data.readUInt32LE(12)},t.prototype.cdOffset=function(){return this.data.readUInt32LE(16)},t.prototype.cdZipComment=function(){return l(this.data,!0,22,this.data.readUInt16LE(20))},t}();e.EndOfCentralDirectory=I;var _=function(t){function e(e,n){"undefined"==typeof n&&(n=""),t.call(this),this.data=e,this.name=n,this._index=new i.FileIndex,this.populateIndex()}return f(e,t),e.prototype.getName=function(){return"ZipFS"+(""!==this.name?" "+this.name:"")},e.isAvailable=function(){return!0},e.prototype.diskSpace=function(t,e){e(this.data.length,0)},e.prototype.isReadOnly=function(){return!0},e.prototype.supportsLinks=function(){return!1},e.prototype.supportsProps=function(){return!1},e.prototype.supportsSynch=function(){return!0},e.prototype.statSync=function(t){var e=this._index.getInode(t);if(null===e)throw new d(1,""+t+" not found.");var n;return n=e.isFile()?e.getData().getStats():e.getStats()},e.prototype.openSync=function(t,e){if(e.isWriteable())throw new d(0,t);var n=this._index.getInode(t);if(null===n)throw new d(1,""+t+" is not in the FileIndex.");if(n.isDir())throw new d(8,""+t+" is a directory.");var r=n.getData(),i=r.getStats();switch(e.pathExistsAction()){case 1:case 2:throw new d(6,""+t+" already exists.");case 0:return new p.NoSyncFile(this,t,e,i,r.getData());default:throw new d(9,"Invalid FileMode object.")}return null},e.prototype.readdirSync=function(t){var e=this._index.getInode(t);if(null===e)throw new d(1,""+t+" not found.");if(e.isFile())throw new d(7,""+t+" is a file, not a directory.");return e.getListing()},e.prototype.readFileSync=function(t,e,r){var i=this.openSync(t,r,420);try{var o=i,a=o._buffer;return null===e?a.length>0?a.sliceCopy():new n.Buffer(0):a.toString(e)}finally{i.closeSync()}},e.prototype.getEOCD=function(){for(var t=22,e=Math.min(t+65535,this.data.length-1),n=t;e>n;n++)if(101010256===this.data.readUInt32LE(this.data.length-n))return new I(this.data.slice(this.data.length-n));throw new d(9,"Invalid ZIP file: Could not locate End of Central Directory signature.")},e.prototype.populateIndex=function(){var t=this.getEOCD();if(t.diskNumber()!==t.cdDiskNumber())throw new d(9,"ZipFS does not support spanned zip files.");var e=t.cdOffset();if(4294967295===e)throw new d(9,"ZipFS does not support Zip64.");for(var n=e+t.cdSize();n>e;){var r=new S(this.data,this.data.slice(e));e+=r.totalSize();var o=r.fileName();if("/"===o.charAt(0))throw new Error("WHY IS THIS ABSOLUTE");"/"===o.charAt(o.length-1)&&(o=o.substr(0,o.length-1)),r.isDirectory()?this._index.addPath("/"+o,new i.DirInode):this._index.addPath("/"+o,new i.FileInode(r))}},e}(s.SynchronousFileSystem);e.ZipFS=_,o.registerFileSystem("ZipFS",_)}),s("core/global").BrowserFS=s("core/browserfs"),s("generic/emscripten_fs"),s("backend/IndexedDB"),s("backend/XmlHttpRequest"),s("backend/dropbox"),s("backend/html5fs"),s("backend/in_memory"),s("backend/localStorage"),s("backend/mountable_file_system"),s("backend/zipfs")}(); +//# sourceMappingURL=browserfs.min.js.map \ No newline at end of file diff --git a/emscripten/template2.html b/emscripten/template2.html index c8d8b05c3d..e8d4af262e 100644 --- a/emscripten/template2.html +++ b/emscripten/template2.html @@ -33,16 +33,17 @@

Settings

- - - - +

-

+ + +

+ + +

+

-

-

Console

diff --git a/emscripten/web.js b/emscripten/web.js index 77177f18d4..05c625b73c 100644 --- a/emscripten/web.js +++ b/emscripten/web.js @@ -49,7 +49,7 @@ function createConfig() function setupFileSystem() { - console.log("setupFileSystem"); + console.log("setupFileSystem"); if(localStorage.getItem("fs_inited")!="true") { @@ -59,8 +59,11 @@ function setupFileSystem() FS.mount(BFS, {root: '/'}, '/home'); - localStorage.setItem("fs_inited","true"); - console.log('Filesystem initialized: ' + localStorage.getItem("fs_inited")); + console.log('Filesystem initialized'); + } + else + { + console.log('Filesystem already initialized'); } } @@ -69,7 +72,8 @@ function runEmulator(files) if (Modernizr.localstorage) { - setupFileSystem(); + if(firstRun) + setupFileSystem(); } setupFolders(); @@ -99,7 +103,29 @@ function runEmulator(files) function uploadContent(data, name) { var dataView = new Uint8Array(data); - Module.FS_createDataFile('/', name, dataView, true, false); + FS.createDataFile('/', name, dataView, true, false); +} + +function copyFile(src,dest) +{ + console.log('copying: ' + src + ' to: ' + dest); + var contents = FS.readFile(src,{ encoding: 'binary' }); + console.log(contents); + FS.writeFile(dest,contents,{ encoding: 'binary' }); +} + +function uploadData(files, path) +{ + count = files.length; + for (var i = 0; i < files.length; i++) + { + filereader = new FileReader(); + filereader.file_name = files[i].name; + filereader.readAsArrayBuffer(files[i]); + filereader.onload = function(){uploadContent(this.result, '/tmp/' + this.file_name)}; + filereader.onloadend = function(){copyFile('/tmp/' + this.file_name,'/home/web_user/retroarch/' + path + '/' + this.file_name)}; + + } } function initFromData()