diff --git a/ajax/libs/react/0.5.0/JSXTransformer.js b/ajax/libs/react/0.5.0/JSXTransformer.js new file mode 100644 index 000000000..fdb470c85 --- /dev/null +++ b/ajax/libs/react/0.5.0/JSXTransformer.js @@ -0,0 +1,13317 @@ +/** + * JSXTransformer v0.5.0 + */ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.JSXTransformer=e():"undefined"!=typeof global?global.JSXTransformer=e():"undefined"!=typeof self&&(self.JSXTransformer=e())}(function(){var define,module,exports; +return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o i; ++i) { + if (array.hasOwnProperty(i)) { + if (isValueSet) { + value = callback(value, array[i], i, array); + } + else { + value = array[i]; + isValueSet = true; + } + } + } + + return value; +}; + +// String.prototype.substr - negative index don't work in IE8 +if ('ab'.substr(-1) !== 'b') { + exports.substr = function (str, start, length) { + // did we get a negative start, calculate how much it is from the beginning of the string + if (start < 0) start = str.length + start; + + // call the original function + return str.substr(start, length); + }; +} else { + exports.substr = function (str, start, length) { + return str.substr(start, length); + }; +} + +// String.prototype.trim is supported in IE9 +exports.trim = function (str) { + if (str.trim) return str.trim(); + return str.replace(/^\s+|\s+$/g, ''); +}; + +// Function.prototype.bind is supported in IE9 +exports.bind = function () { + var args = Array.prototype.slice.call(arguments); + var fn = args.shift(); + if (fn.bind) return fn.bind.apply(fn, args); + var self = args.shift(); + return function () { + fn.apply(self, args.concat([Array.prototype.slice.call(arguments)])); + }; +}; + +// Object.create is supported in IE9 +function create(prototype, properties) { + var object; + if (prototype === null) { + object = { '__proto__' : null }; + } + else { + if (typeof prototype !== 'object') { + throw new TypeError( + 'typeof prototype[' + (typeof prototype) + '] != \'object\'' + ); + } + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (typeof properties !== 'undefined' && Object.defineProperties) { + Object.defineProperties(object, properties); + } + return object; +} +exports.create = typeof Object.create === 'function' ? Object.create : create; + +// Object.keys and Object.getOwnPropertyNames is supported in IE9 however +// they do show a description and number property on Error objects +function notObject(object) { + return ((typeof object != "object" && typeof object != "function") || object === null); +} + +function keysShim(object) { + if (notObject(object)) { + throw new TypeError("Object.keys called on a non-object"); + } + + var result = []; + for (var name in object) { + if (hasOwnProperty.call(object, name)) { + result.push(name); + } + } + return result; +} + +// getOwnPropertyNames is almost the same as Object.keys one key feature +// is that it returns hidden properties, since that can't be implemented, +// this feature gets reduced so it just shows the length property on arrays +function propertyShim(object) { + if (notObject(object)) { + throw new TypeError("Object.getOwnPropertyNames called on a non-object"); + } + + var result = keysShim(object); + if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) { + result.push('length'); + } + return result; +} + +var keys = typeof Object.keys === 'function' ? Object.keys : keysShim; +var getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ? + Object.getOwnPropertyNames : propertyShim; + +if (new Error().hasOwnProperty('description')) { + var ERROR_PROPERTY_FILTER = function (obj, array) { + if (toString.call(obj) === '[object Error]') { + array = exports.filter(array, function (name) { + return name !== 'description' && name !== 'number' && name !== 'message'; + }); + } + return array; + }; + + exports.keys = function (object) { + return ERROR_PROPERTY_FILTER(object, keys(object)); + }; + exports.getOwnPropertyNames = function (object) { + return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object)); + }; +} else { + exports.keys = keys; + exports.getOwnPropertyNames = getOwnPropertyNames; +} + +// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements +function valueObject(value, key) { + return { value: value[key] }; +} + +if (typeof Object.getOwnPropertyDescriptor === 'function') { + try { + Object.getOwnPropertyDescriptor({'a': 1}, 'a'); + exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + } catch (e) { + // IE8 dom element issue - use a try catch and default to valueObject + exports.getOwnPropertyDescriptor = function (value, key) { + try { + return Object.getOwnPropertyDescriptor(value, key); + } catch (e) { + return valueObject(value, key); + } + }; + } +} else { + exports.getOwnPropertyDescriptor = valueObject; +} + +},{}],2:[function(require,module,exports){ +var process=require("__browserify_process");// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var util = require('util'); +var shims = require('_shims'); + +// resolves . and .. elements in a path array with directory names there +// must be no slashes, empty elements, or device names (c:\) in the array +// (so also no leading and trailing slashes - it does not distinguish +// relative and absolute paths) +function normalizeArray(parts, allowAboveRoot) { + // if the path tries to go above the root, `up` ends up > 0 + var up = 0; + for (var i = parts.length - 1; i >= 0; i--) { + var last = parts[i]; + if (last === '.') { + parts.splice(i, 1); + } else if (last === '..') { + parts.splice(i, 1); + up++; + } else if (up) { + parts.splice(i, 1); + up--; + } + } + + // if the path is allowed to go above the root, restore leading ..s + if (allowAboveRoot) { + for (; up--; up) { + parts.unshift('..'); + } + } + + return parts; +} + +// Split a filename into [root, dir, basename, ext], unix version +// 'root' is just a slash, or nothing. +var splitPathRe = + /^(\/?|)([\s\S]*?)((?:\.{1,2}|[^\/]+?|)(\.[^.\/]*|))(?:[\/]*)$/; +var splitPath = function(filename) { + return splitPathRe.exec(filename).slice(1); +}; + +// path.resolve([from ...], to) +// posix version +exports.resolve = function() { + var resolvedPath = '', + resolvedAbsolute = false; + + for (var i = arguments.length - 1; i >= -1 && !resolvedAbsolute; i--) { + var path = (i >= 0) ? arguments[i] : process.cwd(); + + // Skip empty and invalid entries + if (!util.isString(path)) { + throw new TypeError('Arguments to path.resolve must be strings'); + } else if (!path) { + continue; + } + + resolvedPath = path + '/' + resolvedPath; + resolvedAbsolute = path.charAt(0) === '/'; + } + + // At this point the path should be resolved to a full absolute path, but + // handle relative paths to be safe (might happen when process.cwd() fails) + + // Normalize the path + resolvedPath = normalizeArray(shims.filter(resolvedPath.split('/'), function(p) { + return !!p; + }), !resolvedAbsolute).join('/'); + + return ((resolvedAbsolute ? '/' : '') + resolvedPath) || '.'; +}; + +// path.normalize(path) +// posix version +exports.normalize = function(path) { + var isAbsolute = exports.isAbsolute(path), + trailingSlash = shims.substr(path, -1) === '/'; + + // Normalize the path + path = normalizeArray(shims.filter(path.split('/'), function(p) { + return !!p; + }), !isAbsolute).join('/'); + + if (!path && !isAbsolute) { + path = '.'; + } + if (path && trailingSlash) { + path += '/'; + } + + return (isAbsolute ? '/' : '') + path; +}; + +// posix version +exports.isAbsolute = function(path) { + return path.charAt(0) === '/'; +}; + +// posix version +exports.join = function() { + var paths = Array.prototype.slice.call(arguments, 0); + return exports.normalize(shims.filter(paths, function(p, index) { + if (!util.isString(p)) { + throw new TypeError('Arguments to path.join must be strings'); + } + return p; + }).join('/')); +}; + + +// path.relative(from, to) +// posix version +exports.relative = function(from, to) { + from = exports.resolve(from).substr(1); + to = exports.resolve(to).substr(1); + + function trim(arr) { + var start = 0; + for (; start < arr.length; start++) { + if (arr[start] !== '') break; + } + + var end = arr.length - 1; + for (; end >= 0; end--) { + if (arr[end] !== '') break; + } + + if (start > end) return []; + return arr.slice(start, end - start + 1); + } + + var fromParts = trim(from.split('/')); + var toParts = trim(to.split('/')); + + var length = Math.min(fromParts.length, toParts.length); + var samePartsLength = length; + for (var i = 0; i < length; i++) { + if (fromParts[i] !== toParts[i]) { + samePartsLength = i; + break; + } + } + + var outputParts = []; + for (var i = samePartsLength; i < fromParts.length; i++) { + outputParts.push('..'); + } + + outputParts = outputParts.concat(toParts.slice(samePartsLength)); + + return outputParts.join('/'); +}; + +exports.sep = '/'; +exports.delimiter = ':'; + +exports.dirname = function(path) { + var result = splitPath(path), + root = result[0], + dir = result[1]; + + if (!root && !dir) { + // No dirname whatsoever + return '.'; + } + + if (dir) { + // It has a dirname, strip trailing slash + dir = dir.substr(0, dir.length - 1); + } + + return root + dir; +}; + + +exports.basename = function(path, ext) { + var f = splitPath(path)[2]; + // TODO: make this comparison case-insensitive on windows? + if (ext && f.substr(-1 * ext.length) === ext) { + f = f.substr(0, f.length - ext.length); + } + return f; +}; + + +exports.extname = function(path) { + return splitPath(path)[3]; +}; + +},{"__browserify_process":5,"_shims":1,"util":3}],3:[function(require,module,exports){ +var Buffer=require("__browserify_Buffer").Buffer;// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var shims = require('_shims'); + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + shims.forEach(array, function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = shims.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = shims.getOwnPropertyNames(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + + shims.forEach(keys, function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (shims.indexOf(ctx.seen, desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = shims.reduce(output, function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return shims.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && objectToString(e) === '[object Error]'; +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return arg instanceof Buffer; +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = shims.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = shims.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +},{"__browserify_Buffer":4,"_shims":1}],4:[function(require,module,exports){ +require=(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o> 1, + nBits = -7, + i = isBE ? 0 : (nBytes - 1), + d = isBE ? 1 : -1, + s = buffer[offset + i]; + + i += d; + + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; + for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8); + + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; + for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8); + + if (e === 0) { + e = 1 - eBias; + } else if (e === eMax) { + return m ? NaN : ((s ? -1 : 1) * Infinity); + } else { + m = m + Math.pow(2, mLen); + e = e - eBias; + } + return (s ? -1 : 1) * m * Math.pow(2, e - mLen); +}; + +exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) { + var e, m, c, + eLen = nBytes * 8 - mLen - 1, + eMax = (1 << eLen) - 1, + eBias = eMax >> 1, + rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0), + i = isBE ? (nBytes - 1) : 0, + d = isBE ? -1 : 1, + s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; + + value = Math.abs(value); + + if (isNaN(value) || value === Infinity) { + m = isNaN(value) ? 1 : 0; + e = eMax; + } else { + e = Math.floor(Math.log(value) / Math.LN2); + if (value * (c = Math.pow(2, -e)) < 1) { + e--; + c *= 2; + } + if (e + eBias >= 1) { + value += rt / c; + } else { + value += rt * Math.pow(2, 1 - eBias); + } + if (value * c >= 2) { + e++; + c /= 2; + } + + if (e + eBias >= eMax) { + m = 0; + e = eMax; + } else if (e + eBias >= 1) { + m = (value * c - 1) * Math.pow(2, mLen); + e = e + eBias; + } else { + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); + e = 0; + } + } + + for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8); + + e = (e << mLen) | m; + eLen += mLen; + for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8); + + buffer[offset + i - d] |= s * 128; +}; + +},{}],"q9TxCC":[function(require,module,exports){ +var assert; +exports.Buffer = Buffer; +exports.SlowBuffer = Buffer; +Buffer.poolSize = 8192; +exports.INSPECT_MAX_BYTES = 50; + +function stringtrim(str) { + if (str.trim) return str.trim(); + return str.replace(/^\s+|\s+$/g, ''); +} + +function Buffer(subject, encoding, offset) { + if(!assert) assert= require('assert'); + if (!(this instanceof Buffer)) { + return new Buffer(subject, encoding, offset); + } + this.parent = this; + this.offset = 0; + + // Work-around: node's base64 implementation + // allows for non-padded strings while base64-js + // does not.. + if (encoding == "base64" && typeof subject == "string") { + subject = stringtrim(subject); + while (subject.length % 4 != 0) { + subject = subject + "="; + } + } + + var type; + + // Are we slicing? + if (typeof offset === 'number') { + this.length = coerce(encoding); + // slicing works, with limitations (no parent tracking/update) + // check https://github.com/toots/buffer-browserify/issues/19 + for (var i = 0; i < this.length; i++) { + this[i] = subject.get(i+offset); + } + } else { + // Find the length + switch (type = typeof subject) { + case 'number': + this.length = coerce(subject); + break; + + case 'string': + this.length = Buffer.byteLength(subject, encoding); + break; + + case 'object': // Assume object is an array + this.length = coerce(subject.length); + break; + + default: + throw new Error('First argument needs to be a number, ' + + 'array or string.'); + } + + // Treat array-ish objects as a byte array. + if (isArrayIsh(subject)) { + for (var i = 0; i < this.length; i++) { + if (subject instanceof Buffer) { + this[i] = subject.readUInt8(i); + } + else { + this[i] = subject[i]; + } + } + } else if (type == 'string') { + // We are a string + this.length = this.write(subject, 0, encoding); + } else if (type === 'number') { + for (var i = 0; i < this.length; i++) { + this[i] = 0; + } + } + } +} + +Buffer.prototype.get = function get(i) { + if (i < 0 || i >= this.length) throw new Error('oob'); + return this[i]; +}; + +Buffer.prototype.set = function set(i, v) { + if (i < 0 || i >= this.length) throw new Error('oob'); + return this[i] = v; +}; + +Buffer.byteLength = function (str, encoding) { + switch (encoding || "utf8") { + case 'hex': + return str.length / 2; + + case 'utf8': + case 'utf-8': + return utf8ToBytes(str).length; + + case 'ascii': + case 'binary': + return str.length; + + case 'base64': + return base64ToBytes(str).length; + + default: + throw new Error('Unknown encoding'); + } +}; + +Buffer.prototype.utf8Write = function (string, offset, length) { + var bytes, pos; + return Buffer._charsWritten = blitBuffer(utf8ToBytes(string), this, offset, length); +}; + +Buffer.prototype.asciiWrite = function (string, offset, length) { + var bytes, pos; + return Buffer._charsWritten = blitBuffer(asciiToBytes(string), this, offset, length); +}; + +Buffer.prototype.binaryWrite = Buffer.prototype.asciiWrite; + +Buffer.prototype.base64Write = function (string, offset, length) { + var bytes, pos; + return Buffer._charsWritten = blitBuffer(base64ToBytes(string), this, offset, length); +}; + +Buffer.prototype.base64Slice = function (start, end) { + var bytes = Array.prototype.slice.apply(this, arguments) + return require("base64-js").fromByteArray(bytes); +}; + +Buffer.prototype.utf8Slice = function () { + var bytes = Array.prototype.slice.apply(this, arguments); + var res = ""; + var tmp = ""; + var i = 0; + while (i < bytes.length) { + if (bytes[i] <= 0x7F) { + res += decodeUtf8Char(tmp) + String.fromCharCode(bytes[i]); + tmp = ""; + } else + tmp += "%" + bytes[i].toString(16); + + i++; + } + + return res + decodeUtf8Char(tmp); +} + +Buffer.prototype.asciiSlice = function () { + var bytes = Array.prototype.slice.apply(this, arguments); + var ret = ""; + for (var i = 0; i < bytes.length; i++) + ret += String.fromCharCode(bytes[i]); + return ret; +} + +Buffer.prototype.binarySlice = Buffer.prototype.asciiSlice; + +Buffer.prototype.inspect = function() { + var out = [], + len = this.length; + for (var i = 0; i < len; i++) { + out[i] = toHex(this[i]); + if (i == exports.INSPECT_MAX_BYTES) { + out[i + 1] = '...'; + break; + } + } + return ''; +}; + + +Buffer.prototype.hexSlice = function(start, end) { + var len = this.length; + + if (!start || start < 0) start = 0; + if (!end || end < 0 || end > len) end = len; + + var out = ''; + for (var i = start; i < end; i++) { + out += toHex(this[i]); + } + return out; +}; + + +Buffer.prototype.toString = function(encoding, start, end) { + encoding = String(encoding || 'utf8').toLowerCase(); + start = +start || 0; + if (typeof end == 'undefined') end = this.length; + + // Fastpath empty strings + if (+end == start) { + return ''; + } + + switch (encoding) { + case 'hex': + return this.hexSlice(start, end); + + case 'utf8': + case 'utf-8': + return this.utf8Slice(start, end); + + case 'ascii': + return this.asciiSlice(start, end); + + case 'binary': + return this.binarySlice(start, end); + + case 'base64': + return this.base64Slice(start, end); + + case 'ucs2': + case 'ucs-2': + return this.ucs2Slice(start, end); + + default: + throw new Error('Unknown encoding'); + } +}; + + +Buffer.prototype.hexWrite = function(string, offset, length) { + offset = +offset || 0; + var remaining = this.length - offset; + if (!length) { + length = remaining; + } else { + length = +length; + if (length > remaining) { + length = remaining; + } + } + + // must be an even number of digits + var strLen = string.length; + if (strLen % 2) { + throw new Error('Invalid hex string'); + } + if (length > strLen / 2) { + length = strLen / 2; + } + for (var i = 0; i < length; i++) { + var byte = parseInt(string.substr(i * 2, 2), 16); + if (isNaN(byte)) throw new Error('Invalid hex string'); + this[offset + i] = byte; + } + Buffer._charsWritten = i * 2; + return i; +}; + + +Buffer.prototype.write = function(string, offset, length, encoding) { + // Support both (string, offset, length, encoding) + // and the legacy (string, encoding, offset, length) + if (isFinite(offset)) { + if (!isFinite(length)) { + encoding = length; + length = undefined; + } + } else { // legacy + var swap = encoding; + encoding = offset; + offset = length; + length = swap; + } + + offset = +offset || 0; + var remaining = this.length - offset; + if (!length) { + length = remaining; + } else { + length = +length; + if (length > remaining) { + length = remaining; + } + } + encoding = String(encoding || 'utf8').toLowerCase(); + + switch (encoding) { + case 'hex': + return this.hexWrite(string, offset, length); + + case 'utf8': + case 'utf-8': + return this.utf8Write(string, offset, length); + + case 'ascii': + return this.asciiWrite(string, offset, length); + + case 'binary': + return this.binaryWrite(string, offset, length); + + case 'base64': + return this.base64Write(string, offset, length); + + case 'ucs2': + case 'ucs-2': + return this.ucs2Write(string, offset, length); + + default: + throw new Error('Unknown encoding'); + } +}; + +// slice(start, end) +function clamp(index, len, defaultValue) { + if (typeof index !== 'number') return defaultValue; + index = ~~index; // Coerce to integer. + if (index >= len) return len; + if (index >= 0) return index; + index += len; + if (index >= 0) return index; + return 0; +} + +Buffer.prototype.slice = function(start, end) { + var len = this.length; + start = clamp(start, len, 0); + end = clamp(end, len, len); + return new Buffer(this, end - start, +start); +}; + +// copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) +Buffer.prototype.copy = function(target, target_start, start, end) { + var source = this; + start || (start = 0); + if (end === undefined || isNaN(end)) { + end = this.length; + } + target_start || (target_start = 0); + + if (end < start) throw new Error('sourceEnd < sourceStart'); + + // Copy 0 bytes; we're done + if (end === start) return 0; + if (target.length == 0 || source.length == 0) return 0; + + if (target_start < 0 || target_start >= target.length) { + throw new Error('targetStart out of bounds'); + } + + if (start < 0 || start >= source.length) { + throw new Error('sourceStart out of bounds'); + } + + if (end < 0 || end > source.length) { + throw new Error('sourceEnd out of bounds'); + } + + // Are we oob? + if (end > this.length) { + end = this.length; + } + + if (target.length - target_start < end - start) { + end = target.length - target_start + start; + } + + var temp = []; + for (var i=start; i= this.length) { + throw new Error('start out of bounds'); + } + + if (end < 0 || end > this.length) { + throw new Error('end out of bounds'); + } + + for (var i = start; i < end; i++) { + this[i] = value; + } +} + +// Static methods +Buffer.isBuffer = function isBuffer(b) { + return b instanceof Buffer || b instanceof Buffer; +}; + +Buffer.concat = function (list, totalLength) { + if (!isArray(list)) { + throw new Error("Usage: Buffer.concat(list, [totalLength])\n \ + list should be an Array."); + } + + if (list.length === 0) { + return new Buffer(0); + } else if (list.length === 1) { + return list[0]; + } + + if (typeof totalLength !== 'number') { + totalLength = 0; + for (var i = 0; i < list.length; i++) { + var buf = list[i]; + totalLength += buf.length; + } + } + + var buffer = new Buffer(totalLength); + var pos = 0; + for (var i = 0; i < list.length; i++) { + var buf = list[i]; + buf.copy(buffer, pos); + pos += buf.length; + } + return buffer; +}; + +Buffer.isEncoding = function(encoding) { + switch ((encoding + '').toLowerCase()) { + case 'hex': + case 'utf8': + case 'utf-8': + case 'ascii': + case 'binary': + case 'base64': + case 'ucs2': + case 'ucs-2': + case 'utf16le': + case 'utf-16le': + case 'raw': + return true; + + default: + return false; + } +}; + +// helpers + +function coerce(length) { + // Coerce length to a number (possibly NaN), round up + // in case it's fractional (e.g. 123.456) then do a + // double negate to coerce a NaN to 0. Easy, right? + length = ~~Math.ceil(+length); + return length < 0 ? 0 : length; +} + +function isArray(subject) { + return (Array.isArray || + function(subject){ + return {}.toString.apply(subject) == '[object Array]' + }) + (subject) +} + +function isArrayIsh(subject) { + return isArray(subject) || Buffer.isBuffer(subject) || + subject && typeof subject === 'object' && + typeof subject.length === 'number'; +} + +function toHex(n) { + if (n < 16) return '0' + n.toString(16); + return n.toString(16); +} + +function utf8ToBytes(str) { + var byteArray = []; + for (var i = 0; i < str.length; i++) + if (str.charCodeAt(i) <= 0x7F) + byteArray.push(str.charCodeAt(i)); + else { + var h = encodeURIComponent(str.charAt(i)).substr(1).split('%'); + for (var j = 0; j < h.length; j++) + byteArray.push(parseInt(h[j], 16)); + } + + return byteArray; +} + +function asciiToBytes(str) { + var byteArray = [] + for (var i = 0; i < str.length; i++ ) + // Node's code seems to be doing this and not & 0x7F.. + byteArray.push( str.charCodeAt(i) & 0xFF ); + + return byteArray; +} + +function base64ToBytes(str) { + return require("base64-js").toByteArray(str); +} + +function blitBuffer(src, dst, offset, length) { + var pos, i = 0; + while (i < length) { + if ((i+offset >= dst.length) || (i >= src.length)) + break; + + dst[i + offset] = src[i]; + i++; + } + return i; +} + +function decodeUtf8Char(str) { + try { + return decodeURIComponent(str); + } catch (err) { + return String.fromCharCode(0xFFFD); // UTF 8 invalid char + } +} + +// read/write bit-twiddling + +Buffer.prototype.readUInt8 = function(offset, noAssert) { + var buffer = this; + + if (!noAssert) { + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset < buffer.length, + 'Trying to read beyond buffer length'); + } + + if (offset >= buffer.length) return; + + return buffer[offset]; +}; + +function readUInt16(buffer, offset, isBigEndian, noAssert) { + var val = 0; + + + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 1 < buffer.length, + 'Trying to read beyond buffer length'); + } + + if (offset >= buffer.length) return 0; + + if (isBigEndian) { + val = buffer[offset] << 8; + if (offset + 1 < buffer.length) { + val |= buffer[offset + 1]; + } + } else { + val = buffer[offset]; + if (offset + 1 < buffer.length) { + val |= buffer[offset + 1] << 8; + } + } + + return val; +} + +Buffer.prototype.readUInt16LE = function(offset, noAssert) { + return readUInt16(this, offset, false, noAssert); +}; + +Buffer.prototype.readUInt16BE = function(offset, noAssert) { + return readUInt16(this, offset, true, noAssert); +}; + +function readUInt32(buffer, offset, isBigEndian, noAssert) { + var val = 0; + + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 3 < buffer.length, + 'Trying to read beyond buffer length'); + } + + if (offset >= buffer.length) return 0; + + if (isBigEndian) { + if (offset + 1 < buffer.length) + val = buffer[offset + 1] << 16; + if (offset + 2 < buffer.length) + val |= buffer[offset + 2] << 8; + if (offset + 3 < buffer.length) + val |= buffer[offset + 3]; + val = val + (buffer[offset] << 24 >>> 0); + } else { + if (offset + 2 < buffer.length) + val = buffer[offset + 2] << 16; + if (offset + 1 < buffer.length) + val |= buffer[offset + 1] << 8; + val |= buffer[offset]; + if (offset + 3 < buffer.length) + val = val + (buffer[offset + 3] << 24 >>> 0); + } + + return val; +} + +Buffer.prototype.readUInt32LE = function(offset, noAssert) { + return readUInt32(this, offset, false, noAssert); +}; + +Buffer.prototype.readUInt32BE = function(offset, noAssert) { + return readUInt32(this, offset, true, noAssert); +}; + + +/* + * Signed integer types, yay team! A reminder on how two's complement actually + * works. The first bit is the signed bit, i.e. tells us whether or not the + * number should be positive or negative. If the two's complement value is + * positive, then we're done, as it's equivalent to the unsigned representation. + * + * Now if the number is positive, you're pretty much done, you can just leverage + * the unsigned translations and return those. Unfortunately, negative numbers + * aren't quite that straightforward. + * + * At first glance, one might be inclined to use the traditional formula to + * translate binary numbers between the positive and negative values in two's + * complement. (Though it doesn't quite work for the most negative value) + * Mainly: + * - invert all the bits + * - add one to the result + * + * Of course, this doesn't quite work in Javascript. Take for example the value + * of -128. This could be represented in 16 bits (big-endian) as 0xff80. But of + * course, Javascript will do the following: + * + * > ~0xff80 + * -65409 + * + * Whoh there, Javascript, that's not quite right. But wait, according to + * Javascript that's perfectly correct. When Javascript ends up seeing the + * constant 0xff80, it has no notion that it is actually a signed number. It + * assumes that we've input the unsigned value 0xff80. Thus, when it does the + * binary negation, it casts it into a signed value, (positive 0xff80). Then + * when you perform binary negation on that, it turns it into a negative number. + * + * Instead, we're going to have to use the following general formula, that works + * in a rather Javascript friendly way. I'm glad we don't support this kind of + * weird numbering scheme in the kernel. + * + * (BIT-MAX - (unsigned)val + 1) * -1 + * + * The astute observer, may think that this doesn't make sense for 8-bit numbers + * (really it isn't necessary for them). However, when you get 16-bit numbers, + * you do. Let's go back to our prior example and see how this will look: + * + * (0xffff - 0xff80 + 1) * -1 + * (0x007f + 1) * -1 + * (0x0080) * -1 + */ +Buffer.prototype.readInt8 = function(offset, noAssert) { + var buffer = this; + var neg; + + if (!noAssert) { + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset < buffer.length, + 'Trying to read beyond buffer length'); + } + + if (offset >= buffer.length) return; + + neg = buffer[offset] & 0x80; + if (!neg) { + return (buffer[offset]); + } + + return ((0xff - buffer[offset] + 1) * -1); +}; + +function readInt16(buffer, offset, isBigEndian, noAssert) { + var neg, val; + + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 1 < buffer.length, + 'Trying to read beyond buffer length'); + } + + val = readUInt16(buffer, offset, isBigEndian, noAssert); + neg = val & 0x8000; + if (!neg) { + return val; + } + + return (0xffff - val + 1) * -1; +} + +Buffer.prototype.readInt16LE = function(offset, noAssert) { + return readInt16(this, offset, false, noAssert); +}; + +Buffer.prototype.readInt16BE = function(offset, noAssert) { + return readInt16(this, offset, true, noAssert); +}; + +function readInt32(buffer, offset, isBigEndian, noAssert) { + var neg, val; + + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 3 < buffer.length, + 'Trying to read beyond buffer length'); + } + + val = readUInt32(buffer, offset, isBigEndian, noAssert); + neg = val & 0x80000000; + if (!neg) { + return (val); + } + + return (0xffffffff - val + 1) * -1; +} + +Buffer.prototype.readInt32LE = function(offset, noAssert) { + return readInt32(this, offset, false, noAssert); +}; + +Buffer.prototype.readInt32BE = function(offset, noAssert) { + return readInt32(this, offset, true, noAssert); +}; + +function readFloat(buffer, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset + 3 < buffer.length, + 'Trying to read beyond buffer length'); + } + + return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, + 23, 4); +} + +Buffer.prototype.readFloatLE = function(offset, noAssert) { + return readFloat(this, offset, false, noAssert); +}; + +Buffer.prototype.readFloatBE = function(offset, noAssert) { + return readFloat(this, offset, true, noAssert); +}; + +function readDouble(buffer, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset + 7 < buffer.length, + 'Trying to read beyond buffer length'); + } + + return require('./buffer_ieee754').readIEEE754(buffer, offset, isBigEndian, + 52, 8); +} + +Buffer.prototype.readDoubleLE = function(offset, noAssert) { + return readDouble(this, offset, false, noAssert); +}; + +Buffer.prototype.readDoubleBE = function(offset, noAssert) { + return readDouble(this, offset, true, noAssert); +}; + + +/* + * We have to make sure that the value is a valid integer. This means that it is + * non-negative. It has no fractional component and that it does not exceed the + * maximum allowed value. + * + * value The number to check for validity + * + * max The maximum value + */ +function verifuint(value, max) { + assert.ok(typeof (value) == 'number', + 'cannot write a non-number as a number'); + + assert.ok(value >= 0, + 'specified a negative value for writing an unsigned value'); + + assert.ok(value <= max, 'value is larger than maximum value for type'); + + assert.ok(Math.floor(value) === value, 'value has a fractional component'); +} + +Buffer.prototype.writeUInt8 = function(value, offset, noAssert) { + var buffer = this; + + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset < buffer.length, + 'trying to write beyond buffer length'); + + verifuint(value, 0xff); + } + + if (offset < buffer.length) { + buffer[offset] = value; + } +}; + +function writeUInt16(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 1 < buffer.length, + 'trying to write beyond buffer length'); + + verifuint(value, 0xffff); + } + + for (var i = 0; i < Math.min(buffer.length - offset, 2); i++) { + buffer[offset + i] = + (value & (0xff << (8 * (isBigEndian ? 1 - i : i)))) >>> + (isBigEndian ? 1 - i : i) * 8; + } + +} + +Buffer.prototype.writeUInt16LE = function(value, offset, noAssert) { + writeUInt16(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeUInt16BE = function(value, offset, noAssert) { + writeUInt16(this, value, offset, true, noAssert); +}; + +function writeUInt32(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 3 < buffer.length, + 'trying to write beyond buffer length'); + + verifuint(value, 0xffffffff); + } + + for (var i = 0; i < Math.min(buffer.length - offset, 4); i++) { + buffer[offset + i] = + (value >>> (isBigEndian ? 3 - i : i) * 8) & 0xff; + } +} + +Buffer.prototype.writeUInt32LE = function(value, offset, noAssert) { + writeUInt32(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeUInt32BE = function(value, offset, noAssert) { + writeUInt32(this, value, offset, true, noAssert); +}; + + +/* + * We now move onto our friends in the signed number category. Unlike unsigned + * numbers, we're going to have to worry a bit more about how we put values into + * arrays. Since we are only worrying about signed 32-bit values, we're in + * slightly better shape. Unfortunately, we really can't do our favorite binary + * & in this system. It really seems to do the wrong thing. For example: + * + * > -32 & 0xff + * 224 + * + * What's happening above is really: 0xe0 & 0xff = 0xe0. However, the results of + * this aren't treated as a signed number. Ultimately a bad thing. + * + * What we're going to want to do is basically create the unsigned equivalent of + * our representation and pass that off to the wuint* functions. To do that + * we're going to do the following: + * + * - if the value is positive + * we can pass it directly off to the equivalent wuint + * - if the value is negative + * we do the following computation: + * mb + val + 1, where + * mb is the maximum unsigned value in that byte size + * val is the Javascript negative integer + * + * + * As a concrete value, take -128. In signed 16 bits this would be 0xff80. If + * you do out the computations: + * + * 0xffff - 128 + 1 + * 0xffff - 127 + * 0xff80 + * + * You can then encode this value as the signed version. This is really rather + * hacky, but it should work and get the job done which is our goal here. + */ + +/* + * A series of checks to make sure we actually have a signed 32-bit number + */ +function verifsint(value, max, min) { + assert.ok(typeof (value) == 'number', + 'cannot write a non-number as a number'); + + assert.ok(value <= max, 'value larger than maximum allowed value'); + + assert.ok(value >= min, 'value smaller than minimum allowed value'); + + assert.ok(Math.floor(value) === value, 'value has a fractional component'); +} + +function verifIEEE754(value, max, min) { + assert.ok(typeof (value) == 'number', + 'cannot write a non-number as a number'); + + assert.ok(value <= max, 'value larger than maximum allowed value'); + + assert.ok(value >= min, 'value smaller than minimum allowed value'); +} + +Buffer.prototype.writeInt8 = function(value, offset, noAssert) { + var buffer = this; + + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset < buffer.length, + 'Trying to write beyond buffer length'); + + verifsint(value, 0x7f, -0x80); + } + + if (value >= 0) { + buffer.writeUInt8(value, offset, noAssert); + } else { + buffer.writeUInt8(0xff + value + 1, offset, noAssert); + } +}; + +function writeInt16(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 1 < buffer.length, + 'Trying to write beyond buffer length'); + + verifsint(value, 0x7fff, -0x8000); + } + + if (value >= 0) { + writeUInt16(buffer, value, offset, isBigEndian, noAssert); + } else { + writeUInt16(buffer, 0xffff + value + 1, offset, isBigEndian, noAssert); + } +} + +Buffer.prototype.writeInt16LE = function(value, offset, noAssert) { + writeInt16(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeInt16BE = function(value, offset, noAssert) { + writeInt16(this, value, offset, true, noAssert); +}; + +function writeInt32(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 3 < buffer.length, + 'Trying to write beyond buffer length'); + + verifsint(value, 0x7fffffff, -0x80000000); + } + + if (value >= 0) { + writeUInt32(buffer, value, offset, isBigEndian, noAssert); + } else { + writeUInt32(buffer, 0xffffffff + value + 1, offset, isBigEndian, noAssert); + } +} + +Buffer.prototype.writeInt32LE = function(value, offset, noAssert) { + writeInt32(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeInt32BE = function(value, offset, noAssert) { + writeInt32(this, value, offset, true, noAssert); +}; + +function writeFloat(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 3 < buffer.length, + 'Trying to write beyond buffer length'); + + verifIEEE754(value, 3.4028234663852886e+38, -3.4028234663852886e+38); + } + + require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, + 23, 4); +} + +Buffer.prototype.writeFloatLE = function(value, offset, noAssert) { + writeFloat(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeFloatBE = function(value, offset, noAssert) { + writeFloat(this, value, offset, true, noAssert); +}; + +function writeDouble(buffer, value, offset, isBigEndian, noAssert) { + if (!noAssert) { + assert.ok(value !== undefined && value !== null, + 'missing value'); + + assert.ok(typeof (isBigEndian) === 'boolean', + 'missing or invalid endian'); + + assert.ok(offset !== undefined && offset !== null, + 'missing offset'); + + assert.ok(offset + 7 < buffer.length, + 'Trying to write beyond buffer length'); + + verifIEEE754(value, 1.7976931348623157E+308, -1.7976931348623157E+308); + } + + require('./buffer_ieee754').writeIEEE754(buffer, value, offset, isBigEndian, + 52, 8); +} + +Buffer.prototype.writeDoubleLE = function(value, offset, noAssert) { + writeDouble(this, value, offset, false, noAssert); +}; + +Buffer.prototype.writeDoubleBE = function(value, offset, noAssert) { + writeDouble(this, value, offset, true, noAssert); +}; + +},{"./buffer_ieee754":1,"assert":6,"base64-js":4}],"buffer-browserify":[function(require,module,exports){ +module.exports=require('q9TxCC'); +},{}],4:[function(require,module,exports){ +(function (exports) { + 'use strict'; + + var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; + + function b64ToByteArray(b64) { + var i, j, l, tmp, placeHolders, arr; + + if (b64.length % 4 > 0) { + throw 'Invalid string. Length must be a multiple of 4'; + } + + // the number of equal signs (place holders) + // if there are two placeholders, than the two characters before it + // represent one byte + // if there is only one, then the three characters before it represent 2 bytes + // this is just a cheap hack to not do indexOf twice + placeHolders = b64.indexOf('='); + placeHolders = placeHolders > 0 ? b64.length - placeHolders : 0; + + // base64 is 4/3 + up to two characters of the original data + arr = [];//new Uint8Array(b64.length * 3 / 4 - placeHolders); + + // if there are placeholders, only get up to the last complete 4 chars + l = placeHolders > 0 ? b64.length - 4 : b64.length; + + for (i = 0, j = 0; i < l; i += 4, j += 3) { + tmp = (lookup.indexOf(b64[i]) << 18) | (lookup.indexOf(b64[i + 1]) << 12) | (lookup.indexOf(b64[i + 2]) << 6) | lookup.indexOf(b64[i + 3]); + arr.push((tmp & 0xFF0000) >> 16); + arr.push((tmp & 0xFF00) >> 8); + arr.push(tmp & 0xFF); + } + + if (placeHolders === 2) { + tmp = (lookup.indexOf(b64[i]) << 2) | (lookup.indexOf(b64[i + 1]) >> 4); + arr.push(tmp & 0xFF); + } else if (placeHolders === 1) { + tmp = (lookup.indexOf(b64[i]) << 10) | (lookup.indexOf(b64[i + 1]) << 4) | (lookup.indexOf(b64[i + 2]) >> 2); + arr.push((tmp >> 8) & 0xFF); + arr.push(tmp & 0xFF); + } + + return arr; + } + + function uint8ToBase64(uint8) { + var i, + extraBytes = uint8.length % 3, // if we have 1 byte left, pad 2 bytes + output = "", + temp, length; + + function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + lookup[num >> 12 & 0x3F] + lookup[num >> 6 & 0x3F] + lookup[num & 0x3F]; + }; + + // go through the array every three bytes, we'll deal with trailing stuff later + for (i = 0, length = uint8.length - extraBytes; i < length; i += 3) { + temp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); + output += tripletToBase64(temp); + } + + // pad the end with zeros, but make sure to not forget the extra bytes + switch (extraBytes) { + case 1: + temp = uint8[uint8.length - 1]; + output += lookup[temp >> 2]; + output += lookup[(temp << 4) & 0x3F]; + output += '=='; + break; + case 2: + temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1]); + output += lookup[temp >> 10]; + output += lookup[(temp >> 4) & 0x3F]; + output += lookup[(temp << 2) & 0x3F]; + output += '='; + break; + } + + return output; + } + + module.exports.toByteArray = b64ToByteArray; + module.exports.fromByteArray = uint8ToBase64; +}()); + +},{}],5:[function(require,module,exports){ + + +// +// The shims in this file are not fully implemented shims for the ES5 +// features, but do work for the particular usecases there is in +// the other modules. +// + +var toString = Object.prototype.toString; +var hasOwnProperty = Object.prototype.hasOwnProperty; + +// Array.isArray is supported in IE9 +function isArray(xs) { + return toString.call(xs) === '[object Array]'; +} +exports.isArray = typeof Array.isArray === 'function' ? Array.isArray : isArray; + +// Array.prototype.indexOf is supported in IE9 +exports.indexOf = function indexOf(xs, x) { + if (xs.indexOf) return xs.indexOf(x); + for (var i = 0; i < xs.length; i++) { + if (x === xs[i]) return i; + } + return -1; +}; + +// Array.prototype.filter is supported in IE9 +exports.filter = function filter(xs, fn) { + if (xs.filter) return xs.filter(fn); + var res = []; + for (var i = 0; i < xs.length; i++) { + if (fn(xs[i], i, xs)) res.push(xs[i]); + } + return res; +}; + +// Array.prototype.forEach is supported in IE9 +exports.forEach = function forEach(xs, fn, self) { + if (xs.forEach) return xs.forEach(fn, self); + for (var i = 0; i < xs.length; i++) { + fn.call(self, xs[i], i, xs); + } +}; + +// Array.prototype.map is supported in IE9 +exports.map = function map(xs, fn) { + if (xs.map) return xs.map(fn); + var out = new Array(xs.length); + for (var i = 0; i < xs.length; i++) { + out[i] = fn(xs[i], i, xs); + } + return out; +}; + +// Array.prototype.reduce is supported in IE9 +exports.reduce = function reduce(array, callback, opt_initialValue) { + if (array.reduce) return array.reduce(callback, opt_initialValue); + var value, isValueSet = false; + + if (2 < arguments.length) { + value = opt_initialValue; + isValueSet = true; + } + for (var i = 0, l = array.length; l > i; ++i) { + if (array.hasOwnProperty(i)) { + if (isValueSet) { + value = callback(value, array[i], i, array); + } + else { + value = array[i]; + isValueSet = true; + } + } + } + + return value; +}; + +// String.prototype.substr - negative index don't work in IE8 +if ('ab'.substr(-1) !== 'b') { + exports.substr = function (str, start, length) { + // did we get a negative start, calculate how much it is from the beginning of the string + if (start < 0) start = str.length + start; + + // call the original function + return str.substr(start, length); + }; +} else { + exports.substr = function (str, start, length) { + return str.substr(start, length); + }; +} + +// String.prototype.trim is supported in IE9 +exports.trim = function (str) { + if (str.trim) return str.trim(); + return str.replace(/^\s+|\s+$/g, ''); +}; + +// Function.prototype.bind is supported in IE9 +exports.bind = function () { + var args = Array.prototype.slice.call(arguments); + var fn = args.shift(); + if (fn.bind) return fn.bind.apply(fn, args); + var self = args.shift(); + return function () { + fn.apply(self, args.concat([Array.prototype.slice.call(arguments)])); + }; +}; + +// Object.create is supported in IE9 +function create(prototype, properties) { + var object; + if (prototype === null) { + object = { '__proto__' : null }; + } + else { + if (typeof prototype !== 'object') { + throw new TypeError( + 'typeof prototype[' + (typeof prototype) + '] != \'object\'' + ); + } + var Type = function () {}; + Type.prototype = prototype; + object = new Type(); + object.__proto__ = prototype; + } + if (typeof properties !== 'undefined' && Object.defineProperties) { + Object.defineProperties(object, properties); + } + return object; +} +exports.create = typeof Object.create === 'function' ? Object.create : create; + +// Object.keys and Object.getOwnPropertyNames is supported in IE9 however +// they do show a description and number property on Error objects +function notObject(object) { + return ((typeof object != "object" && typeof object != "function") || object === null); +} + +function keysShim(object) { + if (notObject(object)) { + throw new TypeError("Object.keys called on a non-object"); + } + + var result = []; + for (var name in object) { + if (hasOwnProperty.call(object, name)) { + result.push(name); + } + } + return result; +} + +// getOwnPropertyNames is almost the same as Object.keys one key feature +// is that it returns hidden properties, since that can't be implemented, +// this feature gets reduced so it just shows the length property on arrays +function propertyShim(object) { + if (notObject(object)) { + throw new TypeError("Object.getOwnPropertyNames called on a non-object"); + } + + var result = keysShim(object); + if (exports.isArray(object) && exports.indexOf(object, 'length') === -1) { + result.push('length'); + } + return result; +} + +var keys = typeof Object.keys === 'function' ? Object.keys : keysShim; +var getOwnPropertyNames = typeof Object.getOwnPropertyNames === 'function' ? + Object.getOwnPropertyNames : propertyShim; + +if (new Error().hasOwnProperty('description')) { + var ERROR_PROPERTY_FILTER = function (obj, array) { + if (toString.call(obj) === '[object Error]') { + array = exports.filter(array, function (name) { + return name !== 'description' && name !== 'number' && name !== 'message'; + }); + } + return array; + }; + + exports.keys = function (object) { + return ERROR_PROPERTY_FILTER(object, keys(object)); + }; + exports.getOwnPropertyNames = function (object) { + return ERROR_PROPERTY_FILTER(object, getOwnPropertyNames(object)); + }; +} else { + exports.keys = keys; + exports.getOwnPropertyNames = getOwnPropertyNames; +} + +// Object.getOwnPropertyDescriptor - supported in IE8 but only on dom elements +function valueObject(value, key) { + return { value: value[key] }; +} + +if (typeof Object.getOwnPropertyDescriptor === 'function') { + try { + Object.getOwnPropertyDescriptor({'a': 1}, 'a'); + exports.getOwnPropertyDescriptor = Object.getOwnPropertyDescriptor; + } catch (e) { + // IE8 dom element issue - use a try catch and default to valueObject + exports.getOwnPropertyDescriptor = function (value, key) { + try { + return Object.getOwnPropertyDescriptor(value, key); + } catch (e) { + return valueObject(value, key); + } + }; + } +} else { + exports.getOwnPropertyDescriptor = valueObject; +} + +},{}],6:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +// UTILITY +var util = require('util'); +var shims = require('_shims'); +var pSlice = Array.prototype.slice; + +// 1. The assert module provides functions that throw +// AssertionError's when particular conditions are not met. The +// assert module must conform to the following interface. + +var assert = module.exports = ok; + +// 2. The AssertionError is defined in assert. +// new assert.AssertionError({ message: message, +// actual: actual, +// expected: expected }) + +assert.AssertionError = function AssertionError(options) { + this.name = 'AssertionError'; + this.actual = options.actual; + this.expected = options.expected; + this.operator = options.operator; + this.message = options.message || getMessage(this); +}; + +// assert.AssertionError instanceof Error +util.inherits(assert.AssertionError, Error); + +function replacer(key, value) { + if (util.isUndefined(value)) { + return '' + value; + } + if (util.isNumber(value) && (isNaN(value) || !isFinite(value))) { + return value.toString(); + } + if (util.isFunction(value) || util.isRegExp(value)) { + return value.toString(); + } + return value; +} + +function truncate(s, n) { + if (util.isString(s)) { + return s.length < n ? s : s.slice(0, n); + } else { + return s; + } +} + +function getMessage(self) { + return truncate(JSON.stringify(self.actual, replacer), 128) + ' ' + + self.operator + ' ' + + truncate(JSON.stringify(self.expected, replacer), 128); +} + +// At present only the three keys mentioned above are used and +// understood by the spec. Implementations or sub modules can pass +// other keys to the AssertionError's constructor - they will be +// ignored. + +// 3. All of the following functions must throw an AssertionError +// when a corresponding condition is not met, with a message that +// may be undefined if not provided. All assertion methods provide +// both the actual and expected values to the assertion error for +// display purposes. + +function fail(actual, expected, message, operator, stackStartFunction) { + throw new assert.AssertionError({ + message: message, + actual: actual, + expected: expected, + operator: operator, + stackStartFunction: stackStartFunction + }); +} + +// EXTENSION! allows for well behaved errors defined elsewhere. +assert.fail = fail; + +// 4. Pure assertion tests whether a value is truthy, as determined +// by !!guard. +// assert.ok(guard, message_opt); +// This statement is equivalent to assert.equal(true, !!guard, +// message_opt);. To test strictly for the value true, use +// assert.strictEqual(true, guard, message_opt);. + +function ok(value, message) { + if (!value) fail(value, true, message, '==', assert.ok); +} +assert.ok = ok; + +// 5. The equality assertion tests shallow, coercive equality with +// ==. +// assert.equal(actual, expected, message_opt); + +assert.equal = function equal(actual, expected, message) { + if (actual != expected) fail(actual, expected, message, '==', assert.equal); +}; + +// 6. The non-equality assertion tests for whether two objects are not equal +// with != assert.notEqual(actual, expected, message_opt); + +assert.notEqual = function notEqual(actual, expected, message) { + if (actual == expected) { + fail(actual, expected, message, '!=', assert.notEqual); + } +}; + +// 7. The equivalence assertion tests a deep equality relation. +// assert.deepEqual(actual, expected, message_opt); + +assert.deepEqual = function deepEqual(actual, expected, message) { + if (!_deepEqual(actual, expected)) { + fail(actual, expected, message, 'deepEqual', assert.deepEqual); + } +}; + +function _deepEqual(actual, expected) { + // 7.1. All identical values are equivalent, as determined by ===. + if (actual === expected) { + return true; + + } else if (util.isBuffer(actual) && util.isBuffer(expected)) { + if (actual.length != expected.length) return false; + + for (var i = 0; i < actual.length; i++) { + if (actual[i] !== expected[i]) return false; + } + + return true; + + // 7.2. If the expected value is a Date object, the actual value is + // equivalent if it is also a Date object that refers to the same time. + } else if (util.isDate(actual) && util.isDate(expected)) { + return actual.getTime() === expected.getTime(); + + // 7.3 If the expected value is a RegExp object, the actual value is + // equivalent if it is also a RegExp object with the same source and + // properties (`global`, `multiline`, `lastIndex`, `ignoreCase`). + } else if (util.isRegExp(actual) && util.isRegExp(expected)) { + return actual.source === expected.source && + actual.global === expected.global && + actual.multiline === expected.multiline && + actual.lastIndex === expected.lastIndex && + actual.ignoreCase === expected.ignoreCase; + + // 7.4. Other pairs that do not both pass typeof value == 'object', + // equivalence is determined by ==. + } else if (!util.isObject(actual) && !util.isObject(expected)) { + return actual == expected; + + // 7.5 For all other Object pairs, including Array objects, equivalence is + // determined by having the same number of owned properties (as verified + // with Object.prototype.hasOwnProperty.call), the same set of keys + // (although not necessarily the same order), equivalent values for every + // corresponding key, and an identical 'prototype' property. Note: this + // accounts for both named and indexed properties on Arrays. + } else { + return objEquiv(actual, expected); + } +} + +function isArguments(object) { + return Object.prototype.toString.call(object) == '[object Arguments]'; +} + +function objEquiv(a, b) { + if (util.isNullOrUndefined(a) || util.isNullOrUndefined(b)) + return false; + // an identical 'prototype' property. + if (a.prototype !== b.prototype) return false; + //~~~I've managed to break Object.keys through screwy arguments passing. + // Converting to array solves the problem. + if (isArguments(a)) { + if (!isArguments(b)) { + return false; + } + a = pSlice.call(a); + b = pSlice.call(b); + return _deepEqual(a, b); + } + try { + var ka = shims.keys(a), + kb = shims.keys(b), + key, i; + } catch (e) {//happens when one is a string literal and the other isn't + return false; + } + // having the same number of owned properties (keys incorporates + // hasOwnProperty) + if (ka.length != kb.length) + return false; + //the same set of keys (although not necessarily the same order), + ka.sort(); + kb.sort(); + //~~~cheap key test + for (i = ka.length - 1; i >= 0; i--) { + if (ka[i] != kb[i]) + return false; + } + //equivalent values for every corresponding key, and + //~~~possibly expensive deep test + for (i = ka.length - 1; i >= 0; i--) { + key = ka[i]; + if (!_deepEqual(a[key], b[key])) return false; + } + return true; +} + +// 8. The non-equivalence assertion tests for any deep inequality. +// assert.notDeepEqual(actual, expected, message_opt); + +assert.notDeepEqual = function notDeepEqual(actual, expected, message) { + if (_deepEqual(actual, expected)) { + fail(actual, expected, message, 'notDeepEqual', assert.notDeepEqual); + } +}; + +// 9. The strict equality assertion tests strict equality, as determined by ===. +// assert.strictEqual(actual, expected, message_opt); + +assert.strictEqual = function strictEqual(actual, expected, message) { + if (actual !== expected) { + fail(actual, expected, message, '===', assert.strictEqual); + } +}; + +// 10. The strict non-equality assertion tests for strict inequality, as +// determined by !==. assert.notStrictEqual(actual, expected, message_opt); + +assert.notStrictEqual = function notStrictEqual(actual, expected, message) { + if (actual === expected) { + fail(actual, expected, message, '!==', assert.notStrictEqual); + } +}; + +function expectedException(actual, expected) { + if (!actual || !expected) { + return false; + } + + if (Object.prototype.toString.call(expected) == '[object RegExp]') { + return expected.test(actual); + } else if (actual instanceof expected) { + return true; + } else if (expected.call({}, actual) === true) { + return true; + } + + return false; +} + +function _throws(shouldThrow, block, expected, message) { + var actual; + + if (util.isString(expected)) { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + message = (expected && expected.name ? ' (' + expected.name + ').' : '.') + + (message ? ' ' + message : '.'); + + if (shouldThrow && !actual) { + fail(actual, expected, 'Missing expected exception' + message); + } + + if (!shouldThrow && expectedException(actual, expected)) { + fail(actual, expected, 'Got unwanted exception' + message); + } + + if ((shouldThrow && actual && expected && + !expectedException(actual, expected)) || (!shouldThrow && actual)) { + throw actual; + } +} + +// 11. Expected to throw an error: +// assert.throws(block, Error_opt, message_opt); + +assert.throws = function(block, /*optional*/error, /*optional*/message) { + _throws.apply(this, [true].concat(pSlice.call(arguments))); +}; + +// EXTENSION! This is annoying to write outside this module. +assert.doesNotThrow = function(block, /*optional*/message) { + _throws.apply(this, [false].concat(pSlice.call(arguments))); +}; + +assert.ifError = function(err) { if (err) {throw err;}}; +},{"_shims":5,"util":7}],7:[function(require,module,exports){ +// Copyright Joyent, Inc. and other Node contributors. +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the +// following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN +// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, +// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. + +var shims = require('_shims'); + +var formatRegExp = /%[sdj%]/g; +exports.format = function(f) { + if (!isString(f)) { + var objects = []; + for (var i = 0; i < arguments.length; i++) { + objects.push(inspect(arguments[i])); + } + return objects.join(' '); + } + + var i = 1; + var args = arguments; + var len = args.length; + var str = String(f).replace(formatRegExp, function(x) { + if (x === '%%') return '%'; + if (i >= len) return x; + switch (x) { + case '%s': return String(args[i++]); + case '%d': return Number(args[i++]); + case '%j': + try { + return JSON.stringify(args[i++]); + } catch (_) { + return '[Circular]'; + } + default: + return x; + } + }); + for (var x = args[i]; i < len; x = args[++i]) { + if (isNull(x) || !isObject(x)) { + str += ' ' + x; + } else { + str += ' ' + inspect(x); + } + } + return str; +}; + +/** + * Echos the value of a value. Trys to print the value out + * in the best way possible given the different types. + * + * @param {Object} obj The object to print out. + * @param {Object} opts Optional options object that alters the output. + */ +/* legacy: obj, showHidden, depth, colors*/ +function inspect(obj, opts) { + // default options + var ctx = { + seen: [], + stylize: stylizeNoColor + }; + // legacy... + if (arguments.length >= 3) ctx.depth = arguments[2]; + if (arguments.length >= 4) ctx.colors = arguments[3]; + if (isBoolean(opts)) { + // legacy... + ctx.showHidden = opts; + } else if (opts) { + // got an "options" object + exports._extend(ctx, opts); + } + // set default options + if (isUndefined(ctx.showHidden)) ctx.showHidden = false; + if (isUndefined(ctx.depth)) ctx.depth = 2; + if (isUndefined(ctx.colors)) ctx.colors = false; + if (isUndefined(ctx.customInspect)) ctx.customInspect = true; + if (ctx.colors) ctx.stylize = stylizeWithColor; + return formatValue(ctx, obj, ctx.depth); +} +exports.inspect = inspect; + + +// http://en.wikipedia.org/wiki/ANSI_escape_code#graphics +inspect.colors = { + 'bold' : [1, 22], + 'italic' : [3, 23], + 'underline' : [4, 24], + 'inverse' : [7, 27], + 'white' : [37, 39], + 'grey' : [90, 39], + 'black' : [30, 39], + 'blue' : [34, 39], + 'cyan' : [36, 39], + 'green' : [32, 39], + 'magenta' : [35, 39], + 'red' : [31, 39], + 'yellow' : [33, 39] +}; + +// Don't use 'blue' not visible on cmd.exe +inspect.styles = { + 'special': 'cyan', + 'number': 'yellow', + 'boolean': 'yellow', + 'undefined': 'grey', + 'null': 'bold', + 'string': 'green', + 'date': 'magenta', + // "name": intentionally not styling + 'regexp': 'red' +}; + + +function stylizeWithColor(str, styleType) { + var style = inspect.styles[styleType]; + + if (style) { + return '\u001b[' + inspect.colors[style][0] + 'm' + str + + '\u001b[' + inspect.colors[style][1] + 'm'; + } else { + return str; + } +} + + +function stylizeNoColor(str, styleType) { + return str; +} + + +function arrayToHash(array) { + var hash = {}; + + shims.forEach(array, function(val, idx) { + hash[val] = true; + }); + + return hash; +} + + +function formatValue(ctx, value, recurseTimes) { + // Provide a hook for user-specified inspect functions. + // Check that value is an object with an inspect function on it + if (ctx.customInspect && + value && + isFunction(value.inspect) && + // Filter out the util module, it's inspect function is special + value.inspect !== exports.inspect && + // Also filter out any prototype objects using the circular check. + !(value.constructor && value.constructor.prototype === value)) { + var ret = value.inspect(recurseTimes); + if (!isString(ret)) { + ret = formatValue(ctx, ret, recurseTimes); + } + return ret; + } + + // Primitive types cannot have properties + var primitive = formatPrimitive(ctx, value); + if (primitive) { + return primitive; + } + + // Look up the keys of the object. + var keys = shims.keys(value); + var visibleKeys = arrayToHash(keys); + + if (ctx.showHidden) { + keys = shims.getOwnPropertyNames(value); + } + + // Some type of object without properties can be shortcutted. + if (keys.length === 0) { + if (isFunction(value)) { + var name = value.name ? ': ' + value.name : ''; + return ctx.stylize('[Function' + name + ']', 'special'); + } + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } + if (isDate(value)) { + return ctx.stylize(Date.prototype.toString.call(value), 'date'); + } + if (isError(value)) { + return formatError(value); + } + } + + var base = '', array = false, braces = ['{', '}']; + + // Make Array say that they are Array + if (isArray(value)) { + array = true; + braces = ['[', ']']; + } + + // Make functions say that they are functions + if (isFunction(value)) { + var n = value.name ? ': ' + value.name : ''; + base = ' [Function' + n + ']'; + } + + // Make RegExps say that they are RegExps + if (isRegExp(value)) { + base = ' ' + RegExp.prototype.toString.call(value); + } + + // Make dates with properties first say the date + if (isDate(value)) { + base = ' ' + Date.prototype.toUTCString.call(value); + } + + // Make error with message first say the error + if (isError(value)) { + base = ' ' + formatError(value); + } + + if (keys.length === 0 && (!array || value.length == 0)) { + return braces[0] + base + braces[1]; + } + + if (recurseTimes < 0) { + if (isRegExp(value)) { + return ctx.stylize(RegExp.prototype.toString.call(value), 'regexp'); + } else { + return ctx.stylize('[Object]', 'special'); + } + } + + ctx.seen.push(value); + + var output; + if (array) { + output = formatArray(ctx, value, recurseTimes, visibleKeys, keys); + } else { + output = keys.map(function(key) { + return formatProperty(ctx, value, recurseTimes, visibleKeys, key, array); + }); + } + + ctx.seen.pop(); + + return reduceToSingleString(output, base, braces); +} + + +function formatPrimitive(ctx, value) { + if (isUndefined(value)) + return ctx.stylize('undefined', 'undefined'); + if (isString(value)) { + var simple = '\'' + JSON.stringify(value).replace(/^"|"$/g, '') + .replace(/'/g, "\\'") + .replace(/\\"/g, '"') + '\''; + return ctx.stylize(simple, 'string'); + } + if (isNumber(value)) + return ctx.stylize('' + value, 'number'); + if (isBoolean(value)) + return ctx.stylize('' + value, 'boolean'); + // For some reason typeof null is "object", so special case here. + if (isNull(value)) + return ctx.stylize('null', 'null'); +} + + +function formatError(value) { + return '[' + Error.prototype.toString.call(value) + ']'; +} + + +function formatArray(ctx, value, recurseTimes, visibleKeys, keys) { + var output = []; + for (var i = 0, l = value.length; i < l; ++i) { + if (hasOwnProperty(value, String(i))) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + String(i), true)); + } else { + output.push(''); + } + } + + shims.forEach(keys, function(key) { + if (!key.match(/^\d+$/)) { + output.push(formatProperty(ctx, value, recurseTimes, visibleKeys, + key, true)); + } + }); + return output; +} + + +function formatProperty(ctx, value, recurseTimes, visibleKeys, key, array) { + var name, str, desc; + desc = shims.getOwnPropertyDescriptor(value, key) || { value: value[key] }; + if (desc.get) { + if (desc.set) { + str = ctx.stylize('[Getter/Setter]', 'special'); + } else { + str = ctx.stylize('[Getter]', 'special'); + } + } else { + if (desc.set) { + str = ctx.stylize('[Setter]', 'special'); + } + } + + if (!hasOwnProperty(visibleKeys, key)) { + name = '[' + key + ']'; + } + if (!str) { + if (shims.indexOf(ctx.seen, desc.value) < 0) { + if (isNull(recurseTimes)) { + str = formatValue(ctx, desc.value, null); + } else { + str = formatValue(ctx, desc.value, recurseTimes - 1); + } + if (str.indexOf('\n') > -1) { + if (array) { + str = str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n').substr(2); + } else { + str = '\n' + str.split('\n').map(function(line) { + return ' ' + line; + }).join('\n'); + } + } + } else { + str = ctx.stylize('[Circular]', 'special'); + } + } + if (isUndefined(name)) { + if (array && key.match(/^\d+$/)) { + return str; + } + name = JSON.stringify('' + key); + if (name.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)) { + name = name.substr(1, name.length - 2); + name = ctx.stylize(name, 'name'); + } else { + name = name.replace(/'/g, "\\'") + .replace(/\\"/g, '"') + .replace(/(^"|"$)/g, "'"); + name = ctx.stylize(name, 'string'); + } + } + + return name + ': ' + str; +} + + +function reduceToSingleString(output, base, braces) { + var numLinesEst = 0; + var length = shims.reduce(output, function(prev, cur) { + numLinesEst++; + if (cur.indexOf('\n') >= 0) numLinesEst++; + return prev + cur.replace(/\u001b\[\d\d?m/g, '').length + 1; + }, 0); + + if (length > 60) { + return braces[0] + + (base === '' ? '' : base + '\n ') + + ' ' + + output.join(',\n ') + + ' ' + + braces[1]; + } + + return braces[0] + base + ' ' + output.join(', ') + ' ' + braces[1]; +} + + +// NOTE: These type checking functions intentionally don't use `instanceof` +// because it is fragile and can be easily faked with `Object.create()`. +function isArray(ar) { + return shims.isArray(ar); +} +exports.isArray = isArray; + +function isBoolean(arg) { + return typeof arg === 'boolean'; +} +exports.isBoolean = isBoolean; + +function isNull(arg) { + return arg === null; +} +exports.isNull = isNull; + +function isNullOrUndefined(arg) { + return arg == null; +} +exports.isNullOrUndefined = isNullOrUndefined; + +function isNumber(arg) { + return typeof arg === 'number'; +} +exports.isNumber = isNumber; + +function isString(arg) { + return typeof arg === 'string'; +} +exports.isString = isString; + +function isSymbol(arg) { + return typeof arg === 'symbol'; +} +exports.isSymbol = isSymbol; + +function isUndefined(arg) { + return arg === void 0; +} +exports.isUndefined = isUndefined; + +function isRegExp(re) { + return isObject(re) && objectToString(re) === '[object RegExp]'; +} +exports.isRegExp = isRegExp; + +function isObject(arg) { + return typeof arg === 'object' && arg; +} +exports.isObject = isObject; + +function isDate(d) { + return isObject(d) && objectToString(d) === '[object Date]'; +} +exports.isDate = isDate; + +function isError(e) { + return isObject(e) && objectToString(e) === '[object Error]'; +} +exports.isError = isError; + +function isFunction(arg) { + return typeof arg === 'function'; +} +exports.isFunction = isFunction; + +function isPrimitive(arg) { + return arg === null || + typeof arg === 'boolean' || + typeof arg === 'number' || + typeof arg === 'string' || + typeof arg === 'symbol' || // ES6 symbol + typeof arg === 'undefined'; +} +exports.isPrimitive = isPrimitive; + +function isBuffer(arg) { + return arg instanceof Buffer; +} +exports.isBuffer = isBuffer; + +function objectToString(o) { + return Object.prototype.toString.call(o); +} + + +function pad(n) { + return n < 10 ? '0' + n.toString(10) : n.toString(10); +} + + +var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', + 'Oct', 'Nov', 'Dec']; + +// 26 Feb 16:19:34 +function timestamp() { + var d = new Date(); + var time = [pad(d.getHours()), + pad(d.getMinutes()), + pad(d.getSeconds())].join(':'); + return [d.getDate(), months[d.getMonth()], time].join(' '); +} + + +// log is just a thin wrapper to console.log that prepends a timestamp +exports.log = function() { + console.log('%s - %s', timestamp(), exports.format.apply(exports, arguments)); +}; + + +/** + * Inherit the prototype methods from one constructor into another. + * + * The Function.prototype.inherits from lang.js rewritten as a standalone + * function (not on Function.prototype). NOTE: If this file is to be loaded + * during bootstrapping this function needs to be rewritten using some native + * functions as prototype setup using normal JavaScript does not work as + * expected during bootstrapping (see mirror.js in r114903). + * + * @param {function} ctor Constructor function which needs to inherit the + * prototype. + * @param {function} superCtor Constructor function to inherit prototype from. + */ +exports.inherits = function(ctor, superCtor) { + ctor.super_ = superCtor; + ctor.prototype = shims.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); +}; + +exports._extend = function(origin, add) { + // Don't do anything if add isn't an object + if (!add || !isObject(add)) return origin; + + var keys = shims.keys(add); + var i = keys.length; + while (i--) { + origin[keys[i]] = add[keys[i]]; + } + return origin; +}; + +function hasOwnProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); +} + +},{"_shims":5}]},{},[]) +;;module.exports=require("buffer-browserify") + +},{}],5:[function(require,module,exports){ +// shim for using process in browser + +var process = module.exports = {}; + +process.nextTick = (function () { + var canSetImmediate = typeof window !== 'undefined' + && window.setImmediate; + var canPost = typeof window !== 'undefined' + && window.postMessage && window.addEventListener + ; + + if (canSetImmediate) { + return function (f) { return window.setImmediate(f) }; + } + + if (canPost) { + var queue = []; + window.addEventListener('message', function (ev) { + if (ev.source === window && ev.data === 'process-tick') { + ev.stopPropagation(); + if (queue.length > 0) { + var fn = queue.shift(); + fn(); + } + } + }, true); + + return function nextTick(fn) { + queue.push(fn); + window.postMessage('process-tick', '*'); + }; + } + + return function nextTick(fn) { + setTimeout(fn, 0); + }; +})(); + +process.title = 'browser'; +process.browser = true; +process.env = {}; +process.argv = []; + +process.binding = function (name) { + throw new Error('process.binding is not supported'); +} + +// TODO(shtylman) +process.cwd = function () { return '/' }; +process.chdir = function (dir) { + throw new Error('process.chdir is not supported'); +}; + +},{}],6:[function(require,module,exports){ +/* + Copyright (C) 2013 Ariya Hidayat + Copyright (C) 2013 Thaddee Tyl + Copyright (C) 2012 Ariya Hidayat + Copyright (C) 2012 Mathias Bynens + Copyright (C) 2012 Joost-Wim Boekesteijn + Copyright (C) 2012 Kris Kowal + Copyright (C) 2012 Yusuke Suzuki + Copyright (C) 2012 Arpad Borsos + Copyright (C) 2011 Ariya Hidayat + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +/*jslint bitwise:true plusplus:true */ +/*global esprima:true, define:true, exports:true, window: true, +throwError: true, generateStatement: true, peek: true, +parseAssignmentExpression: true, parseBlock: true, +parseClassExpression: true, parseClassDeclaration: true, parseExpression: true, +parseForStatement: true, +parseFunctionDeclaration: true, parseFunctionExpression: true, +parseFunctionSourceElements: true, parseVariableIdentifier: true, +parseImportSpecifier: true, +parseLeftHandSideExpression: true, parseParams: true, validateParam: true, +parseSpreadOrAssignmentExpression: true, +parseStatement: true, parseSourceElement: true, parseModuleBlock: true, parseConciseBody: true, +advanceXJSChild: true, isXJSIdentifierStart: true, isXJSIdentifierPart: true, +scanXJSStringLiteral: true, scanXJSIdentifier: true, +parseXJSAttributeValue: true, parseXJSChild: true, parseXJSElement: true, parseXJSExpressionContainer: true, parseXJSEmptyExpression: true, +parseYieldExpression: true +*/ + +(function (root, factory) { + 'use strict'; + + // Universal Module Definition (UMD) to support AMD, CommonJS/Node.js, + // Rhino, and plain browser loading. + if (typeof define === 'function' && define.amd) { + define(['exports'], factory); + } else if (typeof exports !== 'undefined') { + factory(exports); + } else { + factory((root.esprima = {})); + } +}(this, function (exports) { + 'use strict'; + + var Token, + TokenName, + FnExprTokens, + Syntax, + PropertyKind, + Messages, + Regex, + SyntaxTreeDelegate, + XHTMLEntities, + ClassPropertyType, + source, + strict, + index, + lineNumber, + lineStart, + length, + delegate, + lookahead, + state, + extra; + + Token = { + BooleanLiteral: 1, + EOF: 2, + Identifier: 3, + Keyword: 4, + NullLiteral: 5, + NumericLiteral: 6, + Punctuator: 7, + StringLiteral: 8, + RegularExpression: 9, + Template: 10, + XJSIdentifier: 11, + XJSText: 12 + }; + + TokenName = {}; + TokenName[Token.BooleanLiteral] = 'Boolean'; + TokenName[Token.EOF] = ''; + TokenName[Token.Identifier] = 'Identifier'; + TokenName[Token.Keyword] = 'Keyword'; + TokenName[Token.NullLiteral] = 'Null'; + TokenName[Token.NumericLiteral] = 'Numeric'; + TokenName[Token.Punctuator] = 'Punctuator'; + TokenName[Token.StringLiteral] = 'String'; + TokenName[Token.XJSIdentifier] = 'XJSIdentifier'; + TokenName[Token.XJSText] = 'XJSText'; + TokenName[Token.RegularExpression] = 'RegularExpression'; + + // A function following one of those tokens is an expression. + FnExprTokens = ["(", "{", "[", "in", "typeof", "instanceof", "new", + "return", "case", "delete", "throw", "void", + // assignment operators + "=", "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", + "&=", "|=", "^=", ",", + // binary/unary operators + "+", "-", "*", "/", "%", "++", "--", "<<", ">>", ">>>", "&", + "|", "^", "!", "~", "&&", "||", "?", ":", "===", "==", ">=", + "<=", "<", ">", "!=", "!=="]; + + Syntax = { + ArrayExpression: 'ArrayExpression', + ArrayPattern: 'ArrayPattern', + ArrowFunctionExpression: 'ArrowFunctionExpression', + AssignmentExpression: 'AssignmentExpression', + BinaryExpression: 'BinaryExpression', + BlockStatement: 'BlockStatement', + BreakStatement: 'BreakStatement', + CallExpression: 'CallExpression', + CatchClause: 'CatchClause', + ClassBody: 'ClassBody', + ClassDeclaration: 'ClassDeclaration', + ClassExpression: 'ClassExpression', + ClassHeritage: 'ClassHeritage', + ComprehensionBlock: 'ComprehensionBlock', + ComprehensionExpression: 'ComprehensionExpression', + ConditionalExpression: 'ConditionalExpression', + ContinueStatement: 'ContinueStatement', + DebuggerStatement: 'DebuggerStatement', + DoWhileStatement: 'DoWhileStatement', + EmptyStatement: 'EmptyStatement', + ExportDeclaration: 'ExportDeclaration', + ExportBatchSpecifier: 'ExportBatchSpecifier', + ExportSpecifier: 'ExportSpecifier', + ExpressionStatement: 'ExpressionStatement', + ForInStatement: 'ForInStatement', + ForOfStatement: 'ForOfStatement', + ForStatement: 'ForStatement', + FunctionDeclaration: 'FunctionDeclaration', + FunctionExpression: 'FunctionExpression', + Identifier: 'Identifier', + IfStatement: 'IfStatement', + ImportDeclaration: 'ImportDeclaration', + ImportSpecifier: 'ImportSpecifier', + LabeledStatement: 'LabeledStatement', + Literal: 'Literal', + LogicalExpression: 'LogicalExpression', + MemberExpression: 'MemberExpression', + MethodDefinition: 'MethodDefinition', + ModuleDeclaration: 'ModuleDeclaration', + NewExpression: 'NewExpression', + ObjectExpression: 'ObjectExpression', + ObjectPattern: 'ObjectPattern', + Program: 'Program', + Property: 'Property', + ReturnStatement: 'ReturnStatement', + SequenceExpression: 'SequenceExpression', + SpreadElement: 'SpreadElement', + SwitchCase: 'SwitchCase', + SwitchStatement: 'SwitchStatement', + TaggedTemplateExpression: 'TaggedTemplateExpression', + TemplateElement: 'TemplateElement', + TemplateLiteral: 'TemplateLiteral', + ThisExpression: 'ThisExpression', + ThrowStatement: 'ThrowStatement', + TryStatement: 'TryStatement', + TypeAnnotatedIdentifier: 'TypeAnnotatedIdentifier', + TypeAnnotation: 'TypeAnnotation', + UnaryExpression: 'UnaryExpression', + UpdateExpression: 'UpdateExpression', + VariableDeclaration: 'VariableDeclaration', + VariableDeclarator: 'VariableDeclarator', + WhileStatement: 'WhileStatement', + WithStatement: 'WithStatement', + XJSIdentifier: 'XJSIdentifier', + XJSEmptyExpression: 'XJSEmptyExpression', + XJSExpressionContainer: 'XJSExpressionContainer', + XJSElement: 'XJSElement', + XJSClosingElement: 'XJSClosingElement', + XJSOpeningElement: 'XJSOpeningElement', + XJSAttribute: 'XJSAttribute', + XJSText: 'XJSText', + YieldExpression: 'YieldExpression' + }; + + PropertyKind = { + Data: 1, + Get: 2, + Set: 4 + }; + + ClassPropertyType = { + static: 'static', + prototype: 'prototype' + }; + + // Error messages should be identical to V8. + Messages = { + UnexpectedToken: 'Unexpected token %0', + UnexpectedNumber: 'Unexpected number', + UnexpectedString: 'Unexpected string', + UnexpectedIdentifier: 'Unexpected identifier', + UnexpectedReserved: 'Unexpected reserved word', + UnexpectedTemplate: 'Unexpected quasi %0', + UnexpectedEOS: 'Unexpected end of input', + NewlineAfterThrow: 'Illegal newline after throw', + InvalidRegExp: 'Invalid regular expression', + UnterminatedRegExp: 'Invalid regular expression: missing /', + InvalidLHSInAssignment: 'Invalid left-hand side in assignment', + InvalidLHSInFormalsList: 'Invalid left-hand side in formals list', + InvalidLHSInForIn: 'Invalid left-hand side in for-in', + MultipleDefaultsInSwitch: 'More than one default clause in switch statement', + NoCatchOrFinally: 'Missing catch or finally after try', + UnknownLabel: 'Undefined label \'%0\'', + Redeclaration: '%0 \'%1\' has already been declared', + IllegalContinue: 'Illegal continue statement', + IllegalBreak: 'Illegal break statement', + IllegalDuplicateClassProperty: 'Illegal duplicate property in class definition', + IllegalReturn: 'Illegal return statement', + IllegalYield: 'Illegal yield expression', + IllegalSpread: 'Illegal spread element', + StrictModeWith: 'Strict mode code may not include a with statement', + StrictCatchVariable: 'Catch variable may not be eval or arguments in strict mode', + StrictVarName: 'Variable name may not be eval or arguments in strict mode', + StrictParamName: 'Parameter name eval or arguments is not allowed in strict mode', + StrictParamDupe: 'Strict mode function may not have duplicate parameter names', + ParameterAfterRestParameter: 'Rest parameter must be final parameter of an argument list', + DefaultRestParameter: 'Rest parameter can not have a default value', + ElementAfterSpreadElement: 'Spread must be the final element of an element list', + ObjectPatternAsRestParameter: 'Invalid rest parameter', + ObjectPatternAsSpread: 'Invalid spread argument', + StrictFunctionName: 'Function name may not be eval or arguments in strict mode', + StrictOctalLiteral: 'Octal literals are not allowed in strict mode.', + StrictDelete: 'Delete of an unqualified identifier in strict mode.', + StrictDuplicateProperty: 'Duplicate data property in object literal not allowed in strict mode', + AccessorDataProperty: 'Object literal may not have data and accessor property with the same name', + AccessorGetSet: 'Object literal may not have multiple get/set accessors with the same name', + StrictLHSAssignment: 'Assignment to eval or arguments is not allowed in strict mode', + StrictLHSPostfix: 'Postfix increment/decrement may not have eval or arguments operand in strict mode', + StrictLHSPrefix: 'Prefix increment/decrement may not have eval or arguments operand in strict mode', + StrictReservedWord: 'Use of future reserved word in strict mode', + NewlineAfterModule: 'Illegal newline after module', + NoFromAfterImport: 'Missing from after import', + InvalidModuleSpecifier: 'Invalid module specifier', + NestedModule: 'Module declaration can not be nested', + NoYieldInGenerator: 'Missing yield in generator', + NoUnintializedConst: 'Const must be initialized', + ComprehensionRequiresBlock: 'Comprehension must have at least one block', + ComprehensionError: 'Comprehension Error', + EachNotAllowed: 'Each is not supported', + InvalidXJSTagName: 'XJS tag name can not be empty', + InvalidXJSAttributeValue: 'XJS value should be either an expression or a quoted XJS text', + ExpectedXJSClosingTag: 'Expected corresponding XJS closing tag for %0' + }; + + // See also tools/generate-unicode-regex.py. + Regex = { + NonAsciiIdentifierStart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u05d0-\u05ea\u05f0-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u08a0\u08a2-\u08ac\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0977\u0979-\u097f\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d\u0c58\u0c59\u0c60\u0c61\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d60\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191c\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19c1-\u19c7\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2e2f\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua697\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa80-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]'), + NonAsciiIdentifierPart: new RegExp('[\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0300-\u0374\u0376\u0377\u037a-\u037d\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u0483-\u0487\u048a-\u0527\u0531-\u0556\u0559\u0561-\u0587\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u05d0-\u05ea\u05f0-\u05f2\u0610-\u061a\u0620-\u0669\u066e-\u06d3\u06d5-\u06dc\u06df-\u06e8\u06ea-\u06fc\u06ff\u0710-\u074a\u074d-\u07b1\u07c0-\u07f5\u07fa\u0800-\u082d\u0840-\u085b\u08a0\u08a2-\u08ac\u08e4-\u08fe\u0900-\u0963\u0966-\u096f\u0971-\u0977\u0979-\u097f\u0981-\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bc-\u09c4\u09c7\u09c8\u09cb-\u09ce\u09d7\u09dc\u09dd\u09df-\u09e3\u09e6-\u09f1\u0a01-\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a59-\u0a5c\u0a5e\u0a66-\u0a75\u0a81-\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abc-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ad0\u0ae0-\u0ae3\u0ae6-\u0aef\u0b01-\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3c-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b5c\u0b5d\u0b5f-\u0b63\u0b66-\u0b6f\u0b71\u0b82\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd0\u0bd7\u0be6-\u0bef\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c33\u0c35-\u0c39\u0c3d-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c58\u0c59\u0c60-\u0c63\u0c66-\u0c6f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbc-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0cde\u0ce0-\u0ce3\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d44\u0d46-\u0d48\u0d4a-\u0d4e\u0d57\u0d60-\u0d63\u0d66-\u0d6f\u0d7a-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0df2\u0df3\u0e01-\u0e3a\u0e40-\u0e4e\u0e50-\u0e59\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb9\u0ebb-\u0ebd\u0ec0-\u0ec4\u0ec6\u0ec8-\u0ecd\u0ed0-\u0ed9\u0edc-\u0edf\u0f00\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e-\u0f47\u0f49-\u0f6c\u0f71-\u0f84\u0f86-\u0f97\u0f99-\u0fbc\u0fc6\u1000-\u1049\u1050-\u109d\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u135d-\u135f\u1380-\u138f\u13a0-\u13f4\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f0\u1700-\u170c\u170e-\u1714\u1720-\u1734\u1740-\u1753\u1760-\u176c\u176e-\u1770\u1772\u1773\u1780-\u17d3\u17d7\u17dc\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u1820-\u1877\u1880-\u18aa\u18b0-\u18f5\u1900-\u191c\u1920-\u192b\u1930-\u193b\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19d9\u1a00-\u1a1b\u1a20-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1aa7\u1b00-\u1b4b\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1bf3\u1c00-\u1c37\u1c40-\u1c49\u1c4d-\u1c7d\u1cd0-\u1cd2\u1cd4-\u1cf6\u1d00-\u1de6\u1dfc-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200c\u200d\u203f\u2040\u2054\u2071\u207f\u2090-\u209c\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d7f-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u2de0-\u2dff\u2e2f\u3005-\u3007\u3021-\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u3099\u309a\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fcc\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua62b\ua640-\ua66f\ua674-\ua67d\ua67f-\ua697\ua69f-\ua6f1\ua717-\ua71f\ua722-\ua788\ua78b-\ua78e\ua790-\ua793\ua7a0-\ua7aa\ua7f8-\ua827\ua840-\ua873\ua880-\ua8c4\ua8d0-\ua8d9\ua8e0-\ua8f7\ua8fb\ua900-\ua92d\ua930-\ua953\ua960-\ua97c\ua980-\ua9c0\ua9cf-\ua9d9\uaa00-\uaa36\uaa40-\uaa4d\uaa50-\uaa59\uaa60-\uaa76\uaa7a\uaa7b\uaa80-\uaac2\uaadb-\uaadd\uaae0-\uaaef\uaaf2-\uaaf6\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uabc0-\uabea\uabec\uabed\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe00-\ufe0f\ufe20-\ufe26\ufe33\ufe34\ufe4d-\ufe4f\ufe70-\ufe74\ufe76-\ufefc\uff10-\uff19\uff21-\uff3a\uff3f\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]') + }; + + // Ensure the condition is true, otherwise throw an error. + // This is only to have a better contract semantic, i.e. another safety net + // to catch a logic error. The condition shall be fulfilled in normal case. + // Do NOT use this to enforce a certain condition on any user input. + + function assert(condition, message) { + if (!condition) { + throw new Error('ASSERT: ' + message); + } + } + + function isDecimalDigit(ch) { + return (ch >= 48 && ch <= 57); // 0..9 + } + + function isHexDigit(ch) { + return '0123456789abcdefABCDEF'.indexOf(ch) >= 0; + } + + function isOctalDigit(ch) { + return '01234567'.indexOf(ch) >= 0; + } + + + // 7.2 White Space + + function isWhiteSpace(ch) { + return (ch === 32) || // space + (ch === 9) || // tab + (ch === 0xB) || + (ch === 0xC) || + (ch === 0xA0) || + (ch >= 0x1680 && '\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\uFEFF'.indexOf(String.fromCharCode(ch)) > 0); + } + + // 7.3 Line Terminators + + function isLineTerminator(ch) { + return (ch === 10) || (ch === 13) || (ch === 0x2028) || (ch === 0x2029); + } + + // 7.6 Identifier Names and Identifiers + + function isIdentifierStart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierStart.test(String.fromCharCode(ch))); + } + + function isIdentifierPart(ch) { + return (ch === 36) || (ch === 95) || // $ (dollar) and _ (underscore) + (ch >= 65 && ch <= 90) || // A..Z + (ch >= 97 && ch <= 122) || // a..z + (ch >= 48 && ch <= 57) || // 0..9 + (ch === 92) || // \ (backslash) + ((ch >= 0x80) && Regex.NonAsciiIdentifierPart.test(String.fromCharCode(ch))); + } + + // 7.6.1.2 Future Reserved Words + + function isFutureReservedWord(id) { + switch (id) { + case 'class': + case 'enum': + case 'export': + case 'extends': + case 'import': + case 'super': + return true; + default: + return false; + } + } + + function isStrictModeReservedWord(id) { + switch (id) { + case 'implements': + case 'interface': + case 'package': + case 'private': + case 'protected': + case 'public': + case 'static': + case 'yield': + case 'let': + return true; + default: + return false; + } + } + + function isRestrictedWord(id) { + return id === 'eval' || id === 'arguments'; + } + + // 7.6.1.1 Keywords + + function isKeyword(id) { + if (strict && isStrictModeReservedWord(id)) { + return true; + } + + // 'const' is specialized as Keyword in V8. + // 'yield' and 'let' are for compatiblity with SpiderMonkey and ES.next. + // Some others are from future reserved words. + + switch (id.length) { + case 2: + return (id === 'if') || (id === 'in') || (id === 'do'); + case 3: + return (id === 'var') || (id === 'for') || (id === 'new') || + (id === 'try') || (id === 'let'); + case 4: + return (id === 'this') || (id === 'else') || (id === 'case') || + (id === 'void') || (id === 'with') || (id === 'enum'); + case 5: + return (id === 'while') || (id === 'break') || (id === 'catch') || + (id === 'throw') || (id === 'const') || (id === 'yield') || + (id === 'class') || (id === 'super'); + case 6: + return (id === 'return') || (id === 'typeof') || (id === 'delete') || + (id === 'switch') || (id === 'export') || (id === 'import'); + case 7: + return (id === 'default') || (id === 'finally') || (id === 'extends'); + case 8: + return (id === 'function') || (id === 'continue') || (id === 'debugger'); + case 10: + return (id === 'instanceof'); + default: + return false; + } + } + + // 7.4 Comments + + function skipComment() { + var ch, blockComment, lineComment; + + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source.charCodeAt(index); + + if (lineComment) { + ++index; + if (isLineTerminator(ch)) { + lineComment = false; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } + } else if (blockComment) { + if (isLineTerminator(ch)) { + if (ch === 13 && source.charCodeAt(index + 1) === 10) { + ++index; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source.charCodeAt(index++); + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + // Block comment ends with '*/' (char #42, char #47). + if (ch === 42) { + ch = source.charCodeAt(index); + if (ch === 47) { + ++index; + blockComment = false; + } + } + } + } else if (ch === 47) { + ch = source.charCodeAt(index + 1); + // Line comment starts with '//' (char #47, char #47). + if (ch === 47) { + index += 2; + lineComment = true; + } else if (ch === 42) { + // Block comment starts with '/*' (char #47, char #42). + index += 2; + blockComment = true; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch)) { + ++index; + } else if (isLineTerminator(ch)) { + ++index; + if (ch === 13 && source.charCodeAt(index) === 10) { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function scanHexEscape(prefix) { + var i, len, ch, code = 0; + + len = (prefix === 'u') ? 4 : 2; + for (i = 0; i < len; ++i) { + if (index < length && isHexDigit(source[index])) { + ch = source[index++]; + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } else { + return ''; + } + } + return String.fromCharCode(code); + } + + function scanUnicodeCodePointEscape() { + var ch, code, cu1, cu2; + + ch = source[index]; + code = 0; + + // At least, one hex digit is required. + if (ch === '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + while (index < length) { + ch = source[index++]; + if (!isHexDigit(ch)) { + break; + } + code = code * 16 + '0123456789abcdef'.indexOf(ch.toLowerCase()); + } + + if (code > 0x10FFFF || ch !== '}') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // UTF-16 Encoding + if (code <= 0xFFFF) { + return String.fromCharCode(code); + } + cu1 = ((code - 0x10000) >> 10) + 0xD800; + cu2 = ((code - 0x10000) & 1023) + 0xDC00; + return String.fromCharCode(cu1, cu2); + } + + function getEscapedIdentifier() { + var ch, id; + + ch = source.charCodeAt(index++); + id = String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierStart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id = ch; + } + + while (index < length) { + ch = source.charCodeAt(index); + if (!isIdentifierPart(ch)) { + break; + } + ++index; + id += String.fromCharCode(ch); + + // '\u' (char #92, char #117) denotes an escaped character. + if (ch === 92) { + id = id.substr(0, id.length - 1); + if (source.charCodeAt(index) !== 117) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + ++index; + ch = scanHexEscape('u'); + if (!ch || ch === '\\' || !isIdentifierPart(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + id += ch; + } + } + + return id; + } + + function getIdentifier() { + var start, ch; + + start = index++; + while (index < length) { + ch = source.charCodeAt(index); + if (ch === 92) { + // Blackslash (char #92) marks Unicode escape sequence. + index = start; + return getEscapedIdentifier(); + } + if (isIdentifierPart(ch)) { + ++index; + } else { + break; + } + } + + return source.slice(start, index); + } + + function scanIdentifier() { + var start, id, type; + + start = index; + + // Backslash (char #92) starts an escaped character. + id = (source.charCodeAt(index) === 92) ? getEscapedIdentifier() : getIdentifier(); + + // There is no keyword or literal with only one character. + // Thus, it must be an identifier. + if (id.length === 1) { + type = Token.Identifier; + } else if (isKeyword(id)) { + type = Token.Keyword; + } else if (id === 'null') { + type = Token.NullLiteral; + } else if (id === 'true' || id === 'false') { + type = Token.BooleanLiteral; + } else { + type = Token.Identifier; + } + + return { + type: type, + value: id, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + + // 7.7 Punctuators + + function scanPunctuator() { + var start = index, + code = source.charCodeAt(index), + code2, + ch1 = source[index], + ch2, + ch3, + ch4; + + switch (code) { + // Check for most common single-character punctuators. + case 40: // ( open bracket + case 41: // ) close bracket + case 59: // ; semicolon + case 44: // , comma + case 123: // { open curly brace + case 125: // } close curly brace + case 91: // [ + case 93: // ] + case 58: // : + case 63: // ? + case 126: // ~ + ++index; + if (extra.tokenize) { + if (code === 40) { + extra.openParenToken = extra.tokens.length; + } else if (code === 123) { + extra.openCurlyToken = extra.tokens.length; + } + } + return { + type: Token.Punctuator, + value: String.fromCharCode(code), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + default: + code2 = source.charCodeAt(index + 1); + + // '=' (char #61) marks an assignment or comparison operator. + if (code2 === 61) { + switch (code) { + case 37: // % + case 38: // & + case 42: // *: + case 43: // + + case 45: // - + case 47: // / + case 60: // < + case 62: // > + case 94: // ^ + case 124: // | + index += 2; + return { + type: Token.Punctuator, + value: String.fromCharCode(code) + String.fromCharCode(code2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + + case 33: // ! + case 61: // = + index += 2; + + // !== and === + if (source.charCodeAt(index) === 61) { + ++index; + } + return { + type: Token.Punctuator, + value: source.slice(start, index), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + default: + break; + } + } + break; + } + + // Peek more characters. + + ch2 = source[index + 1]; + ch3 = source[index + 2]; + ch4 = source[index + 3]; + + // 4-character punctuator: >>>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + if (ch4 === '=') { + index += 4; + return { + type: Token.Punctuator, + value: '>>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + } + + // 3-character punctuators: === !== >>> <<= >>= + + if (ch1 === '>' && ch2 === '>' && ch3 === '>') { + index += 3; + return { + type: Token.Punctuator, + value: '>>>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '<' && ch2 === '<' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '<<=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '>' && ch2 === '>' && ch3 === '=') { + index += 3; + return { + type: Token.Punctuator, + value: '>>=', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.' && ch2 === '.' && ch3 === '.') { + index += 3; + return { + type: Token.Punctuator, + value: '...', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // Other 2-character punctuators: ++ -- << >> && || + + if (ch1 === ch2 && ('+-<>&|'.indexOf(ch1) >= 0)) { + index += 2; + return { + type: Token.Punctuator, + value: ch1 + ch2, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '=' && ch2 === '>') { + index += 2; + return { + type: Token.Punctuator, + value: '=>', + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if ('<>=!+-*%&|^/'.indexOf(ch1) >= 0) { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + if (ch1 === '.') { + ++index; + return { + type: Token.Punctuator, + value: ch1, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + // 7.8.3 Numeric Literals + + function scanHexLiteral(start) { + var number = ''; + + while (index < length) { + if (!isHexDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt('0x' + number, 16), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanOctalLiteral(prefix, start) { + var number, octal; + + if (isOctalDigit(prefix)) { + octal = true; + number = '0' + source[index++]; + } else { + octal = false; + ++index; + number = ''; + } + + while (index < length) { + if (!isOctalDigit(source[index])) { + break; + } + number += source[index++]; + } + + if (!octal && number.length === 0) { + // only 0o or 0O + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (isIdentifierStart(source.charCodeAt(index)) || isDecimalDigit(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseInt(number, 8), + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanNumericLiteral() { + var number, start, ch, octal; + + ch = source[index]; + assert(isDecimalDigit(ch.charCodeAt(0)) || (ch === '.'), + 'Numeric literal must start with a decimal digit or a decimal point'); + + start = index; + number = ''; + if (ch !== '.') { + number = source[index++]; + ch = source[index]; + + // Hex number starts with '0x'. + // Octal number starts with '0'. + // Octal number in ES6 starts with '0o'. + // Binary number in ES6 starts with '0b'. + if (number === '0') { + if (ch === 'x' || ch === 'X') { + ++index; + return scanHexLiteral(start); + } + if (ch === 'b' || ch === 'B') { + ++index; + number = ''; + + while (index < length) { + ch = source[index]; + if (ch !== '0' && ch !== '1') { + break; + } + number += source[index++]; + } + + if (number.length === 0) { + // only 0b or 0B + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + if (index < length) { + ch = source.charCodeAt(index); + if (isIdentifierStart(ch) || isDecimalDigit(ch)) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + return { + type: Token.NumericLiteral, + value: parseInt(number, 2), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + if (ch === 'o' || ch === 'O' || isOctalDigit(ch)) { + return scanOctalLiteral(ch, start); + } + // decimal number starts with '0' such as '09' is illegal. + if (ch && isDecimalDigit(ch.charCodeAt(0))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === '.') { + number += source[index++]; + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + ch = source[index]; + } + + if (ch === 'e' || ch === 'E') { + number += source[index++]; + + ch = source[index]; + if (ch === '+' || ch === '-') { + number += source[index++]; + } + if (isDecimalDigit(source.charCodeAt(index))) { + while (isDecimalDigit(source.charCodeAt(index))) { + number += source[index++]; + } + } else { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } + + if (isIdentifierStart(source.charCodeAt(index))) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.NumericLiteral, + value: parseFloat(number), + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + // 7.8.4 String Literals + + function scanStringLiteral() { + var str = '', quote, start, ch, code, unescaped, restore, octal = false; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + while (index < length) { + ch = source[index++]; + + if (ch === quote) { + quote = ''; + break; + } else if (ch === '\\') { + ch = source[index++]; + if (!ch || !isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + str += '\n'; + break; + case 'r': + str += '\r'; + break; + case 't': + str += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + str += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + str += unescaped; + } else { + index = restore; + str += ch; + } + } + break; + case 'b': + str += '\b'; + break; + case 'f': + str += '\f'; + break; + case 'v': + str += '\x0B'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + str += String.fromCharCode(code); + } else { + str += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + break; + } else { + str += ch; + } + } + + if (quote !== '') { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.StringLiteral, + value: str, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplate() { + var cooked = '', ch, start, terminated, tail, restore, unescaped, code, octal; + + terminated = false; + tail = false; + start = index; + + ++index; + + while (index < length) { + ch = source[index++]; + if (ch === '`') { + tail = true; + terminated = true; + break; + } else if (ch === '$') { + if (source[index] === '{') { + ++index; + terminated = true; + break; + } + cooked += ch; + } else if (ch === '\\') { + ch = source[index++]; + if (!isLineTerminator(ch.charCodeAt(0))) { + switch (ch) { + case 'n': + cooked += '\n'; + break; + case 'r': + cooked += '\r'; + break; + case 't': + cooked += '\t'; + break; + case 'u': + case 'x': + if (source[index] === '{') { + ++index; + cooked += scanUnicodeCodePointEscape(); + } else { + restore = index; + unescaped = scanHexEscape(ch); + if (unescaped) { + cooked += unescaped; + } else { + index = restore; + cooked += ch; + } + } + break; + case 'b': + cooked += '\b'; + break; + case 'f': + cooked += '\f'; + break; + case 'v': + cooked += '\v'; + break; + + default: + if (isOctalDigit(ch)) { + code = '01234567'.indexOf(ch); + + // \0 is not octal escape sequence + if (code !== 0) { + octal = true; + } + + if (index < length && isOctalDigit(source[index])) { + octal = true; + code = code * 8 + '01234567'.indexOf(source[index++]); + + // 3 digits are only allowed when string starts + // with 0, 1, 2, 3 + if ('0123'.indexOf(ch) >= 0 && + index < length && + isOctalDigit(source[index])) { + code = code * 8 + '01234567'.indexOf(source[index++]); + } + } + cooked += String.fromCharCode(code); + } else { + cooked += ch; + } + break; + } + } else { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + } + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + cooked += '\n'; + } else { + cooked += ch; + } + } + + if (!terminated) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + return { + type: Token.Template, + value: { + cooked: cooked, + raw: source.slice(start + 1, index - ((tail) ? 1 : 2)) + }, + tail: tail, + octal: octal, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanTemplateElement(option) { + var startsWith, template; + + lookahead = null; + skipComment(); + + startsWith = (option.head) ? '`' : '}'; + + if (source[index] !== startsWith) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + template = scanTemplate(); + + peek(); + + return template; + } + + function scanRegExp() { + var str, ch, start, pattern, flags, value, classMarker = false, restore, terminated = false; + + lookahead = null; + skipComment(); + + start = index; + ch = source[index]; + assert(ch === '/', 'Regular expression literal must start with a slash'); + str = source[index++]; + + while (index < length) { + ch = source[index++]; + str += ch; + if (classMarker) { + if (ch === ']') { + classMarker = false; + } + } else { + if (ch === '\\') { + ch = source[index++]; + // ECMA-262 7.8.5 + if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + str += ch; + } else if (ch === '/') { + terminated = true; + break; + } else if (ch === '[') { + classMarker = true; + } else if (isLineTerminator(ch.charCodeAt(0))) { + throwError({}, Messages.UnterminatedRegExp); + } + } + } + + if (!terminated) { + throwError({}, Messages.UnterminatedRegExp); + } + + // Exclude leading and trailing slash. + pattern = str.substr(1, str.length - 2); + + flags = ''; + while (index < length) { + ch = source[index]; + if (!isIdentifierPart(ch.charCodeAt(0))) { + break; + } + + ++index; + if (ch === '\\' && index < length) { + ch = source[index]; + if (ch === 'u') { + ++index; + restore = index; + ch = scanHexEscape('u'); + if (ch) { + flags += ch; + for (str += '\\u'; restore < index; ++restore) { + str += source[restore]; + } + } else { + index = restore; + flags += 'u'; + str += '\\u'; + } + } else { + str += '\\'; + } + } else { + flags += ch; + str += ch; + } + } + + try { + value = new RegExp(pattern, flags); + } catch (e) { + throwError({}, Messages.InvalidRegExp); + } + + peek(); + + + if (extra.tokenize) { + return { + type: Token.RegularExpression, + value: value, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + return { + literal: str, + value: value, + range: [start, index] + }; + } + + function isIdentifierName(token) { + return token.type === Token.Identifier || + token.type === Token.Keyword || + token.type === Token.BooleanLiteral || + token.type === Token.NullLiteral; + } + + function advanceSlash() { + var prevToken, + checkToken; + // Using the following algorithm: + // https://github.com/mozilla/sweet.js/wiki/design + prevToken = extra.tokens[extra.tokens.length - 1]; + if (!prevToken) { + // Nothing before that: it cannot be a division. + return scanRegExp(); + } + if (prevToken.type === "Punctuator") { + if (prevToken.value === ")") { + checkToken = extra.tokens[extra.openParenToken - 1]; + if (checkToken && + checkToken.type === "Keyword" && + (checkToken.value === "if" || + checkToken.value === "while" || + checkToken.value === "for" || + checkToken.value === "with")) { + return scanRegExp(); + } + return scanPunctuator(); + } + if (prevToken.value === "}") { + // Dividing a function by anything makes little sense, + // but we have to check for that. + if (extra.tokens[extra.openCurlyToken - 3] && + extra.tokens[extra.openCurlyToken - 3].type === "Keyword") { + // Anonymous function. + checkToken = extra.tokens[extra.openCurlyToken - 4]; + if (!checkToken) { + return scanPunctuator(); + } + } else if (extra.tokens[extra.openCurlyToken - 4] && + extra.tokens[extra.openCurlyToken - 4].type === "Keyword") { + // Named function. + checkToken = extra.tokens[extra.openCurlyToken - 5]; + if (!checkToken) { + return scanRegExp(); + } + } else { + return scanPunctuator(); + } + // checkToken determines whether the function is + // a declaration or an expression. + if (FnExprTokens.indexOf(checkToken.value) >= 0) { + // It is an expression. + return scanPunctuator(); + } + // It is a declaration. + return scanRegExp(); + } + return scanRegExp(); + } + if (prevToken.type === "Keyword") { + return scanRegExp(); + } + return scanPunctuator(); + } + + function advance() { + var ch; + + if (state.inXJSChild) { + return advanceXJSChild(); + } + + skipComment(); + + if (index >= length) { + return { + type: Token.EOF, + lineNumber: lineNumber, + lineStart: lineStart, + range: [index, index] + }; + } + + ch = source.charCodeAt(index); + + // Very common: ( and ) and ; + if (ch === 40 || ch === 41 || ch === 58) { + return scanPunctuator(); + } + + // String literal starts with single quote (#39) or double quote (#34). + if (ch === 39 || ch === 34) { + if (state.inXJSTag) { + return scanXJSStringLiteral(); + } + return scanStringLiteral(); + } + + if (state.inXJSTag && isXJSIdentifierStart(ch)) { + return scanXJSIdentifier(); + } + + if (ch === 96) { + return scanTemplate(); + } + if (isIdentifierStart(ch)) { + return scanIdentifier(); + } + + // Dot (.) char #46 can also start a floating-point number, hence the need + // to check the next character. + if (ch === 46) { + if (isDecimalDigit(source.charCodeAt(index + 1))) { + return scanNumericLiteral(); + } + return scanPunctuator(); + } + + if (isDecimalDigit(ch)) { + return scanNumericLiteral(); + } + + // Slash (/) char #47 can also start a regex. + if (extra.tokenize && ch === 47) { + return advanceSlash(); + } + + return scanPunctuator(); + } + + function lex() { + var token; + + token = lookahead; + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + lookahead = advance(); + + index = token.range[1]; + lineNumber = token.lineNumber; + lineStart = token.lineStart; + + return token; + } + + function peek() { + var pos, line, start; + + pos = index; + line = lineNumber; + start = lineStart; + lookahead = advance(); + index = pos; + lineNumber = line; + lineStart = start; + } + + function lookahead2() { + var adv, pos, line, start, result; + + // If we are collecting the tokens, don't grab the next one yet. + adv = (typeof extra.advance === 'function') ? extra.advance : advance; + + pos = index; + line = lineNumber; + start = lineStart; + + // Scan for the next immediate token. + if (lookahead === null) { + lookahead = adv(); + } + index = lookahead.range[1]; + lineNumber = lookahead.lineNumber; + lineStart = lookahead.lineStart; + + // Grab the token right after. + result = adv(); + index = pos; + lineNumber = line; + lineStart = start; + + return result; + } + + SyntaxTreeDelegate = { + + name: 'SyntaxTree', + + postProcess: function (node) { + return node; + }, + + createArrayExpression: function (elements) { + return { + type: Syntax.ArrayExpression, + elements: elements + }; + }, + + createAssignmentExpression: function (operator, left, right) { + return { + type: Syntax.AssignmentExpression, + operator: operator, + left: left, + right: right + }; + }, + + createBinaryExpression: function (operator, left, right) { + var type = (operator === '||' || operator === '&&') ? Syntax.LogicalExpression : + Syntax.BinaryExpression; + return { + type: type, + operator: operator, + left: left, + right: right + }; + }, + + createBlockStatement: function (body) { + return { + type: Syntax.BlockStatement, + body: body + }; + }, + + createBreakStatement: function (label) { + return { + type: Syntax.BreakStatement, + label: label + }; + }, + + createCallExpression: function (callee, args) { + return { + type: Syntax.CallExpression, + callee: callee, + 'arguments': args + }; + }, + + createCatchClause: function (param, body) { + return { + type: Syntax.CatchClause, + param: param, + body: body + }; + }, + + createConditionalExpression: function (test, consequent, alternate) { + return { + type: Syntax.ConditionalExpression, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createContinueStatement: function (label) { + return { + type: Syntax.ContinueStatement, + label: label + }; + }, + + createDebuggerStatement: function () { + return { + type: Syntax.DebuggerStatement + }; + }, + + createDoWhileStatement: function (body, test) { + return { + type: Syntax.DoWhileStatement, + body: body, + test: test + }; + }, + + createEmptyStatement: function () { + return { + type: Syntax.EmptyStatement + }; + }, + + createExpressionStatement: function (expression) { + return { + type: Syntax.ExpressionStatement, + expression: expression + }; + }, + + createForStatement: function (init, test, update, body) { + return { + type: Syntax.ForStatement, + init: init, + test: test, + update: update, + body: body + }; + }, + + createForInStatement: function (left, right, body) { + return { + type: Syntax.ForInStatement, + left: left, + right: right, + body: body, + each: false + }; + }, + + createForOfStatement: function (left, right, body) { + return { + type: Syntax.ForOfStatement, + left: left, + right: right, + body: body, + }; + }, + + createFunctionDeclaration: function (id, params, defaults, body, rest, generator, expression, + returnTypeAnnotation) { + return { + type: Syntax.FunctionDeclaration, + id: id, + params: params, + defaults: defaults, + returnType: returnTypeAnnotation, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createFunctionExpression: function (id, params, defaults, body, rest, generator, expression, + returnTypeAnnotation) { + return { + type: Syntax.FunctionExpression, + id: id, + params: params, + defaults: defaults, + returnType: returnTypeAnnotation, + body: body, + rest: rest, + generator: generator, + expression: expression + }; + }, + + createIdentifier: function (name) { + return { + type: Syntax.Identifier, + name: name + }; + }, + + createTypeAnnotatedIdentifier: function (annotation, identifier) { + return { + type: Syntax.TypeAnnotatedIdentifier, + annotation: annotation, + identifier: identifier + }; + }, + + createTypeAnnotation: function (annotatedType, templateTypes, + paramTypes, returnType, unionType, + nullable) { + return { + type: Syntax.TypeAnnotation, + annotatedType: annotatedType, + templateTypes: templateTypes, + paramTypes: paramTypes, + returnType: returnType, + unionType: unionType, + nullable: nullable + }; + }, + + createXJSAttribute: function (name, value) { + return { + type: Syntax.XJSAttribute, + name: name, + value: value + }; + }, + + createXJSIdentifier: function (name, namespace) { + return { + type: Syntax.XJSIdentifier, + name: name, + namespace: namespace + }; + }, + + createXJSElement: function (openingElement, closingElement, children) { + return { + type: Syntax.XJSElement, + name: openingElement.name, + selfClosing: openingElement.selfClosing, + openingElement: openingElement, + closingElement: closingElement, + attributes: openingElement.attributes, + children: children + }; + }, + + createXJSEmptyExpression: function () { + return { + type: Syntax.XJSEmptyExpression + }; + }, + + createXJSExpressionContainer: function (expression) { + return { + type: Syntax.XJSExpressionContainer, + expression: expression + }; + }, + + createXJSOpeningElement: function (name, attributes, selfClosing) { + return { + type: Syntax.XJSOpeningElement, + name: name, + selfClosing: selfClosing, + attributes: attributes + }; + }, + + createXJSClosingElement: function (name) { + return { + type: Syntax.XJSClosingElement, + name: name + }; + }, + + createIfStatement: function (test, consequent, alternate) { + return { + type: Syntax.IfStatement, + test: test, + consequent: consequent, + alternate: alternate + }; + }, + + createLabeledStatement: function (label, body) { + return { + type: Syntax.LabeledStatement, + label: label, + body: body + }; + }, + + createLiteral: function (token) { + return { + type: Syntax.Literal, + value: token.value, + raw: source.slice(token.range[0], token.range[1]) + }; + }, + + createMemberExpression: function (accessor, object, property) { + return { + type: Syntax.MemberExpression, + computed: accessor === '[', + object: object, + property: property + }; + }, + + createNewExpression: function (callee, args) { + return { + type: Syntax.NewExpression, + callee: callee, + 'arguments': args + }; + }, + + createObjectExpression: function (properties) { + return { + type: Syntax.ObjectExpression, + properties: properties + }; + }, + + createPostfixExpression: function (operator, argument) { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: false + }; + }, + + createProgram: function (body) { + return { + type: Syntax.Program, + body: body + }; + }, + + createProperty: function (kind, key, value, method, shorthand) { + return { + type: Syntax.Property, + key: key, + value: value, + kind: kind, + method: method, + shorthand: shorthand + }; + }, + + createReturnStatement: function (argument) { + return { + type: Syntax.ReturnStatement, + argument: argument + }; + }, + + createSequenceExpression: function (expressions) { + return { + type: Syntax.SequenceExpression, + expressions: expressions + }; + }, + + createSwitchCase: function (test, consequent) { + return { + type: Syntax.SwitchCase, + test: test, + consequent: consequent + }; + }, + + createSwitchStatement: function (discriminant, cases) { + return { + type: Syntax.SwitchStatement, + discriminant: discriminant, + cases: cases + }; + }, + + createThisExpression: function () { + return { + type: Syntax.ThisExpression + }; + }, + + createThrowStatement: function (argument) { + return { + type: Syntax.ThrowStatement, + argument: argument + }; + }, + + createTryStatement: function (block, guardedHandlers, handlers, finalizer) { + return { + type: Syntax.TryStatement, + block: block, + guardedHandlers: guardedHandlers, + handlers: handlers, + finalizer: finalizer + }; + }, + + createUnaryExpression: function (operator, argument) { + if (operator === '++' || operator === '--') { + return { + type: Syntax.UpdateExpression, + operator: operator, + argument: argument, + prefix: true + }; + } + return { + type: Syntax.UnaryExpression, + operator: operator, + argument: argument + }; + }, + + createVariableDeclaration: function (declarations, kind) { + return { + type: Syntax.VariableDeclaration, + declarations: declarations, + kind: kind + }; + }, + + createVariableDeclarator: function (id, init) { + return { + type: Syntax.VariableDeclarator, + id: id, + init: init + }; + }, + + createWhileStatement: function (test, body) { + return { + type: Syntax.WhileStatement, + test: test, + body: body + }; + }, + + createWithStatement: function (object, body) { + return { + type: Syntax.WithStatement, + object: object, + body: body + }; + }, + + createTemplateElement: function (value, tail) { + return { + type: Syntax.TemplateElement, + value: value, + tail: tail + }; + }, + + createTemplateLiteral: function (quasis, expressions) { + return { + type: Syntax.TemplateLiteral, + quasis: quasis, + expressions: expressions + }; + }, + + createSpreadElement: function (argument) { + return { + type: Syntax.SpreadElement, + argument: argument + }; + }, + + createTaggedTemplateExpression: function (tag, quasi) { + return { + type: Syntax.TaggedTemplateExpression, + tag: tag, + quasi: quasi + }; + }, + + createArrowFunctionExpression: function (params, defaults, body, rest, expression) { + return { + type: Syntax.ArrowFunctionExpression, + id: null, + params: params, + defaults: defaults, + body: body, + rest: rest, + generator: false, + expression: expression + }; + }, + + createMethodDefinition: function (propertyType, kind, key, value) { + return { + type: Syntax.MethodDefinition, + key: key, + value: value, + kind: kind, + 'static': propertyType === ClassPropertyType.static + }; + }, + + createClassBody: function (body) { + return { + type: Syntax.ClassBody, + body: body + }; + }, + + createClassExpression: function (id, superClass, body) { + return { + type: Syntax.ClassExpression, + id: id, + superClass: superClass, + body: body + }; + }, + + createClassDeclaration: function (id, superClass, body) { + return { + type: Syntax.ClassDeclaration, + id: id, + superClass: superClass, + body: body + }; + }, + + createExportSpecifier: function (id, name) { + return { + type: Syntax.ExportSpecifier, + id: id, + name: name + }; + }, + + createExportBatchSpecifier: function () { + return { + type: Syntax.ExportBatchSpecifier + }; + }, + + createExportDeclaration: function (def, declaration, specifiers, source) { + return { + type: Syntax.ExportDeclaration, + declaration: declaration, + default: def, + specifiers: specifiers, + source: source + }; + }, + + createImportSpecifier: function (id, name) { + return { + type: Syntax.ImportSpecifier, + id: id, + name: name + }; + }, + + createImportDeclaration: function (specifiers, kind, source) { + return { + type: Syntax.ImportDeclaration, + specifiers: specifiers, + kind: kind, + source: source + }; + }, + + createYieldExpression: function (argument, delegate) { + return { + type: Syntax.YieldExpression, + argument: argument, + delegate: delegate + }; + }, + + createModuleDeclaration: function (id, source, body) { + return { + type: Syntax.ModuleDeclaration, + id: id, + source: source, + body: body + }; + } + + + }; + + // Return true if there is a line terminator before the next token. + + function peekLineTerminator() { + var pos, line, start, found; + + pos = index; + line = lineNumber; + start = lineStart; + skipComment(); + found = lineNumber !== line; + index = pos; + lineNumber = line; + lineStart = start; + + return found; + } + + // Throw an exception + + function throwError(token, messageFormat) { + var error, + args = Array.prototype.slice.call(arguments, 2), + msg = messageFormat.replace( + /%(\d)/g, + function (whole, index) { + assert(index < args.length, 'Message reference must be in range'); + return args[index]; + } + ); + + if (typeof token.lineNumber === 'number') { + error = new Error('Line ' + token.lineNumber + ': ' + msg); + error.index = token.range[0]; + error.lineNumber = token.lineNumber; + error.column = token.range[0] - lineStart + 1; + } else { + error = new Error('Line ' + lineNumber + ': ' + msg); + error.index = index; + error.lineNumber = lineNumber; + error.column = index - lineStart + 1; + } + + error.description = msg; + throw error; + } + + function throwErrorTolerant() { + try { + throwError.apply(null, arguments); + } catch (e) { + if (extra.errors) { + extra.errors.push(e); + } else { + throw e; + } + } + } + + + // Throw an exception because of the token. + + function throwUnexpected(token) { + if (token.type === Token.EOF) { + throwError(token, Messages.UnexpectedEOS); + } + + if (token.type === Token.NumericLiteral) { + throwError(token, Messages.UnexpectedNumber); + } + + if (token.type === Token.StringLiteral) { + throwError(token, Messages.UnexpectedString); + } + + if (token.type === Token.Identifier) { + throwError(token, Messages.UnexpectedIdentifier); + } + + if (token.type === Token.Keyword) { + if (isFutureReservedWord(token.value)) { + throwError(token, Messages.UnexpectedReserved); + } else if (strict && isStrictModeReservedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictReservedWord); + return; + } + throwError(token, Messages.UnexpectedToken, token.value); + } + + if (token.type === Token.Template) { + throwError(token, Messages.UnexpectedTemplate, token.value.raw); + } + + // BooleanLiteral, NullLiteral, or Punctuator. + throwError(token, Messages.UnexpectedToken, token.value); + } + + // Expect the next token to match the specified punctuator. + // If not, an exception will be thrown. + + function expect(value) { + var token = lex(); + if (token.type !== Token.Punctuator || token.value !== value) { + throwUnexpected(token); + } + } + + // Expect the next token to match the specified keyword. + // If not, an exception will be thrown. + + function expectKeyword(keyword) { + var token = lex(); + if (token.type !== Token.Keyword || token.value !== keyword) { + throwUnexpected(token); + } + } + + // Return true if the next token matches the specified punctuator. + + function match(value) { + return lookahead.type === Token.Punctuator && lookahead.value === value; + } + + // Return true if the next token matches the specified keyword + + function matchKeyword(keyword) { + return lookahead.type === Token.Keyword && lookahead.value === keyword; + } + + + // Return true if the next token matches the specified contextual keyword + + function matchContextualKeyword(keyword) { + return lookahead.type === Token.Identifier && lookahead.value === keyword; + } + + // Return true if the next token is an assignment operator + + function matchAssign() { + var op; + + if (lookahead.type !== Token.Punctuator) { + return false; + } + op = lookahead.value; + return op === '=' || + op === '*=' || + op === '/=' || + op === '%=' || + op === '+=' || + op === '-=' || + op === '<<=' || + op === '>>=' || + op === '>>>=' || + op === '&=' || + op === '^=' || + op === '|='; + } + + function consumeSemicolon() { + var line; + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + return; + } + + line = lineNumber; + skipComment(); + if (lineNumber !== line) { + return; + } + + if (match(';')) { + lex(); + return; + } + + if (lookahead.type !== Token.EOF && !match('}')) { + throwUnexpected(lookahead); + } + } + + // Return true if provided expression is LeftHandSideExpression + + function isLeftHandSide(expr) { + return expr.type === Syntax.Identifier || expr.type === Syntax.MemberExpression; + } + + function isAssignableLeftHandSide(expr) { + return isLeftHandSide(expr) || expr.type === Syntax.ObjectPattern || expr.type === Syntax.ArrayPattern; + } + + // 11.1.4 Array Initialiser + + function parseArrayInitialiser() { + var elements = [], blocks = [], filter = null, tmp, possiblecomprehension = true, body; + + expect('['); + while (!match(']')) { + if (lookahead.value === 'for' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + matchKeyword('for'); + tmp = parseForStatement({ignore_body: true}); + tmp.of = tmp.type === Syntax.ForOfStatement; + tmp.type = Syntax.ComprehensionBlock; + if (tmp.left.kind) { // can't be let or const + throwError({}, Messages.ComprehensionError); + } + blocks.push(tmp); + } else if (lookahead.value === 'if' && + lookahead.type === Token.Keyword) { + if (!possiblecomprehension) { + throwError({}, Messages.ComprehensionError); + } + expectKeyword('if'); + expect('('); + filter = parseExpression(); + expect(')'); + } else if (lookahead.value === ',' && + lookahead.type === Token.Punctuator) { + possiblecomprehension = false; // no longer allowed. + lex(); + elements.push(null); + } else { + tmp = parseSpreadOrAssignmentExpression(); + elements.push(tmp); + if (tmp && tmp.type === Syntax.SpreadElement) { + if (!match(']')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + } else if (!(match(']') || matchKeyword('for') || matchKeyword('if'))) { + expect(','); // this lexes. + possiblecomprehension = false; + } + } + } + + expect(']'); + + if (filter && !blocks.length) { + throwError({}, Messages.ComprehensionRequiresBlock); + } + + if (blocks.length) { + if (elements.length !== 1) { + throwError({}, Messages.ComprehensionError); + } + return { + type: Syntax.ComprehensionExpression, + filter: filter, + blocks: blocks, + body: elements[0] + }; + } + return delegate.createArrayExpression(elements); + } + + // 11.1.5 Object Initialiser + + function parsePropertyFunction(options) { + var previousStrict, previousYieldAllowed, params, defaults, body; + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = options.generator; + params = options.params || []; + defaults = options.defaults || []; + + body = parseConciseBody(); + if (options.name && strict && isRestrictedWord(params[0].name)) { + throwErrorTolerant(options.name, Messages.StrictParamName); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(null, params, defaults, body, options.rest || null, options.generator, body.type !== Syntax.BlockStatement, + options.returnTypeAnnotation); + } + + + function parsePropertyMethodFunction(options) { + var previousStrict, tmp, method; + + previousStrict = strict; + strict = true; + + tmp = parseParams(); + + if (tmp.stricted) { + throwErrorTolerant(tmp.stricted, tmp.message); + } + + + method = parsePropertyFunction({ + params: tmp.params, + defaults: tmp.defaults, + rest: tmp.rest, + generator: options.generator, + returnTypeAnnotation: tmp.returnTypeAnnotation + }); + + strict = previousStrict; + + return method; + } + + + function parseObjectPropertyKey() { + var token = lex(); + + // Note: This function is called only from parseObjectProperty(), where + // EOF and Punctuator tokens are already filtered out. + + if (token.type === Token.StringLiteral || token.type === Token.NumericLiteral) { + if (strict && token.octal) { + throwErrorTolerant(token, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseObjectProperty() { + var token, key, id, value, param; + + token = lookahead; + + if (token.type === Token.Identifier) { + + id = parseObjectPropertyKey(); + + // Property Assignment: Getter and Setter. + + if (token.value === 'get' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + expect(')'); + return delegate.createProperty('get', key, parsePropertyFunction({ generator: false }), false, false); + } + if (token.value === 'set' && !(match(':') || match('('))) { + key = parseObjectPropertyKey(); + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createProperty('set', key, parsePropertyFunction({ params: param, generator: false, name: token }), false, false); + } + if (match(':')) { + lex(); + return delegate.createProperty('init', id, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: false }), true, false); + } + return delegate.createProperty('init', id, id, false, true); + } + if (token.type === Token.EOF || token.type === Token.Punctuator) { + if (!match('*')) { + throwUnexpected(token); + } + lex(); + + id = parseObjectPropertyKey(); + + if (!match('(')) { + throwUnexpected(lex()); + } + + return delegate.createProperty('init', id, parsePropertyMethodFunction({ generator: true }), true, false); + } + key = parseObjectPropertyKey(); + if (match(':')) { + lex(); + return delegate.createProperty('init', key, parseAssignmentExpression(), false, false); + } + if (match('(')) { + return delegate.createProperty('init', key, parsePropertyMethodFunction({ generator: false }), true, false); + } + throwUnexpected(lex()); + } + + function parseObjectInitialiser() { + var properties = [], property, name, key, kind, map = {}, toString = String; + + expect('{'); + + while (!match('}')) { + property = parseObjectProperty(); + + if (property.key.type === Syntax.Identifier) { + name = property.key.name; + } else { + name = toString(property.key.value); + } + kind = (property.kind === 'init') ? PropertyKind.Data : (property.kind === 'get') ? PropertyKind.Get : PropertyKind.Set; + + key = '$' + name; + if (Object.prototype.hasOwnProperty.call(map, key)) { + if (map[key] === PropertyKind.Data) { + if (strict && kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.StrictDuplicateProperty); + } else if (kind !== PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } + } else { + if (kind === PropertyKind.Data) { + throwErrorTolerant({}, Messages.AccessorDataProperty); + } else if (map[key] & kind) { + throwErrorTolerant({}, Messages.AccessorGetSet); + } + } + map[key] |= kind; + } else { + map[key] = kind; + } + + properties.push(property); + + if (!match('}')) { + expect(','); + } + } + + expect('}'); + + return delegate.createObjectExpression(properties); + } + + function parseTemplateElement(option) { + var token = scanTemplateElement(option); + if (strict && token.octal) { + throwError(token, Messages.StrictOctalLiteral); + } + return delegate.createTemplateElement({ raw: token.value.raw, cooked: token.value.cooked }, token.tail); + } + + function parseTemplateLiteral() { + var quasi, quasis, expressions; + + quasi = parseTemplateElement({ head: true }); + quasis = [ quasi ]; + expressions = []; + + while (!quasi.tail) { + expressions.push(parseExpression()); + quasi = parseTemplateElement({ head: false }); + quasis.push(quasi); + } + + return delegate.createTemplateLiteral(quasis, expressions); + } + + // 11.1.6 The Grouping Operator + + function parseGroupExpression() { + var expr; + + expect('('); + + ++state.parenthesizedCount; + + state.allowArrowFunction = !state.allowArrowFunction; + expr = parseExpression(); + state.allowArrowFunction = false; + + if (expr.type !== Syntax.ArrowFunctionExpression) { + expect(')'); + } + + return expr; + } + + + // 11.1 Primary Expressions + + function parsePrimaryExpression() { + var type, token; + + token = lookahead; + type = lookahead.type; + + if (type === Token.Identifier) { + lex(); + return delegate.createIdentifier(token.value); + } + + if (type === Token.StringLiteral || type === Token.NumericLiteral) { + if (strict && lookahead.octal) { + throwErrorTolerant(lookahead, Messages.StrictOctalLiteral); + } + return delegate.createLiteral(lex()); + } + + if (type === Token.Keyword) { + if (matchKeyword('this')) { + lex(); + return delegate.createThisExpression(); + } + + if (matchKeyword('function')) { + return parseFunctionExpression(); + } + + if (matchKeyword('class')) { + return parseClassExpression(); + } + + if (matchKeyword('super')) { + lex(); + return delegate.createIdentifier('super'); + } + } + + if (type === Token.BooleanLiteral) { + token = lex(); + token.value = (token.value === 'true'); + return delegate.createLiteral(token); + } + + if (type === Token.NullLiteral) { + token = lex(); + token.value = null; + return delegate.createLiteral(token); + } + + if (match('[')) { + return parseArrayInitialiser(); + } + + if (match('{')) { + return parseObjectInitialiser(); + } + + if (match('(')) { + return parseGroupExpression(); + } + + if (match('/') || match('/=')) { + return delegate.createLiteral(scanRegExp()); + } + + if (type === Token.Template) { + return parseTemplateLiteral(); + } + + if (match('<')) { + return parseXJSElement(); + } + + return throwUnexpected(lex()); + } + + // 11.2 Left-Hand-Side Expressions + + function parseArguments() { + var args = [], arg; + + expect('('); + + if (!match(')')) { + while (index < length) { + arg = parseSpreadOrAssignmentExpression(); + args.push(arg); + + if (match(')')) { + break; + } else if (arg.type === Syntax.SpreadElement) { + throwError({}, Messages.ElementAfterSpreadElement); + } + + expect(','); + } + } + + expect(')'); + + return args; + } + + function parseSpreadOrAssignmentExpression() { + if (match('...')) { + lex(); + return delegate.createSpreadElement(parseAssignmentExpression()); + } + return parseAssignmentExpression(); + } + + function parseNonComputedProperty() { + var token = lex(); + + if (!isIdentifierName(token)) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseNonComputedMember() { + expect('.'); + + return parseNonComputedProperty(); + } + + function parseComputedMember() { + var expr; + + expect('['); + + expr = parseExpression(); + + expect(']'); + + return expr; + } + + function parseNewExpression() { + var callee, args; + + expectKeyword('new'); + callee = parseLeftHandSideExpression(); + args = match('(') ? parseArguments() : []; + + return delegate.createNewExpression(callee, args); + } + + function parseLeftHandSideExpressionAllowCall() { + var expr, args, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + + function parseLeftHandSideExpression() { + var expr, property; + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + } + } + + return expr; + } + + // 11.3 Postfix Expressions + + function parsePostfixExpression() { + var expr = parseLeftHandSideExpressionAllowCall(), + token = lookahead; + + if (lookahead.type !== Token.Punctuator) { + return expr; + } + + if ((match('++') || match('--')) && !peekLineTerminator()) { + // 11.3.1, 11.3.2 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPostfix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + token = lex(); + expr = delegate.createPostfixExpression(token.value, expr); + } + + return expr; + } + + // 11.4 Unary Operators + + function parseUnaryExpression() { + var token, expr; + + if (lookahead.type !== Token.Punctuator && lookahead.type !== Token.Keyword) { + return parsePostfixExpression(); + } + + if (match('++') || match('--')) { + token = lex(); + expr = parseUnaryExpression(); + // 11.4.4, 11.4.5 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant({}, Messages.StrictLHSPrefix); + } + + if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + return delegate.createUnaryExpression(token.value, expr); + } + + if (match('+') || match('-') || match('~') || match('!')) { + token = lex(); + expr = parseUnaryExpression(); + return delegate.createUnaryExpression(token.value, expr); + } + + if (matchKeyword('delete') || matchKeyword('void') || matchKeyword('typeof')) { + token = lex(); + expr = parseUnaryExpression(); + expr = delegate.createUnaryExpression(token.value, expr); + if (strict && expr.operator === 'delete' && expr.argument.type === Syntax.Identifier) { + throwErrorTolerant({}, Messages.StrictDelete); + } + return expr; + } + + return parsePostfixExpression(); + } + + function binaryPrecedence(token, allowIn) { + var prec = 0; + + if (token.type !== Token.Punctuator && token.type !== Token.Keyword) { + return 0; + } + + switch (token.value) { + case '||': + prec = 1; + break; + + case '&&': + prec = 2; + break; + + case '|': + prec = 3; + break; + + case '^': + prec = 4; + break; + + case '&': + prec = 5; + break; + + case '==': + case '!=': + case '===': + case '!==': + prec = 6; + break; + + case '<': + case '>': + case '<=': + case '>=': + case 'instanceof': + prec = 7; + break; + + case 'in': + prec = allowIn ? 7 : 0; + break; + + case '<<': + case '>>': + case '>>>': + prec = 8; + break; + + case '+': + case '-': + prec = 9; + break; + + case '*': + case '/': + case '%': + prec = 11; + break; + + default: + break; + } + + return prec; + } + + // 11.5 Multiplicative Operators + // 11.6 Additive Operators + // 11.7 Bitwise Shift Operators + // 11.8 Relational Operators + // 11.9 Equality Operators + // 11.10 Binary Bitwise Operators + // 11.11 Binary Logical Operators + + function parseBinaryExpression() { + var expr, token, prec, previousAllowIn, stack, right, operator, left, i; + + previousAllowIn = state.allowIn; + state.allowIn = true; + + expr = parseUnaryExpression(); + + token = lookahead; + prec = binaryPrecedence(token, previousAllowIn); + if (prec === 0) { + return expr; + } + token.prec = prec; + lex(); + + stack = [expr, token, parseUnaryExpression()]; + + while ((prec = binaryPrecedence(lookahead, previousAllowIn)) > 0) { + + // Reduce: make a binary expression from the three topmost entries. + while ((stack.length > 2) && (prec <= stack[stack.length - 2].prec)) { + right = stack.pop(); + operator = stack.pop().value; + left = stack.pop(); + stack.push(delegate.createBinaryExpression(operator, left, right)); + } + + // Shift. + token = lex(); + token.prec = prec; + stack.push(token); + stack.push(parseUnaryExpression()); + } + + state.allowIn = previousAllowIn; + + // Final reduce to clean-up the stack. + i = stack.length - 1; + expr = stack[i]; + while (i > 1) { + expr = delegate.createBinaryExpression(stack[i - 1].value, stack[i - 2], expr); + i -= 2; + } + return expr; + } + + + // 11.12 Conditional Operator + + function parseConditionalExpression() { + var expr, previousAllowIn, consequent, alternate; + + expr = parseBinaryExpression(); + + if (match('?')) { + lex(); + previousAllowIn = state.allowIn; + state.allowIn = true; + consequent = parseAssignmentExpression(); + state.allowIn = previousAllowIn; + expect(':'); + alternate = parseAssignmentExpression(); + + expr = delegate.createConditionalExpression(expr, consequent, alternate); + } + + return expr; + } + + // 11.13 Assignment Operators + + function reinterpretAsAssignmentBindingPattern(expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInAssignment); + } + reinterpretAsAssignmentBindingPattern(property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsAssignmentBindingPattern(element); + } + } + } else if (expr.type === Syntax.Identifier) { + if (isRestrictedWord(expr.name)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } else if (expr.type === Syntax.SpreadElement) { + reinterpretAsAssignmentBindingPattern(expr.argument); + if (expr.argument.type === Syntax.ObjectPattern) { + throwError({}, Messages.ObjectPatternAsSpread); + } + } else { + if (expr.type !== Syntax.MemberExpression && expr.type !== Syntax.CallExpression && expr.type !== Syntax.NewExpression) { + throwError({}, Messages.InvalidLHSInAssignment); + } + } + } + + + function reinterpretAsDestructuredParameter(options, expr) { + var i, len, property, element; + + if (expr.type === Syntax.ObjectExpression) { + expr.type = Syntax.ObjectPattern; + for (i = 0, len = expr.properties.length; i < len; i += 1) { + property = expr.properties[i]; + if (property.kind !== 'init') { + throwError({}, Messages.InvalidLHSInFormalsList); + } + reinterpretAsDestructuredParameter(options, property.value); + } + } else if (expr.type === Syntax.ArrayExpression) { + expr.type = Syntax.ArrayPattern; + for (i = 0, len = expr.elements.length; i < len; i += 1) { + element = expr.elements[i]; + if (element) { + reinterpretAsDestructuredParameter(options, element); + } + } + } else if (expr.type === Syntax.Identifier) { + validateParam(options, expr, expr.name); + } else { + if (expr.type !== Syntax.MemberExpression) { + throwError({}, Messages.InvalidLHSInFormalsList); + } + } + } + + function reinterpretAsCoverFormalsList(expressions) { + var i, len, param, params, defaults, defaultCount, options, rest; + + params = []; + defaults = []; + defaultCount = 0; + rest = null; + options = { + paramSet: {} + }; + + for (i = 0, len = expressions.length; i < len; i += 1) { + param = expressions[i]; + if (param.type === Syntax.Identifier) { + params.push(param); + defaults.push(null); + validateParam(options, param, param.name); + } else if (param.type === Syntax.ObjectExpression || param.type === Syntax.ArrayExpression) { + reinterpretAsDestructuredParameter(options, param); + params.push(param); + defaults.push(null); + } else if (param.type === Syntax.SpreadElement) { + assert(i === len - 1, "It is guaranteed that SpreadElement is last element by parseExpression"); + reinterpretAsDestructuredParameter(options, param.argument); + rest = param.argument; + } else if (param.type === Syntax.AssignmentExpression) { + params.push(param.left); + defaults.push(param.right); + ++defaultCount; + } else { + return null; + } + } + + if (options.firstRestricted) { + throwError(options.firstRestricted, options.message); + } + if (options.stricted) { + throwErrorTolerant(options.stricted, options.message); + } + + if (defaultCount === 0) { + defaults = []; + } + + return { params: params, defaults: defaults, rest: rest }; + } + + function parseArrowFunctionExpression(options) { + var previousStrict, previousYieldAllowed, body; + + expect('=>'); + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + strict = true; + state.yieldAllowed = false; + body = parseConciseBody(); + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createArrowFunctionExpression(options.params, options.defaults, body, options.rest, body.type !== Syntax.BlockStatement); + } + + function parseAssignmentExpression() { + var expr, token, params, oldParenthesizedCount; + + if (matchKeyword('yield')) { + return parseYieldExpression(); + } + + oldParenthesizedCount = state.parenthesizedCount; + + if (match('(')) { + token = lookahead2(); + if ((token.type === Token.Punctuator && token.value === ')') || token.value === '...') { + params = parseParams(); + if (!match('=>')) { + throwUnexpected(lex()); + } + return parseArrowFunctionExpression(params); + } + } + + token = lookahead; + expr = parseConditionalExpression(); + + if (match('=>') && expr.type === Syntax.Identifier) { + if (state.parenthesizedCount === oldParenthesizedCount || state.parenthesizedCount === (oldParenthesizedCount + 1)) { + if (isRestrictedWord(expr.name)) { + throwError({}, Messages.StrictParamName); + } + return parseArrowFunctionExpression({ params: [ expr ], defaults: [], rest: null }); + } + } + + if (matchAssign()) { + // 11.13.1 + if (strict && expr.type === Syntax.Identifier && isRestrictedWord(expr.name)) { + throwErrorTolerant(token, Messages.StrictLHSAssignment); + } + + // ES.next draf 11.13 Runtime Semantics step 1 + if (match('=') && (expr.type === Syntax.ObjectExpression || expr.type === Syntax.ArrayExpression)) { + reinterpretAsAssignmentBindingPattern(expr); + } else if (!isLeftHandSide(expr)) { + throwError({}, Messages.InvalidLHSInAssignment); + } + + expr = delegate.createAssignmentExpression(lex().value, expr, parseAssignmentExpression()); + } + + return expr; + } + + // 11.14 Comma Operator + + function parseExpression() { + var expr, expressions, sequence, coverFormalsList, spreadFound, token; + + expr = parseAssignmentExpression(); + expressions = [ expr ]; + + if (match(',')) { + while (index < length) { + if (!match(',')) { + break; + } + + lex(); + expr = parseSpreadOrAssignmentExpression(); + expressions.push(expr); + + if (expr.type === Syntax.SpreadElement) { + spreadFound = true; + if (!match(')')) { + throwError({}, Messages.ElementAfterSpreadElement); + } + break; + } + } + + sequence = delegate.createSequenceExpression(expressions); + } + + if (state.allowArrowFunction && match(')')) { + token = lookahead2(); + if (token.value === '=>') { + lex(); + + state.allowArrowFunction = false; + expr = expressions; + coverFormalsList = reinterpretAsCoverFormalsList(expr); + if (coverFormalsList) { + return parseArrowFunctionExpression(coverFormalsList); + } + + throwUnexpected(token); + } + } + + if (spreadFound) { + throwError({}, Messages.IllegalSpread); + } + + return sequence || expr; + } + + // 12.1 Block + + function parseStatementList() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseSourceElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseBlock() { + var block; + + expect('{'); + + block = parseStatementList(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + // 12.2 Variable Statement + + function parseVariableIdentifier() { + var token = lex(); + + if (token.type !== Token.Identifier) { + throwUnexpected(token); + } + + return delegate.createIdentifier(token.value); + } + + function parseTypeAnnotation() { + var isNullable = false, paramTypes = null, returnType = null, + templateTypes = null, type, unionType = null; + + if (match('?')) { + lex(); + isNullable = true; + } + + type = parseVariableIdentifier(); + + if (match('<')) { + lex(); + templateTypes = []; + while (lookahead.type === Token.Identifier || match('?')) { + templateTypes.push(parseTypeAnnotation()); + if (!match('>')) { + expect(','); + } + } + expect('>'); + } + + if (match('(')) { + lex(); + paramTypes = []; + while (lookahead.type === Token.Identifier || match('?')) { + paramTypes.push(parseTypeAnnotation()); + if (!match(')')) { + expect(','); + } + } + expect(')'); + + if (match(':')) { + lex(); + returnType = parseTypeAnnotation(); + } + } + + if (match('|')) { + lex(); + unionType = parseTypeAnnotation(); + } + + return delegate.createTypeAnnotation( + type, + templateTypes, + paramTypes, + returnType, + unionType, + isNullable + ); + } + + function parseAnnotatableIdentifier() { + var annotation, annotationLookahead, annotationPresent, identifier, + matchesNullableToken; + + matchesNullableToken = match('?'); + + if (lookahead.type !== Token.Identifier && !matchesNullableToken) { + throwUnexpected(lookahead); + } + + if (!matchesNullableToken) { + annotationLookahead = lookahead2(); + } + + annotationPresent = + matchesNullableToken + + // function (number numVal) {} + || annotationLookahead.type === Token.Identifier + + // function (fn(number)|array param) {} + || (annotationLookahead.type === Token.Punctuator + && (annotationLookahead.value === '(' + || annotationLookahead.value === '<' + || annotationLookahead.value === '|')); + + if (!annotationPresent) { + return parseVariableIdentifier(); + } + + annotation = parseTypeAnnotation(); + identifier = parseVariableIdentifier(); + + return delegate.createTypeAnnotatedIdentifier( + annotation, + identifier + ); + } + + function parseVariableDeclaration(kind) { + var id, + init = null; + if (match('{')) { + id = parseObjectInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else if (match('[')) { + id = parseArrayInitialiser(); + reinterpretAsAssignmentBindingPattern(id); + } else { + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + // 12.2.1 + if (strict && isRestrictedWord(id.name)) { + throwErrorTolerant({}, Messages.StrictVarName); + } + } + + if (kind === 'const') { + if (!match('=')) { + throwError({}, Messages.NoUnintializedConst); + } + expect('='); + init = parseAssignmentExpression(); + } else if (match('=')) { + lex(); + init = parseAssignmentExpression(); + } + + return delegate.createVariableDeclarator(id, init); + } + + function parseVariableDeclarationList(kind) { + var list = []; + + do { + list.push(parseVariableDeclaration(kind)); + if (!match(',')) { + break; + } + lex(); + } while (index < length); + + return list; + } + + function parseVariableStatement() { + var declarations; + + expectKeyword('var'); + + declarations = parseVariableDeclarationList(); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, 'var'); + } + + // kind may be `const` or `let` + // Both are experimental and not in the specification yet. + // see http://wiki.ecmascript.org/doku.php?id=harmony:const + // and http://wiki.ecmascript.org/doku.php?id=harmony:let + function parseConstLetDeclaration(kind) { + var declarations; + + expectKeyword(kind); + + declarations = parseVariableDeclarationList(kind); + + consumeSemicolon(); + + return delegate.createVariableDeclaration(declarations, kind); + } + + // http://wiki.ecmascript.org/doku.php?id=harmony:modules + + function parseModuleDeclaration() { + var id, src, body; + + lex(); // 'module' + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterModule); + } + + switch (lookahead.type) { + + case Token.StringLiteral: + id = parsePrimaryExpression(); + body = parseModuleBlock(); + src = null; + break; + + case Token.Identifier: + id = parseVariableIdentifier(); + body = null; + if (!matchContextualKeyword('from')) { + throwUnexpected(lex()); + } + lex(); + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + break; + } + + consumeSemicolon(); + return delegate.createModuleDeclaration(id, src, body); + } + + function parseExportBatchSpecifier() { + expect('*'); + return delegate.createExportBatchSpecifier(); + } + + function parseExportSpecifier() { + var id, name = null; + + id = parseVariableIdentifier(); + if (matchContextualKeyword('as')) { + lex(); + name = parseNonComputedProperty(); + } + + return delegate.createExportSpecifier(id, name); + } + + function parseExportDeclaration() { + var previousAllowDefault, decl, def, src, specifiers; + + expectKeyword('export'); + + if (matchKeyword('default')) { + lex(); + if (match('=')) { + lex(); + def = parseAssignmentExpression(); + } else if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'let': + case 'const': + case 'var': + case 'class': + def = parseSourceElement(); + break; + case 'function': + def = parseFunctionExpression(); + break; + default: + throwUnexpected(lex()); + } + } else { + def = parseAssignmentExpression(); + } + consumeSemicolon(); + return delegate.createExportDeclaration(true, def, null, null); + } + + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'let': + case 'const': + case 'var': + case 'class': + case 'function': + previousAllowDefault = state.allowDefault; + state.allowDefault = true; + decl = delegate.createExportDeclaration(false, parseSourceElement(), null, null); + state.allowDefault = previousAllowDefault; + return decl; + } + throwUnexpected(lex()); + } + + specifiers = []; + src = null; + + if (match('*')) { + specifiers.push(parseExportBatchSpecifier()); + } else { + expect('{'); + do { + specifiers.push(parseExportSpecifier()); + } while (match(',') && lex()); + expect('}'); + } + + if (matchContextualKeyword('from')) { + lex(); + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + } + + consumeSemicolon(); + + return delegate.createExportDeclaration(false, null, specifiers, src); + } + + function parseImportDeclaration() { + var specifiers, kind, src; + + expectKeyword('import'); + specifiers = []; + + if (isIdentifierName(lookahead)) { + kind = 'default'; + specifiers.push(parseImportSpecifier()); + + if (!matchContextualKeyword('from')) { + throwError({}, Messages.NoFromAfterImport); + } + lex(); + } else if (match('{')) { + kind = 'named'; + lex(); + do { + specifiers.push(parseImportSpecifier()); + } while (match(',') && lex()); + expect('}'); + + if (!matchContextualKeyword('from')) { + throwError({}, Messages.NoFromAfterImport); + } + lex(); + } + + src = parsePrimaryExpression(); + if (src.type !== Syntax.Literal) { + throwError({}, Messages.InvalidModuleSpecifier); + } + + consumeSemicolon(); + + return delegate.createImportDeclaration(specifiers, kind, src); + } + + function parseImportSpecifier() { + var id, name = null; + + id = parseNonComputedProperty(); + if (matchContextualKeyword('as')) { + lex(); + name = parseVariableIdentifier(); + } + + return delegate.createImportSpecifier(id, name); + } + + // 12.3 Empty Statement + + function parseEmptyStatement() { + expect(';'); + return delegate.createEmptyStatement(); + } + + // 12.4 Expression Statement + + function parseExpressionStatement() { + var expr = parseExpression(); + consumeSemicolon(); + return delegate.createExpressionStatement(expr); + } + + // 12.5 If statement + + function parseIfStatement() { + var test, consequent, alternate; + + expectKeyword('if'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + consequent = parseStatement(); + + if (matchKeyword('else')) { + lex(); + alternate = parseStatement(); + } else { + alternate = null; + } + + return delegate.createIfStatement(test, consequent, alternate); + } + + // 12.6 Iteration Statements + + function parseDoWhileStatement() { + var body, test, oldInIteration; + + expectKeyword('do'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + if (match(';')) { + lex(); + } + + return delegate.createDoWhileStatement(body, test); + } + + function parseWhileStatement() { + var test, body, oldInIteration; + + expectKeyword('while'); + + expect('('); + + test = parseExpression(); + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + body = parseStatement(); + + state.inIteration = oldInIteration; + + return delegate.createWhileStatement(test, body); + } + + function parseForVariableDeclaration() { + var token = lex(), + declarations = parseVariableDeclarationList(); + + return delegate.createVariableDeclaration(declarations, token.value); + } + + function parseForStatement(opts) { + var init, test, update, left, right, body, operator, oldInIteration; + init = test = update = null; + expectKeyword('for'); + + // http://wiki.ecmascript.org/doku.php?id=proposals:iterators_and_generators&s=each + if (matchContextualKeyword("each")) { + throwError({}, Messages.EachNotAllowed); + } + + expect('('); + + if (match(';')) { + lex(); + } else { + if (matchKeyword('var') || matchKeyword('let') || matchKeyword('const')) { + state.allowIn = false; + init = parseForVariableDeclaration(); + state.allowIn = true; + + if (init.declarations.length === 1) { + if (matchKeyword('in') || matchContextualKeyword('of')) { + operator = lookahead; + if (!((operator.value === 'in' || init.kind !== 'var') && init.declarations[0].init)) { + lex(); + left = init; + right = parseExpression(); + init = null; + } + } + } + } else { + state.allowIn = false; + init = parseExpression(); + state.allowIn = true; + + if (matchContextualKeyword('of')) { + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } else if (matchKeyword('in')) { + // LeftHandSideExpression + if (!isAssignableLeftHandSide(init)) { + throwError({}, Messages.InvalidLHSInForIn); + } + operator = lex(); + left = init; + right = parseExpression(); + init = null; + } + } + + if (typeof left === 'undefined') { + expect(';'); + } + } + + if (typeof left === 'undefined') { + + if (!match(';')) { + test = parseExpression(); + } + expect(';'); + + if (!match(')')) { + update = parseExpression(); + } + } + + expect(')'); + + oldInIteration = state.inIteration; + state.inIteration = true; + + if (!(opts !== undefined && opts.ignore_body)) { + body = parseStatement(); + } + + state.inIteration = oldInIteration; + + if (typeof left === 'undefined') { + return delegate.createForStatement(init, test, update, body); + } + + if (operator.value === 'in') { + return delegate.createForInStatement(left, right, body); + } + return delegate.createForOfStatement(left, right, body); + } + + // 12.7 The continue statement + + function parseContinueStatement() { + var label = null, key; + + expectKeyword('continue'); + + // Optimize the most common form: 'continue;'. + if (source.charCodeAt(index) === 59) { + lex(); + + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (peekLineTerminator()) { + if (!state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !state.inIteration) { + throwError({}, Messages.IllegalContinue); + } + + return delegate.createContinueStatement(label); + } + + // 12.8 The break statement + + function parseBreakStatement() { + var label = null, key; + + expectKeyword('break'); + + // Catch the very common case first: immediately a semicolon (char #59). + if (source.charCodeAt(index) === 59) { + lex(); + + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (peekLineTerminator()) { + if (!(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(null); + } + + if (lookahead.type === Token.Identifier) { + label = parseVariableIdentifier(); + + key = '$' + label.name; + if (!Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.UnknownLabel, label.name); + } + } + + consumeSemicolon(); + + if (label === null && !(state.inIteration || state.inSwitch)) { + throwError({}, Messages.IllegalBreak); + } + + return delegate.createBreakStatement(label); + } + + // 12.9 The return statement + + function parseReturnStatement() { + var argument = null; + + expectKeyword('return'); + + if (!state.inFunctionBody) { + throwErrorTolerant({}, Messages.IllegalReturn); + } + + // 'return' followed by a space and an identifier is very common. + if (source.charCodeAt(index) === 32) { + if (isIdentifierStart(source.charCodeAt(index + 1))) { + argument = parseExpression(); + consumeSemicolon(); + return delegate.createReturnStatement(argument); + } + } + + if (peekLineTerminator()) { + return delegate.createReturnStatement(null); + } + + if (!match(';')) { + if (!match('}') && lookahead.type !== Token.EOF) { + argument = parseExpression(); + } + } + + consumeSemicolon(); + + return delegate.createReturnStatement(argument); + } + + // 12.10 The with statement + + function parseWithStatement() { + var object, body; + + if (strict) { + throwErrorTolerant({}, Messages.StrictModeWith); + } + + expectKeyword('with'); + + expect('('); + + object = parseExpression(); + + expect(')'); + + body = parseStatement(); + + return delegate.createWithStatement(object, body); + } + + // 12.10 The swith statement + + function parseSwitchCase() { + var test, + consequent = [], + sourceElement; + + if (matchKeyword('default')) { + lex(); + test = null; + } else { + expectKeyword('case'); + test = parseExpression(); + } + expect(':'); + + while (index < length) { + if (match('}') || matchKeyword('default') || matchKeyword('case')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + consequent.push(sourceElement); + } + + return delegate.createSwitchCase(test, consequent); + } + + function parseSwitchStatement() { + var discriminant, cases, clause, oldInSwitch, defaultFound; + + expectKeyword('switch'); + + expect('('); + + discriminant = parseExpression(); + + expect(')'); + + expect('{'); + + cases = []; + + if (match('}')) { + lex(); + return delegate.createSwitchStatement(discriminant, cases); + } + + oldInSwitch = state.inSwitch; + state.inSwitch = true; + defaultFound = false; + + while (index < length) { + if (match('}')) { + break; + } + clause = parseSwitchCase(); + if (clause.test === null) { + if (defaultFound) { + throwError({}, Messages.MultipleDefaultsInSwitch); + } + defaultFound = true; + } + cases.push(clause); + } + + state.inSwitch = oldInSwitch; + + expect('}'); + + return delegate.createSwitchStatement(discriminant, cases); + } + + // 12.13 The throw statement + + function parseThrowStatement() { + var argument; + + expectKeyword('throw'); + + if (peekLineTerminator()) { + throwError({}, Messages.NewlineAfterThrow); + } + + argument = parseExpression(); + + consumeSemicolon(); + + return delegate.createThrowStatement(argument); + } + + // 12.14 The try statement + + function parseCatchClause() { + var param, body; + + expectKeyword('catch'); + + expect('('); + if (match(')')) { + throwUnexpected(lookahead); + } + + param = parseExpression(); + // 12.14.1 + if (strict && param.type === Syntax.Identifier && isRestrictedWord(param.name)) { + throwErrorTolerant({}, Messages.StrictCatchVariable); + } + + expect(')'); + body = parseBlock(); + return delegate.createCatchClause(param, body); + } + + function parseTryStatement() { + var block, handlers = [], finalizer = null; + + expectKeyword('try'); + + block = parseBlock(); + + if (matchKeyword('catch')) { + handlers.push(parseCatchClause()); + } + + if (matchKeyword('finally')) { + lex(); + finalizer = parseBlock(); + } + + if (handlers.length === 0 && !finalizer) { + throwError({}, Messages.NoCatchOrFinally); + } + + return delegate.createTryStatement(block, [], handlers, finalizer); + } + + // 12.15 The debugger statement + + function parseDebuggerStatement() { + expectKeyword('debugger'); + + consumeSemicolon(); + + return delegate.createDebuggerStatement(); + } + + // 12 Statements + + function parseStatement() { + var type = lookahead.type, + expr, + labeledBody, + key; + + if (type === Token.EOF) { + throwUnexpected(lookahead); + } + + if (type === Token.Punctuator) { + switch (lookahead.value) { + case ';': + return parseEmptyStatement(); + case '{': + return parseBlock(); + case '(': + return parseExpressionStatement(); + default: + break; + } + } + + if (type === Token.Keyword) { + switch (lookahead.value) { + case 'break': + return parseBreakStatement(); + case 'continue': + return parseContinueStatement(); + case 'debugger': + return parseDebuggerStatement(); + case 'do': + return parseDoWhileStatement(); + case 'for': + return parseForStatement(); + case 'function': + return parseFunctionDeclaration(); + case 'class': + return parseClassDeclaration(); + case 'if': + return parseIfStatement(); + case 'return': + return parseReturnStatement(); + case 'switch': + return parseSwitchStatement(); + case 'throw': + return parseThrowStatement(); + case 'try': + return parseTryStatement(); + case 'var': + return parseVariableStatement(); + case 'while': + return parseWhileStatement(); + case 'with': + return parseWithStatement(); + default: + break; + } + } + + expr = parseExpression(); + + // 12.12 Labelled Statements + if ((expr.type === Syntax.Identifier) && match(':')) { + lex(); + + key = '$' + expr.name; + if (Object.prototype.hasOwnProperty.call(state.labelSet, key)) { + throwError({}, Messages.Redeclaration, 'Label', expr.name); + } + + state.labelSet[key] = true; + labeledBody = parseStatement(); + delete state.labelSet[key]; + return delegate.createLabeledStatement(expr, labeledBody); + } + + consumeSemicolon(); + + return delegate.createExpressionStatement(expr); + } + + // 13 Function Definition + + function parseConciseBody() { + if (match('{')) { + return parseFunctionSourceElements(); + } + return parseAssignmentExpression(); + } + + function parseFunctionSourceElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted, + oldLabelSet, oldInIteration, oldInSwitch, oldInFunctionBody, oldParenthesizedCount; + + expect('{'); + + while (index < length) { + if (lookahead.type !== Token.StringLiteral) { + break; + } + token = lookahead; + + sourceElement = parseSourceElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + oldLabelSet = state.labelSet; + oldInIteration = state.inIteration; + oldInSwitch = state.inSwitch; + oldInFunctionBody = state.inFunctionBody; + oldParenthesizedCount = state.parenthesizedCount; + + state.labelSet = {}; + state.inIteration = false; + state.inSwitch = false; + state.inFunctionBody = true; + state.parenthesizedCount = 0; + + while (index < length) { + if (match('}')) { + break; + } + sourceElement = parseSourceElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + + expect('}'); + + state.labelSet = oldLabelSet; + state.inIteration = oldInIteration; + state.inSwitch = oldInSwitch; + state.inFunctionBody = oldInFunctionBody; + state.parenthesizedCount = oldParenthesizedCount; + + return delegate.createBlockStatement(sourceElements); + } + + function validateParam(options, param, name) { + var key = '$' + name; + if (strict) { + if (isRestrictedWord(name)) { + options.stricted = param; + options.message = Messages.StrictParamName; + } + if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.stricted = param; + options.message = Messages.StrictParamDupe; + } + } else if (!options.firstRestricted) { + if (isRestrictedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictParamName; + } else if (isStrictModeReservedWord(name)) { + options.firstRestricted = param; + options.message = Messages.StrictReservedWord; + } else if (Object.prototype.hasOwnProperty.call(options.paramSet, key)) { + options.firstRestricted = param; + options.message = Messages.StrictParamDupe; + } + } + options.paramSet[key] = true; + } + + function parseParam(options) { + var token, rest, param, def; + + token = lookahead; + if (token.value === '...') { + token = lex(); + rest = true; + } + + if (match('[')) { + param = parseArrayInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else if (match('{')) { + if (rest) { + throwError({}, Messages.ObjectPatternAsRestParameter); + } + param = parseObjectInitialiser(); + reinterpretAsDestructuredParameter(options, param); + } else { + // We don't currently support typed rest params because doing so is + // a bit awkward. We may come back to this, but for now we'll punt + // on it. + param = rest + ? parseVariableIdentifier() + : parseAnnotatableIdentifier(); + validateParam(options, token, token.value); + if (match('=')) { + if (rest) { + throwErrorTolerant(lookahead, Messages.DefaultRestParameter); + } + lex(); + def = parseAssignmentExpression(); + ++options.defaultCount; + } + } + + if (rest) { + if (!match(')')) { + throwError({}, Messages.ParameterAfterRestParameter); + } + options.rest = param; + return false; + } + + options.params.push(param); + options.defaults.push(def); + return !match(')'); + } + + function parseParams(firstRestricted) { + var options; + + options = { + params: [], + defaultCount: 0, + defaults: [], + rest: null, + firstRestricted: firstRestricted + }; + + expect('('); + + if (!match(')')) { + options.paramSet = {}; + while (index < length) { + if (!parseParam(options)) { + break; + } + expect(','); + } + } + + expect(')'); + + if (options.defaultCount === 0) { + options.defaults = []; + } + + if (match(':')) { + lex(); + options.returnTypeAnnotation = parseTypeAnnotation(); + } + + return options; + } + + function parseFunctionDeclaration() { + var id, body, token, tmp, firstRestricted, message, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + if (match('*')) { + lex(); + generator = true; + } + + token = lookahead; + + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionDeclaration(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression, + tmp.returnTypeAnnotation); + } + + function parseFunctionExpression() { + var token, id = null, firstRestricted, message, tmp, body, previousStrict, previousYieldAllowed, generator, expression; + + expectKeyword('function'); + + generator = false; + + if (match('*')) { + lex(); + generator = true; + } + + if (!match('(')) { + token = lookahead; + id = parseVariableIdentifier(); + if (strict) { + if (isRestrictedWord(token.value)) { + throwErrorTolerant(token, Messages.StrictFunctionName); + } + } else { + if (isRestrictedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictFunctionName; + } else if (isStrictModeReservedWord(token.value)) { + firstRestricted = token; + message = Messages.StrictReservedWord; + } + } + } + + tmp = parseParams(firstRestricted); + firstRestricted = tmp.firstRestricted; + if (tmp.message) { + message = tmp.message; + } + + previousStrict = strict; + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = generator; + + // here we redo some work in order to set 'expression' + expression = !match('{'); + body = parseConciseBody(); + + if (strict && firstRestricted) { + throwError(firstRestricted, message); + } + if (strict && tmp.stricted) { + throwErrorTolerant(tmp.stricted, message); + } + if (state.yieldAllowed && !state.yieldFound) { + throwErrorTolerant({}, Messages.NoYieldInGenerator); + } + strict = previousStrict; + state.yieldAllowed = previousYieldAllowed; + + return delegate.createFunctionExpression(id, tmp.params, tmp.defaults, body, tmp.rest, generator, expression, + tmp.returnTypeAnnotation); + } + + function parseYieldExpression() { + var delegateFlag, expr, previousYieldAllowed; + + expectKeyword('yield'); + + if (!state.yieldAllowed) { + throwErrorTolerant({}, Messages.IllegalYield); + } + + delegateFlag = false; + if (match('*')) { + lex(); + delegateFlag = true; + } + + // It is a Syntax Error if any AssignmentExpression Contains YieldExpression. + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + expr = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + state.yieldFound = true; + + return delegate.createYieldExpression(expr, delegateFlag); + } + + // 14 Classes + + function parseMethodDefinition(existingPropNames) { + var token, key, param, propType, isValidDuplicateProp = false; + + if (lookahead.value === 'static') { + propType = ClassPropertyType.static; + lex(); + } else { + propType = ClassPropertyType.prototype; + } + + if (match('*')) { + lex(); + return delegate.createMethodDefinition( + propType, + '', + parseObjectPropertyKey(), + parsePropertyMethodFunction({ generator: true }) + ); + } + + token = lookahead; + key = parseObjectPropertyKey(); + + if (token.value === 'get' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a setter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a getter for this prop + existingPropNames[propType][key.name].get === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a setter + && existingPropNames[propType][key.name].set !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].get = true; + + expect('('); + expect(')'); + return delegate.createMethodDefinition( + propType, + 'get', + key, + parsePropertyFunction({ generator: false }) + ); + } + if (token.value === 'set' && !match('(')) { + key = parseObjectPropertyKey(); + + // It is a syntax error if any other properties have a name + // duplicating this one unless they are a getter + if (existingPropNames[propType].hasOwnProperty(key.name)) { + isValidDuplicateProp = + // There isn't already a setter for this prop + existingPropNames[propType][key.name].set === undefined + // There isn't already a data prop by this name + && existingPropNames[propType][key.name].data === undefined + // The only existing prop by this name is a getter + && existingPropNames[propType][key.name].get !== undefined; + if (!isValidDuplicateProp) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].set = true; + + expect('('); + token = lookahead; + param = [ parseVariableIdentifier() ]; + expect(')'); + return delegate.createMethodDefinition( + propType, + 'set', + key, + parsePropertyFunction({ params: param, generator: false, name: token }) + ); + } + + // It is a syntax error if any other properties have the same name as a + // non-getter, non-setter method + if (existingPropNames[propType].hasOwnProperty(key.name)) { + throwError(key, Messages.IllegalDuplicateClassProperty); + } else { + existingPropNames[propType][key.name] = {}; + } + existingPropNames[propType][key.name].data = true; + + return delegate.createMethodDefinition( + propType, + '', + key, + parsePropertyMethodFunction({ generator: false }) + ); + } + + function parseClassElement(existingProps) { + if (match(';')) { + lex(); + return; + } + return parseMethodDefinition(existingProps); + } + + function parseClassBody() { + var classElement, classElements = [], existingProps = {}; + + existingProps[ClassPropertyType.static] = {}; + existingProps[ClassPropertyType.prototype] = {}; + + expect('{'); + + while (index < length) { + if (match('}')) { + break; + } + classElement = parseClassElement(existingProps); + + if (typeof classElement !== 'undefined') { + classElements.push(classElement); + } + } + + expect('}'); + + return delegate.createClassBody(classElements); + } + + function parseClassExpression() { + var id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + if (!matchKeyword('extends') && !match('{')) { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassExpression(id, superClass, parseClassBody()); + } + + function parseClassDeclaration() { + var id, previousYieldAllowed, superClass = null; + + expectKeyword('class'); + + if (state.allowDefault) { + id = matchKeyword('default') ? parseNonComputedProperty() : parseVariableIdentifier(); + } else { + id = parseVariableIdentifier(); + } + + if (matchKeyword('extends')) { + expectKeyword('extends'); + previousYieldAllowed = state.yieldAllowed; + state.yieldAllowed = false; + superClass = parseAssignmentExpression(); + state.yieldAllowed = previousYieldAllowed; + } + + return delegate.createClassDeclaration(id, superClass, parseClassBody()); + } + + // 15 Program + + function matchModuleDeclaration() { + var id; + if (matchContextualKeyword('module')) { + id = lookahead2(); + return id.type === Token.StringLiteral || id.type === Token.Identifier; + } + return false; + } + + function parseSourceElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'const': + case 'let': + return parseConstLetDeclaration(lookahead.value); + case 'function': + return parseFunctionDeclaration(); + case 'export': + return parseExportDeclaration(); + case 'import': + return parseImportDeclaration(); + default: + return parseStatement(); + } + } + + if (matchModuleDeclaration()) { + throwError({}, Messages.NestedModule); + } + + if (lookahead.type !== Token.EOF) { + return parseStatement(); + } + } + + function parseProgramElement() { + if (lookahead.type === Token.Keyword) { + switch (lookahead.value) { + case 'export': + return parseExportDeclaration(); + case 'import': + return parseImportDeclaration(); + } + } + + if (matchModuleDeclaration()) { + return parseModuleDeclaration(); + } + + return parseSourceElement(); + } + + function parseProgramElements() { + var sourceElement, sourceElements = [], token, directive, firstRestricted; + + while (index < length) { + token = lookahead; + if (token.type !== Token.StringLiteral) { + break; + } + + sourceElement = parseProgramElement(); + sourceElements.push(sourceElement); + if (sourceElement.expression.type !== Syntax.Literal) { + // this is not directive + break; + } + directive = source.slice(token.range[0] + 1, token.range[1] - 1); + if (directive === 'use strict') { + strict = true; + if (firstRestricted) { + throwErrorTolerant(firstRestricted, Messages.StrictOctalLiteral); + } + } else { + if (!firstRestricted && token.octal) { + firstRestricted = token; + } + } + } + + while (index < length) { + sourceElement = parseProgramElement(); + if (typeof sourceElement === 'undefined') { + break; + } + sourceElements.push(sourceElement); + } + return sourceElements; + } + + function parseModuleElement() { + return parseSourceElement(); + } + + function parseModuleElements() { + var list = [], + statement; + + while (index < length) { + if (match('}')) { + break; + } + statement = parseModuleElement(); + if (typeof statement === 'undefined') { + break; + } + list.push(statement); + } + + return list; + } + + function parseModuleBlock() { + var block; + + expect('{'); + + block = parseModuleElements(); + + expect('}'); + + return delegate.createBlockStatement(block); + } + + function parseProgram() { + var body; + strict = false; + peek(); + body = parseProgramElements(); + return delegate.createProgram(body); + } + + // The following functions are needed only when the option to preserve + // the comments is active. + + function addComment(type, value, start, end, loc) { + assert(typeof start === 'number', 'Comment must have valid position'); + + // Because the way the actual token is scanned, often the comments + // (if any) are skipped twice during the lexical analysis. + // Thus, we need to skip adding a comment if the comment array already + // handled it. + if (extra.comments.length > 0) { + if (extra.comments[extra.comments.length - 1].range[1] > start) { + return; + } + } + + extra.comments.push({ + type: type, + value: value, + range: [start, end], + loc: loc + }); + } + + function scanComment() { + var comment, ch, loc, start, blockComment, lineComment; + + comment = ''; + blockComment = false; + lineComment = false; + + while (index < length) { + ch = source[index]; + + if (lineComment) { + ch = source[index++]; + if (isLineTerminator(ch.charCodeAt(0))) { + loc.end = { + line: lineNumber, + column: index - lineStart - 1 + }; + lineComment = false; + addComment('Line', comment, start, index - 1, loc); + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + comment = ''; + } else if (index >= length) { + lineComment = false; + comment += ch; + loc.end = { + line: lineNumber, + column: length - lineStart + }; + addComment('Line', comment, start, length, loc); + } else { + comment += ch; + } + } else if (blockComment) { + if (isLineTerminator(ch.charCodeAt(0))) { + if (ch === '\r' && source[index + 1] === '\n') { + ++index; + comment += '\r\n'; + } else { + comment += ch; + } + ++lineNumber; + ++index; + lineStart = index; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + ch = source[index++]; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + comment += ch; + if (ch === '*') { + ch = source[index]; + if (ch === '/') { + comment = comment.substr(0, comment.length - 1); + blockComment = false; + ++index; + loc.end = { + line: lineNumber, + column: index - lineStart + }; + addComment('Block', comment, start, index, loc); + comment = ''; + } + } + } + } else if (ch === '/') { + ch = source[index + 1]; + if (ch === '/') { + loc = { + start: { + line: lineNumber, + column: index - lineStart + } + }; + start = index; + index += 2; + lineComment = true; + if (index >= length) { + loc.end = { + line: lineNumber, + column: index - lineStart + }; + lineComment = false; + addComment('Line', comment, start, index, loc); + } + } else if (ch === '*') { + start = index; + index += 2; + blockComment = true; + loc = { + start: { + line: lineNumber, + column: index - lineStart - 2 + } + }; + if (index >= length) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + } else { + break; + } + } else if (isWhiteSpace(ch.charCodeAt(0))) { + ++index; + } else if (isLineTerminator(ch.charCodeAt(0))) { + ++index; + if (ch === '\r' && source[index] === '\n') { + ++index; + } + ++lineNumber; + lineStart = index; + } else { + break; + } + } + } + + function filterCommentLocation() { + var i, entry, comment, comments = []; + + for (i = 0; i < extra.comments.length; ++i) { + entry = extra.comments[i]; + comment = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + comment.range = entry.range; + } + if (extra.loc) { + comment.loc = entry.loc; + } + comments.push(comment); + } + + extra.comments = comments; + } + + // 16 XJS + + XHTMLEntities = { + quot: '\u0022', + amp: '&', + apos: "\u0027", + lt: "<", + gt: ">", + nbsp: "\u00A0", + iexcl: "\u00A1", + cent: "\u00A2", + pound: "\u00A3", + curren: "\u00A4", + yen: "\u00A5", + brvbar: "\u00A6", + sect: "\u00A7", + uml: "\u00A8", + copy: "\u00A9", + ordf: "\u00AA", + laquo: "\u00AB", + not: "\u00AC", + shy: "\u00AD", + reg: "\u00AE", + macr: "\u00AF", + deg: "\u00B0", + plusmn: "\u00B1", + sup2: "\u00B2", + sup3: "\u00B3", + acute: "\u00B4", + micro: "\u00B5", + para: "\u00B6", + middot: "\u00B7", + cedil: "\u00B8", + sup1: "\u00B9", + ordm: "\u00BA", + raquo: "\u00BB", + frac14: "\u00BC", + frac12: "\u00BD", + frac34: "\u00BE", + iquest: "\u00BF", + Agrave: "\u00C0", + Aacute: "\u00C1", + Acirc: "\u00C2", + Atilde: "\u00C3", + Auml: "\u00C4", + Aring: "\u00C5", + AElig: "\u00C6", + Ccedil: "\u00C7", + Egrave: "\u00C8", + Eacute: "\u00C9", + Ecirc: "\u00CA", + Euml: "\u00CB", + Igrave: "\u00CC", + Iacute: "\u00CD", + Icirc: "\u00CE", + Iuml: "\u00CF", + ETH: "\u00D0", + Ntilde: "\u00D1", + Ograve: "\u00D2", + Oacute: "\u00D3", + Ocirc: "\u00D4", + Otilde: "\u00D5", + Ouml: "\u00D6", + times: "\u00D7", + Oslash: "\u00D8", + Ugrave: "\u00D9", + Uacute: "\u00DA", + Ucirc: "\u00DB", + Uuml: "\u00DC", + Yacute: "\u00DD", + THORN: "\u00DE", + szlig: "\u00DF", + agrave: "\u00E0", + aacute: "\u00E1", + acirc: "\u00E2", + atilde: "\u00E3", + auml: "\u00E4", + aring: "\u00E5", + aelig: "\u00E6", + ccedil: "\u00E7", + egrave: "\u00E8", + eacute: "\u00E9", + ecirc: "\u00EA", + euml: "\u00EB", + igrave: "\u00EC", + iacute: "\u00ED", + icirc: "\u00EE", + iuml: "\u00EF", + eth: "\u00F0", + ntilde: "\u00F1", + ograve: "\u00F2", + oacute: "\u00F3", + ocirc: "\u00F4", + otilde: "\u00F5", + ouml: "\u00F6", + divide: "\u00F7", + oslash: "\u00F8", + ugrave: "\u00F9", + uacute: "\u00FA", + ucirc: "\u00FB", + uuml: "\u00FC", + yacute: "\u00FD", + thorn: "\u00FE", + yuml: "\u00FF", + OElig: "\u0152", + oelig: "\u0153", + Scaron: "\u0160", + scaron: "\u0161", + Yuml: "\u0178", + fnof: "\u0192", + circ: "\u02C6", + tilde: "\u02DC", + Alpha: "\u0391", + Beta: "\u0392", + Gamma: "\u0393", + Delta: "\u0394", + Epsilon: "\u0395", + Zeta: "\u0396", + Eta: "\u0397", + Theta: "\u0398", + Iota: "\u0399", + Kappa: "\u039A", + Lambda: "\u039B", + Mu: "\u039C", + Nu: "\u039D", + Xi: "\u039E", + Omicron: "\u039F", + Pi: "\u03A0", + Rho: "\u03A1", + Sigma: "\u03A3", + Tau: "\u03A4", + Upsilon: "\u03A5", + Phi: "\u03A6", + Chi: "\u03A7", + Psi: "\u03A8", + Omega: "\u03A9", + alpha: "\u03B1", + beta: "\u03B2", + gamma: "\u03B3", + delta: "\u03B4", + epsilon: "\u03B5", + zeta: "\u03B6", + eta: "\u03B7", + theta: "\u03B8", + iota: "\u03B9", + kappa: "\u03BA", + lambda: "\u03BB", + mu: "\u03BC", + nu: "\u03BD", + xi: "\u03BE", + omicron: "\u03BF", + pi: "\u03C0", + rho: "\u03C1", + sigmaf: "\u03C2", + sigma: "\u03C3", + tau: "\u03C4", + upsilon: "\u03C5", + phi: "\u03C6", + chi: "\u03C7", + psi: "\u03C8", + omega: "\u03C9", + thetasym: "\u03D1", + upsih: "\u03D2", + piv: "\u03D6", + ensp: "\u2002", + emsp: "\u2003", + thinsp: "\u2009", + zwnj: "\u200C", + zwj: "\u200D", + lrm: "\u200E", + rlm: "\u200F", + ndash: "\u2013", + mdash: "\u2014", + lsquo: "\u2018", + rsquo: "\u2019", + sbquo: "\u201A", + ldquo: "\u201C", + rdquo: "\u201D", + bdquo: "\u201E", + dagger: "\u2020", + Dagger: "\u2021", + bull: "\u2022", + hellip: "\u2026", + permil: "\u2030", + prime: "\u2032", + Prime: "\u2033", + lsaquo: "\u2039", + rsaquo: "\u203A", + oline: "\u203E", + frasl: "\u2044", + euro: "\u20AC", + image: "\u2111", + weierp: "\u2118", + real: "\u211C", + trade: "\u2122", + alefsym: "\u2135", + larr: "\u2190", + uarr: "\u2191", + rarr: "\u2192", + darr: "\u2193", + harr: "\u2194", + crarr: "\u21B5", + lArr: "\u21D0", + uArr: "\u21D1", + rArr: "\u21D2", + dArr: "\u21D3", + hArr: "\u21D4", + forall: "\u2200", + part: "\u2202", + exist: "\u2203", + empty: "\u2205", + nabla: "\u2207", + isin: "\u2208", + notin: "\u2209", + ni: "\u220B", + prod: "\u220F", + sum: "\u2211", + minus: "\u2212", + lowast: "\u2217", + radic: "\u221A", + prop: "\u221D", + infin: "\u221E", + ang: "\u2220", + and: "\u2227", + or: "\u2228", + cap: "\u2229", + cup: "\u222A", + "int": "\u222B", + there4: "\u2234", + sim: "\u223C", + cong: "\u2245", + asymp: "\u2248", + ne: "\u2260", + equiv: "\u2261", + le: "\u2264", + ge: "\u2265", + sub: "\u2282", + sup: "\u2283", + nsub: "\u2284", + sube: "\u2286", + supe: "\u2287", + oplus: "\u2295", + otimes: "\u2297", + perp: "\u22A5", + sdot: "\u22C5", + lceil: "\u2308", + rceil: "\u2309", + lfloor: "\u230A", + rfloor: "\u230B", + lang: "\u2329", + rang: "\u232A", + loz: "\u25CA", + spades: "\u2660", + clubs: "\u2663", + hearts: "\u2665", + diams: "\u2666" + }; + + function isXJSIdentifierStart(ch) { + // exclude backslash (\) + return (ch !== 92) && isIdentifierStart(ch); + } + + function isXJSIdentifierPart(ch) { + // exclude backslash (\) and add hyphen (-) + return (ch !== 92) && (ch === 45 || isIdentifierPart(ch)); + } + + function scanXJSIdentifier() { + var ch, start, id = '', namespace; + + start = index; + while (index < length) { + ch = source.charCodeAt(index); + if (!isXJSIdentifierPart(ch)) { + break; + } + id += source[index++]; + } + + if (ch === 58) { // : + ++index; + namespace = id; + id = ''; + + while (index < length) { + ch = source.charCodeAt(index); + if (!isXJSIdentifierPart(ch)) { + break; + } + id += source[index++]; + } + } + + if (!id) { + throwError({}, Messages.InvalidXJSTagName); + } + + return { + type: Token.XJSIdentifier, + value: id, + namespace: namespace, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSEntity() { + var ch, str = '', count = 0, entity; + ch = source[index]; + assert(ch === '&', 'Entity must start with an ampersand'); + index++; + while (index < length && count++ < 10) { + ch = source[index++]; + if (ch === ';') { + break; + } + str += ch; + } + + if (str[0] === '#' && str[1] === 'x') { + entity = String.fromCharCode(parseInt(str.substr(2), 16)); + } else if (str[0] === '#') { + entity = String.fromCharCode(parseInt(str.substr(1), 10)); + } else { + entity = XHTMLEntities[str]; + } + return entity; + } + + function scanXJSText(stopChars) { + var ch, str = '', start; + start = index; + while (index < length) { + ch = source[index]; + if (stopChars.indexOf(ch) !== -1) { + break; + } + if (ch === '&') { + str += scanXJSEntity(); + } else { + ch = source[index++]; + if (isLineTerminator(ch.charCodeAt(0))) { + ++lineNumber; + lineStart = index; + } + str += ch; + } + } + return { + type: Token.XJSText, + value: str, + lineNumber: lineNumber, + lineStart: lineStart, + range: [start, index] + }; + } + + function scanXJSStringLiteral() { + var innerToken, quote, start; + + quote = source[index]; + assert((quote === '\'' || quote === '"'), + 'String literal must starts with a quote'); + + start = index; + ++index; + + innerToken = scanXJSText([quote]); + + if (quote !== source[index]) { + throwError({}, Messages.UnexpectedToken, 'ILLEGAL'); + } + + ++index; + + innerToken.range = [start, index]; + + return innerToken; + } + + /** + * Between XJS opening and closing tags (e.g. HERE), anything that + * is not another XJS tag and is not an expression wrapped by {} is text. + */ + function advanceXJSChild() { + var ch = source.charCodeAt(index); + + // { (123) and < (60) + if (ch !== 123 && ch !== 60) { + return scanXJSText(['<', '{']); + } + + return scanPunctuator(); + } + + function parseXJSIdentifier() { + var token; + + if (lookahead.type !== Token.XJSIdentifier) { + throwUnexpected(lookahead); + } + + token = lex(); + return delegate.createXJSIdentifier(token.value, token.namespace); + } + + function parseXJSAttributeValue() { + var value; + if (match('{')) { + value = parseXJSExpressionContainer(); + if (value.expression.type === Syntax.XJSEmptyExpression) { + throwError( + value, + 'XJS attributes must only be assigned a non-empty ' + + 'expression' + ); + } + } else if (lookahead.type === Token.XJSText) { + value = delegate.createLiteral(lex()); + } else { + throwError({}, Messages.InvalidXJSAttributeValue); + } + return value; + } + + function parseXJSEmptyExpression() { + while (source.charAt(index) !== '}') { + index++; + } + return delegate.createXJSEmptyExpression(); + } + + function parseXJSExpressionContainer() { + var expression, origInXJSChild, origInXJSTag; + + origInXJSChild = state.inXJSChild; + origInXJSTag = state.inXJSTag; + state.inXJSChild = false; + state.inXJSTag = false; + + expect('{'); + + if (match('}')) { + expression = parseXJSEmptyExpression(); + } else { + expression = parseExpression(); + } + + state.inXJSChild = origInXJSChild; + state.inXJSTag = origInXJSTag; + + expect('}'); + + return delegate.createXJSExpressionContainer(expression); + } + + function parseXJSAttribute() { + var token, name, value; + + name = parseXJSIdentifier(); + + // HTML empty attribute + if (match('=')) { + lex(); + return delegate.createXJSAttribute(name, parseXJSAttributeValue()); + } + + return delegate.createXJSAttribute(name); + } + + function parseXJSChild() { + var token; + if (match('{')) { + token = parseXJSExpressionContainer(); + } else if (lookahead.type === Token.XJSText) { + token = delegate.createLiteral(lex()); + } else { + state.inXJSChild = false; + token = parseXJSElement(); + state.inXJSChild = true; + } + return token; + } + + function parseXJSClosingElement() { + var name, origInXJSTag; + origInXJSTag = state.inXJSTag; + state.inXJSTag = true; + state.inXJSChild = false; + expect('<'); + expect('/'); + name = parseXJSIdentifier(); + state.inXJSTag = origInXJSTag; + expect('>'); + return delegate.createXJSClosingElement(name); + } + + function parseXJSOpeningElement() { + var name, attribute, attributes = [], selfClosing = false, origInXJSTag; + + origInXJSTag = state.inXJSTag; + state.inXJSTag = true; + + expect('<'); + + name = parseXJSIdentifier(); + + while (index < length && + lookahead.value !== '/' && + lookahead.value !== '>') { + attributes.push(parseXJSAttribute()); + } + + state.inXJSTag = origInXJSTag; + + if (lookahead.value === '/') { + expect('/'); + expect('>'); + selfClosing = true; + } else { + state.inXJSChild = true; + expect('>'); + } + return delegate.createXJSOpeningElement(name, attributes, selfClosing); + } + + function parseXJSElement() { + var openingElement, closingElement, children = [], origInXJSChild; + + openingElement = parseXJSOpeningElement(); + + if (!openingElement.selfClosing) { + origInXJSChild = state.inXJSChild; + while (index < length) { + state.inXJSChild = false; // 0) { + token = extra.tokens[extra.tokens.length - 1]; + if (token.range[0] === pos && token.type === 'Punctuator') { + if (token.value === '/' || token.value === '/=') { + extra.tokens.pop(); + } + } + } + + extra.tokens.push({ + type: 'RegularExpression', + value: regex.literal, + range: [pos, index], + loc: loc + }); + } + + return regex; + } + + function filterTokenLocation() { + var i, entry, token, tokens = []; + + for (i = 0; i < extra.tokens.length; ++i) { + entry = extra.tokens[i]; + token = { + type: entry.type, + value: entry.value + }; + if (extra.range) { + token.range = entry.range; + } + if (extra.loc) { + token.loc = entry.loc; + } + tokens.push(token); + } + + extra.tokens = tokens; + } + + function LocationMarker() { + this.range = [index, index]; + this.loc = { + start: { + line: lineNumber, + column: index - lineStart + }, + end: { + line: lineNumber, + column: index - lineStart + } + }; + } + + LocationMarker.prototype = { + constructor: LocationMarker, + + end: function () { + this.range[1] = index; + this.loc.end.line = lineNumber; + this.loc.end.column = index - lineStart; + }, + + applyGroup: function (node) { + if (extra.range) { + node.groupRange = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.groupLoc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + }, + + apply: function (node) { + var nodeType = typeof node; + assert(nodeType === "object", + "Applying location marker to an unexpected node type: " + + nodeType); + + if (extra.range) { + node.range = [this.range[0], this.range[1]]; + } + if (extra.loc) { + node.loc = { + start: { + line: this.loc.start.line, + column: this.loc.start.column + }, + end: { + line: this.loc.end.line, + column: this.loc.end.column + } + }; + node = delegate.postProcess(node); + } + } + }; + + function createLocationMarker() { + return new LocationMarker(); + } + + function trackGroupExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + expect('('); + + ++state.parenthesizedCount; + + state.allowArrowFunction = !state.allowArrowFunction; + expr = parseExpression(); + state.allowArrowFunction = false; + + if (expr.type === 'ArrowFunctionExpression') { + marker.end(); + marker.apply(expr); + } else { + expect(')'); + marker.end(); + marker.applyGroup(expr); + } + + return expr; + } + + function trackLeftHandSideExpression() { + var marker, expr; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || lookahead.type === Token.Template) { + if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function trackLeftHandSideExpressionAllowCall() { + var marker, expr, args; + + skipComment(); + marker = createLocationMarker(); + + expr = matchKeyword('new') ? parseNewExpression() : parsePrimaryExpression(); + + while (match('.') || match('[') || match('(') || lookahead.type === Token.Template) { + if (match('(')) { + args = parseArguments(); + expr = delegate.createCallExpression(expr, args); + marker.end(); + marker.apply(expr); + } else if (match('[')) { + expr = delegate.createMemberExpression('[', expr, parseComputedMember()); + marker.end(); + marker.apply(expr); + } else if (match('.')) { + expr = delegate.createMemberExpression('.', expr, parseNonComputedMember()); + marker.end(); + marker.apply(expr); + } else { + expr = delegate.createTaggedTemplateExpression(expr, parseTemplateLiteral()); + marker.end(); + marker.apply(expr); + } + } + + return expr; + } + + function filterGroup(node) { + var n, i, entry; + + n = (Object.prototype.toString.apply(node) === '[object Array]') ? [] : {}; + for (i in node) { + if (node.hasOwnProperty(i) && i !== 'groupRange' && i !== 'groupLoc') { + entry = node[i]; + if (entry === null || typeof entry !== 'object' || entry instanceof RegExp) { + n[i] = entry; + } else { + n[i] = filterGroup(entry); + } + } + } + return n; + } + + function wrapTrackingFunction(range, loc, preserveWhitespace) { + + return function (parseFunction) { + + function isBinary(node) { + return node.type === Syntax.LogicalExpression || + node.type === Syntax.BinaryExpression; + } + + function visit(node) { + var start, end; + + if (isBinary(node.left)) { + visit(node.left); + } + if (isBinary(node.right)) { + visit(node.right); + } + + if (range) { + if (node.left.groupRange || node.right.groupRange) { + start = node.left.groupRange ? node.left.groupRange[0] : node.left.range[0]; + end = node.right.groupRange ? node.right.groupRange[1] : node.right.range[1]; + node.range = [start, end]; + } else if (typeof node.range === 'undefined') { + start = node.left.range[0]; + end = node.right.range[1]; + node.range = [start, end]; + } + } + if (loc) { + if (node.left.groupLoc || node.right.groupLoc) { + start = node.left.groupLoc ? node.left.groupLoc.start : node.left.loc.start; + end = node.right.groupLoc ? node.right.groupLoc.end : node.right.loc.end; + node.loc = { + start: start, + end: end + }; + node = delegate.postProcess(node); + } else if (typeof node.loc === 'undefined') { + node.loc = { + start: node.left.loc.start, + end: node.right.loc.end + }; + node = delegate.postProcess(node); + } + } + } + + return function () { + var marker, node; + + if (!preserveWhitespace) { + skipComment(); + } + + marker = createLocationMarker(); + node = parseFunction.apply(null, arguments); + marker.end(); + + if (range && typeof node.range === 'undefined') { + marker.apply(node); + } + + if (loc && typeof node.loc === 'undefined') { + marker.apply(node); + } + + if (isBinary(node)) { + visit(node); + } + + return node; + }; + }; + } + + function patch() { + + var wrapTracking, wrapTrackingPreserveWhitespace; + + if (extra.comments) { + extra.skipComment = skipComment; + skipComment = scanComment; + } + + if (extra.range || extra.loc) { + + extra.parseGroupExpression = parseGroupExpression; + extra.parseLeftHandSideExpression = parseLeftHandSideExpression; + extra.parseLeftHandSideExpressionAllowCall = parseLeftHandSideExpressionAllowCall; + parseGroupExpression = trackGroupExpression; + parseLeftHandSideExpression = trackLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = trackLeftHandSideExpressionAllowCall; + + wrapTracking = wrapTrackingFunction(extra.range, extra.loc); + wrapTrackingPreserveWhitespace = + wrapTrackingFunction(extra.range, extra.loc, true); + + extra.parseAssignmentExpression = parseAssignmentExpression; + extra.parseBinaryExpression = parseBinaryExpression; + extra.parseBlock = parseBlock; + extra.parseFunctionSourceElements = parseFunctionSourceElements; + extra.parseCatchClause = parseCatchClause; + extra.parseComputedMember = parseComputedMember; + extra.parseConditionalExpression = parseConditionalExpression; + extra.parseConstLetDeclaration = parseConstLetDeclaration; + extra.parseExportBatchSpecifier = parseExportBatchSpecifier; + extra.parseExportDeclaration = parseExportDeclaration; + extra.parseExportSpecifier = parseExportSpecifier; + extra.parseExpression = parseExpression; + extra.parseForVariableDeclaration = parseForVariableDeclaration; + extra.parseFunctionDeclaration = parseFunctionDeclaration; + extra.parseFunctionExpression = parseFunctionExpression; + extra.parseParams = parseParams; + extra.parseImportDeclaration = parseImportDeclaration; + extra.parseImportSpecifier = parseImportSpecifier; + extra.parseModuleDeclaration = parseModuleDeclaration; + extra.parseModuleBlock = parseModuleBlock; + extra.parseNewExpression = parseNewExpression; + extra.parseNonComputedProperty = parseNonComputedProperty; + extra.parseObjectProperty = parseObjectProperty; + extra.parseObjectPropertyKey = parseObjectPropertyKey; + extra.parsePostfixExpression = parsePostfixExpression; + extra.parsePrimaryExpression = parsePrimaryExpression; + extra.parseProgram = parseProgram; + extra.parsePropertyFunction = parsePropertyFunction; + extra.parseSpreadOrAssignmentExpression = parseSpreadOrAssignmentExpression; + extra.parseTemplateElement = parseTemplateElement; + extra.parseTemplateLiteral = parseTemplateLiteral; + extra.parseStatement = parseStatement; + extra.parseSwitchCase = parseSwitchCase; + extra.parseUnaryExpression = parseUnaryExpression; + extra.parseVariableDeclaration = parseVariableDeclaration; + extra.parseVariableIdentifier = parseVariableIdentifier; + extra.parseAnnotatableIdentifier = parseAnnotatableIdentifier; + extra.parseTypeAnnotation = parseTypeAnnotation; + extra.parseMethodDefinition = parseMethodDefinition; + extra.parseClassDeclaration = parseClassDeclaration; + extra.parseClassExpression = parseClassExpression; + extra.parseClassBody = parseClassBody; + extra.parseXJSIdentifier = parseXJSIdentifier; + extra.parseXJSChild = parseXJSChild; + extra.parseXJSAttribute = parseXJSAttribute; + extra.parseXJSAttributeValue = parseXJSAttributeValue; + extra.parseXJSExpressionContainer = parseXJSExpressionContainer; + extra.parseXJSEmptyExpression = parseXJSEmptyExpression; + extra.parseXJSElement = parseXJSElement; + extra.parseXJSClosingElement = parseXJSClosingElement; + extra.parseXJSOpeningElement = parseXJSOpeningElement; + + parseAssignmentExpression = wrapTracking(extra.parseAssignmentExpression); + parseBinaryExpression = wrapTracking(extra.parseBinaryExpression); + parseBlock = wrapTracking(extra.parseBlock); + parseFunctionSourceElements = wrapTracking(extra.parseFunctionSourceElements); + parseCatchClause = wrapTracking(extra.parseCatchClause); + parseComputedMember = wrapTracking(extra.parseComputedMember); + parseConditionalExpression = wrapTracking(extra.parseConditionalExpression); + parseConstLetDeclaration = wrapTracking(extra.parseConstLetDeclaration); + parseExportBatchSpecifier = wrapTracking(parseExportBatchSpecifier); + parseExportDeclaration = wrapTracking(parseExportDeclaration); + parseExportSpecifier = wrapTracking(parseExportSpecifier); + parseExpression = wrapTracking(extra.parseExpression); + parseForVariableDeclaration = wrapTracking(extra.parseForVariableDeclaration); + parseFunctionDeclaration = wrapTracking(extra.parseFunctionDeclaration); + parseFunctionExpression = wrapTracking(extra.parseFunctionExpression); + parseParams = wrapTracking(extra.parseParams); + parseImportDeclaration = wrapTracking(extra.parseImportDeclaration); + parseImportSpecifier = wrapTracking(extra.parseImportSpecifier); + parseModuleDeclaration = wrapTracking(extra.parseModuleDeclaration); + parseModuleBlock = wrapTracking(extra.parseModuleBlock); + parseLeftHandSideExpression = wrapTracking(parseLeftHandSideExpression); + parseNewExpression = wrapTracking(extra.parseNewExpression); + parseNonComputedProperty = wrapTracking(extra.parseNonComputedProperty); + parseObjectProperty = wrapTracking(extra.parseObjectProperty); + parseObjectPropertyKey = wrapTracking(extra.parseObjectPropertyKey); + parsePostfixExpression = wrapTracking(extra.parsePostfixExpression); + parsePrimaryExpression = wrapTracking(extra.parsePrimaryExpression); + parseProgram = wrapTracking(extra.parseProgram); + parsePropertyFunction = wrapTracking(extra.parsePropertyFunction); + parseTemplateElement = wrapTracking(extra.parseTemplateElement); + parseTemplateLiteral = wrapTracking(extra.parseTemplateLiteral); + parseSpreadOrAssignmentExpression = wrapTracking(extra.parseSpreadOrAssignmentExpression); + parseStatement = wrapTracking(extra.parseStatement); + parseSwitchCase = wrapTracking(extra.parseSwitchCase); + parseUnaryExpression = wrapTracking(extra.parseUnaryExpression); + parseVariableDeclaration = wrapTracking(extra.parseVariableDeclaration); + parseVariableIdentifier = wrapTracking(extra.parseVariableIdentifier); + parseAnnotatableIdentifier = wrapTracking(extra.parseAnnotatableIdentifier); + parseTypeAnnotation = wrapTracking(extra.parseTypeAnnotation); + parseMethodDefinition = wrapTracking(extra.parseMethodDefinition); + parseClassDeclaration = wrapTracking(extra.parseClassDeclaration); + parseClassExpression = wrapTracking(extra.parseClassExpression); + parseClassBody = wrapTracking(extra.parseClassBody); + parseXJSIdentifier = wrapTracking(extra.parseXJSIdentifier); + parseXJSChild = wrapTrackingPreserveWhitespace(extra.parseXJSChild); + parseXJSAttribute = wrapTracking(extra.parseXJSAttribute); + parseXJSAttributeValue = wrapTracking(extra.parseXJSAttributeValue); + parseXJSExpressionContainer = wrapTracking(extra.parseXJSExpressionContainer); + parseXJSEmptyExpression = wrapTrackingPreserveWhitespace(extra.parseXJSEmptyExpression); + parseXJSElement = wrapTracking(extra.parseXJSElement); + parseXJSClosingElement = wrapTracking(extra.parseXJSClosingElement); + parseXJSOpeningElement = wrapTracking(extra.parseXJSOpeningElement); + } + + if (typeof extra.tokens !== 'undefined') { + extra.advance = advance; + extra.scanRegExp = scanRegExp; + + advance = collectToken; + scanRegExp = collectRegex; + } + } + + function unpatch() { + if (typeof extra.skipComment === 'function') { + skipComment = extra.skipComment; + } + + if (extra.range || extra.loc) { + parseAssignmentExpression = extra.parseAssignmentExpression; + parseBinaryExpression = extra.parseBinaryExpression; + parseBlock = extra.parseBlock; + parseFunctionSourceElements = extra.parseFunctionSourceElements; + parseCatchClause = extra.parseCatchClause; + parseComputedMember = extra.parseComputedMember; + parseConditionalExpression = extra.parseConditionalExpression; + parseConstLetDeclaration = extra.parseConstLetDeclaration; + parseExportBatchSpecifier = extra.parseExportBatchSpecifier; + parseExportDeclaration = extra.parseExportDeclaration; + parseExportSpecifier = extra.parseExportSpecifier; + parseExpression = extra.parseExpression; + parseForVariableDeclaration = extra.parseForVariableDeclaration; + parseFunctionDeclaration = extra.parseFunctionDeclaration; + parseFunctionExpression = extra.parseFunctionExpression; + parseImportDeclaration = extra.parseImportDeclaration; + parseImportSpecifier = extra.parseImportSpecifier; + parseGroupExpression = extra.parseGroupExpression; + parseLeftHandSideExpression = extra.parseLeftHandSideExpression; + parseLeftHandSideExpressionAllowCall = extra.parseLeftHandSideExpressionAllowCall; + parseModuleDeclaration = extra.parseModuleDeclaration; + parseModuleBlock = extra.parseModuleBlock; + parseNewExpression = extra.parseNewExpression; + parseNonComputedProperty = extra.parseNonComputedProperty; + parseObjectProperty = extra.parseObjectProperty; + parseObjectPropertyKey = extra.parseObjectPropertyKey; + parsePostfixExpression = extra.parsePostfixExpression; + parsePrimaryExpression = extra.parsePrimaryExpression; + parseProgram = extra.parseProgram; + parsePropertyFunction = extra.parsePropertyFunction; + parseTemplateElement = extra.parseTemplateElement; + parseTemplateLiteral = extra.parseTemplateLiteral; + parseSpreadOrAssignmentExpression = extra.parseSpreadOrAssignmentExpression; + parseStatement = extra.parseStatement; + parseSwitchCase = extra.parseSwitchCase; + parseUnaryExpression = extra.parseUnaryExpression; + parseVariableDeclaration = extra.parseVariableDeclaration; + parseVariableIdentifier = extra.parseVariableIdentifier; + parseAnnotatableIdentifier = extra.parseAnnotatableIdentifier; + parseTypeAnnotation = extra.parseTypeAnnotation; + parseMethodDefinition = extra.parseMethodDefinition; + parseClassDeclaration = extra.parseClassDeclaration; + parseClassExpression = extra.parseClassExpression; + parseClassBody = extra.parseClassBody; + parseXJSIdentifier = extra.parseXJSIdentifier; + parseXJSChild = extra.parseXJSChild; + parseXJSAttribute = extra.parseXJSAttribute; + parseXJSAttributeValue = extra.parseXJSAttributeValue; + parseXJSExpressionContainer = extra.parseXJSExpressionContainer; + parseXJSEmptyExpression = extra.parseXJSEmptyExpression; + parseXJSElement = extra.parseXJSElement; + parseXJSClosingElement = extra.parseXJSClosingElement; + parseXJSOpeningElement = extra.parseXJSOpeningElement; + } + + if (typeof extra.scanRegExp === 'function') { + advance = extra.advance; + scanRegExp = extra.scanRegExp; + } + } + + // This is used to modify the delegate. + + function extend(object, properties) { + var entry, result = {}; + + for (entry in object) { + if (object.hasOwnProperty(entry)) { + result[entry] = object[entry]; + } + } + + for (entry in properties) { + if (properties.hasOwnProperty(entry)) { + result[entry] = properties[entry]; + } + } + + return result; + } + + function tokenize(code, options) { + var toString, + token, + tokens; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowDefault: true, + allowIn: true, + labelSet: {}, + inFunctionBody: false, + inIteration: false, + inSwitch: false + }; + + extra = {}; + + // Options matching. + options = options || {}; + + // Of course we collect tokens here. + options.tokens = true; + extra.tokens = []; + extra.tokenize = true; + // The following two fields are necessary to compute the Regex tokens. + extra.openParenToken = -1; + extra.openCurlyToken = -1; + + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + + try { + peek(); + if (lookahead.type === Token.EOF) { + return extra.tokens; + } + + token = lex(); + while (lookahead.type !== Token.EOF) { + try { + token = lex(); + } catch (lexError) { + token = lookahead; + if (extra.errors) { + extra.errors.push(lexError); + // We have to break on the first error + // to avoid infinite loops. + break; + } else { + throw lexError; + } + } + } + + filterTokenLocation(); + tokens = extra.tokens; + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + tokens.comments = extra.comments; + } + if (typeof extra.errors !== 'undefined') { + tokens.errors = extra.errors; + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + return tokens; + } + + function parse(code, options) { + var program, toString; + + toString = String; + if (typeof code !== 'string' && !(code instanceof String)) { + code = toString(code); + } + + delegate = SyntaxTreeDelegate; + source = code; + index = 0; + lineNumber = (source.length > 0) ? 1 : 0; + lineStart = 0; + length = source.length; + lookahead = null; + state = { + allowDefault: false, + allowIn: true, + labelSet: {}, + parenthesizedCount: 0, + inFunctionBody: false, + inIteration: false, + inSwitch: false, + yieldAllowed: false, + yieldFound: false + }; + + extra = {}; + if (typeof options !== 'undefined') { + extra.range = (typeof options.range === 'boolean') && options.range; + extra.loc = (typeof options.loc === 'boolean') && options.loc; + + if (extra.loc && options.source !== null && options.source !== undefined) { + delegate = extend(delegate, { + 'postProcess': function (node) { + node.loc.source = toString(options.source); + return node; + } + }); + } + + if (typeof options.tokens === 'boolean' && options.tokens) { + extra.tokens = []; + } + if (typeof options.comment === 'boolean' && options.comment) { + extra.comments = []; + } + if (typeof options.tolerant === 'boolean' && options.tolerant) { + extra.errors = []; + } + } + + if (length > 0) { + if (typeof source[0] === 'undefined') { + // Try first to convert to a string. This is good as fast path + // for old IE which understands string indexing for string + // literals only and not for string object. + if (code instanceof String) { + source = code.valueOf(); + } + } + } + + patch(); + try { + program = parseProgram(); + if (typeof extra.comments !== 'undefined') { + filterCommentLocation(); + program.comments = extra.comments; + } + if (typeof extra.tokens !== 'undefined') { + filterTokenLocation(); + program.tokens = extra.tokens; + } + if (typeof extra.errors !== 'undefined') { + program.errors = extra.errors; + } + if (extra.range || extra.loc) { + program.body = filterGroup(program.body); + } + } catch (e) { + throw e; + } finally { + unpatch(); + extra = {}; + } + + return program; + } + + // Sync with package.json and component.json. + exports.version = '1.1.0-dev-harmony'; + + exports.tokenize = tokenize; + + exports.parse = parse; + + // Deep copy. + exports.Syntax = (function () { + var name, types = {}; + + if (typeof Object.create === 'function') { + types = Object.create(null); + } + + for (name in Syntax) { + if (Syntax.hasOwnProperty(name)) { + types[name] = Syntax[name]; + } + } + + if (typeof Object.freeze === 'function') { + Object.freeze(types); + } + + return types; + }()); + +})); +/* vim: set sw=4 ts=4 et tw=80 : */ + +},{}],7:[function(require,module,exports){ +var Base62 = (function (my) { + my.chars = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "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"] + + my.encode = function(i){ + if (i === 0) {return '0'} + var s = '' + while (i > 0) { + s = this.chars[i % 62] + s + i = Math.floor(i/62) + } + return s + }; + my.decode = function(a,b,c,d){ + for ( + b = c = ( + a === (/\W|_|^$/.test(a += "") || a) + ) - 1; + d = a.charCodeAt(c++); + ) + b = b * 62 + d - [, 48, 29, 87][d >> 5]; + return b + }; + + return my; +}({})); + +module.exports = Base62 +},{}],8:[function(require,module,exports){ +/* + * Copyright 2009-2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE.txt or: + * http://opensource.org/licenses/BSD-3-Clause + */ +exports.SourceMapGenerator = require('./source-map/source-map-generator').SourceMapGenerator; +exports.SourceMapConsumer = require('./source-map/source-map-consumer').SourceMapConsumer; +exports.SourceNode = require('./source-map/source-node').SourceNode; + +},{"./source-map/source-map-consumer":13,"./source-map/source-map-generator":14,"./source-map/source-node":15}],9:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + /** + * A data structure which is a combination of an array and a set. Adding a new + * member is O(1), testing for membership is O(1), and finding the index of an + * element is O(1). Removing elements from the set is not supported. Only + * strings are supported for membership. + */ + function ArraySet() { + this._array = []; + this._set = {}; + } + + /** + * Static method for creating ArraySet instances from an existing array. + */ + ArraySet.fromArray = function ArraySet_fromArray(aArray) { + var set = new ArraySet(); + for (var i = 0, len = aArray.length; i < len; i++) { + set.add(aArray[i]); + } + return set; + }; + + /** + * Because behavior goes wacky when you set `__proto__` on `this._set`, we + * have to prefix all the strings in our set with an arbitrary character. + * + * See https://github.com/mozilla/source-map/pull/31 and + * https://github.com/mozilla/source-map/issues/30 + * + * @param String aStr + */ + ArraySet.prototype._toSetString = function ArraySet__toSetString (aStr) { + return "$" + aStr; + }; + + /** + * Add the given string to this set. + * + * @param String aStr + */ + ArraySet.prototype.add = function ArraySet_add(aStr) { + if (this.has(aStr)) { + // Already a member; nothing to do. + return; + } + var idx = this._array.length; + this._array.push(aStr); + this._set[this._toSetString(aStr)] = idx; + }; + + /** + * Is the given string a member of this set? + * + * @param String aStr + */ + ArraySet.prototype.has = function ArraySet_has(aStr) { + return Object.prototype.hasOwnProperty.call(this._set, + this._toSetString(aStr)); + }; + + /** + * What is the index of the given string in the array? + * + * @param String aStr + */ + ArraySet.prototype.indexOf = function ArraySet_indexOf(aStr) { + if (this.has(aStr)) { + return this._set[this._toSetString(aStr)]; + } + throw new Error('"' + aStr + '" is not in the set.'); + }; + + /** + * What is the element at the given index? + * + * @param Number aIdx + */ + ArraySet.prototype.at = function ArraySet_at(aIdx) { + if (aIdx >= 0 && aIdx < this._array.length) { + return this._array[aIdx]; + } + throw new Error('No element indexed by ' + aIdx); + }; + + /** + * Returns the array representation of this set (which has the proper indices + * indicated by indexOf). Note that this is a copy of the internal array used + * for storing the members so that no one can mess with internal state. + */ + ArraySet.prototype.toArray = function ArraySet_toArray() { + return this._array.slice(); + }; + + exports.ArraySet = ArraySet; + +}); + +},{"amdefine":17}],10:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + * + * Based on the Base 64 VLQ implementation in Closure Compiler: + * https://code.google.com/p/closure-compiler/source/browse/trunk/src/com/google/debugging/sourcemap/Base64VLQ.java + * + * Copyright 2011 The Closure Compiler Authors. All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var base64 = require('./base64'); + + // A single base 64 digit can contain 6 bits of data. For the base 64 variable + // length quantities we use in the source map spec, the first bit is the sign, + // the next four bits are the actual value, and the 6th bit is the + // continuation bit. The continuation bit tells us whether there are more + // digits in this value following this digit. + // + // Continuation + // | Sign + // | | + // V V + // 101011 + + var VLQ_BASE_SHIFT = 5; + + // binary: 100000 + var VLQ_BASE = 1 << VLQ_BASE_SHIFT; + + // binary: 011111 + var VLQ_BASE_MASK = VLQ_BASE - 1; + + // binary: 100000 + var VLQ_CONTINUATION_BIT = VLQ_BASE; + + /** + * Converts from a two-complement value to a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 1 becomes 2 (10 binary), -1 becomes 3 (11 binary) + * 2 becomes 4 (100 binary), -2 becomes 5 (101 binary) + */ + function toVLQSigned(aValue) { + return aValue < 0 + ? ((-aValue) << 1) + 1 + : (aValue << 1) + 0; + } + + /** + * Converts to a two-complement value from a value where the sign bit is + * is placed in the least significant bit. For example, as decimals: + * 2 (10 binary) becomes 1, 3 (11 binary) becomes -1 + * 4 (100 binary) becomes 2, 5 (101 binary) becomes -2 + */ + function fromVLQSigned(aValue) { + var isNegative = (aValue & 1) === 1; + var shifted = aValue >> 1; + return isNegative + ? -shifted + : shifted; + } + + /** + * Returns the base 64 VLQ encoded value. + */ + exports.encode = function base64VLQ_encode(aValue) { + var encoded = ""; + var digit; + + var vlq = toVLQSigned(aValue); + + do { + digit = vlq & VLQ_BASE_MASK; + vlq >>>= VLQ_BASE_SHIFT; + if (vlq > 0) { + // There are still more digits in this value, so we must make sure the + // continuation bit is marked. + digit |= VLQ_CONTINUATION_BIT; + } + encoded += base64.encode(digit); + } while (vlq > 0); + + return encoded; + }; + + /** + * Decodes the next base 64 VLQ value from the given string and returns the + * value and the rest of the string. + */ + exports.decode = function base64VLQ_decode(aStr) { + var i = 0; + var strLen = aStr.length; + var result = 0; + var shift = 0; + var continuation, digit; + + do { + if (i >= strLen) { + throw new Error("Expected more digits in base 64 VLQ value."); + } + digit = base64.decode(aStr.charAt(i++)); + continuation = !!(digit & VLQ_CONTINUATION_BIT); + digit &= VLQ_BASE_MASK; + result = result + (digit << shift); + shift += VLQ_BASE_SHIFT; + } while (continuation); + + return { + value: fromVLQSigned(result), + rest: aStr.slice(i) + }; + }; + +}); + +},{"./base64":11,"amdefine":17}],11:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var charToIntMap = {}; + var intToCharMap = {}; + + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' + .split('') + .forEach(function (ch, index) { + charToIntMap[ch] = index; + intToCharMap[index] = ch; + }); + + /** + * Encode an integer in the range of 0 to 63 to a single base 64 digit. + */ + exports.encode = function base64_encode(aNumber) { + if (aNumber in intToCharMap) { + return intToCharMap[aNumber]; + } + throw new TypeError("Must be between 0 and 63: " + aNumber); + }; + + /** + * Decode a single base 64 digit to an integer. + */ + exports.decode = function base64_decode(aChar) { + if (aChar in charToIntMap) { + return charToIntMap[aChar]; + } + throw new TypeError("Not a valid base 64 digit: " + aChar); + }; + +}); + +},{"amdefine":17}],12:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + /** + * Recursive implementation of binary search. + * + * @param aLow Indices here and lower do not contain the needle. + * @param aHigh Indices here and higher do not contain the needle. + * @param aNeedle The element being searched for. + * @param aHaystack The non-empty array being searched. + * @param aCompare Function which takes two elements and returns -1, 0, or 1. + */ + function recursiveSearch(aLow, aHigh, aNeedle, aHaystack, aCompare) { + // This function terminates when one of the following is true: + // + // 1. We find the exact element we are looking for. + // + // 2. We did not find the exact element, but we can return the next + // closest element that is less than that element. + // + // 3. We did not find the exact element, and there is no next-closest + // element which is less than the one we are searching for, so we + // return null. + var mid = Math.floor((aHigh - aLow) / 2) + aLow; + var cmp = aCompare(aNeedle, aHaystack[mid]); + if (cmp === 0) { + // Found the element we are looking for. + return aHaystack[mid]; + } + else if (cmp > 0) { + // aHaystack[mid] is greater than our needle. + if (aHigh - mid > 1) { + // The element is in the upper half. + return recursiveSearch(mid, aHigh, aNeedle, aHaystack, aCompare); + } + // We did not find an exact match, return the next closest one + // (termination case 2). + return aHaystack[mid]; + } + else { + // aHaystack[mid] is less than our needle. + if (mid - aLow > 1) { + // The element is in the lower half. + return recursiveSearch(aLow, mid, aNeedle, aHaystack, aCompare); + } + // The exact needle element was not found in this haystack. Determine if + // we are in termination case (2) or (3) and return the appropriate thing. + return aLow < 0 + ? null + : aHaystack[aLow]; + } + } + + /** + * This is an implementation of binary search which will always try and return + * the next lowest value checked if there is no exact hit. This is because + * mappings between original and generated line/col pairs are single points, + * and there is an implicit region between each of them, so a miss just means + * that you aren't on the very start of a region. + * + * @param aNeedle The element you are looking for. + * @param aHaystack The array that is being searched. + * @param aCompare A function which takes the needle and an element in the + * array and returns -1, 0, or 1 depending on whether the needle is less + * than, equal to, or greater than the element, respectively. + */ + exports.search = function search(aNeedle, aHaystack, aCompare) { + return aHaystack.length > 0 + ? recursiveSearch(-1, aHaystack.length, aNeedle, aHaystack, aCompare) + : null; + }; + +}); + +},{"amdefine":17}],13:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var util = require('./util'); + var binarySearch = require('./binary-search'); + var ArraySet = require('./array-set').ArraySet; + var base64VLQ = require('./base64-vlq'); + + /** + * A SourceMapConsumer instance represents a parsed source map which we can + * query for information about the original file positions by giving it a file + * position in the generated source. + * + * The only parameter is the raw source map (either as a JSON string, or + * already parsed to an object). According to the spec, source maps have the + * following attributes: + * + * - version: Which version of the source map spec this map is following. + * - sources: An array of URLs to the original source files. + * - names: An array of identifiers which can be referrenced by individual mappings. + * - sourceRoot: Optional. The URL root from which all sources are relative. + * - mappings: A string of base64 VLQs which contain the actual mappings. + * - file: The generated file this source map is associated with. + * + * Here is an example source map, taken from the source map spec[0]: + * + * { + * version : 3, + * file: "out.js", + * sourceRoot : "", + * sources: ["foo.js", "bar.js"], + * names: ["src", "maps", "are", "fun"], + * mappings: "AA,AB;;ABCDE;" + * } + * + * [0]: https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k/edit?pli=1# + */ + function SourceMapConsumer(aSourceMap) { + var sourceMap = aSourceMap; + if (typeof aSourceMap === 'string') { + sourceMap = JSON.parse(aSourceMap.replace(/^\)\]\}'/, '')); + } + + var version = util.getArg(sourceMap, 'version'); + var sources = util.getArg(sourceMap, 'sources'); + var names = util.getArg(sourceMap, 'names'); + var sourceRoot = util.getArg(sourceMap, 'sourceRoot', null); + var mappings = util.getArg(sourceMap, 'mappings'); + var file = util.getArg(sourceMap, 'file'); + + if (version !== this._version) { + throw new Error('Unsupported version: ' + version); + } + + this._names = ArraySet.fromArray(names); + this._sources = ArraySet.fromArray(sources); + this._sourceRoot = sourceRoot; + this.file = file; + + // `this._generatedMappings` and `this._originalMappings` hold the parsed + // mapping coordinates from the source map's "mappings" attribute. Each + // object in the array is of the form + // + // { + // generatedLine: The line number in the generated code, + // generatedColumn: The column number in the generated code, + // source: The path to the original source file that generated this + // chunk of code, + // originalLine: The line number in the original source that + // corresponds to this chunk of generated code, + // originalColumn: The column number in the original source that + // corresponds to this chunk of generated code, + // name: The name of the original symbol which generated this chunk of + // code. + // } + // + // All properties except for `generatedLine` and `generatedColumn` can be + // `null`. + // + // `this._generatedMappings` is ordered by the generated positions. + // + // `this._originalMappings` is ordered by the original positions. + this._generatedMappings = []; + this._originalMappings = []; + this._parseMappings(mappings, sourceRoot); + } + + /** + * The version of the source mapping spec that we are consuming. + */ + SourceMapConsumer.prototype._version = 3; + + /** + * The list of original sources. + */ + Object.defineProperty(SourceMapConsumer.prototype, 'sources', { + get: function () { + return this._sources.toArray().map(function (s) { + return this._sourceRoot ? util.join(this._sourceRoot, s) : s; + }, this); + } + }); + + /** + * Parse the mappings in a string in to a data structure which we can easily + * query (an ordered list in this._generatedMappings). + */ + SourceMapConsumer.prototype._parseMappings = + function SourceMapConsumer_parseMappings(aStr, aSourceRoot) { + var generatedLine = 1; + var previousGeneratedColumn = 0; + var previousOriginalLine = 0; + var previousOriginalColumn = 0; + var previousSource = 0; + var previousName = 0; + var mappingSeparator = /^[,;]/; + var str = aStr; + var mapping; + var temp; + + while (str.length > 0) { + if (str.charAt(0) === ';') { + generatedLine++; + str = str.slice(1); + previousGeneratedColumn = 0; + } + else if (str.charAt(0) === ',') { + str = str.slice(1); + } + else { + mapping = {}; + mapping.generatedLine = generatedLine; + + // Generated column. + temp = base64VLQ.decode(str); + mapping.generatedColumn = previousGeneratedColumn + temp.value; + previousGeneratedColumn = mapping.generatedColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original source. + temp = base64VLQ.decode(str); + if (aSourceRoot) { + mapping.source = util.join(aSourceRoot, this._sources.at(previousSource + temp.value)); + } + else { + mapping.source = this._sources.at(previousSource + temp.value); + } + previousSource += temp.value; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source, but no line and column'); + } + + // Original line. + temp = base64VLQ.decode(str); + mapping.originalLine = previousOriginalLine + temp.value; + previousOriginalLine = mapping.originalLine; + // Lines are stored 0-based + mapping.originalLine += 1; + str = temp.rest; + if (str.length === 0 || mappingSeparator.test(str.charAt(0))) { + throw new Error('Found a source and line, but no column'); + } + + // Original column. + temp = base64VLQ.decode(str); + mapping.originalColumn = previousOriginalColumn + temp.value; + previousOriginalColumn = mapping.originalColumn; + str = temp.rest; + + if (str.length > 0 && !mappingSeparator.test(str.charAt(0))) { + // Original name. + temp = base64VLQ.decode(str); + mapping.name = this._names.at(previousName + temp.value); + previousName += temp.value; + str = temp.rest; + } + } + + this._generatedMappings.push(mapping); + this._originalMappings.push(mapping); + } + } + + this._originalMappings.sort(this._compareOriginalPositions); + }; + + /** + * Comparator between two mappings where the original positions are compared. + */ + SourceMapConsumer.prototype._compareOriginalPositions = + function SourceMapConsumer_compareOriginalPositions(mappingA, mappingB) { + if (mappingA.source > mappingB.source) { + return 1; + } + else if (mappingA.source < mappingB.source) { + return -1; + } + else { + var cmp = mappingA.originalLine - mappingB.originalLine; + return cmp === 0 + ? mappingA.originalColumn - mappingB.originalColumn + : cmp; + } + }; + + /** + * Comparator between two mappings where the generated positions are compared. + */ + SourceMapConsumer.prototype._compareGeneratedPositions = + function SourceMapConsumer_compareGeneratedPositions(mappingA, mappingB) { + var cmp = mappingA.generatedLine - mappingB.generatedLine; + return cmp === 0 + ? mappingA.generatedColumn - mappingB.generatedColumn + : cmp; + }; + + /** + * Find the mapping that best matches the hypothetical "needle" mapping that + * we are searching for in the given "haystack" of mappings. + */ + SourceMapConsumer.prototype._findMapping = + function SourceMapConsumer_findMapping(aNeedle, aMappings, aLineName, + aColumnName, aComparator) { + // To return the position we are searching for, we must first find the + // mapping for the given position and then return the opposite position it + // points to. Because the mappings are sorted, we can use binary search to + // find the best mapping. + + if (aNeedle[aLineName] <= 0) { + throw new TypeError('Line must be greater than or equal to 1, got ' + + aNeedle[aLineName]); + } + if (aNeedle[aColumnName] < 0) { + throw new TypeError('Column must be greater than or equal to 0, got ' + + aNeedle[aColumnName]); + } + + return binarySearch.search(aNeedle, aMappings, aComparator); + }; + + /** + * Returns the original source, line, and column information for the generated + * source's line and column positions provided. The only argument is an object + * with the following properties: + * + * - line: The line number in the generated source. + * - column: The column number in the generated source. + * + * and an object is returned with the following properties: + * + * - source: The original source file, or null. + * - line: The line number in the original source, or null. + * - column: The column number in the original source, or null. + * - name: The original identifier, or null. + */ + SourceMapConsumer.prototype.originalPositionFor = + function SourceMapConsumer_originalPositionFor(aArgs) { + var needle = { + generatedLine: util.getArg(aArgs, 'line'), + generatedColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._generatedMappings, + "generatedLine", + "generatedColumn", + this._compareGeneratedPositions) + + if (mapping) { + return { + source: util.getArg(mapping, 'source', null), + line: util.getArg(mapping, 'originalLine', null), + column: util.getArg(mapping, 'originalColumn', null), + name: util.getArg(mapping, 'name', null) + }; + } + + return { + source: null, + line: null, + column: null, + name: null + }; + }; + + /** + * Returns the generated line and column information for the original source, + * line, and column positions provided. The only argument is an object with + * the following properties: + * + * - source: The filename of the original source. + * - line: The line number in the original source. + * - column: The column number in the original source. + * + * and an object is returned with the following properties: + * + * - line: The line number in the generated source, or null. + * - column: The column number in the generated source, or null. + */ + SourceMapConsumer.prototype.generatedPositionFor = + function SourceMapConsumer_generatedPositionFor(aArgs) { + var needle = { + source: util.getArg(aArgs, 'source'), + originalLine: util.getArg(aArgs, 'line'), + originalColumn: util.getArg(aArgs, 'column') + }; + + var mapping = this._findMapping(needle, + this._originalMappings, + "originalLine", + "originalColumn", + this._compareOriginalPositions) + + if (mapping) { + return { + line: util.getArg(mapping, 'generatedLine', null), + column: util.getArg(mapping, 'generatedColumn', null) + }; + } + + return { + line: null, + column: null + }; + }; + + SourceMapConsumer.GENERATED_ORDER = 1; + SourceMapConsumer.ORIGINAL_ORDER = 2; + + /** + * Iterate over each mapping between an original source/line/column and a + * generated line/column in this source map. + * + * @param Function aCallback + * The function that is called with each mapping. This function should + * not mutate the mapping. + * @param Object aContext + * Optional. If specified, this object will be the value of `this` every + * time that `aCallback` is called. + * @param aOrder + * Either `SourceMapConsumer.GENERATED_ORDER` or + * `SourceMapConsumer.ORIGINAL_ORDER`. Specifies whether you want to + * iterate over the mappings sorted by the generated file's line/column + * order or the original's source/line/column order, respectively. Defaults to + * `SourceMapConsumer.GENERATED_ORDER`. + */ + SourceMapConsumer.prototype.eachMapping = + function SourceMapConsumer_eachMapping(aCallback, aContext, aOrder) { + var context = aContext || null; + var order = aOrder || SourceMapConsumer.GENERATED_ORDER; + + var mappings; + switch (order) { + case SourceMapConsumer.GENERATED_ORDER: + mappings = this._generatedMappings; + break; + case SourceMapConsumer.ORIGINAL_ORDER: + mappings = this._originalMappings; + break; + default: + throw new Error("Unknown order of iteration."); + } + + mappings.forEach(aCallback, context); + }; + + exports.SourceMapConsumer = SourceMapConsumer; + +}); + +},{"./array-set":9,"./base64-vlq":10,"./binary-search":12,"./util":16,"amdefine":17}],14:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var base64VLQ = require('./base64-vlq'); + var util = require('./util'); + var ArraySet = require('./array-set').ArraySet; + + /** + * An instance of the SourceMapGenerator represents a source map which is + * being built incrementally. To create a new one, you must pass an object + * with the following properties: + * + * - file: The filename of the generated source. + * - sourceRoot: An optional root for all URLs in this source map. + */ + function SourceMapGenerator(aArgs) { + this._file = util.getArg(aArgs, 'file'); + this._sourceRoot = util.getArg(aArgs, 'sourceRoot', null); + this._sources = new ArraySet(); + this._names = new ArraySet(); + this._mappings = []; + } + + SourceMapGenerator.prototype._version = 3; + + /** + * Add a single mapping from original source line and column to the generated + * source's line and column for this source map being created. The mapping + * object should have the following properties: + * + * - generated: An object with the generated line and column positions. + * - original: An object with the original line and column positions. + * - source: The original source file (relative to the sourceRoot). + * - name: An optional original token name for this mapping. + */ + SourceMapGenerator.prototype.addMapping = + function SourceMapGenerator_addMapping(aArgs) { + var generated = util.getArg(aArgs, 'generated'); + var original = util.getArg(aArgs, 'original', null); + var source = util.getArg(aArgs, 'source', null); + var name = util.getArg(aArgs, 'name', null); + + this._validateMapping(generated, original, source, name); + + if (source && !this._sources.has(source)) { + this._sources.add(source); + } + + if (name && !this._names.has(name)) { + this._names.add(name); + } + + this._mappings.push({ + generated: generated, + original: original, + source: source, + name: name + }); + }; + + /** + * A mapping can have one of the three levels of data: + * + * 1. Just the generated position. + * 2. The Generated position, original position, and original source. + * 3. Generated and original position, original source, as well as a name + * token. + * + * To maintain consistency, we validate that any new mapping being added falls + * in to one of these categories. + */ + SourceMapGenerator.prototype._validateMapping = + function SourceMapGenerator_validateMapping(aGenerated, aOriginal, aSource, + aName) { + if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aGenerated.line > 0 && aGenerated.column >= 0 + && !aOriginal && !aSource && !aName) { + // Case 1. + return; + } + else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated + && aOriginal && 'line' in aOriginal && 'column' in aOriginal + && aGenerated.line > 0 && aGenerated.column >= 0 + && aOriginal.line > 0 && aOriginal.column >= 0 + && aSource) { + // Cases 2 and 3. + return; + } + else { + throw new Error('Invalid mapping.'); + } + }; + + /** + * Serialize the accumulated mappings in to the stream of base 64 VLQs + * specified by the source map format. + */ + SourceMapGenerator.prototype._serializeMappings = + function SourceMapGenerator_serializeMappings() { + var previousGeneratedColumn = 0; + var previousGeneratedLine = 1; + var previousOriginalColumn = 0; + var previousOriginalLine = 0; + var previousName = 0; + var previousSource = 0; + var result = ''; + var mapping; + + // The mappings must be guarenteed to be in sorted order before we start + // serializing them or else the generated line numbers (which are defined + // via the ';' separators) will be all messed up. Note: it might be more + // performant to maintain the sorting as we insert them, rather than as we + // serialize them, but the big O is the same either way. + this._mappings.sort(function (mappingA, mappingB) { + var cmp = mappingA.generated.line - mappingB.generated.line; + return cmp === 0 + ? mappingA.generated.column - mappingB.generated.column + : cmp; + }); + + for (var i = 0, len = this._mappings.length; i < len; i++) { + mapping = this._mappings[i]; + + if (mapping.generated.line !== previousGeneratedLine) { + previousGeneratedColumn = 0; + while (mapping.generated.line !== previousGeneratedLine) { + result += ';'; + previousGeneratedLine++; + } + } + else { + if (i > 0) { + result += ','; + } + } + + result += base64VLQ.encode(mapping.generated.column + - previousGeneratedColumn); + previousGeneratedColumn = mapping.generated.column; + + if (mapping.source && mapping.original) { + result += base64VLQ.encode(this._sources.indexOf(mapping.source) + - previousSource); + previousSource = this._sources.indexOf(mapping.source); + + // lines are stored 0-based in SourceMap spec version 3 + result += base64VLQ.encode(mapping.original.line - 1 + - previousOriginalLine); + previousOriginalLine = mapping.original.line - 1; + + result += base64VLQ.encode(mapping.original.column + - previousOriginalColumn); + previousOriginalColumn = mapping.original.column; + + if (mapping.name) { + result += base64VLQ.encode(this._names.indexOf(mapping.name) + - previousName); + previousName = this._names.indexOf(mapping.name); + } + } + } + + return result; + }; + + /** + * Externalize the source map. + */ + SourceMapGenerator.prototype.toJSON = + function SourceMapGenerator_toJSON() { + var map = { + version: this._version, + file: this._file, + sources: this._sources.toArray(), + names: this._names.toArray(), + mappings: this._serializeMappings() + }; + if (this._sourceRoot) { + map.sourceRoot = this._sourceRoot; + } + return map; + }; + + /** + * Render the source map being generated to a string. + */ + SourceMapGenerator.prototype.toString = + function SourceMapGenerator_toString() { + return JSON.stringify(this); + }; + + exports.SourceMapGenerator = SourceMapGenerator; + +}); + +},{"./array-set":9,"./base64-vlq":10,"./util":16,"amdefine":17}],15:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + var SourceMapGenerator = require('./source-map-generator').SourceMapGenerator; + + /** + * SourceNodes provide a way to abstract over interpolating/concatenating + * snippets of generated JavaScript source code while maintaining the line and + * column information associated with the original source code. + * + * @param aLine The original line number. + * @param aColumn The original column number. + * @param aSource The original source's filename. + * @param aChunks Optional. An array of strings which are snippets of + * generated JS, or other SourceNodes. + */ + function SourceNode(aLine, aColumn, aSource, aChunks) { + this.children = []; + this.line = aLine; + this.column = aColumn; + this.source = aSource; + if (aChunks != null) this.add(aChunks); + } + + /** + * Add a chunk of generated JS to this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.add = function SourceNode_add(aChunk) { + if (Array.isArray(aChunk)) { + aChunk.forEach(function (chunk) { + this.add(chunk); + }, this); + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + if (aChunk) { + this.children.push(aChunk); + } + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Add a chunk of generated JS to the beginning of this source node. + * + * @param aChunk A string snippet of generated JS code, another instance of + * SourceNode, or an array where each member is one of those things. + */ + SourceNode.prototype.prepend = function SourceNode_prepend(aChunk) { + if (Array.isArray(aChunk)) { + for (var i = aChunk.length-1; i >= 0; i--) { + this.prepend(aChunk[i]); + } + } + else if (aChunk instanceof SourceNode || typeof aChunk === "string") { + this.children.unshift(aChunk); + } + else { + throw new TypeError( + "Expected a SourceNode, string, or an array of SourceNodes and strings. Got " + aChunk + ); + } + return this; + }; + + /** + * Walk over the tree of JS snippets in this node and its children. The + * walking function is called once for each snippet of JS and is passed that + * snippet and the its original associated source's line/column location. + * + * @param aFn The traversal function. + */ + SourceNode.prototype.walk = function SourceNode_walk(aFn) { + this.children.forEach(function (chunk) { + if (chunk instanceof SourceNode) { + chunk.walk(aFn); + } + else { + if (chunk !== '') { + aFn(chunk, { source: this.source, line: this.line, column: this.column }); + } + } + }, this); + }; + + /** + * Like `String.prototype.join` except for SourceNodes. Inserts `aStr` between + * each of `this.children`. + * + * @param aSep The separator. + */ + SourceNode.prototype.join = function SourceNode_join(aSep) { + var newChildren; + var i; + var len = this.children.length + if (len > 0) { + newChildren = []; + for (i = 0; i < len-1; i++) { + newChildren.push(this.children[i]); + newChildren.push(aSep); + } + newChildren.push(this.children[i]); + this.children = newChildren; + } + return this; + }; + + /** + * Call String.prototype.replace on the very right-most source snippet. Useful + * for trimming whitespace from the end of a source node, etc. + * + * @param aPattern The pattern to replace. + * @param aReplacement The thing to replace the pattern with. + */ + SourceNode.prototype.replaceRight = function SourceNode_replaceRight(aPattern, aReplacement) { + var lastChild = this.children[this.children.length - 1]; + if (lastChild instanceof SourceNode) { + lastChild.replaceRight(aPattern, aReplacement); + } + else if (typeof lastChild === 'string') { + this.children[this.children.length - 1] = lastChild.replace(aPattern, aReplacement); + } + else { + this.children.push(''.replace(aPattern, aReplacement)); + } + return this; + }; + + /** + * Return the string representation of this source node. Walks over the tree + * and concatenates all the various snippets together to one string. + */ + SourceNode.prototype.toString = function SourceNode_toString() { + var str = ""; + this.walk(function (chunk) { + str += chunk; + }); + return str; + }; + + /** + * Returns the string representation of this source node along with a source + * map. + */ + SourceNode.prototype.toStringWithSourceMap = function SourceNode_toStringWithSourceMap(aArgs) { + var generated = { + code: "", + line: 1, + column: 0 + }; + var map = new SourceMapGenerator(aArgs); + this.walk(function (chunk, original) { + generated.code += chunk; + if (original.source != null + && original.line != null + && original.column != null) { + map.addMapping({ + source: original.source, + original: { + line: original.line, + column: original.column + }, + generated: { + line: generated.line, + column: generated.column + } + }); + } + chunk.split('').forEach(function (char) { + if (char === '\n') { + generated.line++; + generated.column = 0; + } else { + generated.column++; + } + }); + }); + + return { code: generated.code, map: map }; + }; + + exports.SourceNode = SourceNode; + +}); + +},{"./source-map-generator":14,"amdefine":17}],16:[function(require,module,exports){ +/* -*- Mode: js; js-indent-level: 2; -*- */ +/* + * Copyright 2011 Mozilla Foundation and contributors + * Licensed under the New BSD license. See LICENSE or: + * http://opensource.org/licenses/BSD-3-Clause + */ +if (typeof define !== 'function') { + var define = require('amdefine')(module); +} +define(function (require, exports, module) { + + /** + * This is a helper function for getting values from parameter/options + * objects. + * + * @param args The object we are extracting values from + * @param name The name of the property we are getting. + * @param defaultValue An optional value to return if the property is missing + * from the object. If this is not specified and the property is missing, an + * error will be thrown. + */ + function getArg(aArgs, aName, aDefaultValue) { + if (aName in aArgs) { + return aArgs[aName]; + } else if (arguments.length === 3) { + return aDefaultValue; + } else { + throw new Error('"' + aName + '" is a required argument.'); + } + } + exports.getArg = getArg; + + function join(aRoot, aPath) { + return aPath.charAt(0) === '/' + ? aPath + : aRoot.replace(/\/*$/, '') + '/' + aPath; + } + exports.join = join; + +}); + +},{"amdefine":17}],17:[function(require,module,exports){ +var process=require("__browserify_process"),__filename="/../node_modules/jstransform/node_modules/source-map/node_modules/amdefine/amdefine.js";/** vim: et:ts=4:sw=4:sts=4 + * @license amdefine 0.1.0 Copyright (c) 2011, The Dojo Foundation All Rights Reserved. + * Available via the MIT or new BSD license. + * see: http://github.com/jrburke/amdefine for details + */ + +/*jslint node: true */ +/*global module, process */ +'use strict'; + +/** + * Creates a define for node. + * @param {Object} module the "module" object that is defined by Node for the + * current module. + * @param {Function} [requireFn]. Node's require function for the current module. + * It only needs to be passed in Node versions before 0.5, when module.require + * did not exist. + * @returns {Function} a define function that is usable for the current node + * module. + */ +function amdefine(module, requireFn) { + 'use strict'; + var defineCache = {}, + loaderCache = {}, + alreadyCalled = false, + path = require('path'), + makeRequire, stringRequire; + + /** + * Trims the . and .. from an array of path segments. + * It will keep a leading path segment if a .. will become + * the first path segment, to help with module name lookups, + * which act like paths, but can be remapped. But the end result, + * all paths that use this function should look normalized. + * NOTE: this method MODIFIES the input array. + * @param {Array} ary the array of path segments. + */ + function trimDots(ary) { + var i, part; + for (i = 0; ary[i]; i+= 1) { + part = ary[i]; + if (part === '.') { + ary.splice(i, 1); + i -= 1; + } else if (part === '..') { + if (i === 1 && (ary[2] === '..' || ary[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) { + ary.splice(i - 1, 2); + i -= 2; + } + } + } + } + + function normalize(name, baseName) { + var baseParts; + + //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) { + baseParts = baseName.split('/'); + baseParts = baseParts.slice(0, baseParts.length - 1); + baseParts = baseParts.concat(name.split('/')); + trimDots(baseParts); + name = baseParts.join('/'); + } + } + + return name; + } + + /** + * Create the normalize() function passed to a loader plugin's + * normalize method. + */ + function makeNormalize(relName) { + return function (name) { + return normalize(name, relName); + }; + } + + function makeLoad(id) { + function load(value) { + loaderCache[id] = value; + } + + load.fromText = function (id, text) { + //This one is difficult because the text can/probably uses + //define, and any relative paths and requires should be relative + //to that id was it would be found on disk. But this would require + //bootstrapping a module/require fairly deeply from node core. + //Not sure how best to go about that yet. + throw new Error('amdefine does not implement load.fromText'); + }; + + return load; + } + + makeRequire = function (systemRequire, exports, module, relId) { + function amdRequire(deps, callback) { + if (typeof deps === 'string') { + //Synchronous, single module require('') + return stringRequire(systemRequire, exports, module, deps, relId); + } else { + //Array of dependencies with a callback. + + //Convert the dependencies to modules. + deps = deps.map(function (depName) { + return stringRequire(systemRequire, exports, module, depName, relId); + }); + + //Wait for next tick to call back the require call. + process.nextTick(function () { + callback.apply(null, deps); + }); + } + } + + amdRequire.toUrl = function (filePath) { + if (filePath.indexOf('.') === 0) { + return normalize(filePath, path.dirname(module.filename)); + } else { + return filePath; + } + }; + + return amdRequire; + }; + + //Favor explicit value, passed in if the module wants to support Node 0.4. + requireFn = requireFn || function req() { + return module.require.apply(module, arguments); + }; + + function runFactory(id, deps, factory) { + var r, e, m, result; + + if (id) { + e = loaderCache[id] = {}; + m = { + id: id, + uri: __filename, + exports: e + }; + r = makeRequire(requireFn, e, m, id); + } else { + //Only support one define call per file + if (alreadyCalled) { + throw new Error('amdefine with no module ID cannot be called more than once per file.'); + } + alreadyCalled = true; + + //Use the real variables from node + //Use module.exports for exports, since + //the exports in here is amdefine exports. + e = module.exports; + m = module; + r = makeRequire(requireFn, e, m, module.id); + } + + //If there are dependencies, they are strings, so need + //to convert them to dependency values. + if (deps) { + deps = deps.map(function (depName) { + return r(depName); + }); + } + + //Call the factory with the right dependencies. + if (typeof factory === 'function') { + result = factory.apply(m.exports, deps); + } else { + result = factory; + } + + if (result !== undefined) { + m.exports = result; + if (id) { + loaderCache[id] = m.exports; + } + } + } + + stringRequire = function (systemRequire, exports, module, id, relId) { + //Split the ID by a ! so that + var index = id.indexOf('!'), + originalId = id, + prefix, plugin; + + if (index === -1) { + id = normalize(id, relId); + + //Straight module lookup. If it is one of the special dependencies, + //deal with it, otherwise, delegate to node. + if (id === 'require') { + return makeRequire(systemRequire, exports, module, relId); + } else if (id === 'exports') { + return exports; + } else if (id === 'module') { + return module; + } else if (loaderCache.hasOwnProperty(id)) { + return loaderCache[id]; + } else if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } else { + if(systemRequire) { + return systemRequire(originalId); + } else { + throw new Error('No module with ID: ' + id); + } + } + } else { + //There is a plugin in play. + prefix = id.substring(0, index); + id = id.substring(index + 1, id.length); + + plugin = stringRequire(systemRequire, exports, module, prefix, relId); + + if (plugin.normalize) { + id = plugin.normalize(id, makeNormalize(relId)); + } else { + //Normalize the ID normally. + id = normalize(id, relId); + } + + if (loaderCache[id]) { + return loaderCache[id]; + } else { + plugin.load(id, makeRequire(systemRequire, exports, module, relId), makeLoad(id), {}); + + return loaderCache[id]; + } + } + }; + + //Create a define function specific to the module asking for amdefine. + function define(id, deps, factory) { + if (Array.isArray(id)) { + factory = deps; + deps = id; + id = undefined; + } else if (typeof id !== 'string') { + factory = id; + id = deps = undefined; + } + + if (deps && !Array.isArray(deps)) { + factory = deps; + deps = undefined; + } + + if (!deps) { + deps = ['require', 'exports', 'module']; + } + + //Set up properties for this module. If an ID, then use + //internal cache. If no ID, then use the external variables + //for this node module. + if (id) { + //Put the module in deep freeze until there is a + //require call for it. + defineCache[id] = [id, deps, factory]; + } else { + runFactory(id, deps, factory); + } + } + + //define.require, which has access to all the values in the + //cache. Useful for AMD modules that all have IDs in the file, + //but need to finally export a value to node based on one of those + //IDs. + define.require = function (id) { + if (loaderCache[id]) { + return loaderCache[id]; + } + + if (defineCache[id]) { + runFactory.apply(null, defineCache[id]); + return loaderCache[id]; + } + }; + + define.amd = {}; + + return define; +} + +module.exports = amdefine; + +},{"__browserify_process":5,"path":2}],18:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +var docblockRe = /^\s*(\/\*\*(.|\r?\n)*?\*\/)/; +var ltrimRe = /^\s*/; +/** + * @param {String} contents + * @return {String} + */ +function extract(contents) { + var match = contents.match(docblockRe); + if (match) { + return match[0].replace(ltrimRe, '') || ''; + } + return ''; +} + + +var commentStartRe = /^\/\*\*?/; +var commentEndRe = /\*\/$/; +var wsRe = /[\t ]+/g; +var stringStartRe = /(\r?\n|^) *\*/g; +var multilineRe = /(?:^|\r?\n) *(@[^\r\n]*?) *\r?\n *([^@\r\n\s][^@\r\n]+?) *\r?\n/g; +var propertyRe = /(?:^|\r?\n) *@(\S+) *([^\r\n]*)/g; + +/** + * @param {String} contents + * @return {Array} + */ +function parse(docblock) { + docblock = docblock + .replace(commentStartRe, '') + .replace(commentEndRe, '') + .replace(wsRe, ' ') + .replace(stringStartRe, '$1'); + + // Normalize multi-line directives + var prev = ''; + while (prev != docblock) { + prev = docblock; + docblock = docblock.replace(multilineRe, "\n$1 $2\n"); + } + docblock = docblock.trim(); + + var result = []; + var match; + while (match = propertyRe.exec(docblock)) { + result.push([match[1], match[2]]); + } + + return result; +} + +/** + * Same as parse but returns an object of prop: value instead of array of paris + * If a property appers more than once the last one will be returned + * + * @param {String} contents + * @return {Object} + */ +function parseAsObject(docblock) { + var pairs = parse(docblock); + var result = {}; + for (var i = 0; i < pairs.length; i++) { + result[pairs[i][0]] = pairs[i][1]; + } + return result; +} + + +exports.extract = extract; +exports.parse = parse; +exports.parseAsObject = parseAsObject; + +},{}],19:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/*jslint node: true*/ +"use strict"; + +/** + * Syntax transfomer for javascript. Takes the source in, spits the source + * out. + * + * Parses input source with esprima, applies the given list of visitors to the + * AST tree, and returns the resulting output. + */ +var esprima = require('esprima-fb'); + +var createState = require('./utils').createState; +var catchup = require('./utils').catchup; +var updateState = require('./utils').updateState; +var analyzeAndTraverse = require('./utils').analyzeAndTraverse; + +var Syntax = esprima.Syntax; + +/** + * @param {object} node + * @param {object} parentNode + * @return {boolean} + */ +function _nodeIsClosureScopeBoundary(node, parentNode) { + if (node.type === Syntax.Program) { + return true; + } + + var parentIsFunction = + parentNode.type === Syntax.FunctionDeclaration + || parentNode.type === Syntax.FunctionExpression; + + return node.type === Syntax.BlockStatement && parentIsFunction; +} + +function _nodeIsBlockScopeBoundary(node, parentNode) { + if (node.type === Syntax.Program) { + return false; + } + + return node.type === Syntax.BlockStatement + && parentNode.type === Syntax.CatchClause; +} + +/** + * @param {object} node + * @param {function} visitor + * @param {array} path + * @param {object} state + */ +function traverse(node, path, state) { + // Create a scope stack entry if this is the first node we've encountered in + // its local scope + var parentNode = path[0]; + if (!Array.isArray(node) && state.localScope.parentNode !== parentNode) { + if (_nodeIsClosureScopeBoundary(node, parentNode)) { + var scopeIsStrict = + state.scopeIsStrict + || node.body.length > 0 + && node.body[0].type === Syntax.ExpressionStatement + && node.body[0].expression.type === Syntax.Literal + && node.body[0].expression.value === 'use strict'; + + if (node.type === Syntax.Program) { + state = updateState(state, { + scopeIsStrict: scopeIsStrict + }); + } else { + state = updateState(state, { + localScope: { + parentNode: parentNode, + parentScope: state.localScope, + identifiers: {} + }, + scopeIsStrict: scopeIsStrict + }); + + // All functions have an implicit 'arguments' object in scope + state.localScope.identifiers['arguments'] = true; + + // Include function arg identifiers in the scope boundaries of the + // function + if (parentNode.params.length > 0) { + var param; + for (var i = 0; i < parentNode.params.length; i++) { + param = parentNode.params[i]; + if (param.type === Syntax.Identifier) { + state.localScope.identifiers[param.name] = true; + } + } + } + + // Named FunctionExpressions scope their name within the body block of + // themselves only + if (parentNode.type === Syntax.FunctionExpression && parentNode.id) { + state.localScope.identifiers[parentNode.id.name] = true; + } + } + + // Traverse and find all local identifiers in this closure first to + // account for function/variable declaration hoisting + collectClosureIdentsAndTraverse(node, path, state); + } + + if (_nodeIsBlockScopeBoundary(node, parentNode)) { + state = updateState(state, { + localScope: { + parentNode: parentNode, + parentScope: state.localScope, + identifiers: {} + } + }); + + if (parentNode.type === Syntax.CatchClause) { + state.localScope.identifiers[parentNode.param.name] = true; + } + collectBlockIdentsAndTraverse(node, path, state); + } + } + + // Only catchup() before and after traversing a child node + function traverser(node, path, state) { + node.range && catchup(node.range[0], state); + traverse(node, path, state); + node.range && catchup(node.range[1], state); + } + + analyzeAndTraverse(walker, traverser, node, path, state); +} + +function collectClosureIdentsAndTraverse(node, path, state) { + analyzeAndTraverse( + visitLocalClosureIdentifiers, + collectClosureIdentsAndTraverse, + node, + path, + state + ); +} + +function collectBlockIdentsAndTraverse(node, path, state) { + analyzeAndTraverse( + visitLocalBlockIdentifiers, + collectBlockIdentsAndTraverse, + node, + path, + state + ); +} + +function visitLocalClosureIdentifiers(node, path, state) { + var identifiers = state.localScope.identifiers; + switch (node.type) { + case Syntax.FunctionExpression: + // Function expressions don't get their names (if there is one) added to + // the closure scope they're defined in + return false; + case Syntax.ClassDeclaration: + case Syntax.ClassExpression: + case Syntax.FunctionDeclaration: + if (node.id) { + identifiers[node.id.name] = true; + } + return false; + case Syntax.VariableDeclarator: + if (path[0].kind === 'var') { + identifiers[node.id.name] = true; + } + break; + } +} + +function visitLocalBlockIdentifiers(node, path, state) { + // TODO: Support 'let' here...maybe...one day...or something... + if (node.type === Syntax.CatchClause) { + return false; + } +} + +function walker(node, path, state) { + var visitors = state.g.visitors; + for (var i = 0; i < visitors.length; i++) { + if (visitors[i].test(node, path, state)) { + return visitors[i](traverse, node, path, state); + } + } +} + +/** + * Applies all available transformations to the source + * @param {array} visitors + * @param {string} source + * @param {?object} options + * @return {object} + */ +function transform(visitors, source, options) { + options = options || {}; + + var ast; + try { + ast = esprima.parse(source, { + comment: true, + loc: true, + range: true + }); + } catch (e) { + e.message = 'Parse Error: ' + e.message; + throw e; + } + var state = createState(source, ast, options); + state.g.visitors = visitors; + + if (options.sourceMap) { + var SourceMapGenerator = require('source-map').SourceMapGenerator; + state.g.sourceMap = new SourceMapGenerator({file: 'transformed.js'}); + } + + traverse(ast, [], state); + catchup(source.length, state); + + var ret = {code: state.g.buffer}; + if (options.sourceMap) { + ret.sourceMap = state.g.sourceMap; + ret.sourceMapFilename = options.filename || 'source.js'; + } + return ret; +} + +exports.transform = transform; + +},{"./utils":20,"esprima-fb":6,"source-map":8}],20:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +/*jslint node: true*/ + +/** + * A `state` object represents the state of the parser. It has "local" and + * "global" parts. Global contains parser position, source, etc. Local contains + * scope based properties like current class name. State should contain all the + * info required for transformation. It's the only mandatory object that is + * being passed to every function in transform chain. + * + * @param {string} source + * @param {object} transformOptions + * @return {object} + */ +function createState(source, rootNode, transformOptions) { + return { + /** + * A tree representing the current local scope (and its lexical scope chain) + * Useful for tracking identifiers from parent scopes, etc. + * @type {Object} + */ + localScope: { + parentNode: rootNode, + parentScope: null, + identifiers: {} + }, + /** + * The name (and, if applicable, expression) of the super class + * @type {Object} + */ + superClass: null, + /** + * The namespace to use when munging identifiers + * @type {String} + */ + mungeNamespace: '', + /** + * Ref to the node for the FunctionExpression of the enclosing + * MethodDefinition + * @type {Object} + */ + methodFuncNode: null, + /** + * Name of the enclosing class + * @type {String} + */ + className: null, + /** + * Whether we're currently within a `strict` scope + * @type {Bool} + */ + scopeIsStrict: null, + /** + * Global state (not affected by updateState) + * @type {Object} + */ + g: { + /** + * A set of general options that transformations can consider while doing + * a transformation: + * + * - minify + * Specifies that transformation steps should do their best to minify + * the output source when possible. This is useful for places where + * minification optimizations are possible with higher-level context + * info than what jsxmin can provide. + * + * For example, the ES6 class transform will minify munged private + * variables if this flag is set. + */ + opts: transformOptions, + /** + * Current position in the source code + * @type {Number} + */ + position: 0, + /** + * Buffer containing the result + * @type {String} + */ + buffer: '', + /** + * Indentation offset (only negative offset is supported now) + * @type {Number} + */ + indentBy: 0, + /** + * Source that is being transformed + * @type {String} + */ + source: source, + + /** + * Cached parsed docblock (see getDocblock) + * @type {object} + */ + docblock: null, + + /** + * Whether the thing was used + * @type {Boolean} + */ + tagNamespaceUsed: false, + + /** + * If using bolt xjs transformation + * @type {Boolean} + */ + isBolt: undefined, + + /** + * Whether to record source map (expensive) or not + * @type {SourceMapGenerator|null} + */ + sourceMap: null, + + /** + * Filename of the file being processed. Will be returned as a source + * attribute in the source map + */ + sourceMapFilename: 'source.js', + + /** + * Only when source map is used: last line in the source for which + * source map was generated + * @type {Number} + */ + sourceLine: 1, + + /** + * Only when source map is used: last line in the buffer for which + * source map was generated + * @type {Number} + */ + bufferLine: 1, + + /** + * The top-level Program AST for the original file. + */ + originalProgramAST: null, + + sourceColumn: 0, + bufferColumn: 0 + } + }; +} + +/** + * Updates a copy of a given state with "update" and returns an updated state. + * + * @param {object} state + * @param {object} update + * @return {object} + */ +function updateState(state, update) { + var ret = Object.create(state); + Object.keys(update).forEach(function(updatedKey) { + ret[updatedKey] = update[updatedKey]; + }); + return ret; +} + +/** + * Given a state fill the resulting buffer from the original source up to + * the end + * + * @param {number} end + * @param {object} state + * @param {?function} contentTransformer Optional callback to transform newly + * added content. + */ +function catchup(end, state, contentTransformer) { + if (end < state.g.position) { + // cannot move backwards + return; + } + var source = state.g.source.substring(state.g.position, end); + var transformed = updateIndent(source, state); + if (state.g.sourceMap && transformed) { + // record where we are + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); + + // record line breaks in transformed source + var sourceLines = source.split('\n'); + var transformedLines = transformed.split('\n'); + // Add line break mappings between last known mapping and the end of the + // added piece. So for the code piece + // (foo, bar); + // > var x = 2; + // > var b = 3; + // var c = + // only add lines marked with ">": 2, 3. + for (var i = 1; i < sourceLines.length - 1; i++) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: 0 }, + original: { line: state.g.sourceLine, column: 0 }, + source: state.g.sourceMapFilename + }); + state.g.sourceLine++; + state.g.bufferLine++; + } + // offset for the last piece + if (sourceLines.length > 1) { + state.g.sourceLine++; + state.g.bufferLine++; + state.g.sourceColumn = 0; + state.g.bufferColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; + } + state.g.buffer += + contentTransformer ? contentTransformer(transformed) : transformed; + state.g.position = end; +} + +/** + * Removes all non-whitespace characters + */ +var reNonWhite = /(\S)/g; +function stripNonWhite(value) { + return value.replace(reNonWhite, function() { + return ''; + }); +} + +/** + * Catches up as `catchup` but removes all non-whitespace characters. + */ +function catchupWhiteSpace(end, state) { + catchup(end, state, stripNonWhite); +} + +/** + * Removes all non-newline characters + */ +var reNonNewline = /[^\n]/g; +function stripNonNewline(value) { + return value.replace(reNonNewline, function() { + return ''; + }); +} + +/** + * Catches up as `catchup` but removes all non-newline characters. + * + * Equivalent to appending as many newlines as there are in the original source + * between the current position and `end`. + */ +function catchupNewlines(end, state) { + catchup(end, state, stripNonNewline); +} + + +/** + * Same as catchup but does not touch the buffer + * + * @param {number} end + * @param {object} state + */ +function move(end, state) { + // move the internal cursors + if (state.g.sourceMap) { + if (end < state.g.position) { + state.g.position = 0; + state.g.sourceLine = 1; + state.g.sourceColumn = 0; + } + + var source = state.g.source.substring(state.g.position, end); + var sourceLines = source.split('\n'); + if (sourceLines.length > 1) { + state.g.sourceLine += sourceLines.length - 1; + state.g.sourceColumn = 0; + } + state.g.sourceColumn += sourceLines[sourceLines.length - 1].length; + } + state.g.position = end; +} + +/** + * Appends a string of text to the buffer + * + * @param {string} str + * @param {object} state + */ +function append(str, state) { + if (state.g.sourceMap && str) { + state.g.sourceMap.addMapping({ + generated: { line: state.g.bufferLine, column: state.g.bufferColumn }, + original: { line: state.g.sourceLine, column: state.g.sourceColumn }, + source: state.g.sourceMapFilename + }); + var transformedLines = str.split('\n'); + if (transformedLines.length > 1) { + state.g.bufferLine += transformedLines.length - 1; + state.g.bufferColumn = 0; + } + state.g.bufferColumn += + transformedLines[transformedLines.length - 1].length; + } + state.g.buffer += str; +} + +/** + * Update indent using state.indentBy property. Indent is measured in + * double spaces. Updates a single line only. + * + * @param {string} str + * @param {object} state + * @return {string} + */ +function updateIndent(str, state) { + for (var i = 0; i < -state.g.indentBy; i++) { + str = str.replace(/(^|\n)( {2}|\t)/g, '$1'); + } + return str; +} + +/** + * Calculates indent from the beginning of the line until "start" or the first + * character before start. + * @example + * " foo.bar()" + * ^ + * start + * indent will be 2 + * + * @param {number} start + * @param {object} state + * @return {number} + */ +function indentBefore(start, state) { + var end = start; + start = start - 1; + + while (start > 0 && state.g.source[start] != '\n') { + if (!state.g.source[start].match(/[ \t]/)) { + end = start; + } + start--; + } + return state.g.source.substring(start + 1, end); +} + +function getDocblock(state) { + if (!state.g.docblock) { + var docblock = require('./docblock'); + state.g.docblock = + docblock.parseAsObject(docblock.extract(state.g.source)); + } + return state.g.docblock; +} + +function identWithinLexicalScope(identName, state, stopBeforeNode) { + var currScope = state.localScope; + while (currScope) { + if (currScope.identifiers[identName] !== undefined) { + return true; + } + + if (stopBeforeNode && currScope.parentNode === stopBeforeNode) { + break; + } + + currScope = currScope.parentScope; + } + return false; +} + +function identInLocalScope(identName, state) { + return state.localScope.identifiers[identName] !== undefined; +} + +function declareIdentInLocalScope(identName, state) { + state.localScope.identifiers[identName] = true; +} + +/** + * Apply the given analyzer function to the current node. If the analyzer + * doesn't return false, traverse each child of the current node using the given + * traverser function. + * + * @param {function} analyzer + * @param {function} traverser + * @param {object} node + * @param {function} visitor + * @param {array} path + * @param {object} state + */ +function analyzeAndTraverse(analyzer, traverser, node, path, state) { + var key, child; + + if (node.type) { + if (analyzer(node, path, state) === false) { + return; + } + path.unshift(node); + } + + for (key in node) { + // skip obviously wrong attributes + if (key === 'range' || key === 'loc') { + continue; + } + if (node.hasOwnProperty(key)) { + child = node[key]; + if (typeof child === 'object' && child !== null) { + traverser(child, path, state); + } + } + } + node.type && path.shift(); +} + +/** + * Checks whether a node or any of its sub-nodes contains + * a syntactic construct of the passed type. + * @param {object} node - AST node to test. + * @param {string} type - node type to lookup. + */ +function containsChildOfType(node, type) { + var foundMatchingChild = false; + function nodeTypeAnalyzer(node) { + if (node.type === type) { + foundMatchingChild = true; + return false; + } + } + function nodeTypeTraverser(child, path, state) { + if (!foundMatchingChild) { + foundMatchingChild = containsChildOfType(child, type); + } + } + analyzeAndTraverse( + nodeTypeAnalyzer, + nodeTypeTraverser, + node, + [] + ); + return foundMatchingChild; +} + +exports.append = append; +exports.catchup = catchup; +exports.catchupWhiteSpace = catchupWhiteSpace; +exports.catchupNewlines = catchupNewlines; +exports.containsChildOfType = containsChildOfType; +exports.createState = createState; +exports.declareIdentInLocalScope = declareIdentInLocalScope; +exports.getDocblock = getDocblock; +exports.identWithinLexicalScope = identWithinLexicalScope; +exports.identInLocalScope = identInLocalScope; +exports.indentBefore = indentBefore; +exports.move = move; +exports.updateIndent = updateIndent; +exports.updateState = updateState; +exports.analyzeAndTraverse = analyzeAndTraverse; + +},{"./docblock":18}],21:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/*jslint node:true*/ + +/** + * @typechecks + */ +'use strict'; + +var base62 = require('base62'); +var Syntax = require('esprima-fb').Syntax; +var utils = require('../src/utils'); + +var SUPER_PROTO_IDENT_PREFIX = '____SuperProtoOf'; + +var _anonClassUUIDCounter = 0; +var _mungedSymbolMaps = {}; + +/** + * Used to generate a unique class for use with code-gens for anonymous class + * expressions. + * + * @param {object} state + * @return {string} + */ +function _generateAnonymousClassName(state) { + var mungeNamespace = state.mungeNamespace || ''; + return '____Class' + mungeNamespace + base62.encode(_anonClassUUIDCounter++); +} + +/** + * Given an identifier name, munge it using the current state's mungeNamespace. + * + * @param {string} identName + * @param {object} state + * @return {string} + */ +function _getMungedName(identName, state) { + var mungeNamespace = state.mungeNamespace; + var shouldMinify = state.g.opts.minify; + + if (shouldMinify) { + if (!_mungedSymbolMaps[mungeNamespace]) { + _mungedSymbolMaps[mungeNamespace] = { + symbolMap: {}, + identUUIDCounter: 0 + }; + } + + var symbolMap = _mungedSymbolMaps[mungeNamespace].symbolMap; + if (!symbolMap[identName]) { + symbolMap[identName] = + base62.encode(_mungedSymbolMaps[mungeNamespace].identUUIDCounter++); + } + identName = symbolMap[identName]; + } + return '$' + mungeNamespace + identName; +} + +/** + * Extracts super class information from a class node. + * + * Information includes name of the super class and/or the expression string + * (if extending from an expression) + * + * @param {object} node + * @param {object} state + * @return {object} + */ +function _getSuperClassInfo(node, state) { + var ret = { + name: null, + expression: null + }; + if (node.superClass) { + if (node.superClass.type === Syntax.Identifier) { + ret.name = node.superClass.name; + } else { + // Extension from an expression + ret.name = _generateAnonymousClassName(state); + ret.expression = state.g.source.substring( + node.superClass.range[0], + node.superClass.range[1] + ); + } + } + return ret; +} + +/** + * Used with .filter() to find the constructor method in a list of + * MethodDefinition nodes. + * + * @param {object} classElement + * @return {boolean} + */ +function _isConstructorMethod(classElement) { + return classElement.type === Syntax.MethodDefinition && + classElement.key.type === Syntax.Identifier && + classElement.key.name === 'constructor'; +} + +/** + * @param {object} node + * @param {object} state + * @return {boolean} + */ +function _shouldMungeIdentifier(node, state) { + return ( + !!state.methodFuncNode && + !utils.getDocblock(state).hasOwnProperty('preventMunge') && + /^_(?!_)/.test(node.name) + ); +} + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitClassMethod(traverse, node, path, state) { + utils.catchup(node.range[0], state); + path.unshift(node); + traverse(node.value, path, state); + path.shift(); + return false; +} +visitClassMethod.test = function(node, path, state) { + return node.type === Syntax.MethodDefinition; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitClassFunctionExpression(traverse, node, path, state) { + var methodNode = path[0]; + + state = utils.updateState(state, { + methodFuncNode: node + }); + + if (methodNode.key.name === 'constructor') { + utils.append('function ' + state.className, state); + } else { + var methodName = methodNode.key.name; + if (_shouldMungeIdentifier(methodNode.key, state)) { + methodName = _getMungedName(methodName, state); + } + + var prototypeOrStatic = methodNode.static ? '' : 'prototype.'; + utils.append( + state.className + '.' + prototypeOrStatic + methodName + '=function', + state + ); + } + utils.move(methodNode.key.range[1], state); + + var params = node.params; + var paramName; + if (params.length > 0) { + for (var i = 0; i < params.length; i++) { + utils.catchup(node.params[i].range[0], state); + paramName = params[i].name; + if (_shouldMungeIdentifier(params[i], state)) { + paramName = _getMungedName(params[i].name, state); + } + utils.append(paramName, state); + utils.move(params[i].range[1], state); + } + } else { + utils.append('(', state); + } + utils.append(')', state); + utils.catchupWhiteSpace(node.body.range[0], state); + utils.append('{', state); + if (!state.scopeIsStrict) { + utils.append('"use strict";', state); + } + utils.move(node.body.range[0] + '{'.length, state); + + path.unshift(node); + traverse(node.body, path, state); + path.shift(); + utils.catchup(node.body.range[1], state); + + if (methodNode.key.name !== 'constructor') { + utils.append(';', state); + } + return false; +} +visitClassFunctionExpression.test = function(node, path, state) { + return node.type === Syntax.FunctionExpression + && path[0].type === Syntax.MethodDefinition; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function _renderClassBody(traverse, node, path, state) { + var className = state.className; + var superClass = state.superClass; + + // Set up prototype of constructor on same line as `extends` for line-number + // preservation. This relies on function-hoisting if a constructor function is + // defined in the class body. + if (superClass.name) { + // If the super class is an expression, we need to memoize the output of the + // expression into the generated class name variable and use that to refer + // to the super class going forward. Example: + // + // class Foo extends mixin(Bar, Baz) {} + // --transforms to-- + // function Foo() {} var ____Class0Blah = mixin(Bar, Baz); + if (superClass.expression !== null) { + utils.append( + 'var ' + superClass.name + '=' + superClass.expression + ';', + state + ); + } + + var keyName = superClass.name + '____Key'; + var keyNameDeclarator = ''; + if (!utils.identWithinLexicalScope(keyName, state)) { + keyNameDeclarator = 'var '; + utils.declareIdentInLocalScope(keyName, state); + } + utils.append( + 'for(' + keyNameDeclarator + keyName + ' in ' + superClass.name + '){' + + 'if(' + superClass.name + '.hasOwnProperty(' + keyName + ')){' + + className + '[' + keyName + ']=' + + superClass.name + '[' + keyName + '];' + + '}' + + '}', + state + ); + + var superProtoIdentStr = SUPER_PROTO_IDENT_PREFIX + superClass.name; + if (!utils.identWithinLexicalScope(superProtoIdentStr, state)) { + utils.append( + 'var ' + superProtoIdentStr + '=' + superClass.name + '===null?' + + 'null:' + superClass.name + '.prototype;', + state + ); + utils.declareIdentInLocalScope(superProtoIdentStr, state); + } + + utils.append( + className + '.prototype=Object.create(' + superProtoIdentStr + ');', + state + ); + utils.append( + className + '.prototype.constructor=' + className + ';', + state + ); + utils.append( + className + '.__superConstructor__=' + superClass.name + ';', + state + ); + } + + // If there's no constructor method specified in the class body, create an + // empty constructor function at the top (same line as the class keyword) + if (!node.body.body.filter(_isConstructorMethod).pop()) { + utils.append('function ' + className + '(){', state); + if (!state.scopeIsStrict) { + utils.append('"use strict";', state); + } + if (superClass.name) { + utils.append( + 'if(' + superClass.name + '!==null){' + + superClass.name + '.apply(this,arguments);}', + state + ); + } + utils.append('}', state); + } + + utils.move(node.body.range[0] + '{'.length, state); + traverse(node.body, path, state); + utils.catchupWhiteSpace(node.range[1], state); +} + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitClassDeclaration(traverse, node, path, state) { + var className = node.id.name; + var superClass = _getSuperClassInfo(node, state); + + state = utils.updateState(state, { + mungeNamespace: className, + className: className, + superClass: superClass + }); + + _renderClassBody(traverse, node, path, state); + + return false; +} +visitClassDeclaration.test = function(node, path, state) { + return node.type === Syntax.ClassDeclaration; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitClassExpression(traverse, node, path, state) { + var className = node.id && node.id.name || _generateAnonymousClassName(state); + var superClass = _getSuperClassInfo(node, state); + + utils.append('(function(){', state); + + state = utils.updateState(state, { + mungeNamespace: className, + className: className, + superClass: superClass + }); + + _renderClassBody(traverse, node, path, state); + + utils.append('return ' + className + ';})()', state); + return false; +} +visitClassExpression.test = function(node, path, state) { + return node.type === Syntax.ClassExpression; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitPrivateIdentifier(traverse, node, path, state) { + utils.append(_getMungedName(node.name, state), state); + utils.move(node.range[1], state); +} +visitPrivateIdentifier.test = function(node, path, state) { + if (node.type === Syntax.Identifier && _shouldMungeIdentifier(node, state)) { + // Always munge non-computed properties of MemberExpressions + // (a la preventing access of properties of unowned objects) + if (path[0].type === Syntax.MemberExpression && path[0].object !== node + && path[0].computed === false) { + return true; + } + + // Always munge identifiers that were declared within the method function + // scope + if (utils.identWithinLexicalScope(node.name, state, state.methodFuncNode)) { + return true; + } + + // Always munge private keys on object literals defined within a method's + // scope. + if (path[0].type === Syntax.Property + && path[1].type === Syntax.ObjectExpression) { + return true; + } + + // Always munge function parameters + if (path[0].type === Syntax.FunctionExpression + || path[0].type === Syntax.FunctionDeclaration) { + for (var i = 0; i < path[0].params.length; i++) { + if (path[0].params[i] === node) { + return true; + } + } + } + } + return false; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitSuperCallExpression(traverse, node, path, state) { + var superClassName = state.superClass.name; + + if (node.callee.type === Syntax.Identifier) { + utils.append(superClassName + '.call(', state); + utils.move(node.callee.range[1], state); + } else if (node.callee.type === Syntax.MemberExpression) { + utils.append(SUPER_PROTO_IDENT_PREFIX + superClassName, state); + utils.move(node.callee.object.range[1], state); + + if (node.callee.computed) { + // ["a" + "b"] + utils.catchup(node.callee.property.range[1] + ']'.length, state); + } else { + // .ab + utils.append('.' + node.callee.property.name, state); + } + + utils.append('.call(', state); + utils.move(node.callee.range[1], state); + } + + utils.append('this', state); + if (node.arguments.length > 0) { + utils.append(',', state); + utils.catchupWhiteSpace(node.arguments[0].range[0], state); + traverse(node.arguments, path, state); + } + + utils.catchupWhiteSpace(node.range[1], state); + utils.append(')', state); + return false; +} +visitSuperCallExpression.test = function(node, path, state) { + if (state.superClass && node.type === Syntax.CallExpression) { + var callee = node.callee; + if (callee.type === Syntax.Identifier && callee.name === 'super' + || callee.type == Syntax.MemberExpression + && callee.object.name === 'super') { + return true; + } + } + return false; +}; + +/** + * @param {function} traverse + * @param {object} node + * @param {array} path + * @param {object} state + */ +function visitSuperMemberExpression(traverse, node, path, state) { + var superClassName = state.superClass.name; + + utils.append(SUPER_PROTO_IDENT_PREFIX + superClassName, state); + utils.move(node.object.range[1], state); +} +visitSuperMemberExpression.test = function(node, path, state) { + return state.superClass + && node.type === Syntax.MemberExpression + && node.object.type === Syntax.Identifier + && node.object.name === 'super'; +}; + +exports.visitorList = [ + visitClassDeclaration, + visitClassExpression, + visitClassFunctionExpression, + visitClassMethod, + visitPrivateIdentifier, + visitSuperCallExpression, + visitSuperMemberExpression +]; + +},{"../src/utils":20,"base62":7,"esprima-fb":6}],22:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* jshint browser: true */ +/* jslint evil: true */ + +'use strict'; +var runScripts; +var headEl; + +var transform = require('jstransform').transform; +var visitors = require('./fbtransform/visitors').transformVisitors; +var transform = transform.bind(null, visitors.react); +var docblock = require('jstransform/src/docblock'); + + +exports.transform = transform; + +exports.exec = function(code) { + return eval(transform(code).code); +}; + +if (typeof window === "undefined" || window === null) { + return; +} +headEl = document.getElementsByTagName('head')[0]; + +var run = exports.run = function(code) { + var jsx = docblock.parseAsObject(docblock.extract(code)).jsx; + + var functionBody = jsx ? transform(code).code : code; + var scriptEl = document.createElement('script'); + + scriptEl.innerHTML = functionBody; + headEl.appendChild(scriptEl); +}; + +var load = exports.load = function(url, callback) { + var xhr; + xhr = window.ActiveXObject ? new window.ActiveXObject('Microsoft.XMLHTTP') + : new XMLHttpRequest(); + + // Disable async since we need to execute scripts in the order they are in the + // DOM to mirror normal script loading. + xhr.open('GET', url, false); + if ('overrideMimeType' in xhr) { + xhr.overrideMimeType('text/plain'); + } + xhr.onreadystatechange = function() { + if (xhr.readyState === 4) { + if (xhr.status === 0 || xhr.status === 200) { + run(xhr.responseText); + } else { + throw new Error("Could not load " + url); + } + if (callback) { + return callback(); + } + } + }; + return xhr.send(null); +}; + +runScripts = function() { + var scripts = document.getElementsByTagName('script'); + scripts = Array.prototype.slice.call(scripts); + var jsxScripts = scripts.filter(function(script) { + return script.type === 'text/jsx'; + }); + + console.warn("You are using the in-browser JSX transformer. Be sure to precompile your JSX for production - http://facebook.github.io/react/docs/tooling-integration.html#jsx"); + + jsxScripts.forEach(function(script) { + if (script.src) { + load(script.src); + } else { + run(script.innerHTML); + } + }); +}; + +if (window.addEventListener) { + window.addEventListener('DOMContentLoaded', runScripts, false); +} else { + window.attachEvent('onload', runScripts); +} + +},{"./fbtransform/visitors":26,"jstransform":19,"jstransform/src/docblock":18}],23:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; + +var Syntax = require('esprima-fb').Syntax; + +var catchup = require('jstransform/src/utils').catchup; +var catchupWhiteSpace = require('jstransform/src/utils').catchupWhiteSpace; +var append = require('jstransform/src/utils').append; +var move = require('jstransform/src/utils').move; +var getDocblock = require('jstransform/src/utils').getDocblock; + +var FALLBACK_TAGS = require('./xjs').knownTags; +var renderXJSExpressionContainer = + require('./xjs').renderXJSExpressionContainer; +var renderXJSLiteral = require('./xjs').renderXJSLiteral; +var quoteAttrName = require('./xjs').quoteAttrName; + +/** + * Customized desugar processor. + * + * Currently: (Somewhat tailored to React) + * => X(null, null) + * => X({prop: '1'}, null) + * => X({prop:'2'}, Y(null, null)) + * => X({prop:'2'}, [Y(null, null), Z(null, null)]) + * + * Exceptions to the simple rules above: + * if a property is named "class" it will be changed to "className" in the + * javascript since "class" is not a valid object key in javascript. + */ + +var JSX_ATTRIBUTE_TRANSFORMS = { + cxName: function(attr) { + if (attr.value.type !== Syntax.Literal) { + throw new Error("cx only accepts a string literal"); + } else { + var classNames = attr.value.value.split(/\s+/g); + return 'cx(' + classNames.map(JSON.stringify).join(',') + ')'; + } + } +}; + +function visitReactTag(traverse, object, path, state) { + var jsxObjIdent = getDocblock(state).jsx; + + catchup(object.openingElement.range[0], state); + + if (object.name.namespace) { + throw new Error( + 'Namespace tags are not supported. ReactJSX is not XML.'); + } + + var isFallbackTag = FALLBACK_TAGS[object.name.name]; + append( + (isFallbackTag ? jsxObjIdent + '.' : '') + (object.name.name) + '(', + state + ); + + move(object.name.range[1], state); + + var childrenToRender = object.children.filter(function(child) { + return !(child.type === Syntax.Literal && !child.value.match(/\S/)); + }); + + // if we don't have any attributes, pass in null + if (object.attributes.length === 0) { + append('null', state); + } + + // write attributes + object.attributes.forEach(function(attr, index) { + catchup(attr.range[0], state); + if (attr.name.namespace) { + throw new Error( + 'Namespace attributes are not supported. ReactJSX is not XML.'); + } + var name = attr.name.name; + var isFirst = index === 0; + var isLast = index === object.attributes.length - 1; + + if (isFirst) { + append('{', state); + } + + append(quoteAttrName(name), state); + append(':', state); + + if (!attr.value) { + state.g.buffer += 'true'; + state.g.position = attr.name.range[1]; + if (!isLast) { + append(',', state); + } + } else { + move(attr.name.range[1], state); + // Use catchupWhiteSpace to skip over the '=' in the attribute + catchupWhiteSpace(attr.value.range[0], state); + if (JSX_ATTRIBUTE_TRANSFORMS[attr.name.name]) { + append(JSX_ATTRIBUTE_TRANSFORMS[attr.name.name](attr), state); + move(attr.value.range[1], state); + if (!isLast) { + append(',', state); + } + } else if (attr.value.type === Syntax.Literal) { + renderXJSLiteral(attr.value, isLast, state); + } else { + renderXJSExpressionContainer(traverse, attr.value, isLast, path, state); + } + } + + if (isLast) { + append('}', state); + } + + catchup(attr.range[1], state); + }); + + if (!object.selfClosing) { + catchup(object.openingElement.range[1] - 1, state); + move(object.openingElement.range[1], state); + } + + // filter out whitespace + if (childrenToRender.length > 0) { + append(', ', state); + + object.children.forEach(function(child) { + if (child.type === Syntax.Literal && !child.value.match(/\S/)) { + return; + } + catchup(child.range[0], state); + + var isLast = child === childrenToRender[childrenToRender.length - 1]; + + if (child.type === Syntax.Literal) { + renderXJSLiteral(child, isLast, state); + } else if (child.type === Syntax.XJSExpressionContainer) { + renderXJSExpressionContainer(traverse, child, isLast, path, state); + } else { + traverse(child, path, state); + if (!isLast) { + append(',', state); + state.g.buffer = state.g.buffer.replace(/(\s*),$/, ',$1'); + } + } + + catchup(child.range[1], state); + }); + } + + if (object.selfClosing) { + // everything up to /> + catchup(object.openingElement.range[1] - 2, state); + move(object.openingElement.range[1], state); + } else { + // everything up to + catchup(object.closingElement.range[0], state); + move(object.closingElement.range[1], state); + } + + append(')', state); + return false; +} + +visitReactTag.test = function(object, path, state) { + // only run react when react @jsx namespace is specified in docblock + var jsx = getDocblock(state).jsx; + return object.type === Syntax.XJSElement && jsx && jsx.length; +}; + +exports.visitReactTag = visitReactTag; + +},{"./xjs":25,"esprima-fb":6,"jstransform/src/utils":20}],24:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; + +var Syntax = require('esprima-fb').Syntax; +var catchup = require('jstransform/src/utils').catchup; +var append = require('jstransform/src/utils').append; +var getDocblock = require('jstransform/src/utils').getDocblock; + +/** + * Transforms the following: + * + * var MyComponent = React.createClass({ + * render: ... + * }); + * + * into: + * + * var MyComponent = React.createClass({ + * displayName: 'MyComponent', + * render: ... + * }); + */ +function visitReactDisplayName(traverse, object, path, state) { + if (object.id.type === Syntax.Identifier && + object.init && + object.init.type === Syntax.CallExpression && + object.init.callee.type === Syntax.MemberExpression && + object.init.callee.object.type === Syntax.Identifier && + object.init.callee.object.name === 'React' && + object.init.callee.property.type === Syntax.Identifier && + object.init.callee.property.name === 'createClass' && + object.init['arguments'].length === 1 && + object.init['arguments'][0].type === Syntax.ObjectExpression) { + + var displayName = object.id.name; + catchup(object.init['arguments'][0].range[0] + 1, state); + append("displayName: '" + displayName + "',", state); + } +} + +/** + * Will only run on @jsx files for now. + */ +visitReactDisplayName.test = function(object, path, state) { + return object.type === Syntax.VariableDeclarator && !!getDocblock(state).jsx; +}; + +exports.visitReactDisplayName = visitReactDisplayName; + +},{"esprima-fb":6,"jstransform/src/utils":20}],25:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/*global exports:true*/ +"use strict"; +var append = require('jstransform/src/utils').append; +var catchup = require('jstransform/src/utils').catchup; +var move = require('jstransform/src/utils').move; +var Syntax = require('esprima-fb').Syntax; + +var knownTags = { + a: true, + abbr: true, + address: true, + applet: true, + area: true, + article: true, + aside: true, + audio: true, + b: true, + base: true, + bdi: true, + bdo: true, + big: true, + blockquote: true, + body: true, + br: true, + button: true, + canvas: true, + caption: true, + circle: true, + cite: true, + code: true, + col: true, + colgroup: true, + command: true, + data: true, + datalist: true, + dd: true, + del: true, + details: true, + dfn: true, + dialog: true, + div: true, + dl: true, + dt: true, + ellipse: true, + em: true, + embed: true, + fieldset: true, + figcaption: true, + figure: true, + footer: true, + form: true, + g: true, + h1: true, + h2: true, + h3: true, + h4: true, + h5: true, + h6: true, + head: true, + header: true, + hgroup: true, + hr: true, + html: true, + i: true, + iframe: true, + img: true, + input: true, + ins: true, + kbd: true, + keygen: true, + label: true, + legend: true, + li: true, + line: true, + link: true, + main: true, + map: true, + mark: true, + marquee: true, + menu: true, + menuitem: true, + meta: true, + meter: true, + nav: true, + noscript: true, + object: true, + ol: true, + optgroup: true, + option: true, + output: true, + p: true, + param: true, + path: true, + polyline: true, + pre: true, + progress: true, + q: true, + rect: true, + rp: true, + rt: true, + ruby: true, + s: true, + samp: true, + script: true, + section: true, + select: true, + small: true, + source: true, + span: true, + strong: true, + style: true, + sub: true, + summary: true, + sup: true, + svg: true, + table: true, + tbody: true, + td: true, + text: true, + textarea: true, + tfoot: true, + th: true, + thead: true, + time: true, + title: true, + tr: true, + track: true, + u: true, + ul: true, + 'var': true, + video: true, + wbr: true +}; + +function safeTrim(string) { + return string.replace(/^[ \t]+/, '').replace(/[ \t]+$/, ''); +} + +// Replace all trailing whitespace characters with a single space character +function trimWithSingleSpace(string) { + return string.replace(/^[ \t\xA0]{2,}/, ' '). + replace(/[ \t\xA0]{2,}$/, ' ').replace(/^\s+$/, ''); +} + +/** + * Special handling for multiline string literals + * print lines: + * + * line + * line + * + * as: + * + * "line "+ + * "line" + */ +function renderXJSLiteral(object, isLast, state, start, end) { + /** Added blank check filtering and triming*/ + var trimmedChildValue = safeTrim(object.value); + var hasFinalNewLine = false; + + if (trimmedChildValue) { + // head whitespace + append(object.value.match(/^[\t ]*/)[0], state); + if (start) { + append(start, state); + } + + var trimmedChildValueWithSpace = trimWithSingleSpace(object.value); + + /** + */ + var initialLines = trimmedChildValue.split(/\r\n|\n|\r/); + + var lines = initialLines.filter(function(line) { + return safeTrim(line).length > 0; + }); + + var hasInitialNewLine = initialLines[0] !== lines[0]; + hasFinalNewLine = + initialLines[initialLines.length - 1] !== lines[lines.length - 1]; + + var numLines = lines.length; + lines.forEach(function (line, ii) { + var lastLine = ii === numLines - 1; + var trimmedLine = safeTrim(line); + if (trimmedLine === '' && !lastLine) { + append(line, state); + } else { + var preString = ''; + var postString = ''; + var leading = line.match(/^[ \t]*/)[0]; + + if (ii === 0) { + if (hasInitialNewLine) { + preString = ' '; + leading = '\n' + leading; + } + if (trimmedChildValueWithSpace.substring(0, 1) === ' ') { + // If this is the first line, and the original content starts with + // whitespace, place a single space at the beginning. + preString = ' '; + } + } + if (!lastLine || trimmedChildValueWithSpace.substr( + trimmedChildValueWithSpace.length - 1, 1) === ' ' || + hasFinalNewLine + ) { + // If either not on the last line, or the original content ends with + // whitespace, place a single character at the end. + postString = ' '; + } + + append( + leading + + JSON.stringify( + preString + trimmedLine + postString + ) + + (lastLine ? '' : '+') + + line.match(/[ \t]*$/)[0], + state); + } + if (!lastLine) { + append('\n', state); + } + }); + } else { + if (start) { + append(start, state); + } + append('""', state); + } + if (end) { + append(end, state); + } + + // add comma before trailing whitespace + if (!isLast) { + append(',', state); + } + + // tail whitespace + if (hasFinalNewLine) { + append('\n', state); + } + append(object.value.match(/[ \t]*$/)[0], state); + move(object.range[1], state); +} + +function renderXJSExpressionContainer(traverse, object, isLast, path, state) { + // Plus 1 to skip `{`. + move(object.range[0] + 1, state); + traverse(object.expression, path, state); + if (!isLast && object.expression.type !== Syntax.XJSEmptyExpression) { + // If we need to append a comma, make sure to do so after the expression. + catchup(object.expression.range[1], state); + append(',', state); + } + + // Minus 1 to skip `}`. + catchup(object.range[1] - 1, state); + move(object.range[1], state); + return false; +} + +function quoteAttrName(attr) { + // Quote invalid JS identifiers. + if (!/^[a-z_$][a-z\d_$]*$/i.test(attr)) { + return "'" + attr + "'"; + } + return attr; +} + +exports.knownTags = knownTags; +exports.renderXJSExpressionContainer = renderXJSExpressionContainer; +exports.renderXJSLiteral = renderXJSLiteral; +exports.quoteAttrName = quoteAttrName; + +},{"esprima-fb":6,"jstransform/src/utils":20}],26:[function(require,module,exports){ +/*global exports:true*/ +var es6Classes = require('jstransform/visitors/es6-class-visitors').visitorList; +var react = require('./transforms/react'); +var reactDisplayName = require('./transforms/reactDisplayName'); + +/** + * Map from transformName => orderedListOfVisitors. + */ +var transformVisitors = { + 'es6-classes': es6Classes, + 'react': [ + react.visitReactTag, + reactDisplayName.visitReactDisplayName + ] +}; + +/** + * Specifies the order in which each transform should run. + */ +var transformRunOrder = [ + 'es6-classes', + 'react' +]; + +/** + * Given a list of transform names, return the ordered list of visitors to be + * passed to the transform() function. + * + * @param {array?} excludes + * @return {array} + */ +function getVisitorsList(excludes) { + var ret = []; + for (var i = 0, il = transformRunOrder.length; i < il; i++) { + if (!excludes || excludes.indexOf(transformRunOrder[i]) === -1) { + ret = ret.concat(transformVisitors[transformRunOrder[i]]); + } + } + return ret; +} + +exports.getVisitorsList = getVisitorsList; +exports.transformVisitors = transformVisitors; + +},{"./transforms/react":23,"./transforms/reactDisplayName":24,"jstransform/visitors/es6-class-visitors":21}]},{},[22]) +(22) +}); +; \ No newline at end of file diff --git a/ajax/libs/react/0.5.0/react-with-addons.js b/ajax/libs/react/0.5.0/react-with-addons.js new file mode 100644 index 000000000..e440228ac --- /dev/null +++ b/ajax/libs/react/0.5.0/react-with-addons.js @@ -0,0 +1,15314 @@ +/** + * React (with addons) v0.5.0 + */ +!function(e){"object"==typeof exports?module.exports=e():"function"==typeof define&&define.amd?define(e):"undefined"!=typeof window?window.React=e():"undefined"!=typeof global?global.React=e():"undefined"!=typeof self&&(self.React=e())}(function(){var define,module,exports; +return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);throw new Error("Cannot find module '"+o+"'")}var f=n[o]={exports:{}};t[o][0].call(f.exports,function(e){var n=t[o][1][e];return s(n?n:e)},f,f.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o -1; +} + +var CSSCore = { + + /** + * Adds the class passed in to the element if it doesn't already have it. + * + * @param {DOMElement} element the element to set the class on + * @param {string} className the CSS className + * @return {DOMElement} the element passed in + */ + addClass: function(element, className) { + invariant( + !/\s/.test(className), + 'CSSCore.addClass takes only a single class name. "%s" contains ' + + 'multiple classes.', className + ); + + if (className) { + if (element.classList) { + element.classList.add(className); + } else if (!hasClass(element, className)) { + element.className = element.className + ' ' + className; + } + } + return element; + }, + + /** + * Removes the class passed in from the element + * + * @param {DOMElement} element the element to set the class on + * @param {string} className the CSS className + * @return {DOMElement} the element passed in + */ + removeClass: function(element, className) { + invariant( + !/\s/.test(className), + 'CSSCore.removeClass takes only a single class name. "%s" contains ' + + 'multiple classes.', className + ); + + if (className) { + if (element.classList) { + element.classList.remove(className); + } else if (hasClass(element, className)) { + element.className = element.className + .replace(new RegExp('(^|\\s)' + className + '(?:\\s|$)', 'g'), '$1') + .replace(/\s+/g, ' ') // multiple spaces to one + .replace(/^\s*|\s*$/g, ''); // trim the ends + } + } + return element; + }, + + /** + * Helper to add or remove a class from an element based on a condition. + * + * @param {DOMElement} element the element to set the class on + * @param {string} className the CSS className + * @param {*} bool condition to whether to add or remove the class + * @return {DOMElement} the element passed in + */ + conditionClass: function(element, className, bool) { + return (bool ? CSSCore.addClass : CSSCore.removeClass)(element, className); + } +}; + +module.exports = CSSCore; + +},{"./invariant":106}],3:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule CSSProperty + */ + +"use strict"; + +/** + * CSS properties which accept numbers but are not in units of "px". + */ +var isUnitlessNumber = { + fillOpacity: true, + fontWeight: true, + lineHeight: true, + opacity: true, + orphans: true, + zIndex: true, + zoom: true +}; + +/** + * Most style properties can be unset by doing .style[prop] = '' but IE8 + * doesn't like doing that with shorthand properties so for the properties that + * IE8 breaks on, which are listed here, we instead unset each of the + * individual properties. See http://bugs.jquery.com/ticket/12385. + * The 4-value 'clock' properties like margin, padding, border-width seem to + * behave without any problems. Curiously, list-style works too without any + * special prodding. + */ +var shorthandPropertyExpansions = { + background: { + backgroundImage: true, + backgroundPosition: true, + backgroundRepeat: true, + backgroundColor: true + }, + border: { + borderWidth: true, + borderStyle: true, + borderColor: true + }, + borderBottom: { + borderBottomWidth: true, + borderBottomStyle: true, + borderBottomColor: true + }, + borderLeft: { + borderLeftWidth: true, + borderLeftStyle: true, + borderLeftColor: true + }, + borderRight: { + borderRightWidth: true, + borderRightStyle: true, + borderRightColor: true + }, + borderTop: { + borderTopWidth: true, + borderTopStyle: true, + borderTopColor: true + }, + font: { + fontStyle: true, + fontVariant: true, + fontWeight: true, + fontSize: true, + lineHeight: true, + fontFamily: true + } +}; + +var CSSProperty = { + isUnitlessNumber: isUnitlessNumber, + shorthandPropertyExpansions: shorthandPropertyExpansions +}; + +module.exports = CSSProperty; + +},{}],4:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule CSSPropertyOperations + * @typechecks static-only + */ + +"use strict"; + +var CSSProperty = require("./CSSProperty"); + +var dangerousStyleValue = require("./dangerousStyleValue"); +var escapeTextForBrowser = require("./escapeTextForBrowser"); +var hyphenate = require("./hyphenate"); +var memoizeStringOnly = require("./memoizeStringOnly"); + +var processStyleName = memoizeStringOnly(function(styleName) { + return escapeTextForBrowser(hyphenate(styleName)); +}); + +/** + * Operations for dealing with CSS properties. + */ +var CSSPropertyOperations = { + + /** + * Serializes a mapping of style properties for use as inline styles: + * + * > createMarkupForStyles({width: '200px', height: 0}) + * "width:200px;height:0;" + * + * Undefined values are ignored so that declarative programming is easier. + * + * @param {object} styles + * @return {?string} + */ + createMarkupForStyles: function(styles) { + var serialized = ''; + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + var styleValue = styles[styleName]; + if (styleValue != null) { + serialized += processStyleName(styleName) + ':'; + serialized += dangerousStyleValue(styleName, styleValue) + ';'; + } + } + return serialized || null; + }, + + /** + * Sets the value for multiple styles on a node. If a value is specified as + * '' (empty string), the corresponding style property will be unset. + * + * @param {DOMElement} node + * @param {object} styles + */ + setValueForStyles: function(node, styles) { + var style = node.style; + for (var styleName in styles) { + if (!styles.hasOwnProperty(styleName)) { + continue; + } + var styleValue = dangerousStyleValue(styleName, styles[styleName]); + if (styleValue) { + style[styleName] = styleValue; + } else { + var expansion = CSSProperty.shorthandPropertyExpansions[styleName]; + if (expansion) { + // Shorthand property that IE8 won't like unsetting, so unset each + // component to placate it + for (var individualStyleName in expansion) { + style[individualStyleName] = ''; + } + } else { + style[styleName] = ''; + } + } + } + } + +}; + +module.exports = CSSPropertyOperations; + +},{"./CSSProperty":3,"./dangerousStyleValue":91,"./escapeTextForBrowser":93,"./hyphenate":105,"./memoizeStringOnly":114}],5:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule CallbackRegistry + * @typechecks static-only + */ + +"use strict"; + +var listenerBank = {}; + +/** + * Stores "listeners" by `registrationName`/`id`. There should be at most one + * "listener" per `registrationName`/`id` in the `listenerBank`. + * + * Access listeners via `listenerBank[registrationName][id]`. + * + * @class CallbackRegistry + * @internal + */ +var CallbackRegistry = { + + /** + * Stores `listener` at `listenerBank[registrationName][id]`. Is idempotent. + * + * @param {string} id ID of the DOM element. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @param {?function} listener The callback to store. + */ + putListener: function(id, registrationName, listener) { + var bankForRegistrationName = + listenerBank[registrationName] || (listenerBank[registrationName] = {}); + bankForRegistrationName[id] = listener; + }, + + /** + * @param {string} id ID of the DOM element. + * @param {string} registrationName Name of listener (e.g. `onClick`). + * @return {?function} The stored callback. + */ + getListener: function(id, registrationName) { + var bankForRegistrationName = listenerBank[registrationName]; + return bankForRegistrationName && bankForRegistrationName[id]; + }, + + /** + * Deletes a listener from the registration bank. + * + * @param {string} id ID of the DOM element. + * @param {string} registrationName Name of listener (e.g. `onClick`). + */ + deleteListener: function(id, registrationName) { + var bankForRegistrationName = listenerBank[registrationName]; + if (bankForRegistrationName) { + delete bankForRegistrationName[id]; + } + }, + + /** + * Deletes all listeners for the DOM element with the supplied ID. + * + * @param {string} id ID of the DOM element. + */ + deleteAllListeners: function(id) { + for (var registrationName in listenerBank) { + delete listenerBank[registrationName][id]; + } + }, + + /** + * This is needed for tests only. Do not use! + */ + __purge: function() { + listenerBank = {}; + } + +}; + +module.exports = CallbackRegistry; + +},{}],6:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule ChangeEventPlugin + */ + +"use strict"; + +var EventConstants = require("./EventConstants"); +var EventPluginHub = require("./EventPluginHub"); +var EventPropagators = require("./EventPropagators"); +var ExecutionEnvironment = require("./ExecutionEnvironment"); +var SyntheticEvent = require("./SyntheticEvent"); + +var isEventSupported = require("./isEventSupported"); +var isTextInputElement = require("./isTextInputElement"); +var keyOf = require("./keyOf"); + +var topLevelTypes = EventConstants.topLevelTypes; + +var eventTypes = { + change: { + phasedRegistrationNames: { + bubbled: keyOf({onChange: null}), + captured: keyOf({onChangeCapture: null}) + } + } +}; + +/** + * For IE shims + */ +var activeElement = null; +var activeElementID = null; +var activeElementValue = null; +var activeElementValueProp = null; + +/** + * SECTION: handle `change` event + */ +function shouldUseChangeEvent(elem) { + return ( + elem.nodeName === 'SELECT' || + (elem.nodeName === 'INPUT' && elem.type === 'file') + ); +} + +var doesChangeEventBubble = false; +if (ExecutionEnvironment.canUseDOM) { + // See `handleChange` comment below + doesChangeEventBubble = isEventSupported('change') && ( + !('documentMode' in document) || document.documentMode > 8 + ); +} + +function manualDispatchChangeEvent(nativeEvent) { + var event = SyntheticEvent.getPooled( + eventTypes.change, + activeElementID, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(event); + + // If change bubbled, we'd just bind to it like all the other events + // and have it go through ReactEventTopLevelCallback. Since it doesn't, we + // manually listen for the change event and so we have to enqueue and + // process the abstract event manually. + EventPluginHub.enqueueEvents(event); + EventPluginHub.processEventQueue(); +} + +function startWatchingForChangeEventIE8(target, targetID) { + activeElement = target; + activeElementID = targetID; + activeElement.attachEvent('onchange', manualDispatchChangeEvent); +} + +function stopWatchingForChangeEventIE8() { + if (!activeElement) { + return; + } + activeElement.detachEvent('onchange', manualDispatchChangeEvent); + activeElement = null; + activeElementID = null; +} + +function getTargetIDForChangeEvent( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topChange) { + return topLevelTargetID; + } +} +function handleEventsForChangeEventIE8( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topFocus) { + // stopWatching() should be a noop here but we call it just in case we + // missed a blur event somehow. + stopWatchingForChangeEventIE8(); + startWatchingForChangeEventIE8(topLevelTarget, topLevelTargetID); + } else if (topLevelType === topLevelTypes.topBlur) { + stopWatchingForChangeEventIE8(); + } +} + + +/** + * SECTION: handle `input` event + */ +var isInputEventSupported = false; +if (ExecutionEnvironment.canUseDOM) { + // IE9 claims to support the input event but fails to trigger it when + // deleting text, so we ignore its input events + isInputEventSupported = isEventSupported('input') && ( + !('documentMode' in document) || document.documentMode > 9 + ); +} + +/** + * (For old IE.) Replacement getter/setter for the `value` property that gets + * set on the active element. + */ +var newValueProp = { + get: function() { + return activeElementValueProp.get.call(this); + }, + set: function(val) { + // Cast to a string so we can do equality checks. + activeElementValue = '' + val; + activeElementValueProp.set.call(this, val); + } +}; + +/** + * (For old IE.) Starts tracking propertychange events on the passed-in element + * and override the value property so that we can distinguish user events from + * value changes in JS. + */ +function startWatchingForValueChange(target, targetID) { + activeElement = target; + activeElementID = targetID; + activeElementValue = target.value; + activeElementValueProp = Object.getOwnPropertyDescriptor( + target.constructor.prototype, + 'value' + ); + + Object.defineProperty(activeElement, 'value', newValueProp); + activeElement.attachEvent('onpropertychange', handlePropertyChange); +} + +/** + * (For old IE.) Removes the event listeners from the currently-tracked element, + * if any exists. + */ +function stopWatchingForValueChange() { + if (!activeElement) { + return; + } + + // delete restores the original property definition + delete activeElement.value; + activeElement.detachEvent('onpropertychange', handlePropertyChange); + + activeElement = null; + activeElementID = null; + activeElementValue = null; + activeElementValueProp = null; +} + +/** + * (For old IE.) Handles a propertychange event, sending a `change` event if + * the value of the active element has changed. + */ +function handlePropertyChange(nativeEvent) { + if (nativeEvent.propertyName !== 'value') { + return; + } + var value = nativeEvent.srcElement.value; + if (value === activeElementValue) { + return; + } + activeElementValue = value; + + manualDispatchChangeEvent(nativeEvent); +} + +/** + * If a `change` event should be fired, returns the target's ID. + */ +function getTargetIDForInputEvent( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topInput) { + // In modern browsers (i.e., not IE8 or IE9), the input event is exactly + // what we want so fall through here and trigger an abstract event + return topLevelTargetID; + } +} + +// For IE8 and IE9. +function handleEventsForInputEventIE( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topFocus) { + // In IE8, we can capture almost all .value changes by adding a + // propertychange handler and looking for events with propertyName + // equal to 'value' + // In IE9, propertychange fires for most input events but is buggy and + // doesn't fire when text is deleted, but conveniently, selectionchange + // appears to fire in all of the remaining cases so we catch those and + // forward the event if the value has changed + // In either case, we don't want to call the event handler if the value + // is changed from JS so we redefine a setter for `.value` that updates + // our activeElementValue variable, allowing us to ignore those changes + // + // stopWatching() should be a noop here but we call it just in case we + // missed a blur event somehow. + stopWatchingForValueChange(); + startWatchingForValueChange(topLevelTarget, topLevelTargetID); + } else if (topLevelType === topLevelTypes.topBlur) { + stopWatchingForValueChange(); + } +} + +// For IE8 and IE9. +function getTargetIDForInputEventIE( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topSelectionChange || + topLevelType === topLevelTypes.topKeyUp || + topLevelType === topLevelTypes.topKeyDown) { + // On the selectionchange event, the target is just document which isn't + // helpful for us so just check activeElement instead. + // + // 99% of the time, keydown and keyup aren't necessary. IE8 fails to fire + // propertychange on the first input event after setting `value` from a + // script and fires only keydown, keypress, keyup. Catching keyup usually + // gets it and catching keydown lets us fire an event for the first + // keystroke if user does a key repeat (it'll be a little delayed: right + // before the second keystroke). Other input methods (e.g., paste) seem to + // fire selectionchange normally. + if (activeElement && activeElement.value !== activeElementValue) { + activeElementValue = activeElement.value; + return activeElementID; + } + } +} + + +/** + * SECTION: handle `click` event + */ +function shouldUseClickEvent(elem) { + // Use the `click` event to detect changes to checkbox and radio inputs. + // This approach works across all browsers, whereas `change` does not fire + // until `blur` in IE8. + return ( + elem.nodeName === 'INPUT' && + (elem.type === 'checkbox' || elem.type === 'radio') + ); +} + +function getTargetIDForClickEvent( + topLevelType, + topLevelTarget, + topLevelTargetID) { + if (topLevelType === topLevelTypes.topClick) { + return topLevelTargetID; + } +} + +/** + * This plugin creates an `onChange` event that normalizes change events + * across form elements. This event fires at a time when it's possible to + * change the element's value without seeing a flicker. + * + * Supported elements are: + * - input (see `isTextInputElement`) + * - textarea + * - select + */ +var ChangeEventPlugin = { + + eventTypes: eventTypes, + + /** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + + var getTargetIDFunc, handleEventFunc; + if (shouldUseChangeEvent(topLevelTarget)) { + if (doesChangeEventBubble) { + getTargetIDFunc = getTargetIDForChangeEvent; + } else { + handleEventFunc = handleEventsForChangeEventIE8; + } + } else if (isTextInputElement(topLevelTarget)) { + if (isInputEventSupported) { + getTargetIDFunc = getTargetIDForInputEvent; + } else { + getTargetIDFunc = getTargetIDForInputEventIE; + handleEventFunc = handleEventsForInputEventIE; + } + } else if (shouldUseClickEvent(topLevelTarget)) { + getTargetIDFunc = getTargetIDForClickEvent; + } + + if (getTargetIDFunc) { + var targetID = getTargetIDFunc( + topLevelType, + topLevelTarget, + topLevelTargetID + ); + if (targetID) { + var event = SyntheticEvent.getPooled( + eventTypes.change, + targetID, + nativeEvent + ); + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; + } + } + + if (handleEventFunc) { + handleEventFunc( + topLevelType, + topLevelTarget, + topLevelTargetID + ); + } + } + +}; + +module.exports = ChangeEventPlugin; + +},{"./EventConstants":15,"./EventPluginHub":17,"./EventPropagators":20,"./ExecutionEnvironment":21,"./SyntheticEvent":75,"./isEventSupported":107,"./isTextInputElement":109,"./keyOf":113}],7:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule CompositionEventPlugin + * @typechecks static-only + */ + +"use strict"; + +var EventConstants = require("./EventConstants"); +var EventPropagators = require("./EventPropagators"); +var ExecutionEnvironment = require("./ExecutionEnvironment"); +var ReactInputSelection = require("./ReactInputSelection"); +var SyntheticCompositionEvent = require("./SyntheticCompositionEvent"); + +var getTextContentAccessor = require("./getTextContentAccessor"); +var keyOf = require("./keyOf"); + +var END_KEYCODES = [9, 13, 27, 32]; // Tab, Return, Esc, Space +var START_KEYCODE = 229; + +var useCompositionEvent = ExecutionEnvironment.canUseDOM && + 'CompositionEvent' in window; +var topLevelTypes = EventConstants.topLevelTypes; +var currentComposition = null; + +// Events and their corresponding property names. +var eventTypes = { + compositionEnd: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionEnd: null}), + captured: keyOf({onCompositionEndCapture: null}) + } + }, + compositionStart: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionStart: null}), + captured: keyOf({onCompositionStartCapture: null}) + } + }, + compositionUpdate: { + phasedRegistrationNames: { + bubbled: keyOf({onCompositionUpdate: null}), + captured: keyOf({onCompositionUpdateCapture: null}) + } + } +}; + +/** + * Translate native top level events into event types. + * + * @param {string} topLevelType + * @return {object} + */ +function getCompositionEventType(topLevelType) { + switch (topLevelType) { + case topLevelTypes.topCompositionStart: + return eventTypes.compositionStart; + case topLevelTypes.topCompositionEnd: + return eventTypes.compositionEnd; + case topLevelTypes.topCompositionUpdate: + return eventTypes.compositionUpdate; + } +} + +/** + * Does our fallback best-guess model think this event signifies that + * composition has begun? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackStart(topLevelType, nativeEvent) { + return ( + topLevelType === topLevelTypes.topKeyDown && + nativeEvent.keyCode === START_KEYCODE + ); +} + +/** + * Does our fallback mode think that this event is the end of composition? + * + * @param {string} topLevelType + * @param {object} nativeEvent + * @return {boolean} + */ +function isFallbackEnd(topLevelType, nativeEvent) { + switch (topLevelType) { + case topLevelTypes.topKeyUp: + // Command keys insert or clear IME input. + return (END_KEYCODES.indexOf(nativeEvent.keyCode) !== -1); + case topLevelTypes.topKeyDown: + // Expect IME keyCode on each keydown. If we get any other + // code we must have exited earlier. + return (nativeEvent.keyCode !== START_KEYCODE); + case topLevelTypes.topKeyPress: + case topLevelTypes.topMouseDown: + case topLevelTypes.topBlur: + // Events are not possible without cancelling IME. + return true; + default: + return false; + } +} + +/** + * Helper class stores information about selection and document state + * so we can figure out what changed at a later date. + * + * @param {DOMEventTarget} root + */ +function FallbackCompositionState(root) { + this.root = root; + this.startSelection = ReactInputSelection.getSelection(root); + this.startValue = this.getText(); +} + +/** + * Get current text of input. + * + * @return {string} + */ +FallbackCompositionState.prototype.getText = function() { + return this.root.value || this.root[getTextContentAccessor()]; +}; + +/** + * Text that has changed since the start of composition. + * + * @return {string} + */ +FallbackCompositionState.prototype.getData = function() { + var endValue = this.getText(); + var prefixLength = this.startSelection.start; + var suffixLength = this.startValue.length - this.startSelection.end; + + return endValue.substr( + prefixLength, + endValue.length - suffixLength - prefixLength + ); +}; + +/** + * This plugin creates `onCompositionStart`, `onCompositionUpdate` and + * `onCompositionEnd` events on inputs, textareas and contentEditable + * nodes. + */ +var CompositionEventPlugin = { + + eventTypes: eventTypes, + + /** + * @param {string} topLevelType Record from `EventConstants`. + * @param {DOMEventTarget} topLevelTarget The listening component root node. + * @param {string} topLevelTargetID ID of `topLevelTarget`. + * @param {object} nativeEvent Native browser event. + * @return {*} An accumulation of synthetic events. + * @see {EventPluginHub.extractEvents} + */ + extractEvents: function( + topLevelType, + topLevelTarget, + topLevelTargetID, + nativeEvent) { + + var eventType; + var data; + + if (useCompositionEvent) { + eventType = getCompositionEventType(topLevelType); + } else if (!currentComposition) { + if (isFallbackStart(topLevelType, nativeEvent)) { + eventType = eventTypes.start; + currentComposition = new FallbackCompositionState(topLevelTarget); + } + } else if (isFallbackEnd(topLevelType, nativeEvent)) { + eventType = eventTypes.compositionEnd; + data = currentComposition.getData(); + currentComposition = null; + } + + if (eventType) { + var event = SyntheticCompositionEvent.getPooled( + eventType, + topLevelTargetID, + nativeEvent + ); + if (data) { + // Inject data generated from fallback path into the synthetic event. + // This matches the property of native CompositionEventInterface. + event.data = data; + } + EventPropagators.accumulateTwoPhaseDispatches(event); + return event; + } + } +}; + +module.exports = CompositionEventPlugin; + +},{"./EventConstants":15,"./EventPropagators":20,"./ExecutionEnvironment":21,"./ReactInputSelection":49,"./SyntheticCompositionEvent":74,"./getTextContentAccessor":104,"./keyOf":113}],8:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule DOMChildrenOperations + * @typechecks static-only + */ + +"use strict"; + +var Danger = require("./Danger"); +var ReactMultiChildUpdateTypes = require("./ReactMultiChildUpdateTypes"); + +var getTextContentAccessor = require("./getTextContentAccessor"); + +/** + * The DOM property to use when setting text content. + * + * @type {string} + * @private + */ +var textContentAccessor = getTextContentAccessor() || 'NA'; + +/** + * Inserts `childNode` as a child of `parentNode` at the `index`. + * + * @param {DOMElement} parentNode Parent node in which to insert. + * @param {DOMElement} childNode Child node to insert. + * @param {number} index Index at which to insert the child. + * @internal + */ +function insertChildAt(parentNode, childNode, index) { + var childNodes = parentNode.childNodes; + if (childNodes[index] === childNode) { + return; + } + // If `childNode` is already a child of `parentNode`, remove it so that + // computing `childNodes[index]` takes into account the removal. + if (childNode.parentNode === parentNode) { + parentNode.removeChild(childNode); + } + if (index >= childNodes.length) { + parentNode.appendChild(childNode); + } else { + parentNode.insertBefore(childNode, childNodes[index]); + } +} + +/** + * Operations for updating with DOM children. + */ +var DOMChildrenOperations = { + + dangerouslyReplaceNodeWithMarkup: Danger.dangerouslyReplaceNodeWithMarkup, + + /** + * Updates a component's children by processing a series of updates. The + * update configurations are each expected to have a `parentNode` property. + * + * @param {array} updates List of update configurations. + * @param {array} markupList List of markup strings. + * @internal + */ + processUpdates: function(updates, markupList) { + var update; + // Mapping from parent IDs to initial child orderings. + var initialChildren = null; + // List of children that will be moved or removed. + var updatedChildren = null; + + for (var i = 0; update = updates[i]; i++) { + if (update.type === ReactMultiChildUpdateTypes.MOVE_EXISTING || + update.type === ReactMultiChildUpdateTypes.REMOVE_NODE) { + var updatedIndex = update.fromIndex; + var updatedChild = update.parentNode.childNodes[updatedIndex]; + var parentID = update.parentID; + + initialChildren = initialChildren || {}; + initialChildren[parentID] = initialChildren[parentID] || []; + initialChildren[parentID][updatedIndex] = updatedChild; + + updatedChildren = updatedChildren || []; + updatedChildren.push(updatedChild); + } + } + + var renderedMarkup = Danger.dangerouslyRenderMarkup(markupList); + + // Remove updated children first so that `toIndex` is consistent. + if (updatedChildren) { + for (var j = 0; j < updatedChildren.length; j++) { + updatedChildren[j].parentNode.removeChild(updatedChildren[j]); + } + } + + for (var k = 0; update = updates[k]; k++) { + switch (update.type) { + case ReactMultiChildUpdateTypes.INSERT_MARKUP: + insertChildAt( + update.parentNode, + renderedMarkup[update.markupIndex], + update.toIndex + ); + break; + case ReactMultiChildUpdateTypes.MOVE_EXISTING: + insertChildAt( + update.parentNode, + initialChildren[update.parentID][update.fromIndex], + update.toIndex + ); + break; + case ReactMultiChildUpdateTypes.TEXT_CONTENT: + update.parentNode[textContentAccessor] = update.textContent; + break; + case ReactMultiChildUpdateTypes.REMOVE_NODE: + // Already removed by the for-loop above. + break; + } + } + } + +}; + +module.exports = DOMChildrenOperations; + +},{"./Danger":11,"./ReactMultiChildUpdateTypes":56,"./getTextContentAccessor":104}],9:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule DOMProperty + * @typechecks static-only + */ + +/*jslint bitwise: true */ + +"use strict"; + +var invariant = require("./invariant"); + +var DOMPropertyInjection = { + /** + * Mapping from normalized, camelcased property names to a configuration that + * specifies how the associated DOM property should be accessed or rendered. + */ + MUST_USE_ATTRIBUTE: 0x1, + MUST_USE_PROPERTY: 0x2, + HAS_BOOLEAN_VALUE: 0x4, + HAS_SIDE_EFFECTS: 0x8, + + /** + * Inject some specialized knowledge about the DOM. This takes a config object + * with the following properties: + * + * isCustomAttribute: function that given an attribute name will return true + * if it can be inserted into the DOM verbatim. Useful for data-* or aria-* + * attributes where it's impossible to enumerate all of the possible + * attribute names, + * + * Properties: object mapping DOM property name to one of the + * DOMPropertyInjection constants or null. If your attribute isn't in here, + * it won't get written to the DOM. + * + * DOMAttributeNames: object mapping React attribute name to the DOM + * attribute name. Attribute names not specified use the **lowercase** + * normalized name. + * + * DOMPropertyNames: similar to DOMAttributeNames but for DOM properties. + * Property names not specified use the normalized name. + * + * DOMMutationMethods: Properties that require special mutation methods. If + * `value` is undefined, the mutation method should unset the property. + * + * @param {object} domPropertyConfig the config as described above. + */ + injectDOMPropertyConfig: function(domPropertyConfig) { + var Properties = domPropertyConfig.Properties || {}; + var DOMAttributeNames = domPropertyConfig.DOMAttributeNames || {}; + var DOMPropertyNames = domPropertyConfig.DOMPropertyNames || {}; + var DOMMutationMethods = domPropertyConfig.DOMMutationMethods || {}; + + if (domPropertyConfig.isCustomAttribute) { + DOMProperty._isCustomAttributeFunctions.push( + domPropertyConfig.isCustomAttribute + ); + } + + for (var propName in Properties) { + invariant( + !DOMProperty.isStandardName[propName], + 'injectDOMPropertyConfig(...): You\'re trying to inject DOM property ' + + '\'%s\' which has already been injected. You may be accidentally ' + + 'injecting the same DOM property config twice, or you may be ' + + 'injecting two configs that have conflicting property names.', + propName + ); + + DOMProperty.isStandardName[propName] = true; + + var lowerCased = propName.toLowerCase(); + DOMProperty.getPossibleStandardName[lowerCased] = propName; + + var attributeName = DOMAttributeNames[propName]; + if (attributeName) { + DOMProperty.getPossibleStandardName[attributeName] = propName; + } + + DOMProperty.getAttributeName[propName] = attributeName || lowerCased; + + DOMProperty.getPropertyName[propName] = + DOMPropertyNames[propName] || propName; + + var mutationMethod = DOMMutationMethods[propName]; + if (mutationMethod) { + DOMProperty.getMutationMethod[propName] = mutationMethod; + } + + var propConfig = Properties[propName]; + DOMProperty.mustUseAttribute[propName] = + propConfig & DOMPropertyInjection.MUST_USE_ATTRIBUTE; + DOMProperty.mustUseProperty[propName] = + propConfig & DOMPropertyInjection.MUST_USE_PROPERTY; + DOMProperty.hasBooleanValue[propName] = + propConfig & DOMPropertyInjection.HAS_BOOLEAN_VALUE; + DOMProperty.hasSideEffects[propName] = + propConfig & DOMPropertyInjection.HAS_SIDE_EFFECTS; + + invariant( + !DOMProperty.mustUseAttribute[propName] || + !DOMProperty.mustUseProperty[propName], + 'DOMProperty: Cannot use require using both attribute and property: %s', + propName + ); + invariant( + DOMProperty.mustUseProperty[propName] || + !DOMProperty.hasSideEffects[propName], + 'DOMProperty: Properties that have side effects must use property: %s', + propName + ); + } + } +}; +var defaultValueCache = {}; + +/** + * DOMProperty exports lookup objects that can be used like functions: + * + * > DOMProperty.isValid['id'] + * true + * > DOMProperty.isValid['foobar'] + * undefined + * + * Although this may be confusing, it performs better in general. + * + * @see http://jsperf.com/key-exists + * @see http://jsperf.com/key-missing + */ +var DOMProperty = { + + /** + * Checks whether a property name is a standard property. + * @type {Object} + */ + isStandardName: {}, + + /** + * Mapping from lowercase property names to the properly cased version, used + * to warn in the case of missing properties. + * @type {Object} + */ + getPossibleStandardName: {}, + + /** + * Mapping from normalized names to attribute names that differ. Attribute + * names are used when rendering markup or with `*Attribute()`. + * @type {Object} + */ + getAttributeName: {}, + + /** + * Mapping from normalized names to properties on DOM node instances. + * (This includes properties that mutate due to external factors.) + * @type {Object} + */ + getPropertyName: {}, + + /** + * Mapping from normalized names to mutation methods. This will only exist if + * mutation cannot be set simply by the property or `setAttribute()`. + * @type {Object} + */ + getMutationMethod: {}, + + /** + * Whether the property must be accessed and mutated as an object property. + * @type {Object} + */ + mustUseAttribute: {}, + + /** + * Whether the property must be accessed and mutated using `*Attribute()`. + * (This includes anything that fails ` in `.) + * @type {Object} + */ + mustUseProperty: {}, + + /** + * Whether the property should be removed when set to a falsey value. + * @type {Object} + */ + hasBooleanValue: {}, + + /** + * Whether or not setting a value causes side effects such as triggering + * resources to be loaded or text selection changes. We must ensure that + * the value is only set if it has changed. + * @type {Object} + */ + hasSideEffects: {}, + + /** + * All of the isCustomAttribute() functions that have been injected. + */ + _isCustomAttributeFunctions: [], + + /** + * Checks whether a property name is a custom attribute. + * @method + */ + isCustomAttribute: function(attributeName) { + return DOMProperty._isCustomAttributeFunctions.some( + function(isCustomAttributeFn) { + return isCustomAttributeFn.call(null, attributeName); + } + ); + }, + + /** + * Returns the default property value for a DOM property (i.e., not an + * attribute). Most default values are '' or false, but not all. Worse yet, + * some (in particular, `type`) vary depending on the type of element. + * + * TODO: Is it better to grab all the possible properties when creating an + * element to avoid having to create the same element twice? + */ + getDefaultValueForProperty: function(nodeName, prop) { + var nodeDefaults = defaultValueCache[nodeName]; + var testElement; + if (!nodeDefaults) { + defaultValueCache[nodeName] = nodeDefaults = {}; + } + if (!(prop in nodeDefaults)) { + testElement = document.createElement(nodeName); + nodeDefaults[prop] = testElement[prop]; + } + return nodeDefaults[prop]; + }, + + injection: DOMPropertyInjection +}; + +module.exports = DOMProperty; + +},{"./invariant":106}],10:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule DOMPropertyOperations + * @typechecks static-only + */ + +"use strict"; + +var DOMProperty = require("./DOMProperty"); + +var escapeTextForBrowser = require("./escapeTextForBrowser"); +var memoizeStringOnly = require("./memoizeStringOnly"); + +var processAttributeNameAndPrefix = memoizeStringOnly(function(name) { + return escapeTextForBrowser(name) + '="'; +}); + +if (true) { + var reactProps = { + __owner__: true, + children: true, + dangerouslySetInnerHTML: true, + key: true, + ref: true + }; + var warnedProperties = {}; + + var warnUnknownProperty = function(name) { + if (reactProps[name] || warnedProperties[name]) { + return; + } + + warnedProperties[name] = true; + var lowerCasedName = name.toLowerCase(); + + // data-* attributes should be lowercase; suggest the lowercase version + var standardName = DOMProperty.isCustomAttribute(lowerCasedName) ? + lowerCasedName : DOMProperty.getPossibleStandardName[lowerCasedName]; + + // For now, only warn when we have a suggested correction. This prevents + // logging too much when using transferPropsTo. + if (standardName != null) { + console.warn( + 'Unknown DOM property ' + name + '. Did you mean ' + standardName + '?' + ); + } + + }; +} + +/** + * Operations for dealing with DOM properties. + */ +var DOMPropertyOperations = { + + /** + * Creates markup for a property. + * + * @param {string} name + * @param {*} value + * @return {?string} Markup string, or null if the property was invalid. + */ + createMarkupForProperty: function(name, value) { + if (DOMProperty.isStandardName[name]) { + if (value == null || DOMProperty.hasBooleanValue[name] && !value) { + return ''; + } + var attributeName = DOMProperty.getAttributeName[name]; + return processAttributeNameAndPrefix(attributeName) + + escapeTextForBrowser(value) + '"'; + } else if (DOMProperty.isCustomAttribute(name)) { + if (value == null) { + return ''; + } + return processAttributeNameAndPrefix(name) + + escapeTextForBrowser(value) + '"'; + } else if (true) { + warnUnknownProperty(name); + } + return null; + }, + + /** + * Sets the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + * @param {*} value + */ + setValueForProperty: function(node, name, value) { + if (DOMProperty.isStandardName[name]) { + var mutationMethod = DOMProperty.getMutationMethod[name]; + if (mutationMethod) { + mutationMethod(node, value); + } else if (DOMProperty.mustUseAttribute[name]) { + if (DOMProperty.hasBooleanValue[name] && !value) { + node.removeAttribute(DOMProperty.getAttributeName[name]); + } else { + node.setAttribute(DOMProperty.getAttributeName[name], '' + value); + } + } else { + var propName = DOMProperty.getPropertyName[name]; + if (!DOMProperty.hasSideEffects[name] || node[propName] !== value) { + node[propName] = value; + } + } + } else if (DOMProperty.isCustomAttribute(name)) { + node.setAttribute(name, '' + value); + } else if (true) { + warnUnknownProperty(name); + } + }, + + /** + * Deletes the value for a property on a node. + * + * @param {DOMElement} node + * @param {string} name + */ + deleteValueForProperty: function(node, name) { + if (DOMProperty.isStandardName[name]) { + var mutationMethod = DOMProperty.getMutationMethod[name]; + if (mutationMethod) { + mutationMethod(node, undefined); + } else if (DOMProperty.mustUseAttribute[name]) { + node.removeAttribute(DOMProperty.getAttributeName[name]); + } else { + var propName = DOMProperty.getPropertyName[name]; + node[propName] = DOMProperty.getDefaultValueForProperty( + node.nodeName, + name + ); + } + } else if (DOMProperty.isCustomAttribute(name)) { + node.removeAttribute(name); + } else if (true) { + warnUnknownProperty(name); + } + } + +}; + +module.exports = DOMPropertyOperations; + +},{"./DOMProperty":9,"./escapeTextForBrowser":93,"./memoizeStringOnly":114}],11:[function(require,module,exports){ +/** + * Copyright 2013 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * @providesModule Danger + * @typechecks static-only + */ + +/*jslint evil: true, sub: true */ + +"use strict"; + +var ExecutionEnvironment = require("./ExecutionEnvironment"); + +var createNodesFromMarkup = require("./createNodesFromMarkup"); +var emptyFunction = require("./emptyFunction"); +var getMarkupWrap = require("./getMarkupWrap"); +var invariant = require("./invariant"); +var mutateHTMLNodeWithMarkup = require("./mutateHTMLNodeWithMarkup"); + +var OPEN_TAG_NAME_EXP = /^(<[^ \/>]+)/; +var RESULT_INDEX_ATTR = 'data-danger-index'; + +/** + * Extracts the `nodeName` from a string of markup. + * + * NOTE: Extracting the `nodeName` does not require a regular expression match + * because we make assumptions about React-generated markup (i.e. there are no + * spaces surrounding the opening tag and there is at least one attribute). + * + * @param {string} markup String of markup. + * @return {string} Node name of the supplied markup. + * @see http://jsperf.com/extract-nodename + */ +function getNodeName(markup) { + return markup.substring(1, markup.indexOf(' ')); +} + +var Danger = { + + /** + * Renders markup into an array of nodes. The markup is expected to render + * into a list of root nodes. Also, the length of `resultList` and + * `markupList` should be the same. + * + * @param {array} markupList List of markup strings to render. + * @return {array} List of rendered nodes. + * @internal + */ + dangerouslyRenderMarkup: function(markupList) { + invariant( + ExecutionEnvironment.canUseDOM, + 'dangerouslyRenderMarkup(...): Cannot render markup in a Worker ' + + 'thread. This is likely a bug in the framework. Please report ' + + 'immediately.' + ); + var nodeName; + var markupByNodeName = {}; + // Group markup by `nodeName` if a wrap is necessary, else by '*'. + for (var i = 0; i < markupList.length; i++) { + invariant( + markupList[i], + 'dangerouslyRenderMarkup(...): Missing markup.' + ); + nodeName = getNodeName(markupList[i]); + nodeName = getMarkupWrap(nodeName) ? nodeName : '*'; + markupByNodeName[nodeName] = markupByNodeName[nodeName] || []; + markupByNodeName[nodeName][i] = markupList[i]; + } + var resultList = []; + var resultListAssignmentCount = 0; + for (nodeName in markupByNodeName) { + if (!markupByNodeName.hasOwnProperty(nodeName)) { + continue; + } + var markupListByNodeName = markupByNodeName[nodeName]; + + // This for-in loop skips the holes of the sparse array. The order of + // iteration should follow the order of assignment, which happens to match + // numerical index order, but we don't rely on that. + for (var resultIndex in markupListByNodeName) { + if (markupListByNodeName.hasOwnProperty(resultIndex)) { + var markup = markupListByNodeName[resultIndex]; + + // Push the requested markup with an additional RESULT_INDEX_ATTR + // attribute. If the markup does not start with a < character, it + // will be discarded below (with an appropriate console.error). + markupListByNodeName[resultIndex] = markup.replace( + OPEN_TAG_NAME_EXP, + // This index will be parsed back out below. + '$1 ' + RESULT_INDEX_ATTR + '="' + resultIndex + '" ' + ); + } + } + + // Render each group of markup with similar wrapping `nodeName`. + var renderNodes = createNodesFromMarkup( + markupListByNodeName.join(''), + emptyFunction // Do nothing special with