text: (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.OmegaPac = f()}})(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);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
  var lookup = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
  
  ;(function (exports) {
  	'use strict';
  
    var Arr = (typeof Uint8Array !== 'undefined')
      ? Uint8Array
      : Array
  
  	var PLUS   = '+'.charCodeAt(0)
  	var SLASH  = '/'.charCodeAt(0)
  	var NUMBER = '0'.charCodeAt(0)
  	var LOWER  = 'a'.charCodeAt(0)
  	var UPPER  = 'A'.charCodeAt(0)
  	var PLUS_URL_SAFE = '-'.charCodeAt(0)
  	var SLASH_URL_SAFE = '_'.charCodeAt(0)
  
  	function decode (elt) {
  		var code = elt.charCodeAt(0)
  		if (code === PLUS ||
  		    code === PLUS_URL_SAFE)
  			return 62 // '+'
  		if (code === SLASH ||
  		    code === SLASH_URL_SAFE)
  			return 63 // '/'
  		if (code < NUMBER)
  			return -1 //no match
  		if (code < NUMBER + 10)
  			return code - NUMBER + 26 + 26
  		if (code < UPPER + 26)
  			return code - UPPER
  		if (code < LOWER + 26)
  			return code - LOWER + 26
  	}
  
  	function b64ToByteArray (b64) {
  		var i, j, l, tmp, placeHolders, arr
  
  		if (b64.length % 4 > 0) {
  			throw new Error('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
  		var len = b64.length
  		placeHolders = '=' === b64.charAt(len - 2) ? 2 : '=' === b64.charAt(len - 1) ? 1 : 0
  
  		// base64 is 4/3 + up to two characters of the original data
  		arr = new Arr(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
  
  		var L = 0
  
  		function push (v) {
  			arr[L++] = v
  		}
  
  		for (i = 0, j = 0; i < l; i += 4, j += 3) {
  			tmp = (decode(b64.charAt(i)) << 18) | (decode(b64.charAt(i + 1)) << 12) | (decode(b64.charAt(i + 2)) << 6) | decode(b64.charAt(i + 3))
  			push((tmp & 0xFF0000) >> 16)
  			push((tmp & 0xFF00) >> 8)
  			push(tmp & 0xFF)
  		}
  
  		if (placeHolders === 2) {
  			tmp = (decode(b64.charAt(i)) << 2) | (decode(b64.charAt(i + 1)) >> 4)
  			push(tmp & 0xFF)
  		} else if (placeHolders === 1) {
  			tmp = (decode(b64.charAt(i)) << 10) | (decode(b64.charAt(i + 1)) << 4) | (decode(b64.charAt(i + 2)) >> 2)
  			push((tmp >> 8) & 0xFF)
  			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 encode (num) {
  			return lookup.charAt(num)
  		}
  
  		function tripletToBase64 (num) {
  			return encode(num >> 18 & 0x3F) + encode(num >> 12 & 0x3F) + encode(num >> 6 & 0x3F) + encode(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 += encode(temp >> 2)
  				output += encode((temp << 4) & 0x3F)
  				output += '=='
  				break
  			case 2:
  				temp = (uint8[uint8.length - 2] << 8) + (uint8[uint8.length - 1])
  				output += encode(temp >> 10)
  				output += encode((temp >> 4) & 0x3F)
  				output += encode((temp << 2) & 0x3F)
  				output += '='
  				break
  		}
  
  		return output
  	}
  
  	exports.toByteArray = b64ToByteArray
  	exports.fromByteArray = uint8ToBase64
  }(typeof exports === 'undefined' ? (this.base64js = {}) : exports))
  
  },{}],2:[function(require,module,exports){
  (function (global){
  /*!
   * The buffer module from node.js, for the browser.
   *
   * @author   Feross Aboukhadijeh <http://feross.org>
   * @license  MIT
   */
  /* eslint-disable no-proto */
  
  'use strict'
  
  var base64 = require('base64-js')
  var ieee754 = require('ieee754')
  var isArray = require('isarray')
  
  exports.Buffer = Buffer
  exports.SlowBuffer = SlowBuffer
  exports.INSPECT_MAX_BYTES = 50
  Buffer.poolSize = 8192 // not used by this implementation
  
  var rootParent = {}
  
  /**
   * If `Buffer.TYPED_ARRAY_SUPPORT`:
   *   === true    Use Uint8Array implementation (fastest)
   *   === false   Use Object implementation (most compatible, even IE6)
   *
   * Browsers that support typed arrays are IE 10+, Firefox 4+, Chrome 7+, Safari 5.1+,
   * Opera 11.6+, iOS 4.2+.
   *
   * Due to various browser bugs, sometimes the Object implementation will be used even
   * when the browser supports typed arrays.
   *
   * Note:
   *
   *   - Firefox 4-29 lacks support for adding new properties to `Uint8Array` instances,
   *     See: https://bugzilla.mozilla.org/show_bug.cgi?id=695438.
   *
   *   - Safari 5-7 lacks support for changing the `Object.prototype.constructor` property
   *     on objects.
   *
   *   - Chrome 9-10 is missing the `TypedArray.prototype.subarray` function.
   *
   *   - IE10 has a broken `TypedArray.prototype.subarray` function which returns arrays of
   *     incorrect length in some situations.
  
   * We detect these buggy browsers and set `Buffer.TYPED_ARRAY_SUPPORT` to `false` so they
   * get the Object implementation, which is slower but behaves correctly.
   */
  Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined
    ? global.TYPED_ARRAY_SUPPORT
    : typedArraySupport()
  
  function typedArraySupport () {
    function Bar () {}
    try {
      var arr = new Uint8Array(1)
      arr.foo = function () { return 42 }
      arr.constructor = Bar
      return arr.foo() === 42 && // typed array instances can be augmented
          arr.constructor === Bar && // constructor can be set
          typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray`
          arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray`
    } catch (e) {
      return false
    }
  }
  
  function kMaxLength () {
    return Buffer.TYPED_ARRAY_SUPPORT
      ? 0x7fffffff
      : 0x3fffffff
  }
  
  /**
   * Class: Buffer
   * =============
   *
   * The Buffer constructor returns instances of `Uint8Array` that are augmented
   * with function properties for all the node `Buffer` API functions. We use
   * `Uint8Array` so that square bracket notation works as expected -- it returns
   * a single octet.
   *
   * By augmenting the instances, we can avoid modifying the `Uint8Array`
   * prototype.
   */
  function Buffer (arg) {
    if (!(this instanceof Buffer)) {
      // Avoid going through an ArgumentsAdaptorTrampoline in the common case.
      if (arguments.length > 1) return new Buffer(arg, arguments[1])
      return new Buffer(arg)
    }
  
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      this.length = 0
      this.parent = undefined
    }
  
    // Common case.
    if (typeof arg === 'number') {
      return fromNumber(this, arg)
    }
  
    // Slightly less common case.
    if (typeof arg === 'string') {
      return fromString(this, arg, arguments.length > 1 ? arguments[1] : 'utf8')
    }
  
    // Unusual.
    return fromObject(this, arg)
  }
  
  function fromNumber (that, length) {
    that = allocate(that, length < 0 ? 0 : checked(length) | 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) {
      for (var i = 0; i < length; i++) {
        that[i] = 0
      }
    }
    return that
  }
  
  function fromString (that, string, encoding) {
    if (typeof encoding !== 'string' || encoding === '') encoding = 'utf8'
  
    // Assumption: byteLength() return value is always < kMaxLength.
    var length = byteLength(string, encoding) | 0
    that = allocate(that, length)
  
    that.write(string, encoding)
    return that
  }
  
  function fromObject (that, object) {
    if (Buffer.isBuffer(object)) return fromBuffer(that, object)
  
    if (isArray(object)) return fromArray(that, object)
  
    if (object == null) {
      throw new TypeError('must start with number, buffer, array or string')
    }
  
    if (typeof ArrayBuffer !== 'undefined') {
      if (object.buffer instanceof ArrayBuffer) {
        return fromTypedArray(that, object)
      }
      if (object instanceof ArrayBuffer) {
        return fromArrayBuffer(that, object)
      }
    }
  
    if (object.length) return fromArrayLike(that, object)
  
    return fromJsonObject(that, object)
  }
  
  function fromBuffer (that, buffer) {
    var length = checked(buffer.length) | 0
    that = allocate(that, length)
    buffer.copy(that, 0, 0, length)
    return that
  }
  
  function fromArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Duplicate of fromArray() to keep fromArray() monomorphic.
  function fromTypedArray (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    // Truncating the elements is probably not what people expect from typed
    // arrays with BYTES_PER_ELEMENT > 1 but it's compatible with the behavior
    // of the old Buffer constructor.
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  function fromArrayBuffer (that, array) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      array.byteLength
      that = Buffer._augment(new Uint8Array(array))
    } else {
      // Fallback: Return an object instance of the Buffer class
      that = fromTypedArray(that, new Uint8Array(array))
    }
    return that
  }
  
  function fromArrayLike (that, array) {
    var length = checked(array.length) | 0
    that = allocate(that, length)
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  // Deserialize { type: 'Buffer', data: [1,2,3,...] } into a Buffer object.
  // Returns a zero-length buffer for inputs that don't conform to the spec.
  function fromJsonObject (that, object) {
    var array
    var length = 0
  
    if (object.type === 'Buffer' && isArray(object.data)) {
      array = object.data
      length = checked(array.length) | 0
    }
    that = allocate(that, length)
  
    for (var i = 0; i < length; i += 1) {
      that[i] = array[i] & 255
    }
    return that
  }
  
  if (Buffer.TYPED_ARRAY_SUPPORT) {
    Buffer.prototype.__proto__ = Uint8Array.prototype
    Buffer.__proto__ = Uint8Array
  } else {
    // pre-set for values that may exist in the future
    Buffer.prototype.length = undefined
    Buffer.prototype.parent = undefined
  }
  
  function allocate (that, length) {
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      // Return an augmented `Uint8Array` instance, for best performance
      that = Buffer._augment(new Uint8Array(length))
      that.__proto__ = Buffer.prototype
    } else {
      // Fallback: Return an object instance of the Buffer class
      that.length = length
      that._isBuffer = true
    }
  
    var fromPool = length !== 0 && length <= Buffer.poolSize >>> 1
    if (fromPool) that.parent = rootParent
  
    return that
  }
  
  function checked (length) {
    // Note: cannot use `length < kMaxLength` here because that fails when
    // length is NaN (which is otherwise coerced to zero.)
    if (length >= kMaxLength()) {
      throw new RangeError('Attempt to allocate Buffer larger than maximum ' +
                           'size: 0x' + kMaxLength().toString(16) + ' bytes')
    }
    return length | 0
  }
  
  function SlowBuffer (subject, encoding) {
    if (!(this instanceof SlowBuffer)) return new SlowBuffer(subject, encoding)
  
    var buf = new Buffer(subject, encoding)
    delete buf.parent
    return buf
  }
  
  Buffer.isBuffer = function isBuffer (b) {
    return !!(b != null && b._isBuffer)
  }
  
  Buffer.compare = function compare (a, b) {
    if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) {
      throw new TypeError('Arguments must be Buffers')
    }
  
    if (a === b) return 0
  
    var x = a.length
    var y = b.length
  
    var i = 0
    var len = Math.min(x, y)
    while (i < len) {
      if (a[i] !== b[i]) break
  
      ++i
    }
  
    if (i !== len) {
      x = a[i]
      y = b[i]
    }
  
    if (x < y) return -1
    if (y < x) return 1
    return 0
  }
  
  Buffer.isEncoding = function isEncoding (encoding) {
    switch (String(encoding).toLowerCase()) {
      case 'hex':
      case 'utf8':
      case 'utf-8':
      case 'ascii':
      case 'binary':
      case 'base64':
      case 'raw':
      case 'ucs2':
      case 'ucs-2':
      case 'utf16le':
      case 'utf-16le':
        return true
      default:
        return false
    }
  }
  
  Buffer.concat = function concat (list, length) {
    if (!isArray(list)) throw new TypeError('list argument must be an Array of Buffers.')
  
    if (list.length === 0) {
      return new Buffer(0)
    }
  
    var i
    if (length === undefined) {
      length = 0
      for (i = 0; i < list.length; i++) {
        length += list[i].length
      }
    }
  
    var buf = new Buffer(length)
    var pos = 0
    for (i = 0; i < list.length; i++) {
      var item = list[i]
      item.copy(buf, pos)
      pos += item.length
    }
    return buf
  }
  
  function byteLength (string, encoding) {
    if (typeof string !== 'string') string = '' + string
  
    var len = string.length
    if (len === 0) return 0
  
    // Use a for loop to avoid recursion
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'ascii':
        case 'binary':
        // Deprecated
        case 'raw':
        case 'raws':
          return len
        case 'utf8':
        case 'utf-8':
          return utf8ToBytes(string).length
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return len * 2
        case 'hex':
          return len >>> 1
        case 'base64':
          return base64ToBytes(string).length
        default:
          if (loweredCase) return utf8ToBytes(string).length // assume utf8
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  Buffer.byteLength = byteLength
  
  function slowToString (encoding, start, end) {
    var loweredCase = false
  
    start = start | 0
    end = end === undefined || end === Infinity ? this.length : end | 0
  
    if (!encoding) encoding = 'utf8'
    if (start < 0) start = 0
    if (end > this.length) end = this.length
    if (end <= start) return ''
  
    while (true) {
      switch (encoding) {
        case 'hex':
          return hexSlice(this, start, end)
  
        case 'utf8':
        case 'utf-8':
          return utf8Slice(this, start, end)
  
        case 'ascii':
          return asciiSlice(this, start, end)
  
        case 'binary':
          return binarySlice(this, start, end)
  
        case 'base64':
          return base64Slice(this, start, end)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return utf16leSlice(this, start, end)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = (encoding + '').toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toString = function toString () {
    var length = this.length | 0
    if (length === 0) return ''
    if (arguments.length === 0) return utf8Slice(this, 0, length)
    return slowToString.apply(this, arguments)
  }
  
  Buffer.prototype.equals = function equals (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return true
    return Buffer.compare(this, b) === 0
  }
  
  Buffer.prototype.inspect = function inspect () {
    var str = ''
    var max = exports.INSPECT_MAX_BYTES
    if (this.length > 0) {
      str = this.toString('hex', 0, max).match(/.{2}/g).join(' ')
      if (this.length > max) str += ' ... '
    }
    return '<Buffer ' + str + '>'
  }
  
  Buffer.prototype.compare = function compare (b) {
    if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer')
    if (this === b) return 0
    return Buffer.compare(this, b)
  }
  
  Buffer.prototype.indexOf = function indexOf (val, byteOffset) {
    if (byteOffset > 0x7fffffff) byteOffset = 0x7fffffff
    else if (byteOffset < -0x80000000) byteOffset = -0x80000000
    byteOffset >>= 0
  
    if (this.length === 0) return -1
    if (byteOffset >= this.length) return -1
  
    // Negative offsets start from the end of the buffer
    if (byteOffset < 0) byteOffset = Math.max(this.length + byteOffset, 0)
  
    if (typeof val === 'string') {
      if (val.length === 0) return -1 // special case: looking for empty string always fails
      return String.prototype.indexOf.call(this, val, byteOffset)
    }
    if (Buffer.isBuffer(val)) {
      return arrayIndexOf(this, val, byteOffset)
    }
    if (typeof val === 'number') {
      if (Buffer.TYPED_ARRAY_SUPPORT && Uint8Array.prototype.indexOf === 'function') {
        return Uint8Array.prototype.indexOf.call(this, val, byteOffset)
      }
      return arrayIndexOf(this, [ val ], byteOffset)
    }
  
    function arrayIndexOf (arr, val, byteOffset) {
      var foundIndex = -1
      for (var i = 0; byteOffset + i < arr.length; i++) {
        if (arr[byteOffset + i] === val[foundIndex === -1 ? 0 : i - foundIndex]) {
          if (foundIndex === -1) foundIndex = i
          if (i - foundIndex + 1 === val.length) return byteOffset + foundIndex
        } else {
          foundIndex = -1
        }
      }
      return -1
    }
  
    throw new TypeError('val must be string, number or Buffer')
  }
  
  // `get` is deprecated
  Buffer.prototype.get = function get (offset) {
    console.log('.get() is deprecated. Access using array indexes instead.')
    return this.readUInt8(offset)
  }
  
  // `set` is deprecated
  Buffer.prototype.set = function set (v, offset) {
    console.log('.set() is deprecated. Access using array indexes instead.')
    return this.writeUInt8(v, offset)
  }
  
  function hexWrite (buf, string, offset, length) {
    offset = Number(offset) || 0
    var remaining = buf.length - offset
    if (!length) {
      length = remaining
    } else {
      length = Number(length)
      if (length > remaining) {
        length = remaining
      }
    }
  
    // must be an even number of digits
    var strLen = string.length
    if (strLen % 2 !== 0) throw new Error('Invalid hex string')
  
    if (length > strLen / 2) {
      length = strLen / 2
    }
    for (var i = 0; i < length; i++) {
      var parsed = parseInt(string.substr(i * 2, 2), 16)
      if (isNaN(parsed)) throw new Error('Invalid hex string')
      buf[offset + i] = parsed
    }
    return i
  }
  
  function utf8Write (buf, string, offset, length) {
    return blitBuffer(utf8ToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  function asciiWrite (buf, string, offset, length) {
    return blitBuffer(asciiToBytes(string), buf, offset, length)
  }
  
  function binaryWrite (buf, string, offset, length) {
    return asciiWrite(buf, string, offset, length)
  }
  
  function base64Write (buf, string, offset, length) {
    return blitBuffer(base64ToBytes(string), buf, offset, length)
  }
  
  function ucs2Write (buf, string, offset, length) {
    return blitBuffer(utf16leToBytes(string, buf.length - offset), buf, offset, length)
  }
  
  Buffer.prototype.write = function write (string, offset, length, encoding) {
    // Buffer#write(string)
    if (offset === undefined) {
      encoding = 'utf8'
      length = this.length
      offset = 0
    // Buffer#write(string, encoding)
    } else if (length === undefined && typeof offset === 'string') {
      encoding = offset
      length = this.length
      offset = 0
    // Buffer#write(string, offset[, length][, encoding])
    } else if (isFinite(offset)) {
      offset = offset | 0
      if (isFinite(length)) {
        length = length | 0
        if (encoding === undefined) encoding = 'utf8'
      } else {
        encoding = length
        length = undefined
      }
    // legacy write(string, encoding, offset, length) - remove in v0.13
    } else {
      var swap = encoding
      encoding = offset
      offset = length | 0
      length = swap
    }
  
    var remaining = this.length - offset
    if (length === undefined || length > remaining) length = remaining
  
    if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) {
      throw new RangeError('attempt to write outside buffer bounds')
    }
  
    if (!encoding) encoding = 'utf8'
  
    var loweredCase = false
    for (;;) {
      switch (encoding) {
        case 'hex':
          return hexWrite(this, string, offset, length)
  
        case 'utf8':
        case 'utf-8':
          return utf8Write(this, string, offset, length)
  
        case 'ascii':
          return asciiWrite(this, string, offset, length)
  
        case 'binary':
          return binaryWrite(this, string, offset, length)
  
        case 'base64':
          // Warning: maxLength not taken into account in base64Write
          return base64Write(this, string, offset, length)
  
        case 'ucs2':
        case 'ucs-2':
        case 'utf16le':
        case 'utf-16le':
          return ucs2Write(this, string, offset, length)
  
        default:
          if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding)
          encoding = ('' + encoding).toLowerCase()
          loweredCase = true
      }
    }
  }
  
  Buffer.prototype.toJSON = function toJSON () {
    return {
      type: 'Buffer',
      data: Array.prototype.slice.call(this._arr || this, 0)
    }
  }
  
  function base64Slice (buf, start, end) {
    if (start === 0 && end === buf.length) {
      return base64.fromByteArray(buf)
    } else {
      return base64.fromByteArray(buf.slice(start, end))
    }
  }
  
  function utf8Slice (buf, start, end) {
    end = Math.min(buf.length, end)
    var res = []
  
    var i = start
    while (i < end) {
      var firstByte = buf[i]
      var codePoint = null
      var bytesPerSequence = (firstByte > 0xEF) ? 4
        : (firstByte > 0xDF) ? 3
        : (firstByte > 0xBF) ? 2
        : 1
  
      if (i + bytesPerSequence <= end) {
        var secondByte, thirdByte, fourthByte, tempCodePoint
  
        switch (bytesPerSequence) {
          case 1:
            if (firstByte < 0x80) {
              codePoint = firstByte
            }
            break
          case 2:
            secondByte = buf[i + 1]
            if ((secondByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F)
              if (tempCodePoint > 0x7F) {
                codePoint = tempCodePoint
              }
            }
            break
          case 3:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F)
              if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) {
                codePoint = tempCodePoint
              }
            }
            break
          case 4:
            secondByte = buf[i + 1]
            thirdByte = buf[i + 2]
            fourthByte = buf[i + 3]
            if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) {
              tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F)
              if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) {
                codePoint = tempCodePoint
              }
            }
        }
      }
  
      if (codePoint === null) {
        // we did not generate a valid codePoint so insert a
        // replacement char (U+FFFD) and advance only 1 byte
        codePoint = 0xFFFD
        bytesPerSequence = 1
      } else if (codePoint > 0xFFFF) {
        // encode to utf16 (surrogate pair dance)
        codePoint -= 0x10000
        res.push(codePoint >>> 10 & 0x3FF | 0xD800)
        codePoint = 0xDC00 | codePoint & 0x3FF
      }
  
      res.push(codePoint)
      i += bytesPerSequence
    }
  
    return decodeCodePointsArray(res)
  }
  
  // Based on http://stackoverflow.com/a/22747272/680742, the browser with
  // the lowest limit is Chrome, with 0x10000 args.
  // We go 1 magnitude less, for safety
  var MAX_ARGUMENTS_LENGTH = 0x1000
  
  function decodeCodePointsArray (codePoints) {
    var len = codePoints.length
    if (len <= MAX_ARGUMENTS_LENGTH) {
      return String.fromCharCode.apply(String, codePoints) // avoid extra slice()
    }
  
    // Decode in chunks to avoid "call stack size exceeded".
    var res = ''
    var i = 0
    while (i < len) {
      res += String.fromCharCode.apply(
        String,
        codePoints.slice(i, i += MAX_ARGUMENTS_LENGTH)
      )
    }
    return res
  }
  
  function asciiSlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i] & 0x7F)
    }
    return ret
  }
  
  function binarySlice (buf, start, end) {
    var ret = ''
    end = Math.min(buf.length, end)
  
    for (var i = start; i < end; i++) {
      ret += String.fromCharCode(buf[i])
    }
    return ret
  }
  
  function hexSlice (buf, start, end) {
    var len = buf.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(buf[i])
    }
    return out
  }
  
  function utf16leSlice (buf, start, end) {
    var bytes = buf.slice(start, end)
    var res = ''
    for (var i = 0; i < bytes.length; i += 2) {
      res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256)
    }
    return res
  }
  
  Buffer.prototype.slice = function slice (start, end) {
    var len = this.length
    start = ~~start
    end = end === undefined ? len : ~~end
  
    if (start < 0) {
      start += len
      if (start < 0) start = 0
    } else if (start > len) {
      start = len
    }
  
    if (end < 0) {
      end += len
      if (end < 0) end = 0
    } else if (end > len) {
      end = len
    }
  
    if (end < start) end = start
  
    var newBuf
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      newBuf = Buffer._augment(this.subarray(start, end))
    } else {
      var sliceLen = end - start
      newBuf = new Buffer(sliceLen, undefined)
      for (var i = 0; i < sliceLen; i++) {
        newBuf[i] = this[i + start]
      }
    }
  
    if (newBuf.length) newBuf.parent = this.parent || this
  
    return newBuf
  }
  
  /*
   * Need to make sure that buffer isn't trying to write out of bounds.
   */
  function checkOffset (offset, ext, length) {
    if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint')
    if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length')
  }
  
  Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) {
      checkOffset(offset, byteLength, this.length)
    }
  
    var val = this[offset + --byteLength]
    var mul = 1
    while (byteLength > 0 && (mul *= 0x100)) {
      val += this[offset + --byteLength] * mul
    }
  
    return val
  }
  
  Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    return this[offset]
  }
  
  Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return this[offset] | (this[offset + 1] << 8)
  }
  
  Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    return (this[offset] << 8) | this[offset + 1]
  }
  
  Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return ((this[offset]) |
        (this[offset + 1] << 8) |
        (this[offset + 2] << 16)) +
        (this[offset + 3] * 0x1000000)
  }
  
  Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] * 0x1000000) +
      ((this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      this[offset + 3])
  }
  
  Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var val = this[offset]
    var mul = 1
    var i = 0
    while (++i < byteLength && (mul *= 0x100)) {
      val += this[offset + i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) {
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkOffset(offset, byteLength, this.length)
  
    var i = byteLength
    var mul = 1
    var val = this[offset + --i]
    while (i > 0 && (mul *= 0x100)) {
      val += this[offset + --i] * mul
    }
    mul *= 0x80
  
    if (val >= mul) val -= Math.pow(2, 8 * byteLength)
  
    return val
  }
  
  Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 1, this.length)
    if (!(this[offset] & 0x80)) return (this[offset])
    return ((0xff - this[offset] + 1) * -1)
  }
  
  Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset] | (this[offset + 1] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 2, this.length)
    var val = this[offset + 1] | (this[offset] << 8)
    return (val & 0x8000) ? val | 0xFFFF0000 : val
  }
  
  Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset]) |
      (this[offset + 1] << 8) |
      (this[offset + 2] << 16) |
      (this[offset + 3] << 24)
  }
  
  Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
  
    return (this[offset] << 24) |
      (this[offset + 1] << 16) |
      (this[offset + 2] << 8) |
      (this[offset + 3])
  }
  
  Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, true, 23, 4)
  }
  
  Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 4, this.length)
    return ieee754.read(this, offset, false, 23, 4)
  }
  
  Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, true, 52, 8)
  }
  
  Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) {
    if (!noAssert) checkOffset(offset, 8, this.length)
    return ieee754.read(this, offset, false, 52, 8)
  }
  
  function checkInt (buf, value, offset, ext, max, min) {
    if (!Buffer.isBuffer(buf)) throw new TypeError('buffer must be a Buffer instance')
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
  }
  
  Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var mul = 1
    var i = 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    byteLength = byteLength | 0
    if (!noAssert) checkInt(this, value, offset, byteLength, Math.pow(2, 8 * byteLength), 0)
  
    var i = byteLength - 1
    var mul = 1
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = (value / mul) & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  function objectWriteUInt16 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; i++) {
      buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>>
        (littleEndian ? i : 1 - i) * 8
    }
  }
  
  Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  function objectWriteUInt32 (buf, value, offset, littleEndian) {
    if (value < 0) value = 0xffffffff + value + 1
    for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; i++) {
      buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff
    }
  }
  
  Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset + 3] = (value >>> 24)
      this[offset + 2] = (value >>> 16)
      this[offset + 1] = (value >>> 8)
      this[offset] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = 0
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset] = value & 0xFF
    while (++i < byteLength && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) {
      var limit = Math.pow(2, 8 * byteLength - 1)
  
      checkInt(this, value, offset, byteLength, limit - 1, -limit)
    }
  
    var i = byteLength - 1
    var mul = 1
    var sub = value < 0 ? 1 : 0
    this[offset + i] = value & 0xFF
    while (--i >= 0 && (mul *= 0x100)) {
      this[offset + i] = ((value / mul) >> 0) - sub & 0xFF
    }
  
    return offset + byteLength
  }
  
  Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80)
    if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value)
    if (value < 0) value = 0xff + value + 1
    this[offset] = (value & 0xff)
    return offset + 1
  }
  
  Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
    } else {
      objectWriteUInt16(this, value, offset, true)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 8)
      this[offset + 1] = (value & 0xff)
    } else {
      objectWriteUInt16(this, value, offset, false)
    }
    return offset + 2
  }
  
  Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value & 0xff)
      this[offset + 1] = (value >>> 8)
      this[offset + 2] = (value >>> 16)
      this[offset + 3] = (value >>> 24)
    } else {
      objectWriteUInt32(this, value, offset, true)
    }
    return offset + 4
  }
  
  Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) {
    value = +value
    offset = offset | 0
    if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000)
    if (value < 0) value = 0xffffffff + value + 1
    if (Buffer.TYPED_ARRAY_SUPPORT) {
      this[offset] = (value >>> 24)
      this[offset + 1] = (value >>> 16)
      this[offset + 2] = (value >>> 8)
      this[offset + 3] = (value & 0xff)
    } else {
      objectWriteUInt32(this, value, offset, false)
    }
    return offset + 4
  }
  
  function checkIEEE754 (buf, value, offset, ext, max, min) {
    if (value > max || value < min) throw new RangeError('value is out of bounds')
    if (offset + ext > buf.length) throw new RangeError('index out of range')
    if (offset < 0) throw new RangeError('index out of range')
  }
  
  function writeFloat (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38)
    }
    ieee754.write(buf, value, offset, littleEndian, 23, 4)
    return offset + 4
  }
  
  Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) {
    return writeFloat(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) {
    return writeFloat(this, value, offset, false, noAssert)
  }
  
  function writeDouble (buf, value, offset, littleEndian, noAssert) {
    if (!noAssert) {
      checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308)
    }
    ieee754.write(buf, value, offset, littleEndian, 52, 8)
    return offset + 8
  }
  
  Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) {
    return writeDouble(this, value, offset, true, noAssert)
  }
  
  Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) {
    return writeDouble(this, value, offset, false, noAssert)
  }
  
  // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length)
  Buffer.prototype.copy = function copy (target, targetStart, start, end) {
    if (!start) start = 0
    if (!end && end !== 0) end = this.length
    if (targetStart >= target.length) targetStart = target.length
    if (!targetStart) targetStart = 0
    if (end > 0 && end < start) end = start
  
    // Copy 0 bytes; we're done
    if (end === start) return 0
    if (target.length === 0 || this.length === 0) return 0
  
    // Fatal error conditions
    if (targetStart < 0) {
      throw new RangeError('targetStart out of bounds')
    }
    if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds')
    if (end < 0) throw new RangeError('sourceEnd out of bounds')
  
    // Are we oob?
    if (end > this.length) end = this.length
    if (target.length - targetStart < end - start) {
      end = target.length - targetStart + start
    }
  
    var len = end - start
    var i
  
    if (this === target && start < targetStart && targetStart < end) {
      // descending copy from end
      for (i = len - 1; i >= 0; i--) {
        target[i + targetStart] = this[i + start]
      }
    } else if (len < 1000 || !Buffer.TYPED_ARRAY_SUPPORT) {
      // ascending copy from start
      for (i = 0; i < len; i++) {
        target[i + targetStart] = this[i + start]
      }
    } else {
      target._set(this.subarray(start, start + len), targetStart)
    }
  
    return len
  }
  
  // fill(value, start=0, end=buffer.length)
  Buffer.prototype.fill = function fill (value, start, end) {
    if (!value) value = 0
    if (!start) start = 0
    if (!end) end = this.length
  
    if (end < start) throw new RangeError('end < start')
  
    // Fill 0 bytes; we're done
    if (end === start) return
    if (this.length === 0) return
  
    if (start < 0 || start >= this.length) throw new RangeError('start out of bounds')
    if (end < 0 || end > this.length) throw new RangeError('end out of bounds')
  
    var i
    if (typeof value === 'number') {
      for (i = start; i < end; i++) {
        this[i] = value
      }
    } else {
      var bytes = utf8ToBytes(value.toString())
      var len = bytes.length
      for (i = start; i < end; i++) {
        this[i] = bytes[i % len]
      }
    }
  
    return this
  }
  
  /**
   * Creates a new `ArrayBuffer` with the *copied* memory of the buffer instance.
   * Added in Node 0.12. Only available in browsers that support ArrayBuffer.
   */
  Buffer.prototype.toArrayBuffer = function toArrayBuffer () {
    if (typeof Uint8Array !== 'undefined') {
      if (Buffer.TYPED_ARRAY_SUPPORT) {
        return (new Buffer(this)).buffer
      } else {
        var buf = new Uint8Array(this.length)
        for (var i = 0, len = buf.length; i < len; i += 1) {
          buf[i] = this[i]
        }
        return buf.buffer
      }
    } else {
      throw new TypeError('Buffer.toArrayBuffer not supported in this browser')
    }
  }
  
  // HELPER FUNCTIONS
  // ================
  
  var BP = Buffer.prototype
  
  /**
   * Augment a Uint8Array *instance* (not the Uint8Array class!) with Buffer methods
   */
  Buffer._augment = function _augment (arr) {
    arr.constructor = Buffer
    arr._isBuffer = true
  
    // save reference to original Uint8Array set method before overwriting
    arr._set = arr.set
  
    // deprecated
    arr.get = BP.get
    arr.set = BP.set
  
    arr.write = BP.write
    arr.toString = BP.toString
    arr.toLocaleString = BP.toString
    arr.toJSON = BP.toJSON
    arr.equals = BP.equals
    arr.compare = BP.compare
    arr.indexOf = BP.indexOf
    arr.copy = BP.copy
    arr.slice = BP.slice
    arr.readUIntLE = BP.readUIntLE
    arr.readUIntBE = BP.readUIntBE
    arr.readUInt8 = BP.readUInt8
    arr.readUInt16LE = BP.readUInt16LE
    arr.readUInt16BE = BP.readUInt16BE
    arr.readUInt32LE = BP.readUInt32LE
    arr.readUInt32BE = BP.readUInt32BE
    arr.readIntLE = BP.readIntLE
    arr.readIntBE = BP.readIntBE
    arr.readInt8 = BP.readInt8
    arr.readInt16LE = BP.readInt16LE
    arr.readInt16BE = BP.readInt16BE
    arr.readInt32LE = BP.readInt32LE
    arr.readInt32BE = BP.readInt32BE
    arr.readFloatLE = BP.readFloatLE
    arr.readFloatBE = BP.readFloatBE
    arr.readDoubleLE = BP.readDoubleLE
    arr.readDoubleBE = BP.readDoubleBE
    arr.writeUInt8 = BP.writeUInt8
    arr.writeUIntLE = BP.writeUIntLE
    arr.writeUIntBE = BP.writeUIntBE
    arr.writeUInt16LE = BP.writeUInt16LE
    arr.writeUInt16BE = BP.writeUInt16BE
    arr.writeUInt32LE = BP.writeUInt32LE
    arr.writeUInt32BE = BP.writeUInt32BE
    arr.writeIntLE = BP.writeIntLE
    arr.writeIntBE = BP.writeIntBE
    arr.writeInt8 = BP.writeInt8
    arr.writeInt16LE = BP.writeInt16LE
    arr.writeInt16BE = BP.writeInt16BE
    arr.writeInt32LE = BP.writeInt32LE
    arr.writeInt32BE = BP.writeInt32BE
    arr.writeFloatLE = BP.writeFloatLE
    arr.writeFloatBE = BP.writeFloatBE
    arr.writeDoubleLE = BP.writeDoubleLE
    arr.writeDoubleBE = BP.writeDoubleBE
    arr.fill = BP.fill
    arr.inspect = BP.inspect
    arr.toArrayBuffer = BP.toArrayBuffer
  
    return arr
  }
  
  var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g
  
  function base64clean (str) {
    // Node strips out invalid characters like \n and \t from the string, base64-js does not
    str = stringtrim(str).replace(INVALID_BASE64_RE, '')
    // Node converts strings with length < 2 to ''
    if (str.length < 2) return ''
    // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not
    while (str.length % 4 !== 0) {
      str = str + '='
    }
    return str
  }
  
  function stringtrim (str) {
    if (str.trim) return str.trim()
    return str.replace(/^\s+|\s+$/g, '')
  }
  
  function toHex (n) {
    if (n < 16) return '0' + n.toString(16)
    return n.toString(16)
  }
  
  function utf8ToBytes (string, units) {
    units = units || Infinity
    var codePoint
    var length = string.length
    var leadSurrogate = null
    var bytes = []
  
    for (var i = 0; i < length; i++) {
      codePoint = string.charCodeAt(i)
  
      // is surrogate component
      if (codePoint > 0xD7FF && codePoint < 0xE000) {
        // last char was a lead
        if (!leadSurrogate) {
          // no lead yet
          if (codePoint > 0xDBFF) {
            // unexpected trail
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          } else if (i + 1 === length) {
            // unpaired lead
            if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
            continue
          }
  
          // valid lead
          leadSurrogate = codePoint
  
          continue
        }
  
        // 2 leads in a row
        if (codePoint < 0xDC00) {
          if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
          leadSurrogate = codePoint
          continue
        }
  
        // valid surrogate pair
        codePoint = (leadSurrogate - 0xD800 << 10 | codePoint - 0xDC00) + 0x10000
      } else if (leadSurrogate) {
        // valid bmp char, but last char was a lead
        if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD)
      }
  
      leadSurrogate = null
  
      // encode utf8
      if (codePoint < 0x80) {
        if ((units -= 1) < 0) break
        bytes.push(codePoint)
      } else if (codePoint < 0x800) {
        if ((units -= 2) < 0) break
        bytes.push(
          codePoint >> 0x6 | 0xC0,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x10000) {
        if ((units -= 3) < 0) break
        bytes.push(
          codePoint >> 0xC | 0xE0,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else if (codePoint < 0x110000) {
        if ((units -= 4) < 0) break
        bytes.push(
          codePoint >> 0x12 | 0xF0,
          codePoint >> 0xC & 0x3F | 0x80,
          codePoint >> 0x6 & 0x3F | 0x80,
          codePoint & 0x3F | 0x80
        )
      } else {
        throw new Error('Invalid code point')
      }
    }
  
    return bytes
  }
  
  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 utf16leToBytes (str, units) {
    var c, hi, lo
    var byteArray = []
    for (var i = 0; i < str.length; i++) {
      if ((units -= 2) < 0) break
  
      c = str.charCodeAt(i)
      hi = c >> 8
      lo = c % 256
      byteArray.push(lo)
      byteArray.push(hi)
    }
  
    return byteArray
  }
  
  function base64ToBytes (str) {
    return base64.toByteArray(base64clean(str))
  }
  
  function blitBuffer (src, dst, offset, length) {
    for (var i = 0; i < length; i++) {
      if ((i + offset >= dst.length) || (i >= src.length)) break
      dst[i + offset] = src[i]
    }
    return i
  }
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{"base64-js":1,"ieee754":4,"isarray":3}],3:[function(require,module,exports){
  var toString = {}.toString;
  
  module.exports = Array.isArray || function (arr) {
    return toString.call(arr) == '[object Array]';
  };
  
  },{}],4:[function(require,module,exports){
  exports.read = function (buffer, offset, isLE, mLen, nBytes) {
    var e, m
    var eLen = (nBytes * 8) - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var nBits = -7
    var i = isLE ? (nBytes - 1) : 0
    var d = isLE ? -1 : 1
    var 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.write = function (buffer, value, offset, isLE, mLen, nBytes) {
    var e, m, c
    var eLen = (nBytes * 8) - mLen - 1
    var eMax = (1 << eLen) - 1
    var eBias = eMax >> 1
    var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0)
    var i = isLE ? 0 : (nBytes - 1)
    var d = isLE ? 1 : -1
    var 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
  }
  
  },{}],5:[function(require,module,exports){
  exports.v4 = require('./lib/ipv4.js').v4;
  exports.v6 = require('./lib/ipv6.js').v6;
  
  },{"./lib/ipv4.js":7,"./lib/ipv6.js":8}],6:[function(require,module,exports){
  'use strict';
  
  var repeatString = exports.repeatString = function (s, n) {
    var result = '';
    var i;
  
    for (i = 0; i < n; i++) {
      result += s;
    }
  
    return result;
  };
  
  exports.zeroPad = function (s, n) {
    return String(repeatString(0, n) + s).slice(n * -1);
  };
  
  // A wrapper function that returns false if the address is not valid; used to
  // avoid boilerplate checks for `if (!this.valid) { return false; }`
  var falseIfInvalid = exports.falseIfInvalid = function (fn) {
    return function () {
      if (!this.valid) {
        return false;
      }
  
      return fn.apply(this, arguments);
    };
  };
  
  exports.isInSubnet = falseIfInvalid(function (address) {
    if (this.subnetMask < address.subnetMask) {
      return false;
    }
  
    if (this.mask(address.subnetMask) === address.mask()) {
      return true;
    }
  
    return false;
  });
  
  exports.isCorrect = function (defaultBits) {
    return falseIfInvalid(function () {
      if (this.addressMinusSuffix !== this.correctForm()) {
        return false;
      }
  
      if (this.subnetMask === defaultBits && !this.parsedSubnet) {
        return true;
      }
  
      return this.parsedSubnet === String(this.subnetMask);
    });
  };
  
  },{}],7:[function(require,module,exports){
  'use strict';
  
  var BigInteger = require('jsbn');
  var common = require('./common.js');
  var merge = require('lodash.merge');
  var sprintf = require('sprintf').sprintf;
  
  var v4 = exports.v4 = {};
  
  merge(v4, require('./v4/constants.js'));
  
  /*
   * Instantiates an IPv4 address
   */
  v4.Address = function (address) {
    this.valid = false;
    this.address = address;
    this.groups = v4.GROUPS;
  
    this.v4 = true;
  
    this.subnet = '/32';
    this.subnetMask = 32;
  
    var subnet = v4.RE_SUBNET_STRING.exec(address);
  
    if (subnet) {
      this.parsedSubnet = subnet[0].replace('/', '');
      this.subnetMask = parseInt(this.parsedSubnet, 10);
      this.subnet = '/' + this.subnetMask;
  
      if (this.subnetMask < 0 || this.subnetMask > v4.BITS) {
        this.valid = false;
        this.error = 'Invalid subnet mask.';
  
        return;
      }
  
      address = address.replace(v4.RE_SUBNET_STRING, '');
    }
  
    this.addressMinusSuffix = address;
  
    this.parsedAddress = this.parse(address);
  };
  
  /*
   * Parses a v4 address
   */
  v4.Address.prototype.parse = function (address) {
    var groups = address.split('.');
  
    if (address.match(v4.RE_ADDRESS)) {
      this.valid = true;
    } else {
      this.error = 'Invalid IPv4 address.';
    }
  
    return groups;
  };
  
  /*
   * Returns true if the address is valid
   */
  v4.Address.prototype.isValid = function () {
    return this.valid;
  };
  
  /*
   * Returns the correct form of an address
   */
  v4.Address.prototype.correctForm = function () {
    return this.parsedAddress.map(function (part) {
      return parseInt(part, 10);
    }).join('.');
  };
  
  /*
   * Returns true if the address is correct, false otherwise
   */
  v4.Address.prototype.isCorrect = common.isCorrect(v4.BITS);
  
  /*
   * Converts a hex string to an IPv4 address object
   */
  v4.Address.fromHex = function (hex) {
    var padded = common.zeroPad(hex.replace(/:/g, ''), 8);
    var groups = [];
    var i;
  
    for (i = 0; i < 8; i += 2) {
      var h = padded.slice(i, i + 2);
  
      groups.push(parseInt(h, 16));
    }
  
    return new v4.Address(groups.join('.'));
  };
  
  /*
   * Converts an integer into a IPv4 address object
   */
  v4.Address.fromInteger = function (integer) {
    return v4.Address.fromHex(integer.toString(16));
  };
  
  /*
   * Converts an IPv4 address object to a hex string
   */
  v4.Address.prototype.toHex = function () {
    return this.parsedAddress.map(function (part) {
      return sprintf('%02x', parseInt(part, 10));
    }).join(':');
  };
  
  /*
   * Converts an IPv4 address object to an array of bytes
   */
  v4.Address.prototype.toArray = function () {
    return this.parsedAddress.map(function (part) {
      return parseInt(part, 10);
    });
  };
  
  /*
   * Converts an IPv4 address object to an IPv6 address group
   */
  v4.Address.prototype.toV6Group = function () {
    var output = [];
    var i;
  
    for (i = 0; i < v4.GROUPS; i += 2) {
      var hex = sprintf('%02x%02x',
        parseInt(this.parsedAddress[i], 10),
        parseInt(this.parsedAddress[i + 1], 10));
  
      output.push(sprintf('%x', parseInt(hex, 16)));
    }
  
    return output.join(':');
  };
  
  /*
   * Returns the address as a BigInteger
   */
  v4.Address.prototype.bigInteger = function () {
    if (!this.valid) {
      return null;
    }
  
    return new BigInteger(this.parsedAddress.map(function (n) {
      return sprintf('%02x', parseInt(n, 10));
    }).join(''), 16);
  };
  
  /*
   * The first address in the range given by this address' subnet.
   * Often referred to as the Network Address.
   */
  v4.Address.prototype.startAddress = function () {
    var startAddress = new BigInteger(this.mask() +
      common.repeatString(0, v4.BITS - this.subnetMask), 2);
  
    return v4.Address.fromBigInteger(startAddress);
  };
  
  /*
   * The last address in the range given by this address' subnet
   * Often referred to as the Broadcast
   */
  v4.Address.prototype.endAddress = function () {
    var endAddress = new BigInteger(this.mask() +
      common.repeatString(1, v4.BITS - this.subnetMask), 2);
  
    return v4.Address.fromBigInteger(endAddress);
  };
  
  /*
   * Converts a BigInteger to a v4 address object
   */
  v4.Address.fromBigInteger = function (bigInteger) {
    return v4.Address.fromInteger(parseInt(bigInteger.toString(), 10));
  };
  
  /*
   * Returns the first n bits of the address, defaulting to the
   * subnet mask
   */
  v4.Address.prototype.mask = function (optionalMask) {
    if (optionalMask === undefined) {
      optionalMask = this.subnetMask;
    }
  
    return this.getBitsBase2(0, optionalMask);
  };
  
  /*
   * Returns the bits in the given range as a base-2 string
   */
  v4.Address.prototype.getBitsBase2 = function (start, end) {
    return this.binaryZeroPad().slice(start, end);
  };
  
  /*
   * Returns true if the given address is in the subnet of the current address
   */
  v4.Address.prototype.isInSubnet = common.isInSubnet;
  
  /*
   * Returns a zero-padded base-2 string representation of the address
   */
  v4.Address.prototype.binaryZeroPad = function () {
    return common.zeroPad(this.bigInteger().toString(2), v4.BITS);
  };
  
  },{"./common.js":6,"./v4/constants.js":9,"jsbn":15,"lodash.merge":36,"sprintf":44}],8:[function(require,module,exports){
  'use strict';
  
  var BigInteger = require('jsbn');
  var common = require('./common.js');
  var find = require('lodash.find');
  var merge = require('lodash.merge');
  var sprintf = require('sprintf').sprintf;
  
  var v4 = require('./ipv4.js').v4;
  
  var v6 = exports.v6 = {
    helpers: require('./v6/helpers.js')
  };
  
  merge(v6, require('./v6/constants.js'));
  
  function addCommas(number) {
    var r = /(\d+)(\d{3})/;
  
    while (r.test(number)) {
      number = number.replace(r, '$1,$2');
    }
  
    return number;
  }
  
  function spanLeadingZeroes4(n) {
    n = n.replace(/^(0{1,})([1-9]+)$/, '<span class="parse-error">$1</span>$2');
    n = n.replace(/^(0{1,})(0)$/, '<span class="parse-error">$1</span>$2');
  
    return n;
  }
  
  /*
   * Instantiates an IPv6 address
   */
  v6.Address = function (address, optionalGroups) {
    if (optionalGroups === undefined) {
      this.groups = v6.GROUPS;
    } else {
      this.groups = optionalGroups;
    }
  
    this.v4 = false;
  
    this.subnet = '/128';
    this.subnetMask = 128;
  
    this.zone = '';
  
    this.address = address;
  
    var subnet = v6.RE_SUBNET_STRING.exec(address);
  
    if (subnet) {
      this.parsedSubnet = subnet[0].replace('/', '');
      this.subnetMask = parseInt(this.parsedSubnet, 10);
      this.subnet = '/' + this.subnetMask;
  
      if (isNaN(this.subnetMask) ||
        this.subnetMask < 0 ||
        this.subnetMask > v6.BITS) {
        this.valid = false;
        this.error = 'Invalid subnet mask.';
  
        return;
      }
  
      address = address.replace(v6.RE_SUBNET_STRING, '');
    } else if (/\//.test(address)) {
      this.valid = false;
      this.error = 'Invalid subnet mask.';
  
      return;
    }
  
    var zone = v6.RE_ZONE_STRING.exec(address);
  
    if (zone) {
      this.zone = zone[0];
  
      address = address.replace(v6.RE_ZONE_STRING, '');
    }
  
    this.addressMinusSuffix = address;
  
    this.parsedAddress = this.parse(this.addressMinusSuffix);
  };
  
  merge(v6.Address.prototype, require('./v6/attributes.js'));
  merge(v6.Address.prototype, require('./v6/html.js'));
  merge(v6.Address.prototype, require('./v6/regular-expressions.js'));
  
  /*
   * Converts a BigInteger to a v6 address object
   */
  v6.Address.fromBigInteger = function (bigInteger) {
    var hex = common.zeroPad(bigInteger.toString(16), 32);
    var groups = [];
    var i;
  
    for (i = 0; i < v6.GROUPS; i++) {
      groups.push(hex.slice(i * 4, (i + 1) * 4));
    }
  
    return new v6.Address(groups.join(':'));
  };
  
  /*
   * Converts a URL (optional port number) to an address object
   */
  v6.Address.fromURL = function (url) {
    var host;
    var port;
    var result;
  
    // If we have brackets parse them and find a port
    if (url.indexOf('[') !== -1 && url.indexOf(']:') !== -1) {
      result = v6.RE_URL_WITH_PORT.exec(url);
  
      if (result === null) {
        return {
          error: 'failed to parse address with port',
          address: null,
          port: null
        };
      }
  
      host = result[1];
      port = result[2];
    // If there's a URL extract the address
    } else if (url.indexOf('/') !== -1) {
      // Remove the protocol prefix
      url = url.replace(/^[a-z0-9]+:\/\//, '');
  
      // Parse the address
      result = v6.RE_URL.exec(url);
  
      if (result === null) {
        return {
          error: 'failed to parse address from URL',
          address: null,
          port: null
        };
      }
  
      host = result[1];
    // Otherwise just assign the URL to the host and let the library parse it
    } else {
      host = url;
    }
  
    // If there's a port convert it to an integer
    if (port) {
      port = parseInt(port, 10);
  
      //squelch out of range ports
      if (port < 0 || port > 65536) {
        port = null;
      }
    } else {
      // Standardize `undefined` to `null`
      port = null;
    }
  
    return {
      address: new v6.Address(host),
      port: port
    };
  };
  
  /*
   * Create an IPv6-mapped address given an IPv4 address
   */
  v6.Address.fromAddress4 = function (address4) {
    return new v6.Address('::ffff:' + address4);
  };
  
  /*
   * A helper function to compact an array
   */
  v6.Address.compact = function (address, slice) {
    var s1 = [];
    var s2 = [];
    var i;
  
    for (i = 0; i < address.length; i++) {
      if (i < slice[0]) {
        s1.push(address[i]);
      } else if (i > slice[1]) {
        s2.push(address[i]);
      }
    }
  
    return s1.concat(['compact']).concat(s2);
  };
  
  /*
   * Returns the Microsoft UNC transcription of the address
   */
  v6.Address.prototype.microsoftTranscription = function () {
    return sprintf('%s.ipv6-literal.net',
      this.correctForm().replace(/:/g, '-'));
  };
  
  /*
   * Returns the first n bits of the address, defaulting to the
   * subnet mask
   */
  v6.Address.prototype.mask = function (optionalMask) {
    if (optionalMask === undefined) {
      optionalMask = this.subnetMask;
    }
  
    return this.getBitsBase2(0, optionalMask);
  };
  
  /*
   * Returns the number of possible subnets of a given size in the address
   */
  v6.Address.prototype.possibleSubnets = function (optionalSubnetSize) {
    if (optionalSubnetSize === undefined) {
      optionalSubnetSize = 128;
    }
  
    var availableBits = v6.BITS - this.subnetMask;
    var subnetBits = Math.abs(optionalSubnetSize - v6.BITS);
    var subnetPowers = availableBits - subnetBits;
  
    if (subnetPowers < 0) {
      return '0';
    }
  
    return addCommas(new BigInteger('2', 10).pow(subnetPowers).toString(10));
  };
  
  /*
   * The first address in the range given by this address' subnet
   */
  v6.Address.prototype.startAddress = function () {
    var startAddress = new BigInteger(this.mask() +
      common.repeatString(0, v6.BITS - this.subnetMask), 2);
  
    return v6.Address.fromBigInteger(startAddress);
  };
  
  /*
   * The last address in the range given by this address' subnet
   */
  v6.Address.prototype.endAddress = function () {
    var endAddress = new BigInteger(this.mask() +
      common.repeatString(1, v6.BITS - this.subnetMask), 2);
  
    return v6.Address.fromBigInteger(endAddress);
  };
  
  /*
   * Returns the scope of the address
   */
  v6.Address.prototype.getScope = function () {
    var scope = v6.SCOPES[this.getBits(12, 16)];
  
    if (this.getType() === 'Global unicast' &&
        scope !== 'Link local') {
      scope = 'Global';
    }
  
    return scope;
  };
  
  /*
   * Returns the type of the address
   */
  v6.Address.prototype.getType = function () {
    var self = this;
  
    function isType(name, type) {
      return self.isInSubnet(new v6.Address(type));
    }
  
    return find(v6.TYPES, isType) || 'Global unicast';
  };
  
  /*
   * Returns the bits in the given range as a BigInteger
   */
  v6.Address.prototype.getBits = function (start, end) {
    return new BigInteger(this.getBitsBase2(start, end), 2);
  };
  
  /*
   * Returns the bits in the given range as a base-2 string
   */
  v6.Address.prototype.getBitsBase2 = function (start, end) {
    return this.binaryZeroPad().slice(start, end);
  };
  
  /*
   * Returns the bits in the given range as a base-16 string
   */
  v6.Address.prototype.getBitsBase16 = function (start, end) {
    var length = end - start;
  
    if (length % 4 !== 0) {
      return null;
    }
  
    return common.zeroPad(this.getBits(start, end).toString(16), length / 4);
  };
  
  /*
   * Returns the bits that are set past the subnet mask length
   */
  v6.Address.prototype.getBitsPastSubnet = function () {
    return this.getBitsBase2(this.subnetMask, v6.BITS);
  };
  
  /*
   * Returns the reversed ip6.arpa form of the address
   */
  v6.Address.prototype.reverseForm = function () {
    var characters = Math.floor(this.subnetMask / 4);
  
    var reversed = this.canonicalForm()
      .replace(/:/g, '')
      .split('')
      .slice(0, characters)
      .reverse()
      .join('.');
  
    if (characters > 0) {
      return sprintf('%s.ip6.arpa.', reversed);
    }
  
    return 'ip6.arpa.';
  };
  
  /*
   * Returns the correct form of the address
   */
  v6.Address.prototype.correctForm = function () {
    if (!this.parsedAddress) {
      return null;
    }
  
    var i;
    var groups = [];
  
    var zeroCounter = 0;
    var zeroes = [];
  
    for (i = 0; i < this.parsedAddress.length; i++) {
      var value = parseInt(this.parsedAddress[i], 16);
  
      if (value === 0) {
        zeroCounter++;
      }
  
      if (value !== 0 && zeroCounter > 0) {
        if (zeroCounter > 1) {
          zeroes.push([i - zeroCounter, i - 1]);
        }
  
        zeroCounter = 0;
      }
    }
  
    // Do we end with a string of zeroes?
    if (zeroCounter > 1) {
      zeroes.push([this.parsedAddress.length - zeroCounter,
        this.parsedAddress.length - 1]);
    }
  
    var zeroLengths = zeroes.map(function (n) {
      return (n[1] - n[0]) + 1;
    });
  
    if (zeroes.length > 0) {
      var max = Math.max.apply(Math, zeroLengths);
      var index = zeroLengths.indexOf(max);
  
      groups = v6.Address.compact(this.parsedAddress, zeroes[index]);
    } else {
      groups = this.parsedAddress;
    }
  
    for (i = 0; i < groups.length; i++) {
      if (groups[i] !== 'compact') {
        groups[i] = parseInt(groups[i], 16).toString(16);
      }
    }
  
    var correct = groups.join(':');
  
    correct = correct.replace(/^compact$/, '::');
    correct = correct.replace(/^compact|compact$/, ':');
    correct = correct.replace(/compact/, '');
  
    return correct;
  };
  
  /*
   * Returns a zero-padded base-2 string representation of the address
   */
  v6.Address.prototype.binaryZeroPad = function () {
    return common.zeroPad(this.bigInteger().toString(2), v6.BITS);
  };
  
  // TODO: Improve the semantics of this helper function
  v6.Address.prototype.parse4in6 = function (address) {
    var groups = address.split(':');
    var lastGroup = groups.slice(-1)[0];
  
    var address4 = lastGroup.match(v4.RE_ADDRESS);
  
    if (address4) {
      var temp4 = new v4.Address(address4[0]);
  
      for (var i = 0; i < temp4.groups; i++) {
        if (/^0[0-9]+/.test(temp4.parsedAddress[i])) {
          this.valid = false;
          this.error = 'IPv4 addresses can not have leading zeroes.';
  
          this.parseError = address.replace(v4.RE_ADDRESS,
            temp4.parsedAddress.map(spanLeadingZeroes4).join('.'));
  
          return null;
        }
      }
  
      this.v4 = true;
  
      groups[groups.length - 1] = temp4.toV6Group();
  
      address = groups.join(':');
    }
  
    return address;
  };
  
  // TODO: Make private?
  v6.Address.prototype.parse = function (address) {
    address = this.parse4in6(address);
  
    if (this.error) {
      return null;
    }
  
    var badCharacters = address.match(v6.RE_BAD_CHARACTERS);
  
    if (badCharacters) {
      this.valid = false;
      this.error = sprintf('Bad character%s detected in address: %s',
        badCharacters.length > 1 ? 's' : '', badCharacters.join(''));
  
      this.parseError = address.replace(v6.RE_BAD_CHARACTERS,
        '<span class="parse-error">$1</span>');
  
      return null;
    }
  
    var badAddress = address.match(v6.RE_BAD_ADDRESS);
  
    if (badAddress) {
      this.valid = false;
      this.error = sprintf('Address failed regex: %s', badAddress.join(''));
  
      this.parseError = address.replace(v6.RE_BAD_ADDRESS,
        '<span class="parse-error">$1</span>');
  
      return null;
    }
  
    var groups = [];
  
    var halves = address.split('::');
  
    if (halves.length === 2) {
      var first = halves[0].split(':');
      var last = halves[1].split(':');
  
      if (first.length === 1 &&
        first[0] === '') {
        first = [];
      }
  
      if (last.length === 1 &&
        last[0] === '') {
        last = [];
      }
  
      var remaining = this.groups - (first.length + last.length);
  
      if (!remaining) {
        this.valid = false;
        this.error = 'Error parsing groups';
  
        return null;
      }
  
      this.elidedGroups = remaining;
  
      this.elisionBegin = first.length;
      this.elisionEnd = first.length + this.elidedGroups;
  
      first.forEach(function (group) {
        groups.push(group);
      });
  
      for (var i = 0; i < remaining; i++) {
        groups.push(0);
      }
  
      last.forEach(function (group) {
        groups.push(group);
      });
    } else if (halves.length === 1) {
      groups = address.split(':');
  
      this.elidedGroups = 0;
    } else {
      this.valid = false;
      this.error = 'Too many :: groups found';
  
      return null;
    }
  
    groups = groups.map(function (g) {
      return sprintf('%x', parseInt(g, 16));
    });
  
    if (groups.length !== this.groups) {
      this.valid = false;
      this.error = 'Incorrect number of groups found';
  
      return null;
    }
  
    this.valid = true;
  
    return groups;
  };
  
  /*
   * Returns the canonical form of the address
   */
  v6.Address.prototype.canonicalForm = function () {
    if (!this.valid) {
      return null;
    }
  
    return this.parsedAddress.map(function (n) {
      return sprintf('%04x', parseInt(n, 16));
    }).join(':');
  };
  
  /*
   * Returns the decimal form of the address
   */
  v6.Address.prototype.decimal = function () {
    if (!this.valid) {
      return null;
    }
  
    return this.parsedAddress.map(function (n) {
      return sprintf('%05d', parseInt(n, 16));
    }).join(':');
  };
  
  /*
   * Returns the address as a BigInteger
   */
  v6.Address.prototype.bigInteger = function () {
    if (!this.valid) {
      return null;
    }
  
    return new BigInteger(this.parsedAddress.map(function (n) {
      return sprintf('%04x', parseInt(n, 16));
    }).join(''), 16);
  };
  
  v6.Address.prototype.tov4 = function () {
    var binary = this.binaryZeroPad().split('');
  
    return v4.Address.fromHex(new BigInteger(binary.slice(96, 128)
      .join(''), 2).toString(16));
  };
  
  /*
   * Returns the v4-in-v6 form of the address
   */
  v6.Address.prototype.v4inv6 = function () {
    var address4 = this.tov4();
    var address6 = new v6.Address(this.parsedAddress.slice(0, 6).join(':'), 6);
  
    var correct = address6.correctForm();
  
    var infix = '';
  
    if (!/:$/.test(correct)) {
      infix = ':';
    }
  
    return address6.correctForm() + infix + address4.address;
  };
  
  /*
   * Returns an object containing the Teredo properties of the address
   */
  v6.Address.prototype.teredo = function () {
    /*
    - Bits 0 to 31 are set to the Teredo prefix (normally 2001:0000::/32).
    - Bits 32 to 63 embed the primary IPv4 address of the Teredo server that
      is used.
    - Bits 64 to 79 can be used to define some flags. Currently only the
      higher order bit is used; it is set to 1 if the Teredo client is
      located behind a cone NAT, 0 otherwise. For Microsoft's Windows Vista
      and Windows Server 2008 implementations, more bits are used. In those
      implementations, the format for these 16 bits is "CRAAAAUG AAAAAAAA",
      where "C" remains the "Cone" flag. The "R" bit is reserved for future
      use. The "U" bit is for the Universal/Local flag (set to 0). The "G" bit
      is Individual/Group flag (set to 0). The A bits are set to a 12-bit
      randomly generated number chosen by the Teredo client to introduce
      additional protection for the Teredo node against IPv6-based scanning
      attacks.
    - Bits 80 to 95 contains the obfuscated UDP port number. This is the
      port number that is mapped by the NAT to the Teredo client with all
      bits inverted.
    - Bits 96 to 127 contains the obfuscated IPv4 address. This is the
      public IPv4 address of the NAT with all bits inverted.
    */
    var prefix = this.getBitsBase16(0, 32);
  
    var udpPort = this.getBits(80, 96).xor(new BigInteger('ffff', 16)).toString();
  
    var server4 = v4.Address.fromHex(this.getBitsBase16(32, 64));
    var client4 = v4.Address.fromHex(this.getBits(96, 128)
      .xor(new BigInteger('ffffffff', 16)).toString(16));
  
    var flags = this.getBits(64, 80);
    var flagsBase2 = this.getBitsBase2(64, 80);
  
    var coneNat = flags.testBit(15);
    var reserved = flags.testBit(14);
    var groupIndividual = flags.testBit(8);
    var universalLocal = flags.testBit(9);
    var nonce = new BigInteger(flagsBase2.slice(2, 6) +
      flagsBase2.slice(8, 16), 2).toString(10);
  
    return {
      prefix: sprintf('%s:%s', prefix.slice(0, 4), prefix.slice(4, 8)),
      server4: server4.address,
      client4: client4.address,
      flags: flagsBase2,
      coneNat: coneNat,
      microsoft: {
        reserved: reserved,
        universalLocal: universalLocal,
        groupIndividual: groupIndividual,
        nonce: nonce
      },
      udpPort: udpPort
    };
  };
  
  /*
   * Returns an object containing the 6to4 properties of the address
   */
  v6.Address.prototype.six2four = function () {
    /*
    - Bits 0 to 15 are set to the 6to4 prefix (2002::/16).
    - Bits 16 to 48 embed the IPv4 address of the 6to4 gateway that is used.
    */
  
    var prefix = this.getBitsBase16(0, 16);
  
    var gateway = v4.Address.fromHex(this.getBitsBase16(16, 48));
  
    return {
      prefix: sprintf('%s', prefix.slice(0, 4)),
      gateway: gateway.address
    };
  };
  
  /*
   * Returns a v6 6to4 address from a v6 v4inv6 address.
   */
  v6.Address.prototype.get6to4 = function () {
    if (!this.is4()) {
      return null;
    }
  
    var addr6to4 = [
      '2002',
      this.getBitsBase16(96, 112),
      this.getBitsBase16(112, 128),
      '',
      '/16'
    ].join(':');
  
    return new v6.Address(addr6to4);
  };
  
  v6.Address.prototype.toByteArray = function () {
    return this.bigInteger().toByteArray();
  };
  
  v6.Address.prototype.toUnsignedByteArray = function () {
    return this.toByteArray().map(function (b) {
      return b & 0xFF;
    });
  };
  
  v6.Address.fromUnsignedByteArray = function (bytes) {
    var BYTE_MAX = new BigInteger('256', 10);
    var result = new BigInteger('0', 10);
    var multiplier = new BigInteger('1', 10);
  
    for (var i = bytes.length - 1; i >= 0; i--) {
      result = result.add(
        multiplier.multiply(new BigInteger(bytes[i].toString(10), 10)));
  
      multiplier = multiplier.multiply(BYTE_MAX);
    }
  
    return v6.Address.fromBigInteger(result);
  };
  
  v6.Address.fromByteArray = function (bytes) {
    return this.fromUnsignedByteArray(bytes.map(function (b) {
      return b & 0xFF;
    }));
  };
  
  },{"./common.js":6,"./ipv4.js":7,"./v6/attributes.js":10,"./v6/constants.js":11,"./v6/helpers.js":12,"./v6/html.js":13,"./v6/regular-expressions.js":14,"jsbn":15,"lodash.find":29,"lodash.merge":36,"sprintf":44}],9:[function(require,module,exports){
  exports.BITS = 32;
  exports.GROUPS = 4;
  
  exports.RE_ADDRESS = /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/g;
  exports.RE_SUBNET_STRING = /\/\d{1,2}$/;
  
  },{}],10:[function(require,module,exports){
  'use strict';
  
  var common = require('../common.js');
  var v6 = require('./constants.js');
  
  /*
   * Returns true if the address is valid, false otherwise
   */
  exports.isValid = function () {
    return this.valid;
  };
  
  /*
   * Returns true if the given address is in the subnet of the current address
   */
  exports.isInSubnet = common.isInSubnet;
  
  /*
   * Returns true if the address is correct, false otherwise
   */
  exports.isCorrect = common.isCorrect(v6.BITS);
  
  /*
   * Returns true if the address is in the canonical form, false otherwise
   */
  exports.isCanonical = common.falseIfInvalid(function () {
    return this.addressMinusSuffix === this.canonicalForm();
  });
  
  /*
   * Returns true if the address is a link local address, false otherwise
   */
  exports.isLinkLocal = common.falseIfInvalid(function () {
    // Zeroes are required, i.e. we can't check isInSubnet with 'fe80::/10'
    if (this.getBitsBase2(0, 64) ===
      '1111111010000000000000000000000000000000000000000000000000000000') {
      return true;
    }
  
    return false;
  });
  
  /*
   * Returns true if the address is a multicast address, false otherwise
   */
  exports.isMulticast = common.falseIfInvalid(function () {
    return this.getType() === 'Multicast';
  });
  
  /*
   * Returns true if the address is a v4-in-v6 address, false otherwise
   */
  exports.is4 = common.falseIfInvalid(function () {
    return this.v4;
  });
  
  /*
   * Returns true if the address is a Teredo address, false otherwise
   */
  exports.isTeredo = common.falseIfInvalid(function () {
    return this.isInSubnet(new this.constructor('2001::/32'));
  });
  
  /*
   * Returns true if the address is a 6to4 address, false otherwise
   */
  exports.is6to4 = common.falseIfInvalid(function () {
    return this.isInSubnet(new this.constructor('2002::/16'));
  });
  
  /*
   * Returns true if the address is a loopback address, false otherwise
   */
  exports.isLoopback = common.falseIfInvalid(function () {
    return this.getType() === 'Loopback';
  });
  
  },{"../common.js":6,"./constants.js":11}],11:[function(require,module,exports){
  exports.BITS = 128;
  exports.GROUPS = 8;
  
  exports.SCOPES = {
    0: 'Reserved',
    1: 'Interface local',
    2: 'Link local',
    4: 'Admin local',
    5: 'Site local',
    8: 'Organization local',
    15: 'Global',
    16: 'Reserved'
  };
  
  // TODO: Add ff0x::fb, etc. for multicast DNS
  exports.TYPES = {
    'ff01::1/128': 'Multicast (All nodes on this interface)',
    'ff01::2/128': 'Multicast (All routers on this interface)',
    'ff02::1/128': 'Multicast (All nodes on this link)',
    'ff02::2/128': 'Multicast (All routers on this link)',
    'ff05::2/128': 'Multicast (All routers in this site)',
    'ff02::5/128': 'Multicast (OSPFv3 AllSPF routers)',
    'ff02::6/128': 'Multicast (OSPFv3 AllDR routers)',
    'ff02::9/128': 'Multicast (RIP routers)',
    'ff02::a/128': 'Multicast (EIGRP routers)',
    'ff02::d/128': 'Multicast (PIM routers)',
    'ff02::16/128': 'Multicast (MLDv2 reports)',
    'ff01::fb/128': 'Multicast (mDNSv6)',
    'ff02::fb/128': 'Multicast (mDNSv6)',
    'ff05::fb/128': 'Multicast (mDNSv6)',
    'ff02::1:2/128': 'Multicast (All DHCP servers and relay agents on this link)',
    'ff05::1:2/128': 'Multicast (All DHCP servers and relay agents in this site)',
    'ff02::1:3/128': 'Multicast (All DHCP servers on this link)',
    'ff05::1:3/128': 'Multicast (All DHCP servers in this site)',
    '::/128': 'Unspecified',
    '::1/128': 'Loopback',
    'ff00::/8': 'Multicast',
    'fe80::/10': 'Link-local unicast'
  };
  
  exports.RE_BAD_CHARACTERS = /([^0-9a-f:\/%])/ig;
  exports.RE_BAD_ADDRESS = /([0-9a-f]{5,}|:{3,}|[^:]:$|^:[^:]|\/$)/ig;
  
  exports.RE_SUBNET_STRING = /\/\d{1,3}(?=%|$)/;
  exports.RE_ZONE_STRING = /%.*$/;
  
  exports.RE_URL = new RegExp(/^\[{0,1}([0-9a-f:]+)\]{0,1}/);
  exports.RE_URL_WITH_PORT = new RegExp(/\[([0-9a-f:]+)\]:([0-9]{1,5})/);
  
  },{}],12:[function(require,module,exports){
  'use strict';
  
  var sprintf = require('sprintf');
  
  /*
   * Returns the string with all zeroes contained in a <span>
   */
  var spanAllZeroes = exports.spanAllZeroes = function (s) {
    return s.replace(/(0+)/g, '<span class="zero">$1</span>');
  };
  
  /*
   * Returns the string with each character contained in a <span>
   */
  exports.spanAll = function (s, optionalOffset) {
    if (optionalOffset === undefined) {
      optionalOffset = 0;
    }
  
    var letters = s.split('');
  
    return letters.map(function (n, i) {
      return sprintf('<span class="digit value-%s position-%d">%s</span>', n,
        i + optionalOffset,
        spanAllZeroes(n)); // XXX Use #base-2 .value-0 instead?
    }).join('');
  };
  
  function spanLeadingZeroesSimple(group) {
    return group.replace(/^(0+)/, '<span class="zero">$1</span>');
  }
  
  /*
   * Returns the string with leading zeroes contained in a <span>
   */
  exports.spanLeadingZeroes = function (address) {
    var groups = address.split(':');
  
    return groups.map(function (g) {
      return spanLeadingZeroesSimple(g);
    }).join(':');
  };
  
  /*
   * Groups an address
   */
  exports.simpleGroup = function (addressString, offset) {
    var groups = addressString.split(':');
  
    if (!offset) {
      offset = 0;
    }
  
    return groups.map(function (g, i) {
      if (/group-v4/.test(g)) {
        return g;
      }
  
      return sprintf('<span class="hover-group group-%d">%s</span>',
        i + offset,
        spanLeadingZeroesSimple(g));
    }).join(':');
  };
  
  },{"sprintf":44}],13:[function(require,module,exports){
  'use strict';
  
  var constants4 = require('../v4/constants.js');
  var helpers = require('./helpers.js');
  var sprintf = require('sprintf').sprintf;
  
  /*
   * Returns the address in link form with a default port of 80
   */
  exports.href = function (optionalPort) {
    if (optionalPort === undefined) {
      optionalPort = '';
    } else {
      optionalPort = sprintf(':%s', optionalPort);
    }
  
    return sprintf('http://[%s]%s/', this.correctForm(), optionalPort);
  };
  
  /*
   * Returns a link suitable for conveying the address via a URL hash
   */
  exports.link = function (options) {
    if (!options) {
      options = {};
    }
  
    if (options.className === undefined) {
      options.className = '';
    }
  
    if (options.prefix === undefined) {
      options.prefix = '/#address=';
    }
  
    if (options.v4 === undefined) {
      options.v4 = false;
    }
  
    var formFunction = this.correctForm;
  
    if (options.v4) {
      formFunction = this.v4inv6;
    }
  
    if (options.className) {
      return sprintf('<a href="%1$s%2$s" class="%3$s">%2$s</a>',
        options.prefix, formFunction.call(this), options.className);
    }
  
    return sprintf('<a href="%1$s%2$s">%2$s</a>', options.prefix,
      formFunction.call(this));
  };
  
  /*
   * Groups an address
   */
  exports.group = function () {
    var address4 = this.address.match(constants4.RE_ADDRESS);
    var i;
  
    if (address4) {
      // The IPv4 case
      var segments = address4[0].split('.');
  
      this.address = this.address.replace(constants4.RE_ADDRESS,
        sprintf('<span class="hover-group group-v4 group-6">%s</span>' +
          '.' +
          '<span class="hover-group group-v4 group-7">%s</span>',
          segments.slice(0, 2).join('.'),
          segments.slice(2, 4).join('.')));
    }
  
    if (this.elidedGroups === 0) {
      // The simple case
      return helpers.simpleGroup(this.address);
    }
  
    // The elided case
    var output = [];
  
    var halves = this.address.split('::');
  
    if (halves[0].length) {
      output.push(helpers.simpleGroup(halves[0]));
    } else {
      output.push('');
    }
  
    var classes = ['hover-group'];
  
    for (i = this.elisionBegin;
         i < this.elisionBegin + this.elidedGroups; i++) {
      classes.push(sprintf('group-%d', i));
    }
  
    output.push(sprintf('<span class="%s"></span>', classes.join(' ')));
  
    if (halves[1].length) {
      output.push(helpers.simpleGroup(halves[1], this.elisionEnd));
    } else {
      output.push('');
    }
  
    return output.join(':');
  };
  
  },{"../v4/constants.js":9,"./helpers.js":12,"sprintf":44}],14:[function(require,module,exports){
  'use strict';
  
  var sprintf = require('sprintf').sprintf;
  
  var v6 = require('./constants.js');
  
  function groupPossibilities(possibilities) {
    return sprintf('(%s)', possibilities.join('|'));
  }
  
  function padGroup(group) {
    if (group.length < 4) {
      return sprintf('0{0,%d}%s', 4 - group.length, group);
    }
  
    return group;
  }
  
  function simpleRegularExpression(groups) {
    var zeroIndexes = [];
  
    groups.forEach(function (group, i) {
      var groupInteger = parseInt(group, 16);
  
      if (groupInteger === 0) {
        zeroIndexes.push(i);
      }
    });
  
    // You can technically elide a single 0, this creates the regular expressions
    // to match that eventuality
    var possibilities = zeroIndexes.map(function (zeroIndex) {
      return groups.map(function (group, i) {
        if (i === zeroIndex) {
          var elision = (i === 0 || i === v6.GROUPS - 1) ? ':' : '';
  
          return groupPossibilities([padGroup(group), elision]);
        }
  
        return padGroup(group);
      }).join(':');
    });
  
    // The simplest case
    possibilities.push(groups.map(padGroup).join(':'));
  
    return groupPossibilities(possibilities);
  }
  
  function possibleElisions(elidedGroups, moreLeft, moreRight) {
    var left = moreLeft ? '' : ':';
    var right = moreRight ? '' : ':';
  
    var possibilities = [];
  
    // 1. elision of everything (::)
    if (!moreLeft && !moreRight) {
      possibilities.push('::');
    }
  
    // 2. complete elision of the middle
    if (moreLeft && moreRight) {
      possibilities.push('');
    }
  
    if ((moreRight && !moreLeft) || (!moreRight && moreLeft)) {
      // 3. complete elision of one side
      possibilities.push(':');
    }
  
    // 4. elision from the left side
    possibilities.push(sprintf('%s(:0{1,4}){1,%d}', left, elidedGroups - 1));
  
    // 5. elision from the right side
    possibilities.push(sprintf('(0{1,4}:){1,%d}%s', elidedGroups - 1, right));
  
    // 6. no elision
    possibilities.push(sprintf('(0{1,4}:){%d}0{1,4}', elidedGroups - 1));
  
    // 7. elision (including sloppy elision) from the middle
    for (var groups = 1; groups < elidedGroups - 1; groups++) {
      for (var position = 1; position < elidedGroups - groups; position++) {
        possibilities.push(sprintf('(0{1,4}:){%d}:(0{1,4}:){%d}0{1,4}',
                                   position,
                                   elidedGroups - position - groups - 1));
      }
    }
  
    return groupPossibilities(possibilities);
  }
  
  /*
   * Generate a regular expression string that can be used to find or validate all
   * variations of this address.
   */
  exports.regularExpressionString = function (optionalSubString) {
    if (optionalSubString === undefined) {
      optionalSubString = false;
    }
  
    var output = [];
  
    // TODO: revisit why this is necessary
    var address6 = new this.constructor(this.correctForm());
  
    if (address6.elidedGroups === 0) {
      // The simple case
      output.push(simpleRegularExpression(address6.parsedAddress));
    } else if (address6.elidedGroups === v6.GROUPS) {
      // A completely elided address
      output.push(possibleElisions(v6.GROUPS));
    } else {
      // A partially elided address
      var halves = address6.address.split('::');
  
      if (halves[0].length) {
        output.push(simpleRegularExpression(halves[0].split(':')));
      }
  
      output.push(possibleElisions(address6.elidedGroups,
                           halves[0].length !== 0,
                           halves[1].length !== 0));
  
      if (halves[1].length) {
        output.push(simpleRegularExpression(halves[1].split(':')));
      }
  
      output = [output.join(':')];
    }
  
    if (!optionalSubString) {
      output = [].concat('(?=^|\\b|[^\\w\\:])(', output, ')(?=[^\\w\\:]|\\b|$)');
    }
  
    return output.join('');
  };
  
  /*
   * Generate a regular expression that can be used to find or validate all
   * variations of this address.
   */
  exports.regularExpression = function (optionalSubstring) {
    return new RegExp(this.regularExpressionString(optionalSubstring), 'i');
  };
  
  },{"./constants.js":11,"sprintf":44}],15:[function(require,module,exports){
  (function(){
      
      // Copyright (c) 2005  Tom Wu
      // All Rights Reserved.
      // See "LICENSE" for details.
  
      // Basic JavaScript BN library - subset useful for RSA encryption.
  
      // Bits per digit
      var dbits;
  
      // JavaScript engine analysis
      var canary = 0xdeadbeefcafe;
      var j_lm = ((canary&0xffffff)==0xefcafe);
  
      // (public) Constructor
      function BigInteger(a,b,c) {
        if(a != null)
          if("number" == typeof a) this.fromNumber(a,b,c);
          else if(b == null && "string" != typeof a) this.fromString(a,256);
          else this.fromString(a,b);
      }
  
      // return new, unset BigInteger
      function nbi() { return new BigInteger(null); }
  
      // am: Compute w_j += (x*this_i), propagate carries,
      // c is initial carry, returns final carry.
      // c < 3*dvalue, x < 2*dvalue, this_i < dvalue
      // We need to select the fastest one that works in this environment.
  
      // am1: use a single mult and divide to get the high bits,
      // max digit bits should be 26 because
      // max internal value = 2*dvalue^2-2*dvalue (< 2^53)
      function am1(i,x,w,j,c,n) {
        while(--n >= 0) {
          var v = x*this[i++]+w[j]+c;
          c = Math.floor(v/0x4000000);
          w[j++] = v&0x3ffffff;
        }
        return c;
      }
      // am2 avoids a big mult-and-extract completely.
      // Max digit bits should be <= 30 because we do bitwise ops
      // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
      function am2(i,x,w,j,c,n) {
        var xl = x&0x7fff, xh = x>>15;
        while(--n >= 0) {
          var l = this[i]&0x7fff;
          var h = this[i++]>>15;
          var m = xh*l+h*xl;
          l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
          c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
          w[j++] = l&0x3fffffff;
        }
        return c;
      }
      // Alternately, set max digit bits to 28 since some
      // browsers slow down when dealing with 32-bit numbers.
      function am3(i,x,w,j,c,n) {
        var xl = x&0x3fff, xh = x>>14;
        while(--n >= 0) {
          var l = this[i]&0x3fff;
          var h = this[i++]>>14;
          var m = xh*l+h*xl;
          l = xl*l+((m&0x3fff)<<14)+w[j]+c;
          c = (l>>28)+(m>>14)+xh*h;
          w[j++] = l&0xfffffff;
        }
        return c;
      }
      var inBrowser = typeof navigator !== "undefined";
      if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
        BigInteger.prototype.am = am2;
        dbits = 30;
      }
      else if(inBrowser && j_lm && (navigator.appName != "Netscape")) {
        BigInteger.prototype.am = am1;
        dbits = 26;
      }
      else { // Mozilla/Netscape seems to prefer am3
        BigInteger.prototype.am = am3;
        dbits = 28;
      }
  
      BigInteger.prototype.DB = dbits;
      BigInteger.prototype.DM = ((1<<dbits)-1);
      BigInteger.prototype.DV = (1<<dbits);
  
      var BI_FP = 52;
      BigInteger.prototype.FV = Math.pow(2,BI_FP);
      BigInteger.prototype.F1 = BI_FP-dbits;
      BigInteger.prototype.F2 = 2*dbits-BI_FP;
  
      // Digit conversions
      var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
      var BI_RC = new Array();
      var rr,vv;
      rr = "0".charCodeAt(0);
      for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
      rr = "a".charCodeAt(0);
      for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
      rr = "A".charCodeAt(0);
      for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
  
      function int2char(n) { return BI_RM.charAt(n); }
      function intAt(s,i) {
        var c = BI_RC[s.charCodeAt(i)];
        return (c==null)?-1:c;
      }
  
      // (protected) copy this to r
      function bnpCopyTo(r) {
        for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
        r.t = this.t;
        r.s = this.s;
      }
  
      // (protected) set from integer value x, -DV <= x < DV
      function bnpFromInt(x) {
        this.t = 1;
        this.s = (x<0)?-1:0;
        if(x > 0) this[0] = x;
        else if(x < -1) this[0] = x+DV;
        else this.t = 0;
      }
  
      // return bigint initialized to value
      function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
  
      // (protected) set from string and radix
      function bnpFromString(s,b) {
        var k;
        if(b == 16) k = 4;
        else if(b == 8) k = 3;
        else if(b == 256) k = 8; // byte array
        else if(b == 2) k = 1;
        else if(b == 32) k = 5;
        else if(b == 4) k = 2;
        else { this.fromRadix(s,b); return; }
        this.t = 0;
        this.s = 0;
        var i = s.length, mi = false, sh = 0;
        while(--i >= 0) {
          var x = (k==8)?s[i]&0xff:intAt(s,i);
          if(x < 0) {
            if(s.charAt(i) == "-") mi = true;
            continue;
          }
          mi = false;
          if(sh == 0)
            this[this.t++] = x;
          else if(sh+k > this.DB) {
            this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
            this[this.t++] = (x>>(this.DB-sh));
          }
          else
            this[this.t-1] |= x<<sh;
          sh += k;
          if(sh >= this.DB) sh -= this.DB;
        }
        if(k == 8 && (s[0]&0x80) != 0) {
          this.s = -1;
          if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
        }
        this.clamp();
        if(mi) BigInteger.ZERO.subTo(this,this);
      }
  
      // (protected) clamp off excess high words
      function bnpClamp() {
        var c = this.s&this.DM;
        while(this.t > 0 && this[this.t-1] == c) --this.t;
      }
  
      // (public) return string representation in given radix
      function bnToString(b) {
        if(this.s < 0) return "-"+this.negate().toString(b);
        var k;
        if(b == 16) k = 4;
        else if(b == 8) k = 3;
        else if(b == 2) k = 1;
        else if(b == 32) k = 5;
        else if(b == 4) k = 2;
        else return this.toRadix(b);
        var km = (1<<k)-1, d, m = false, r = "", i = this.t;
        var p = this.DB-(i*this.DB)%k;
        if(i-- > 0) {
          if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
          while(i >= 0) {
            if(p < k) {
              d = (this[i]&((1<<p)-1))<<(k-p);
              d |= this[--i]>>(p+=this.DB-k);
            }
            else {
              d = (this[i]>>(p-=k))&km;
              if(p <= 0) { p += this.DB; --i; }
            }
            if(d > 0) m = true;
            if(m) r += int2char(d);
          }
        }
        return m?r:"0";
      }
  
      // (public) -this
      function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
  
      // (public) |this|
      function bnAbs() { return (this.s<0)?this.negate():this; }
  
      // (public) return + if this > a, - if this < a, 0 if equal
      function bnCompareTo(a) {
        var r = this.s-a.s;
        if(r != 0) return r;
        var i = this.t;
        r = i-a.t;
        if(r != 0) return (this.s<0)?-r:r;
        while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
        return 0;
      }
  
      // returns bit length of the integer x
      function nbits(x) {
        var r = 1, t;
        if((t=x>>>16) != 0) { x = t; r += 16; }
        if((t=x>>8) != 0) { x = t; r += 8; }
        if((t=x>>4) != 0) { x = t; r += 4; }
        if((t=x>>2) != 0) { x = t; r += 2; }
        if((t=x>>1) != 0) { x = t; r += 1; }
        return r;
      }
  
      // (public) return the number of bits in "this"
      function bnBitLength() {
        if(this.t <= 0) return 0;
        return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
      }
  
      // (protected) r = this << n*DB
      function bnpDLShiftTo(n,r) {
        var i;
        for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
        for(i = n-1; i >= 0; --i) r[i] = 0;
        r.t = this.t+n;
        r.s = this.s;
      }
  
      // (protected) r = this >> n*DB
      function bnpDRShiftTo(n,r) {
        for(var i = n; i < this.t; ++i) r[i-n] = this[i];
        r.t = Math.max(this.t-n,0);
        r.s = this.s;
      }
  
      // (protected) r = this << n
      function bnpLShiftTo(n,r) {
        var bs = n%this.DB;
        var cbs = this.DB-bs;
        var bm = (1<<cbs)-1;
        var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
        for(i = this.t-1; i >= 0; --i) {
          r[i+ds+1] = (this[i]>>cbs)|c;
          c = (this[i]&bm)<<bs;
        }
        for(i = ds-1; i >= 0; --i) r[i] = 0;
        r[ds] = c;
        r.t = this.t+ds+1;
        r.s = this.s;
        r.clamp();
      }
  
      // (protected) r = this >> n
      function bnpRShiftTo(n,r) {
        r.s = this.s;
        var ds = Math.floor(n/this.DB);
        if(ds >= this.t) { r.t = 0; return; }
        var bs = n%this.DB;
        var cbs = this.DB-bs;
        var bm = (1<<bs)-1;
        r[0] = this[ds]>>bs;
        for(var i = ds+1; i < this.t; ++i) {
          r[i-ds-1] |= (this[i]&bm)<<cbs;
          r[i-ds] = this[i]>>bs;
        }
        if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
        r.t = this.t-ds;
        r.clamp();
      }
  
      // (protected) r = this - a
      function bnpSubTo(a,r) {
        var i = 0, c = 0, m = Math.min(a.t,this.t);
        while(i < m) {
          c += this[i]-a[i];
          r[i++] = c&this.DM;
          c >>= this.DB;
        }
        if(a.t < this.t) {
          c -= a.s;
          while(i < this.t) {
            c += this[i];
            r[i++] = c&this.DM;
            c >>= this.DB;
          }
          c += this.s;
        }
        else {
          c += this.s;
          while(i < a.t) {
            c -= a[i];
            r[i++] = c&this.DM;
            c >>= this.DB;
          }
          c -= a.s;
        }
        r.s = (c<0)?-1:0;
        if(c < -1) r[i++] = this.DV+c;
        else if(c > 0) r[i++] = c;
        r.t = i;
        r.clamp();
      }
  
      // (protected) r = this * a, r != this,a (HAC 14.12)
      // "this" should be the larger one if appropriate.
      function bnpMultiplyTo(a,r) {
        var x = this.abs(), y = a.abs();
        var i = x.t;
        r.t = i+y.t;
        while(--i >= 0) r[i] = 0;
        for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
        r.s = 0;
        r.clamp();
        if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
      }
  
      // (protected) r = this^2, r != this (HAC 14.16)
      function bnpSquareTo(r) {
        var x = this.abs();
        var i = r.t = 2*x.t;
        while(--i >= 0) r[i] = 0;
        for(i = 0; i < x.t-1; ++i) {
          var c = x.am(i,x[i],r,2*i,0,1);
          if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
            r[i+x.t] -= x.DV;
            r[i+x.t+1] = 1;
          }
        }
        if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
        r.s = 0;
        r.clamp();
      }
  
      // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
      // r != q, this != m.  q or r may be null.
      function bnpDivRemTo(m,q,r) {
        var pm = m.abs();
        if(pm.t <= 0) return;
        var pt = this.abs();
        if(pt.t < pm.t) {
          if(q != null) q.fromInt(0);
          if(r != null) this.copyTo(r);
          return;
        }
        if(r == null) r = nbi();
        var y = nbi(), ts = this.s, ms = m.s;
        var nsh = this.DB-nbits(pm[pm.t-1]);   // normalize modulus
        if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
        else { pm.copyTo(y); pt.copyTo(r); }
        var ys = y.t;
        var y0 = y[ys-1];
        if(y0 == 0) return;
        var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
        var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
        var i = r.t, j = i-ys, t = (q==null)?nbi():q;
        y.dlShiftTo(j,t);
        if(r.compareTo(t) >= 0) {
          r[r.t++] = 1;
          r.subTo(t,r);
        }
        BigInteger.ONE.dlShiftTo(ys,t);
        t.subTo(y,y);  // "negative" y so we can replace sub with am later
        while(y.t < ys) y[y.t++] = 0;
        while(--j >= 0) {
          // Estimate quotient digit
          var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
          if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) {   // Try it out
            y.dlShiftTo(j,t);
            r.subTo(t,r);
            while(r[i] < --qd) r.subTo(t,r);
          }
        }
        if(q != null) {
          r.drShiftTo(ys,q);
          if(ts != ms) BigInteger.ZERO.subTo(q,q);
        }
        r.t = ys;
        r.clamp();
        if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
        if(ts < 0) BigInteger.ZERO.subTo(r,r);
      }
  
      // (public) this mod a
      function bnMod(a) {
        var r = nbi();
        this.abs().divRemTo(a,null,r);
        if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
        return r;
      }
  
      // Modular reduction using "classic" algorithm
      function Classic(m) { this.m = m; }
      function cConvert(x) {
        if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
        else return x;
      }
      function cRevert(x) { return x; }
      function cReduce(x) { x.divRemTo(this.m,null,x); }
      function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
      function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
  
      Classic.prototype.convert = cConvert;
      Classic.prototype.revert = cRevert;
      Classic.prototype.reduce = cReduce;
      Classic.prototype.mulTo = cMulTo;
      Classic.prototype.sqrTo = cSqrTo;
  
      // (protected) return "-1/this % 2^DB"; useful for Mont. reduction
      // justification:
      //         xy == 1 (mod m)
      //         xy =  1+km
      //   xy(2-xy) = (1+km)(1-km)
      // x[y(2-xy)] = 1-k^2m^2
      // x[y(2-xy)] == 1 (mod m^2)
      // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
      // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
      // JS multiply "overflows" differently from C/C++, so care is needed here.
      function bnpInvDigit() {
        if(this.t < 1) return 0;
        var x = this[0];
        if((x&1) == 0) return 0;
        var y = x&3;       // y == 1/x mod 2^2
        y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
        y = (y*(2-(x&0xff)*y))&0xff;   // y == 1/x mod 2^8
        y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff;    // y == 1/x mod 2^16
        // last step - calculate inverse mod DV directly;
        // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
        y = (y*(2-x*y%this.DV))%this.DV;       // y == 1/x mod 2^dbits
        // we really want the negative inverse, and -DV < y < DV
        return (y>0)?this.DV-y:-y;
      }
  
      // Montgomery reduction
      function Montgomery(m) {
        this.m = m;
        this.mp = m.invDigit();
        this.mpl = this.mp&0x7fff;
        this.mph = this.mp>>15;
        this.um = (1<<(m.DB-15))-1;
        this.mt2 = 2*m.t;
      }
  
      // xR mod m
      function montConvert(x) {
        var r = nbi();
        x.abs().dlShiftTo(this.m.t,r);
        r.divRemTo(this.m,null,r);
        if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
        return r;
      }
  
      // x/R mod m
      function montRevert(x) {
        var r = nbi();
        x.copyTo(r);
        this.reduce(r);
        return r;
      }
  
      // x = x/R mod m (HAC 14.32)
      function montReduce(x) {
        while(x.t <= this.mt2) // pad x so am has enough room later
          x[x.t++] = 0;
        for(var i = 0; i < this.m.t; ++i) {
          // faster way of calculating u0 = x[i]*mp mod DV
          var j = x[i]&0x7fff;
          var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
          // use am to combine the multiply-shift-add into one call
          j = i+this.m.t;
          x[j] += this.m.am(0,u0,x,i,0,this.m.t);
          // propagate carry
          while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
        }
        x.clamp();
        x.drShiftTo(this.m.t,x);
        if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
      }
  
      // r = "x^2/R mod m"; x != r
      function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
  
      // r = "xy/R mod m"; x,y != r
      function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
  
      Montgomery.prototype.convert = montConvert;
      Montgomery.prototype.revert = montRevert;
      Montgomery.prototype.reduce = montReduce;
      Montgomery.prototype.mulTo = montMulTo;
      Montgomery.prototype.sqrTo = montSqrTo;
  
      // (protected) true iff this is even
      function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
  
      // (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
      function bnpExp(e,z) {
        if(e > 0xffffffff || e < 1) return BigInteger.ONE;
        var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
        g.copyTo(r);
        while(--i >= 0) {
          z.sqrTo(r,r2);
          if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
          else { var t = r; r = r2; r2 = t; }
        }
        return z.revert(r);
      }
  
      // (public) this^e % m, 0 <= e < 2^32
      function bnModPowInt(e,m) {
        var z;
        if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
        return this.exp(e,z);
      }
  
      // protected
      BigInteger.prototype.copyTo = bnpCopyTo;
      BigInteger.prototype.fromInt = bnpFromInt;
      BigInteger.prototype.fromString = bnpFromString;
      BigInteger.prototype.clamp = bnpClamp;
      BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
      BigInteger.prototype.drShiftTo = bnpDRShiftTo;
      BigInteger.prototype.lShiftTo = bnpLShiftTo;
      BigInteger.prototype.rShiftTo = bnpRShiftTo;
      BigInteger.prototype.subTo = bnpSubTo;
      BigInteger.prototype.multiplyTo = bnpMultiplyTo;
      BigInteger.prototype.squareTo = bnpSquareTo;
      BigInteger.prototype.divRemTo = bnpDivRemTo;
      BigInteger.prototype.invDigit = bnpInvDigit;
      BigInteger.prototype.isEven = bnpIsEven;
      BigInteger.prototype.exp = bnpExp;
  
      // public
      BigInteger.prototype.toString = bnToString;
      BigInteger.prototype.negate = bnNegate;
      BigInteger.prototype.abs = bnAbs;
      BigInteger.prototype.compareTo = bnCompareTo;
      BigInteger.prototype.bitLength = bnBitLength;
      BigInteger.prototype.mod = bnMod;
      BigInteger.prototype.modPowInt = bnModPowInt;
  
      // "constants"
      BigInteger.ZERO = nbv(0);
      BigInteger.ONE = nbv(1);
  
      // Copyright (c) 2005-2009  Tom Wu
      // All Rights Reserved.
      // See "LICENSE" for details.
  
      // Extended JavaScript BN functions, required for RSA private ops.
  
      // Version 1.1: new BigInteger("0", 10) returns "proper" zero
      // Version 1.2: square() API, isProbablePrime fix
  
      // (public)
      function bnClone() { var r = nbi(); this.copyTo(r); return r; }
  
      // (public) return value as integer
      function bnIntValue() {
        if(this.s < 0) {
          if(this.t == 1) return this[0]-this.DV;
          else if(this.t == 0) return -1;
        }
        else if(this.t == 1) return this[0];
        else if(this.t == 0) return 0;
        // assumes 16 < DB < 32
        return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
      }
  
      // (public) return value as byte
      function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
  
      // (public) return value as short (assumes DB>=16)
      function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
  
      // (protected) return x s.t. r^x < DV
      function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
  
      // (public) 0 if this == 0, 1 if this > 0
      function bnSigNum() {
        if(this.s < 0) return -1;
        else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
        else return 1;
      }
  
      // (protected) convert to radix string
      function bnpToRadix(b) {
        if(b == null) b = 10;
        if(this.signum() == 0 || b < 2 || b > 36) return "0";
        var cs = this.chunkSize(b);
        var a = Math.pow(b,cs);
        var d = nbv(a), y = nbi(), z = nbi(), r = "";
        this.divRemTo(d,y,z);
        while(y.signum() > 0) {
          r = (a+z.intValue()).toString(b).substr(1) + r;
          y.divRemTo(d,y,z);
        }
        return z.intValue().toString(b) + r;
      }
  
      // (protected) convert from radix string
      function bnpFromRadix(s,b) {
        this.fromInt(0);
        if(b == null) b = 10;
        var cs = this.chunkSize(b);
        var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
        for(var i = 0; i < s.length; ++i) {
          var x = intAt(s,i);
          if(x < 0) {
            if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
            continue;
          }
          w = b*w+x;
          if(++j >= cs) {
            this.dMultiply(d);
            this.dAddOffset(w,0);
            j = 0;
            w = 0;
          }
        }
        if(j > 0) {
          this.dMultiply(Math.pow(b,j));
          this.dAddOffset(w,0);
        }
        if(mi) BigInteger.ZERO.subTo(this,this);
      }
  
      // (protected) alternate constructor
      function bnpFromNumber(a,b,c) {
        if("number" == typeof b) {
          // new BigInteger(int,int,RNG)
          if(a < 2) this.fromInt(1);
          else {
            this.fromNumber(a,c);
            if(!this.testBit(a-1))	// force MSB set
              this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
            if(this.isEven()) this.dAddOffset(1,0); // force odd
            while(!this.isProbablePrime(b)) {
              this.dAddOffset(2,0);
              if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
            }
          }
        }
        else {
          // new BigInteger(int,RNG)
          var x = new Array(), t = a&7;
          x.length = (a>>3)+1;
          b.nextBytes(x);
          if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
          this.fromString(x,256);
        }
      }
  
      // (public) convert to bigendian byte array
      function bnToByteArray() {
        var i = this.t, r = new Array();
        r[0] = this.s;
        var p = this.DB-(i*this.DB)%8, d, k = 0;
        if(i-- > 0) {
          if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
            r[k++] = d|(this.s<<(this.DB-p));
          while(i >= 0) {
            if(p < 8) {
              d = (this[i]&((1<<p)-1))<<(8-p);
              d |= this[--i]>>(p+=this.DB-8);
            }
            else {
              d = (this[i]>>(p-=8))&0xff;
              if(p <= 0) { p += this.DB; --i; }
            }
            if((d&0x80) != 0) d |= -256;
            if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
            if(k > 0 || d != this.s) r[k++] = d;
          }
        }
        return r;
      }
  
      function bnEquals(a) { return(this.compareTo(a)==0); }
      function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
      function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
  
      // (protected) r = this op a (bitwise)
      function bnpBitwiseTo(a,op,r) {
        var i, f, m = Math.min(a.t,this.t);
        for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
        if(a.t < this.t) {
          f = a.s&this.DM;
          for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
          r.t = this.t;
        }
        else {
          f = this.s&this.DM;
          for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
          r.t = a.t;
        }
        r.s = op(this.s,a.s);
        r.clamp();
      }
  
      // (public) this & a
      function op_and(x,y) { return x&y; }
      function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
  
      // (public) this | a
      function op_or(x,y) { return x|y; }
      function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
  
      // (public) this ^ a
      function op_xor(x,y) { return x^y; }
      function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
  
      // (public) this & ~a
      function op_andnot(x,y) { return x&~y; }
      function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
  
      // (public) ~this
      function bnNot() {
        var r = nbi();
        for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
        r.t = this.t;
        r.s = ~this.s;
        return r;
      }
  
      // (public) this << n
      function bnShiftLeft(n) {
        var r = nbi();
        if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
        return r;
      }
  
      // (public) this >> n
      function bnShiftRight(n) {
        var r = nbi();
        if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
        return r;
      }
  
      // return index of lowest 1-bit in x, x < 2^31
      function lbit(x) {
        if(x == 0) return -1;
        var r = 0;
        if((x&0xffff) == 0) { x >>= 16; r += 16; }
        if((x&0xff) == 0) { x >>= 8; r += 8; }
        if((x&0xf) == 0) { x >>= 4; r += 4; }
        if((x&3) == 0) { x >>= 2; r += 2; }
        if((x&1) == 0) ++r;
        return r;
      }
  
      // (public) returns index of lowest 1-bit (or -1 if none)
      function bnGetLowestSetBit() {
        for(var i = 0; i < this.t; ++i)
          if(this[i] != 0) return i*this.DB+lbit(this[i]);
        if(this.s < 0) return this.t*this.DB;
        return -1;
      }
  
      // return number of 1 bits in x
      function cbit(x) {
        var r = 0;
        while(x != 0) { x &= x-1; ++r; }
        return r;
      }
  
      // (public) return number of set bits
      function bnBitCount() {
        var r = 0, x = this.s&this.DM;
        for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
        return r;
      }
  
      // (public) true iff nth bit is set
      function bnTestBit(n) {
        var j = Math.floor(n/this.DB);
        if(j >= this.t) return(this.s!=0);
        return((this[j]&(1<<(n%this.DB)))!=0);
      }
  
      // (protected) this op (1<<n)
      function bnpChangeBit(n,op) {
        var r = BigInteger.ONE.shiftLeft(n);
        this.bitwiseTo(r,op,r);
        return r;
      }
  
      // (public) this | (1<<n)
      function bnSetBit(n) { return this.changeBit(n,op_or); }
  
      // (public) this & ~(1<<n)
      function bnClearBit(n) { return this.changeBit(n,op_andnot); }
  
      // (public) this ^ (1<<n)
      function bnFlipBit(n) { return this.changeBit(n,op_xor); }
  
      // (protected) r = this + a
      function bnpAddTo(a,r) {
        var i = 0, c = 0, m = Math.min(a.t,this.t);
        while(i < m) {
          c += this[i]+a[i];
          r[i++] = c&this.DM;
          c >>= this.DB;
        }
        if(a.t < this.t) {
          c += a.s;
          while(i < this.t) {
            c += this[i];
            r[i++] = c&this.DM;
            c >>= this.DB;
          }
          c += this.s;
        }
        else {
          c += this.s;
          while(i < a.t) {
            c += a[i];
            r[i++] = c&this.DM;
            c >>= this.DB;
          }
          c += a.s;
        }
        r.s = (c<0)?-1:0;
        if(c > 0) r[i++] = c;
        else if(c < -1) r[i++] = this.DV+c;
        r.t = i;
        r.clamp();
      }
  
      // (public) this + a
      function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
  
      // (public) this - a
      function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
  
      // (public) this * a
      function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
  
      // (public) this^2
      function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
  
      // (public) this / a
      function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
  
      // (public) this % a
      function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
  
      // (public) [this/a,this%a]
      function bnDivideAndRemainder(a) {
        var q = nbi(), r = nbi();
        this.divRemTo(a,q,r);
        return new Array(q,r);
      }
  
      // (protected) this *= n, this >= 0, 1 < n < DV
      function bnpDMultiply(n) {
        this[this.t] = this.am(0,n-1,this,0,0,this.t);
        ++this.t;
        this.clamp();
      }
  
      // (protected) this += n << w words, this >= 0
      function bnpDAddOffset(n,w) {
        if(n == 0) return;
        while(this.t <= w) this[this.t++] = 0;
        this[w] += n;
        while(this[w] >= this.DV) {
          this[w] -= this.DV;
          if(++w >= this.t) this[this.t++] = 0;
          ++this[w];
        }
      }
  
      // A "null" reducer
      function NullExp() {}
      function nNop(x) { return x; }
      function nMulTo(x,y,r) { x.multiplyTo(y,r); }
      function nSqrTo(x,r) { x.squareTo(r); }
  
      NullExp.prototype.convert = nNop;
      NullExp.prototype.revert = nNop;
      NullExp.prototype.mulTo = nMulTo;
      NullExp.prototype.sqrTo = nSqrTo;
  
      // (public) this^e
      function bnPow(e) { return this.exp(e,new NullExp()); }
  
      // (protected) r = lower n words of "this * a", a.t <= n
      // "this" should be the larger one if appropriate.
      function bnpMultiplyLowerTo(a,n,r) {
        var i = Math.min(this.t+a.t,n);
        r.s = 0; // assumes a,this >= 0
        r.t = i;
        while(i > 0) r[--i] = 0;
        var j;
        for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
        for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
        r.clamp();
      }
  
      // (protected) r = "this * a" without lower n words, n > 0
      // "this" should be the larger one if appropriate.
      function bnpMultiplyUpperTo(a,n,r) {
        --n;
        var i = r.t = this.t+a.t-n;
        r.s = 0; // assumes a,this >= 0
        while(--i >= 0) r[i] = 0;
        for(i = Math.max(n-this.t,0); i < a.t; ++i)
          r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
        r.clamp();
        r.drShiftTo(1,r);
      }
  
      // Barrett modular reduction
      function Barrett(m) {
        // setup Barrett
        this.r2 = nbi();
        this.q3 = nbi();
        BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
        this.mu = this.r2.divide(m);
        this.m = m;
      }
  
      function barrettConvert(x) {
        if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
        else if(x.compareTo(this.m) < 0) return x;
        else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
      }
  
      function barrettRevert(x) { return x; }
  
      // x = x mod m (HAC 14.42)
      function barrettReduce(x) {
        x.drShiftTo(this.m.t-1,this.r2);
        if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
        this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
        this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
        while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
        x.subTo(this.r2,x);
        while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
      }
  
      // r = x^2 mod m; x != r
      function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
  
      // r = x*y mod m; x,y != r
      function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
  
      Barrett.prototype.convert = barrettConvert;
      Barrett.prototype.revert = barrettRevert;
      Barrett.prototype.reduce = barrettReduce;
      Barrett.prototype.mulTo = barrettMulTo;
      Barrett.prototype.sqrTo = barrettSqrTo;
  
      // (public) this^e % m (HAC 14.85)
      function bnModPow(e,m) {
        var i = e.bitLength(), k, r = nbv(1), z;
        if(i <= 0) return r;
        else if(i < 18) k = 1;
        else if(i < 48) k = 3;
        else if(i < 144) k = 4;
        else if(i < 768) k = 5;
        else k = 6;
        if(i < 8)
          z = new Classic(m);
        else if(m.isEven())
          z = new Barrett(m);
        else
          z = new Montgomery(m);
  
        // precomputation
        var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
        g[1] = z.convert(this);
        if(k > 1) {
          var g2 = nbi();
          z.sqrTo(g[1],g2);
          while(n <= km) {
            g[n] = nbi();
            z.mulTo(g2,g[n-2],g[n]);
            n += 2;
          }
        }
  
        var j = e.t-1, w, is1 = true, r2 = nbi(), t;
        i = nbits(e[j])-1;
        while(j >= 0) {
          if(i >= k1) w = (e[j]>>(i-k1))&km;
          else {
            w = (e[j]&((1<<(i+1))-1))<<(k1-i);
            if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
          }
  
          n = k;
          while((w&1) == 0) { w >>= 1; --n; }
          if((i -= n) < 0) { i += this.DB; --j; }
          if(is1) {	// ret == 1, don't bother squaring or multiplying it
            g[w].copyTo(r);
            is1 = false;
          }
          else {
            while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
            if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
            z.mulTo(r2,g[w],r);
          }
  
          while(j >= 0 && (e[j]&(1<<i)) == 0) {
            z.sqrTo(r,r2); t = r; r = r2; r2 = t;
            if(--i < 0) { i = this.DB-1; --j; }
          }
        }
        return z.revert(r);
      }
  
      // (public) gcd(this,a) (HAC 14.54)
      function bnGCD(a) {
        var x = (this.s<0)?this.negate():this.clone();
        var y = (a.s<0)?a.negate():a.clone();
        if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
        var i = x.getLowestSetBit(), g = y.getLowestSetBit();
        if(g < 0) return x;
        if(i < g) g = i;
        if(g > 0) {
          x.rShiftTo(g,x);
          y.rShiftTo(g,y);
        }
        while(x.signum() > 0) {
          if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
          if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
          if(x.compareTo(y) >= 0) {
            x.subTo(y,x);
            x.rShiftTo(1,x);
          }
          else {
            y.subTo(x,y);
            y.rShiftTo(1,y);
          }
        }
        if(g > 0) y.lShiftTo(g,y);
        return y;
      }
  
      // (protected) this % n, n < 2^26
      function bnpModInt(n) {
        if(n <= 0) return 0;
        var d = this.DV%n, r = (this.s<0)?n-1:0;
        if(this.t > 0)
          if(d == 0) r = this[0]%n;
          else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
        return r;
      }
  
      // (public) 1/this % m (HAC 14.61)
      function bnModInverse(m) {
        var ac = m.isEven();
        if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
        var u = m.clone(), v = this.clone();
        var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
        while(u.signum() != 0) {
          while(u.isEven()) {
            u.rShiftTo(1,u);
            if(ac) {
              if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
              a.rShiftTo(1,a);
            }
            else if(!b.isEven()) b.subTo(m,b);
            b.rShiftTo(1,b);
          }
          while(v.isEven()) {
            v.rShiftTo(1,v);
            if(ac) {
              if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
              c.rShiftTo(1,c);
            }
            else if(!d.isEven()) d.subTo(m,d);
            d.rShiftTo(1,d);
          }
          if(u.compareTo(v) >= 0) {
            u.subTo(v,u);
            if(ac) a.subTo(c,a);
            b.subTo(d,b);
          }
          else {
            v.subTo(u,v);
            if(ac) c.subTo(a,c);
            d.subTo(b,d);
          }
        }
        if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
        if(d.compareTo(m) >= 0) return d.subtract(m);
        if(d.signum() < 0) d.addTo(m,d); else return d;
        if(d.signum() < 0) return d.add(m); else return d;
      }
  
      var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
      var lplim = (1<<26)/lowprimes[lowprimes.length-1];
  
      // (public) test primality with certainty >= 1-.5^t
      function bnIsProbablePrime(t) {
        var i, x = this.abs();
        if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
          for(i = 0; i < lowprimes.length; ++i)
            if(x[0] == lowprimes[i]) return true;
          return false;
        }
        if(x.isEven()) return false;
        i = 1;
        while(i < lowprimes.length) {
          var m = lowprimes[i], j = i+1;
          while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
          m = x.modInt(m);
          while(i < j) if(m%lowprimes[i++] == 0) return false;
        }
        return x.millerRabin(t);
      }
  
      // (protected) true if probably prime (HAC 4.24, Miller-Rabin)
      function bnpMillerRabin(t) {
        var n1 = this.subtract(BigInteger.ONE);
        var k = n1.getLowestSetBit();
        if(k <= 0) return false;
        var r = n1.shiftRight(k);
        t = (t+1)>>1;
        if(t > lowprimes.length) t = lowprimes.length;
        var a = nbi();
        for(var i = 0; i < t; ++i) {
          //Pick bases at random, instead of starting at 2
          a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
          var y = a.modPow(r,this);
          if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
            var j = 1;
            while(j++ < k && y.compareTo(n1) != 0) {
              y = y.modPowInt(2,this);
              if(y.compareTo(BigInteger.ONE) == 0) return false;
            }
            if(y.compareTo(n1) != 0) return false;
          }
        }
        return true;
      }
  
      // protected
      BigInteger.prototype.chunkSize = bnpChunkSize;
      BigInteger.prototype.toRadix = bnpToRadix;
      BigInteger.prototype.fromRadix = bnpFromRadix;
      BigInteger.prototype.fromNumber = bnpFromNumber;
      BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
      BigInteger.prototype.changeBit = bnpChangeBit;
      BigInteger.prototype.addTo = bnpAddTo;
      BigInteger.prototype.dMultiply = bnpDMultiply;
      BigInteger.prototype.dAddOffset = bnpDAddOffset;
      BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
      BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
      BigInteger.prototype.modInt = bnpModInt;
      BigInteger.prototype.millerRabin = bnpMillerRabin;
  
      // public
      BigInteger.prototype.clone = bnClone;
      BigInteger.prototype.intValue = bnIntValue;
      BigInteger.prototype.byteValue = bnByteValue;
      BigInteger.prototype.shortValue = bnShortValue;
      BigInteger.prototype.signum = bnSigNum;
      BigInteger.prototype.toByteArray = bnToByteArray;
      BigInteger.prototype.equals = bnEquals;
      BigInteger.prototype.min = bnMin;
      BigInteger.prototype.max = bnMax;
      BigInteger.prototype.and = bnAnd;
      BigInteger.prototype.or = bnOr;
      BigInteger.prototype.xor = bnXor;
      BigInteger.prototype.andNot = bnAndNot;
      BigInteger.prototype.not = bnNot;
      BigInteger.prototype.shiftLeft = bnShiftLeft;
      BigInteger.prototype.shiftRight = bnShiftRight;
      BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
      BigInteger.prototype.bitCount = bnBitCount;
      BigInteger.prototype.testBit = bnTestBit;
      BigInteger.prototype.setBit = bnSetBit;
      BigInteger.prototype.clearBit = bnClearBit;
      BigInteger.prototype.flipBit = bnFlipBit;
      BigInteger.prototype.add = bnAdd;
      BigInteger.prototype.subtract = bnSubtract;
      BigInteger.prototype.multiply = bnMultiply;
      BigInteger.prototype.divide = bnDivide;
      BigInteger.prototype.remainder = bnRemainder;
      BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
      BigInteger.prototype.modPow = bnModPow;
      BigInteger.prototype.modInverse = bnModInverse;
      BigInteger.prototype.pow = bnPow;
      BigInteger.prototype.gcd = bnGCD;
      BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
  
      // JSBN-specific extension
      BigInteger.prototype.square = bnSquare;
  
      // BigInteger interfaces not implemented in jsbn:
  
      // BigInteger(int signum, byte[] magnitude)
      // double doubleValue()
      // float floatValue()
      // int hashCode()
      // long longValue()
      // static BigInteger valueOf(long val)
      if (typeof exports !== 'undefined') {
          exports = module.exports = BigInteger;
      } else {
          this.BigInteger = BigInteger;
      }
      
  }).call(this);
  },{}],16:[function(require,module,exports){
  /**
   * lodash 3.0.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * Copies the values of `source` to `array`.
   *
   * @private
   * @param {Array} source The array to copy values from.
   * @param {Array} [array=[]] The array to copy values to.
   * @returns {Array} Returns `array`.
   */
  function arrayCopy(source, array) {
    var index = -1,
        length = source.length;
  
    array || (array = Array(length));
    while (++index < length) {
      array[index] = source[index];
    }
    return array;
  }
  
  module.exports = arrayCopy;
  
  },{}],17:[function(require,module,exports){
  /**
   * lodash 3.0.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * A specialized version of `_.forEach` for arrays without support for callback
   * shorthands or `this` binding.
   *
   * @private
   * @param {Array} array The array to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array} Returns `array`.
   */
  function arrayEach(array, iteratee) {
    var index = -1,
        length = array.length;
  
    while (++index < length) {
      if (iteratee(array[index], index, array) === false) {
        break;
      }
    }
    return array;
  }
  
  module.exports = arrayEach;
  
  },{}],18:[function(require,module,exports){
  /**
   * lodash 3.3.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var baseIsEqual = require('lodash._baseisequal'),
      bindCallback = require('lodash._bindcallback'),
      isArray = require('lodash.isarray'),
      pairs = require('lodash.pairs');
  
  /** Used to match property names within property paths. */
  var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\n\\]|\\.)*?\1)\]/,
      reIsPlainProp = /^\w*$/,
      rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\n\\]|\\.)*?)\2)\]/g;
  
  /** Used to match backslashes in property paths. */
  var reEscapeChar = /\\(\\)?/g;
  
  /**
   * Converts `value` to a string if it's not one. An empty string is returned
   * for `null` or `undefined` values.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {string} Returns the string.
   */
  function baseToString(value) {
    return value == null ? '' : (value + '');
  }
  
  /**
   * The base implementation of `_.callback` which supports specifying the
   * number of arguments to provide to `func`.
   *
   * @private
   * @param {*} [func=_.identity] The value to convert to a callback.
   * @param {*} [thisArg] The `this` binding of `func`.
   * @param {number} [argCount] The number of arguments to provide to `func`.
   * @returns {Function} Returns the callback.
   */
  function baseCallback(func, thisArg, argCount) {
    var type = typeof func;
    if (type == 'function') {
      return thisArg === undefined
        ? func
        : bindCallback(func, thisArg, argCount);
    }
    if (func == null) {
      return identity;
    }
    if (type == 'object') {
      return baseMatches(func);
    }
    return thisArg === undefined
      ? property(func)
      : baseMatchesProperty(func, thisArg);
  }
  
  /**
   * The base implementation of `get` without support for string paths
   * and default values.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {Array} path The path of the property to get.
   * @param {string} [pathKey] The key representation of path.
   * @returns {*} Returns the resolved value.
   */
  function baseGet(object, path, pathKey) {
    if (object == null) {
      return;
    }
    if (pathKey !== undefined && pathKey in toObject(object)) {
      path = [pathKey];
    }
    var index = 0,
        length = path.length;
  
    while (object != null && index < length) {
      object = object[path[index++]];
    }
    return (index && index == length) ? object : undefined;
  }
  
  /**
   * The base implementation of `_.isMatch` without support for callback
   * shorthands and `this` binding.
   *
   * @private
   * @param {Object} object The object to inspect.
   * @param {Array} matchData The propery names, values, and compare flags to match.
   * @param {Function} [customizer] The function to customize comparing objects.
   * @returns {boolean} Returns `true` if `object` is a match, else `false`.
   */
  function baseIsMatch(object, matchData, customizer) {
    var index = matchData.length,
        length = index,
        noCustomizer = !customizer;
  
    if (object == null) {
      return !length;
    }
    object = toObject(object);
    while (index--) {
      var data = matchData[index];
      if ((noCustomizer && data[2])
            ? data[1] !== object[data[0]]
            : !(data[0] in object)
          ) {
        return false;
      }
    }
    while (++index < length) {
      data = matchData[index];
      var key = data[0],
          objValue = object[key],
          srcValue = data[1];
  
      if (noCustomizer && data[2]) {
        if (objValue === undefined && !(key in object)) {
          return false;
        }
      } else {
        var result = customizer ? customizer(objValue, srcValue, key) : undefined;
        if (!(result === undefined ? baseIsEqual(srcValue, objValue, customizer, true) : result)) {
          return false;
        }
      }
    }
    return true;
  }
  
  /**
   * The base implementation of `_.matches` which does not clone `source`.
   *
   * @private
   * @param {Object} source The object of property values to match.
   * @returns {Function} Returns the new function.
   */
  function baseMatches(source) {
    var matchData = getMatchData(source);
    if (matchData.length == 1 && matchData[0][2]) {
      var key = matchData[0][0],
          value = matchData[0][1];
  
      return function(object) {
        if (object == null) {
          return false;
        }
        return object[key] === value && (value !== undefined || (key in toObject(object)));
      };
    }
    return function(object) {
      return baseIsMatch(object, matchData);
    };
  }
  
  /**
   * The base implementation of `_.matchesProperty` which does not clone `srcValue`.
   *
   * @private
   * @param {string} path The path of the property to get.
   * @param {*} srcValue The value to compare.
   * @returns {Function} Returns the new function.
   */
  function baseMatchesProperty(path, srcValue) {
    var isArr = isArray(path),
        isCommon = isKey(path) && isStrictComparable(srcValue),
        pathKey = (path + '');
  
    path = toPath(path);
    return function(object) {
      if (object == null) {
        return false;
      }
      var key = pathKey;
      object = toObject(object);
      if ((isArr || !isCommon) && !(key in object)) {
        object = path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
        if (object == null) {
          return false;
        }
        key = last(path);
        object = toObject(object);
      }
      return object[key] === srcValue
        ? (srcValue !== undefined || (key in object))
        : baseIsEqual(srcValue, object[key], undefined, true);
    };
  }
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  /**
   * A specialized version of `baseProperty` which supports deep paths.
   *
   * @private
   * @param {Array|string} path The path of the property to get.
   * @returns {Function} Returns the new function.
   */
  function basePropertyDeep(path) {
    var pathKey = (path + '');
    path = toPath(path);
    return function(object) {
      return baseGet(object, path, pathKey);
    };
  }
  
  /**
   * The base implementation of `_.slice` without an iteratee call guard.
   *
   * @private
   * @param {Array} array The array to slice.
   * @param {number} [start=0] The start position.
   * @param {number} [end=array.length] The end position.
   * @returns {Array} Returns the slice of `array`.
   */
  function baseSlice(array, start, end) {
    var index = -1,
        length = array.length;
  
    start = start == null ? 0 : (+start || 0);
    if (start < 0) {
      start = -start > length ? 0 : (length + start);
    }
    end = (end === undefined || end > length) ? length : (+end || 0);
    if (end < 0) {
      end += length;
    }
    length = start > end ? 0 : ((end - start) >>> 0);
    start >>>= 0;
  
    var result = Array(length);
    while (++index < length) {
      result[index] = array[index + start];
    }
    return result;
  }
  
  /**
   * Gets the propery names, values, and compare flags of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the match data of `object`.
   */
  function getMatchData(object) {
    var result = pairs(object),
        length = result.length;
  
    while (length--) {
      result[length][2] = isStrictComparable(result[length][1]);
    }
    return result;
  }
  
  /**
   * Checks if `value` is a property name and not a property path.
   *
   * @private
   * @param {*} value The value to check.
   * @param {Object} [object] The object to query keys on.
   * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
   */
  function isKey(value, object) {
    var type = typeof value;
    if ((type == 'string' && reIsPlainProp.test(value)) || type == 'number') {
      return true;
    }
    if (isArray(value)) {
      return false;
    }
    var result = !reIsDeepProp.test(value);
    return result || (object != null && value in toObject(object));
  }
  
  /**
   * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` if suitable for strict
   *  equality comparisons, else `false`.
   */
  function isStrictComparable(value) {
    return value === value && !isObject(value);
  }
  
  /**
   * Converts `value` to an object if it's not one.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {Object} Returns the object.
   */
  function toObject(value) {
    return isObject(value) ? value : Object(value);
  }
  
  /**
   * Converts `value` to property path array if it's not one.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {Array} Returns the property path array.
   */
  function toPath(value) {
    if (isArray(value)) {
      return value;
    }
    var result = [];
    baseToString(value).replace(rePropName, function(match, number, quote, string) {
      result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
    });
    return result;
  }
  
  /**
   * Gets the last element of `array`.
   *
   * @static
   * @memberOf _
   * @category Array
   * @param {Array} array The array to query.
   * @returns {*} Returns the last element of `array`.
   * @example
   *
   * _.last([1, 2, 3]);
   * // => 3
   */
  function last(array) {
    var length = array ? array.length : 0;
    return length ? array[length - 1] : undefined;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * This method returns the first argument provided to it.
   *
   * @static
   * @memberOf _
   * @category Utility
   * @param {*} value Any value.
   * @returns {*} Returns `value`.
   * @example
   *
   * var object = { 'user': 'fred' };
   *
   * _.identity(object) === object;
   * // => true
   */
  function identity(value) {
    return value;
  }
  
  /**
   * Creates a function that returns the property value at `path` on a
   * given object.
   *
   * @static
   * @memberOf _
   * @category Utility
   * @param {Array|string} path The path of the property to get.
   * @returns {Function} Returns the new function.
   * @example
   *
   * var objects = [
   *   { 'a': { 'b': { 'c': 2 } } },
   *   { 'a': { 'b': { 'c': 1 } } }
   * ];
   *
   * _.map(objects, _.property('a.b.c'));
   * // => [2, 1]
   *
   * _.pluck(_.sortBy(objects, _.property(['a', 'b', 'c'])), 'a.b.c');
   * // => [1, 2]
   */
  function property(path) {
    return isKey(path) ? baseProperty(path) : basePropertyDeep(path);
  }
  
  module.exports = baseCallback;
  
  },{"lodash._baseisequal":24,"lodash._bindcallback":25,"lodash.isarray":31,"lodash.pairs":37}],19:[function(require,module,exports){
  /**
   * lodash 3.0.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * Copies properties of `source` to `object`.
   *
   * @private
   * @param {Object} source The object to copy properties from.
   * @param {Array} props The property names to copy.
   * @param {Object} [object={}] The object to copy properties to.
   * @returns {Object} Returns `object`.
   */
  function baseCopy(source, props, object) {
    object || (object = {});
  
    var index = -1,
        length = props.length;
  
    while (++index < length) {
      var key = props[index];
      object[key] = source[key];
    }
    return object;
  }
  
  module.exports = baseCopy;
  
  },{}],20:[function(require,module,exports){
  /**
   * lodash 3.0.4 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var keys = require('lodash.keys');
  
  /**
   * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * The base implementation of `_.forEach` without support for callback
   * shorthands and `this` binding.
   *
   * @private
   * @param {Array|Object|string} collection The collection to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Array|Object|string} Returns `collection`.
   */
  var baseEach = createBaseEach(baseForOwn);
  
  /**
   * The base implementation of `baseForIn` and `baseForOwn` which iterates
   * over `object` properties returned by `keysFunc` invoking `iteratee` for
   * each property. Iteratee functions may exit iteration early by explicitly
   * returning `false`.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @returns {Object} Returns `object`.
   */
  var baseFor = createBaseFor();
  
  /**
   * The base implementation of `_.forOwn` without support for callback
   * shorthands and `this` binding.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Object} Returns `object`.
   */
  function baseForOwn(object, iteratee) {
    return baseFor(object, iteratee, keys);
  }
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  /**
   * Creates a `baseEach` or `baseEachRight` function.
   *
   * @private
   * @param {Function} eachFunc The function to iterate over a collection.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new base function.
   */
  function createBaseEach(eachFunc, fromRight) {
    return function(collection, iteratee) {
      var length = collection ? getLength(collection) : 0;
      if (!isLength(length)) {
        return eachFunc(collection, iteratee);
      }
      var index = fromRight ? length : -1,
          iterable = toObject(collection);
  
      while ((fromRight ? index-- : ++index < length)) {
        if (iteratee(iterable[index], index, iterable) === false) {
          break;
        }
      }
      return collection;
    };
  }
  
  /**
   * Creates a base function for `_.forIn` or `_.forInRight`.
   *
   * @private
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new base function.
   */
  function createBaseFor(fromRight) {
    return function(object, iteratee, keysFunc) {
      var iterable = toObject(object),
          props = keysFunc(object),
          length = props.length,
          index = fromRight ? length : -1;
  
      while ((fromRight ? index-- : ++index < length)) {
        var key = props[index];
        if (iteratee(iterable[key], key, iterable) === false) {
          break;
        }
      }
      return object;
    };
  }
  
  /**
   * Gets the "length" property value of `object`.
   *
   * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
   * that affects Safari on at least iOS 8.1-8.3 ARM64.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {*} Returns the "length" value.
   */
  var getLength = baseProperty('length');
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Converts `value` to an object if it's not one.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {Object} Returns the object.
   */
  function toObject(value) {
    return isObject(value) ? value : Object(value);
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  module.exports = baseEach;
  
  },{"lodash.keys":34}],21:[function(require,module,exports){
  /**
   * lodash 3.0.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * The base implementation of `_.find`, `_.findLast`, `_.findKey`, and `_.findLastKey`,
   * without support for callback shorthands and `this` binding, which iterates
   * over `collection` using the provided `eachFunc`.
   *
   * @private
   * @param {Array|Object|string} collection The collection to search.
   * @param {Function} predicate The function invoked per iteration.
   * @param {Function} eachFunc The function to iterate over `collection`.
   * @param {boolean} [retKey] Specify returning the key of the found element
   *  instead of the element itself.
   * @returns {*} Returns the found element or its key, else `undefined`.
   */
  function baseFind(collection, predicate, eachFunc, retKey) {
    var result;
    eachFunc(collection, function(value, key, collection) {
      if (predicate(value, key, collection)) {
        result = retKey ? key : value;
        return false;
      }
    });
    return result;
  }
  
  module.exports = baseFind;
  
  },{}],22:[function(require,module,exports){
  /**
   * lodash 3.6.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.2 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * The base implementation of `_.findIndex` and `_.findLastIndex` without
   * support for callback shorthands and `this` binding.
   *
   * @private
   * @param {Array} array The array to search.
   * @param {Function} predicate The function invoked per iteration.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {number} Returns the index of the matched value, else `-1`.
   */
  function baseFindIndex(array, predicate, fromRight) {
    var length = array.length,
        index = fromRight ? length : -1;
  
    while ((fromRight ? index-- : ++index < length)) {
      if (predicate(array[index], index, array)) {
        return index;
      }
    }
    return -1;
  }
  
  module.exports = baseFindIndex;
  
  },{}],23:[function(require,module,exports){
  /**
   * lodash 3.0.3 (Custom Build) <https://lodash.com/>
   * Build: `lodash modularize exports="npm" -o ./`
   * Copyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2016 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * The base implementation of `baseForIn` and `baseForOwn` which iterates
   * over `object` properties returned by `keysFunc` invoking `iteratee` for
   * each property. Iteratee functions may exit iteration early by explicitly
   * returning `false`.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @param {Function} keysFunc The function to get the keys of `object`.
   * @returns {Object} Returns `object`.
   */
  var baseFor = createBaseFor();
  
  /**
   * Creates a base function for methods like `_.forIn`.
   *
   * @private
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new base function.
   */
  function createBaseFor(fromRight) {
    return function(object, iteratee, keysFunc) {
      var index = -1,
          iterable = Object(object),
          props = keysFunc(object),
          length = props.length;
  
      while (length--) {
        var key = props[fromRight ? length : ++index];
        if (iteratee(iterable[key], key, iterable) === false) {
          break;
        }
      }
      return object;
    };
  }
  
  module.exports = baseFor;
  
  },{}],24:[function(require,module,exports){
  /**
   * lodash 3.0.7 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var isArray = require('lodash.isarray'),
      isTypedArray = require('lodash.istypedarray'),
      keys = require('lodash.keys');
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      regexpTag = '[object RegExp]',
      stringTag = '[object String]';
  
  /**
   * Checks if `value` is object-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the [`toStringTag`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-object.prototype.tostring)
   * of values.
   */
  var objToString = objectProto.toString;
  
  /**
   * A specialized version of `_.some` for arrays without support for callback
   * shorthands and `this` binding.
   *
   * @private
   * @param {Array} array The array to iterate over.
   * @param {Function} predicate The function invoked per iteration.
   * @returns {boolean} Returns `true` if any element passes the predicate check,
   *  else `false`.
   */
  function arraySome(array, predicate) {
    var index = -1,
        length = array.length;
  
    while (++index < length) {
      if (predicate(array[index], index, array)) {
        return true;
      }
    }
    return false;
  }
  
  /**
   * The base implementation of `_.isEqual` without support for `this` binding
   * `customizer` functions.
   *
   * @private
   * @param {*} value The value to compare.
   * @param {*} other The other value to compare.
   * @param {Function} [customizer] The function to customize comparing values.
   * @param {boolean} [isLoose] Specify performing partial comparisons.
   * @param {Array} [stackA] Tracks traversed `value` objects.
   * @param {Array} [stackB] Tracks traversed `other` objects.
   * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
   */
  function baseIsEqual(value, other, customizer, isLoose, stackA, stackB) {
    if (value === other) {
      return true;
    }
    if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
      return value !== value && other !== other;
    }
    return baseIsEqualDeep(value, other, baseIsEqual, customizer, isLoose, stackA, stackB);
  }
  
  /**
   * A specialized version of `baseIsEqual` for arrays and objects which performs
   * deep comparisons and tracks traversed objects enabling objects with circular
   * references to be compared.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Function} [customizer] The function to customize comparing objects.
   * @param {boolean} [isLoose] Specify performing partial comparisons.
   * @param {Array} [stackA=[]] Tracks traversed `value` objects.
   * @param {Array} [stackB=[]] Tracks traversed `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function baseIsEqualDeep(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
    var objIsArr = isArray(object),
        othIsArr = isArray(other),
        objTag = arrayTag,
        othTag = arrayTag;
  
    if (!objIsArr) {
      objTag = objToString.call(object);
      if (objTag == argsTag) {
        objTag = objectTag;
      } else if (objTag != objectTag) {
        objIsArr = isTypedArray(object);
      }
    }
    if (!othIsArr) {
      othTag = objToString.call(other);
      if (othTag == argsTag) {
        othTag = objectTag;
      } else if (othTag != objectTag) {
        othIsArr = isTypedArray(other);
      }
    }
    var objIsObj = objTag == objectTag,
        othIsObj = othTag == objectTag,
        isSameTag = objTag == othTag;
  
    if (isSameTag && !(objIsArr || objIsObj)) {
      return equalByTag(object, other, objTag);
    }
    if (!isLoose) {
      var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
          othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
  
      if (objIsWrapped || othIsWrapped) {
        return equalFunc(objIsWrapped ? object.value() : object, othIsWrapped ? other.value() : other, customizer, isLoose, stackA, stackB);
      }
    }
    if (!isSameTag) {
      return false;
    }
    // Assume cyclic values are equal.
    // For more information on detecting circular references see https://es5.github.io/#JO.
    stackA || (stackA = []);
    stackB || (stackB = []);
  
    var length = stackA.length;
    while (length--) {
      if (stackA[length] == object) {
        return stackB[length] == other;
      }
    }
    // Add `object` and `other` to the stack of traversed objects.
    stackA.push(object);
    stackB.push(other);
  
    var result = (objIsArr ? equalArrays : equalObjects)(object, other, equalFunc, customizer, isLoose, stackA, stackB);
  
    stackA.pop();
    stackB.pop();
  
    return result;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for arrays with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Array} array The array to compare.
   * @param {Array} other The other array to compare.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Function} [customizer] The function to customize comparing arrays.
   * @param {boolean} [isLoose] Specify performing partial comparisons.
   * @param {Array} [stackA] Tracks traversed `value` objects.
   * @param {Array} [stackB] Tracks traversed `other` objects.
   * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
   */
  function equalArrays(array, other, equalFunc, customizer, isLoose, stackA, stackB) {
    var index = -1,
        arrLength = array.length,
        othLength = other.length;
  
    if (arrLength != othLength && !(isLoose && othLength > arrLength)) {
      return false;
    }
    // Ignore non-index properties.
    while (++index < arrLength) {
      var arrValue = array[index],
          othValue = other[index],
          result = customizer ? customizer(isLoose ? othValue : arrValue, isLoose ? arrValue : othValue, index) : undefined;
  
      if (result !== undefined) {
        if (result) {
          continue;
        }
        return false;
      }
      // Recursively compare arrays (susceptible to call stack limits).
      if (isLoose) {
        if (!arraySome(other, function(othValue) {
              return arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB);
            })) {
          return false;
        }
      } else if (!(arrValue === othValue || equalFunc(arrValue, othValue, customizer, isLoose, stackA, stackB))) {
        return false;
      }
    }
    return true;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for comparing objects of
   * the same `toStringTag`.
   *
   * **Note:** This function only supports comparing values with tags of
   * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
   *
   * @private
   * @param {Object} value The object to compare.
   * @param {Object} other The other object to compare.
   * @param {string} tag The `toStringTag` of the objects to compare.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalByTag(object, other, tag) {
    switch (tag) {
      case boolTag:
      case dateTag:
        // Coerce dates and booleans to numbers, dates to milliseconds and booleans
        // to `1` or `0` treating invalid dates coerced to `NaN` as not equal.
        return +object == +other;
  
      case errorTag:
        return object.name == other.name && object.message == other.message;
  
      case numberTag:
        // Treat `NaN` vs. `NaN` as equal.
        return (object != +object)
          ? other != +other
          : object == +other;
  
      case regexpTag:
      case stringTag:
        // Coerce regexes to strings and treat strings primitives and string
        // objects as equal. See https://es5.github.io/#x15.10.6.4 for more details.
        return object == (other + '');
    }
    return false;
  }
  
  /**
   * A specialized version of `baseIsEqualDeep` for objects with support for
   * partial deep comparisons.
   *
   * @private
   * @param {Object} object The object to compare.
   * @param {Object} other The other object to compare.
   * @param {Function} equalFunc The function to determine equivalents of values.
   * @param {Function} [customizer] The function to customize comparing values.
   * @param {boolean} [isLoose] Specify performing partial comparisons.
   * @param {Array} [stackA] Tracks traversed `value` objects.
   * @param {Array} [stackB] Tracks traversed `other` objects.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function equalObjects(object, other, equalFunc, customizer, isLoose, stackA, stackB) {
    var objProps = keys(object),
        objLength = objProps.length,
        othProps = keys(other),
        othLength = othProps.length;
  
    if (objLength != othLength && !isLoose) {
      return false;
    }
    var index = objLength;
    while (index--) {
      var key = objProps[index];
      if (!(isLoose ? key in other : hasOwnProperty.call(other, key))) {
        return false;
      }
    }
    var skipCtor = isLoose;
    while (++index < objLength) {
      key = objProps[index];
      var objValue = object[key],
          othValue = other[key],
          result = customizer ? customizer(isLoose ? othValue : objValue, isLoose? objValue : othValue, key) : undefined;
  
      // Recursively compare objects (susceptible to call stack limits).
      if (!(result === undefined ? equalFunc(objValue, othValue, customizer, isLoose, stackA, stackB) : result)) {
        return false;
      }
      skipCtor || (skipCtor = key == 'constructor');
    }
    if (!skipCtor) {
      var objCtor = object.constructor,
          othCtor = other.constructor;
  
      // Non `Object` object instances with different constructors are not equal.
      if (objCtor != othCtor &&
          ('constructor' in object && 'constructor' in other) &&
          !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
            typeof othCtor == 'function' && othCtor instanceof othCtor)) {
        return false;
      }
    }
    return true;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  module.exports = baseIsEqual;
  
  },{"lodash.isarray":31,"lodash.istypedarray":33,"lodash.keys":34}],25:[function(require,module,exports){
  /**
   * lodash 3.0.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /**
   * A specialized version of `baseCallback` which only supports `this` binding
   * and specifying the number of arguments to provide to `func`.
   *
   * @private
   * @param {Function} func The function to bind.
   * @param {*} thisArg The `this` binding of `func`.
   * @param {number} [argCount] The number of arguments to provide to `func`.
   * @returns {Function} Returns the callback.
   */
  function bindCallback(func, thisArg, argCount) {
    if (typeof func != 'function') {
      return identity;
    }
    if (thisArg === undefined) {
      return func;
    }
    switch (argCount) {
      case 1: return function(value) {
        return func.call(thisArg, value);
      };
      case 3: return function(value, index, collection) {
        return func.call(thisArg, value, index, collection);
      };
      case 4: return function(accumulator, value, index, collection) {
        return func.call(thisArg, accumulator, value, index, collection);
      };
      case 5: return function(value, other, key, object, source) {
        return func.call(thisArg, value, other, key, object, source);
      };
    }
    return function() {
      return func.apply(thisArg, arguments);
    };
  }
  
  /**
   * This method returns the first argument provided to it.
   *
   * @static
   * @memberOf _
   * @category Utility
   * @param {*} value Any value.
   * @returns {*} Returns `value`.
   * @example
   *
   * var object = { 'user': 'fred' };
   *
   * _.identity(object) === object;
   * // => true
   */
  function identity(value) {
    return value;
  }
  
  module.exports = bindCallback;
  
  },{}],26:[function(require,module,exports){
  /**
   * lodash 3.1.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var bindCallback = require('lodash._bindcallback'),
      isIterateeCall = require('lodash._isiterateecall'),
      restParam = require('lodash.restparam');
  
  /**
   * Creates a function that assigns properties of source object(s) to a given
   * destination object.
   *
   * **Note:** This function is used to create `_.assign`, `_.defaults`, and `_.merge`.
   *
   * @private
   * @param {Function} assigner The function to assign values.
   * @returns {Function} Returns the new assigner function.
   */
  function createAssigner(assigner) {
    return restParam(function(object, sources) {
      var index = -1,
          length = object == null ? 0 : sources.length,
          customizer = length > 2 ? sources[length - 2] : undefined,
          guard = length > 2 ? sources[2] : undefined,
          thisArg = length > 1 ? sources[length - 1] : undefined;
  
      if (typeof customizer == 'function') {
        customizer = bindCallback(customizer, thisArg, 5);
        length -= 2;
      } else {
        customizer = typeof thisArg == 'function' ? thisArg : undefined;
        length -= (customizer ? 1 : 0);
      }
      if (guard && isIterateeCall(sources[0], sources[1], guard)) {
        customizer = length < 3 ? undefined : customizer;
        length = 1;
      }
      while (++index < length) {
        var source = sources[index];
        if (source) {
          assigner(object, source, customizer);
        }
      }
      return object;
    });
  }
  
  module.exports = createAssigner;
  
  },{"lodash._bindcallback":25,"lodash._isiterateecall":28,"lodash.restparam":38}],27:[function(require,module,exports){
  /**
   * lodash 3.9.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /** `Object#toString` result references. */
  var funcTag = '[object Function]';
  
  /** Used to detect host constructors (Safari > 5). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  
  /**
   * Checks if `value` is object-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to resolve the decompiled source of functions. */
  var fnToString = Function.prototype.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objToString = objectProto.toString;
  
  /** Used to detect if a method is native. */
  var reIsNative = RegExp('^' +
    fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  /**
   * Gets the native function at `key` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {string} key The key of the method to get.
   * @returns {*} Returns the function if it's native, else `undefined`.
   */
  function getNative(object, key) {
    var value = object == null ? undefined : object[key];
    return isNative(value) ? value : undefined;
  }
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in older versions of Chrome and Safari which return 'function' for regexes
    // and Safari 8 equivalents which return 'object' for typed array constructors.
    return isObject(value) && objToString.call(value) == funcTag;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Checks if `value` is a native function.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
   * @example
   *
   * _.isNative(Array.prototype.push);
   * // => true
   *
   * _.isNative(_);
   * // => false
   */
  function isNative(value) {
    if (value == null) {
      return false;
    }
    if (isFunction(value)) {
      return reIsNative.test(fnToString.call(value));
    }
    return isObjectLike(value) && reIsHostCtor.test(value);
  }
  
  module.exports = getNative;
  
  },{}],28:[function(require,module,exports){
  /**
   * lodash 3.0.9 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^\d+$/;
  
  /**
   * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  /**
   * Gets the "length" property value of `object`.
   *
   * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
   * that affects Safari on at least iOS 8.1-8.3 ARM64.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {*} Returns the "length" value.
   */
  var getLength = baseProperty('length');
  
  /**
   * Checks if `value` is array-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   */
  function isArrayLike(value) {
    return value != null && isLength(getLength(value));
  }
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
    length = length == null ? MAX_SAFE_INTEGER : length;
    return value > -1 && value % 1 == 0 && value < length;
  }
  
  /**
   * Checks if the provided arguments are from an iteratee call.
   *
   * @private
   * @param {*} value The potential iteratee value argument.
   * @param {*} index The potential iteratee index or key argument.
   * @param {*} object The potential iteratee object argument.
   * @returns {boolean} Returns `true` if the arguments are from an iteratee call, else `false`.
   */
  function isIterateeCall(value, index, object) {
    if (!isObject(object)) {
      return false;
    }
    var type = typeof index;
    if (type == 'number'
        ? (isArrayLike(object) && isIndex(index, object.length))
        : (type == 'string' && index in object)) {
      var other = object[index];
      return value === value ? (value === other) : (other !== other);
    }
    return false;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  module.exports = isIterateeCall;
  
  },{}],29:[function(require,module,exports){
  /**
   * lodash 3.2.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var baseCallback = require('lodash._basecallback'),
      baseEach = require('lodash._baseeach'),
      baseFind = require('lodash._basefind'),
      baseFindIndex = require('lodash._basefindindex'),
      isArray = require('lodash.isarray');
  
  /**
   * Creates a `_.find` or `_.findLast` function.
   *
   * @private
   * @param {Function} eachFunc The function to iterate over a collection.
   * @param {boolean} [fromRight] Specify iterating from right to left.
   * @returns {Function} Returns the new find function.
   */
  function createFind(eachFunc, fromRight) {
    return function(collection, predicate, thisArg) {
      predicate = baseCallback(predicate, thisArg, 3);
      if (isArray(collection)) {
        var index = baseFindIndex(collection, predicate, fromRight);
        return index > -1 ? collection[index] : undefined;
      }
      return baseFind(collection, predicate, eachFunc);
    };
  }
  
  /**
   * Iterates over elements of `collection`, returning the first element
   * `predicate` returns truthy for. The predicate is bound to `thisArg` and
   * invoked with three arguments: (value, index|key, collection).
   *
   * If a property name is provided for `predicate` the created `_.property`
   * style callback returns the property value of the given element.
   *
   * If a value is also provided for `thisArg` the created `_.matchesProperty`
   * style callback returns `true` for elements that have a matching property
   * value, else `false`.
   *
   * If an object is provided for `predicate` the created `_.matches` style
   * callback returns `true` for elements that have the properties of the given
   * object, else `false`.
   *
   * @static
   * @memberOf _
   * @alias detect
   * @category Collection
   * @param {Array|Object|string} collection The collection to search.
   * @param {Function|Object|string} [predicate=_.identity] The function invoked
   *  per iteration.
   * @param {*} [thisArg] The `this` binding of `predicate`.
   * @returns {*} Returns the matched element, else `undefined`.
   * @example
   *
   * var users = [
   *   { 'user': 'barney',  'age': 36, 'active': true },
   *   { 'user': 'fred',    'age': 40, 'active': false },
   *   { 'user': 'pebbles', 'age': 1,  'active': true }
   * ];
   *
   * _.result(_.find(users, function(chr) {
   *   return chr.age < 40;
   * }), 'user');
   * // => 'barney'
   *
   * // using the `_.matches` callback shorthand
   * _.result(_.find(users, { 'age': 1, 'active': true }), 'user');
   * // => 'pebbles'
   *
   * // using the `_.matchesProperty` callback shorthand
   * _.result(_.find(users, 'active', false), 'user');
   * // => 'fred'
   *
   * // using the `_.property` callback shorthand
   * _.result(_.find(users, 'active'), 'user');
   * // => 'barney'
   */
  var find = createFind(baseEach);
  
  module.exports = find;
  
  },{"lodash._basecallback":18,"lodash._baseeach":20,"lodash._basefind":21,"lodash._basefindindex":22,"lodash.isarray":31}],30:[function(require,module,exports){
  /**
   * lodash (Custom Build) <https://lodash.com/>
   * Build: `lodash modularize exports="npm" -o ./`
   * Copyright jQuery Foundation and other contributors <https://jquery.org/>
   * Released under MIT license <https://lodash.com/license>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   */
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      funcTag = '[object Function]',
      genTag = '[object GeneratorFunction]';
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the
   * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objectToString = objectProto.toString;
  
  /** Built-in value references. */
  var propertyIsEnumerable = objectProto.propertyIsEnumerable;
  
  /**
   * Checks if `value` is likely an `arguments` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an `arguments` object,
   *  else `false`.
   * @example
   *
   * _.isArguments(function() { return arguments; }());
   * // => true
   *
   * _.isArguments([1, 2, 3]);
   * // => false
   */
  function isArguments(value) {
    // Safari 8.1 makes `arguments.callee` enumerable in strict mode.
    return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
      (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
  }
  
  /**
   * Checks if `value` is array-like. A value is considered array-like if it's
   * not a function and has a `value.length` that's an integer greater than or
   * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   * @example
   *
   * _.isArrayLike([1, 2, 3]);
   * // => true
   *
   * _.isArrayLike(document.body.children);
   * // => true
   *
   * _.isArrayLike('abc');
   * // => true
   *
   * _.isArrayLike(_.noop);
   * // => false
   */
  function isArrayLike(value) {
    return value != null && isLength(value.length) && !isFunction(value);
  }
  
  /**
   * This method is like `_.isArrayLike` except that it also checks if `value`
   * is an object.
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an array-like object,
   *  else `false`.
   * @example
   *
   * _.isArrayLikeObject([1, 2, 3]);
   * // => true
   *
   * _.isArrayLikeObject(document.body.children);
   * // => true
   *
   * _.isArrayLikeObject('abc');
   * // => false
   *
   * _.isArrayLikeObject(_.noop);
   * // => false
   */
  function isArrayLikeObject(value) {
    return isObjectLike(value) && isArrayLike(value);
  }
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a function, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in Safari 8-9 which returns 'object' for typed array and other constructors.
    var tag = isObject(value) ? objectToString.call(value) : '';
    return tag == funcTag || tag == genTag;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This method is loosely based on
   * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   * @example
   *
   * _.isLength(3);
   * // => true
   *
   * _.isLength(Number.MIN_VALUE);
   * // => false
   *
   * _.isLength(Infinity);
   * // => false
   *
   * _.isLength('3');
   * // => false
   */
  function isLength(value) {
    return typeof value == 'number' &&
      value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the
   * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
   * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @since 0.1.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(_.noop);
   * // => true
   *
   * _.isObject(null);
   * // => false
   */
  function isObject(value) {
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Checks if `value` is object-like. A value is object-like if it's not `null`
   * and has a `typeof` result of "object".
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   * @example
   *
   * _.isObjectLike({});
   * // => true
   *
   * _.isObjectLike([1, 2, 3]);
   * // => true
   *
   * _.isObjectLike(_.noop);
   * // => false
   *
   * _.isObjectLike(null);
   * // => false
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  module.exports = isArguments;
  
  },{}],31:[function(require,module,exports){
  /**
   * lodash 3.0.4 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /** `Object#toString` result references. */
  var arrayTag = '[object Array]',
      funcTag = '[object Function]';
  
  /** Used to detect host constructors (Safari > 5). */
  var reIsHostCtor = /^\[object .+?Constructor\]$/;
  
  /**
   * Checks if `value` is object-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to resolve the decompiled source of functions. */
  var fnToString = Function.prototype.toString;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objToString = objectProto.toString;
  
  /** Used to detect if a method is native. */
  var reIsNative = RegExp('^' +
    fnToString.call(hasOwnProperty).replace(/[\\^$.*+?()[\]{}|]/g, '\\$&')
    .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
  );
  
  /* Native method references for those with the same name as other `lodash` methods. */
  var nativeIsArray = getNative(Array, 'isArray');
  
  /**
   * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * Gets the native function at `key` of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @param {string} key The key of the method to get.
   * @returns {*} Returns the function if it's native, else `undefined`.
   */
  function getNative(object, key) {
    var value = object == null ? undefined : object[key];
    return isNative(value) ? value : undefined;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is classified as an `Array` object.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
   * @example
   *
   * _.isArray([1, 2, 3]);
   * // => true
   *
   * _.isArray(function() { return arguments; }());
   * // => false
   */
  var isArray = nativeIsArray || function(value) {
    return isObjectLike(value) && isLength(value.length) && objToString.call(value) == arrayTag;
  };
  
  /**
   * Checks if `value` is classified as a `Function` object.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is correctly classified, else `false`.
   * @example
   *
   * _.isFunction(_);
   * // => true
   *
   * _.isFunction(/abc/);
   * // => false
   */
  function isFunction(value) {
    // The use of `Object#toString` avoids issues with the `typeof` operator
    // in older versions of Chrome and Safari which return 'function' for regexes
    // and Safari 8 equivalents which return 'object' for typed array constructors.
    return isObject(value) && objToString.call(value) == funcTag;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Checks if `value` is a native function.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a native function, else `false`.
   * @example
   *
   * _.isNative(Array.prototype.push);
   * // => true
   *
   * _.isNative(_);
   * // => false
   */
  function isNative(value) {
    if (value == null) {
      return false;
    }
    if (isFunction(value)) {
      return reIsNative.test(fnToString.call(value));
    }
    return isObjectLike(value) && reIsHostCtor.test(value);
  }
  
  module.exports = isArray;
  
  },{}],32:[function(require,module,exports){
  /**
   * lodash 3.2.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var baseFor = require('lodash._basefor'),
      isArguments = require('lodash.isarguments'),
      keysIn = require('lodash.keysin');
  
  /** `Object#toString` result references. */
  var objectTag = '[object Object]';
  
  /**
   * Checks if `value` is object-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objToString = objectProto.toString;
  
  /**
   * The base implementation of `_.forIn` without support for callback
   * shorthands and `this` binding.
   *
   * @private
   * @param {Object} object The object to iterate over.
   * @param {Function} iteratee The function invoked per iteration.
   * @returns {Object} Returns `object`.
   */
  function baseForIn(object, iteratee) {
    return baseFor(object, iteratee, keysIn);
  }
  
  /**
   * Checks if `value` is a plain object, that is, an object created by the
   * `Object` constructor or one with a `[[Prototype]]` of `null`.
   *
   * **Note:** This method assumes objects created by the `Object` constructor
   * have no inherited enumerable properties.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   * }
   *
   * _.isPlainObject(new Foo);
   * // => false
   *
   * _.isPlainObject([1, 2, 3]);
   * // => false
   *
   * _.isPlainObject({ 'x': 0, 'y': 0 });
   * // => true
   *
   * _.isPlainObject(Object.create(null));
   * // => true
   */
  function isPlainObject(value) {
    var Ctor;
  
    // Exit early for non `Object` objects.
    if (!(isObjectLike(value) && objToString.call(value) == objectTag && !isArguments(value)) ||
        (!hasOwnProperty.call(value, 'constructor') && (Ctor = value.constructor, typeof Ctor == 'function' && !(Ctor instanceof Ctor)))) {
      return false;
    }
    // IE < 9 iterates inherited properties before own properties. If the first
    // iterated property is an object's own property then there are no inherited
    // enumerable properties.
    var result;
    // In most environments an object's own properties are iterated before
    // its inherited properties. If the last iterated property is an object's
    // own property then there are no inherited enumerable properties.
    baseForIn(value, function(subValue, key) {
      result = key;
    });
    return result === undefined || hasOwnProperty.call(value, result);
  }
  
  module.exports = isPlainObject;
  
  },{"lodash._basefor":23,"lodash.isarguments":30,"lodash.keysin":35}],33:[function(require,module,exports){
  /**
   * lodash 3.0.6 (Custom Build) <https://lodash.com/>
   * Build: `lodash modularize exports="npm" -o ./`
   * Copyright jQuery Foundation and other contributors <https://jquery.org/>
   * Released under MIT license <https://lodash.com/license>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   */
  
  /** Used as references for various `Number` constants. */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /** `Object#toString` result references. */
  var argsTag = '[object Arguments]',
      arrayTag = '[object Array]',
      boolTag = '[object Boolean]',
      dateTag = '[object Date]',
      errorTag = '[object Error]',
      funcTag = '[object Function]',
      mapTag = '[object Map]',
      numberTag = '[object Number]',
      objectTag = '[object Object]',
      regexpTag = '[object RegExp]',
      setTag = '[object Set]',
      stringTag = '[object String]',
      weakMapTag = '[object WeakMap]';
  
  var arrayBufferTag = '[object ArrayBuffer]',
      dataViewTag = '[object DataView]',
      float32Tag = '[object Float32Array]',
      float64Tag = '[object Float64Array]',
      int8Tag = '[object Int8Array]',
      int16Tag = '[object Int16Array]',
      int32Tag = '[object Int32Array]',
      uint8Tag = '[object Uint8Array]',
      uint8ClampedTag = '[object Uint8ClampedArray]',
      uint16Tag = '[object Uint16Array]',
      uint32Tag = '[object Uint32Array]';
  
  /** Used to identify `toStringTag` values of typed arrays. */
  var typedArrayTags = {};
  typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
  typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
  typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
  typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
  typedArrayTags[uint32Tag] = true;
  typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
  typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
  typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
  typedArrayTags[errorTag] = typedArrayTags[funcTag] =
  typedArrayTags[mapTag] = typedArrayTags[numberTag] =
  typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
  typedArrayTags[setTag] = typedArrayTags[stringTag] =
  typedArrayTags[weakMapTag] = false;
  
  /** Used for built-in method references. */
  var objectProto = Object.prototype;
  
  /**
   * Used to resolve the [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
   * of values.
   */
  var objectToString = objectProto.toString;
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is loosely based on
   * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length,
   *  else `false`.
   * @example
   *
   * _.isLength(3);
   * // => true
   *
   * _.isLength(Number.MIN_VALUE);
   * // => false
   *
   * _.isLength(Infinity);
   * // => false
   *
   * _.isLength('3');
   * // => false
   */
  function isLength(value) {
    return typeof value == 'number' &&
      value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is object-like. A value is object-like if it's not `null`
   * and has a `typeof` result of "object".
   *
   * @static
   * @memberOf _
   * @since 4.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   * @example
   *
   * _.isObjectLike({});
   * // => true
   *
   * _.isObjectLike([1, 2, 3]);
   * // => true
   *
   * _.isObjectLike(_.noop);
   * // => false
   *
   * _.isObjectLike(null);
   * // => false
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /**
   * Checks if `value` is classified as a typed array.
   *
   * @static
   * @memberOf _
   * @since 3.0.0
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is correctly classified,
   *  else `false`.
   * @example
   *
   * _.isTypedArray(new Uint8Array);
   * // => true
   *
   * _.isTypedArray([]);
   * // => false
   */
  function isTypedArray(value) {
    return isObjectLike(value) &&
      isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
  }
  
  module.exports = isTypedArray;
  
  },{}],34:[function(require,module,exports){
  /**
   * lodash 3.1.2 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var getNative = require('lodash._getnative'),
      isArguments = require('lodash.isarguments'),
      isArray = require('lodash.isarray');
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^\d+$/;
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /* Native method references for those with the same name as other `lodash` methods. */
  var nativeKeys = getNative(Object, 'keys');
  
  /**
   * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  /**
   * Gets the "length" property value of `object`.
   *
   * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
   * that affects Safari on at least iOS 8.1-8.3 ARM64.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {*} Returns the "length" value.
   */
  var getLength = baseProperty('length');
  
  /**
   * Checks if `value` is array-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   */
  function isArrayLike(value) {
    return value != null && isLength(getLength(value));
  }
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
    length = length == null ? MAX_SAFE_INTEGER : length;
    return value > -1 && value % 1 == 0 && value < length;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * A fallback implementation of `Object.keys` which creates an array of the
   * own enumerable property names of `object`.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   */
  function shimKeys(object) {
    var props = keysIn(object),
        propsLength = props.length,
        length = propsLength && object.length;
  
    var allowIndexes = !!length && isLength(length) &&
      (isArray(object) || isArguments(object));
  
    var index = -1,
        result = [];
  
    while (++index < propsLength) {
      var key = props[index];
      if ((allowIndexes && isIndex(key, length)) || hasOwnProperty.call(object, key)) {
        result.push(key);
      }
    }
    return result;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Creates an array of the own enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects. See the
   * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
   * for more details.
   *
   * @static
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keys(new Foo);
   * // => ['a', 'b'] (iteration order is not guaranteed)
   *
   * _.keys('hi');
   * // => ['0', '1']
   */
  var keys = !nativeKeys ? shimKeys : function(object) {
    var Ctor = object == null ? undefined : object.constructor;
    if ((typeof Ctor == 'function' && Ctor.prototype === object) ||
        (typeof object != 'function' && isArrayLike(object))) {
      return shimKeys(object);
    }
    return isObject(object) ? nativeKeys(object) : [];
  };
  
  /**
   * Creates an array of the own and inherited enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects.
   *
   * @static
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keysIn(new Foo);
   * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
   */
  function keysIn(object) {
    if (object == null) {
      return [];
    }
    if (!isObject(object)) {
      object = Object(object);
    }
    var length = object.length;
    length = (length && isLength(length) &&
      (isArray(object) || isArguments(object)) && length) || 0;
  
    var Ctor = object.constructor,
        index = -1,
        isProto = typeof Ctor == 'function' && Ctor.prototype === object,
        result = Array(length),
        skipIndexes = length > 0;
  
    while (++index < length) {
      result[index] = (index + '');
    }
    for (var key in object) {
      if (!(skipIndexes && isIndex(key, length)) &&
          !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = keys;
  
  },{"lodash._getnative":27,"lodash.isarguments":30,"lodash.isarray":31}],35:[function(require,module,exports){
  /**
   * lodash 3.0.8 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var isArguments = require('lodash.isarguments'),
      isArray = require('lodash.isarray');
  
  /** Used to detect unsigned integer values. */
  var reIsUint = /^\d+$/;
  
  /** Used for native method references. */
  var objectProto = Object.prototype;
  
  /** Used to check objects for own properties. */
  var hasOwnProperty = objectProto.hasOwnProperty;
  
  /**
   * Used as the [maximum length](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * Checks if `value` is a valid array-like index.
   *
   * @private
   * @param {*} value The value to check.
   * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
   * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
   */
  function isIndex(value, length) {
    value = (typeof value == 'number' || reIsUint.test(value)) ? +value : -1;
    length = length == null ? MAX_SAFE_INTEGER : length;
    return value > -1 && value % 1 == 0 && value < length;
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](https://people.mozilla.org/~jorendorff/es6-draft.html#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Creates an array of the own and inherited enumerable property names of `object`.
   *
   * **Note:** Non-object values are coerced to objects.
   *
   * @static
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the array of property names.
   * @example
   *
   * function Foo() {
   *   this.a = 1;
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.keysIn(new Foo);
   * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
   */
  function keysIn(object) {
    if (object == null) {
      return [];
    }
    if (!isObject(object)) {
      object = Object(object);
    }
    var length = object.length;
    length = (length && isLength(length) &&
      (isArray(object) || isArguments(object)) && length) || 0;
  
    var Ctor = object.constructor,
        index = -1,
        isProto = typeof Ctor == 'function' && Ctor.prototype === object,
        result = Array(length),
        skipIndexes = length > 0;
  
    while (++index < length) {
      result[index] = (index + '');
    }
    for (var key in object) {
      if (!(skipIndexes && isIndex(key, length)) &&
          !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
        result.push(key);
      }
    }
    return result;
  }
  
  module.exports = keysIn;
  
  },{"lodash.isarguments":30,"lodash.isarray":31}],36:[function(require,module,exports){
  /**
   * lodash 3.3.2 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var arrayCopy = require('lodash._arraycopy'),
      arrayEach = require('lodash._arrayeach'),
      createAssigner = require('lodash._createassigner'),
      isArguments = require('lodash.isarguments'),
      isArray = require('lodash.isarray'),
      isPlainObject = require('lodash.isplainobject'),
      isTypedArray = require('lodash.istypedarray'),
      keys = require('lodash.keys'),
      toPlainObject = require('lodash.toplainobject');
  
  /**
   * Checks if `value` is object-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
   */
  function isObjectLike(value) {
    return !!value && typeof value == 'object';
  }
  
  /**
   * Used as the [maximum length](http://ecma-international.org/ecma-262/6.0/#sec-number.max_safe_integer)
   * of an array-like value.
   */
  var MAX_SAFE_INTEGER = 9007199254740991;
  
  /**
   * The base implementation of `_.merge` without support for argument juggling,
   * multiple sources, and `this` binding `customizer` functions.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @param {Function} [customizer] The function to customize merged values.
   * @param {Array} [stackA=[]] Tracks traversed source objects.
   * @param {Array} [stackB=[]] Associates values with source counterparts.
   * @returns {Object} Returns `object`.
   */
  function baseMerge(object, source, customizer, stackA, stackB) {
    if (!isObject(object)) {
      return object;
    }
    var isSrcArr = isArrayLike(source) && (isArray(source) || isTypedArray(source)),
        props = isSrcArr ? undefined : keys(source);
  
    arrayEach(props || source, function(srcValue, key) {
      if (props) {
        key = srcValue;
        srcValue = source[key];
      }
      if (isObjectLike(srcValue)) {
        stackA || (stackA = []);
        stackB || (stackB = []);
        baseMergeDeep(object, source, key, baseMerge, customizer, stackA, stackB);
      }
      else {
        var value = object[key],
            result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
            isCommon = result === undefined;
  
        if (isCommon) {
          result = srcValue;
        }
        if ((result !== undefined || (isSrcArr && !(key in object))) &&
            (isCommon || (result === result ? (result !== value) : (value === value)))) {
          object[key] = result;
        }
      }
    });
    return object;
  }
  
  /**
   * A specialized version of `baseMerge` for arrays and objects which performs
   * deep merges and tracks traversed objects enabling objects with circular
   * references to be merged.
   *
   * @private
   * @param {Object} object The destination object.
   * @param {Object} source The source object.
   * @param {string} key The key of the value to merge.
   * @param {Function} mergeFunc The function to merge values.
   * @param {Function} [customizer] The function to customize merged values.
   * @param {Array} [stackA=[]] Tracks traversed source objects.
   * @param {Array} [stackB=[]] Associates values with source counterparts.
   * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
   */
  function baseMergeDeep(object, source, key, mergeFunc, customizer, stackA, stackB) {
    var length = stackA.length,
        srcValue = source[key];
  
    while (length--) {
      if (stackA[length] == srcValue) {
        object[key] = stackB[length];
        return;
      }
    }
    var value = object[key],
        result = customizer ? customizer(value, srcValue, key, object, source) : undefined,
        isCommon = result === undefined;
  
    if (isCommon) {
      result = srcValue;
      if (isArrayLike(srcValue) && (isArray(srcValue) || isTypedArray(srcValue))) {
        result = isArray(value)
          ? value
          : (isArrayLike(value) ? arrayCopy(value) : []);
      }
      else if (isPlainObject(srcValue) || isArguments(srcValue)) {
        result = isArguments(value)
          ? toPlainObject(value)
          : (isPlainObject(value) ? value : {});
      }
      else {
        isCommon = false;
      }
    }
    // Add the source value to the stack of traversed objects and associate
    // it with its merged value.
    stackA.push(srcValue);
    stackB.push(result);
  
    if (isCommon) {
      // Recursively merge objects and arrays (susceptible to call stack limits).
      object[key] = mergeFunc(result, srcValue, customizer, stackA, stackB);
    } else if (result === result ? (result !== value) : (value === value)) {
      object[key] = result;
    }
  }
  
  /**
   * The base implementation of `_.property` without support for deep paths.
   *
   * @private
   * @param {string} key The key of the property to get.
   * @returns {Function} Returns the new function.
   */
  function baseProperty(key) {
    return function(object) {
      return object == null ? undefined : object[key];
    };
  }
  
  /**
   * Gets the "length" property value of `object`.
   *
   * **Note:** This function is used to avoid a [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792)
   * that affects Safari on at least iOS 8.1-8.3 ARM64.
   *
   * @private
   * @param {Object} object The object to query.
   * @returns {*} Returns the "length" value.
   */
  var getLength = baseProperty('length');
  
  /**
   * Checks if `value` is array-like.
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
   */
  function isArrayLike(value) {
    return value != null && isLength(getLength(value));
  }
  
  /**
   * Checks if `value` is a valid array-like length.
   *
   * **Note:** This function is based on [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
   *
   * @private
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
   */
  function isLength(value) {
    return typeof value == 'number' && value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Recursively merges own enumerable properties of the source object(s), that
   * don't resolve to `undefined` into the destination object. Subsequent sources
   * overwrite property assignments of previous sources. If `customizer` is
   * provided it is invoked to produce the merged values of the destination and
   * source properties. If `customizer` returns `undefined` merging is handled
   * by the method instead. The `customizer` is bound to `thisArg` and invoked
   * with five arguments: (objectValue, sourceValue, key, object, source).
   *
   * @static
   * @memberOf _
   * @category Object
   * @param {Object} object The destination object.
   * @param {...Object} [sources] The source objects.
   * @param {Function} [customizer] The function to customize assigned values.
   * @param {*} [thisArg] The `this` binding of `customizer`.
   * @returns {Object} Returns `object`.
   * @example
   *
   * var users = {
   *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
   * };
   *
   * var ages = {
   *   'data': [{ 'age': 36 }, { 'age': 40 }]
   * };
   *
   * _.merge(users, ages);
   * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
   *
   * // using a customizer callback
   * var object = {
   *   'fruits': ['apple'],
   *   'vegetables': ['beet']
   * };
   *
   * var other = {
   *   'fruits': ['banana'],
   *   'vegetables': ['carrot']
   * };
   *
   * _.merge(object, other, function(a, b) {
   *   if (_.isArray(a)) {
   *     return a.concat(b);
   *   }
   * });
   * // => { 'fruits': ['apple', 'banana'], 'vegetables': ['beet', 'carrot'] }
   */
  var merge = createAssigner(baseMerge);
  
  module.exports = merge;
  
  },{"lodash._arraycopy":16,"lodash._arrayeach":17,"lodash._createassigner":26,"lodash.isarguments":30,"lodash.isarray":31,"lodash.isplainobject":32,"lodash.istypedarray":33,"lodash.keys":34,"lodash.toplainobject":39}],37:[function(require,module,exports){
  /**
   * lodash 3.0.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var keys = require('lodash.keys');
  
  /**
   * Converts `value` to an object if it's not one.
   *
   * @private
   * @param {*} value The value to process.
   * @returns {Object} Returns the object.
   */
  function toObject(value) {
    return isObject(value) ? value : Object(value);
  }
  
  /**
   * Checks if `value` is the [language type](https://es5.github.io/#x8) of `Object`.
   * (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to check.
   * @returns {boolean} Returns `true` if `value` is an object, else `false`.
   * @example
   *
   * _.isObject({});
   * // => true
   *
   * _.isObject([1, 2, 3]);
   * // => true
   *
   * _.isObject(1);
   * // => false
   */
  function isObject(value) {
    // Avoid a V8 JIT bug in Chrome 19-20.
    // See https://code.google.com/p/v8/issues/detail?id=2291 for more details.
    var type = typeof value;
    return !!value && (type == 'object' || type == 'function');
  }
  
  /**
   * Creates a two dimensional array of the key-value pairs for `object`,
   * e.g. `[[key1, value1], [key2, value2]]`.
   *
   * @static
   * @memberOf _
   * @category Object
   * @param {Object} object The object to query.
   * @returns {Array} Returns the new array of key-value pairs.
   * @example
   *
   * _.pairs({ 'barney': 36, 'fred': 40 });
   * // => [['barney', 36], ['fred', 40]] (iteration order is not guaranteed)
   */
  function pairs(object) {
    object = toObject(object);
  
    var index = -1,
        props = keys(object),
        length = props.length,
        result = Array(length);
  
    while (++index < length) {
      var key = props[index];
      result[index] = [key, object[key]];
    }
    return result;
  }
  
  module.exports = pairs;
  
  },{"lodash.keys":34}],38:[function(require,module,exports){
  /**
   * lodash 3.6.1 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  
  /** Used as the `TypeError` message for "Functions" methods. */
  var FUNC_ERROR_TEXT = 'Expected a function';
  
  /* Native method references for those with the same name as other `lodash` methods. */
  var nativeMax = Math.max;
  
  /**
   * Creates a function that invokes `func` with the `this` binding of the
   * created function and arguments from `start` and beyond provided as an array.
   *
   * **Note:** This method is based on the [rest parameter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters).
   *
   * @static
   * @memberOf _
   * @category Function
   * @param {Function} func The function to apply a rest parameter to.
   * @param {number} [start=func.length-1] The start position of the rest parameter.
   * @returns {Function} Returns the new function.
   * @example
   *
   * var say = _.restParam(function(what, names) {
   *   return what + ' ' + _.initial(names).join(', ') +
   *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
   * });
   *
   * say('hello', 'fred', 'barney', 'pebbles');
   * // => 'hello fred, barney, & pebbles'
   */
  function restParam(func, start) {
    if (typeof func != 'function') {
      throw new TypeError(FUNC_ERROR_TEXT);
    }
    start = nativeMax(start === undefined ? (func.length - 1) : (+start || 0), 0);
    return function() {
      var args = arguments,
          index = -1,
          length = nativeMax(args.length - start, 0),
          rest = Array(length);
  
      while (++index < length) {
        rest[index] = args[start + index];
      }
      switch (start) {
        case 0: return func.call(this, rest);
        case 1: return func.call(this, args[0], rest);
        case 2: return func.call(this, args[0], args[1], rest);
      }
      var otherArgs = Array(start + 1);
      index = -1;
      while (++index < start) {
        otherArgs[index] = args[index];
      }
      otherArgs[start] = rest;
      return func.apply(this, otherArgs);
    };
  }
  
  module.exports = restParam;
  
  },{}],39:[function(require,module,exports){
  /**
   * lodash 3.0.0 (Custom Build) <https://lodash.com/>
   * Build: `lodash modern modularize exports="npm" -o ./`
   * Copyright 2012-2015 The Dojo Foundation <http://dojofoundation.org/>
   * Based on Underscore.js 1.7.0 <http://underscorejs.org/LICENSE>
   * Copyright 2009-2015 Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
   * Available under MIT license <https://lodash.com/license>
   */
  var baseCopy = require('lodash._basecopy'),
      keysIn = require('lodash.keysin');
  
  /**
   * Converts `value` to a plain object flattening inherited enumerable
   * properties of `value` to own properties of the plain object.
   *
   * @static
   * @memberOf _
   * @category Lang
   * @param {*} value The value to convert.
   * @returns {Object} Returns the converted plain object.
   * @example
   *
   * function Foo() {
   *   this.b = 2;
   * }
   *
   * Foo.prototype.c = 3;
   *
   * _.assign({ 'a': 1 }, new Foo);
   * // => { 'a': 1, 'b': 2 }
   *
   * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
   * // => { 'a': 1, 'b': 2, 'c': 3 }
   */
  function toPlainObject(value) {
    return baseCopy(value, keysIn(value));
  }
  
  module.exports = toPlainObject;
  
  },{"lodash._basecopy":19,"lodash.keysin":35}],40:[function(require,module,exports){
  (function (global){
  /*! https://mths.be/punycode v1.4.1 by @mathias */
  ;(function(root) {
  
  	/** Detect free variables */
  	var freeExports = typeof exports == 'object' && exports &&
  		!exports.nodeType && exports;
  	var freeModule = typeof module == 'object' && module &&
  		!module.nodeType && module;
  	var freeGlobal = typeof global == 'object' && global;
  	if (
  		freeGlobal.global === freeGlobal ||
  		freeGlobal.window === freeGlobal ||
  		freeGlobal.self === freeGlobal
  	) {
  		root = freeGlobal;
  	}
  
  	/**
  	 * The `punycode` object.
  	 * @name punycode
  	 * @type Object
  	 */
  	var punycode,
  
  	/** Highest positive signed 32-bit float value */
  	maxInt = 2147483647, // aka. 0x7FFFFFFF or 2^31-1
  
  	/** Bootstring parameters */
  	base = 36,
  	tMin = 1,
  	tMax = 26,
  	skew = 38,
  	damp = 700,
  	initialBias = 72,
  	initialN = 128, // 0x80
  	delimiter = '-', // '\x2D'
  
  	/** Regular expressions */
  	regexPunycode = /^xn--/,
  	regexNonASCII = /[^\x20-\x7E]/, // unprintable ASCII chars + non-ASCII chars
  	regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g, // RFC 3490 separators
  
  	/** Error messages */
  	errors = {
  		'overflow': 'Overflow: input needs wider integers to process',
  		'not-basic': 'Illegal input >= 0x80 (not a basic code point)',
  		'invalid-input': 'Invalid input'
  	},
  
  	/** Convenience shortcuts */
  	baseMinusTMin = base - tMin,
  	floor = Math.floor,
  	stringFromCharCode = String.fromCharCode,
  
  	/** Temporary variable */
  	key;
  
  	/*--------------------------------------------------------------------------*/
  
  	/**
  	 * A generic error utility function.
  	 * @private
  	 * @param {String} type The error type.
  	 * @returns {Error} Throws a `RangeError` with the applicable error message.
  	 */
  	function error(type) {
  		throw new RangeError(errors[type]);
  	}
  
  	/**
  	 * A generic `Array#map` utility function.
  	 * @private
  	 * @param {Array} array The array to iterate over.
  	 * @param {Function} callback The function that gets called for every array
  	 * item.
  	 * @returns {Array} A new array of values returned by the callback function.
  	 */
  	function map(array, fn) {
  		var length = array.length;
  		var result = [];
  		while (length--) {
  			result[length] = fn(array[length]);
  		}
  		return result;
  	}
  
  	/**
  	 * A simple `Array#map`-like wrapper to work with domain name strings or email
  	 * addresses.
  	 * @private
  	 * @param {String} domain The domain name or email address.
  	 * @param {Function} callback The function that gets called for every
  	 * character.
  	 * @returns {Array} A new string of characters returned by the callback
  	 * function.
  	 */
  	function mapDomain(string, fn) {
  		var parts = string.split('@');
  		var result = '';
  		if (parts.length > 1) {
  			// In email addresses, only the domain name should be punycoded. Leave
  			// the local part (i.e. everything up to `@`) intact.
  			result = parts[0] + '@';
  			string = parts[1];
  		}
  		// Avoid `split(regex)` for IE8 compatibility. See #17.
  		string = string.replace(regexSeparators, '\x2E');
  		var labels = string.split('.');
  		var encoded = map(labels, fn).join('.');
  		return result + encoded;
  	}
  
  	/**
  	 * Creates an array containing the numeric code points of each Unicode
  	 * character in the string. While JavaScript uses UCS-2 internally,
  	 * this function will convert a pair of surrogate halves (each of which
  	 * UCS-2 exposes as separate characters) into a single code point,
  	 * matching UTF-16.
  	 * @see `punycode.ucs2.encode`
  	 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  	 * @memberOf punycode.ucs2
  	 * @name decode
  	 * @param {String} string The Unicode input string (UCS-2).
  	 * @returns {Array} The new array of code points.
  	 */
  	function ucs2decode(string) {
  		var output = [],
  		    counter = 0,
  		    length = string.length,
  		    value,
  		    extra;
  		while (counter < length) {
  			value = string.charCodeAt(counter++);
  			if (value >= 0xD800 && value <= 0xDBFF && counter < length) {
  				// high surrogate, and there is a next character
  				extra = string.charCodeAt(counter++);
  				if ((extra & 0xFC00) == 0xDC00) { // low surrogate
  					output.push(((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000);
  				} else {
  					// unmatched surrogate; only append this code unit, in case the next
  					// code unit is the high surrogate of a surrogate pair
  					output.push(value);
  					counter--;
  				}
  			} else {
  				output.push(value);
  			}
  		}
  		return output;
  	}
  
  	/**
  	 * Creates a string based on an array of numeric code points.
  	 * @see `punycode.ucs2.decode`
  	 * @memberOf punycode.ucs2
  	 * @name encode
  	 * @param {Array} codePoints The array of numeric code points.
  	 * @returns {String} The new Unicode string (UCS-2).
  	 */
  	function ucs2encode(array) {
  		return map(array, function(value) {
  			var output = '';
  			if (value > 0xFFFF) {
  				value -= 0x10000;
  				output += stringFromCharCode(value >>> 10 & 0x3FF | 0xD800);
  				value = 0xDC00 | value & 0x3FF;
  			}
  			output += stringFromCharCode(value);
  			return output;
  		}).join('');
  	}
  
  	/**
  	 * Converts a basic code point into a digit/integer.
  	 * @see `digitToBasic()`
  	 * @private
  	 * @param {Number} codePoint The basic numeric code point value.
  	 * @returns {Number} The numeric value of a basic code point (for use in
  	 * representing integers) in the range `0` to `base - 1`, or `base` if
  	 * the code point does not represent a value.
  	 */
  	function basicToDigit(codePoint) {
  		if (codePoint - 48 < 10) {
  			return codePoint - 22;
  		}
  		if (codePoint - 65 < 26) {
  			return codePoint - 65;
  		}
  		if (codePoint - 97 < 26) {
  			return codePoint - 97;
  		}
  		return base;
  	}
  
  	/**
  	 * Converts a digit/integer into a basic code point.
  	 * @see `basicToDigit()`
  	 * @private
  	 * @param {Number} digit The numeric value of a basic code point.
  	 * @returns {Number} The basic code point whose value (when used for
  	 * representing integers) is `digit`, which needs to be in the range
  	 * `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
  	 * used; else, the lowercase form is used. The behavior is undefined
  	 * if `flag` is non-zero and `digit` has no uppercase form.
  	 */
  	function digitToBasic(digit, flag) {
  		//  0..25 map to ASCII a..z or A..Z
  		// 26..35 map to ASCII 0..9
  		return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
  	}
  
  	/**
  	 * Bias adaptation function as per section 3.4 of RFC 3492.
  	 * https://tools.ietf.org/html/rfc3492#section-3.4
  	 * @private
  	 */
  	function adapt(delta, numPoints, firstTime) {
  		var k = 0;
  		delta = firstTime ? floor(delta / damp) : delta >> 1;
  		delta += floor(delta / numPoints);
  		for (/* no initialization */; delta > baseMinusTMin * tMax >> 1; k += base) {
  			delta = floor(delta / baseMinusTMin);
  		}
  		return floor(k + (baseMinusTMin + 1) * delta / (delta + skew));
  	}
  
  	/**
  	 * Converts a Punycode string of ASCII-only symbols to a string of Unicode
  	 * symbols.
  	 * @memberOf punycode
  	 * @param {String} input The Punycode string of ASCII-only symbols.
  	 * @returns {String} The resulting string of Unicode symbols.
  	 */
  	function decode(input) {
  		// Don't use UCS-2
  		var output = [],
  		    inputLength = input.length,
  		    out,
  		    i = 0,
  		    n = initialN,
  		    bias = initialBias,
  		    basic,
  		    j,
  		    index,
  		    oldi,
  		    w,
  		    k,
  		    digit,
  		    t,
  		    /** Cached calculation results */
  		    baseMinusT;
  
  		// Handle the basic code points: let `basic` be the number of input code
  		// points before the last delimiter, or `0` if there is none, then copy
  		// the first basic code points to the output.
  
  		basic = input.lastIndexOf(delimiter);
  		if (basic < 0) {
  			basic = 0;
  		}
  
  		for (j = 0; j < basic; ++j) {
  			// if it's not a basic code point
  			if (input.charCodeAt(j) >= 0x80) {
  				error('not-basic');
  			}
  			output.push(input.charCodeAt(j));
  		}
  
  		// Main decoding loop: start just after the last delimiter if any basic code
  		// points were copied; start at the beginning otherwise.
  
  		for (index = basic > 0 ? basic + 1 : 0; index < inputLength; /* no final expression */) {
  
  			// `index` is the index of the next character to be consumed.
  			// Decode a generalized variable-length integer into `delta`,
  			// which gets added to `i`. The overflow checking is easier
  			// if we increase `i` as we go, then subtract off its starting
  			// value at the end to obtain `delta`.
  			for (oldi = i, w = 1, k = base; /* no condition */; k += base) {
  
  				if (index >= inputLength) {
  					error('invalid-input');
  				}
  
  				digit = basicToDigit(input.charCodeAt(index++));
  
  				if (digit >= base || digit > floor((maxInt - i) / w)) {
  					error('overflow');
  				}
  
  				i += digit * w;
  				t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  
  				if (digit < t) {
  					break;
  				}
  
  				baseMinusT = base - t;
  				if (w > floor(maxInt / baseMinusT)) {
  					error('overflow');
  				}
  
  				w *= baseMinusT;
  
  			}
  
  			out = output.length + 1;
  			bias = adapt(i - oldi, out, oldi == 0);
  
  			// `i` was supposed to wrap around from `out` to `0`,
  			// incrementing `n` each time, so we'll fix that now:
  			if (floor(i / out) > maxInt - n) {
  				error('overflow');
  			}
  
  			n += floor(i / out);
  			i %= out;
  
  			// Insert `n` at position `i` of the output
  			output.splice(i++, 0, n);
  
  		}
  
  		return ucs2encode(output);
  	}
  
  	/**
  	 * Converts a string of Unicode symbols (e.g. a domain name label) to a
  	 * Punycode string of ASCII-only symbols.
  	 * @memberOf punycode
  	 * @param {String} input The string of Unicode symbols.
  	 * @returns {String} The resulting Punycode string of ASCII-only symbols.
  	 */
  	function encode(input) {
  		var n,
  		    delta,
  		    handledCPCount,
  		    basicLength,
  		    bias,
  		    j,
  		    m,
  		    q,
  		    k,
  		    t,
  		    currentValue,
  		    output = [],
  		    /** `inputLength` will hold the number of code points in `input`. */
  		    inputLength,
  		    /** Cached calculation results */
  		    handledCPCountPlusOne,
  		    baseMinusT,
  		    qMinusT;
  
  		// Convert the input in UCS-2 to Unicode
  		input = ucs2decode(input);
  
  		// Cache the length
  		inputLength = input.length;
  
  		// Initialize the state
  		n = initialN;
  		delta = 0;
  		bias = initialBias;
  
  		// Handle the basic code points
  		for (j = 0; j < inputLength; ++j) {
  			currentValue = input[j];
  			if (currentValue < 0x80) {
  				output.push(stringFromCharCode(currentValue));
  			}
  		}
  
  		handledCPCount = basicLength = output.length;
  
  		// `handledCPCount` is the number of code points that have been handled;
  		// `basicLength` is the number of basic code points.
  
  		// Finish the basic string - if it is not empty - with a delimiter
  		if (basicLength) {
  			output.push(delimiter);
  		}
  
  		// Main encoding loop:
  		while (handledCPCount < inputLength) {
  
  			// All non-basic code points < n have been handled already. Find the next
  			// larger one:
  			for (m = maxInt, j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  				if (currentValue >= n && currentValue < m) {
  					m = currentValue;
  				}
  			}
  
  			// Increase `delta` enough to advance the decoder's <n,i> state to <m,0>,
  			// but guard against overflow
  			handledCPCountPlusOne = handledCPCount + 1;
  			if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) {
  				error('overflow');
  			}
  
  			delta += (m - n) * handledCPCountPlusOne;
  			n = m;
  
  			for (j = 0; j < inputLength; ++j) {
  				currentValue = input[j];
  
  				if (currentValue < n && ++delta > maxInt) {
  					error('overflow');
  				}
  
  				if (currentValue == n) {
  					// Represent delta as a generalized variable-length integer
  					for (q = delta, k = base; /* no condition */; k += base) {
  						t = k <= bias ? tMin : (k >= bias + tMax ? tMax : k - bias);
  						if (q < t) {
  							break;
  						}
  						qMinusT = q - t;
  						baseMinusT = base - t;
  						output.push(
  							stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0))
  						);
  						q = floor(qMinusT / baseMinusT);
  					}
  
  					output.push(stringFromCharCode(digitToBasic(q, 0)));
  					bias = adapt(delta, handledCPCountPlusOne, handledCPCount == basicLength);
  					delta = 0;
  					++handledCPCount;
  				}
  			}
  
  			++delta;
  			++n;
  
  		}
  		return output.join('');
  	}
  
  	/**
  	 * Converts a Punycode string representing a domain name or an email address
  	 * to Unicode. Only the Punycoded parts of the input will be converted, i.e.
  	 * it doesn't matter if you call it on a string that has already been
  	 * converted to Unicode.
  	 * @memberOf punycode
  	 * @param {String} input The Punycoded domain name or email address to
  	 * convert to Unicode.
  	 * @returns {String} The Unicode representation of the given Punycode
  	 * string.
  	 */
  	function toUnicode(input) {
  		return mapDomain(input, function(string) {
  			return regexPunycode.test(string)
  				? decode(string.slice(4).toLowerCase())
  				: string;
  		});
  	}
  
  	/**
  	 * Converts a Unicode string representing a domain name or an email address to
  	 * Punycode. Only the non-ASCII parts of the domain name will be converted,
  	 * i.e. it doesn't matter if you call it with a domain that's already in
  	 * ASCII.
  	 * @memberOf punycode
  	 * @param {String} input The domain name or email address to convert, as a
  	 * Unicode string.
  	 * @returns {String} The Punycode representation of the given domain name or
  	 * email address.
  	 */
  	function toASCII(input) {
  		return mapDomain(input, function(string) {
  			return regexNonASCII.test(string)
  				? 'xn--' + encode(string)
  				: string;
  		});
  	}
  
  	/*--------------------------------------------------------------------------*/
  
  	/** Define the public API */
  	punycode = {
  		/**
  		 * A string representing the current Punycode.js version number.
  		 * @memberOf punycode
  		 * @type String
  		 */
  		'version': '1.4.1',
  		/**
  		 * An object of methods to convert from JavaScript's internal character
  		 * representation (UCS-2) to Unicode code points, and back.
  		 * @see <https://mathiasbynens.be/notes/javascript-encoding>
  		 * @memberOf punycode
  		 * @type Object
  		 */
  		'ucs2': {
  			'decode': ucs2decode,
  			'encode': ucs2encode
  		},
  		'decode': decode,
  		'encode': encode,
  		'toASCII': toASCII,
  		'toUnicode': toUnicode
  	};
  
  	/** Expose `punycode` */
  	// Some AMD build optimizers, like r.js, check for specific condition patterns
  	// like the following:
  	if (
  		typeof define == 'function' &&
  		typeof define.amd == 'object' &&
  		define.amd
  	) {
  		define('punycode', function() {
  			return punycode;
  		});
  	} else if (freeExports && freeModule) {
  		if (module.exports == freeExports) {
  			// in Node.js, io.js, or RingoJS v0.8.0+
  			freeModule.exports = punycode;
  		} else {
  			// in Narwhal or RingoJS v0.7.0-
  			for (key in punycode) {
  				punycode.hasOwnProperty(key) && (freeExports[key] = punycode[key]);
  			}
  		}
  	} else {
  		// in Rhino or a web browser
  		root.punycode = punycode;
  	}
  
  }(this));
  
  }).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
  },{}],41:[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.
  
  'use strict';
  
  // If obj.hasOwnProperty has been overridden, then calling
  // obj.hasOwnProperty(prop) will break.
  // See: https://github.com/joyent/node/issues/1707
  function hasOwnProperty(obj, prop) {
    return Object.prototype.hasOwnProperty.call(obj, prop);
  }
  
  module.exports = function(qs, sep, eq, options) {
    sep = sep || '&';
    eq = eq || '=';
    var obj = {};
  
    if (typeof qs !== 'string' || qs.length === 0) {
      return obj;
    }
  
    var regexp = /\+/g;
    qs = qs.split(sep);
  
    var maxKeys = 1000;
    if (options && typeof options.maxKeys === 'number') {
      maxKeys = options.maxKeys;
    }
  
    var len = qs.length;
    // maxKeys <= 0 means that we should not limit keys count
    if (maxKeys > 0 && len > maxKeys) {
      len = maxKeys;
    }
  
    for (var i = 0; i < len; ++i) {
      var x = qs[i].replace(regexp, '%20'),
          idx = x.indexOf(eq),
          kstr, vstr, k, v;
  
      if (idx >= 0) {
        kstr = x.substr(0, idx);
        vstr = x.substr(idx + 1);
      } else {
        kstr = x;
        vstr = '';
      }
  
      k = decodeURIComponent(kstr);
      v = decodeURIComponent(vstr);
  
      if (!hasOwnProperty(obj, k)) {
        obj[k] = v;
      } else if (isArray(obj[k])) {
        obj[k].push(v);
      } else {
        obj[k] = [obj[k], v];
      }
    }
  
    return obj;
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  },{}],42:[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.
  
  'use strict';
  
  var stringifyPrimitive = function(v) {
    switch (typeof v) {
      case 'string':
        return v;
  
      case 'boolean':
        return v ? 'true' : 'false';
  
      case 'number':
        return isFinite(v) ? v : '';
  
      default:
        return '';
    }
  };
  
  module.exports = function(obj, sep, eq, name) {
    sep = sep || '&';
    eq = eq || '=';
    if (obj === null) {
      obj = undefined;
    }
  
    if (typeof obj === 'object') {
      return map(objectKeys(obj), function(k) {
        var ks = encodeURIComponent(stringifyPrimitive(k)) + eq;
        if (isArray(obj[k])) {
          return map(obj[k], function(v) {
            return ks + encodeURIComponent(stringifyPrimitive(v));
          }).join(sep);
        } else {
          return ks + encodeURIComponent(stringifyPrimitive(obj[k]));
        }
      }).join(sep);
  
    }
  
    if (!name) return '';
    return encodeURIComponent(stringifyPrimitive(name)) + eq +
           encodeURIComponent(stringifyPrimitive(obj));
  };
  
  var isArray = Array.isArray || function (xs) {
    return Object.prototype.toString.call(xs) === '[object Array]';
  };
  
  function map (xs, f) {
    if (xs.map) return xs.map(f);
    var res = [];
    for (var i = 0; i < xs.length; i++) {
      res.push(f(xs[i], i));
    }
    return res;
  }
  
  var objectKeys = Object.keys || function (obj) {
    var res = [];
    for (var key in obj) {
      if (Object.prototype.hasOwnProperty.call(obj, key)) res.push(key);
    }
    return res;
  };
  
  },{}],43:[function(require,module,exports){
  'use strict';
  
  exports.decode = exports.parse = require('./decode');
  exports.encode = exports.stringify = require('./encode');
  
  },{"./decode":41,"./encode":42}],44:[function(require,module,exports){
  /**
  sprintf() for JavaScript 0.7-beta1
  http://www.diveintojavascript.com/projects/javascript-sprintf
  
  Copyright (c) Alexandru Marasteanu <alexaholic [at) gmail (dot] com>
  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 sprintf() for JavaScript 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 Alexandru Marasteanu 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.
  
  
  Changelog:
  2010.11.07 - 0.7-beta1-node
    - converted it to a node.js compatible module
  
  2010.09.06 - 0.7-beta1
    - features: vsprintf, support for named placeholders
    - enhancements: format cache, reduced global namespace pollution
  
  2010.05.22 - 0.6:
   - reverted to 0.4 and fixed the bug regarding the sign of the number 0
   Note:
   Thanks to Raphael Pigulla <raph (at] n3rd [dot) org> (http://www.n3rd.org/)
   who warned me about a bug in 0.5, I discovered that the last update was
   a regress. I appologize for that.
  
  2010.05.09 - 0.5:
   - bug fix: 0 is now preceeded with a + sign
   - bug fix: the sign was not at the right position on padded results (Kamal Abdali)
   - switched from GPL to BSD license
  
  2007.10.21 - 0.4:
   - unit test and patch (David Baird)
  
  2007.09.17 - 0.3:
   - bug fix: no longer throws exception on empty paramenters (Hans Pufal)
  
  2007.09.11 - 0.2:
   - feature: added argument swapping
  
  2007.04.03 - 0.1:
   - initial release
  **/
  
  var sprintf = (function() {
  	function get_type(variable) {
  		return Object.prototype.toString.call(variable).slice(8, -1).toLowerCase();
  	}
  	function str_repeat(input, multiplier) {
  		for (var output = []; multiplier > 0; output[--multiplier] = input) {/* do nothing */}
  		return output.join('');
  	}
  
  	var str_format = function() {
  		if (!str_format.cache.hasOwnProperty(arguments[0])) {
  			str_format.cache[arguments[0]] = str_format.parse(arguments[0]);
  		}
  		return str_format.format.call(null, str_format.cache[arguments[0]], arguments);
  	};
  
  	// convert object to simple one line string without indentation or
  	// newlines. Note that this implementation does not print array
  	// values to their actual place for sparse arrays. 
  	//
  	// For example sparse array like this
  	//    l = []
  	//    l[4] = 1
  	// Would be printed as "[1]" instead of "[, , , , 1]"
  	// 
  	// If argument 'seen' is not null and array the function will check for 
  	// circular object references from argument.
  	str_format.object_stringify = function(obj, depth, maxdepth, seen) {
  		var str = '';
  		if (obj != null) {
  			switch( typeof(obj) ) {
  			case 'function': 
  				return '[Function' + (obj.name ? ': '+obj.name : '') + ']';
  			    break;
  			case 'object':
  				if ( obj instanceof Error) { return '[' + obj.toString() + ']' };
  				if (depth >= maxdepth) return '[Object]'
  				if (seen) {
  					// add object to seen list
  					seen = seen.slice(0)
  					seen.push(obj);
  				}
  				if (obj.length != null) { //array
  					str += '[';
  					var arr = []
  					for (var i in obj) {
  						if (seen && seen.indexOf(obj[i]) >= 0) arr.push('[Circular]');
  						else arr.push(str_format.object_stringify(obj[i], depth+1, maxdepth, seen));
  					}
  					str += arr.join(', ') + ']';
  				} else if ('getMonth' in obj) { // date
  					return 'Date(' + obj + ')';
  				} else { // object
  					str += '{';
  					var arr = []
  					for (var k in obj) { 
  						if(obj.hasOwnProperty(k)) {
  							if (seen && seen.indexOf(obj[k]) >= 0) arr.push(k + ': [Circular]');
  							else arr.push(k +': ' +str_format.object_stringify(obj[k], depth+1, maxdepth, seen)); 
  						}
  					}
  					str += arr.join(', ') + '}';
  				}
  				return str;
  				break;
  			case 'string':				
  				return '"' + obj + '"';
  				break
  			}
  		}
  		return '' + obj;
  	}
  
  	str_format.format = function(parse_tree, argv) {
  		var cursor = 1, tree_length = parse_tree.length, node_type = '', arg, output = [], i, k, match, pad, pad_character, pad_length;
  		for (i = 0; i < tree_length; i++) {
  			node_type = get_type(parse_tree[i]);
  			if (node_type === 'string') {
  				output.push(parse_tree[i]);
  			}
  			else if (node_type === 'array') {
  				match = parse_tree[i]; // convenience purposes only
  				if (match[2]) { // keyword argument
  					arg = argv[cursor];
  					for (k = 0; k < match[2].length; k++) {
  						if (!arg.hasOwnProperty(match[2][k])) {
  							throw new Error(sprintf('[sprintf] property "%s" does not exist', match[2][k]));
  						}
  						arg = arg[match[2][k]];
  					}
  				}
  				else if (match[1]) { // positional argument (explicit)
  					arg = argv[match[1]];
  				}
  				else { // positional argument (implicit)
  					arg = argv[cursor++];
  				}
  
  				if (/[^sO]/.test(match[8]) && (get_type(arg) != 'number')) {
  					throw new Error(sprintf('[sprintf] expecting number but found %s "' + arg + '"', get_type(arg)));
  				}
  				switch (match[8]) {
  					case 'b': arg = arg.toString(2); break;
  					case 'c': arg = String.fromCharCode(arg); break;
  					case 'd': arg = parseInt(arg, 10); break;
  					case 'e': arg = match[7] ? arg.toExponential(match[7]) : arg.toExponential(); break;
  					case 'f': arg = match[7] ? parseFloat(arg).toFixed(match[7]) : parseFloat(arg); break;
  				    case 'O': arg = str_format.object_stringify(arg, 0, parseInt(match[7]) || 5); break;
  					case 'o': arg = arg.toString(8); break;
  					case 's': arg = ((arg = String(arg)) && match[7] ? arg.substring(0, match[7]) : arg); break;
  					case 'u': arg = Math.abs(arg); break;
  					case 'x': arg = arg.toString(16); break;
  					case 'X': arg = arg.toString(16).toUpperCase(); break;
  				}
  				arg = (/[def]/.test(match[8]) && match[3] && arg >= 0 ? '+'+ arg : arg);
  				pad_character = match[4] ? match[4] == '0' ? '0' : match[4].charAt(1) : ' ';
  				pad_length = match[6] - String(arg).length;
  				pad = match[6] ? str_repeat(pad_character, pad_length) : '';
  				output.push(match[5] ? arg + pad : pad + arg);
  			}
  		}
  		return output.join('');
  	};
  
  	str_format.cache = {};
  
  	str_format.parse = function(fmt) {
  		var _fmt = fmt, match = [], parse_tree = [], arg_names = 0;
  		while (_fmt) {
  			if ((match = /^[^\x25]+/.exec(_fmt)) !== null) {
  				parse_tree.push(match[0]);
  			}
  			else if ((match = /^\x25{2}/.exec(_fmt)) !== null) {
  				parse_tree.push('%');
  			}
  			else if ((match = /^\x25(?:([1-9]\d*)\$|\(([^\)]+)\))?(\+)?(0|'[^$])?(-)?(\d+)?(?:\.(\d+))?([b-fosOuxX])/.exec(_fmt)) !== null) {
  				if (match[2]) {
  					arg_names |= 1;
  					var field_list = [], replacement_field = match[2], field_match = [];
  					if ((field_match = /^([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  						field_list.push(field_match[1]);
  						while ((replacement_field = replacement_field.substring(field_match[0].length)) !== '') {
  							if ((field_match = /^\.([a-z_][a-z_\d]*)/i.exec(replacement_field)) !== null) {
  								field_list.push(field_match[1]);
  							}
  							else if ((field_match = /^\[(\d+)\]/.exec(replacement_field)) !== null) {
  								field_list.push(field_match[1]);
  							}
  							else {
  								throw new Error('[sprintf] ' + replacement_field);
  							}
  						}
  					}
  					else {
                          throw new Error('[sprintf] ' + replacement_field);
  					}
  					match[2] = field_list;
  				}
  				else {
  					arg_names |= 2;
  				}
  				if (arg_names === 3) {
  					throw new Error('[sprintf] mixing positional and named placeholders is not (yet) supported');
  				}
  				parse_tree.push(match);
  			}
  			else {
  				throw new Error('[sprintf] ' + _fmt);
  			}
  			_fmt = _fmt.substring(match[0].length);
  		}
  		return parse_tree;
  	};
  
  	return str_format;
  })();
  
  var vsprintf = function(fmt, argv) {
  	var argvClone = argv.slice();
  	argvClone.unshift(fmt);
  	return sprintf.apply(null, argvClone);
  };
  
  module.exports = sprintf;
  sprintf.sprintf = sprintf;
  sprintf.vsprintf = vsprintf;
  
  },{}],45:[function(require,module,exports){
  "use strict";
  
  var allRules = require('./rules.json');
  
  var cleanHostValue = require('./lib/clean-host.js');
  var escapeRegExp = require('./lib/escape-regexp.js');
  var getRulesForTld = require('./lib/tld-rules.js');
  var getDomain = require('./lib/domain.js');
  var getSubdomain = require('./lib/subdomain.js');
  var isValid = require('./lib/is-valid.js');
  var getPublicSuffix = require('./lib/public-suffix.js');
  var tldExists = require('./lib/tld-exists.js');
  
  /**
   * Creates a new instance of tldjs
   * @param  {Object.<rules,validHosts>} options [description]
   * @return {tldjs|Object}                      [description]
   */
  function factory(options) {
    var rules = options.rules || allRules || {};
    var validHosts = options.validHosts || [];
  
    return {
      cleanHostValue: cleanHostValue,
      escapeRegExp: escapeRegExp,
      getRulesForTld: getRulesForTld,
      getDomain: function (host) {
        return getDomain(rules, validHosts, host);
      },
      getSubdomain: function (host) {
        return getSubdomain(rules, validHosts, host);
      },
      isValid: function (host) {
        return isValid(validHosts, host);
      },
      getPublicSuffix: function (host) {
        return getPublicSuffix(rules, host);
      },
      tldExists: function (tld) {
        return tldExists(rules, tld);
      },
      fromUserSettings: factory
    };
  }
  
  module.exports = factory({ validHosts: [], rules: allRules });
  
  },{"./lib/clean-host.js":47,"./lib/domain.js":48,"./lib/escape-regexp.js":49,"./lib/is-valid.js":51,"./lib/public-suffix.js":54,"./lib/subdomain.js":56,"./lib/tld-exists.js":57,"./lib/tld-rules.js":58,"./rules.json":59}],46:[function(require,module,exports){
  var some = require('./polyfills/array-some.js');
  
  /**
   * Returns the best rule for a given host based on candidates
   *
   * @static
   * @param host {String} Hostname to check rules against
   * @param rules {Array} List of rules used to work on
   * @return {Object} Candidate object, with a normal and exception state
   */
  module.exports = function getCandidateRule (host, rules, options) {
    var rule = {'normal': null, 'exception': null};
  
    options = options || { lazy: false };
  
    some(rules, function (r) {
      var pattern;
  
      // sld matching or validHost? escape the loop immediately (except if it's an exception)
      if ('.' + host === r.getNormalXld()) {
        if (options.lazy || r.exception || r.isHost) {
          rule.normal = r;
        }
  
        return true;
      }
  
      // otherwise check as a complete host
      // if it's an exception, we want to loop a bit more to a normal rule
      pattern = '.+' + r.getNormalPattern() + '$';
  
      if ((new RegExp(pattern)).test(host)) {
        rule[r.exception ? 'exception' : 'normal'] = r;
        return !r.exception;
      }
  
      return false;
    });
  
    // favouring the exception if encountered
    // previously we were copy-altering a rule, creating inconsistent results based on rule order order
    // @see https://github.com/oncletom/tld.js/pull/35
    if (rule.normal && rule.exception) {
      return rule.exception;
    }
  
    return rule.normal;
  };
  
  },{"./polyfills/array-some.js":53}],47:[function(require,module,exports){
  var URL = require('url');
  
  /**
   * Utility to cleanup the base host value. Also removes url fragments.
   *
   * Works for:
   * - hostname
   * - //hostname
   * - scheme://hostname
   * - scheme+scheme://hostname
   *
   * @param {string} value
   * @return {String}
   */
  
  // scheme      = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
  var hasPrefixRE = /^(([a-z][a-z0-9+.-]*)?:)?\/\//;
  var invalidHostnameChars = /[^A-Za-z0-9.-]/;
  
  //@see https://github.com/oncletom/tld.js/issues/95
  function rtrim(value) {
    return String(value).replace(/[.]+$/g, '');
  }
  
  module.exports = function cleanHostValue(value){
    value = String(value).trim().toLowerCase();
  
    var parts = URL.parse(hasPrefixRE.test(value) ? value : '//' + value, null, true);
  
    if (parts.hostname && !invalidHostnameChars.test(parts.hostname)) { return rtrim(parts.hostname); }
    if (!invalidHostnameChars.test(value)) { return rtrim(value); }
    return '';
  };
  
  },{"url":60}],48:[function(require,module,exports){
  var Rule = require('./rule.js');
  var isValid = require('./is-valid.js');
  var cleanHostValue = require('./clean-host.js');
  var extractTldFromHost = require('./from-host.js');
  var getCandidateRule = require('./canditate-rule.js');
  var getRulesForTld = require('./tld-rules.js');
  
  /**
   * Detects the domain based on rules and upon and a host string
   *
   * @api
   * @param {string} host
   * @return {String}
   */
  module.exports = function getDomain (allRules, validHosts, host) {
    var domain = null, hostTld, rules, rule;
    var _validHosts = validHosts || [];
  
    if (isValid(_validHosts, host) === false) {
      return null;
    }
  
    host = cleanHostValue(host);
    hostTld = extractTldFromHost(host);
    rules = getRulesForTld(allRules, hostTld, new Rule({"firstLevel": hostTld, "isHost": _validHosts.indexOf(hostTld) !== -1}));
    rule = getCandidateRule(host, rules);
  
    if (rule === null) {
      return null;
    }
  
    host.replace(new RegExp(rule.getPattern()), function (m, d) {
      domain = d;
    });
  
    return domain;
  };
  
  },{"./canditate-rule.js":46,"./clean-host.js":47,"./from-host.js":50,"./is-valid.js":51,"./rule.js":55,"./tld-rules.js":58}],49:[function(require,module,exports){
  /**
   * Escapes RegExp specific chars.
   *
   * @since 1.3.1
   * @see https://github.com/oncletom/tld.js/pull/33
   * @param {String|Mixed} s
   * @returns {string} Escaped string for a safe use in a `new RegExp` expression
   */
  module.exports = function escapeRegExp(s) {
    return String(s).replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
  };
  
  },{}],50:[function(require,module,exports){
  /**
   * Utility to extract the TLD from a host string
   *
   * @param {string} host
   * @return {String}
   */
  module.exports = function extractTldFromHost(host){
    return host.split('.').pop();
  };
  
  },{}],51:[function(require,module,exports){
  /**
   * Checking if a host string is valid
   * It's usually a preliminary check before trying to use getDomain or anything else
   *
   * Beware: it does not check if the TLD exists.
   *
   * @api
   * @param host {String}
   * @return {Boolean}
   */
  module.exports = function isValid (validHosts, host) {
    return typeof host === 'string' && (validHosts.indexOf(host) !== -1 || (host.indexOf('.') !== -1 && host[0] !== '.'));
  };
  
  },{}],52:[function(require,module,exports){
  // Array.map polyfill for IE8
  module.exports = function _mapFunction(thisVal, fun /*, thisArg */) {
    "use strict";
  
    if (thisVal === void 0 || thisVal === null) {
      throw new TypeError();
    }
  
    var t = Object(thisVal);
    var len = t.length >>> 0;
    if (typeof fun !== "function") {
      throw new TypeError();
    }
  
    var res = new Array(len);
    var thisArg = arguments.length >= 3 ? arguments[2] : void 0;
  
    for (var i = 0; i < len; i++)
    {
      // NOTE: Absolute correctness would demand Object.defineProperty
      //       be used.  But this method is fairly new, and failure is
      //       possible only if Object.prototype or Array.prototype
      //       has a property |i| (very unlikely), so use a lesscorrect
      //       but more portable alternative.
      if (i in t) {
        res[i] = fun.call(thisArg, t[i], i, t);      
      }
    }
  
    return res;
  };
  
  },{}],53:[function(require,module,exports){
  // Array.some() polyfill for IE8
  module.exports = function _someFunction(value, fun /*, thisArg */) {
      'use strict';
  
      if (value === void 0 || value === null) {
        throw new TypeError();
      }
  
      var t = Object(value);
      var len = t.length >>> 0;
      if (typeof fun !== 'function') {
        throw new TypeError();
      }
  
      var thisArg = arguments.length >= 3 ? arguments[2] : void 0;
      for (var i = 0; i < len; i++)
      {
        if (i in t && fun.call(thisArg, t[i], i, t)) {
          return true;
        }
      }
  
      return false;
  };
  
  },{}],54:[function(require,module,exports){
  var cleanHostValue = require('./clean-host.js');
  var extractTldFromHost = require('./from-host.js');
  var getCandidateRule = require('./canditate-rule.js');
  var getRulesForTld = require('./tld-rules.js');
  
  /**
   * Returns the public suffix (including exact matches)
   *
   * @api
   * @since 1.5
   * @param {string} host
   * @return {String}
   */
  module.exports = function getPublicSuffix(allRules, host) {
    var hostTld, rules, rule;
  
    if (host in allRules){
  	  return host;
    }
  
    host = cleanHostValue(host);
    hostTld = extractTldFromHost(host);
    rules = getRulesForTld(allRules, hostTld);
    rule = getCandidateRule(host, rules, { lazy: true });
  
    if (rule === null) {
      return null;
    }
  
    return rule.getNormalXld().slice(1);
  };
  
  },{"./canditate-rule.js":46,"./clean-host.js":47,"./from-host.js":50,"./tld-rules.js":58}],55:[function(require,module,exports){
  "use strict";
  
  function Rule (data){
    data = data || {};
  
    this.exception = data.exception || false;
    this.firstLevel = data.firstLevel || '';
    this.secondLevel = data.secondLevel || null;
    this.isHost = data.isHost || false;
    this.source = data.source || '';
    this.wildcard = data.wildcard || false;
  }
  
  /**
   * Returns the TLD or SLD (Second Level Domain) pattern for a rule
   *
   * @return {String}
   */
  Rule.prototype.getNormalXld = function getNormalXld(){
    return (this.secondLevel ? '.' + this.secondLevel : '') + '.' + this.firstLevel;
  };
  
  /**
   * Returns a pattern suitable for normal rule
   * Mostly for internal use
   *
   * @return {String}
   */
  Rule.prototype.getNormalPattern = function getNormalPattern(){
    return (this.secondLevel ? '\\.' + this.secondLevel : '') + '\\.' + this.firstLevel;
  };
  
  /**
   * Returns a pattern suitable for wildcard rule
   * Mostly for internal use
   *
   * @return {String}
   */
  Rule.prototype.getWildcardPattern = function getWildcardPattern(){
    return '\\.[^\\.]+' + this.getNormalXld().replace(/\./g, '\\.');
  };
  
  /**
   * Returns a pattern suitable for exception rule
   * Mostly for internal use
   *
   * @return {String}
   */
  Rule.prototype.getExceptionPattern = function getExceptionPattern(){
    return (this.secondLevel || '') + '\\.' + this.firstLevel;
  };
  
  /**
   * Returns the best pattern possible for a rule
   * You just have to test a value against it to check or extract a hostname
   *
   * @api
   * @param {string|undefined} before
   * @param {string|undefined} after
   * @return {String} A pattern to challenge some string against
   */
  Rule.prototype.getPattern = function getPattern(before, after){
    var pattern = '';
  
    before = (before === undefined) ? '(': before+'';
    after = (after === undefined) ? ')$': after+'';
  
    if (this.exception === true){
      pattern = this.getExceptionPattern();
    }
    else if (this.isHost === true) {
      pattern = this.firstLevel;
    }
    else{
      pattern = '[^\\.]+' + (this.wildcard ? this.getWildcardPattern() : this.getNormalPattern());
    }
  
    return before + pattern + after;
  };
  
  module.exports = Rule;
  
  },{}],56:[function(require,module,exports){
  var cleanHostValue = require('./clean-host.js');
  var getDomain = require('./domain.js');
  var escapeRegExp = require('./escape-regexp.js');
  
  /**
   * Returns the subdomain of a host string
   *
   * @api
   * @param {string} host
   * @return {string|null} a subdomain string if any, blank string if subdomain is empty, otherwise null
   */
  module.exports = function getSubdomain(allRules, validHosts, host){
    var domain, r, subdomain;
  
    host = cleanHostValue(host);
    domain = getDomain(allRules, validHosts, host);
  
    // No domain found? Just abort, abort!
    if (domain === null){
      return null;
    }
  
    r = '\\.?'+ escapeRegExp(domain)+'$';
    subdomain = host.replace(new RegExp(r, 'i'), '');
  
    return subdomain;
  };
  
  },{"./clean-host.js":47,"./domain.js":48,"./escape-regexp.js":49}],57:[function(require,module,exports){
  var cleanHostValue = require('./clean-host.js');
  var extractTldFromHost = require('./from-host.js');
  
  /**
   * Checks if the TLD exists for a given host
   *
   * @api
   * @param {string} host
   * @return {boolean}
   */
  module.exports = function tldExists(rules, host){
    var hostTld;
  
    host = cleanHostValue(host);
  
    // Easy case, it's a TLD
    if (rules[host]){
      return true;
    }
  
    // Popping only the TLD of the hostname
    hostTld = extractTldFromHost(host);
  
    return rules[hostTld] !== undefined;
  };
  
  },{"./clean-host.js":47,"./from-host.js":50}],58:[function(require,module,exports){
  "use strict";
  
  var Rule = require('./rule.js');
  var map = require('./polyfills/array-map.js');
  
  /**
   * Retrieve a subset of rules for a Top-Level-Domain string
   *
   * @param tld {String} Top-Level-Domain string
   * @return {Array} Rules subset
   */
  module.exports = function getRulesForTld (allRules, tld, default_rule) {
    var exception = '!';
    var wildcard = '*';
    var append_tld_rule = true;
    var rules = allRules[tld];
  
    // Already parsed
    // Array.isArray polyfill for IE8
    if (Object.prototype.toString.call(rules)  === '[object Array]') {
      return rules;
    }
  
    // Nothing found, apply some default value
    if (rules === void 0) {
      return default_rule ? [ default_rule ] : [];
    }
  
    // Parsing needed
    rules = map(rules.split('|'), function transformAsRule (sld) {
      var first_bit = sld[0];
  
      if (first_bit === exception || first_bit === wildcard) {
        sld = sld.slice(1);
  
        if (!sld) {
          append_tld_rule = false;
        }
      }
  
      return new Rule({
        "firstLevel":  tld,
        "secondLevel": sld,
        "exception":   first_bit === exception,
        "wildcard":    first_bit === wildcard
      });
    });
  
    // Always prepend to make it the latest rule to be applied
    if (append_tld_rule) {
      rules.unshift(new Rule({
        "firstLevel": tld
      }));
    }
  
    allRules[tld] = rules.reverse();
  
    return rules;
  };
  
  },{"./polyfills/array-map.js":52,"./rule.js":55}],59:[function(require,module,exports){
  module.exports={"ac":"com|edu|gov|net|mil|org","ad":"nom","ae":"co|net|org|sch|ac|gov|mil|blogspot|nom","aero":"accident-investigation|accident-prevention|aerobatic|aeroclub|aerodrome|agents|aircraft|airline|airport|air-surveillance|airtraffic|air-traffic-control|ambulance|amusement|association|author|ballooning|broker|caa|cargo|catering|certification|championship|charter|civilaviation|club|conference|consultant|consulting|control|council|crew|design|dgca|educator|emergency|engine|engineer|entertainment|equipment|exchange|express|federation|flight|freight|fuel|gliding|government|groundhandling|group|hanggliding|homebuilt|insurance|journal|journalist|leasing|logistics|magazine|maintenance|media|microlight|modelling|navigation|parachuting|paragliding|passenger-association|pilot|press|production|recreation|repbody|res|research|rotorcraft|safety|scientist|services|show|skydiving|software|student|trader|trading|trainer|union|workinggroup|works","af":"gov|com|org|net|edu","ag":"com|org|net|co|nom","ai":"off|com|net|org|nom","al":"com|edu|gov|mil|net|org|blogspot|nom","am":"blogspot","ao":"ed|gv|og|co|pb|it","aq":"","ar":"com|edu|gob|gov|int|mil|musica|net|org|tur|blogspot.com","arpa":"e164|in-addr|ip6|iris|uri|urn","as":"gov","asia":"cloudns","at":"ac|co|gv|or|futurehosting|futuremailing|*ex.ortsinfo|*kunden.ortsinfo|blogspot.co|biz|info|priv|12hp|2ix|4lima|lima-city","au":"com|net|org|edu|gov|asn|id|info|conf|oz|act|nsw|nt|qld|sa|tas|vic|wa|act.edu|nsw.edu|nt.edu|qld.edu|sa.edu|tas.edu|vic.edu|wa.edu|qld.gov|sa.gov|tas.gov|vic.gov|wa.gov|blogspot.com","aw":"com","ax":"","az":"com|net|int|gov|org|edu|info|pp|mil|name|pro|biz","ba":"com|edu|gov|mil|net|org|blogspot","bb":"biz|co|com|edu|gov|info|net|org|store|tv","bd":"*","be":"ac|blogspot|*transurl","bf":"gov","bg":"a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|0|1|2|3|4|5|6|7|8|9|blogspot|barsy","bh":"com|edu|net|org|gov","bi":"co|com|edu|or|org","biz":"cloudns|dyndns|for-better|for-more|for-some|for-the|selfip|webhop|mmafan|myftp|no-ip|dscloud","bj":"asso|barreau|gouv|blogspot","bm":"com|edu|gov|net|org","bn":"*","bo":"com|edu|gov|gob|int|org|net|mil|tv","br":"adm|adv|agr|am|arq|art|ato|b|belem|bio|blog|bmd|cim|cng|cnt|com|coop|cri|def|ecn|eco|edu|emp|eng|esp|etc|eti|far|flog|floripa|fm|fnd|fot|fst|g12|ggf|gov|ac.gov|al.gov|am.gov|ap.gov|ba.gov|ce.gov|df.gov|es.gov|go.gov|ma.gov|mg.gov|ms.gov|mt.gov|pa.gov|pb.gov|pe.gov|pi.gov|pr.gov|rj.gov|rn.gov|ro.gov|rr.gov|rs.gov|sc.gov|se.gov|sp.gov|to.gov|imb|ind|inf|jampa|jor|jus|leg|lel|mat|med|mil|mp|mus|net|*nom|not|ntr|odo|org|poa|ppg|pro|psc|psi|qsl|radio|rec|recife|slg|srv|taxi|teo|tmp|trd|tur|tv|vet|vix|vlog|wiki|zlg|blogspot.com|ac.leg|al.leg|am.leg|ap.leg|ba.leg|ce.leg|df.leg|es.leg|go.leg|ma.leg|mg.leg|ms.leg|mt.leg|pa.leg|pb.leg|pe.leg|pi.leg|pr.leg|rj.leg|rn.leg|ro.leg|rr.leg|rs.leg|sc.leg|se.leg|sp.leg|to.leg","bs":"com|net|org|edu|gov|we","bt":"com|edu|gov|net|org","bv":"","bw":"co|org","by":"gov|mil|com|of|blogspot.com|nym","bz":"com|net|org|edu|gov|za|nym","ca":"ab|bc|mb|nb|nf|nl|ns|nt|nu|on|pe|qc|sk|yk|gc|*awdev|co|blogspot|no-ip","cat":"","cc":"cloudns|ftpaccess|game-server|myphotos|scrapping|twmail|fantasyleague","cd":"gov","cf":"blogspot","cg":"","ch":"square7|blogspot|gotdns|12hp|2ix|4lima|lima-city","ci":"org|or|com|co|edu|ed|ac|net|go|asso|xn--aroport-bya|int|presse|md|gouv","ck":"*|!www","cl":"gov|gob|co|mil|blogspot|nom","cm":"co|com|gov|net","cn":"ac|com|edu|gov|net|org|mil|xn--55qx5d|xn--io0a7i|xn--od0alg|ah|bj|cq|fj|gd|gs|gz|gx|ha|hb|he|hi|hl|hn|jl|js|jx|ln|nm|nx|qh|sc|sd|sh|sn|sx|tj|xj|xz|yn|zj|hk|mo|tw|*compute.amazonaws.com|elasticbeanstalk.cn-north-1.amazonaws.com|*elb.amazonaws.com|s3.cn-north-1.amazonaws.com","co":"arts|com|edu|firm|gov|info|int|mil|net|nom|org|rec|web|blogspot.com|nodum","com":"*compute.amazonaws|*compute-1.amazonaws|us-east-1.amazonaws|*elasticbeanstalk|*elb.amazonaws|s3.amazonaws|s3-ap-northeast-1.amazonaws|s3-ap-northeast-2.amazonaws|s3-ap-south-1.amazonaws|s3-ap-southeast-1.amazonaws|s3-ap-southeast-2.amazonaws|s3-ca-central-1.amazonaws|s3-eu-central-1.amazonaws|s3-eu-west-1.amazonaws|s3-eu-west-2.amazonaws|s3-external-1.amazonaws|s3-fips-us-gov-west-1.amazonaws|s3-sa-east-1.amazonaws|s3-us-gov-west-1.amazonaws|s3-us-east-2.amazonaws|s3-us-west-1.amazonaws|s3-us-west-2.amazonaws|s3.ap-northeast-2.amazonaws|s3.ap-south-1.amazonaws|s3.ca-central-1.amazonaws|s3.eu-central-1.amazonaws|s3.eu-west-2.amazonaws|s3.us-east-2.amazonaws|s3.dualstack.ap-northeast-1.amazonaws|s3.dualstack.ap-northeast-2.amazonaws|s3.dualstack.ap-south-1.amazonaws|s3.dualstack.ap-southeast-1.amazonaws|s3.dualstack.ap-southeast-2.amazonaws|s3.dualstack.ca-central-1.amazonaws|s3.dualstack.eu-central-1.amazonaws|s3.dualstack.eu-west-1.amazonaws|s3.dualstack.eu-west-2.amazonaws|s3.dualstack.sa-east-1.amazonaws|s3.dualstack.us-east-1.amazonaws|s3.dualstack.us-east-2.amazonaws|s3-website-us-east-1.amazonaws|s3-website-us-west-1.amazonaws|s3-website-us-west-2.amazonaws|s3-website-ap-northeast-1.amazonaws|s3-website-ap-southeast-1.amazonaws|s3-website-ap-southeast-2.amazonaws|s3-website-eu-west-1.amazonaws|s3-website-sa-east-1.amazonaws|s3-website.ap-northeast-2.amazonaws|s3-website.ap-south-1.amazonaws|s3-website.ca-central-1.amazonaws|s3-website.eu-central-1.amazonaws|s3-website.eu-west-2.amazonaws|s3-website.us-east-2.amazonaws|on-aptible|myasustor|betainabox|bplaced|ar|br|cn|de|eu|gb|hu|jpn|kr|mex|no|qc|ru|sa|se|uk|us|uy|za|africa|gr|co|xenapponazure|jdevcloud|wpdevcloud|cloudcontrolled|cloudcontrolapp|drayddns|dreamhosters|mydrobo|dyndns-at-home|dyndns-at-work|dyndns-blog|dyndns-free|dyndns-home|dyndns-ip|dyndns-mail|dyndns-office|dyndns-pics|dyndns-remote|dyndns-server|dyndns-web|dyndns-wiki|dyndns-work|blogdns|cechire|dnsalias|dnsdojo|doesntexist|dontexist|doomdns|dyn-o-saur|dynalias|est-a-la-maison|est-a-la-masion|est-le-patron|est-mon-blogueur|from-ak|from-al|from-ar|from-ca|from-ct|from-dc|from-de|from-fl|from-ga|from-hi|from-ia|from-id|from-il|from-in|from-ks|from-ky|from-ma|from-md|from-mi|from-mn|from-mo|from-ms|from-mt|from-nc|from-nd|from-ne|from-nh|from-nj|from-nm|from-nv|from-oh|from-ok|from-or|from-pa|from-pr|from-ri|from-sc|from-sd|from-tn|from-tx|from-ut|from-va|from-vt|from-wa|from-wi|from-wv|from-wy|getmyip|gotdns|hobby-site|homelinux|homeunix|iamallama|is-a-anarchist|is-a-blogger|is-a-bookkeeper|is-a-bulls-fan|is-a-caterer|is-a-chef|is-a-conservative|is-a-cpa|is-a-cubicle-slave|is-a-democrat|is-a-designer|is-a-doctor|is-a-financialadvisor|is-a-geek|is-a-green|is-a-guru|is-a-hard-worker|is-a-hunter|is-a-landscaper|is-a-lawyer|is-a-liberal|is-a-libertarian|is-a-llama|is-a-musician|is-a-nascarfan|is-a-nurse|is-a-painter|is-a-personaltrainer|is-a-photographer|is-a-player|is-a-republican|is-a-rockstar|is-a-socialist|is-a-student|is-a-teacher|is-a-techie|is-a-therapist|is-an-accountant|is-an-actor|is-an-actress|is-an-anarchist|is-an-artist|is-an-engineer|is-an-entertainer|is-certified|is-gone|is-into-anime|is-into-cars|is-into-cartoons|is-into-games|is-leet|is-not-certified|is-slick|is-uberleet|is-with-theband|isa-geek|isa-hockeynut|issmarterthanyou|likes-pie|likescandy|neat-url|saves-the-whales|selfip|sells-for-less|sells-for-u|servebbs|simple-url|space-to-rent|teaches-yoga|writesthisblog|ddnsfree|ddnsgeek|giize|gleeze|kozow|loseyourip|ooguy|theworkpc|mytuleap|eu-1.evennode|eu-2.evennode|eu-3.evennode|eu-4.evennode|us-1.evennode|us-2.evennode|us-3.evennode|us-4.evennode|apps.fbsbx|firebaseapp|flynnhub|freebox-os|freeboxos|githubusercontent|*0emm|appspot|blogspot|codespot|googleapis|googlecode|pagespeedmobilizer|publishproxy|withgoogle|withyoutube|herokuapp|herokussl|*cns.joyent|barsyonline|meteorapp|eu.meteorapp|bitballoon|netlify|4u|nfshost|blogsyte|ciscofreak|damnserver|ditchyourip|dnsiskinky|dynns|geekgalaxy|health-carereform|homesecuritymac|homesecuritypc|myactivedirectory|mysecuritycamera|net-freaks|onthewifi|point2this|quicksytes|securitytactics|serveexchange|servehumour|servep2p|servesarcasm|stufftoread|unusualperson|workisboring|3utilities|ddnsking|myvnc|servebeer|servecounterstrike|serveftp|servegame|servehalflife|servehttp|serveirc|servemp3|servepics|servequake|operaunite|outsystemscloud|ownprovider|pgfog|pagefrontapp|gotpantheon|xen.prgmr|qa2|dev-myqnapcloud|alpha-myqnapcloud|myqnapcloud|*quipelements|rackmaze|rhcloud|logoip|firewall-gateway|myshopblocks|1kapp|appchizi|applinzi|sinaapp|vipsinaapp|bounty-full|alpha.bounty-full|beta.bounty-full|temp-dns|dsmynas|familyds|bloxcms|townnews-staging|hk|remotewd|yolasite","coop":"","cr":"ac|co|ed|fi|go|or|sa","cu":"com|edu|org|net|gov|inf","cv":"blogspot","cw":"com|edu|net|org","cx":"gov|ath|info","cy":"ac|biz|com|ekloges|gov|ltd|name|net|org|parliament|press|pro|tm|blogspot.com","cz":"co|realm|e4|blogspot|cloud.metacentrum|custom.metacentrum","de":"bplaced|square7|com|dyn.cosidns|dynamisches-dns|dnsupdater|internet-dns|l-o-g-i-n|dnshome|fuettertdasnetz|isteingeek|istmein|lebtimnetz|leitungsen|traeumtgerade|ddnss|dyn.ddnss|dyndns.ddnss|dyndns1|dyn-ip24|home-webserver|dyn.home-webserver|myhome-server|goip|blogspot|keymachine|git-repos|lcube-server|svn-repos|barsy|logoip|firewall-gateway|my-gateway|my-router|spdns|taifun-dns|12hp|2ix|4lima|lima-city|dd-dns|dray-dns|draydns|dyn-vpn|dynvpn|mein-vigor|my-vigor|my-wan|syno-ds|synology-diskstation|synology-ds","dj":"","dk":"biz|co|firm|reg|store|blogspot","dm":"com|net|org|edu|gov","do":"art|com|edu|gob|gov|mil|net|org|sld|web","dz":"com|org|net|gov|edu|asso|pol|art","ec":"com|info|net|fin|k12|med|pro|org|edu|gov|gob|mil","edu":"","ee":"edu|gov|riik|lib|med|com|pri|aip|org|fie|blogspot.com","eg":"com|edu|eun|gov|mil|name|net|org|sci|blogspot.com","er":"*","es":"com|nom|org|gob|edu|blogspot.com","et":"com|gov|org|edu|biz|name|info|net","eu":"mycd|cloudns|barsy|wellbeingzone|spdns|*transurl|diskstation","fi":"aland|dy|blogspot|iki","fj":"*","fk":"*","fm":"","fo":"","fr":"com|asso|nom|prd|presse|tm|aeroport|assedic|avocat|avoues|cci|chambagri|chirurgiens-dentistes|experts-comptables|geometre-expert|gouv|greta|huissier-justice|medecin|notaires|pharmacien|port|veterinaire|fbx-os|fbxos|freebox-os|freeboxos|blogspot|on-web|chirurgiens-dentistes-en-france","ga":"","gb":"","gd":"nom","ge":"com|edu|gov|org|mil|net|pvt","gf":"","gg":"co|net|org|cya","gh":"com|edu|gov|org|mil","gi":"com|ltd|gov|mod|edu|org","gl":"co|com|edu|net|org|nom","gm":"","gn":"ac|com|edu|gov|org|net","gov":"","gp":"com|net|mobi|edu|org|asso","gq":"","gr":"com|edu|net|org|gov|blogspot|nym","gs":"","gt":"com|edu|gob|ind|mil|net|org|nom","gu":"*","gw":"","gy":"co|com|edu|gov|net|org","hk":"com|edu|gov|idv|net|org|xn--55qx5d|xn--wcvs22d|xn--lcvr32d|xn--mxtq1m|xn--gmqw5a|xn--ciqpn|xn--gmq050i|xn--zf0avx|xn--io0a7i|xn--mk0axi|xn--od0alg|xn--od0aq3b|xn--tn0ag|xn--uc0atv|xn--uc0ay4a|blogspot|ltd|inc","hm":"","hn":"com|edu|org|net|mil|gob|nom","hr":"iz|from|name|com|blogspot","ht":"com|shop|firm|info|adult|net|pro|org|med|art|coop|pol|asso|edu|rel|gouv|perso","hu":"co|info|org|priv|sport|tm|2000|agrar|bolt|casino|city|erotica|erotika|film|forum|games|hotel|ingatlan|jogasz|konyvelo|lakas|media|news|reklam|sex|shop|suli|szex|tozsde|utazas|video|blogspot","id":"ac|biz|co|desa|go|mil|my|net|or|sch|web|blogspot.co","ie":"gov|blogspot","il":"ac|co|gov|idf|k12|muni|net|org|blogspot.co","im":"ac|co|com|ltd.co|net|org|plc.co|tt|tv|ro|nom","in":"co|firm|net|org|gen|ind|nic|ac|edu|res|gov|mil|cloudns|blogspot|barsy","info":"cloudns|dynamic-dns|dyndns|barrel-of-knowledge|barrell-of-knowledge|for-our|groks-the|groks-this|here-for-more|knowsitall|selfip|webhop|nsupdate|dvrcam|ilovecollege|no-ip","int":"eu","io":"com|backplaneapp|boxfuse|browsersafetymark|dedyn|drud|definima|enonic|customer.enonic|github|gitlab|hasura-app|ngrok|stage.nodeart|nodum|nid|pantheonsite|protonet|vaporcloud|hzc|sandcats|shiftedit|apps.lair|*stolos|spacekit|cust.dev.thingdust|cust.disrec.thingdust|cust.prod.thingdust|cust.testing.thingdust|wedeploy","iq":"gov|edu|mil|com|org|net","ir":"ac|co|gov|id|net|org|sch|xn--mgba3a4f16a|xn--mgba3a4fra","is":"net|com|edu|gov|org|int|cupcake|blogspot","it":"gov|edu|abr|abruzzo|aosta-valley|aostavalley|bas|basilicata|cal|calabria|cam|campania|emilia-romagna|emiliaromagna|emr|friuli-v-giulia|friuli-ve-giulia|friuli-vegiulia|friuli-venezia-giulia|friuli-veneziagiulia|friuli-vgiulia|friuliv-giulia|friulive-giulia|friulivegiulia|friulivenezia-giulia|friuliveneziagiulia|friulivgiulia|fvg|laz|lazio|lig|liguria|lom|lombardia|lombardy|lucania|mar|marche|mol|molise|piedmont|piemonte|pmn|pug|puglia|sar|sardegna|sardinia|sic|sicilia|sicily|taa|tos|toscana|trentino-a-adige|trentino-aadige|trentino-alto-adige|trentino-altoadige|trentino-s-tirol|trentino-stirol|trentino-sud-tirol|trentino-sudtirol|trentino-sued-tirol|trentino-suedtirol|trentinoa-adige|trentinoaadige|trentinoalto-adige|trentinoaltoadige|trentinos-tirol|trentinostirol|trentinosud-tirol|trentinosudtirol|trentinosued-tirol|trentinosuedtirol|tuscany|umb|umbria|val-d-aosta|val-daosta|vald-aosta|valdaosta|valle-aosta|valle-d-aosta|valle-daosta|valleaosta|valled-aosta|valledaosta|vallee-aoste|valleeaoste|vao|vda|ven|veneto|ag|agrigento|al|alessandria|alto-adige|altoadige|an|ancona|andria-barletta-trani|andria-trani-barletta|andriabarlettatrani|andriatranibarletta|ao|aosta|aoste|ap|aq|aquila|ar|arezzo|ascoli-piceno|ascolipiceno|asti|at|av|avellino|ba|balsan|bari|barletta-trani-andria|barlettatraniandria|belluno|benevento|bergamo|bg|bi|biella|bl|bn|bo|bologna|bolzano|bozen|br|brescia|brindisi|bs|bt|bz|ca|cagliari|caltanissetta|campidano-medio|campidanomedio|campobasso|carbonia-iglesias|carboniaiglesias|carrara-massa|carraramassa|caserta|catania|catanzaro|cb|ce|cesena-forli|cesenaforli|ch|chieti|ci|cl|cn|co|como|cosenza|cr|cremona|crotone|cs|ct|cuneo|cz|dell-ogliastra|dellogliastra|en|enna|fc|fe|fermo|ferrara|fg|fi|firenze|florence|fm|foggia|forli-cesena|forlicesena|fr|frosinone|ge|genoa|genova|go|gorizia|gr|grosseto|iglesias-carbonia|iglesiascarbonia|im|imperia|is|isernia|kr|la-spezia|laquila|laspezia|latina|lc|le|lecce|lecco|li|livorno|lo|lodi|lt|lu|lucca|macerata|mantova|massa-carrara|massacarrara|matera|mb|mc|me|medio-campidano|mediocampidano|messina|mi|milan|milano|mn|mo|modena|monza-brianza|monza-e-della-brianza|monza|monzabrianza|monzaebrianza|monzaedellabrianza|ms|mt|na|naples|napoli|no|novara|nu|nuoro|og|ogliastra|olbia-tempio|olbiatempio|or|oristano|ot|pa|padova|padua|palermo|parma|pavia|pc|pd|pe|perugia|pesaro-urbino|pesarourbino|pescara|pg|pi|piacenza|pisa|pistoia|pn|po|pordenone|potenza|pr|prato|pt|pu|pv|pz|ra|ragusa|ravenna|rc|re|reggio-calabria|reggio-emilia|reggiocalabria|reggioemilia|rg|ri|rieti|rimini|rm|rn|ro|roma|rome|rovigo|sa|salerno|sassari|savona|si|siena|siracusa|so|sondrio|sp|sr|ss|suedtirol|sv|ta|taranto|te|tempio-olbia|tempioolbia|teramo|terni|tn|to|torino|tp|tr|trani-andria-barletta|trani-barletta-andria|traniandriabarletta|tranibarlettaandria|trapani|trentino|trento|treviso|trieste|ts|turin|tv|ud|udine|urbino-pesaro|urbinopesaro|va|varese|vb|vc|ve|venezia|venice|verbania|vercelli|verona|vi|vibo-valentia|vibovalentia|vicenza|viterbo|vr|vs|vt|vv|blogspot","je":"co|net|org","jm":"*","jo":"com|org|net|edu|sch|gov|mil|name","jobs":"","jp":"ac|ad|co|ed|go|gr|lg|ne|or|aichi|akita|aomori|chiba|ehime|fukui|fukuoka|fukushima|gifu|gunma|hiroshima|hokkaido|hyogo|ibaraki|ishikawa|iwate|kagawa|kagoshima|kanagawa|kochi|kumamoto|kyoto|mie|miyagi|miyazaki|nagano|nagasaki|nara|niigata|oita|okayama|okinawa|osaka|saga|saitama|shiga|shimane|shizuoka|tochigi|tokushima|tokyo|tottori|toyama|wakayama|yamagata|yamaguchi|yamanashi|xn--4pvxs|xn--vgu402c|xn--c3s14m|xn--f6qx53a|xn--8pvr4u|xn--uist22h|xn--djrs72d6uy|xn--mkru45i|xn--0trq7p7nn|xn--8ltr62k|xn--2m4a15e|xn--efvn9s|xn--32vp30h|xn--4it797k|xn--1lqs71d|xn--5rtp49c|xn--5js045d|xn--ehqz56n|xn--1lqs03n|xn--qqqt11m|xn--kbrq7o|xn--pssu33l|xn--ntsq17g|xn--uisz3g|xn--6btw5a|xn--1ctwo|xn--6orx2r|xn--rht61e|xn--rht27z|xn--djty4k|xn--nit225k|xn--rht3d|xn--klty5x|xn--kltx9a|xn--kltp7d|xn--uuwu58a|xn--zbx025d|xn--ntso0iqx3a|xn--elqq16h|xn--4it168d|xn--klt787d|xn--rny31h|xn--7t0a264c|xn--5rtq34k|xn--k7yn95e|xn--tor131o|xn--d5qv7z876c|*kawasaki|*kitakyushu|*kobe|*nagoya|*sapporo|*sendai|*yokohama|!city.kawasaki|!city.kitakyushu|!city.kobe|!city.nagoya|!city.sapporo|!city.sendai|!city.yokohama|aisai.aichi|ama.aichi|anjo.aichi|asuke.aichi|chiryu.aichi|chita.aichi|fuso.aichi|gamagori.aichi|handa.aichi|hazu.aichi|hekinan.aichi|higashiura.aichi|ichinomiya.aichi|inazawa.aichi|inuyama.aichi|isshiki.aichi|iwakura.aichi|kanie.aichi|kariya.aichi|kasugai.aichi|kira.aichi|kiyosu.aichi|komaki.aichi|konan.aichi|kota.aichi|mihama.aichi|miyoshi.aichi|nishio.aichi|nisshin.aichi|obu.aichi|oguchi.aichi|oharu.aichi|okazaki.aichi|owariasahi.aichi|seto.aichi|shikatsu.aichi|shinshiro.aichi|shitara.aichi|tahara.aichi|takahama.aichi|tobishima.aichi|toei.aichi|togo.aichi|tokai.aichi|tokoname.aichi|toyoake.aichi|toyohashi.aichi|toyokawa.aichi|toyone.aichi|toyota.aichi|tsushima.aichi|yatomi.aichi|akita.akita|daisen.akita|fujisato.akita|gojome.akita|hachirogata.akita|happou.akita|higashinaruse.akita|honjo.akita|honjyo.akita|ikawa.akita|kamikoani.akita|kamioka.akita|katagami.akita|kazuno.akita|kitaakita.akita|kosaka.akita|kyowa.akita|misato.akita|mitane.akita|moriyoshi.akita|nikaho.akita|noshiro.akita|odate.akita|oga.akita|ogata.akita|semboku.akita|yokote.akita|yurihonjo.akita|aomori.aomori|gonohe.aomori|hachinohe.aomori|hashikami.aomori|hiranai.aomori|hirosaki.aomori|itayanagi.aomori|kuroishi.aomori|misawa.aomori|mutsu.aomori|nakadomari.aomori|noheji.aomori|oirase.aomori|owani.aomori|rokunohe.aomori|sannohe.aomori|shichinohe.aomori|shingo.aomori|takko.aomori|towada.aomori|tsugaru.aomori|tsuruta.aomori|abiko.chiba|asahi.chiba|chonan.chiba|chosei.chiba|choshi.chiba|chuo.chiba|funabashi.chiba|futtsu.chiba|hanamigawa.chiba|ichihara.chiba|ichikawa.chiba|ichinomiya.chiba|inzai.chiba|isumi.chiba|kamagaya.chiba|kamogawa.chiba|kashiwa.chiba|katori.chiba|katsuura.chiba|kimitsu.chiba|kisarazu.chiba|kozaki.chiba|kujukuri.chiba|kyonan.chiba|matsudo.chiba|midori.chiba|mihama.chiba|minamiboso.chiba|mobara.chiba|mutsuzawa.chiba|nagara.chiba|nagareyama.chiba|narashino.chiba|narita.chiba|noda.chiba|oamishirasato.chiba|omigawa.chiba|onjuku.chiba|otaki.chiba|sakae.chiba|sakura.chiba|shimofusa.chiba|shirako.chiba|shiroi.chiba|shisui.chiba|sodegaura.chiba|sosa.chiba|tako.chiba|tateyama.chiba|togane.chiba|tohnosho.chiba|tomisato.chiba|urayasu.chiba|yachimata.chiba|yachiyo.chiba|yokaichiba.chiba|yokoshibahikari.chiba|yotsukaido.chiba|ainan.ehime|honai.ehime|ikata.ehime|imabari.ehime|iyo.ehime|kamijima.ehime|kihoku.ehime|kumakogen.ehime|masaki.ehime|matsuno.ehime|matsuyama.ehime|namikata.ehime|niihama.ehime|ozu.ehime|saijo.ehime|seiyo.ehime|shikokuchuo.ehime|tobe.ehime|toon.ehime|uchiko.ehime|uwajima.ehime|yawatahama.ehime|echizen.fukui|eiheiji.fukui|fukui.fukui|ikeda.fukui|katsuyama.fukui|mihama.fukui|minamiechizen.fukui|obama.fukui|ohi.fukui|ono.fukui|sabae.fukui|sakai.fukui|takahama.fukui|tsuruga.fukui|wakasa.fukui|ashiya.fukuoka|buzen.fukuoka|chikugo.fukuoka|chikuho.fukuoka|chikujo.fukuoka|chikushino.fukuoka|chikuzen.fukuoka|chuo.fukuoka|dazaifu.fukuoka|fukuchi.fukuoka|hakata.fukuoka|higashi.fukuoka|hirokawa.fukuoka|hisayama.fukuoka|iizuka.fukuoka|inatsuki.fukuoka|kaho.fukuoka|kasuga.fukuoka|kasuya.fukuoka|kawara.fukuoka|keisen.fukuoka|koga.fukuoka|kurate.fukuoka|kurogi.fukuoka|kurume.fukuoka|minami.fukuoka|miyako.fukuoka|miyama.fukuoka|miyawaka.fukuoka|mizumaki.fukuoka|munakata.fukuoka|nakagawa.fukuoka|nakama.fukuoka|nishi.fukuoka|nogata.fukuoka|ogori.fukuoka|okagaki.fukuoka|okawa.fukuoka|oki.fukuoka|omuta.fukuoka|onga.fukuoka|onojo.fukuoka|oto.fukuoka|saigawa.fukuoka|sasaguri.fukuoka|shingu.fukuoka|shinyoshitomi.fukuoka|shonai.fukuoka|soeda.fukuoka|sue.fukuoka|tachiarai.fukuoka|tagawa.fukuoka|takata.fukuoka|toho.fukuoka|toyotsu.fukuoka|tsuiki.fukuoka|ukiha.fukuoka|umi.fukuoka|usui.fukuoka|yamada.fukuoka|yame.fukuoka|yanagawa.fukuoka|yukuhashi.fukuoka|aizubange.fukushima|aizumisato.fukushima|aizuwakamatsu.fukushima|asakawa.fukushima|bandai.fukushima|date.fukushima|fukushima.fukushima|furudono.fukushima|futaba.fukushima|hanawa.fukushima|higashi.fukushima|hirata.fukushima|hirono.fukushima|iitate.fukushima|inawashiro.fukushima|ishikawa.fukushima|iwaki.fukushima|izumizaki.fukushima|kagamiishi.fukushima|kaneyama.fukushima|kawamata.fukushima|kitakata.fukushima|kitashiobara.fukushima|koori.fukushima|koriyama.fukushima|kunimi.fukushima|miharu.fukushima|mishima.fukushima|namie.fukushima|nango.fukushima|nishiaizu.fukushima|nishigo.fukushima|okuma.fukushima|omotego.fukushima|ono.fukushima|otama.fukushima|samegawa.fukushima|shimogo.fukushima|shirakawa.fukushima|showa.fukushima|soma.fukushima|sukagawa.fukushima|taishin.fukushima|tamakawa.fukushima|tanagura.fukushima|tenei.fukushima|yabuki.fukushima|yamato.fukushima|yamatsuri.fukushima|yanaizu.fukushima|yugawa.fukushima|anpachi.gifu|ena.gifu|gifu.gifu|ginan.gifu|godo.gifu|gujo.gifu|hashima.gifu|hichiso.gifu|hida.gifu|higashishirakawa.gifu|ibigawa.gifu|ikeda.gifu|kakamigahara.gifu|kani.gifu|kasahara.gifu|kasamatsu.gifu|kawaue.gifu|kitagata.gifu|mino.gifu|minokamo.gifu|mitake.gifu|mizunami.gifu|motosu.gifu|nakatsugawa.gifu|ogaki.gifu|sakahogi.gifu|seki.gifu|sekigahara.gifu|shirakawa.gifu|tajimi.gifu|takayama.gifu|tarui.gifu|toki.gifu|tomika.gifu|wanouchi.gifu|yamagata.gifu|yaotsu.gifu|yoro.gifu|annaka.gunma|chiyoda.gunma|fujioka.gunma|higashiagatsuma.gunma|isesaki.gunma|itakura.gunma|kanna.gunma|kanra.gunma|katashina.gunma|kawaba.gunma|kiryu.gunma|kusatsu.gunma|maebashi.gunma|meiwa.gunma|midori.gunma|minakami.gunma|naganohara.gunma|nakanojo.gunma|nanmoku.gunma|numata.gunma|oizumi.gunma|ora.gunma|ota.gunma|shibukawa.gunma|shimonita.gunma|shinto.gunma|showa.gunma|takasaki.gunma|takayama.gunma|tamamura.gunma|tatebayashi.gunma|tomioka.gunma|tsukiyono.gunma|tsumagoi.gunma|ueno.gunma|yoshioka.gunma|asaminami.hiroshima|daiwa.hiroshima|etajima.hiroshima|fuchu.hiroshima|fukuyama.hiroshima|hatsukaichi.hiroshima|higashihiroshima.hiroshima|hongo.hiroshima|jinsekikogen.hiroshima|kaita.hiroshima|kui.hiroshima|kumano.hiroshima|kure.hiroshima|mihara.hiroshima|miyoshi.hiroshima|naka.hiroshima|onomichi.hiroshima|osakikamijima.hiroshima|otake.hiroshima|saka.hiroshima|sera.hiroshima|seranishi.hiroshima|shinichi.hiroshima|shobara.hiroshima|takehara.hiroshima|abashiri.hokkaido|abira.hokkaido|aibetsu.hokkaido|akabira.hokkaido|akkeshi.hokkaido|asahikawa.hokkaido|ashibetsu.hokkaido|ashoro.hokkaido|assabu.hokkaido|atsuma.hokkaido|bibai.hokkaido|biei.hokkaido|bifuka.hokkaido|bihoro.hokkaido|biratori.hokkaido|chippubetsu.hokkaido|chitose.hokkaido|date.hokkaido|ebetsu.hokkaido|embetsu.hokkaido|eniwa.hokkaido|erimo.hokkaido|esan.hokkaido|esashi.hokkaido|fukagawa.hokkaido|fukushima.hokkaido|furano.hokkaido|furubira.hokkaido|haboro.hokkaido|hakodate.hokkaido|hamatonbetsu.hokkaido|hidaka.hokkaido|higashikagura.hokkaido|higashikawa.hokkaido|hiroo.hokkaido|hokuryu.hokkaido|hokuto.hokkaido|honbetsu.hokkaido|horokanai.hokkaido|horonobe.hokkaido|ikeda.hokkaido|imakane.hokkaido|ishikari.hokkaido|iwamizawa.hokkaido|iwanai.hokkaido|kamifurano.hokkaido|kamikawa.hokkaido|kamishihoro.hokkaido|kamisunagawa.hokkaido|kamoenai.hokkaido|kayabe.hokkaido|kembuchi.hokkaido|kikonai.hokkaido|kimobetsu.hokkaido|kitahiroshima.hokkaido|kitami.hokkaido|kiyosato.hokkaido|koshimizu.hokkaido|kunneppu.hokkaido|kuriyama.hokkaido|kuromatsunai.hokkaido|kushiro.hokkaido|kutchan.hokkaido|kyowa.hokkaido|mashike.hokkaido|matsumae.hokkaido|mikasa.hokkaido|minamifurano.hokkaido|mombetsu.hokkaido|moseushi.hokkaido|mukawa.hokkaido|muroran.hokkaido|naie.hokkaido|nakagawa.hokkaido|nakasatsunai.hokkaido|nakatombetsu.hokkaido|nanae.hokkaido|nanporo.hokkaido|nayoro.hokkaido|nemuro.hokkaido|niikappu.hokkaido|niki.hokkaido|nishiokoppe.hokkaido|noboribetsu.hokkaido|numata.hokkaido|obihiro.hokkaido|obira.hokkaido|oketo.hokkaido|okoppe.hokkaido|otaru.hokkaido|otobe.hokkaido|otofuke.hokkaido|otoineppu.hokkaido|oumu.hokkaido|ozora.hokkaido|pippu.hokkaido|rankoshi.hokkaido|rebun.hokkaido|rikubetsu.hokkaido|rishiri.hokkaido|rishirifuji.hokkaido|saroma.hokkaido|sarufutsu.hokkaido|shakotan.hokkaido|shari.hokkaido|shibecha.hokkaido|shibetsu.hokkaido|shikabe.hokkaido|shikaoi.hokkaido|shimamaki.hokkaido|shimizu.hokkaido|shimokawa.hokkaido|shinshinotsu.hokkaido|shintoku.hokkaido|shiranuka.hokkaido|shiraoi.hokkaido|shiriuchi.hokkaido|sobetsu.hokkaido|sunagawa.hokkaido|taiki.hokkaido|takasu.hokkaido|takikawa.hokkaido|takinoue.hokkaido|teshikaga.hokkaido|tobetsu.hokkaido|tohma.hokkaido|tomakomai.hokkaido|tomari.hokkaido|toya.hokkaido|toyako.hokkaido|toyotomi.hokkaido|toyoura.hokkaido|tsubetsu.hokkaido|tsukigata.hokkaido|urakawa.hokkaido|urausu.hokkaido|uryu.hokkaido|utashinai.hokkaido|wakkanai.hokkaido|wassamu.hokkaido|yakumo.hokkaido|yoichi.hokkaido|aioi.hyogo|akashi.hyogo|ako.hyogo|amagasaki.hyogo|aogaki.hyogo|asago.hyogo|ashiya.hyogo|awaji.hyogo|fukusaki.hyogo|goshiki.hyogo|harima.hyogo|himeji.hyogo|ichikawa.hyogo|inagawa.hyogo|itami.hyogo|kakogawa.hyogo|kamigori.hyogo|kamikawa.hyogo|kasai.hyogo|kasuga.hyogo|kawanishi.hyogo|miki.hyogo|minamiawaji.hyogo|nishinomiya.hyogo|nishiwaki.hyogo|ono.hyogo|sanda.hyogo|sannan.hyogo|sasayama.hyogo|sayo.hyogo|shingu.hyogo|shinonsen.hyogo|shiso.hyogo|sumoto.hyogo|taishi.hyogo|taka.hyogo|takarazuka.hyogo|takasago.hyogo|takino.hyogo|tamba.hyogo|tatsuno.hyogo|toyooka.hyogo|yabu.hyogo|yashiro.hyogo|yoka.hyogo|yokawa.hyogo|ami.ibaraki|asahi.ibaraki|bando.ibaraki|chikusei.ibaraki|daigo.ibaraki|fujishiro.ibaraki|hitachi.ibaraki|hitachinaka.ibaraki|hitachiomiya.ibaraki|hitachiota.ibaraki|ibaraki.ibaraki|ina.ibaraki|inashiki.ibaraki|itako.ibaraki|iwama.ibaraki|joso.ibaraki|kamisu.ibaraki|kasama.ibaraki|kashima.ibaraki|kasumigaura.ibaraki|koga.ibaraki|miho.ibaraki|mito.ibaraki|moriya.ibaraki|naka.ibaraki|namegata.ibaraki|oarai.ibaraki|ogawa.ibaraki|omitama.ibaraki|ryugasaki.ibaraki|sakai.ibaraki|sakuragawa.ibaraki|shimodate.ibaraki|shimotsuma.ibaraki|shirosato.ibaraki|sowa.ibaraki|suifu.ibaraki|takahagi.ibaraki|tamatsukuri.ibaraki|tokai.ibaraki|tomobe.ibaraki|tone.ibaraki|toride.ibaraki|tsuchiura.ibaraki|tsukuba.ibaraki|uchihara.ibaraki|ushiku.ibaraki|yachiyo.ibaraki|yamagata.ibaraki|yawara.ibaraki|yuki.ibaraki|anamizu.ishikawa|hakui.ishikawa|hakusan.ishikawa|kaga.ishikawa|kahoku.ishikawa|kanazawa.ishikawa|kawakita.ishikawa|komatsu.ishikawa|nakanoto.ishikawa|nanao.ishikawa|nomi.ishikawa|nonoichi.ishikawa|noto.ishikawa|shika.ishikawa|suzu.ishikawa|tsubata.ishikawa|tsurugi.ishikawa|uchinada.ishikawa|wajima.ishikawa|fudai.iwate|fujisawa.iwate|hanamaki.iwate|hiraizumi.iwate|hirono.iwate|ichinohe.iwate|ichinoseki.iwate|iwaizumi.iwate|iwate.iwate|joboji.iwate|kamaishi.iwate|kanegasaki.iwate|karumai.iwate|kawai.iwate|kitakami.iwate|kuji.iwate|kunohe.iwate|kuzumaki.iwate|miyako.iwate|mizusawa.iwate|morioka.iwate|ninohe.iwate|noda.iwate|ofunato.iwate|oshu.iwate|otsuchi.iwate|rikuzentakata.iwate|shiwa.iwate|shizukuishi.iwate|sumita.iwate|tanohata.iwate|tono.iwate|yahaba.iwate|yamada.iwate|ayagawa.kagawa|higashikagawa.kagawa|kanonji.kagawa|kotohira.kagawa|manno.kagawa|marugame.kagawa|mitoyo.kagawa|naoshima.kagawa|sanuki.kagawa|tadotsu.kagawa|takamatsu.kagawa|tonosho.kagawa|uchinomi.kagawa|utazu.kagawa|zentsuji.kagawa|akune.kagoshima|amami.kagoshima|hioki.kagoshima|isa.kagoshima|isen.kagoshima|izumi.kagoshima|kagoshima.kagoshima|kanoya.kagoshima|kawanabe.kagoshima|kinko.kagoshima|kouyama.kagoshima|makurazaki.kagoshima|matsumoto.kagoshima|minamitane.kagoshima|nakatane.kagoshima|nishinoomote.kagoshima|satsumasendai.kagoshima|soo.kagoshima|tarumizu.kagoshima|yusui.kagoshima|aikawa.kanagawa|atsugi.kanagawa|ayase.kanagawa|chigasaki.kanagawa|ebina.kanagawa|fujisawa.kanagawa|hadano.kanagawa|hakone.kanagawa|hiratsuka.kanagawa|isehara.kanagawa|kaisei.kanagawa|kamakura.kanagawa|kiyokawa.kanagawa|matsuda.kanagawa|minamiashigara.kanagawa|miura.kanagawa|nakai.kanagawa|ninomiya.kanagawa|odawara.kanagawa|oi.kanagawa|oiso.kanagawa|sagamihara.kanagawa|samukawa.kanagawa|tsukui.kanagawa|yamakita.kanagawa|yamato.kanagawa|yokosuka.kanagawa|yugawara.kanagawa|zama.kanagawa|zushi.kanagawa|aki.kochi|geisei.kochi|hidaka.kochi|higashitsuno.kochi|ino.kochi|kagami.kochi|kami.kochi|kitagawa.kochi|kochi.kochi|mihara.kochi|motoyama.kochi|muroto.kochi|nahari.kochi|nakamura.kochi|nankoku.kochi|nishitosa.kochi|niyodogawa.kochi|ochi.kochi|okawa.kochi|otoyo.kochi|otsuki.kochi|sakawa.kochi|sukumo.kochi|susaki.kochi|tosa.kochi|tosashimizu.kochi|toyo.kochi|tsuno.kochi|umaji.kochi|yasuda.kochi|yusuhara.kochi|amakusa.kumamoto|arao.kumamoto|aso.kumamoto|choyo.kumamoto|gyokuto.kumamoto|kamiamakusa.kumamoto|kikuchi.kumamoto|kumamoto.kumamoto|mashiki.kumamoto|mifune.kumamoto|minamata.kumamoto|minamioguni.kumamoto|nagasu.kumamoto|nishihara.kumamoto|oguni.kumamoto|ozu.kumamoto|sumoto.kumamoto|takamori.kumamoto|uki.kumamoto|uto.kumamoto|yamaga.kumamoto|yamato.kumamoto|yatsushiro.kumamoto|ayabe.kyoto|fukuchiyama.kyoto|higashiyama.kyoto|ide.kyoto|ine.kyoto|joyo.kyoto|kameoka.kyoto|kamo.kyoto|kita.kyoto|kizu.kyoto|kumiyama.kyoto|kyotamba.kyoto|kyotanabe.kyoto|kyotango.kyoto|maizuru.kyoto|minami.kyoto|minamiyamashiro.kyoto|miyazu.kyoto|muko.kyoto|nagaokakyo.kyoto|nakagyo.kyoto|nantan.kyoto|oyamazaki.kyoto|sakyo.kyoto|seika.kyoto|tanabe.kyoto|uji.kyoto|ujitawara.kyoto|wazuka.kyoto|yamashina.kyoto|yawata.kyoto|asahi.mie|inabe.mie|ise.mie|kameyama.mie|kawagoe.mie|kiho.mie|kisosaki.mie|kiwa.mie|komono.mie|kumano.mie|kuwana.mie|matsusaka.mie|meiwa.mie|mihama.mie|minamiise.mie|misugi.mie|miyama.mie|nabari.mie|shima.mie|suzuka.mie|tado.mie|taiki.mie|taki.mie|tamaki.mie|toba.mie|tsu.mie|udono.mie|ureshino.mie|watarai.mie|yokkaichi.mie|furukawa.miyagi|higashimatsushima.miyagi|ishinomaki.miyagi|iwanuma.miyagi|kakuda.miyagi|kami.miyagi|kawasaki.miyagi|marumori.miyagi|matsushima.miyagi|minamisanriku.miyagi|misato.miyagi|murata.miyagi|natori.miyagi|ogawara.miyagi|ohira.miyagi|onagawa.miyagi|osaki.miyagi|rifu.miyagi|semine.miyagi|shibata.miyagi|shichikashuku.miyagi|shikama.miyagi|shiogama.miyagi|shiroishi.miyagi|tagajo.miyagi|taiwa.miyagi|tome.miyagi|tomiya.miyagi|wakuya.miyagi|watari.miyagi|yamamoto.miyagi|zao.miyagi|aya.miyazaki|ebino.miyazaki|gokase.miyazaki|hyuga.miyazaki|kadogawa.miyazaki|kawaminami.miyazaki|kijo.miyazaki|kitagawa.miyazaki|kitakata.miyazaki|kitaura.miyazaki|kobayashi.miyazaki|kunitomi.miyazaki|kushima.miyazaki|mimata.miyazaki|miyakonojo.miyazaki|miyazaki.miyazaki|morotsuka.miyazaki|nichinan.miyazaki|nishimera.miyazaki|nobeoka.miyazaki|saito.miyazaki|shiiba.miyazaki|shintomi.miyazaki|takaharu.miyazaki|takanabe.miyazaki|takazaki.miyazaki|tsuno.miyazaki|achi.nagano|agematsu.nagano|anan.nagano|aoki.nagano|asahi.nagano|azumino.nagano|chikuhoku.nagano|chikuma.nagano|chino.nagano|fujimi.nagano|hakuba.nagano|hara.nagano|hiraya.nagano|iida.nagano|iijima.nagano|iiyama.nagano|iizuna.nagano|ikeda.nagano|ikusaka.nagano|ina.nagano|karuizawa.nagano|kawakami.nagano|kiso.nagano|kisofukushima.nagano|kitaaiki.nagano|komagane.nagano|komoro.nagano|matsukawa.nagano|matsumoto.nagano|miasa.nagano|minamiaiki.nagano|minamimaki.nagano|minamiminowa.nagano|minowa.nagano|miyada.nagano|miyota.nagano|mochizuki.nagano|nagano.nagano|nagawa.nagano|nagiso.nagano|nakagawa.nagano|nakano.nagano|nozawaonsen.nagano|obuse.nagano|ogawa.nagano|okaya.nagano|omachi.nagano|omi.nagano|ookuwa.nagano|ooshika.nagano|otaki.nagano|otari.nagano|sakae.nagano|sakaki.nagano|saku.nagano|sakuho.nagano|shimosuwa.nagano|shinanomachi.nagano|shiojiri.nagano|suwa.nagano|suzaka.nagano|takagi.nagano|takamori.nagano|takayama.nagano|tateshina.nagano|tatsuno.nagano|togakushi.nagano|togura.nagano|tomi.nagano|ueda.nagano|wada.nagano|yamagata.nagano|yamanouchi.nagano|yasaka.nagano|yasuoka.nagano|chijiwa.nagasaki|futsu.nagasaki|goto.nagasaki|hasami.nagasaki|hirado.nagasaki|iki.nagasaki|isahaya.nagasaki|kawatana.nagasaki|kuchinotsu.nagasaki|matsuura.nagasaki|nagasaki.nagasaki|obama.nagasaki|omura.nagasaki|oseto.nagasaki|saikai.nagasaki|sasebo.nagasaki|seihi.nagasaki|shimabara.nagasaki|shinkamigoto.nagasaki|togitsu.nagasaki|tsushima.nagasaki|unzen.nagasaki|ando.nara|gose.nara|heguri.nara|higashiyoshino.nara|ikaruga.nara|ikoma.nara|kamikitayama.nara|kanmaki.nara|kashiba.nara|kashihara.nara|katsuragi.nara|kawai.nara|kawakami.nara|kawanishi.nara|koryo.nara|kurotaki.nara|mitsue.nara|miyake.nara|nara.nara|nosegawa.nara|oji.nara|ouda.nara|oyodo.nara|sakurai.nara|sango.nara|shimoichi.nara|shimokitayama.nara|shinjo.nara|soni.nara|takatori.nara|tawaramoto.nara|tenkawa.nara|tenri.nara|uda.nara|yamatokoriyama.nara|yamatotakada.nara|yamazoe.nara|yoshino.nara|aga.niigata|agano.niigata|gosen.niigata|itoigawa.niigata|izumozaki.niigata|joetsu.niigata|kamo.niigata|kariwa.niigata|kashiwazaki.niigata|minamiuonuma.niigata|mitsuke.niigata|muika.niigata|murakami.niigata|myoko.niigata|nagaoka.niigata|niigata.niigata|ojiya.niigata|omi.niigata|sado.niigata|sanjo.niigata|seiro.niigata|seirou.niigata|sekikawa.niigata|shibata.niigata|tagami.niigata|tainai.niigata|tochio.niigata|tokamachi.niigata|tsubame.niigata|tsunan.niigata|uonuma.niigata|yahiko.niigata|yoita.niigata|yuzawa.niigata|beppu.oita|bungoono.oita|bungotakada.oita|hasama.oita|hiji.oita|himeshima.oita|hita.oita|kamitsue.oita|kokonoe.oita|kuju.oita|kunisaki.oita|kusu.oita|oita.oita|saiki.oita|taketa.oita|tsukumi.oita|usa.oita|usuki.oita|yufu.oita|akaiwa.okayama|asakuchi.okayama|bizen.okayama|hayashima.okayama|ibara.okayama|kagamino.okayama|kasaoka.okayama|kibichuo.okayama|kumenan.okayama|kurashiki.okayama|maniwa.okayama|misaki.okayama|nagi.okayama|niimi.okayama|nishiawakura.okayama|okayama.okayama|satosho.okayama|setouchi.okayama|shinjo.okayama|shoo.okayama|soja.okayama|takahashi.okayama|tamano.okayama|tsuyama.okayama|wake.okayama|yakage.okayama|aguni.okinawa|ginowan.okinawa|ginoza.okinawa|gushikami.okinawa|haebaru.okinawa|higashi.okinawa|hirara.okinawa|iheya.okinawa|ishigaki.okinawa|ishikawa.okinawa|itoman.okinawa|izena.okinawa|kadena.okinawa|kin.okinawa|kitadaito.okinawa|kitanakagusuku.okinawa|kumejima.okinawa|kunigami.okinawa|minamidaito.okinawa|motobu.okinawa|nago.okinawa|naha.okinawa|nakagusuku.okinawa|nakijin.okinawa|nanjo.okinawa|nishihara.okinawa|ogimi.okinawa|okinawa.okinawa|onna.okinawa|shimoji.okinawa|taketomi.okinawa|tarama.okinawa|tokashiki.okinawa|tomigusuku.okinawa|tonaki.okinawa|urasoe.okinawa|uruma.okinawa|yaese.okinawa|yomitan.okinawa|yonabaru.okinawa|yonaguni.okinawa|zamami.okinawa|abeno.osaka|chihayaakasaka.osaka|chuo.osaka|daito.osaka|fujiidera.osaka|habikino.osaka|hannan.osaka|higashiosaka.osaka|higashisumiyoshi.osaka|higashiyodogawa.osaka|hirakata.osaka|ibaraki.osaka|ikeda.osaka|izumi.osaka|izumiotsu.osaka|izumisano.osaka|kadoma.osaka|kaizuka.osaka|kanan.osaka|kashiwara.osaka|katano.osaka|kawachinagano.osaka|kishiwada.osaka|kita.osaka|kumatori.osaka|matsubara.osaka|minato.osaka|minoh.osaka|misaki.osaka|moriguchi.osaka|neyagawa.osaka|nishi.osaka|nose.osaka|osakasayama.osaka|sakai.osaka|sayama.osaka|sennan.osaka|settsu.osaka|shijonawate.osaka|shimamoto.osaka|suita.osaka|tadaoka.osaka|taishi.osaka|tajiri.osaka|takaishi.osaka|takatsuki.osaka|tondabayashi.osaka|toyonaka.osaka|toyono.osaka|yao.osaka|ariake.saga|arita.saga|fukudomi.saga|genkai.saga|hamatama.saga|hizen.saga|imari.saga|kamimine.saga|kanzaki.saga|karatsu.saga|kashima.saga|kitagata.saga|kitahata.saga|kiyama.saga|kouhoku.saga|kyuragi.saga|nishiarita.saga|ogi.saga|omachi.saga|ouchi.saga|saga.saga|shiroishi.saga|taku.saga|tara.saga|tosu.saga|yoshinogari.saga|arakawa.saitama|asaka.saitama|chichibu.saitama|fujimi.saitama|fujimino.saitama|fukaya.saitama|hanno.saitama|hanyu.saitama|hasuda.saitama|hatogaya.saitama|hatoyama.saitama|hidaka.saitama|higashichichibu.saitama|higashimatsuyama.saitama|honjo.saitama|ina.saitama|iruma.saitama|iwatsuki.saitama|kamiizumi.saitama|kamikawa.saitama|kamisato.saitama|kasukabe.saitama|kawagoe.saitama|kawaguchi.saitama|kawajima.saitama|kazo.saitama|kitamoto.saitama|koshigaya.saitama|kounosu.saitama|kuki.saitama|kumagaya.saitama|matsubushi.saitama|minano.saitama|misato.saitama|miyashiro.saitama|miyoshi.saitama|moroyama.saitama|nagatoro.saitama|namegawa.saitama|niiza.saitama|ogano.saitama|ogawa.saitama|ogose.saitama|okegawa.saitama|omiya.saitama|otaki.saitama|ranzan.saitama|ryokami.saitama|saitama.saitama|sakado.saitama|satte.saitama|sayama.saitama|shiki.saitama|shiraoka.saitama|soka.saitama|sugito.saitama|toda.saitama|tokigawa.saitama|tokorozawa.saitama|tsurugashima.saitama|urawa.saitama|warabi.saitama|yashio.saitama|yokoze.saitama|yono.saitama|yorii.saitama|yoshida.saitama|yoshikawa.saitama|yoshimi.saitama|aisho.shiga|gamo.shiga|higashiomi.shiga|hikone.shiga|koka.shiga|konan.shiga|kosei.shiga|koto.shiga|kusatsu.shiga|maibara.shiga|moriyama.shiga|nagahama.shiga|nishiazai.shiga|notogawa.shiga|omihachiman.shiga|otsu.shiga|ritto.shiga|ryuoh.shiga|takashima.shiga|takatsuki.shiga|torahime.shiga|toyosato.shiga|yasu.shiga|akagi.shimane|ama.shimane|gotsu.shimane|hamada.shimane|higashiizumo.shimane|hikawa.shimane|hikimi.shimane|izumo.shimane|kakinoki.shimane|masuda.shimane|matsue.shimane|misato.shimane|nishinoshima.shimane|ohda.shimane|okinoshima.shimane|okuizumo.shimane|shimane.shimane|tamayu.shimane|tsuwano.shimane|unnan.shimane|yakumo.shimane|yasugi.shimane|yatsuka.shimane|arai.shizuoka|atami.shizuoka|fuji.shizuoka|fujieda.shizuoka|fujikawa.shizuoka|fujinomiya.shizuoka|fukuroi.shizuoka|gotemba.shizuoka|haibara.shizuoka|hamamatsu.shizuoka|higashiizu.shizuoka|ito.shizuoka|iwata.shizuoka|izu.shizuoka|izunokuni.shizuoka|kakegawa.shizuoka|kannami.shizuoka|kawanehon.shizuoka|kawazu.shizuoka|kikugawa.shizuoka|kosai.shizuoka|makinohara.shizuoka|matsuzaki.shizuoka|minamiizu.shizuoka|mishima.shizuoka|morimachi.shizuoka|nishiizu.shizuoka|numazu.shizuoka|omaezaki.shizuoka|shimada.shizuoka|shimizu.shizuoka|shimoda.shizuoka|shizuoka.shizuoka|susono.shizuoka|yaizu.shizuoka|yoshida.shizuoka|ashikaga.tochigi|bato.tochigi|haga.tochigi|ichikai.tochigi|iwafune.tochigi|kaminokawa.tochigi|kanuma.tochigi|karasuyama.tochigi|kuroiso.tochigi|mashiko.tochigi|mibu.tochigi|moka.tochigi|motegi.tochigi|nasu.tochigi|nasushiobara.tochigi|nikko.tochigi|nishikata.tochigi|nogi.tochigi|ohira.tochigi|ohtawara.tochigi|oyama.tochigi|sakura.tochigi|sano.tochigi|shimotsuke.tochigi|shioya.tochigi|takanezawa.tochigi|tochigi.tochigi|tsuga.tochigi|ujiie.tochigi|utsunomiya.tochigi|yaita.tochigi|aizumi.tokushima|anan.tokushima|ichiba.tokushima|itano.tokushima|kainan.tokushima|komatsushima.tokushima|matsushige.tokushima|mima.tokushima|minami.tokushima|miyoshi.tokushima|mugi.tokushima|nakagawa.tokushima|naruto.tokushima|sanagochi.tokushima|shishikui.tokushima|tokushima.tokushima|wajiki.tokushima|adachi.tokyo|akiruno.tokyo|akishima.tokyo|aogashima.tokyo|arakawa.tokyo|bunkyo.tokyo|chiyoda.tokyo|chofu.tokyo|chuo.tokyo|edogawa.tokyo|fuchu.tokyo|fussa.tokyo|hachijo.tokyo|hachioji.tokyo|hamura.tokyo|higashikurume.tokyo|higashimurayama.tokyo|higashiyamato.tokyo|hino.tokyo|hinode.tokyo|hinohara.tokyo|inagi.tokyo|itabashi.tokyo|katsushika.tokyo|kita.tokyo|kiyose.tokyo|kodaira.tokyo|koganei.tokyo|kokubunji.tokyo|komae.tokyo|koto.tokyo|kouzushima.tokyo|kunitachi.tokyo|machida.tokyo|meguro.tokyo|minato.tokyo|mitaka.tokyo|mizuho.tokyo|musashimurayama.tokyo|musashino.tokyo|nakano.tokyo|nerima.tokyo|ogasawara.tokyo|okutama.tokyo|ome.tokyo|oshima.tokyo|ota.tokyo|setagaya.tokyo|shibuya.tokyo|shinagawa.tokyo|shinjuku.tokyo|suginami.tokyo|sumida.tokyo|tachikawa.tokyo|taito.tokyo|tama.tokyo|toshima.tokyo|chizu.tottori|hino.tottori|kawahara.tottori|koge.tottori|kotoura.tottori|misasa.tottori|nanbu.tottori|nichinan.tottori|sakaiminato.tottori|tottori.tottori|wakasa.tottori|yazu.tottori|yonago.tottori|asahi.toyama|fuchu.toyama|fukumitsu.toyama|funahashi.toyama|himi.toyama|imizu.toyama|inami.toyama|johana.toyama|kamiichi.toyama|kurobe.toyama|nakaniikawa.toyama|namerikawa.toyama|nanto.toyama|nyuzen.toyama|oyabe.toyama|taira.toyama|takaoka.toyama|tateyama.toyama|toga.toyama|tonami.toyama|toyama.toyama|unazuki.toyama|uozu.toyama|yamada.toyama|arida.wakayama|aridagawa.wakayama|gobo.wakayama|hashimoto.wakayama|hidaka.wakayama|hirogawa.wakayama|inami.wakayama|iwade.wakayama|kainan.wakayama|kamitonda.wakayama|katsuragi.wakayama|kimino.wakayama|kinokawa.wakayama|kitayama.wakayama|koya.wakayama|koza.wakayama|kozagawa.wakayama|kudoyama.wakayama|kushimoto.wakayama|mihama.wakayama|misato.wakayama|nachikatsuura.wakayama|shingu.wakayama|shirahama.wakayama|taiji.wakayama|tanabe.wakayama|wakayama.wakayama|yuasa.wakayama|yura.wakayama|asahi.yamagata|funagata.yamagata|higashine.yamagata|iide.yamagata|kahoku.yamagata|kaminoyama.yamagata|kaneyama.yamagata|kawanishi.yamagata|mamurogawa.yamagata|mikawa.yamagata|murayama.yamagata|nagai.yamagata|nakayama.yamagata|nanyo.yamagata|nishikawa.yamagata|obanazawa.yamagata|oe.yamagata|oguni.yamagata|ohkura.yamagata|oishida.yamagata|sagae.yamagata|sakata.yamagata|sakegawa.yamagata|shinjo.yamagata|shirataka.yamagata|shonai.yamagata|takahata.yamagata|tendo.yamagata|tozawa.yamagata|tsuruoka.yamagata|yamagata.yamagata|yamanobe.yamagata|yonezawa.yamagata|yuza.yamagata|abu.yamaguchi|hagi.yamaguchi|hikari.yamaguchi|hofu.yamaguchi|iwakuni.yamaguchi|kudamatsu.yamaguchi|mitou.yamaguchi|nagato.yamaguchi|oshima.yamaguchi|shimonoseki.yamaguchi|shunan.yamaguchi|tabuse.yamaguchi|tokuyama.yamaguchi|toyota.yamaguchi|ube.yamaguchi|yuu.yamaguchi|chuo.yamanashi|doshi.yamanashi|fuefuki.yamanashi|fujikawa.yamanashi|fujikawaguchiko.yamanashi|fujiyoshida.yamanashi|hayakawa.yamanashi|hokuto.yamanashi|ichikawamisato.yamanashi|kai.yamanashi|kofu.yamanashi|koshu.yamanashi|kosuge.yamanashi|minami-alps.yamanashi|minobu.yamanashi|nakamichi.yamanashi|nanbu.yamanashi|narusawa.yamanashi|nirasaki.yamanashi|nishikatsura.yamanashi|oshino.yamanashi|otsuki.yamanashi|showa.yamanashi|tabayama.yamanashi|tsuru.yamanashi|uenohara.yamanashi|yamanakako.yamanashi|yamanashi.yamanashi|blogspot","ke":"*|blogspot.co","kg":"org|net|com|edu|gov|mil","kh":"*","ki":"edu|biz|net|org|gov|info|com","km":"org|nom|gov|prd|tm|edu|mil|ass|com|coop|asso|presse|medecin|notaires|pharmaciens|veterinaire|gouv","kn":"net|org|edu|gov","kp":"com|edu|gov|org|rep|tra","kr":"ac|co|es|go|hs|kg|mil|ms|ne|or|pe|re|sc|busan|chungbuk|chungnam|daegu|daejeon|gangwon|gwangju|gyeongbuk|gyeonggi|gyeongnam|incheon|jeju|jeonbuk|jeonnam|seoul|ulsan|blogspot","kw":"*","ky":"edu|gov|com|org|net","kz":"org|edu|net|gov|mil|com|nym","la":"int|net|info|edu|gov|per|com|org|bnr|c|nym","lb":"com|edu|gov|net|org","lc":"com|net|co|org|edu|gov|oy","li":"blogspot|nom|nym","lk":"gov|sch|net|int|com|org|edu|ngo|soc|web|ltd|assn|grp|hotel|ac","lr":"com|edu|gov|org|net","ls":"co|org","lt":"gov|blogspot|nym","lu":"blogspot|nym","lv":"com|edu|gov|org|mil|id|net|asn|conf","ly":"com|net|gov|plc|edu|sch|med|org|id","ma":"co|net|gov|org|ac|press","mc":"tm|asso","md":"blogspot","me":"co|net|org|edu|ac|gov|its|priv|c66|daplie|localhost.daplie|filegear|brasilia|ddns|dnsfor|hopto|loginto|noip|webhop|nym|diskstation|dscloud|i234|myds|synology|wedeploy|yombo","mg":"org|nom|gov|prd|tm|edu|mil|com|co","mh":"","mil":"","mk":"com|org|net|edu|gov|inf|name|blogspot|nom","ml":"com|edu|gouv|gov|net|org|presse","mm":"*","mn":"gov|edu|org|nyc","mo":"com|net|org|edu|gov","mobi":"dscloud","mp":"","mq":"","mr":"gov|blogspot","ms":"com|edu|gov|net|org","mt":"com|edu|net|org|blogspot.com","mu":"com|net|org|gov|ac|co|or","museum":"academy|agriculture|air|airguard|alabama|alaska|amber|ambulance|american|americana|americanantiques|americanart|amsterdam|and|annefrank|anthro|anthropology|antiques|aquarium|arboretum|archaeological|archaeology|architecture|art|artanddesign|artcenter|artdeco|arteducation|artgallery|arts|artsandcrafts|asmatart|assassination|assisi|association|astronomy|atlanta|austin|australia|automotive|aviation|axis|badajoz|baghdad|bahn|bale|baltimore|barcelona|baseball|basel|baths|bauern|beauxarts|beeldengeluid|bellevue|bergbau|berkeley|berlin|bern|bible|bilbao|bill|birdart|birthplace|bonn|boston|botanical|botanicalgarden|botanicgarden|botany|brandywinevalley|brasil|bristol|british|britishcolumbia|broadcast|brunel|brussel|brussels|bruxelles|building|burghof|bus|bushey|cadaques|california|cambridge|can|canada|capebreton|carrier|cartoonart|casadelamoneda|castle|castres|celtic|center|chattanooga|cheltenham|chesapeakebay|chicago|children|childrens|childrensgarden|chiropractic|chocolate|christiansburg|cincinnati|cinema|circus|civilisation|civilization|civilwar|clinton|clock|coal|coastaldefence|cody|coldwar|collection|colonialwilliamsburg|coloradoplateau|columbia|columbus|communication|communications|community|computer|computerhistory|xn--comunicaes-v6a2o|contemporary|contemporaryart|convent|copenhagen|corporation|xn--correios-e-telecomunicaes-ghc29a|corvette|costume|countryestate|county|crafts|cranbrook|creation|cultural|culturalcenter|culture|cyber|cymru|dali|dallas|database|ddr|decorativearts|delaware|delmenhorst|denmark|depot|design|detroit|dinosaur|discovery|dolls|donostia|durham|eastafrica|eastcoast|education|educational|egyptian|eisenbahn|elburg|elvendrell|embroidery|encyclopedic|england|entomology|environment|environmentalconservation|epilepsy|essex|estate|ethnology|exeter|exhibition|family|farm|farmequipment|farmers|farmstead|field|figueres|filatelia|film|fineart|finearts|finland|flanders|florida|force|fortmissoula|fortworth|foundation|francaise|frankfurt|franziskaner|freemasonry|freiburg|fribourg|frog|fundacio|furniture|gallery|garden|gateway|geelvinck|gemological|geology|georgia|giessen|glas|glass|gorge|grandrapids|graz|guernsey|halloffame|hamburg|handson|harvestcelebration|hawaii|health|heimatunduhren|hellas|helsinki|hembygdsforbund|heritage|histoire|historical|historicalsociety|historichouses|historisch|historisches|history|historyofscience|horology|house|humanities|illustration|imageandsound|indian|indiana|indianapolis|indianmarket|intelligence|interactive|iraq|iron|isleofman|jamison|jefferson|jerusalem|jewelry|jewish|jewishart|jfk|journalism|judaica|judygarland|juedisches|juif|karate|karikatur|kids|koebenhavn|koeln|kunst|kunstsammlung|kunstunddesign|labor|labour|lajolla|lancashire|landes|lans|xn--lns-qla|larsson|lewismiller|lincoln|linz|living|livinghistory|localhistory|london|losangeles|louvre|loyalist|lucerne|luxembourg|luzern|mad|madrid|mallorca|manchester|mansion|mansions|manx|marburg|maritime|maritimo|maryland|marylhurst|media|medical|medizinhistorisches|meeres|memorial|mesaverde|michigan|midatlantic|military|mill|miners|mining|minnesota|missile|missoula|modern|moma|money|monmouth|monticello|montreal|moscow|motorcycle|muenchen|muenster|mulhouse|muncie|museet|museumcenter|museumvereniging|music|national|nationalfirearms|nationalheritage|nativeamerican|naturalhistory|naturalhistorymuseum|naturalsciences|nature|naturhistorisches|natuurwetenschappen|naumburg|naval|nebraska|neues|newhampshire|newjersey|newmexico|newport|newspaper|newyork|niepce|norfolk|north|nrw|nuernberg|nuremberg|nyc|nyny|oceanographic|oceanographique|omaha|online|ontario|openair|oregon|oregontrail|otago|oxford|pacific|paderborn|palace|paleo|palmsprings|panama|paris|pasadena|pharmacy|philadelphia|philadelphiaarea|philately|phoenix|photography|pilots|pittsburgh|planetarium|plantation|plants|plaza|portal|portland|portlligat|posts-and-telecommunications|preservation|presidio|press|project|public|pubol|quebec|railroad|railway|research|resistance|riodejaneiro|rochester|rockart|roma|russia|saintlouis|salem|salvadordali|salzburg|sandiego|sanfrancisco|santabarbara|santacruz|santafe|saskatchewan|satx|savannahga|schlesisches|schoenbrunn|schokoladen|school|schweiz|science|scienceandhistory|scienceandindustry|sciencecenter|sciencecenters|science-fiction|sciencehistory|sciences|sciencesnaturelles|scotland|seaport|settlement|settlers|shell|sherbrooke|sibenik|silk|ski|skole|society|sologne|soundandvision|southcarolina|southwest|space|spy|square|stadt|stalbans|starnberg|state|stateofdelaware|station|steam|steiermark|stjohn|stockholm|stpetersburg|stuttgart|suisse|surgeonshall|surrey|svizzera|sweden|sydney|tank|tcm|technology|telekommunikation|television|texas|textile|theater|time|timekeeping|topology|torino|touch|town|transport|tree|trolley|trust|trustee|uhren|ulm|undersea|university|usa|usantiques|usarts|uscountryestate|usculture|usdecorativearts|usgarden|ushistory|ushuaia|uslivinghistory|utah|uvic|valley|vantaa|versailles|viking|village|virginia|virtual|virtuel|vlaanderen|volkenkunde|wales|wallonie|war|washingtondc|watchandclock|watch-and-clock|western|westfalen|whaling|wildlife|williamsburg|windmill|workshop|york|yorkshire|yosemite|youth|zoological|zoology|xn--9dbhblg6di|xn--h1aegh","mv":"aero|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro","mw":"ac|biz|co|com|coop|edu|gov|int|museum|net|org","mx":"com|org|gob|edu|net|blogspot|nym","my":"com|net|org|gov|edu|mil|name|blogspot","mz":"ac|adv|co|edu|gov|mil|net|org","na":"info|pro|name|school|or|dr|us|mx|ca|in|cc|tv|ws|mobi|co|com|org","name":"forgot.her|forgot.his","nc":"asso|nom","ne":"","net":"*alwaysdata|cloudfront|t3l3p0rt|myfritz|boomla|bplaced|square7|gb|hu|jp|se|uk|in|cloudaccess|cdn77-ssl|r.cdn77|feste-ip|knx-server|static-access|*cryptonomic|at-band-camp|blogdns|broke-it|buyshouses|dnsalias|dnsdojo|does-it|dontexist|dynalias|dynathome|endofinternet|from-az|from-co|from-la|from-ny|gets-it|ham-radio-op|homeftp|homeip|homelinux|homeunix|in-the-band|is-a-chef|is-a-geek|isa-geek|kicks-ass|office-on-the|podzone|scrapper-site|selfip|sells-it|servebbs|serveftp|thruhere|webhop|definima|casacam|dynu|dynv6|twmail|ru|fastlylb|map.fastlylb|freetls.fastly|map.fastly|a.prod.fastly|global.prod.fastly|a.ssl.fastly|b.ssl.fastly|global.ssl.fastly|flynnhosting|cloudfunctions|moonscale|ipifony|barsy|azurewebsites|azure-mobile|cloudapp|eating-organic|mydissent|myeffect|mymediapc|mypsx|mysecuritycamera|nhlfan|no-ip|pgafan|privatizehealthinsurance|bounceme|ddns|redirectme|serveblog|serveminecraft|sytes|rackmaze|firewall-gateway|dsmynas|familyds|za","nf":"com|net|per|rec|web|arts|firm|info|other|store","ng":"com|edu|gov|i|mil|mobi|name|net|org|sch|blogspot.com","ni":"ac|biz|co|com|edu|gob|in|info|int|mil|net|nom|org|web","nl":"bv|virtueeldomein|co|blogspot|*transurl|cistron|demon","no":"fhs|vgs|fylkesbibl|folkebibl|museum|idrett|priv|mil|stat|dep|kommune|herad|aa|ah|bu|fm|hl|hm|jan-mayen|mr|nl|nt|of|ol|oslo|rl|sf|st|svalbard|tm|tr|va|vf|gs.aa|gs.ah|gs.bu|gs.fm|gs.hl|gs.hm|gs.jan-mayen|gs.mr|gs.nl|gs.nt|gs.of|gs.ol|gs.oslo|gs.rl|gs.sf|gs.st|gs.svalbard|gs.tm|gs.tr|gs.va|gs.vf|akrehamn|xn--krehamn-dxa|algard|xn--lgrd-poac|arna|brumunddal|bryne|bronnoysund|xn--brnnysund-m8ac|drobak|xn--drbak-wua|egersund|fetsund|floro|xn--flor-jra|fredrikstad|hokksund|honefoss|xn--hnefoss-q1a|jessheim|jorpeland|xn--jrpeland-54a|kirkenes|kopervik|krokstadelva|langevag|xn--langevg-jxa|leirvik|mjondalen|xn--mjndalen-64a|mo-i-rana|mosjoen|xn--mosjen-eya|nesoddtangen|orkanger|osoyro|xn--osyro-wua|raholt|xn--rholt-mra|sandnessjoen|xn--sandnessjen-ogb|skedsmokorset|slattum|spjelkavik|stathelle|stavern|stjordalshalsen|xn--stjrdalshalsen-sqb|tananger|tranby|vossevangen|afjord|xn--fjord-lra|agdenes|al|xn--l-1fa|alesund|xn--lesund-hua|alstahaug|alta|xn--lt-liac|alaheadju|xn--laheadju-7ya|alvdal|amli|xn--mli-tla|amot|xn--mot-tla|andebu|andoy|xn--andy-ira|andasuolo|ardal|xn--rdal-poa|aremark|arendal|xn--s-1fa|aseral|xn--seral-lra|asker|askim|askvoll|askoy|xn--asky-ira|asnes|xn--snes-poa|audnedaln|aukra|aure|aurland|aurskog-holand|xn--aurskog-hland-jnb|austevoll|austrheim|averoy|xn--avery-yua|balestrand|ballangen|balat|xn--blt-elab|balsfjord|bahccavuotna|xn--bhccavuotna-k7a|bamble|bardu|beardu|beiarn|bajddar|xn--bjddar-pta|baidar|xn--bidr-5nac|berg|bergen|berlevag|xn--berlevg-jxa|bearalvahki|xn--bearalvhki-y4a|bindal|birkenes|bjarkoy|xn--bjarky-fya|bjerkreim|bjugn|bodo|xn--bod-2na|badaddja|xn--bdddj-mrabd|budejju|bokn|bremanger|bronnoy|xn--brnny-wuac|bygland|bykle|barum|xn--brum-voa|bo.telemark|xn--b-5ga.telemark|bo.nordland|xn--b-5ga.nordland|bievat|xn--bievt-0qa|bomlo|xn--bmlo-gra|batsfjord|xn--btsfjord-9za|bahcavuotna|xn--bhcavuotna-s4a|dovre|drammen|drangedal|dyroy|xn--dyry-ira|donna|xn--dnna-gra|eid|eidfjord|eidsberg|eidskog|eidsvoll|eigersund|elverum|enebakk|engerdal|etne|etnedal|evenes|evenassi|xn--eveni-0qa01ga|evje-og-hornnes|farsund|fauske|fuossko|fuoisku|fedje|fet|finnoy|xn--finny-yua|fitjar|fjaler|fjell|flakstad|flatanger|flekkefjord|flesberg|flora|fla|xn--fl-zia|folldal|forsand|fosnes|frei|frogn|froland|frosta|frana|xn--frna-woa|froya|xn--frya-hra|fusa|fyresdal|forde|xn--frde-gra|gamvik|gangaviika|xn--ggaviika-8ya47h|gaular|gausdal|gildeskal|xn--gildeskl-g0a|giske|gjemnes|gjerdrum|gjerstad|gjesdal|gjovik|xn--gjvik-wua|gloppen|gol|gran|grane|granvin|gratangen|grimstad|grong|kraanghke|xn--kranghke-b0a|grue|gulen|hadsel|halden|halsa|hamar|hamaroy|habmer|xn--hbmer-xqa|hapmir|xn--hpmir-xqa|hammerfest|hammarfeasta|xn--hmmrfeasta-s4ac|haram|hareid|harstad|hasvik|aknoluokta|xn--koluokta-7ya57h|hattfjelldal|aarborte|haugesund|hemne|hemnes|hemsedal|heroy.more-og-romsdal|xn--hery-ira.xn--mre-og-romsdal-qqb|heroy.nordland|xn--hery-ira.nordland|hitra|hjartdal|hjelmeland|hobol|xn--hobl-ira|hof|hol|hole|holmestrand|holtalen|xn--holtlen-hxa|hornindal|horten|hurdal|hurum|hvaler|hyllestad|hagebostad|xn--hgebostad-g3a|hoyanger|xn--hyanger-q1a|hoylandet|xn--hylandet-54a|ha|xn--h-2fa|ibestad|inderoy|xn--indery-fya|iveland|jevnaker|jondal|jolster|xn--jlster-bya|karasjok|karasjohka|xn--krjohka-hwab49j|karlsoy|galsa|xn--gls-elac|karmoy|xn--karmy-yua|kautokeino|guovdageaidnu|klepp|klabu|xn--klbu-woa|kongsberg|kongsvinger|kragero|xn--krager-gya|kristiansand|kristiansund|krodsherad|xn--krdsherad-m8a|kvalsund|rahkkeravju|xn--rhkkervju-01af|kvam|kvinesdal|kvinnherad|kviteseid|kvitsoy|xn--kvitsy-fya|kvafjord|xn--kvfjord-nxa|giehtavuoatna|kvanangen|xn--kvnangen-k0a|navuotna|xn--nvuotna-hwa|kafjord|xn--kfjord-iua|gaivuotna|xn--givuotna-8ya|larvik|lavangen|lavagis|loabat|xn--loabt-0qa|lebesby|davvesiida|leikanger|leirfjord|leka|leksvik|lenvik|leangaviika|xn--leagaviika-52b|lesja|levanger|lier|lierne|lillehammer|lillesand|lindesnes|lindas|xn--linds-pra|lom|loppa|lahppi|xn--lhppi-xqa|lund|lunner|luroy|xn--lury-ira|luster|lyngdal|lyngen|ivgu|lardal|lerdal|xn--lrdal-sra|lodingen|xn--ldingen-q1a|lorenskog|xn--lrenskog-54a|loten|xn--lten-gra|malvik|masoy|xn--msy-ula0h|muosat|xn--muost-0qa|mandal|marker|marnardal|masfjorden|meland|meldal|melhus|meloy|xn--mely-ira|meraker|xn--merker-kua|moareke|xn--moreke-jua|midsund|midtre-gauldal|modalen|modum|molde|moskenes|moss|mosvik|malselv|xn--mlselv-iua|malatvuopmi|xn--mlatvuopmi-s4a|namdalseid|aejrie|namsos|namsskogan|naamesjevuemie|xn--nmesjevuemie-tcba|laakesvuemie|nannestad|narvik|narviika|naustdal|nedre-eiker|nes.akershus|nes.buskerud|nesna|nesodden|nesseby|unjarga|xn--unjrga-rta|nesset|nissedal|nittedal|nord-aurdal|nord-fron|nord-odal|norddal|nordkapp|davvenjarga|xn--davvenjrga-y4a|nordre-land|nordreisa|raisa|xn--risa-5na|nore-og-uvdal|notodden|naroy|xn--nry-yla5g|notteroy|xn--nttery-byae|odda|oksnes|xn--ksnes-uua|oppdal|oppegard|xn--oppegrd-ixa|orkdal|orland|xn--rland-uua|orskog|xn--rskog-uua|orsta|xn--rsta-fra|os.hedmark|os.hordaland|osen|osteroy|xn--ostery-fya|ostre-toten|xn--stre-toten-zcb|overhalla|ovre-eiker|xn--vre-eiker-k8a|oyer|xn--yer-zna|oygarden|xn--ygarden-p1a|oystre-slidre|xn--ystre-slidre-ujb|porsanger|porsangu|xn--porsgu-sta26f|porsgrunn|radoy|xn--rady-ira|rakkestad|rana|ruovat|randaberg|rauma|rendalen|rennebu|rennesoy|xn--rennesy-v1a|rindal|ringebu|ringerike|ringsaker|rissa|risor|xn--risr-ira|roan|rollag|rygge|ralingen|xn--rlingen-mxa|rodoy|xn--rdy-0nab|romskog|xn--rmskog-bya|roros|xn--rros-gra|rost|xn--rst-0na|royken|xn--ryken-vua|royrvik|xn--ryrvik-bya|rade|xn--rde-ula|salangen|siellak|saltdal|salat|xn--slt-elab|xn--slat-5na|samnanger|sande.more-og-romsdal|sande.xn--mre-og-romsdal-qqb|sande.vestfold|sandefjord|sandnes|sandoy|xn--sandy-yua|sarpsborg|sauda|sauherad|sel|selbu|selje|seljord|sigdal|siljan|sirdal|skaun|skedsmo|ski|skien|skiptvet|skjervoy|xn--skjervy-v1a|skierva|xn--skierv-uta|skjak|xn--skjk-soa|skodje|skanland|xn--sknland-fxa|skanit|xn--sknit-yqa|smola|xn--smla-hra|snillfjord|snasa|xn--snsa-roa|snoasa|snaase|xn--snase-nra|sogndal|sokndal|sola|solund|songdalen|sortland|spydeberg|stange|stavanger|steigen|steinkjer|stjordal|xn--stjrdal-s1a|stokke|stor-elvdal|stord|stordal|storfjord|omasvuotna|strand|stranda|stryn|sula|suldal|sund|sunndal|surnadal|sveio|svelvik|sykkylven|sogne|xn--sgne-gra|somna|xn--smna-gra|sondre-land|xn--sndre-land-0cb|sor-aurdal|xn--sr-aurdal-l8a|sor-fron|xn--sr-fron-q1a|sor-odal|xn--sr-odal-q1a|sor-varanger|xn--sr-varanger-ggb|matta-varjjat|xn--mtta-vrjjat-k7af|sorfold|xn--srfold-bya|sorreisa|xn--srreisa-q1a|sorum|xn--srum-gra|tana|deatnu|time|tingvoll|tinn|tjeldsund|dielddanuorri|tjome|xn--tjme-hra|tokke|tolga|torsken|tranoy|xn--trany-yua|tromso|xn--troms-zua|tromsa|romsa|trondheim|troandin|trysil|trana|xn--trna-woa|trogstad|xn--trgstad-r1a|tvedestrand|tydal|tynset|tysfjord|divtasvuodna|divttasvuotna|tysnes|tysvar|xn--tysvr-vra|tonsberg|xn--tnsberg-q1a|ullensaker|ullensvang|ulvik|utsira|vadso|xn--vads-jra|cahcesuolo|xn--hcesuolo-7ya35b|vaksdal|valle|vang|vanylven|vardo|xn--vard-jra|varggat|xn--vrggt-xqad|vefsn|vaapste|vega|vegarshei|xn--vegrshei-c0a|vennesla|verdal|verran|vestby|vestnes|vestre-slidre|vestre-toten|vestvagoy|xn--vestvgy-ixa6o|vevelstad|vik|vikna|vindafjord|volda|voss|varoy|xn--vry-yla5g|vagan|xn--vgan-qoa|voagat|vagsoy|xn--vgsy-qoa0j|vaga|xn--vg-yiab|valer.ostfold|xn--vler-qoa.xn--stfold-9xa|valer.hedmark|xn--vler-qoa.hedmark|co|blogspot","np":"*","nr":"biz|info|gov|edu|org|net|com","nu":"merseine|mine|shacknet|nom","nz":"ac|co|cri|geek|gen|govt|health|iwi|kiwi|maori|mil|xn--mori-qsa|net|org|parliament|school|blogspot.co|nym","om":"co|com|edu|gov|med|museum|net|org|pro","onion":"","org":"tele.amune|pimienta|poivron|potager|sweetpepper|ae|us|certmgr|c.cdn77|rsc.cdn77|ssl.origin.cdn77-secure|cloudns|duckdns|tunk|dyndns|blogdns|blogsite|boldlygoingnowhere|dnsalias|dnsdojo|doesntexist|dontexist|doomdns|dvrdns|dynalias|endofinternet|endoftheinternet|from-me|game-host|go.dyndns|gotdns|hobby-site|home.dyndns|homedns|homeftp|homelinux|homeunix|is-a-bruinsfan|is-a-candidate|is-a-celticsfan|is-a-chef|is-a-geek|is-a-knight|is-a-linux-user|is-a-patsfan|is-a-soxfan|is-found|is-lost|is-saved|is-very-bad|is-very-evil|is-very-good|is-very-nice|is-very-sweet|isa-geek|kicks-ass|misconfused|podzone|readmyblog|selfip|sellsyourhome|servebbs|serveftp|servegame|stuff-4-sale|webhop|ddnss|accesscam|camdvr|freeddns|mywire|webredirect|eu|al.eu|asso.eu|at.eu|au.eu|be.eu|bg.eu|ca.eu|cd.eu|ch.eu|cn.eu|cy.eu|cz.eu|de.eu|dk.eu|edu.eu|ee.eu|es.eu|fi.eu|fr.eu|gr.eu|hr.eu|hu.eu|ie.eu|il.eu|in.eu|int.eu|is.eu|it.eu|jp.eu|kr.eu|lt.eu|lu.eu|lv.eu|mc.eu|me.eu|mk.eu|mt.eu|my.eu|net.eu|ng.eu|nl.eu|no.eu|nz.eu|paris.eu|pl.eu|pt.eu|q-a.eu|ro.eu|ru.eu|se.eu|si.eu|sk.eu|tr.eu|uk.eu|us.eu|twmail|fedorainfracloud|fedorapeople|cloud.fedoraproject|hepforge|js|bmoattachments|cable-modem|collegefan|couchpotatofries|mlbfan|mysecuritycamera|nflfan|read-books|ufcfan|hopto|myftp|no-ip|zapto|my-firewall|myfirewall|spdns|dsmynas|familyds|tuxfamily|diskstation|hk|wmflabs|za","pa":"ac|gob|com|org|sld|edu|net|ing|abo|med|nom","pe":"edu|gob|nom|mil|org|com|net|blogspot|nym","pf":"com|org|edu","pg":"*","ph":"com|net|org|gov|edu|ngo|mil|i","pk":"com|net|edu|org|fam|biz|web|gov|gob|gok|gon|gop|gos|info","pl":"com|net|org|aid|agro|atm|auto|biz|edu|gmina|gsm|info|mail|miasta|media|mil|nieruchomosci|nom|pc|powiat|priv|realestate|rel|sex|shop|sklep|sos|szkola|targi|tm|tourism|travel|turystyka|gov|ap.gov|ic.gov|is.gov|us.gov|kmpsp.gov|kppsp.gov|kwpsp.gov|psp.gov|wskr.gov|kwp.gov|mw.gov|ug.gov|um.gov|umig.gov|ugim.gov|upow.gov|uw.gov|starostwo.gov|pa.gov|po.gov|psse.gov|pup.gov|rzgw.gov|sa.gov|so.gov|sr.gov|wsa.gov|sko.gov|uzs.gov|wiih.gov|winb.gov|pinb.gov|wios.gov|witd.gov|wzmiuw.gov|piw.gov|wiw.gov|griw.gov|wif.gov|oum.gov|sdn.gov|zp.gov|uppo.gov|mup.gov|wuoz.gov|konsulat.gov|oirm.gov|augustow|babia-gora|bedzin|beskidy|bialowieza|bialystok|bielawa|bieszczady|boleslawiec|bydgoszcz|bytom|cieszyn|czeladz|czest|dlugoleka|elblag|elk|glogow|gniezno|gorlice|grajewo|ilawa|jaworzno|jelenia-gora|jgora|kalisz|kazimierz-dolny|karpacz|kartuzy|kaszuby|katowice|kepno|ketrzyn|klodzko|kobierzyce|kolobrzeg|konin|konskowola|kutno|lapy|lebork|legnica|lezajsk|limanowa|lomza|lowicz|lubin|lukow|malbork|malopolska|mazowsze|mazury|mielec|mielno|mragowo|naklo|nowaruda|nysa|olawa|olecko|olkusz|olsztyn|opoczno|opole|ostroda|ostroleka|ostrowiec|ostrowwlkp|pila|pisz|podhale|podlasie|polkowice|pomorze|pomorskie|prochowice|pruszkow|przeworsk|pulawy|radom|rawa-maz|rybnik|rzeszow|sanok|sejny|slask|slupsk|sosnowiec|stalowa-wola|skoczow|starachowice|stargard|suwalki|swidnica|swiebodzin|swinoujscie|szczecin|szczytno|tarnobrzeg|tgory|turek|tychy|ustka|walbrzych|warmia|warszawa|waw|wegrow|wielun|wlocl|wloclawek|wodzislaw|wolomin|wroclaw|zachpomor|zagan|zarow|zgora|zgorzelec|beep|co|art|gliwice|krakow|poznan|wroc|zakopane|gda|gdansk|gdynia|med|sopot","pm":"","pn":"gov|co|org|edu|net","post":"","pr":"com|net|org|gov|edu|isla|pro|biz|info|name|est|prof|ac","pro":"aaa|aca|acct|avocat|bar|cpa|eng|jur|law|med|recht|cloudns","ps":"edu|gov|sec|plo|com|org|net","pt":"net|gov|org|edu|int|publ|com|nome|blogspot|nym","pw":"co|ne|or|ed|go|belau|cloudns|nom","py":"com|coop|edu|gov|mil|net|org","qa":"com|edu|gov|mil|name|net|org|sch|blogspot|nom","re":"asso|com|nom|blogspot","ro":"arts|com|firm|info|nom|nt|org|rec|store|tm|www|shop|blogspot","rs":"ac|co|edu|gov|in|org|blogspot|nom","ru":"ac|edu|gov|int|mil|test|adygeya|bashkiria|bir|cbg|com|dagestan|grozny|kalmykia|kustanai|marine|mordovia|msk|mytis|nalchik|nov|pyatigorsk|spb|vladikavkaz|vladimir|blogspot|hb.cldmail|net|org|pp","rw":"gov|net|edu|ac|com|co|int|mil|gouv","sa":"com|net|org|gov|med|pub|edu|sch","sb":"com|edu|gov|net|org","sc":"com|gov|net|org|edu","sd":"com|net|org|edu|med|tv|gov|info","se":"a|ac|b|bd|brand|c|d|e|f|fh|fhsk|fhv|g|h|i|k|komforb|kommunalforbund|komvux|l|lanbib|m|n|naturbruksgymn|o|org|p|parti|pp|press|r|s|t|tm|u|w|x|y|z|com|blogspot","sg":"com|net|org|gov|edu|per|blogspot","sh":"com|net|gov|org|mil|hashbang|*platform|now","si":"blogspot|nom","sj":"","sk":"blogspot|nym","sl":"com|net|edu|gov|org","sm":"","sn":"art|com|edu|gouv|org|perso|univ|blogspot","so":"com|net|org","sr":"","st":"co|com|consulado|edu|embaixada|gov|mil|net|org|principe|saotome|store","su":"abkhazia|adygeya|aktyubinsk|arkhangelsk|armenia|ashgabad|azerbaijan|balashov|bashkiria|bryansk|bukhara|chimkent|dagestan|east-kazakhstan|exnet|georgia|grozny|ivanovo|jambyl|kalmykia|kaluga|karacol|karaganda|karelia|khakassia|krasnodar|kurgan|kustanai|lenug|mangyshlak|mordovia|msk|murmansk|nalchik|navoi|north-kazakhstan|nov|obninsk|penza|pokrovsk|sochi|spb|tashkent|termez|togliatti|troitsk|tselinograd|tula|tuva|vladikavkaz|vladimir|vologda|nym","sv":"com|edu|gob|org|red","sx":"gov|nym","sy":"edu|gov|net|mil|com|org","sz":"co|ac|org","tc":"","td":"blogspot","tel":"","tf":"","tg":"","th":"ac|co|go|in|mi|net|or","tj":"ac|biz|co|com|edu|go|gov|int|mil|name|net|nic|org|test|web","tk":"","tl":"gov","tm":"com|co|org|net|nom|gov|mil|edu","tn":"com|ens|fin|gov|ind|intl|nat|net|org|info|perso|tourism|edunet|rnrt|rns|rnu|mincom|agrinet|defense|turen","to":"com|gov|net|org|edu|mil|vpnplus","tr":"com|info|biz|net|org|web|gen|tv|av|dr|bbs|name|tel|gov|bel|pol|mil|k12|edu|kep|nc|gov.nc|blogspot.com","travel":"","tt":"co|com|org|net|biz|info|pro|int|coop|jobs|mobi|travel|museum|aero|name|gov|edu","tv":"dyndns|better-than|on-the-web|worse-than","tw":"edu|gov|mil|com|net|org|idv|game|ebiz|club|xn--zf0ao64a|xn--uc0atv|xn--czrw28b|mymailer.com|url|blogspot|nym","tz":"ac|co|go|hotel|info|me|mil|mobi|ne|or|sc|tv","ua":"com|edu|gov|in|net|org|cherkassy|cherkasy|chernigov|chernihiv|chernivtsi|chernovtsy|ck|cn|cr|crimea|cv|dn|dnepropetrovsk|dnipropetrovsk|dominic|donetsk|dp|if|ivano-frankivsk|kh|kharkiv|kharkov|kherson|khmelnitskiy|khmelnytskyi|kiev|kirovograd|km|kr|krym|ks|kv|kyiv|lg|lt|lugansk|lutsk|lv|lviv|mk|mykolaiv|nikolaev|od|odesa|odessa|pl|poltava|rivne|rovno|rv|sb|sebastopol|sevastopol|sm|sumy|te|ternopil|uz|uzhgorod|vinnica|vinnytsia|vn|volyn|yalta|zaporizhzhe|zaporizhzhia|zhitomir|zhytomyr|zp|zt|cc|inf|ltd|biz|co|pp","ug":"co|or|ac|sc|go|ne|com|org|blogspot|nom","uk":"ac|co|gov|ltd|me|net|nhs|org|plc|police|*sch|service.gov|homeoffice.gov|blogspot.co|no-ip.co|wellbeingzone.co","us":"dni|fed|isa|kids|nsn|ak|al|ar|as|az|ca|co|ct|dc|de|fl|ga|gu|hi|ia|id|il|in|ks|ky|la|ma|md|me|mi|mn|mo|ms|mt|nc|nd|ne|nh|nj|nm|nv|ny|oh|ok|or|pa|pr|ri|sc|sd|tn|tx|ut|vi|vt|va|wa|wi|wv|wy|k12.ak|k12.al|k12.ar|k12.as|k12.az|k12.ca|k12.co|k12.ct|k12.dc|k12.de|k12.fl|k12.ga|k12.gu|k12.ia|k12.id|k12.il|k12.in|k12.ks|k12.ky|k12.la|k12.ma|k12.md|k12.me|k12.mi|k12.mn|k12.mo|k12.ms|k12.mt|k12.nc|k12.ne|k12.nh|k12.nj|k12.nm|k12.nv|k12.ny|k12.oh|k12.ok|k12.or|k12.pa|k12.pr|k12.ri|k12.sc|k12.tn|k12.tx|k12.ut|k12.vi|k12.vt|k12.va|k12.wa|k12.wi|k12.wy|cc.ak|cc.al|cc.ar|cc.as|cc.az|cc.ca|cc.co|cc.ct|cc.dc|cc.de|cc.fl|cc.ga|cc.gu|cc.hi|cc.ia|cc.id|cc.il|cc.in|cc.ks|cc.ky|cc.la|cc.ma|cc.md|cc.me|cc.mi|cc.mn|cc.mo|cc.ms|cc.mt|cc.nc|cc.nd|cc.ne|cc.nh|cc.nj|cc.nm|cc.nv|cc.ny|cc.oh|cc.ok|cc.or|cc.pa|cc.pr|cc.ri|cc.sc|cc.sd|cc.tn|cc.tx|cc.ut|cc.vi|cc.vt|cc.va|cc.wa|cc.wi|cc.wv|cc.wy|lib.ak|lib.al|lib.ar|lib.as|lib.az|lib.ca|lib.co|lib.ct|lib.dc|lib.fl|lib.ga|lib.gu|lib.hi|lib.ia|lib.id|lib.il|lib.in|lib.ks|lib.ky|lib.la|lib.ma|lib.md|lib.me|lib.mi|lib.mn|lib.mo|lib.ms|lib.mt|lib.nc|lib.nd|lib.ne|lib.nh|lib.nj|lib.nm|lib.nv|lib.ny|lib.oh|lib.ok|lib.or|lib.pa|lib.pr|lib.ri|lib.sc|lib.sd|lib.tn|lib.tx|lib.ut|lib.vi|lib.vt|lib.va|lib.wa|lib.wi|lib.wy|pvt.k12.ma|chtr.k12.ma|paroch.k12.ma|cloudns|drud|is-by|land-4-sale|stuff-4-sale|golffan|noip|pointto|lib.de","uy":"com|edu|gub|mil|net|org|blogspot.com|nom","uz":"co|com|net|org","va":"","vc":"com|net|org|gov|mil|edu|nom","ve":"arts|co|com|e12|edu|firm|gob|gov|info|int|mil|net|org|rec|store|tec|web","vg":"nom","vi":"co|com|k12|net|org","vn":"com|net|org|edu|gov|int|ac|biz|info|name|pro|health|blogspot","vu":"com|edu|net|org","wf":"","ws":"com|net|org|gov|edu|*advisor|dyndns|mypets","yt":"","xn--mgbaam7a8h":"","xn--y9a3aq":"","xn--54b7fta0cc":"","xn--90ae":"","xn--90ais":"","xn--fiqs8s":"","xn--fiqz9s":"","xn--lgbbat1ad8j":"","xn--wgbh1c":"","xn--e1a4c":"","xn--node":"","xn--qxam":"","xn--j6w193g":"","xn--2scrj9c":"","xn--3hcrj9c":"","xn--45br5cyl":"","xn--h2breg3eve":"","xn--h2brj9c8c":"","xn--mgbgu82a":"","xn--rvc1e0am3e":"","xn--h2brj9c":"","xn--mgbbh1a71e":"","xn--fpcrj9c3d":"","xn--gecrj9c":"","xn--s9brj9c":"","xn--45brj9c":"","xn--xkc2dl3a5ee0h":"","xn--mgba3a4f16a":"","xn--mgba3a4fra":"","xn--mgbtx2b":"","xn--mgbayh7gpa":"","xn--3e0b707e":"","xn--80ao21a":"","xn--fzc2c9e2c":"","xn--xkc2al3hye2a":"","xn--mgbc0a9azcg":"","xn--d1alf":"","xn--l1acc":"","xn--mix891f":"","xn--mix082f":"","xn--mgbx4cd0ab":"","xn--mgb9awbf":"","xn--mgbai9azgqp6j":"","xn--mgbai9a5eva00b":"","xn--ygbi2ammx":"","xn--90a3ac":"xn--o1ac|xn--c1avg|xn--90azh|xn--d1at|xn--o1ach|xn--80au","xn--p1ai":"","xn--wgbl6a":"","xn--mgberp4a5d4ar":"","xn--mgberp4a5d4a87g":"","xn--mgbqly7c0a67fbc":"","xn--mgbqly7cvafr":"","xn--mgbpl2fh":"","xn--yfro4i67o":"","xn--clchc0ea0b2g2a9gcd":"","xn--ogbpf8fl":"","xn--mgbtf8fl":"","xn--o3cw4h":"xn--12c1fe0br|xn--12co0c3b4eva|xn--h3cuzk1di|xn--o3cyx2a|xn--m3ch0j3a|xn--12cfi8ixb8l","xn--pgbs0dh":"","xn--kpry57d":"","xn--kprw13d":"","xn--nnx388a":"","xn--j1amh":"","xn--mgb2ddes":"","xxx":"","ye":"*","za":"ac|agric|alt|co|edu|gov|grondar|law|mil|net|ngo|nis|nom|org|school|tm|web|blogspot.co","zm":"ac|biz|co|com|edu|gov|info|mil|net|org|sch","zw":"ac|co|gov|mil|org","aaa":"","aarp":"","abarth":"","abb":"","abbott":"","abbvie":"","abc":"","able":"","abogado":"","abudhabi":"","academy":"","accenture":"","accountant":"","accountants":"","aco":"","active":"","actor":"","adac":"","ads":"","adult":"","aeg":"","aetna":"","afamilycompany":"","afl":"","africa":"","agakhan":"","agency":"","aig":"","aigo":"","airbus":"","airforce":"","airtel":"","akdn":"","alfaromeo":"","alibaba":"","alipay":"","allfinanz":"","allstate":"","ally":"","alsace":"","alstom":"","americanexpress":"","americanfamily":"","amex":"","amfam":"","amica":"","amsterdam":"","analytics":"","android":"","anquan":"","anz":"","aol":"","apartments":"","app":"","apple":"","aquarelle":"","arab":"","aramco":"","archi":"","army":"","art":"","arte":"","asda":"","associates":"","athleta":"","attorney":"","auction":"","audi":"","audible":"","audio":"","auspost":"","author":"","auto":"","autos":"","avianca":"","aws":"","axa":"","azure":"","baby":"","baidu":"","banamex":"","bananarepublic":"","band":"","bank":"","bar":"","barcelona":"","barclaycard":"","barclays":"","barefoot":"","bargains":"","baseball":"","basketball":"","bauhaus":"","bayern":"","bbc":"","bbt":"","bbva":"","bcg":"","bcn":"","beats":"","beauty":"","beer":"","bentley":"","berlin":"","best":"","bestbuy":"","bet":"","bharti":"","bible":"","bid":"","bike":"","bing":"","bingo":"","bio":"","black":"","blackfriday":"","blanco":"","blockbuster":"","blog":"","bloomberg":"","blue":"","bms":"","bmw":"","bnl":"","bnpparibas":"","boats":"","boehringer":"","bofa":"","bom":"","bond":"","boo":"","book":"","booking":"","boots":"","bosch":"","bostik":"","boston":"","bot":"","boutique":"","box":"","bradesco":"","bridgestone":"","broadway":"","broker":"","brother":"","brussels":"","budapest":"","bugatti":"","build":"","builders":"","business":"","buy":"","buzz":"","bzh":"","cab":"","cafe":"","cal":"","call":"","calvinklein":"","cam":"","camera":"","camp":"","cancerresearch":"","canon":"","capetown":"","capital":"","capitalone":"","car":"","caravan":"","cards":"","care":"","career":"","careers":"","cars":"","cartier":"","casa":"","case":"","caseih":"","cash":"","casino":"","catering":"","catholic":"","cba":"","cbn":"","cbre":"","cbs":"","ceb":"","center":"","ceo":"","cern":"","cfa":"","cfd":"","chanel":"","channel":"","chase":"","chat":"","cheap":"","chintai":"","chloe":"","christmas":"","chrome":"","chrysler":"","church":"","cipriani":"","circle":"","cisco":"","citadel":"","citi":"","citic":"","city":"","cityeats":"","claims":"","cleaning":"","click":"","clinic":"","clinique":"","clothing":"","cloud":"myfusion|*statics|*magentosite|vapor|*sensiosite|trafficplex","club":"cloudns","clubmed":"","coach":"","codes":"","coffee":"","college":"","cologne":"","comcast":"","commbank":"","community":"","company":"","compare":"","computer":"","comsec":"","condos":"","construction":"","consulting":"","contact":"","contractors":"","cooking":"","cookingchannel":"","cool":"de","corsica":"","country":"","coupon":"","coupons":"","courses":"","credit":"","creditcard":"","creditunion":"","cricket":"","crown":"","crs":"","cruise":"","cruises":"","csc":"","cuisinella":"","cymru":"","cyou":"","dabur":"","dad":"","dance":"","data":"","date":"","dating":"","datsun":"","day":"","dclk":"","dds":"","deal":"","dealer":"","deals":"","degree":"","delivery":"","dell":"","deloitte":"","delta":"","democrat":"","dental":"","dentist":"","desi":"","design":"","dev":"","dhl":"","diamonds":"","diet":"","digital":"","direct":"","directory":"","discount":"","discover":"","dish":"","diy":"","dnp":"","docs":"","doctor":"","dodge":"","dog":"","doha":"","domains":"","dot":"","download":"","drive":"","dtv":"","dubai":"","duck":"","dunlop":"","duns":"","dupont":"","durban":"","dvag":"","dvr":"","earth":"","eat":"","eco":"","edeka":"","education":"","email":"","emerck":"","energy":"","engineer":"","engineering":"","enterprises":"","epost":"","epson":"","equipment":"","ericsson":"","erni":"","esq":"","estate":"*compute","esurance":"","etisalat":"","eurovision":"","eus":"user.party","events":"","everbank":"","exchange":"","expert":"","exposed":"","express":"","extraspace":"","fage":"","fail":"","fairwinds":"","faith":"ybo","family":"","fan":"","fans":"","farm":"storj","farmers":"","fashion":"","fast":"","fedex":"","feedback":"","ferrari":"","ferrero":"","fiat":"","fidelity":"","fido":"","film":"","final":"","finance":"","financial":"","fire":"","firestone":"","firmdale":"","fish":"","fishing":"","fit":"ptplus","fitness":"","flickr":"","flights":"","flir":"","florist":"","flowers":"","fly":"","foo":"","food":"","foodnetwork":"","football":"","ford":"","forex":"","forsale":"","forum":"","foundation":"","fox":"","free":"","fresenius":"","frl":"","frogans":"","frontdoor":"","frontier":"","ftr":"","fujitsu":"","fujixerox":"","fun":"","fund":"","furniture":"","futbol":"","fyi":"","gal":"","gallery":"","gallo":"","gallup":"","game":"","games":"","gap":"","garden":"","gbiz":"","gdn":"","gea":"","gent":"","genting":"","george":"","ggee":"","gift":"","gifts":"","gives":"","giving":"","glade":"","glass":"","gle":"","global":"","globo":"","gmail":"","gmbh":"","gmo":"","gmx":"","godaddy":"","gold":"","goldpoint":"","golf":"","goo":"","goodhands":"","goodyear":"","goog":"cloud","google":"","gop":"","got":"","grainger":"","graphics":"","gratis":"","green":"","gripe":"","grocery":"","group":"","guardian":"","gucci":"","guge":"","guide":"","guitars":"","guru":"","hair":"","hamburg":"","hangout":"","haus":"","hbo":"","hdfc":"","hdfcbank":"","health":"","healthcare":"","help":"","helsinki":"","here":"","hermes":"","hgtv":"","hiphop":"","hisamitsu":"","hitachi":"","hiv":"","hkt":"","hockey":"","holdings":"","holiday":"","homedepot":"","homegoods":"","homes":"","homesense":"","honda":"","honeywell":"","horse":"","hospital":"","host":"cloudaccess|freesite","hosting":"opencraft","hot":"","hoteles":"","hotels":"","hotmail":"","house":"","how":"","hsbc":"","htc":"","hughes":"","hyatt":"","hyundai":"","ibm":"","icbc":"","ice":"","icu":"","ieee":"","ifm":"","ikano":"","imamat":"","imdb":"","immo":"","immobilien":"","industries":"","infiniti":"","ing":"","ink":"","institute":"","insurance":"","insure":"","intel":"","international":"","intuit":"","investments":"","ipiranga":"","irish":"","iselect":"","ismaili":"","ist":"","istanbul":"","itau":"","itv":"","iveco":"","iwc":"","jaguar":"","java":"","jcb":"","jcp":"","jeep":"","jetzt":"","jewelry":"","jio":"","jlc":"","jll":"","jmp":"","jnj":"","joburg":"","jot":"","joy":"","jpmorgan":"","jprs":"","juegos":"","juniper":"","kaufen":"","kddi":"","kerryhotels":"","kerrylogistics":"","kerryproperties":"","kfh":"","kia":"","kim":"","kinder":"","kindle":"","kitchen":"","kiwi":"","koeln":"","komatsu":"","kosher":"","kpmg":"","kpn":"","krd":"co|edu","kred":"","kuokgroup":"","kyoto":"","lacaixa":"","ladbrokes":"","lamborghini":"","lamer":"","lancaster":"","lancia":"","lancome":"","land":"static|dev.static|sites.static","landrover":"","lanxess":"","lasalle":"","lat":"","latino":"","latrobe":"","law":"","lawyer":"","lds":"","lease":"","leclerc":"","lefrak":"","legal":"","lego":"","lexus":"","lgbt":"","liaison":"","lidl":"","life":"","lifeinsurance":"","lifestyle":"","lighting":"","like":"","lilly":"","limited":"","limo":"","lincoln":"","linde":"","link":"cyon|mypep","lipsy":"","live":"","living":"","lixil":"","loan":"","loans":"","locker":"","locus":"","loft":"","lol":"","london":"","lotte":"","lotto":"","love":"","lpl":"","lplfinancial":"","ltd":"","ltda":"","lundbeck":"","lupin":"","luxe":"","luxury":"","macys":"","madrid":"","maif":"","maison":"","makeup":"","man":"","management":"router","mango":"","map":"","market":"","marketing":"","markets":"","marriott":"","marshalls":"","maserati":"","mattel":"","mba":"","mcd":"","mcdonalds":"","mckinsey":"","med":"","media":"","meet":"","melbourne":"","meme":"","memorial":"","men":"","menu":"","meo":"","merckmsd":"","metlife":"","miami":"","microsoft":"","mini":"","mint":"","mit":"","mitsubishi":"","mlb":"","mls":"","mma":"","mobile":"","mobily":"","moda":"","moe":"","moi":"","mom":"","monash":"","money":"","monster":"","montblanc":"","mopar":"","mormon":"","mortgage":"","moscow":"","moto":"","motorcycles":"","mov":"","movie":"","movistar":"","msd":"","mtn":"","mtpc":"","mtr":"","mutual":"","nab":"","nadex":"","nagoya":"","nationwide":"","natura":"","navy":"","nba":"","nec":"","netbank":"","netflix":"","network":"*alces","neustar":"","new":"","newholland":"","news":"","next":"","nextdirect":"","nexus":"","nfl":"","ngo":"","nhk":"","nico":"","nike":"","nikon":"","ninja":"","nissan":"","nissay":"","nokia":"","northwesternmutual":"","norton":"","now":"","nowruz":"","nowtv":"","nra":"","nrw":"","ntt":"","nyc":"","obi":"","observer":"","off":"","office":"","okinawa":"","olayan":"","olayangroup":"","oldnavy":"","ollo":"","omega":"","one":"homelink","ong":"","onl":"","online":"barsy","onyourside":"","ooo":"","open":"","oracle":"","orange":"","organic":"","origins":"","osaka":"","otsuka":"","ott":"","ovh":"nerdpol","page":"","pamperedchef":"","panasonic":"","panerai":"","paris":"","pars":"","partners":"","parts":"","party":"ybo","passagens":"","pay":"","pccw":"","pet":"","pfizer":"","pharmacy":"","phd":"","philips":"","phone":"","photo":"","photography":"","photos":"","physio":"","piaget":"","pics":"","pictet":"","pictures":"1337","pid":"","pin":"","ping":"","pink":"","pioneer":"","pizza":"","place":"","play":"","playstation":"","plumbing":"","plus":"","pnc":"","pohl":"","poker":"","politie":"","porn":"","pramerica":"","praxi":"","press":"","prime":"","prod":"","productions":"","prof":"","progressive":"","promo":"","properties":"","property":"","protection":"","pru":"","prudential":"","pub":"","pwc":"","qpon":"","quebec":"","quest":"","qvc":"","racing":"","radio":"","raid":"","read":"","realestate":"","realtor":"","realty":"","recipes":"","red":"","redstone":"","redumbrella":"","rehab":"","reise":"","reisen":"","reit":"","reliance":"","ren":"","rent":"","rentals":"","repair":"","report":"","republican":"","rest":"","restaurant":"","review":"ybo","reviews":"","rexroth":"","rich":"","richardli":"","ricoh":"","rightathome":"","ril":"","rio":"","rip":"clan","rmit":"","rocher":"","rocks":"myddns|lima-city|webspace","rodeo":"","rogers":"","room":"","rsvp":"","rugby":"","ruhr":"","run":"","rwe":"","ryukyu":"","saarland":"","safe":"","safety":"","sakura":"","sale":"","salon":"","samsclub":"","samsung":"","sandvik":"","sandvikcoromant":"","sanofi":"","sap":"","sapo":"","sarl":"","sas":"","save":"","saxo":"","sbi":"","sbs":"","sca":"","scb":"","schaeffler":"","schmidt":"","scholarships":"","school":"","schule":"","schwarz":"","science":"ybo","scjohnson":"","scor":"","scot":"","search":"","seat":"","secure":"","security":"","seek":"","select":"","sener":"","services":"","ses":"","seven":"","sew":"","sex":"","sexy":"","sfr":"","shangrila":"","sharp":"","shaw":"","shell":"","shia":"","shiksha":"","shoes":"","shop":"","shopping":"","shouji":"","show":"","showtime":"","shriram":"","silk":"","sina":"","singles":"","site":"cyon|*platformsh","ski":"","skin":"","sky":"","skype":"","sling":"","smart":"","smile":"","sncf":"","soccer":"","social":"","softbank":"","software":"","sohu":"","solar":"","solutions":"","song":"","sony":"","soy":"","space":"stackspace|uber|xs4all","spiegel":"","spot":"","spreadbetting":"","srl":"","srt":"","stada":"","staples":"","star":"","starhub":"","statebank":"","statefarm":"","statoil":"","stc":"","stcgroup":"","stockholm":"","storage":"","store":"","stream":"","studio":"","study":"","style":"","sucks":"","supplies":"","supply":"","support":"barsy","surf":"","surgery":"","suzuki":"","swatch":"","swiftcover":"","swiss":"","sydney":"","symantec":"","systems":"knightpoint","tab":"","taipei":"","talk":"","taobao":"","target":"","tatamotors":"","tatar":"","tattoo":"","tax":"","taxi":"","tci":"","tdk":"","team":"","tech":"","technology":"","telecity":"","telefonica":"","temasek":"","tennis":"","teva":"","thd":"","theater":"","theatre":"","tiaa":"","tickets":"","tienda":"","tiffany":"","tips":"","tires":"","tirol":"","tjmaxx":"","tjx":"","tkmaxx":"","tmall":"","today":"","tokyo":"","tools":"","top":"","toray":"","toshiba":"","total":"","tours":"","town":"","toyota":"","toys":"","trade":"ybo","trading":"","training":"","travelchannel":"","travelers":"","travelersinsurance":"","trust":"","trv":"","tube":"","tui":"","tunes":"","tushu":"","tvs":"","ubank":"","ubs":"","uconnect":"","unicom":"","university":"","uno":"","uol":"","ups":"","vacations":"","vana":"","vanguard":"","vegas":"","ventures":"","verisign":"","versicherung":"","vet":"","viajes":"","video":"","vig":"","viking":"","villas":"","vin":"","vip":"","virgin":"","visa":"","vision":"","vista":"","vistaprint":"","viva":"","vivo":"","vlaanderen":"","vodka":"","volkswagen":"","volvo":"","vote":"","voting":"","voto":"","voyage":"","vuelos":"","wales":"","walmart":"","walter":"","wang":"","wanggou":"","warman":"","watch":"","watches":"","weather":"","weatherchannel":"","webcam":"","weber":"","website":"","wed":"","wedding":"","weibo":"","weir":"","whoswho":"","wien":"","wiki":"","williamhill":"","win":"","windows":"","wine":"","winners":"","wme":"","wolterskluwer":"","woodside":"","work":"","works":"","world":"","wow":"","wtc":"","wtf":"","xbox":"","xerox":"","xfinity":"","xihuan":"","xin":"","xn--11b4c3d":"","xn--1ck2e1b":"","xn--1qqw23a":"","xn--30rr7y":"","xn--3bst00m":"","xn--3ds443g":"","xn--3oq18vl8pn36a":"","xn--3pxu8k":"","xn--42c2d9a":"","xn--45q11c":"","xn--4gbrim":"","xn--55qw42g":"","xn--55qx5d":"","xn--5su34j936bgsg":"","xn--5tzm5g":"","xn--6frz82g":"","xn--6qq986b3xl":"","xn--80adxhks":"","xn--80aqecdr1a":"","xn--80asehdb":"","xn--80aswg":"","xn--8y0a063a":"","xn--9dbq2a":"","xn--9et52u":"","xn--9krt00a":"","xn--b4w605ferd":"","xn--bck1b9a5dre4c":"","xn--c1avg":"","xn--c2br7g":"","xn--cck2b3b":"","xn--cg4bki":"","xn--czr694b":"","xn--czrs0t":"","xn--czru2d":"","xn--d1acj3b":"","xn--eckvdtc9d":"","xn--efvy88h":"","xn--estv75g":"","xn--fct429k":"","xn--fhbei":"","xn--fiq228c5hs":"","xn--fiq64b":"","xn--fjq720a":"","xn--flw351e":"","xn--fzys8d69uvgm":"","xn--g2xx48c":"","xn--gckr3f0f":"","xn--gk3at1e":"","xn--hxt814e":"","xn--i1b6b1a6a2e":"","xn--imr513n":"","xn--io0a7i":"","xn--j1aef":"","xn--jlq61u9w7b":"","xn--jvr189m":"","xn--kcrx77d1x4a":"","xn--kpu716f":"","xn--kput3i":"","xn--mgba3a3ejt":"","xn--mgba7c0bbn0a":"","xn--mgbaakc7dvf":"","xn--mgbab2bd":"","xn--mgbb9fbpob":"","xn--mgbca7dzdo":"","xn--mgbi4ecexp":"","xn--mgbt3dhd":"","xn--mk1bu44c":"","xn--mxtq1m":"","xn--ngbc5azd":"","xn--ngbe9e0a":"","xn--ngbrx":"","xn--nqv7f":"","xn--nqv7fs00ema":"","xn--nyqy26a":"","xn--p1acf":"","xn--pbt977c":"","xn--pssy2u":"","xn--q9jyb4c":"","xn--qcka1pmc":"","xn--rhqv96g":"","xn--rovu88b":"","xn--ses554g":"","xn--t60b56a":"","xn--tckwe":"","xn--tiq49xqyj":"","xn--unup4y":"","xn--vermgensberater-ctb":"","xn--vermgensberatung-pwb":"","xn--vhquv":"","xn--vuq861b":"","xn--w4r85el8fhu5dnra":"","xn--w4rs40l":"","xn--xhq521b":"","xn--zfr164b":"","xperia":"","xyz":"blogsite|fhapp","yachts":"","yahoo":"","yamaxun":"","yandex":"","yodobashi":"","yoga":"","yokohama":"","you":"","youtube":"","yun":"","zappos":"","zara":"","zero":"","zip":"","zippo":"","zone":"*triton|lima","zuerich":""}
  },{}],60:[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 punycode = require('punycode');
  
  exports.parse = urlParse;
  exports.resolve = urlResolve;
  exports.resolveObject = urlResolveObject;
  exports.format = urlFormat;
  
  exports.Url = Url;
  
  function Url() {
    this.protocol = null;
    this.slashes = null;
    this.auth = null;
    this.host = null;
    this.port = null;
    this.hostname = null;
    this.hash = null;
    this.search = null;
    this.query = null;
    this.pathname = null;
    this.path = null;
    this.href = null;
  }
  
  // Reference: RFC 3986, RFC 1808, RFC 2396
  
  // define these here so at least they only have to be
  // compiled once on the first module load.
  var protocolPattern = /^([a-z0-9.+-]+:)/i,
      portPattern = /:[0-9]*$/,
  
      // RFC 2396: characters reserved for delimiting URLs.
      // We actually just auto-escape these.
      delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'],
  
      // RFC 2396: characters not allowed for various reasons.
      unwise = ['{', '}', '|', '\\', '^', '`'].concat(delims),
  
      // Allowed by RFCs, but cause of XSS attacks.  Always escape these.
      autoEscape = ['\''].concat(unwise),
      // Characters that are never ever allowed in a hostname.
      // Note that any invalid chars are also handled, but these
      // are the ones that are *expected* to be seen, so we fast-path
      // them.
      nonHostChars = ['%', '/', '?', ';', '#'].concat(autoEscape),
      hostEndingChars = ['/', '?', '#'],
      hostnameMaxLen = 255,
      hostnamePartPattern = /^[a-z0-9A-Z_-]{0,63}$/,
      hostnamePartStart = /^([a-z0-9A-Z_-]{0,63})(.*)$/,
      // protocols that can allow "unsafe" and "unwise" chars.
      unsafeProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that never have a hostname.
      hostlessProtocol = {
        'javascript': true,
        'javascript:': true
      },
      // protocols that always contain a // bit.
      slashedProtocol = {
        'http': true,
        'https': true,
        'ftp': true,
        'gopher': true,
        'file': true,
        'http:': true,
        'https:': true,
        'ftp:': true,
        'gopher:': true,
        'file:': true
      },
      querystring = require('querystring');
  
  function urlParse(url, parseQueryString, slashesDenoteHost) {
    if (url && isObject(url) && url instanceof Url) return url;
  
    var u = new Url;
    u.parse(url, parseQueryString, slashesDenoteHost);
    return u;
  }
  
  Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) {
    if (!isString(url)) {
      throw new TypeError("Parameter 'url' must be a string, not " + typeof url);
    }
  
    var rest = url;
  
    // trim before proceeding.
    // This is to support parse stuff like "  http://foo.com  \n"
    rest = rest.trim();
  
    var proto = protocolPattern.exec(rest);
    if (proto) {
      proto = proto[0];
      var lowerProto = proto.toLowerCase();
      this.protocol = lowerProto;
      rest = rest.substr(proto.length);
    }
  
    // figure out if it's got a host
    // user@server is *always* interpreted as a hostname, and url
    // resolution will treat //foo/bar as host=foo,path=bar because that's
    // how the browser resolves relative URLs.
    if (slashesDenoteHost || proto || rest.match(/^\/\/[^@\/]+@[^@\/]+/)) {
      var slashes = rest.substr(0, 2) === '//';
      if (slashes && !(proto && hostlessProtocol[proto])) {
        rest = rest.substr(2);
        this.slashes = true;
      }
    }
  
    if (!hostlessProtocol[proto] &&
        (slashes || (proto && !slashedProtocol[proto]))) {
  
      // there's a hostname.
      // the first instance of /, ?, ;, or # ends the host.
      //
      // If there is an @ in the hostname, then non-host chars *are* allowed
      // to the left of the last @ sign, unless some host-ending character
      // comes *before* the @-sign.
      // URLs are obnoxious.
      //
      // ex:
      // http://a@b@c/ => user:a@b host:c
      // http://a@b?@c => user:a host:c path:/?@c
  
      // v0.12 TODO(isaacs): This is not quite how Chrome does things.
      // Review our test case against browsers more comprehensively.
  
      // find the first instance of any hostEndingChars
      var hostEnd = -1;
      for (var i = 0; i < hostEndingChars.length; i++) {
        var hec = rest.indexOf(hostEndingChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
  
      // at this point, either we have an explicit point where the
      // auth portion cannot go past, or the last @ char is the decider.
      var auth, atSign;
      if (hostEnd === -1) {
        // atSign can be anywhere.
        atSign = rest.lastIndexOf('@');
      } else {
        // atSign must be in auth portion.
        // http://a@b/c@d => host:b auth:a path:/c@d
        atSign = rest.lastIndexOf('@', hostEnd);
      }
  
      // Now we have a portion which is definitely the auth.
      // Pull that off.
      if (atSign !== -1) {
        auth = rest.slice(0, atSign);
        rest = rest.slice(atSign + 1);
        this.auth = decodeURIComponent(auth);
      }
  
      // the host is the remaining to the left of the first non-host char
      hostEnd = -1;
      for (var i = 0; i < nonHostChars.length; i++) {
        var hec = rest.indexOf(nonHostChars[i]);
        if (hec !== -1 && (hostEnd === -1 || hec < hostEnd))
          hostEnd = hec;
      }
      // if we still have not hit it, then the entire thing is a host.
      if (hostEnd === -1)
        hostEnd = rest.length;
  
      this.host = rest.slice(0, hostEnd);
      rest = rest.slice(hostEnd);
  
      // pull out port.
      this.parseHost();
  
      // we've indicated that there is a hostname,
      // so even if it's empty, it has to be present.
      this.hostname = this.hostname || '';
  
      // if hostname begins with [ and ends with ]
      // assume that it's an IPv6 address.
      var ipv6Hostname = this.hostname[0] === '[' &&
          this.hostname[this.hostname.length - 1] === ']';
  
      // validate a little.
      if (!ipv6Hostname) {
        var hostparts = this.hostname.split(/\./);
        for (var i = 0, l = hostparts.length; i < l; i++) {
          var part = hostparts[i];
          if (!part) continue;
          if (!part.match(hostnamePartPattern)) {
            var newpart = '';
            for (var j = 0, k = part.length; j < k; j++) {
              if (part.charCodeAt(j) > 127) {
                // we replace non-ASCII char with a temporary placeholder
                // we need this to make sure size of hostname is not
                // broken by replacing non-ASCII by nothing
                newpart += 'x';
              } else {
                newpart += part[j];
              }
            }
            // we test again with ASCII char only
            if (!newpart.match(hostnamePartPattern)) {
              var validParts = hostparts.slice(0, i);
              var notHost = hostparts.slice(i + 1);
              var bit = part.match(hostnamePartStart);
              if (bit) {
                validParts.push(bit[1]);
                notHost.unshift(bit[2]);
              }
              if (notHost.length) {
                rest = '/' + notHost.join('.') + rest;
              }
              this.hostname = validParts.join('.');
              break;
            }
          }
        }
      }
  
      if (this.hostname.length > hostnameMaxLen) {
        this.hostname = '';
      } else {
        // hostnames are always lower case.
        this.hostname = this.hostname.toLowerCase();
      }
  
      if (!ipv6Hostname) {
        // IDNA Support: Returns a puny coded representation of "domain".
        // It only converts the part of the domain name that
        // has non ASCII characters. I.e. it dosent matter if
        // you call it with a domain that already is in ASCII.
        var domainArray = this.hostname.split('.');
        var newOut = [];
        for (var i = 0; i < domainArray.length; ++i) {
          var s = domainArray[i];
          newOut.push(s.match(/[^A-Za-z0-9_-]/) ?
              'xn--' + punycode.encode(s) : s);
        }
        this.hostname = newOut.join('.');
      }
  
      var p = this.port ? ':' + this.port : '';
      var h = this.hostname || '';
      this.host = h + p;
      this.href += this.host;
  
      // strip [ and ] from the hostname
      // the host field still retains them, though
      if (ipv6Hostname) {
        this.hostname = this.hostname.substr(1, this.hostname.length - 2);
        if (rest[0] !== '/') {
          rest = '/' + rest;
        }
      }
    }
  
    // now rest is set to the post-host stuff.
    // chop off any delim chars.
    if (!unsafeProtocol[lowerProto]) {
  
      // First, make 100% sure that any "autoEscape" chars get
      // escaped, even if encodeURIComponent doesn't think they
      // need to be.
      for (var i = 0, l = autoEscape.length; i < l; i++) {
        var ae = autoEscape[i];
        var esc = encodeURIComponent(ae);
        if (esc === ae) {
          esc = escape(ae);
        }
        rest = rest.split(ae).join(esc);
      }
    }
  
  
    // chop off from the tail first.
    var hash = rest.indexOf('#');
    if (hash !== -1) {
      // got a fragment string.
      this.hash = rest.substr(hash);
      rest = rest.slice(0, hash);
    }
    var qm = rest.indexOf('?');
    if (qm !== -1) {
      this.search = rest.substr(qm);
      this.query = rest.substr(qm + 1);
      if (parseQueryString) {
        this.query = querystring.parse(this.query);
      }
      rest = rest.slice(0, qm);
    } else if (parseQueryString) {
      // no query string, but parseQueryString still requested
      this.search = '';
      this.query = {};
    }
    if (rest) this.pathname = rest;
    if (slashedProtocol[lowerProto] &&
        this.hostname && !this.pathname) {
      this.pathname = '/';
    }
  
    //to support http.request
    if (this.pathname || this.search) {
      var p = this.pathname || '';
      var s = this.search || '';
      this.path = p + s;
    }
  
    // finally, reconstruct the href based on what has been validated.
    this.href = this.format();
    return this;
  };
  
  // format a parsed object into a url string
  function urlFormat(obj) {
    // ensure it's an object, and not a string url.
    // If it's an obj, this is a no-op.
    // this way, you can call url_format() on strings
    // to clean up potentially wonky urls.
    if (isString(obj)) obj = urlParse(obj);
    if (!(obj instanceof Url)) return Url.prototype.format.call(obj);
    return obj.format();
  }
  
  Url.prototype.format = function() {
    var auth = this.auth || '';
    if (auth) {
      auth = encodeURIComponent(auth);
      auth = auth.replace(/%3A/i, ':');
      auth += '@';
    }
  
    var protocol = this.protocol || '',
        pathname = this.pathname || '',
        hash = this.hash || '',
        host = false,
        query = '';
  
    if (this.host) {
      host = auth + this.host;
    } else if (this.hostname) {
      host = auth + (this.hostname.indexOf(':') === -1 ?
          this.hostname :
          '[' + this.hostname + ']');
      if (this.port) {
        host += ':' + this.port;
      }
    }
  
    if (this.query &&
        isObject(this.query) &&
        Object.keys(this.query).length) {
      query = querystring.stringify(this.query);
    }
  
    var search = this.search || (query && ('?' + query)) || '';
  
    if (protocol && protocol.substr(-1) !== ':') protocol += ':';
  
    // only the slashedProtocols get the //.  Not mailto:, xmpp:, etc.
    // unless they had them to begin with.
    if (this.slashes ||
        (!protocol || slashedProtocol[protocol]) && host !== false) {
      host = '//' + (host || '');
      if (pathname && pathname.charAt(0) !== '/') pathname = '/' + pathname;
    } else if (!host) {
      host = '';
    }
  
    if (hash && hash.charAt(0) !== '#') hash = '#' + hash;
    if (search && search.charAt(0) !== '?') search = '?' + search;
  
    pathname = pathname.replace(/[?#]/g, function(match) {
      return encodeURIComponent(match);
    });
    search = search.replace('#', '%23');
  
    return protocol + host + pathname + search + hash;
  };
  
  function urlResolve(source, relative) {
    return urlParse(source, false, true).resolve(relative);
  }
  
  Url.prototype.resolve = function(relative) {
    return this.resolveObject(urlParse(relative, false, true)).format();
  };
  
  function urlResolveObject(source, relative) {
    if (!source) return relative;
    return urlParse(source, false, true).resolveObject(relative);
  }
  
  Url.prototype.resolveObject = function(relative) {
    if (isString(relative)) {
      var rel = new Url();
      rel.parse(relative, false, true);
      relative = rel;
    }
  
    var result = new Url();
    Object.keys(this).forEach(function(k) {
      result[k] = this[k];
    }, this);
  
    // hash is always overridden, no matter what.
    // even href="" will remove it.
    result.hash = relative.hash;
  
    // if the relative url is empty, then there's nothing left to do here.
    if (relative.href === '') {
      result.href = result.format();
      return result;
    }
  
    // hrefs like //foo/bar always cut to the protocol.
    if (relative.slashes && !relative.protocol) {
      // take everything except the protocol from relative
      Object.keys(relative).forEach(function(k) {
        if (k !== 'protocol')
          result[k] = relative[k];
      });
  
      //urlParse appends trailing / to urls like http://www.example.com
      if (slashedProtocol[result.protocol] &&
          result.hostname && !result.pathname) {
        result.path = result.pathname = '/';
      }
  
      result.href = result.format();
      return result;
    }
  
    if (relative.protocol && relative.protocol !== result.protocol) {
      // if it's a known url protocol, then changing
      // the protocol does weird things
      // first, if it's not file:, then we MUST have a host,
      // and if there was a path
      // to begin with, then we MUST have a path.
      // if it is file:, then the host is dropped,
      // because that's known to be hostless.
      // anything else is assumed to be absolute.
      if (!slashedProtocol[relative.protocol]) {
        Object.keys(relative).forEach(function(k) {
          result[k] = relative[k];
        });
        result.href = result.format();
        return result;
      }
  
      result.protocol = relative.protocol;
      if (!relative.host && !hostlessProtocol[relative.protocol]) {
        var relPath = (relative.pathname || '').split('/');
        while (relPath.length && !(relative.host = relPath.shift()));
        if (!relative.host) relative.host = '';
        if (!relative.hostname) relative.hostname = '';
        if (relPath[0] !== '') relPath.unshift('');
        if (relPath.length < 2) relPath.unshift('');
        result.pathname = relPath.join('/');
      } else {
        result.pathname = relative.pathname;
      }
      result.search = relative.search;
      result.query = relative.query;
      result.host = relative.host || '';
      result.auth = relative.auth;
      result.hostname = relative.hostname || relative.host;
      result.port = relative.port;
      // to support http.request
      if (result.pathname || result.search) {
        var p = result.pathname || '';
        var s = result.search || '';
        result.path = p + s;
      }
      result.slashes = result.slashes || relative.slashes;
      result.href = result.format();
      return result;
    }
  
    var isSourceAbs = (result.pathname && result.pathname.charAt(0) === '/'),
        isRelAbs = (
            relative.host ||
            relative.pathname && relative.pathname.charAt(0) === '/'
        ),
        mustEndAbs = (isRelAbs || isSourceAbs ||
                      (result.host && relative.pathname)),
        removeAllDots = mustEndAbs,
        srcPath = result.pathname && result.pathname.split('/') || [],
        relPath = relative.pathname && relative.pathname.split('/') || [],
        psychotic = result.protocol && !slashedProtocol[result.protocol];
  
    // if the url is a non-slashed url, then relative
    // links like ../.. should be able
    // to crawl up to the hostname, as well.  This is strange.
    // result.protocol has already been set by now.
    // Later on, put the first path part into the host field.
    if (psychotic) {
      result.hostname = '';
      result.port = null;
      if (result.host) {
        if (srcPath[0] === '') srcPath[0] = result.host;
        else srcPath.unshift(result.host);
      }
      result.host = '';
      if (relative.protocol) {
        relative.hostname = null;
        relative.port = null;
        if (relative.host) {
          if (relPath[0] === '') relPath[0] = relative.host;
          else relPath.unshift(relative.host);
        }
        relative.host = null;
      }
      mustEndAbs = mustEndAbs && (relPath[0] === '' || srcPath[0] === '');
    }
  
    if (isRelAbs) {
      // it's absolute.
      result.host = (relative.host || relative.host === '') ?
                    relative.host : result.host;
      result.hostname = (relative.hostname || relative.hostname === '') ?
                        relative.hostname : result.hostname;
      result.search = relative.search;
      result.query = relative.query;
      srcPath = relPath;
      // fall through to the dot-handling below.
    } else if (relPath.length) {
      // it's relative
      // throw away the existing file, and take the new path instead.
      if (!srcPath) srcPath = [];
      srcPath.pop();
      srcPath = srcPath.concat(relPath);
      result.search = relative.search;
      result.query = relative.query;
    } else if (!isNullOrUndefined(relative.search)) {
      // just pull out the search.
      // like href='?foo'.
      // Put this after the other two cases because it simplifies the booleans
      if (psychotic) {
        result.hostname = result.host = srcPath.shift();
        //occationaly the auth can get stuck only in host
        //this especialy happens in cases like
        //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
        var authInHost = result.host && result.host.indexOf('@') > 0 ?
                         result.host.split('@') : false;
        if (authInHost) {
          result.auth = authInHost.shift();
          result.host = result.hostname = authInHost.shift();
        }
      }
      result.search = relative.search;
      result.query = relative.query;
      //to support http.request
      if (!isNull(result.pathname) || !isNull(result.search)) {
        result.path = (result.pathname ? result.pathname : '') +
                      (result.search ? result.search : '');
      }
      result.href = result.format();
      return result;
    }
  
    if (!srcPath.length) {
      // no path at all.  easy.
      // we've already handled the other stuff above.
      result.pathname = null;
      //to support http.request
      if (result.search) {
        result.path = '/' + result.search;
      } else {
        result.path = null;
      }
      result.href = result.format();
      return result;
    }
  
    // if a url ENDs in . or .., then it must get a trailing slash.
    // however, if it ends in anything else non-slashy,
    // then it must NOT get a trailing slash.
    var last = srcPath.slice(-1)[0];
    var hasTrailingSlash = (
        (result.host || relative.host) && (last === '.' || last === '..') ||
        last === '');
  
    // strip single dots, resolve double dots to parent dir
    // if the path tries to go above the root, `up` ends up > 0
    var up = 0;
    for (var i = srcPath.length; i >= 0; i--) {
      last = srcPath[i];
      if (last == '.') {
        srcPath.splice(i, 1);
      } else if (last === '..') {
        srcPath.splice(i, 1);
        up++;
      } else if (up) {
        srcPath.splice(i, 1);
        up--;
      }
    }
  
    // if the path is allowed to go above the root, restore leading ..s
    if (!mustEndAbs && !removeAllDots) {
      for (; up--; up) {
        srcPath.unshift('..');
      }
    }
  
    if (mustEndAbs && srcPath[0] !== '' &&
        (!srcPath[0] || srcPath[0].charAt(0) !== '/')) {
      srcPath.unshift('');
    }
  
    if (hasTrailingSlash && (srcPath.join('/').substr(-1) !== '/')) {
      srcPath.push('');
    }
  
    var isAbsolute = srcPath[0] === '' ||
        (srcPath[0] && srcPath[0].charAt(0) === '/');
  
    // put the host back
    if (psychotic) {
      result.hostname = result.host = isAbsolute ? '' :
                                      srcPath.length ? srcPath.shift() : '';
      //occationaly the auth can get stuck only in host
      //this especialy happens in cases like
      //url.resolveObject('mailto:local1@domain1', 'local2@domain2')
      var authInHost = result.host && result.host.indexOf('@') > 0 ?
                       result.host.split('@') : false;
      if (authInHost) {
        result.auth = authInHost.shift();
        result.host = result.hostname = authInHost.shift();
      }
    }
  
    mustEndAbs = mustEndAbs || (result.host && srcPath.length);
  
    if (mustEndAbs && !isAbsolute) {
      srcPath.unshift('');
    }
  
    if (!srcPath.length) {
      result.pathname = null;
      result.path = null;
    } else {
      result.pathname = srcPath.join('/');
    }
  
    //to support request.http
    if (!isNull(result.pathname) || !isNull(result.search)) {
      result.path = (result.pathname ? result.pathname : '') +
                    (result.search ? result.search : '');
    }
    result.auth = relative.auth || result.auth;
    result.slashes = result.slashes || relative.slashes;
    result.href = result.format();
    return result;
  };
  
  Url.prototype.parseHost = function() {
    var host = this.host;
    var port = portPattern.exec(host);
    if (port) {
      port = port[0];
      if (port !== ':') {
        this.port = port.substr(1);
      }
      host = host.substr(0, host.length - port.length);
    }
    if (host) this.hostname = host;
  };
  
  function isString(arg) {
    return typeof arg === "string";
  }
  
  function isObject(arg) {
    return typeof arg === 'object' && arg !== null;
  }
  
  function isNull(arg) {
    return arg === null;
  }
  function isNullOrUndefined(arg) {
    return  arg == null;
  }
  
  },{"punycode":40,"querystring":43}],61:[function(require,module,exports){
  var AttachedCache, IP, U2, Url, escapeSlash, exports, ref, shExp2RegExp,
    hasProp = {}.hasOwnProperty;
  
  U2 = require('uglify-js');
  
  IP = require('ip-address');
  
  Url = require('url');
  
  ref = require('./shexp_utils'), shExp2RegExp = ref.shExp2RegExp, escapeSlash = ref.escapeSlash;
  
  AttachedCache = require('./utils').AttachedCache;
  
  module.exports = exports = {
    requestFromUrl: function(url) {
      var req;
      if (typeof url === 'string') {
        url = Url.parse(url);
      }
      return req = {
        url: Url.format(url),
        host: url.hostname,
        scheme: url.protocol.replace(':', '')
      };
    },
    urlWildcard2HostWildcard: function(pattern) {
      var result;
      result = pattern.match(/^\*:\/\/((?:\w|[?*._\-])+)\/\*$/);
      return result != null ? result[1] : void 0;
    },
    tag: function(condition) {
      return exports._condCache.tag(condition);
    },
    analyze: function(condition) {
      return exports._condCache.get(condition, function() {
        return {
          analyzed: exports._handler(condition.conditionType).analyze.call(exports, condition)
        };
      });
    },
    match: function(condition, request) {
      var cache;
      cache = exports.analyze(condition);
      return exports._handler(condition.conditionType).match.call(exports, condition, request, cache);
    },
    compile: function(condition) {
      var cache, handler;
      cache = exports.analyze(condition);
      if (cache.compiled) {
        return cache.compiled;
      }
      handler = exports._handler(condition.conditionType);
      return cache.compiled = handler.compile.call(exports, condition, cache);
    },
    str: function(condition, arg) {
      var abbr, endCode, handler, part, result, str, typeStr;
      abbr = (arg != null ? arg : {
        abbr: -1
      }).abbr;
      handler = exports._handler(condition.conditionType);
      if (handler.abbrs[0].length === 0) {
        endCode = condition.pattern.charCodeAt(condition.pattern.length - 1);
        if (endCode !== exports.colonCharCode && condition.pattern.indexOf(' ') < 0) {
          return condition.pattern;
        }
      }
      str = handler.str;
      typeStr = typeof abbr === 'number' ? handler.abbrs[(handler.abbrs.length + abbr) % handler.abbrs.length] : condition.conditionType;
      result = typeStr + ':';
      part = str ? str.call(exports, condition) : condition.pattern;
      if (part) {
        result += ' ' + part;
      }
      return result;
    },
    colonCharCode: ':'.charCodeAt(0),
    fromStr: function(str) {
      var condition, conditionType, fromStr, i;
      str = str.trim();
      i = str.indexOf(' ');
      if (i < 0) {
        i = str.length;
      }
      if (str.charCodeAt(i - 1) === exports.colonCharCode) {
        conditionType = str.substr(0, i - 1);
        str = str.substr(i + 1).trim();
      } else {
        conditionType = '';
      }
      conditionType = exports.typeFromAbbr(conditionType);
      if (!conditionType) {
        return null;
      }
      condition = {
        conditionType: conditionType
      };
      fromStr = exports._handler(condition.conditionType).fromStr;
      if (fromStr) {
        return fromStr.call(exports, str, condition);
      } else {
        condition.pattern = str;
        return condition;
      }
    },
    _abbrs: null,
    typeFromAbbr: function(abbr) {
      var ab, abbrs, j, len, ref1, type;
      if (!exports._abbrs) {
        exports._abbrs = {};
        ref1 = exports._conditionTypes;
        for (type in ref1) {
          if (!hasProp.call(ref1, type)) continue;
          abbrs = ref1[type].abbrs;
          exports._abbrs[type.toUpperCase()] = type;
          for (j = 0, len = abbrs.length; j < len; j++) {
            ab = abbrs[j];
            exports._abbrs[ab.toUpperCase()] = type;
          }
        }
      }
      return exports._abbrs[abbr.toUpperCase()];
    },
    comment: function(comment, node) {
      var base;
      if (!comment) {
        return node;
      }
      if (node.start == null) {
        node.start = {};
      }
      Object.defineProperty(node.start, '_comments_dumped', {
        get: function() {
          return false;
        },
        set: function() {
          return false;
        }
      });
      if ((base = node.start).comments_before == null) {
        base.comments_before = [];
      }
      node.start.comments_before.push({
        type: 'comment2',
        value: comment
      });
      return node;
    },
    safeRegex: function(expr) {
      var _;
      try {
        return new RegExp(expr);
      } catch (error) {
        _ = error;
        return /(?!)/;
      }
    },
    regTest: function(expr, regexp) {
      if (typeof regexp === 'string') {
        regexp = regexSafe(escapeSlash(regexp));
      }
      if (typeof expr === 'string') {
        expr = new U2.AST_SymbolRef({
          name: expr
        });
      }
      return new U2.AST_Call({
        args: [expr],
        expression: new U2.AST_Dot({
          property: 'test',
          expression: new U2.AST_RegExp({
            value: regexp
          })
        })
      });
    },
    isInt: function(num) {
      return typeof num === 'number' && !isNaN(num) && parseFloat(num) === parseInt(num, 10);
    },
    between: function(val, min, max, comment) {
      var pos, str, tmpl;
      if (min === max) {
        if (typeof min === 'number') {
          min = new U2.AST_Number({
            value: min
          });
        }
        return exports.comment(comment, new U2.AST_Binary({
          left: val,
          operator: '===',
          right: min
        }));
      }
      if (min > max) {
        return exports.comment(comment, new U2.AST_False);
      }
      if (exports.isInt(min) && exports.isInt(max) && max - min < 32) {
        comment || (comment = min + " <= value && value <= " + max);
        tmpl = "0123456789abcdefghijklmnopqrstuvwxyz";
        str = max < tmpl.length ? tmpl.substr(min, max - min + 1) : tmpl.substr(0, max - min + 1);
        pos = min === 0 ? val : new U2.AST_Binary({
          left: val,
          operator: '-',
          right: new U2.AST_Number({
            value: min
          })
        });
        return exports.comment(comment, new U2.AST_Binary({
          left: new U2.AST_Call({
            expression: new U2.AST_Dot({
              expression: new U2.AST_String({
                value: str
              }),
              property: 'charCodeAt'
            }),
            args: [pos]
          }),
          operator: '>',
          right: new U2.AST_Number({
            value: 0
          })
        }));
      }
      if (typeof min === 'number') {
        min = new U2.AST_Number({
          value: min
        });
      }
      if (typeof max === 'number') {
        max = new U2.AST_Number({
          value: max
        });
      }
      return exports.comment(comment, new U2.AST_Call({
        args: [val, min, max],
        expression: new U2.AST_Function({
          argnames: [
            new U2.AST_SymbolFunarg({
              name: 'value'
            }), new U2.AST_SymbolFunarg({
              name: 'min'
            }), new U2.AST_SymbolFunarg({
              name: 'max'
            })
          ],
          body: [
            new U2.AST_Return({
              value: new U2.AST_Binary({
                left: new U2.AST_Binary({
                  left: new U2.AST_SymbolRef({
                    name: 'min'
                  }),
                  operator: '<=',
                  right: new U2.AST_SymbolRef({
                    name: 'value'
                  })
                }),
                operator: '&&',
                right: new U2.AST_Binary({
                  left: new U2.AST_SymbolRef({
                    name: 'value'
                  }),
                  operator: '<=',
                  right: new U2.AST_SymbolRef({
                    name: 'max'
                  })
                })
              })
            })
          ]
        })
      }));
    },
    parseIp: function(ip) {
      var addr;
      if (ip.charCodeAt(0) === '['.charCodeAt(0)) {
        ip = ip.substr(1, ip.length - 2);
      }
      addr = new IP.v4.Address(ip);
      if (!addr.isValid()) {
        addr = new IP.v6.Address(ip);
        if (!addr.isValid()) {
          return null;
        }
      }
      return addr;
    },
    normalizeIp: function(addr) {
      var ref1;
      return ((ref1 = addr.correctForm) != null ? ref1 : addr.canonicalForm).call(addr);
    },
    ipv6Max: new IP.v6.Address('::/0').endAddress().canonicalForm(),
    localHosts: ["127.0.0.1", "[::1]", "localhost"],
    getWeekdayList: function(condition) {
      var i, j, k, results, results1;
      if (condition.days) {
        results = [];
        for (i = j = 0; j < 7; i = ++j) {
          results.push(condition.days.charCodeAt(i) > 64);
        }
        return results;
      } else {
        results1 = [];
        for (i = k = 0; k < 7; i = ++k) {
          results1.push((condition.startDay <= i && i <= condition.endDay));
        }
        return results1;
      }
    },
    _condCache: new AttachedCache(function(condition) {
      var result, tag;
      tag = exports._handler(condition.conditionType).tag;
      result = tag ? tag.apply(exports, arguments) : exports.str(condition);
      return condition.conditionType + '$' + result;
    }),
    _setProp: function(obj, prop, value) {
      if (!Object.prototype.hasOwnProperty.call(obj, prop)) {
        Object.defineProperty(obj, prop, {
          writable: true
        });
      }
      return obj[prop] = value;
    },
    _handler: function(conditionType) {
      var handler;
      if (typeof conditionType !== 'string') {
        conditionType = conditionType.conditionType;
      }
      handler = exports._conditionTypes[conditionType];
      if (handler == null) {
        throw new Error("Unknown condition type: " + conditionType);
      }
      return handler;
    },
    _conditionTypes: {
      'TrueCondition': {
        abbrs: ['True'],
        analyze: function(condition) {
          return null;
        },
        match: function() {
          return true;
        },
        compile: function(condition) {
          return new U2.AST_True;
        },
        str: function(condition) {
          return '';
        },
        fromStr: function(str, condition) {
          return condition;
        }
      },
      'FalseCondition': {
        abbrs: ['False', 'Disabled'],
        analyze: function(condition) {
          return null;
        },
        match: function() {
          return false;
        },
        compile: function(condition) {
          return new U2.AST_False;
        },
        fromStr: function(str, condition) {
          if (str.length > 0) {
            condition.pattern = str;
          }
          return condition;
        }
      },
      'UrlRegexCondition': {
        abbrs: ['UR', 'URegex', 'UrlR', 'UrlRegex'],
        analyze: function(condition) {
          return this.safeRegex(escapeSlash(condition.pattern));
        },
        match: function(condition, request, cache) {
          return cache.analyzed.test(request.url);
        },
        compile: function(condition, cache) {
          return this.regTest('url', cache.analyzed);
        }
      },
      'UrlWildcardCondition': {
        abbrs: ['U', 'UW', 'Url', 'UrlW', 'UWild', 'UWildcard', 'UrlWild', 'UrlWildcard'],
        analyze: function(condition) {
          var parts, pattern;
          parts = (function() {
            var j, len, ref1, results;
            ref1 = condition.pattern.split('|');
            results = [];
            for (j = 0, len = ref1.length; j < len; j++) {
              pattern = ref1[j];
              if (pattern) {
                results.push(shExp2RegExp(pattern, {
                  trimAsterisk: true
                }));
              }
            }
            return results;
          })();
          return this.safeRegex(parts.join('|'));
        },
        match: function(condition, request, cache) {
          return cache.analyzed.test(request.url);
        },
        compile: function(condition, cache) {
          return this.regTest('url', cache.analyzed);
        }
      },
      'HostRegexCondition': {
        abbrs: ['R', 'HR', 'Regex', 'HostR', 'HRegex', 'HostRegex'],
        analyze: function(condition) {
          return this.safeRegex(escapeSlash(condition.pattern));
        },
        match: function(condition, request, cache) {
          return cache.analyzed.test(request.host);
        },
        compile: function(condition, cache) {
          return this.regTest('host', cache.analyzed);
        }
      },
      'HostWildcardCondition': {
        abbrs: ['', 'H', 'W', 'HW', 'Wild', 'Wildcard', 'Host', 'HostW', 'HWild', 'HWildcard', 'HostWild', 'HostWildcard'],
        analyze: function(condition) {
          var parts, pattern;
          parts = (function() {
            var j, len, ref1, results;
            ref1 = condition.pattern.split('|');
            results = [];
            for (j = 0, len = ref1.length; j < len; j++) {
              pattern = ref1[j];
              if (!(pattern)) {
                continue;
              }
              if (pattern.charCodeAt(0) === '.'.charCodeAt(0)) {
                pattern = '*' + pattern;
              }
              if (pattern.indexOf('**.') === 0) {
                results.push(shExp2RegExp(pattern.substring(1), {
                  trimAsterisk: true
                }));
              } else if (pattern.indexOf('*.') === 0) {
                results.push(shExp2RegExp(pattern.substring(2), {
                  trimAsterisk: false
                }).replace(/./, '(?:^|\\.)').replace(/\.\*\$$/, ''));
              } else {
                results.push(shExp2RegExp(pattern, {
                  trimAsterisk: true
                }));
              }
            }
            return results;
          })();
          return this.safeRegex(parts.join('|'));
        },
        match: function(condition, request, cache) {
          return cache.analyzed.test(request.host);
        },
        compile: function(condition, cache) {
          return this.regTest('host', cache.analyzed);
        }
      },
      'BypassCondition': {
        abbrs: ['B', 'Bypass'],
        analyze: function(condition) {
          var addr, cache, matchPort, parts, pos, prefixLen, ref1, scheme, server, serverIp, serverRegex;
          cache = {
            host: null,
            ip: null,
            scheme: null,
            url: null,
            normalizedPattern: ''
          };
          server = condition.pattern;
          if (server === '<local>') {
            cache.host = server;
            return cache;
          }
          parts = server.split('://');
          if (parts.length > 1) {
            cache.scheme = parts[0];
            cache.normalizedPattern = cache.scheme + '://';
            server = parts[1];
          }
          parts = server.split('/');
          if (parts.length > 1) {
            addr = this.parseIp(parts[0]);
            prefixLen = parseInt(parts[1]);
            if (addr && !isNaN(prefixLen)) {
              cache.ip = {
                conditionType: 'IpCondition',
                ip: this.normalizeIp(addr),
                prefixLength: prefixLen
              };
              cache.normalizedPattern += cache.ip.ip + '/' + cache.ip.prefixLength;
              return cache;
            }
          }
          serverIp = this.parseIp(server);
          if (serverIp == null) {
            pos = server.lastIndexOf(':');
            if (pos >= 0) {
              matchPort = server.substring(pos + 1);
              server = server.substring(0, pos);
            }
            serverIp = this.parseIp(server);
          }
          if (serverIp != null) {
            server = this.normalizeIp(serverIp);
            if (serverIp.v4) {
              cache.normalizedPattern += server;
            } else {
              cache.normalizedPattern += '[' + server + ']';
            }
          } else {
            if (server.charCodeAt(0) === '.'.charCodeAt(0)) {
              server = '*' + server;
            }
            cache.normalizedPattern = server;
          }
          if (matchPort) {
            cache.port = matchPort;
            cache.normalizedPattern += ':' + cache.port;
            if ((serverIp != null) && !serverIp.v4) {
              server = '[' + server + ']';
            }
            serverRegex = shExp2RegExp(server);
            serverRegex = serverRegex.substring(1, serverRegex.length - 1);
            scheme = (ref1 = cache.scheme) != null ? ref1 : '[^:]+';
            cache.url = this.safeRegex('^' + scheme + ':\\/\\/' + serverRegex + ':' + matchPort + '\\/');
          } else if (server !== '*') {
            serverRegex = shExp2RegExp(server, {
              trimAsterisk: true
            });
            cache.host = this.safeRegex(serverRegex);
          }
          return cache;
        },
        match: function(condition, request, cache) {
          cache = cache.analyzed;
          if ((cache.scheme != null) && cache.scheme !== request.scheme) {
            return false;
          }
          if ((cache.ip != null) && !this.match(cache.ip, request)) {
            return false;
          }
          if (cache.host != null) {
            if (cache.host === '<local>') {
              return request.host === '127.0.0.1' || request.host === '::1' || request.host.indexOf('.') < 0;
            } else {
              if (!cache.host.test(request.host)) {
                return false;
              }
            }
          }
          if ((cache.url != null) && !cache.url.test(request.url)) {
            return false;
          }
          return true;
        },
        str: function(condition) {
          var analyze, cache;
          analyze = this._handler(condition).analyze;
          cache = analyze.call(exports, condition);
          if (cache.normalizedPattern) {
            return cache.normalizedPattern;
          } else {
            return condition.pattern;
          }
        },
        compile: function(condition, cache) {
          var conditions, hostEquals;
          cache = cache.analyzed;
          if (cache.url != null) {
            return this.regTest('url', cache.url);
          }
          conditions = [];
          if (cache.host === '<local>') {
            hostEquals = function(host) {
              return new U2.AST_Binary({
                left: new U2.AST_SymbolRef({
                  name: 'host'
                }),
                operator: '===',
                right: new U2.AST_String({
                  value: host
                })
              });
            };
            return new U2.AST_Binary({
              left: new U2.AST_Binary({
                left: hostEquals('127.0.0.1'),
                operator: '||',
                right: hostEquals('::1')
              }),
              operator: '||',
              right: new U2.AST_Binary({
                left: new U2.AST_Call({
                  expression: new U2.AST_Dot({
                    expression: new U2.AST_SymbolRef({
                      name: 'host'
                    }),
                    property: 'indexOf'
                  }),
                  args: [
                    new U2.AST_String({
                      value: '.'
                    })
                  ]
                }),
                operator: '<',
                right: new U2.AST_Number({
                  value: 0
                })
              })
            });
          }
          if (cache.scheme != null) {
            conditions.push(new U2.AST_Binary({
              left: new U2.AST_SymbolRef({
                name: 'scheme'
              }),
              operator: '===',
              right: new U2.AST_String({
                value: cache.scheme
              })
            }));
          }
          if (cache.host != null) {
            conditions.push(this.regTest('host', cache.host));
          } else if (cache.ip != null) {
            conditions.push(this.compile(cache.ip));
          }
          switch (conditions.length) {
            case 0:
              return new U2.AST_True;
            case 1:
              return conditions[0];
            case 2:
              return new U2.AST_Binary({
                left: conditions[0],
                operator: '&&',
                right: conditions[1]
              });
          }
        }
      },
      'KeywordCondition': {
        abbrs: ['K', 'KW', 'Keyword'],
        analyze: function(condition) {
          return null;
        },
        match: function(condition, request) {
          return request.scheme === 'http' && request.url.indexOf(condition.pattern) >= 0;
        },
        compile: function(condition) {
          return new U2.AST_Binary({
            left: new U2.AST_Binary({
              left: new U2.AST_SymbolRef({
                name: 'scheme'
              }),
              operator: '===',
              right: new U2.AST_String({
                value: 'http'
              })
            }),
            operator: '&&',
            right: new U2.AST_Binary({
              left: new U2.AST_Call({
                expression: new U2.AST_Dot({
                  expression: new U2.AST_SymbolRef({
                    name: 'url'
                  }),
                  property: 'indexOf'
                }),
                args: [
                  new U2.AST_String({
                    value: condition.pattern
                  })
                ]
              }),
              operator: '>=',
              right: new U2.AST_Number({
                value: 0
              })
            })
          });
        }
      },
      'IpCondition': {
        abbrs: ['Ip'],
        analyze: function(condition) {
          var addr, cache, ip, mask;
          cache = {
            addr: null,
            normalized: null
          };
          ip = condition.ip;
          if (ip.charCodeAt(0) === '['.charCodeAt(0)) {
            ip = ip.substr(1, ip.length - 2);
          }
          addr = ip + '/' + condition.prefixLength;
          cache.addr = this.parseIp(addr);
          if (cache.addr == null) {
            throw new Error("Invalid IP address " + addr);
          }
          cache.normalized = this.normalizeIp(cache.addr);
          mask = cache.addr.v4 ? new IP.v4.Address('255.255.255.255/' + cache.addr.subnetMask) : new IP.v6.Address(this.ipv6Max + '/' + cache.addr.subnetMask);
          cache.mask = this.normalizeIp(mask.startAddress());
          return cache;
        },
        match: function(condition, request, cache) {
          var addr;
          addr = this.parseIp(request.host);
          if (addr == null) {
            return false;
          }
          cache = cache.analyzed;
          if (addr.v4 !== cache.addr.v4) {
            return false;
          }
          return addr.isInSubnet(cache.addr);
        },
        compile: function(condition, cache) {
          var hostIsInNet, hostIsInNetEx, hostLooksLikeIp;
          cache = cache.analyzed;
          hostLooksLikeIp = cache.addr.v4 ? new U2.AST_Binary({
            left: new U2.AST_Sub({
              expression: new U2.AST_SymbolRef({
                name: 'host'
              }),
              property: new U2.AST_Binary({
                left: new U2.AST_Dot({
                  expression: new U2.AST_SymbolRef({
                    name: 'host'
                  }),
                  property: 'length'
                }),
                operator: '-',
                right: new U2.AST_Number({
                  value: 1
                })
              })
            }),
            operator: '>=',
            right: new U2.AST_Number({
              value: 0
            })
          }) : new U2.AST_Binary({
            left: new U2.AST_Call({
              expression: new U2.AST_Dot({
                expression: new U2.AST_SymbolRef({
                  name: 'host'
                }),
                property: 'indexOf'
              }),
              args: [
                new U2.AST_String({
                  value: ':'
                })
              ]
            }),
            operator: '>=',
            right: new U2.AST_Number({
              value: 0
            })
          });
          if (cache.addr.subnetMask === 0) {
            return hostLooksLikeIp;
          }
          hostIsInNet = new U2.AST_Call({
            expression: new U2.AST_SymbolRef({
              name: 'isInNet'
            }),
            args: [
              new U2.AST_SymbolRef({
                name: 'host'
              }), new U2.AST_String({
                value: cache.normalized
              }), new U2.AST_String({
                value: cache.mask
              })
            ]
          });
          if (!cache.addr.v4) {
            hostIsInNetEx = new U2.AST_Call({
              expression: new U2.AST_SymbolRef({
                name: 'isInNetEx'
              }),
              args: [
                new U2.AST_SymbolRef({
                  name: 'host'
                }), new U2.AST_String({
                  value: cache.normalized + cache.addr.subnet
                })
              ]
            });
            hostIsInNet = new U2.AST_Conditional({
              condition: new U2.AST_Binary({
                left: new U2.AST_UnaryPrefix({
                  operator: 'typeof',
                  expression: new U2.AST_SymbolRef({
                    name: 'isInNetEx'
                  })
                }),
                operator: '===',
                right: new U2.AST_String({
                  value: 'function'
                })
              }),
              consequent: hostIsInNetEx,
              alternative: hostIsInNet
            });
          }
          return new U2.AST_Binary({
            left: hostLooksLikeIp,
            operator: '&&',
            right: hostIsInNet
          });
        },
        str: function(condition) {
          return condition.ip + '/' + condition.prefixLength;
        },
        fromStr: function(str, condition) {
          var addr;
          addr = this.parseIp(str);
          if (addr != null) {
            condition.ip = addr.addressMinusSuffix;
            condition.prefixLength = addr.subnetMask;
          } else {
            condition.ip = '0.0.0.0';
            condition.prefixLength = 0;
          }
          return condition;
        }
      },
      'HostLevelsCondition': {
        abbrs: ['Lv', 'Level', 'Levels', 'HL', 'HLv', 'HLevel', 'HLevels', 'HostL', 'HostLv', 'HostLevel', 'HostLevels'],
        analyze: function(condition) {
          return '.'.charCodeAt(0);
        },
        match: function(condition, request, cache) {
          var dotCharCode, dotCount, i, j, ref1;
          dotCharCode = cache.analyzed;
          dotCount = 0;
          for (i = j = 0, ref1 = request.host.length; 0 <= ref1 ? j < ref1 : j > ref1; i = 0 <= ref1 ? ++j : --j) {
            if (request.host.charCodeAt(i) === dotCharCode) {
              dotCount++;
              if (dotCount > condition.maxValue) {
                return false;
              }
            }
          }
          return dotCount >= condition.minValue;
        },
        compile: function(condition) {
          var val;
          val = new U2.AST_Dot({
            property: 'length',
            expression: new U2.AST_Call({
              args: [
                new U2.AST_String({
                  value: '.'
                })
              ],
              expression: new U2.AST_Dot({
                expression: new U2.AST_SymbolRef({
                  name: 'host'
                }),
                property: 'split'
              })
            })
          });
          return this.between(val, condition.minValue + 1, condition.maxValue + 1, condition.minValue + " <= hostLevels <= " + condition.maxValue);
        },
        str: function(condition) {
          return condition.minValue + '~' + condition.maxValue;
        },
        fromStr: function(str, condition) {
          var maxValue, minValue, ref1;
          ref1 = str.split('~'), minValue = ref1[0], maxValue = ref1[1];
          condition.minValue = parseInt(minValue, 10);
          condition.maxValue = parseInt(maxValue, 10);
          if (!(condition.minValue > 0)) {
            condition.minValue = 1;
          }
          if (!(condition.maxValue > 0)) {
            condition.maxValue = 1;
          }
          return condition;
        }
      },
      'WeekdayCondition': {
        abbrs: ['WD', 'Week', 'Day', 'Weekday'],
        analyze: function(condition) {
          return null;
        },
        match: function(condition, request) {
          var day;
          day = new Date().getDay();
          if (condition.days) {
            return condition.days.charCodeAt(day) > 64;
          }
          return condition.startDay <= day && day <= condition.endDay;
        },
        compile: function(condition) {
          var getDay;
          getDay = new U2.AST_Call({
            args: [],
            expression: new U2.AST_Dot({
              property: 'getDay',
              expression: new U2.AST_New({
                args: [],
                expression: new U2.AST_SymbolRef({
                  name: 'Date'
                })
              })
            })
          });
          if (condition.days) {
            return new U2.AST_Binary({
              left: new U2.AST_Call({
                expression: new U2.AST_Dot({
                  expression: new U2.AST_String({
                    value: condition.days
                  }),
                  property: 'charCodeAt'
                }),
                args: [getDay]
              }),
              operator: '>',
              right: new U2.AST_Number({
                value: 64
              })
            });
          } else {
            return this.between(getDay, condition.startDay, condition.endDay);
          }
        },
        str: function(condition) {
          if (condition.days) {
            return condition.days;
          } else {
            return condition.startDay + '~' + condition.endDay;
          }
        },
        fromStr: function(str, condition) {
          var endDay, ref1, ref2, ref3, startDay;
          if (str.indexOf('~') < 0 && str.length === 7) {
            condition.days = str;
          } else {
            ref1 = str.split('~'), startDay = ref1[0], endDay = ref1[1];
            condition.startDay = parseInt(startDay, 10);
            condition.endDay = parseInt(endDay, 10);
            if (!((0 <= (ref2 = condition.startDay) && ref2 <= 6))) {
              condition.startDay = 0;
            }
            if (!((0 <= (ref3 = condition.endDay) && ref3 <= 6))) {
              condition.endDay = 0;
            }
          }
          return condition;
        }
      },
      'TimeCondition': {
        abbrs: ['T', 'Time', 'Hour'],
        analyze: function(condition) {
          return null;
        },
        match: function(condition, request) {
          var hour;
          hour = new Date().getHours();
          return condition.startHour <= hour && hour <= condition.endHour;
        },
        compile: function(condition) {
          var val;
          val = new U2.AST_Call({
            args: [],
            expression: new U2.AST_Dot({
              property: 'getHours',
              expression: new U2.AST_New({
                args: [],
                expression: new U2.AST_SymbolRef({
                  name: 'Date'
                })
              })
            })
          });
          return this.between(val, condition.startHour, condition.endHour);
        },
        str: function(condition) {
          return condition.startHour + '~' + condition.endHour;
        },
        fromStr: function(str, condition) {
          var endHour, ref1, ref2, ref3, startHour;
          ref1 = str.split('~'), startHour = ref1[0], endHour = ref1[1];
          condition.startHour = parseInt(startHour, 10);
          condition.endHour = parseInt(endHour, 10);
          if (!((0 <= (ref2 = condition.startHour) && ref2 < 24))) {
            condition.startHour = 0;
          }
          if (!((0 <= (ref3 = condition.endHour) && ref3 < 24))) {
            condition.endHour = 0;
          }
          return condition;
        }
      }
    }
  };
  
  
  },{"./shexp_utils":65,"./utils":66,"ip-address":5,"uglify-js":67,"url":60}],62:[function(require,module,exports){
  var Profiles, U2;
  
  U2 = require('uglify-js');
  
  Profiles = require('./profiles');
  
  module.exports = {
    ascii: function(str) {
      return str.replace(/[\u0080-\uffff]/g, function(char) {
        var _, hex, i, ref, result;
        hex = char.charCodeAt(0).toString(16);
        result = '\\u';
        for (_ = i = ref = hex.length; ref <= 4 ? i < 4 : i > 4; _ = ref <= 4 ? ++i : --i) {
          result += '0';
        }
        result += hex;
        return result;
      });
    },
    compress: function(ast) {
      var compressed_ast, compressor;
      ast.figure_out_scope();
      compressor = U2.Compressor({
        warnings: false,
        keep_fargs: true
      }, {
        if_return: false
      });
      compressed_ast = ast.transform(compressor);
      compressed_ast.figure_out_scope();
      compressed_ast.compute_char_frequency();
      compressed_ast.mangle_names();
      return compressed_ast;
    },
    script: function(options, profile, args) {
      var factory, key, name, p, profiles, refs;
      if (typeof profile === 'string') {
        profile = Profiles.byName(profile, options);
      }
      refs = Profiles.allReferenceSet(profile, options, {
        profileNotFound: args != null ? args.profileNotFound : void 0
      });
      profiles = new U2.AST_Object({
        properties: (function() {
          var results;
          results = [];
          for (key in refs) {
            name = refs[key];
            if (!(key !== '+direct')) {
              continue;
            }
            p = typeof profile === 'object' && profile.name === name ? profile : Profiles.byName(name, options);
            if (p == null) {
              p = Profiles.profileNotFound(name, args != null ? args.profileNotFound : void 0);
            }
            results.push(new U2.AST_ObjectKeyVal({
              key: key,
              value: Profiles.compile(p)
            }));
          }
          return results;
        })()
      });
      factory = new U2.AST_Function({
        argnames: [
          new U2.AST_SymbolFunarg({
            name: 'init'
          }), new U2.AST_SymbolFunarg({
            name: 'profiles'
          })
        ],
        body: [
          new U2.AST_Return({
            value: new U2.AST_Function({
              argnames: [
                new U2.AST_SymbolFunarg({
                  name: 'url'
                }), new U2.AST_SymbolFunarg({
                  name: 'host'
                })
              ],
              body: [
                new U2.AST_Directive({
                  value: 'use strict'
                }), new U2.AST_Var({
                  definitions: [
                    new U2.AST_VarDef({
                      name: new U2.AST_SymbolVar({
                        name: 'result'
                      }),
                      value: new U2.AST_SymbolRef({
                        name: 'init'
                      })
                    }), new U2.AST_VarDef({
                      name: new U2.AST_SymbolVar({
                        name: 'scheme'
                      }),
                      value: new U2.AST_Call({
                        expression: new U2.AST_Dot({
                          expression: new U2.AST_SymbolRef({
                            name: 'url'
                          }),
                          property: 'substr'
                        }),
                        args: [
                          new U2.AST_Number({
                            value: 0
                          }), new U2.AST_Call({
                            expression: new U2.AST_Dot({
                              expression: new U2.AST_SymbolRef({
                                name: 'url'
                              }),
                              property: 'indexOf'
                            }),
                            args: [
                              new U2.AST_String({
                                value: ':'
                              })
                            ]
                          })
                        ]
                      })
                    })
                  ]
                }), new U2.AST_Do({
                  body: new U2.AST_BlockStatement({
                    body: [
                      new U2.AST_SimpleStatement({
                        body: new U2.AST_Assign({
                          left: new U2.AST_SymbolRef({
                            name: 'result'
                          }),
                          operator: '=',
                          right: new U2.AST_Sub({
                            expression: new U2.AST_SymbolRef({
                              name: 'profiles'
                            }),
                            property: new U2.AST_SymbolRef({
                              name: 'result'
                            })
                          })
                        })
                      }), new U2.AST_If({
                        condition: new U2.AST_Binary({
                          left: new U2.AST_UnaryPrefix({
                            operator: 'typeof',
                            expression: new U2.AST_SymbolRef({
                              name: 'result'
                            })
                          }),
                          operator: '===',
                          right: new U2.AST_String({
                            value: 'function'
                          })
                        }),
                        body: new U2.AST_SimpleStatement({
                          body: new U2.AST_Assign({
                            left: new U2.AST_SymbolRef({
                              name: 'result'
                            }),
                            operator: '=',
                            right: new U2.AST_Call({
                              expression: new U2.AST_SymbolRef({
                                name: 'result'
                              }),
                              args: [
                                new U2.AST_SymbolRef({
                                  name: 'url'
                                }), new U2.AST_SymbolRef({
                                  name: 'host'
                                }), new U2.AST_SymbolRef({
                                  name: 'scheme'
                                })
                              ]
                            })
                          })
                        })
                      })
                    ]
                  }),
                  condition: new U2.AST_Binary({
                    left: new U2.AST_Binary({
                      left: new U2.AST_UnaryPrefix({
                        operator: 'typeof',
                        expression: new U2.AST_SymbolRef({
                          name: 'result'
                        })
                      }),
                      operator: '!==',
                      right: new U2.AST_String({
                        value: 'string'
                      })
                    }),
                    operator: '||',
                    right: new U2.AST_Binary({
                      left: new U2.AST_Call({
                        expression: new U2.AST_Dot({
                          expression: new U2.AST_SymbolRef({
                            name: 'result'
                          }),
                          property: 'charCodeAt'
                        }),
                        args: [
                          new U2.AST_Number({
                            value: 0
                          })
                        ]
                      }),
                      operator: '===',
                      right: new U2.AST_Number({
                        value: '+'.charCodeAt(0)
                      })
                    })
                  })
                }), new U2.AST_Return({
                  value: new U2.AST_SymbolRef({
                    name: 'result'
                  })
                })
              ]
            })
          })
        ]
      });
      return new U2.AST_Toplevel({
        body: [
          new U2.AST_Var({
            definitions: [
              new U2.AST_VarDef({
                name: new U2.AST_SymbolVar({
                  name: 'FindProxyForURL'
                }),
                value: new U2.AST_Call({
                  expression: factory,
                  args: [Profiles.profileResult(profile.name), profiles]
                })
              })
            ]
          })
        ]
      });
    }
  };
  
  
  },{"./profiles":63,"uglify-js":67}],63:[function(require,module,exports){
  var AST_Raw, AttachedCache, Conditions, Revision, RuleList, ShexpUtils, U2, exports, ref1,
    extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
    hasProp = {}.hasOwnProperty;
  
  U2 = require('uglify-js');
  
  ShexpUtils = require('./shexp_utils');
  
  Conditions = require('./conditions');
  
  RuleList = require('./rule_list');
  
  ref1 = require('./utils'), AttachedCache = ref1.AttachedCache, Revision = ref1.Revision;
  
  AST_Raw = (function(superClass) {
    extend(AST_Raw, superClass);
  
    function AST_Raw(raw) {
      U2.AST_SymbolRef.call(this, {
        name: raw
      });
      this.aborts = function() {
        return false;
      };
    }
  
    return AST_Raw;
  
  })(U2.AST_SymbolRef);
  
  module.exports = exports = {
    builtinProfiles: {
      '+direct': {
        name: 'direct',
        profileType: 'DirectProfile',
        color: '#aaaaaa',
        builtin: true
      },
      '+system': {
        name: 'system',
        profileType: 'SystemProfile',
        color: '#000000',
        builtin: true
      }
    },
    schemes: [
      {
        scheme: 'http',
        prop: 'proxyForHttp'
      }, {
        scheme: 'https',
        prop: 'proxyForHttps'
      }, {
        scheme: 'ftp',
        prop: 'proxyForFtp'
      }, {
        scheme: '',
        prop: 'fallbackProxy'
      }
    ],
    pacProtocols: {
      'http': 'PROXY',
      'https': 'HTTPS',
      'socks4': 'SOCKS',
      'socks5': 'SOCKS5'
    },
    formatByType: {
      'SwitchyRuleListProfile': 'Switchy',
      'AutoProxyRuleListProfile': 'AutoProxy'
    },
    ruleListFormats: ['Switchy', 'AutoProxy'],
    parseHostPort: function(str, scheme) {
      var host, port, sep;
      sep = str.lastIndexOf(':');
      if (sep < 0) {
        return;
      }
      port = parseInt(str.substr(sep + 1)) || 80;
      host = str.substr(0, sep);
      if (!host) {
        return;
      }
      return {
        scheme: scheme,
        host: host,
        port: port
      };
    },
    pacResult: function(proxy) {
      if (proxy) {
        if (proxy.scheme === 'socks5') {
          return "SOCKS5 " + proxy.host + ":" + proxy.port + "; SOCKS " + proxy.host + ":" + proxy.port;
        } else {
          return exports.pacProtocols[proxy.scheme] + " " + proxy.host + ":" + proxy.port;
        }
      } else {
        return 'DIRECT';
      }
    },
    isFileUrl: function(url) {
      return !!((url != null ? url.substr(0, 5).toUpperCase() : void 0) === 'FILE:');
    },
    nameAsKey: function(profileName) {
      if (typeof profileName !== 'string') {
        profileName = profileName.name;
      }
      return '+' + profileName;
    },
    byName: function(profileName, options) {
      var key, ref2;
      if (typeof profileName === 'string') {
        key = exports.nameAsKey(profileName);
        profileName = (ref2 = exports.builtinProfiles[key]) != null ? ref2 : options[key];
      }
      return profileName;
    },
    byKey: function(key, options) {
      var ref2;
      if (typeof key === 'string') {
        key = (ref2 = exports.builtinProfiles[key]) != null ? ref2 : options[key];
      }
      return key;
    },
    each: function(options, callback) {
      var charCodePlus, key, profile, ref2, results;
      charCodePlus = '+'.charCodeAt(0);
      for (key in options) {
        profile = options[key];
        if (key.charCodeAt(0) === charCodePlus) {
          callback(key, profile);
        }
      }
      ref2 = exports.builtinProfiles;
      results = [];
      for (key in ref2) {
        profile = ref2[key];
        if (key.charCodeAt(0) === charCodePlus) {
          results.push(callback(key, profile));
        } else {
          results.push(void 0);
        }
      }
      return results;
    },
    profileResult: function(profileName) {
      var key;
      key = exports.nameAsKey(profileName);
      if (key === '+direct') {
        key = exports.pacResult();
      }
      return new U2.AST_String({
        value: key
      });
    },
    isIncludable: function(profile) {
      var includable;
      includable = exports._handler(profile).includable;
      if (typeof includable === 'function') {
        includable = includable.call(exports, profile);
      }
      return !!includable;
    },
    isInclusive: function(profile) {
      return !!exports._handler(profile).inclusive;
    },
    updateUrl: function(profile) {
      var ref2;
      return (ref2 = exports._handler(profile).updateUrl) != null ? ref2.call(exports, profile) : void 0;
    },
    updateContentTypeHints: function(profile) {
      var ref2;
      return (ref2 = exports._handler(profile).updateContentTypeHints) != null ? ref2.call(exports, profile) : void 0;
    },
    update: function(profile, data) {
      return exports._handler(profile).update.call(exports, profile, data);
    },
    tag: function(profile) {
      return exports._profileCache.tag(profile);
    },
    create: function(profile, opt_profileType) {
      var create;
      if (typeof profile === 'string') {
        profile = {
          name: profile,
          profileType: opt_profileType
        };
      } else if (opt_profileType) {
        profile.profileType = opt_profileType;
      }
      create = exports._handler(profile).create;
      if (!create) {
        return profile;
      }
      create.call(exports, profile);
      return profile;
    },
    updateRevision: function(profile, revision) {
      if (revision == null) {
        revision = Revision.fromTime();
      }
      return profile.revision = revision;
    },
    replaceRef: function(profile, fromName, toName) {
      var handler;
      if (!exports.isInclusive(profile)) {
        return false;
      }
      handler = exports._handler(profile);
      return handler.replaceRef.call(exports, profile, fromName, toName);
    },
    analyze: function(profile) {
      var analyze, cache, result;
      cache = exports._profileCache.get(profile, {});
      if (!Object.prototype.hasOwnProperty.call(cache, 'analyzed')) {
        analyze = exports._handler(profile).analyze;
        result = analyze != null ? analyze.call(exports, profile) : void 0;
        cache.analyzed = result;
      }
      return cache;
    },
    dropCache: function(profile) {
      return exports._profileCache.drop(profile);
    },
    directReferenceSet: function(profile) {
      var cache, handler;
      if (!exports.isInclusive(profile)) {
        return {};
      }
      cache = exports._profileCache.get(profile, {});
      if (cache.directReferenceSet) {
        return cache.directReferenceSet;
      }
      handler = exports._handler(profile);
      return cache.directReferenceSet = handler.directReferenceSet.call(exports, profile);
    },
    profileNotFound: function(name, action) {
      if (action == null) {
        throw new Error("Profile " + name + " does not exist!");
      }
      if (typeof action === 'function') {
        action = action(name);
      }
      if (typeof action === 'object' && action.profileType) {
        return action;
      }
      switch (action) {
        case 'ignore':
          return null;
        case 'dumb':
          return exports.create({
            name: name,
            profileType: 'VirtualProfile',
            defaultProfileName: 'direct'
          });
      }
      throw action;
    },
    allReferenceSet: function(profile, options, opt_args) {
      var has_out, key, name, o_profile, ref2, result;
      o_profile = profile;
      profile = exports.byName(profile, options);
      if (profile == null) {
        profile = typeof exports.profileNotFound === "function" ? exports.profileNotFound(o_profile, opt_args.profileNotFound) : void 0;
      }
      if (opt_args == null) {
        opt_args = {};
      }
      has_out = opt_args.out != null;
      result = opt_args.out != null ? opt_args.out : opt_args.out = {};
      if (profile) {
        result[exports.nameAsKey(profile.name)] = profile.name;
        ref2 = exports.directReferenceSet(profile);
        for (key in ref2) {
          name = ref2[key];
          exports.allReferenceSet(name, options, opt_args);
        }
      }
      if (!has_out) {
        delete opt_args.out;
      }
      return result;
    },
    referencedBySet: function(profile, options, opt_args) {
      var has_out, profileKey, result;
      profileKey = exports.nameAsKey(profile);
      if (opt_args == null) {
        opt_args = {};
      }
      has_out = opt_args.out != null;
      result = opt_args.out != null ? opt_args.out : opt_args.out = {};
      exports.each(options, function(key, prof) {
        if (exports.directReferenceSet(prof)[profileKey]) {
          result[key] = prof.name;
          return exports.referencedBySet(prof, options, opt_args);
        }
      });
      if (!has_out) {
        delete opt_args.out;
      }
      return result;
    },
    validResultProfilesFor: function(profile, options) {
      var profileKey, ref, result;
      profile = exports.byName(profile, options);
      if (!exports.isInclusive(profile)) {
        return [];
      }
      profileKey = exports.nameAsKey(profile);
      ref = exports.referencedBySet(profile, options);
      ref[profileKey] = profileKey;
      result = [];
      exports.each(options, function(key, prof) {
        if (!ref[key] && exports.isIncludable(prof)) {
          return result.push(prof);
        }
      });
      return result;
    },
    match: function(profile, request, opt_profileType) {
      var cache, match;
      if (opt_profileType == null) {
        opt_profileType = profile.profileType;
      }
      cache = exports.analyze(profile);
      match = exports._handler(opt_profileType).match;
      return match != null ? match.call(exports, profile, request, cache) : void 0;
    },
    compile: function(profile, opt_profileType) {
      var cache, handler;
      if (opt_profileType == null) {
        opt_profileType = profile.profileType;
      }
      cache = exports.analyze(profile);
      if (cache.compiled) {
        return cache.compiled;
      }
      handler = exports._handler(opt_profileType);
      return cache.compiled = handler.compile.call(exports, profile, cache);
    },
    _profileCache: new AttachedCache(function(profile) {
      return profile.revision;
    }),
    _handler: function(profileType) {
      var handler;
      if (typeof profileType !== 'string') {
        profileType = profileType.profileType;
      }
      handler = profileType;
      while (typeof handler === 'string') {
        handler = exports._profileTypes[handler];
      }
      if (handler == null) {
        throw new Error("Unknown profile type: " + profileType);
      }
      return handler;
    },
    _profileTypes: {
      'SystemProfile': {
        compile: function(profile) {
          throw new Error("SystemProfile cannot be used in PAC scripts");
        }
      },
      'DirectProfile': {
        includable: true,
        compile: function(profile) {
          return new U2.AST_String({
            value: this.pacResult()
          });
        }
      },
      'FixedProfile': {
        includable: true,
        create: function(profile) {
          return profile.bypassList != null ? profile.bypassList : profile.bypassList = [
            {
              conditionType: 'BypassCondition',
              pattern: '127.0.0.1'
            }, {
              conditionType: 'BypassCondition',
              pattern: '[::1]'
            }, {
              conditionType: 'BypassCondition',
              pattern: 'localhost'
            }
          ];
        },
        match: function(profile, request) {
          var cond, i, j, len, len1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, ref9, s;
          if (profile.bypassList) {
            ref2 = profile.bypassList;
            for (i = 0, len = ref2.length; i < len; i++) {
              cond = ref2[i];
              if (Conditions.match(cond, request)) {
                return [
                  this.pacResult(), cond, {
                    scheme: 'direct'
                  }, void 0
                ];
              }
            }
          }
          ref3 = this.schemes;
          for (j = 0, len1 = ref3.length; j < len1; j++) {
            s = ref3[j];
            if (s.scheme === request.scheme && profile[s.prop]) {
              return [this.pacResult(profile[s.prop]), s.scheme, profile[s.prop], (ref4 = (ref5 = profile.auth) != null ? ref5[s.prop] : void 0) != null ? ref4 : (ref6 = profile.auth) != null ? ref6['all'] : void 0];
            }
          }
          return [this.pacResult(profile.fallbackProxy), '', profile.fallbackProxy, (ref7 = (ref8 = profile.auth) != null ? ref8.fallbackProxy : void 0) != null ? ref7 : (ref9 = profile.auth) != null ? ref9['all'] : void 0];
        },
        compile: function(profile) {
          var body, cond, condition, conditions, i, len, ref2, ret, s;
          if ((!profile.bypassList || !profile.fallbackProxy) && !profile.proxyForHttp && !profile.proxyForHttps && !profile.proxyForFtp) {
            return new U2.AST_String({
              value: this.pacResult(profile.fallbackProxy)
            });
          }
          body = [
            new U2.AST_Directive({
              value: 'use strict'
            })
          ];
          if (profile.bypassList && profile.bypassList.length) {
            conditions = null;
            ref2 = profile.bypassList;
            for (i = 0, len = ref2.length; i < len; i++) {
              cond = ref2[i];
              condition = Conditions.compile(cond);
              if (conditions != null) {
                conditions = new U2.AST_Binary({
                  left: conditions,
                  operator: '||',
                  right: condition
                });
              } else {
                conditions = condition;
              }
            }
            body.push(new U2.AST_If({
              condition: conditions,
              body: new U2.AST_Return({
                value: new U2.AST_String({
                  value: this.pacResult()
                })
              })
            }));
          }
          if (!profile.proxyForHttp && !profile.proxyForHttps && !profile.proxyForFtp) {
            body.push(new U2.AST_Return({
              value: new U2.AST_String({
                value: this.pacResult(profile.fallbackProxy)
              })
            }));
          } else {
            body.push(new U2.AST_Switch({
              expression: new U2.AST_SymbolRef({
                name: 'scheme'
              }),
              body: (function() {
                var j, len1, ref3, results;
                ref3 = this.schemes;
                results = [];
                for (j = 0, len1 = ref3.length; j < len1; j++) {
                  s = ref3[j];
                  if (!(!s.scheme || profile[s.prop])) {
                    continue;
                  }
                  ret = [
                    new U2.AST_Return({
                      value: new U2.AST_String({
                        value: this.pacResult(profile[s.prop])
                      })
                    })
                  ];
                  if (s.scheme) {
                    results.push(new U2.AST_Case({
                      expression: new U2.AST_String({
                        value: s.scheme
                      }),
                      body: ret
                    }));
                  } else {
                    results.push(new U2.AST_Default({
                      body: ret
                    }));
                  }
                }
                return results;
              }).call(this)
            }));
          }
          return new U2.AST_Function({
            argnames: [
              new U2.AST_SymbolFunarg({
                name: 'url'
              }), new U2.AST_SymbolFunarg({
                name: 'host'
              }), new U2.AST_SymbolFunarg({
                name: 'scheme'
              })
            ],
            body: body
          });
        }
      },
      'PacProfile': {
        includable: function(profile) {
          return !this.isFileUrl(profile.pacUrl);
        },
        create: function(profile) {
          return profile.pacScript != null ? profile.pacScript : profile.pacScript = 'function FindProxyForURL(url, host) {\n  return "DIRECT";\n}';
        },
        compile: function(profile) {
          return new U2.AST_Call({
            args: [new U2.AST_This],
            expression: new U2.AST_Dot({
              property: 'call',
              expression: new U2.AST_Function({
                argnames: [],
                body: [
                  new AST_Raw(';\n' + profile.pacScript + '\n\n/* End of PAC */;'), new U2.AST_Return({
                    value: new U2.AST_SymbolRef({
                      name: 'FindProxyForURL'
                    })
                  })
                ]
              })
            })
          });
        },
        updateUrl: function(profile) {
          if (this.isFileUrl(profile.pacUrl)) {
            return void 0;
          } else {
            return profile.pacUrl;
          }
        },
        updateContentTypeHints: function() {
          return ['!text/html', '!application/xhtml+xml', 'application/x-ns-proxy-autoconfig', 'application/x-javascript-config'];
        },
        update: function(profile, data) {
          if (profile.pacScript === data) {
            return false;
          }
          profile.pacScript = data;
          return true;
        }
      },
      'AutoDetectProfile': 'PacProfile',
      'SwitchProfile': {
        includable: true,
        inclusive: true,
        create: function(profile) {
          if (profile.defaultProfileName == null) {
            profile.defaultProfileName = 'direct';
          }
          return profile.rules != null ? profile.rules : profile.rules = [];
        },
        directReferenceSet: function(profile) {
          var i, len, ref2, refs, rule;
          refs = {};
          refs[exports.nameAsKey(profile.defaultProfileName)] = profile.defaultProfileName;
          ref2 = profile.rules;
          for (i = 0, len = ref2.length; i < len; i++) {
            rule = ref2[i];
            refs[exports.nameAsKey(rule.profileName)] = rule.profileName;
          }
          return refs;
        },
        analyze: function(profile) {
          return profile.rules;
        },
        replaceRef: function(profile, fromName, toName) {
          var changed, i, len, ref2, rule;
          changed = false;
          if (profile.defaultProfileName === fromName) {
            profile.defaultProfileName = toName;
            changed = true;
          }
          ref2 = profile.rules;
          for (i = 0, len = ref2.length; i < len; i++) {
            rule = ref2[i];
            if (rule.profileName === fromName) {
              rule.profileName = toName;
              changed = true;
            }
          }
          return changed;
        },
        match: function(profile, request, cache) {
          var i, len, ref2, rule;
          ref2 = cache.analyzed;
          for (i = 0, len = ref2.length; i < len; i++) {
            rule = ref2[i];
            if (Conditions.match(rule.condition, request)) {
              return rule;
            }
          }
          return [exports.nameAsKey(profile.defaultProfileName), null];
        },
        compile: function(profile, cache) {
          var body, i, len, rule, rules;
          rules = cache.analyzed;
          if (rules.length === 0) {
            return this.profileResult(profile.defaultProfileName);
          }
          body = [
            new U2.AST_Directive({
              value: 'use strict'
            })
          ];
          for (i = 0, len = rules.length; i < len; i++) {
            rule = rules[i];
            body.push(new U2.AST_If({
              condition: Conditions.compile(rule.condition),
              body: new U2.AST_Return({
                value: this.profileResult(rule.profileName)
              })
            }));
          }
          body.push(new U2.AST_Return({
            value: this.profileResult(profile.defaultProfileName)
          }));
          return new U2.AST_Function({
            argnames: [
              new U2.AST_SymbolFunarg({
                name: 'url'
              }), new U2.AST_SymbolFunarg({
                name: 'host'
              }), new U2.AST_SymbolFunarg({
                name: 'scheme'
              })
            ],
            body: body
          });
        }
      },
      'VirtualProfile': 'SwitchProfile',
      'RuleListProfile': {
        includable: true,
        inclusive: true,
        create: function(profile) {
          var ref2;
          if (profile.profileType == null) {
            profile.profileType = 'RuleListProfile';
          }
          if (profile.format == null) {
            profile.format = (ref2 = exports.formatByType[profile.profileType]) != null ? ref2 : 'Switchy';
          }
          if (profile.defaultProfileName == null) {
            profile.defaultProfileName = 'direct';
          }
          if (profile.matchProfileName == null) {
            profile.matchProfileName = 'direct';
          }
          return profile.ruleList != null ? profile.ruleList : profile.ruleList = '';
        },
        directReferenceSet: function(profile) {
          var i, len, name, ref2, ref3, refs;
          if (profile.ruleList != null) {
            refs = (ref2 = RuleList[profile.format]) != null ? typeof ref2.directReferenceSet === "function" ? ref2.directReferenceSet(profile) : void 0 : void 0;
            if (refs) {
              return refs;
            }
          }
          refs = {};
          ref3 = [profile.matchProfileName, profile.defaultProfileName];
          for (i = 0, len = ref3.length; i < len; i++) {
            name = ref3[i];
            refs[exports.nameAsKey(name)] = name;
          }
          return refs;
        },
        replaceRef: function(profile, fromName, toName) {
          var changed;
          changed = false;
          if (profile.defaultProfileName === fromName) {
            profile.defaultProfileName = toName;
            changed = true;
          }
          if (profile.matchProfileName === fromName) {
            profile.matchProfileName = toName;
            changed = true;
          }
          return changed;
        },
        analyze: function(profile) {
          var format, formatHandler, ref2, ref3, ruleList;
          format = (ref2 = profile.format) != null ? ref2 : exports.formatByType[profile.profileType];
          formatHandler = RuleList[format];
          if (!formatHandler) {
            throw new Error("Unsupported rule list format " + format + "!");
          }
          ruleList = ((ref3 = profile.ruleList) != null ? ref3.trim() : void 0) || '';
          if (formatHandler.preprocess != null) {
            ruleList = formatHandler.preprocess(ruleList);
          }
          return formatHandler.parse(ruleList, profile.matchProfileName, profile.defaultProfileName);
        },
        match: function(profile, request) {
          var result;
          return result = exports.match(profile, request, 'SwitchProfile');
        },
        compile: function(profile) {
          return exports.compile(profile, 'SwitchProfile');
        },
        updateUrl: function(profile) {
          return profile.sourceUrl;
        },
        updateContentTypeHints: function() {
          return ['!text/html', '!application/xhtml+xml', 'text/plain', '*'];
        },
        update: function(profile, data) {
          var base, base1, format, formatHandler, formatName, original, ref2, result;
          data = data.trim();
          original = (ref2 = profile.format) != null ? ref2 : exports.formatByType[profile.profileType];
          profile.profileType = 'RuleListProfile';
          format = original;
          if ((typeof (base = RuleList[format]).detect === "function" ? base.detect(data) : void 0) === false) {
            format = null;
          }
          for (formatName in RuleList) {
            if (!hasProp.call(RuleList, formatName)) continue;
            result = typeof (base1 = RuleList[formatName]).detect === "function" ? base1.detect(data) : void 0;
            if (result === true || (result !== false && (format == null))) {
              profile.format = format = formatName;
            }
          }
          if (format == null) {
            format = original;
          }
          formatHandler = RuleList[format];
          if (formatHandler.preprocess != null) {
            data = formatHandler.preprocess(data);
          }
          if (profile.ruleList === data) {
            return false;
          }
          profile.ruleList = data;
          return true;
        }
      },
      'SwitchyRuleListProfile': 'RuleListProfile',
      'AutoProxyRuleListProfile': 'RuleListProfile'
    }
  };
  
  
  },{"./conditions":61,"./rule_list":64,"./shexp_utils":65,"./utils":66,"uglify-js":67}],64:[function(require,module,exports){
  var Buffer, Conditions, exports, strStartsWith,
    hasProp = {}.hasOwnProperty;
  
  Buffer = require('buffer').Buffer;
  
  Conditions = require('./conditions');
  
  strStartsWith = function(str, prefix) {
    return str.substr(0, prefix.length) === prefix;
  };
  
  module.exports = exports = {
    'AutoProxy': {
      magicPrefix: 'W0F1dG9Qcm94',
      detect: function(text) {
        if (strStartsWith(text, exports['AutoProxy'].magicPrefix)) {
          return true;
        } else if (strStartsWith(text, '[AutoProxy')) {
          return true;
        }
      },
      preprocess: function(text) {
        if (strStartsWith(text, exports['AutoProxy'].magicPrefix)) {
          text = new Buffer(text, 'base64').toString('utf8');
        }
        return text;
      },
      parse: function(text, matchProfileName, defaultProfileName) {
        var cond, exclusive_rules, i, len, line, list, normal_rules, profile, ref, source;
        normal_rules = [];
        exclusive_rules = [];
        ref = text.split(/\n|\r/);
        for (i = 0, len = ref.length; i < len; i++) {
          line = ref[i];
          line = line.trim();
          if (line.length === 0 || line[0] === '!' || line[0] === '[') {
            continue;
          }
          source = line;
          profile = matchProfileName;
          list = normal_rules;
          if (line[0] === '@' && line[1] === '@') {
            profile = defaultProfileName;
            list = exclusive_rules;
            line = line.substring(2);
          }
          cond = line[0] === '/' ? {
            conditionType: 'UrlRegexCondition',
            pattern: line.substring(1, line.length - 1)
          } : line[0] === '|' ? line[1] === '|' ? {
            conditionType: 'HostWildcardCondition',
            pattern: "*." + line.substring(2)
          } : {
            conditionType: 'UrlWildcardCondition',
            pattern: line.substring(1) + "*"
          } : line.indexOf('*') < 0 ? {
            conditionType: 'KeywordCondition',
            pattern: line
          } : {
            conditionType: 'UrlWildcardCondition',
            pattern: 'http://*' + line + '*'
          };
          list.push({
            condition: cond,
            profileName: profile,
            source: source
          });
        }
        return exclusive_rules.concat(normal_rules);
      }
    },
    'Switchy': {
      omegaPrefix: '[SwitchyOmega Conditions',
      specialLineStart: "[;#@!",
      detect: function(text) {
        if (strStartsWith(text, exports['Switchy'].omegaPrefix)) {
          return true;
        }
      },
      parse: function(text, matchProfileName, defaultProfileName) {
        var parser, switchy;
        switchy = exports['Switchy'];
        parser = switchy.getParser(text);
        return switchy[parser](text, matchProfileName, defaultProfileName);
      },
      directReferenceSet: function(arg) {
        var defaultProfileName, i, iSpace, len, line, matchProfileName, parser, profile, ref, refs, ruleList, switchy, text;
        ruleList = arg.ruleList, matchProfileName = arg.matchProfileName, defaultProfileName = arg.defaultProfileName;
        text = ruleList.trim();
        switchy = exports['Switchy'];
        parser = switchy.getParser(text);
        if (parser !== 'parseOmega') {
          return;
        }
        if (!/(^|\n)@with\s+results?(\r|\n|$)/i.test(text)) {
          return;
        }
        refs = {};
        ref = text.split(/\n|\r/);
        for (i = 0, len = ref.length; i < len; i++) {
          line = ref[i];
          line = line.trim();
          if (switchy.specialLineStart.indexOf(line[0]) < 0) {
            iSpace = line.lastIndexOf(' +');
            if (iSpace < 0) {
              profile = defaultProfileName || 'direct';
            } else {
              profile = line.substr(iSpace + 2).trim();
            }
            refs['+' + profile] = profile;
          }
        }
        return refs;
      },
      compose: function(arg, arg1) {
        var defaultProfileName, eol, i, len, line, ref, rule, ruleList, rules, specialLineStart, useExclusive, withResult;
        rules = arg.rules, defaultProfileName = arg.defaultProfileName;
        ref = arg1 != null ? arg1 : {}, withResult = ref.withResult, useExclusive = ref.useExclusive;
        eol = '\r\n';
        ruleList = '[SwitchyOmega Conditions]' + eol;
        if (useExclusive == null) {
          useExclusive = !withResult;
        }
        if (withResult) {
          ruleList += '@with result' + eol + eol;
        } else {
          ruleList += eol;
        }
        specialLineStart = exports['Switchy'].specialLineStart + '+';
        for (i = 0, len = rules.length; i < len; i++) {
          rule = rules[i];
          if (rule.note) {
            ruleList += '@note ' + rule.note + eol;
          }
          line = Conditions.str(rule.condition);
          if (useExclusive && rule.profileName === defaultProfileName) {
            line = '!' + line;
          } else {
            if (specialLineStart.indexOf(line[0]) >= 0) {
              line = ': ' + line;
            }
            if (withResult) {
              line += ' +' + rule.profileName;
            }
          }
          ruleList += line + eol;
        }
        if (withResult) {
          ruleList += eol + '* +' + defaultProfileName + eol;
        }
        return ruleList;
      },
      getParser: function(text) {
        var parser, switchy;
        switchy = exports['Switchy'];
        parser = 'parseOmega';
        if (!strStartsWith(text, switchy.omegaPrefix)) {
          if (text[0] === '#' || text.indexOf('\n#') >= 0) {
            parser = 'parseLegacy';
          }
        }
        return parser;
      },
      conditionFromLegacyWildcard: function(pattern) {
        var host;
        if (pattern[0] === '@') {
          pattern = pattern.substring(1);
        } else {
          if (pattern.indexOf('://') <= 0 && pattern[0] !== '*') {
            pattern = '*' + pattern;
          }
          if (pattern[pattern.length - 1] !== '*') {
            pattern += '*';
          }
        }
        host = Conditions.urlWildcard2HostWildcard(pattern);
        if (host) {
          return {
            conditionType: 'HostWildcardCondition',
            pattern: host
          };
        } else {
          return {
            conditionType: 'UrlWildcardCondition',
            pattern: pattern
          };
        }
      },
      parseLegacy: function(text, matchProfileName, defaultProfileName) {
        var begin, cond, exclusive_rules, i, len, line, list, normal_rules, profile, ref, section, source;
        normal_rules = [];
        exclusive_rules = [];
        begin = false;
        section = 'WILDCARD';
        ref = text.split(/\n|\r/);
        for (i = 0, len = ref.length; i < len; i++) {
          line = ref[i];
          line = line.trim();
          if (line.length === 0 || line[0] === ';') {
            continue;
          }
          if (!begin) {
            if (line.toUpperCase() === '#BEGIN') {
              begin = true;
            }
            continue;
          }
          if (line.toUpperCase() === '#END') {
            break;
          }
          if (line[0] === '[' && line[line.length - 1] === ']') {
            section = line.substring(1, line.length - 1).toUpperCase();
            continue;
          }
          source = line;
          profile = matchProfileName;
          list = normal_rules;
          if (line[0] === '!') {
            profile = defaultProfileName;
            list = exclusive_rules;
            line = line.substring(1);
          }
          cond = (function() {
            switch (section) {
              case 'WILDCARD':
                return exports['Switchy'].conditionFromLegacyWildcard(line);
              case 'REGEXP':
                return {
                  conditionType: 'UrlRegexCondition',
                  pattern: line
                };
              default:
                return null;
            }
          })();
          if (cond != null) {
            list.push({
              condition: cond,
              profileName: profile,
              source: source
            });
          }
        }
        return exclusive_rules.concat(normal_rules);
      },
      parseOmega: function(text, matchProfileName, defaultProfileName, args) {
        var cond, directive, error, exclusiveProfile, feature, i, iSpace, includeSource, j, len, len1, line, lno, noteForNextRule, profile, ref, ref1, rule, rules, rulesWithDefaultProfile, source, strict, withResult;
        if (args == null) {
          args = {};
        }
        strict = args.strict;
        if (strict) {
          error = function(fields) {
            var err, key, value;
            err = new Error(fields.message);
            for (key in fields) {
              if (!hasProp.call(fields, key)) continue;
              value = fields[key];
              err[key] = value;
            }
            throw err;
          };
        }
        includeSource = (ref = args.source) != null ? ref : true;
        rules = [];
        rulesWithDefaultProfile = [];
        withResult = false;
        exclusiveProfile = null;
        noteForNextRule = null;
        lno = 0;
        ref1 = text.split(/\n|\r/);
        for (i = 0, len = ref1.length; i < len; i++) {
          line = ref1[i];
          lno++;
          line = line.trim();
          if (line.length === 0) {
            continue;
          }
          switch (line[0]) {
            case '[':
              continue;
            case ';':
              continue;
            case '@':
              iSpace = line.indexOf(' ');
              if (iSpace < 0) {
                iSpace = line.length;
              }
              directive = line.substr(1, iSpace - 1);
              line = line.substr(iSpace + 1).trim();
              switch (directive.toUpperCase()) {
                case 'WITH':
                  feature = line.toUpperCase();
                  if (feature === 'RESULT' || feature === 'RESULTS') {
                    withResult = true;
                  }
                  break;
                case 'NOTE':
                  noteForNextRule = line;
              }
              continue;
          }
          source = null;
          if (strict) {
            exclusiveProfile = null;
          }
          if (line[0] === '!') {
            profile = withResult ? null : defaultProfileName;
            source = line;
            line = line.substr(1);
          } else if (withResult) {
            iSpace = line.lastIndexOf(' +');
            if (iSpace < 0) {
              if (typeof error === "function") {
                error({
                  message: "Missing result profile name: " + line,
                  reason: 'missingResultProfile',
                  source: line,
                  sourceLineNo: lno
                });
              }
              continue;
            }
            profile = line.substr(iSpace + 2).trim();
            line = line.substr(0, iSpace).trim();
            if (line === '*') {
              exclusiveProfile = profile;
            }
          } else {
            profile = matchProfileName;
          }
          cond = Conditions.fromStr(line);
          if (!cond) {
            if (typeof error === "function") {
              error({
                message: "Invalid rule: " + line,
                reason: 'invalidRule',
                source: source != null ? source : line,
                sourceLineNo: lno
              });
            }
            continue;
          }
          rule = {
            condition: cond,
            profileName: profile,
            source: includeSource ? source != null ? source : line : void 0
          };
          if (noteForNextRule != null) {
            rule.note = noteForNextRule;
            noteForNextRule = null;
          }
          rules.push(rule);
          if (!profile) {
            rulesWithDefaultProfile.push(rule);
          }
        }
        if (withResult) {
          if (!exclusiveProfile) {
            if (strict) {
              if (typeof error === "function") {
                error({
                  message: "Missing default rule with catch-all '*' condition",
                  reason: 'noDefaultRule'
                });
              }
            }
            exclusiveProfile = defaultProfileName || 'direct';
          }
          for (j = 0, len1 = rulesWithDefaultProfile.length; j < len1; j++) {
            rule = rulesWithDefaultProfile[j];
            rule.profileName = exclusiveProfile;
          }
        }
        return rules;
      }
    }
  };
  
  
  },{"./conditions":61,"buffer":2}],65:[function(require,module,exports){
  var exports;
  
  module.exports = exports = {
    regExpMetaChars: (function() {
      var chars, i, j, ref, set;
      chars = '\\[\^$.|?*+(){}/';
      set = {};
      for (i = j = 0, ref = chars.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
        set[chars.charCodeAt(i)] = true;
      }
      return set;
    })(),
    escapeSlash: function(pattern) {
      var charCodeBackSlash, charCodeSlash, code, escaped, i, j, ref, result, start;
      charCodeSlash = 47;
      charCodeBackSlash = 92;
      escaped = false;
      start = 0;
      result = '';
      for (i = j = 0, ref = pattern.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
        code = pattern.charCodeAt(i);
        if (code === charCodeSlash && !escaped) {
          result += pattern.substring(start, i);
          result += '\\';
          start = i;
        }
        escaped = code === charCodeBackSlash && !escaped;
      }
      return result += pattern.substr(start);
    },
    shExp2RegExp: function(pattern, options) {
      var charCodeAsterisk, charCodeQuestion, code, end, i, j, ref, ref1, regex, start, trimAsterisk;
      trimAsterisk = (options != null ? options.trimAsterisk : void 0) || false;
      start = 0;
      end = pattern.length;
      charCodeAsterisk = 42;
      charCodeQuestion = 63;
      if (trimAsterisk) {
        while (start < end && pattern.charCodeAt(start) === charCodeAsterisk) {
          start++;
        }
        while (start < end && pattern.charCodeAt(end - 1) === charCodeAsterisk) {
          end--;
        }
        if (end - start === 1 && pattern.charCodeAt(start) === charCodeAsterisk) {
          return '';
        }
      }
      regex = '';
      if (start === 0) {
        regex += '^';
      }
      for (i = j = ref = start, ref1 = end; ref <= ref1 ? j < ref1 : j > ref1; i = ref <= ref1 ? ++j : --j) {
        code = pattern.charCodeAt(i);
        switch (code) {
          case charCodeAsterisk:
            regex += '.*';
            break;
          case charCodeQuestion:
            regex += '.';
            break;
          default:
            if (exports.regExpMetaChars[code] >= 0) {
              regex += '\\';
            }
            regex += pattern[i];
        }
      }
      if (end === pattern.length) {
        regex += '$';
      }
      return regex;
    }
  };
  
  
  },{}],66:[function(require,module,exports){
  var AttachedCache, Revision, Url, tld;
  
  Revision = {
    fromTime: function(time) {
      time = time ? new Date(time) : new Date();
      return time.getTime().toString(16);
    },
    compare: function(a, b) {
      if (!a && !b) {
        return 0;
      }
      if (!a) {
        return -1;
      }
      if (!b) {
        return 1;
      }
      if (a.length > b.length) {
        return 1;
      }
      if (a.length < b.length) {
        return -1;
      }
      if (a > b) {
        return 1;
      }
      if (a < b) {
        return -1;
      }
      return 0;
    }
  };
  
  exports.Revision = Revision;
  
  AttachedCache = (function() {
    function AttachedCache(opt_prop, tag1) {
      this.tag = tag1;
      this.prop = opt_prop;
      if (typeof this.tag === 'undefined') {
        this.tag = opt_prop;
        this.prop = '_cache';
      }
    }
  
    AttachedCache.prototype.get = function(obj, otherwise) {
      var cache, tag, value;
      tag = this.tag(obj);
      cache = this._getCache(obj);
      if ((cache != null) && cache.tag === tag) {
        return cache.value;
      }
      value = typeof otherwise === 'function' ? otherwise() : otherwise;
      this._setCache(obj, {
        tag: tag,
        value: value
      });
      return value;
    };
  
    AttachedCache.prototype.drop = function(obj) {
      if (obj[this.prop] != null) {
        return obj[this.prop] = void 0;
      }
    };
  
    AttachedCache.prototype._getCache = function(obj) {
      return obj[this.prop];
    };
  
    AttachedCache.prototype._setCache = function(obj, value) {
      if (!Object.prototype.hasOwnProperty.call(obj, this.prop)) {
        Object.defineProperty(obj, this.prop, {
          writable: true
        });
      }
      return obj[this.prop] = value;
    };
  
    return AttachedCache;
  
  })();
  
  exports.AttachedCache = AttachedCache;
  
  tld = require('tldjs');
  
  exports.isIp = function(domain) {
    var lastCharCode;
    if (domain.indexOf(':') > 0) {
      return true;
    }
    lastCharCode = domain.charCodeAt(domain.length - 1);
    if ((48 <= lastCharCode && lastCharCode <= 57)) {
      return true;
    }
    return false;
  };
  
  exports.getBaseDomain = function(domain) {
    var ref;
    if (exports.isIp(domain)) {
      return domain;
    }
    return (ref = tld.getDomain(domain)) != null ? ref : domain;
  };
  
  exports.wildcardForDomain = function(domain) {
    if (exports.isIp(domain)) {
      return domain;
    }
    return '*.' + exports.getBaseDomain(domain);
  };
  
  Url = require('url');
  
  exports.wildcardForUrl = function(url) {
    var domain;
    domain = Url.parse(url).hostname;
    return exports.wildcardForDomain(domain);
  };
  
  
  },{"tldjs":45,"url":60}],67:[function(require,module,exports){
  require('uglify-js-real');
  module.exports = UglifyJS;
  
  },{"uglify-js-real":68}],68:[function(require,module,exports){
  (function(exports, global) {
      global["UglifyJS"] = exports;
      "use strict";
      function array_to_hash(a) {
          var ret = Object.create(null);
          for (var i = 0; i < a.length; ++i) ret[a[i]] = true;
          return ret;
      }
      function slice(a, start) {
          return Array.prototype.slice.call(a, start || 0);
      }
      function characters(str) {
          return str.split("");
      }
      function member(name, array) {
          for (var i = array.length; --i >= 0; ) if (array[i] == name) return true;
          return false;
      }
      function find_if(func, array) {
          for (var i = 0, n = array.length; i < n; ++i) {
              if (func(array[i])) return array[i];
          }
      }
      function repeat_string(str, i) {
          if (i <= 0) return "";
          if (i == 1) return str;
          var d = repeat_string(str, i >> 1);
          d += d;
          if (i & 1) d += str;
          return d;
      }
      function DefaultsError(msg, defs) {
          Error.call(this, msg);
          this.msg = msg;
          this.defs = defs;
      }
      DefaultsError.prototype = Object.create(Error.prototype);
      DefaultsError.prototype.constructor = DefaultsError;
      DefaultsError.croak = function(msg, defs) {
          throw new DefaultsError(msg, defs);
      };
      function defaults(args, defs, croak) {
          if (args === true) args = {};
          var ret = args || {};
          if (croak) for (var i in ret) if (ret.hasOwnProperty(i) && !defs.hasOwnProperty(i)) DefaultsError.croak("`" + i + "` is not a supported option", defs);
          for (var i in defs) if (defs.hasOwnProperty(i)) {
              ret[i] = args && args.hasOwnProperty(i) ? args[i] : defs[i];
          }
          return ret;
      }
      function merge(obj, ext) {
          for (var i in ext) if (ext.hasOwnProperty(i)) {
              obj[i] = ext[i];
          }
          return obj;
      }
      function noop() {}
      var MAP = function() {
          function MAP(a, f, backwards) {
              var ret = [], top = [], i;
              function doit() {
                  var val = f(a[i], i);
                  var is_last = val instanceof Last;
                  if (is_last) val = val.v;
                  if (val instanceof AtTop) {
                      val = val.v;
                      if (val instanceof Splice) {
                          top.push.apply(top, backwards ? val.v.slice().reverse() : val.v);
                      } else {
                          top.push(val);
                      }
                  } else if (val !== skip) {
                      if (val instanceof Splice) {
                          ret.push.apply(ret, backwards ? val.v.slice().reverse() : val.v);
                      } else {
                          ret.push(val);
                      }
                  }
                  return is_last;
              }
              if (a instanceof Array) {
                  if (backwards) {
                      for (i = a.length; --i >= 0; ) if (doit()) break;
                      ret.reverse();
                      top.reverse();
                  } else {
                      for (i = 0; i < a.length; ++i) if (doit()) break;
                  }
              } else {
                  for (i in a) if (a.hasOwnProperty(i)) if (doit()) break;
              }
              return top.concat(ret);
          }
          MAP.at_top = function(val) {
              return new AtTop(val);
          };
          MAP.splice = function(val) {
              return new Splice(val);
          };
          MAP.last = function(val) {
              return new Last(val);
          };
          var skip = MAP.skip = {};
          function AtTop(val) {
              this.v = val;
          }
          function Splice(val) {
              this.v = val;
          }
          function Last(val) {
              this.v = val;
          }
          return MAP;
      }();
      function push_uniq(array, el) {
          if (array.indexOf(el) < 0) array.push(el);
      }
      function string_template(text, props) {
          return text.replace(/\{(.+?)\}/g, function(str, p) {
              return props[p];
          });
      }
      function remove(array, el) {
          for (var i = array.length; --i >= 0; ) {
              if (array[i] === el) array.splice(i, 1);
          }
      }
      function mergeSort(array, cmp) {
          if (array.length < 2) return array.slice();
          function merge(a, b) {
              var r = [], ai = 0, bi = 0, i = 0;
              while (ai < a.length && bi < b.length) {
                  cmp(a[ai], b[bi]) <= 0 ? r[i++] = a[ai++] : r[i++] = b[bi++];
              }
              if (ai < a.length) r.push.apply(r, a.slice(ai));
              if (bi < b.length) r.push.apply(r, b.slice(bi));
              return r;
          }
          function _ms(a) {
              if (a.length <= 1) return a;
              var m = Math.floor(a.length / 2), left = a.slice(0, m), right = a.slice(m);
              left = _ms(left);
              right = _ms(right);
              return merge(left, right);
          }
          return _ms(array);
      }
      function set_difference(a, b) {
          return a.filter(function(el) {
              return b.indexOf(el) < 0;
          });
      }
      function set_intersection(a, b) {
          return a.filter(function(el) {
              return b.indexOf(el) >= 0;
          });
      }
      function makePredicate(words) {
          if (!(words instanceof Array)) words = words.split(" ");
          if (typeof UglifyJS_NoUnsafeEval !== "undefined") {
              return function(str) {
                  return words.indexOf(str) >= 0;
              };
          }
          var f = "", cats = [];
          out: for (var i = 0; i < words.length; ++i) {
              for (var j = 0; j < cats.length; ++j) if (cats[j][0].length == words[i].length) {
                  cats[j].push(words[i]);
                  continue out;
              }
              cats.push([ words[i] ]);
          }
          function compareTo(arr) {
              if (arr.length == 1) return f += "return str === " + JSON.stringify(arr[0]) + ";";
              f += "switch(str){";
              for (var i = 0; i < arr.length; ++i) f += "case " + JSON.stringify(arr[i]) + ":";
              f += "return true}return false;";
          }
          if (cats.length > 3) {
              cats.sort(function(a, b) {
                  return b.length - a.length;
              });
              f += "switch(str.length){";
              for (var i = 0; i < cats.length; ++i) {
                  var cat = cats[i];
                  f += "case " + cat[0].length + ":";
                  compareTo(cat);
              }
              f += "}";
          } else {
              compareTo(words);
          }
          return new Function("str", f);
      }
      function all(array, predicate) {
          for (var i = array.length; --i >= 0; ) if (!predicate(array[i])) return false;
          return true;
      }
      function Dictionary() {
          this._values = Object.create(null);
          this._size = 0;
      }
      Dictionary.prototype = {
          set: function(key, val) {
              if (!this.has(key)) ++this._size;
              this._values["$" + key] = val;
              return this;
          },
          add: function(key, val) {
              if (this.has(key)) {
                  this.get(key).push(val);
              } else {
                  this.set(key, [ val ]);
              }
              return this;
          },
          get: function(key) {
              return this._values["$" + key];
          },
          del: function(key) {
              if (this.has(key)) {
                  --this._size;
                  delete this._values["$" + key];
              }
              return this;
          },
          has: function(key) {
              return "$" + key in this._values;
          },
          each: function(f) {
              for (var i in this._values) f(this._values[i], i.substr(1));
          },
          size: function() {
              return this._size;
          },
          map: function(f) {
              var ret = [];
              for (var i in this._values) ret.push(f(this._values[i], i.substr(1)));
              return ret;
          }
      };
      "use strict";
      function DEFNODE(type, props, methods, base) {
          if (arguments.length < 4) base = AST_Node;
          if (!props) props = []; else props = props.split(/\s+/);
          var self_props = props;
          if (base && base.PROPS) props = props.concat(base.PROPS);
          var proto = base && new base();
          var ctor;
          if (typeof UglifyJS_NoUnsafeEval === "undefined") {
              var code = "return function AST_" + type + "(props){ if (props) { ";
              for (var i = props.length; --i >= 0; ) {
                  code += "this." + props[i] + " = props." + props[i] + ";";
              }
              if (proto && proto.initialize || methods && methods.initialize) code += "this.initialize();";
              code += "}}";
              ctor = new Function(code)();
          } else {
              ctor = function(values) {
                  if (values) {
                      for (var i = props.length; --i >= 0; ) this[props[i]] = values[props[i]];
                      if (proto && proto.initialize || methods && methods.initialize) this.initialize();
                  }
              };
          }
          if (proto) {
              ctor.prototype = proto;
              ctor.BASE = base;
          }
          if (base) base.SUBCLASSES.push(ctor);
          ctor.prototype.CTOR = ctor;
          ctor.PROPS = props || null;
          ctor.SELF_PROPS = self_props;
          ctor.SUBCLASSES = [];
          if (type) {
              ctor.prototype.TYPE = ctor.TYPE = type;
          }
          if (methods) for (i in methods) if (methods.hasOwnProperty(i)) {
              if (/^\$/.test(i)) {
                  ctor[i.substr(1)] = methods[i];
              } else {
                  ctor.prototype[i] = methods[i];
              }
          }
          ctor.DEFMETHOD = function(name, method) {
              this.prototype[name] = method;
          };
          return ctor;
      }
      var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_before file", {}, null);
      var AST_Node = DEFNODE("Node", "start end", {
          clone: function() {
              return new this.CTOR(this);
          },
          $documentation: "Base class of all AST nodes",
          $propdoc: {
              start: "[AST_Token] The first token of this node",
              end: "[AST_Token] The last token of this node"
          },
          _walk: function(visitor) {
              return visitor._visit(this);
          },
          walk: function(visitor) {
              return this._walk(visitor);
          }
      }, null);
      AST_Node.warn_function = null;
      AST_Node.warn = function(txt, props) {
          if (AST_Node.warn_function) AST_Node.warn_function(string_template(txt, props));
      };
      var AST_Statement = DEFNODE("Statement", null, {
          $documentation: "Base class of all statements"
      });
      var AST_Debugger = DEFNODE("Debugger", null, {
          $documentation: "Represents a debugger statement"
      }, AST_Statement);
      var AST_Directive = DEFNODE("Directive", "value scope", {
          $documentation: 'Represents a directive, like "use strict";',
          $propdoc: {
              value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
              scope: "[AST_Scope/S] The scope that this directive affects"
          }
      }, AST_Statement);
      var AST_SimpleStatement = DEFNODE("SimpleStatement", "body", {
          $documentation: "A statement consisting of an expression, i.e. a = 1 + 2",
          $propdoc: {
              body: "[AST_Node] an expression node (should not be instanceof AST_Statement)"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.body._walk(visitor);
              });
          }
      }, AST_Statement);
      function walk_body(node, visitor) {
          if (node.body instanceof AST_Statement) {
              node.body._walk(visitor);
          } else node.body.forEach(function(stat) {
              stat._walk(visitor);
          });
      }
      var AST_Block = DEFNODE("Block", "body", {
          $documentation: "A body of statements (usually bracketed)",
          $propdoc: {
              body: "[AST_Statement*] an array of statements"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  walk_body(this, visitor);
              });
          }
      }, AST_Statement);
      var AST_BlockStatement = DEFNODE("BlockStatement", null, {
          $documentation: "A block statement"
      }, AST_Block);
      var AST_EmptyStatement = DEFNODE("EmptyStatement", null, {
          $documentation: "The empty statement (empty block or simply a semicolon)",
          _walk: function(visitor) {
              return visitor._visit(this);
          }
      }, AST_Statement);
      var AST_StatementWithBody = DEFNODE("StatementWithBody", "body", {
          $documentation: "Base class for all statements that contain one nested body: `For`, `ForIn`, `Do`, `While`, `With`",
          $propdoc: {
              body: "[AST_Statement] the body; this should always be present, even if it's an AST_EmptyStatement"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.body._walk(visitor);
              });
          }
      }, AST_Statement);
      var AST_LabeledStatement = DEFNODE("LabeledStatement", "label", {
          $documentation: "Statement with a label",
          $propdoc: {
              label: "[AST_Label] a label definition"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.label._walk(visitor);
                  this.body._walk(visitor);
              });
          }
      }, AST_StatementWithBody);
      var AST_IterationStatement = DEFNODE("IterationStatement", null, {
          $documentation: "Internal class.  All loops inherit from it."
      }, AST_StatementWithBody);
      var AST_DWLoop = DEFNODE("DWLoop", "condition", {
          $documentation: "Base class for do/while statements",
          $propdoc: {
              condition: "[AST_Node] the loop condition.  Should not be instanceof AST_Statement"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.condition._walk(visitor);
                  this.body._walk(visitor);
              });
          }
      }, AST_IterationStatement);
      var AST_Do = DEFNODE("Do", null, {
          $documentation: "A `do` statement"
      }, AST_DWLoop);
      var AST_While = DEFNODE("While", null, {
          $documentation: "A `while` statement"
      }, AST_DWLoop);
      var AST_For = DEFNODE("For", "init condition step", {
          $documentation: "A `for` statement",
          $propdoc: {
              init: "[AST_Node?] the `for` initialization code, or null if empty",
              condition: "[AST_Node?] the `for` termination clause, or null if empty",
              step: "[AST_Node?] the `for` update clause, or null if empty"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  if (this.init) this.init._walk(visitor);
                  if (this.condition) this.condition._walk(visitor);
                  if (this.step) this.step._walk(visitor);
                  this.body._walk(visitor);
              });
          }
      }, AST_IterationStatement);
      var AST_ForIn = DEFNODE("ForIn", "init name object", {
          $documentation: "A `for ... in` statement",
          $propdoc: {
              init: "[AST_Node] the `for/in` initialization code",
              name: "[AST_SymbolRef?] the loop variable, only if `init` is AST_Var",
              object: "[AST_Node] the object that we're looping through"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.init._walk(visitor);
                  this.object._walk(visitor);
                  this.body._walk(visitor);
              });
          }
      }, AST_IterationStatement);
      var AST_With = DEFNODE("With", "expression", {
          $documentation: "A `with` statement",
          $propdoc: {
              expression: "[AST_Node] the `with` expression"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
                  this.body._walk(visitor);
              });
          }
      }, AST_StatementWithBody);
      var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
          $documentation: "Base class for all statements introducing a lexical scope",
          $propdoc: {
              directives: "[string*/S] an array of directives declared in this scope",
              variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
              functions: "[Object/S] like `variables`, but only lists function declarations",
              uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
              uses_eval: "[boolean/S] tells whether this scope contains a direct call to the global `eval`",
              parent_scope: "[AST_Scope?/S] link to the parent scope",
              enclosed: "[SymbolDef*/S] a list of all symbol definitions that are accessed from this scope or any subscopes",
              cname: "[integer/S] current index for mangling variables (used internally by the mangler)"
          }
      }, AST_Block);
      var AST_Toplevel = DEFNODE("Toplevel", "globals", {
          $documentation: "The toplevel scope",
          $propdoc: {
              globals: "[Object/S] a map of name -> SymbolDef for all undeclared names"
          },
          wrap_enclose: function(arg_parameter_pairs) {
              var self = this;
              var args = [];
              var parameters = [];
              arg_parameter_pairs.forEach(function(pair) {
                  var splitAt = pair.lastIndexOf(":");
                  args.push(pair.substr(0, splitAt));
                  parameters.push(pair.substr(splitAt + 1));
              });
              var wrapped_tl = "(function(" + parameters.join(",") + "){ '$ORIG'; })(" + args.join(",") + ")";
              wrapped_tl = parse(wrapped_tl);
              wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
                  if (node instanceof AST_Directive && node.value == "$ORIG") {
                      return MAP.splice(self.body);
                  }
              }));
              return wrapped_tl;
          },
          wrap_commonjs: function(name, export_all) {
              var self = this;
              var to_export = [];
              if (export_all) {
                  self.figure_out_scope();
                  self.walk(new TreeWalker(function(node) {
                      if (node instanceof AST_SymbolDeclaration && node.definition().global) {
                          if (!find_if(function(n) {
                              return n.name == node.name;
                          }, to_export)) to_export.push(node);
                      }
                  }));
              }
              var wrapped_tl = "(function(exports, global){ global['" + name + "'] = exports; '$ORIG'; '$EXPORTS'; }({}, (function(){return this}())))";
              wrapped_tl = parse(wrapped_tl);
              wrapped_tl = wrapped_tl.transform(new TreeTransformer(function before(node) {
                  if (node instanceof AST_SimpleStatement) {
                      node = node.body;
                      if (node instanceof AST_String) switch (node.getValue()) {
                        case "$ORIG":
                          return MAP.splice(self.body);
  
                        case "$EXPORTS":
                          var body = [];
                          to_export.forEach(function(sym) {
                              body.push(new AST_SimpleStatement({
                                  body: new AST_Assign({
                                      left: new AST_Sub({
                                          expression: new AST_SymbolRef({
                                              name: "exports"
                                          }),
                                          property: new AST_String({
                                              value: sym.name
                                          })
                                      }),
                                      operator: "=",
                                      right: new AST_SymbolRef(sym)
                                  })
                              }));
                          });
                          return MAP.splice(body);
                      }
                  }
              }));
              return wrapped_tl;
          }
      }, AST_Scope);
      var AST_Lambda = DEFNODE("Lambda", "name argnames uses_arguments", {
          $documentation: "Base class for functions",
          $propdoc: {
              name: "[AST_SymbolDeclaration?] the name of this function",
              argnames: "[AST_SymbolFunarg*] array of function arguments",
              uses_arguments: "[boolean/S] tells whether this function accesses the arguments array"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  if (this.name) this.name._walk(visitor);
                  this.argnames.forEach(function(arg) {
                      arg._walk(visitor);
                  });
                  walk_body(this, visitor);
              });
          }
      }, AST_Scope);
      var AST_Accessor = DEFNODE("Accessor", null, {
          $documentation: "A setter/getter function.  The `name` property is always null."
      }, AST_Lambda);
      var AST_Function = DEFNODE("Function", null, {
          $documentation: "A function expression"
      }, AST_Lambda);
      var AST_Defun = DEFNODE("Defun", null, {
          $documentation: "A function definition"
      }, AST_Lambda);
      var AST_Jump = DEFNODE("Jump", null, {
          $documentation: "Base class for “jumps” (for now that's `return`, `throw`, `break` and `continue`)"
      }, AST_Statement);
      var AST_Exit = DEFNODE("Exit", "value", {
          $documentation: "Base class for “exits” (`return` and `throw`)",
          $propdoc: {
              value: "[AST_Node?] the value returned or thrown by this statement; could be null for AST_Return"
          },
          _walk: function(visitor) {
              return visitor._visit(this, this.value && function() {
                  this.value._walk(visitor);
              });
          }
      }, AST_Jump);
      var AST_Return = DEFNODE("Return", null, {
          $documentation: "A `return` statement"
      }, AST_Exit);
      var AST_Throw = DEFNODE("Throw", null, {
          $documentation: "A `throw` statement"
      }, AST_Exit);
      var AST_LoopControl = DEFNODE("LoopControl", "label", {
          $documentation: "Base class for loop control statements (`break` and `continue`)",
          $propdoc: {
              label: "[AST_LabelRef?] the label, or null if none"
          },
          _walk: function(visitor) {
              return visitor._visit(this, this.label && function() {
                  this.label._walk(visitor);
              });
          }
      }, AST_Jump);
      var AST_Break = DEFNODE("Break", null, {
          $documentation: "A `break` statement"
      }, AST_LoopControl);
      var AST_Continue = DEFNODE("Continue", null, {
          $documentation: "A `continue` statement"
      }, AST_LoopControl);
      var AST_If = DEFNODE("If", "condition alternative", {
          $documentation: "A `if` statement",
          $propdoc: {
              condition: "[AST_Node] the `if` condition",
              alternative: "[AST_Statement?] the `else` part, or null if not present"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.condition._walk(visitor);
                  this.body._walk(visitor);
                  if (this.alternative) this.alternative._walk(visitor);
              });
          }
      }, AST_StatementWithBody);
      var AST_Switch = DEFNODE("Switch", "expression", {
          $documentation: "A `switch` statement",
          $propdoc: {
              expression: "[AST_Node] the `switch` “discriminant”"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
                  walk_body(this, visitor);
              });
          }
      }, AST_Block);
      var AST_SwitchBranch = DEFNODE("SwitchBranch", null, {
          $documentation: "Base class for `switch` branches"
      }, AST_Block);
      var AST_Default = DEFNODE("Default", null, {
          $documentation: "A `default` switch branch"
      }, AST_SwitchBranch);
      var AST_Case = DEFNODE("Case", "expression", {
          $documentation: "A `case` switch branch",
          $propdoc: {
              expression: "[AST_Node] the `case` expression"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
                  walk_body(this, visitor);
              });
          }
      }, AST_SwitchBranch);
      var AST_Try = DEFNODE("Try", "bcatch bfinally", {
          $documentation: "A `try` statement",
          $propdoc: {
              bcatch: "[AST_Catch?] the catch block, or null if not present",
              bfinally: "[AST_Finally?] the finally block, or null if not present"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  walk_body(this, visitor);
                  if (this.bcatch) this.bcatch._walk(visitor);
                  if (this.bfinally) this.bfinally._walk(visitor);
              });
          }
      }, AST_Block);
      var AST_Catch = DEFNODE("Catch", "argname", {
          $documentation: "A `catch` node; only makes sense as part of a `try` statement",
          $propdoc: {
              argname: "[AST_SymbolCatch] symbol for the exception"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.argname._walk(visitor);
                  walk_body(this, visitor);
              });
          }
      }, AST_Block);
      var AST_Finally = DEFNODE("Finally", null, {
          $documentation: "A `finally` node; only makes sense as part of a `try` statement"
      }, AST_Block);
      var AST_Definitions = DEFNODE("Definitions", "definitions", {
          $documentation: "Base class for `var` or `const` nodes (variable declarations/initializations)",
          $propdoc: {
              definitions: "[AST_VarDef*] array of variable definitions"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.definitions.forEach(function(def) {
                      def._walk(visitor);
                  });
              });
          }
      }, AST_Statement);
      var AST_Var = DEFNODE("Var", null, {
          $documentation: "A `var` statement"
      }, AST_Definitions);
      var AST_Const = DEFNODE("Const", null, {
          $documentation: "A `const` statement"
      }, AST_Definitions);
      var AST_VarDef = DEFNODE("VarDef", "name value", {
          $documentation: "A variable declaration; only appears in a AST_Definitions node",
          $propdoc: {
              name: "[AST_SymbolVar|AST_SymbolConst] name of the variable",
              value: "[AST_Node?] initializer, or null of there's no initializer"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.name._walk(visitor);
                  if (this.value) this.value._walk(visitor);
              });
          }
      });
      var AST_Call = DEFNODE("Call", "expression args", {
          $documentation: "A function call expression",
          $propdoc: {
              expression: "[AST_Node] expression to invoke as function",
              args: "[AST_Node*] array of arguments"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
                  this.args.forEach(function(arg) {
                      arg._walk(visitor);
                  });
              });
          }
      });
      var AST_New = DEFNODE("New", null, {
          $documentation: "An object instantiation.  Derives from a function call since it has exactly the same properties"
      }, AST_Call);
      var AST_Seq = DEFNODE("Seq", "car cdr", {
          $documentation: "A sequence expression (two comma-separated expressions)",
          $propdoc: {
              car: "[AST_Node] first element in sequence",
              cdr: "[AST_Node] second element in sequence"
          },
          $cons: function(x, y) {
              var seq = new AST_Seq(x);
              seq.car = x;
              seq.cdr = y;
              return seq;
          },
          $from_array: function(array) {
              if (array.length == 0) return null;
              if (array.length == 1) return array[0].clone();
              var list = null;
              for (var i = array.length; --i >= 0; ) {
                  list = AST_Seq.cons(array[i], list);
              }
              var p = list;
              while (p) {
                  if (p.cdr && !p.cdr.cdr) {
                      p.cdr = p.cdr.car;
                      break;
                  }
                  p = p.cdr;
              }
              return list;
          },
          to_array: function() {
              var p = this, a = [];
              while (p) {
                  a.push(p.car);
                  if (p.cdr && !(p.cdr instanceof AST_Seq)) {
                      a.push(p.cdr);
                      break;
                  }
                  p = p.cdr;
              }
              return a;
          },
          add: function(node) {
              var p = this;
              while (p) {
                  if (!(p.cdr instanceof AST_Seq)) {
                      var cell = AST_Seq.cons(p.cdr, node);
                      return p.cdr = cell;
                  }
                  p = p.cdr;
              }
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.car._walk(visitor);
                  if (this.cdr) this.cdr._walk(visitor);
              });
          }
      });
      var AST_PropAccess = DEFNODE("PropAccess", "expression property", {
          $documentation: 'Base class for property access expressions, i.e. `a.foo` or `a["foo"]`',
          $propdoc: {
              expression: "[AST_Node] the “container” expression",
              property: "[AST_Node|string] the property to access.  For AST_Dot this is always a plain string, while for AST_Sub it's an arbitrary AST_Node"
          }
      });
      var AST_Dot = DEFNODE("Dot", null, {
          $documentation: "A dotted property access expression",
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
              });
          }
      }, AST_PropAccess);
      var AST_Sub = DEFNODE("Sub", null, {
          $documentation: 'Index-style property access, i.e. `a["foo"]`',
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
                  this.property._walk(visitor);
              });
          }
      }, AST_PropAccess);
      var AST_Unary = DEFNODE("Unary", "operator expression", {
          $documentation: "Base class for unary expressions",
          $propdoc: {
              operator: "[string] the operator",
              expression: "[AST_Node] expression that this unary operator applies to"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.expression._walk(visitor);
              });
          }
      });
      var AST_UnaryPrefix = DEFNODE("UnaryPrefix", null, {
          $documentation: "Unary prefix expression, i.e. `typeof i` or `++i`"
      }, AST_Unary);
      var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
          $documentation: "Unary postfix expression, i.e. `i++`"
      }, AST_Unary);
      var AST_Binary = DEFNODE("Binary", "left operator right", {
          $documentation: "Binary expression, i.e. `a + b`",
          $propdoc: {
              left: "[AST_Node] left-hand side expression",
              operator: "[string] the operator",
              right: "[AST_Node] right-hand side expression"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.left._walk(visitor);
                  this.right._walk(visitor);
              });
          }
      });
      var AST_Conditional = DEFNODE("Conditional", "condition consequent alternative", {
          $documentation: "Conditional expression using the ternary operator, i.e. `a ? b : c`",
          $propdoc: {
              condition: "[AST_Node]",
              consequent: "[AST_Node]",
              alternative: "[AST_Node]"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.condition._walk(visitor);
                  this.consequent._walk(visitor);
                  this.alternative._walk(visitor);
              });
          }
      });
      var AST_Assign = DEFNODE("Assign", null, {
          $documentation: "An assignment expression — `a = b + 5`"
      }, AST_Binary);
      var AST_Array = DEFNODE("Array", "elements", {
          $documentation: "An array literal",
          $propdoc: {
              elements: "[AST_Node*] array of elements"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.elements.forEach(function(el) {
                      el._walk(visitor);
                  });
              });
          }
      });
      var AST_Object = DEFNODE("Object", "properties", {
          $documentation: "An object literal",
          $propdoc: {
              properties: "[AST_ObjectProperty*] array of properties"
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.properties.forEach(function(prop) {
                      prop._walk(visitor);
                  });
              });
          }
      });
      var AST_ObjectProperty = DEFNODE("ObjectProperty", "key value", {
          $documentation: "Base class for literal object properties",
          $propdoc: {
              key: "[string] the property name converted to a string for ObjectKeyVal.  For setters and getters this is an arbitrary AST_Node.",
              value: "[AST_Node] property value.  For setters and getters this is an AST_Function."
          },
          _walk: function(visitor) {
              return visitor._visit(this, function() {
                  this.value._walk(visitor);
              });
          }
      });
      var AST_ObjectKeyVal = DEFNODE("ObjectKeyVal", null, {
          $documentation: "A key: value object property"
      }, AST_ObjectProperty);
      var AST_ObjectSetter = DEFNODE("ObjectSetter", null, {
          $documentation: "An object setter property"
      }, AST_ObjectProperty);
      var AST_ObjectGetter = DEFNODE("ObjectGetter", null, {
          $documentation: "An object getter property"
      }, AST_ObjectProperty);
      var AST_Symbol = DEFNODE("Symbol", "scope name thedef", {
          $propdoc: {
              name: "[string] name of this symbol",
              scope: "[AST_Scope/S] the current scope (not necessarily the definition scope)",
              thedef: "[SymbolDef/S] the definition of this symbol"
          },
          $documentation: "Base class for all symbols"
      });
      var AST_SymbolAccessor = DEFNODE("SymbolAccessor", null, {
          $documentation: "The name of a property accessor (setter/getter function)"
      }, AST_Symbol);
      var AST_SymbolDeclaration = DEFNODE("SymbolDeclaration", "init", {
          $documentation: "A declaration symbol (symbol in var/const, function name or argument, symbol in catch)",
          $propdoc: {
              init: "[AST_Node*/S] array of initializers for this declaration."
          }
      }, AST_Symbol);
      var AST_SymbolVar = DEFNODE("SymbolVar", null, {
          $documentation: "Symbol defining a variable"
      }, AST_SymbolDeclaration);
      var AST_SymbolConst = DEFNODE("SymbolConst", null, {
          $documentation: "A constant declaration"
      }, AST_SymbolDeclaration);
      var AST_SymbolFunarg = DEFNODE("SymbolFunarg", null, {
          $documentation: "Symbol naming a function argument"
      }, AST_SymbolVar);
      var AST_SymbolDefun = DEFNODE("SymbolDefun", null, {
          $documentation: "Symbol defining a function"
      }, AST_SymbolDeclaration);
      var AST_SymbolLambda = DEFNODE("SymbolLambda", null, {
          $documentation: "Symbol naming a function expression"
      }, AST_SymbolDeclaration);
      var AST_SymbolCatch = DEFNODE("SymbolCatch", null, {
          $documentation: "Symbol naming the exception in catch"
      }, AST_SymbolDeclaration);
      var AST_Label = DEFNODE("Label", "references", {
          $documentation: "Symbol naming a label (declaration)",
          $propdoc: {
              references: "[AST_LoopControl*] a list of nodes referring to this label"
          },
          initialize: function() {
              this.references = [];
              this.thedef = this;
          }
      }, AST_Symbol);
      var AST_SymbolRef = DEFNODE("SymbolRef", null, {
          $documentation: "Reference to some symbol (not definition/declaration)"
      }, AST_Symbol);
      var AST_LabelRef = DEFNODE("LabelRef", null, {
          $documentation: "Reference to a label symbol"
      }, AST_Symbol);
      var AST_This = DEFNODE("This", null, {
          $documentation: "The `this` symbol"
      }, AST_Symbol);
      var AST_Constant = DEFNODE("Constant", null, {
          $documentation: "Base class for all constants",
          getValue: function() {
              return this.value;
          }
      });
      var AST_String = DEFNODE("String", "value", {
          $documentation: "A string literal",
          $propdoc: {
              value: "[string] the contents of this string"
          }
      }, AST_Constant);
      var AST_Number = DEFNODE("Number", "value", {
          $documentation: "A number literal",
          $propdoc: {
              value: "[number] the numeric value"
          }
      }, AST_Constant);
      var AST_RegExp = DEFNODE("RegExp", "value", {
          $documentation: "A regexp literal",
          $propdoc: {
              value: "[RegExp] the actual regexp"
          }
      }, AST_Constant);
      var AST_Atom = DEFNODE("Atom", null, {
          $documentation: "Base class for atoms"
      }, AST_Constant);
      var AST_Null = DEFNODE("Null", null, {
          $documentation: "The `null` atom",
          value: null
      }, AST_Atom);
      var AST_NaN = DEFNODE("NaN", null, {
          $documentation: "The impossible value",
          value: 0 / 0
      }, AST_Atom);
      var AST_Undefined = DEFNODE("Undefined", null, {
          $documentation: "The `undefined` value",
          value: function() {}()
      }, AST_Atom);
      var AST_Hole = DEFNODE("Hole", null, {
          $documentation: "A hole in an array",
          value: function() {}()
      }, AST_Atom);
      var AST_Infinity = DEFNODE("Infinity", null, {
          $documentation: "The `Infinity` value",
          value: 1 / 0
      }, AST_Atom);
      var AST_Boolean = DEFNODE("Boolean", null, {
          $documentation: "Base class for booleans"
      }, AST_Atom);
      var AST_False = DEFNODE("False", null, {
          $documentation: "The `false` atom",
          value: false
      }, AST_Boolean);
      var AST_True = DEFNODE("True", null, {
          $documentation: "The `true` atom",
          value: true
      }, AST_Boolean);
      function TreeWalker(callback) {
          this.visit = callback;
          this.stack = [];
      }
      TreeWalker.prototype = {
          _visit: function(node, descend) {
              this.stack.push(node);
              var ret = this.visit(node, descend ? function() {
                  descend.call(node);
              } : noop);
              if (!ret && descend) {
                  descend.call(node);
              }
              this.stack.pop();
              return ret;
          },
          parent: function(n) {
              return this.stack[this.stack.length - 2 - (n || 0)];
          },
          push: function(node) {
              this.stack.push(node);
          },
          pop: function() {
              return this.stack.pop();
          },
          self: function() {
              return this.stack[this.stack.length - 1];
          },
          find_parent: function(type) {
              var stack = this.stack;
              for (var i = stack.length; --i >= 0; ) {
                  var x = stack[i];
                  if (x instanceof type) return x;
              }
          },
          has_directive: function(type) {
              return this.find_parent(AST_Scope).has_directive(type);
          },
          in_boolean_context: function() {
              var stack = this.stack;
              var i = stack.length, self = stack[--i];
              while (i > 0) {
                  var p = stack[--i];
                  if (p instanceof AST_If && p.condition === self || p instanceof AST_Conditional && p.condition === self || p instanceof AST_DWLoop && p.condition === self || p instanceof AST_For && p.condition === self || p instanceof AST_UnaryPrefix && p.operator == "!" && p.expression === self) {
                      return true;
                  }
                  if (!(p instanceof AST_Binary && (p.operator == "&&" || p.operator == "||"))) return false;
                  self = p;
              }
          },
          loopcontrol_target: function(label) {
              var stack = this.stack;
              if (label) for (var i = stack.length; --i >= 0; ) {
                  var x = stack[i];
                  if (x instanceof AST_LabeledStatement && x.label.name == label.name) {
                      return x.body;
                  }
              } else for (var i = stack.length; --i >= 0; ) {
                  var x = stack[i];
                  if (x instanceof AST_Switch || x instanceof AST_IterationStatement) return x;
              }
          }
      };
      "use strict";
      var KEYWORDS = "break case catch const continue debugger default delete do else finally for function if in instanceof new return switch throw try typeof var void while with";
      var KEYWORDS_ATOM = "false null true";
      var RESERVED_WORDS = "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized this throws transient volatile yield" + " " + KEYWORDS_ATOM + " " + KEYWORDS;
      var KEYWORDS_BEFORE_EXPRESSION = "return new delete throw else case";
      KEYWORDS = makePredicate(KEYWORDS);
      RESERVED_WORDS = makePredicate(RESERVED_WORDS);
      KEYWORDS_BEFORE_EXPRESSION = makePredicate(KEYWORDS_BEFORE_EXPRESSION);
      KEYWORDS_ATOM = makePredicate(KEYWORDS_ATOM);
      var OPERATOR_CHARS = makePredicate(characters("+-*&%=<>!?|~^"));
      var RE_HEX_NUMBER = /^0x[0-9a-f]+$/i;
      var RE_OCT_NUMBER = /^0[0-7]+$/;
      var RE_DEC_NUMBER = /^\d*\.?\d*(?:e[+-]?\d*(?:\d\.?|\.?\d)\d*)?$/i;
      var OPERATORS = makePredicate([ "in", "instanceof", "typeof", "new", "void", "delete", "++", "--", "+", "-", "!", "~", "&", "|", "^", "*", "/", "%", ">>", "<<", ">>>", "<", ">", "<=", ">=", "==", "===", "!=", "!==", "?", "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=", "&&", "||" ]);
      var WHITESPACE_CHARS = makePredicate(characters("  \n\r	\f​᠎             　"));
      var PUNC_BEFORE_EXPRESSION = makePredicate(characters("[{(,.;:"));
      var PUNC_CHARS = makePredicate(characters("[]{}(),;:"));
      var REGEXP_MODIFIERS = makePredicate(characters("gmsiy"));
      var UNICODE = {
          letter: new RegExp("[\\u0041-\\u005A\\u0061-\\u007A\\u00AA\\u00B5\\u00BA\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02C1\\u02C6-\\u02D1\\u02E0-\\u02E4\\u02EC\\u02EE\\u0370-\\u0374\\u0376\\u0377\\u037A-\\u037D\\u0386\\u0388-\\u038A\\u038C\\u038E-\\u03A1\\u03A3-\\u03F5\\u03F7-\\u0481\\u048A-\\u0523\\u0531-\\u0556\\u0559\\u0561-\\u0587\\u05D0-\\u05EA\\u05F0-\\u05F2\\u0621-\\u064A\\u066E\\u066F\\u0671-\\u06D3\\u06D5\\u06E5\\u06E6\\u06EE\\u06EF\\u06FA-\\u06FC\\u06FF\\u0710\\u0712-\\u072F\\u074D-\\u07A5\\u07B1\\u07CA-\\u07EA\\u07F4\\u07F5\\u07FA\\u0904-\\u0939\\u093D\\u0950\\u0958-\\u0961\\u0971\\u0972\\u097B-\\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\\u0D05-\\u0D0C\\u0D0E-\\u0D10\\u0D12-\\u0D28\\u0D2A-\\u0D39\\u0D3D\\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\\u0EDD\\u0F00\\u0F40-\\u0F47\\u0F49-\\u0F6C\\u0F88-\\u0F8B\\u1000-\\u102A\\u103F\\u1050-\\u1055\\u105A-\\u105D\\u1061\\u1065\\u1066\\u106E-\\u1070\\u1075-\\u1081\\u108E\\u10A0-\\u10C5\\u10D0-\\u10FA\\u10FC\\u1100-\\u1159\\u115F-\\u11A2\\u11A8-\\u11F9\\u1200-\\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-\\u1676\\u1681-\\u169A\\u16A0-\\u16EA\\u1700-\\u170C\\u170E-\\u1711\\u1720-\\u1731\\u1740-\\u1751\\u1760-\\u176C\\u176E-\\u1770\\u1780-\\u17B3\\u17D7\\u17DC\\u1820-\\u1877\\u1880-\\u18A8\\u18AA\\u1900-\\u191C\\u1950-\\u196D\\u1970-\\u1974\\u1980-\\u19A9\\u19C1-\\u19C7\\u1A00-\\u1A16\\u1B05-\\u1B33\\u1B45-\\u1B4B\\u1B83-\\u1BA0\\u1BAE\\u1BAF\\u1C00-\\u1C23\\u1C4D-\\u1C4F\\u1C5A-\\u1C7D\\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-\\u2094\\u2102\\u2107\\u210A-\\u2113\\u2115\\u2119-\\u211D\\u2124\\u2126\\u2128\\u212A-\\u212D\\u212F-\\u2139\\u213C-\\u213F\\u2145-\\u2149\\u214E\\u2183\\u2184\\u2C00-\\u2C2E\\u2C30-\\u2C5E\\u2C60-\\u2C6F\\u2C71-\\u2C7D\\u2C80-\\u2CE4\\u2D00-\\u2D25\\u2D30-\\u2D65\\u2D6F\\u2D80-\\u2D96\\u2DA0-\\u2DA6\\u2DA8-\\u2DAE\\u2DB0-\\u2DB6\\u2DB8-\\u2DBE\\u2DC0-\\u2DC6\\u2DC8-\\u2DCE\\u2DD0-\\u2DD6\\u2DD8-\\u2DDE\\u2E2F\\u3005\\u3006\\u3031-\\u3035\\u303B\\u303C\\u3041-\\u3096\\u309D-\\u309F\\u30A1-\\u30FA\\u30FC-\\u30FF\\u3105-\\u312D\\u3131-\\u318E\\u31A0-\\u31B7\\u31F0-\\u31FF\\u3400\\u4DB5\\u4E00\\u9FC3\\uA000-\\uA48C\\uA500-\\uA60C\\uA610-\\uA61F\\uA62A\\uA62B\\uA640-\\uA65F\\uA662-\\uA66E\\uA67F-\\uA697\\uA717-\\uA71F\\uA722-\\uA788\\uA78B\\uA78C\\uA7FB-\\uA801\\uA803-\\uA805\\uA807-\\uA80A\\uA80C-\\uA822\\uA840-\\uA873\\uA882-\\uA8B3\\uA90A-\\uA925\\uA930-\\uA946\\uAA00-\\uAA28\\uAA40-\\uAA42\\uAA44-\\uAA4B\\uAC00\\uD7A3\\uF900-\\uFA2D\\uFA30-\\uFA6A\\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]"),
          non_spacing_mark: new RegExp("[\\u0300-\\u036F\\u0483-\\u0487\\u0591-\\u05BD\\u05BF\\u05C1\\u05C2\\u05C4\\u05C5\\u05C7\\u0610-\\u061A\\u064B-\\u065E\\u0670\\u06D6-\\u06DC\\u06DF-\\u06E4\\u06E7\\u06E8\\u06EA-\\u06ED\\u0711\\u0730-\\u074A\\u07A6-\\u07B0\\u07EB-\\u07F3\\u0816-\\u0819\\u081B-\\u0823\\u0825-\\u0827\\u0829-\\u082D\\u0900-\\u0902\\u093C\\u0941-\\u0948\\u094D\\u0951-\\u0955\\u0962\\u0963\\u0981\\u09BC\\u09C1-\\u09C4\\u09CD\\u09E2\\u09E3\\u0A01\\u0A02\\u0A3C\\u0A41\\u0A42\\u0A47\\u0A48\\u0A4B-\\u0A4D\\u0A51\\u0A70\\u0A71\\u0A75\\u0A81\\u0A82\\u0ABC\\u0AC1-\\u0AC5\\u0AC7\\u0AC8\\u0ACD\\u0AE2\\u0AE3\\u0B01\\u0B3C\\u0B3F\\u0B41-\\u0B44\\u0B4D\\u0B56\\u0B62\\u0B63\\u0B82\\u0BC0\\u0BCD\\u0C3E-\\u0C40\\u0C46-\\u0C48\\u0C4A-\\u0C4D\\u0C55\\u0C56\\u0C62\\u0C63\\u0CBC\\u0CBF\\u0CC6\\u0CCC\\u0CCD\\u0CE2\\u0CE3\\u0D41-\\u0D44\\u0D4D\\u0D62\\u0D63\\u0DCA\\u0DD2-\\u0DD4\\u0DD6\\u0E31\\u0E34-\\u0E3A\\u0E47-\\u0E4E\\u0EB1\\u0EB4-\\u0EB9\\u0EBB\\u0EBC\\u0EC8-\\u0ECD\\u0F18\\u0F19\\u0F35\\u0F37\\u0F39\\u0F71-\\u0F7E\\u0F80-\\u0F84\\u0F86\\u0F87\\u0F90-\\u0F97\\u0F99-\\u0FBC\\u0FC6\\u102D-\\u1030\\u1032-\\u1037\\u1039\\u103A\\u103D\\u103E\\u1058\\u1059\\u105E-\\u1060\\u1071-\\u1074\\u1082\\u1085\\u1086\\u108D\\u109D\\u135F\\u1712-\\u1714\\u1732-\\u1734\\u1752\\u1753\\u1772\\u1773\\u17B7-\\u17BD\\u17C6\\u17C9-\\u17D3\\u17DD\\u180B-\\u180D\\u18A9\\u1920-\\u1922\\u1927\\u1928\\u1932\\u1939-\\u193B\\u1A17\\u1A18\\u1A56\\u1A58-\\u1A5E\\u1A60\\u1A62\\u1A65-\\u1A6C\\u1A73-\\u1A7C\\u1A7F\\u1B00-\\u1B03\\u1B34\\u1B36-\\u1B3A\\u1B3C\\u1B42\\u1B6B-\\u1B73\\u1B80\\u1B81\\u1BA2-\\u1BA5\\u1BA8\\u1BA9\\u1C2C-\\u1C33\\u1C36\\u1C37\\u1CD0-\\u1CD2\\u1CD4-\\u1CE0\\u1CE2-\\u1CE8\\u1CED\\u1DC0-\\u1DE6\\u1DFD-\\u1DFF\\u20D0-\\u20DC\\u20E1\\u20E5-\\u20F0\\u2CEF-\\u2CF1\\u2DE0-\\u2DFF\\u302A-\\u302F\\u3099\\u309A\\uA66F\\uA67C\\uA67D\\uA6F0\\uA6F1\\uA802\\uA806\\uA80B\\uA825\\uA826\\uA8C4\\uA8E0-\\uA8F1\\uA926-\\uA92D\\uA947-\\uA951\\uA980-\\uA982\\uA9B3\\uA9B6-\\uA9B9\\uA9BC\\uAA29-\\uAA2E\\uAA31\\uAA32\\uAA35\\uAA36\\uAA43\\uAA4C\\uAAB0\\uAAB2-\\uAAB4\\uAAB7\\uAAB8\\uAABE\\uAABF\\uAAC1\\uABE5\\uABE8\\uABED\\uFB1E\\uFE00-\\uFE0F\\uFE20-\\uFE26]"),
          space_combining_mark: new RegExp("[\\u0903\\u093E-\\u0940\\u0949-\\u094C\\u094E\\u0982\\u0983\\u09BE-\\u09C0\\u09C7\\u09C8\\u09CB\\u09CC\\u09D7\\u0A03\\u0A3E-\\u0A40\\u0A83\\u0ABE-\\u0AC0\\u0AC9\\u0ACB\\u0ACC\\u0B02\\u0B03\\u0B3E\\u0B40\\u0B47\\u0B48\\u0B4B\\u0B4C\\u0B57\\u0BBE\\u0BBF\\u0BC1\\u0BC2\\u0BC6-\\u0BC8\\u0BCA-\\u0BCC\\u0BD7\\u0C01-\\u0C03\\u0C41-\\u0C44\\u0C82\\u0C83\\u0CBE\\u0CC0-\\u0CC4\\u0CC7\\u0CC8\\u0CCA\\u0CCB\\u0CD5\\u0CD6\\u0D02\\u0D03\\u0D3E-\\u0D40\\u0D46-\\u0D48\\u0D4A-\\u0D4C\\u0D57\\u0D82\\u0D83\\u0DCF-\\u0DD1\\u0DD8-\\u0DDF\\u0DF2\\u0DF3\\u0F3E\\u0F3F\\u0F7F\\u102B\\u102C\\u1031\\u1038\\u103B\\u103C\\u1056\\u1057\\u1062-\\u1064\\u1067-\\u106D\\u1083\\u1084\\u1087-\\u108C\\u108F\\u109A-\\u109C\\u17B6\\u17BE-\\u17C5\\u17C7\\u17C8\\u1923-\\u1926\\u1929-\\u192B\\u1930\\u1931\\u1933-\\u1938\\u19B0-\\u19C0\\u19C8\\u19C9\\u1A19-\\u1A1B\\u1A55\\u1A57\\u1A61\\u1A63\\u1A64\\u1A6D-\\u1A72\\u1B04\\u1B35\\u1B3B\\u1B3D-\\u1B41\\u1B43\\u1B44\\u1B82\\u1BA1\\u1BA6\\u1BA7\\u1BAA\\u1C24-\\u1C2B\\u1C34\\u1C35\\u1CE1\\u1CF2\\uA823\\uA824\\uA827\\uA880\\uA881\\uA8B4-\\uA8C3\\uA952\\uA953\\uA983\\uA9B4\\uA9B5\\uA9BA\\uA9BB\\uA9BD-\\uA9C0\\uAA2F\\uAA30\\uAA33\\uAA34\\uAA4D\\uAA7B\\uABE3\\uABE4\\uABE6\\uABE7\\uABE9\\uABEA\\uABEC]"),
          connector_punctuation: new RegExp("[\\u005F\\u203F\\u2040\\u2054\\uFE33\\uFE34\\uFE4D-\\uFE4F\\uFF3F]")
      };
      function is_letter(code) {
          return code >= 97 && code <= 122 || code >= 65 && code <= 90 || code >= 170 && UNICODE.letter.test(String.fromCharCode(code));
      }
      function is_digit(code) {
          return code >= 48 && code <= 57;
      }
      function is_alphanumeric_char(code) {
          return is_digit(code) || is_letter(code);
      }
      function is_unicode_combining_mark(ch) {
          return UNICODE.non_spacing_mark.test(ch) || UNICODE.space_combining_mark.test(ch);
      }
      function is_unicode_connector_punctuation(ch) {
          return UNICODE.connector_punctuation.test(ch);
      }
      function is_identifier(name) {
          return !RESERVED_WORDS(name) && /^[a-z_$][a-z0-9_$]*$/i.test(name);
      }
      function is_identifier_start(code) {
          return code == 36 || code == 95 || is_letter(code);
      }
      function is_identifier_char(ch) {
          var code = ch.charCodeAt(0);
          return is_identifier_start(code) || is_digit(code) || code == 8204 || code == 8205 || is_unicode_combining_mark(ch) || is_unicode_connector_punctuation(ch);
      }
      function is_identifier_string(str) {
          return /^[a-z_$][a-z0-9_$]*$/i.test(str);
      }
      function parse_js_number(num) {
          if (RE_HEX_NUMBER.test(num)) {
              return parseInt(num.substr(2), 16);
          } else if (RE_OCT_NUMBER.test(num)) {
              return parseInt(num.substr(1), 8);
          } else if (RE_DEC_NUMBER.test(num)) {
              return parseFloat(num);
          }
      }
      function JS_Parse_Error(message, line, col, pos) {
          this.message = message;
          this.line = line;
          this.col = col;
          this.pos = pos;
          this.stack = new Error().stack;
      }
      JS_Parse_Error.prototype.toString = function() {
          return this.message + " (line: " + this.line + ", col: " + this.col + ", pos: " + this.pos + ")" + "\n\n" + this.stack;
      };
      function js_error(message, filename, line, col, pos) {
          throw new JS_Parse_Error(message, line, col, pos);
      }
      function is_token(token, type, val) {
          return token.type == type && (val == null || token.value == val);
      }
      var EX_EOF = {};
      function tokenizer($TEXT, filename, html5_comments) {
          var S = {
              text: $TEXT.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/\uFEFF/g, ""),
              filename: filename,
              pos: 0,
              tokpos: 0,
              line: 1,
              tokline: 0,
              col: 0,
              tokcol: 0,
              newline_before: false,
              regex_allowed: false,
              comments_before: []
          };
          function peek() {
              return S.text.charAt(S.pos);
          }
          function next(signal_eof, in_string) {
              var ch = S.text.charAt(S.pos++);
              if (signal_eof && !ch) throw EX_EOF;
              if (ch == "\n") {
                  S.newline_before = S.newline_before || !in_string;
                  ++S.line;
                  S.col = 0;
              } else {
                  ++S.col;
              }
              return ch;
          }
          function forward(i) {
              while (i-- > 0) next();
          }
          function looking_at(str) {
              return S.text.substr(S.pos, str.length) == str;
          }
          function find(what, signal_eof) {
              var pos = S.text.indexOf(what, S.pos);
              if (signal_eof && pos == -1) throw EX_EOF;
              return pos;
          }
          function start_token() {
              S.tokline = S.line;
              S.tokcol = S.col;
              S.tokpos = S.pos;
          }
          var prev_was_dot = false;
          function token(type, value, is_comment) {
              S.regex_allowed = type == "operator" && !UNARY_POSTFIX(value) || type == "keyword" && KEYWORDS_BEFORE_EXPRESSION(value) || type == "punc" && PUNC_BEFORE_EXPRESSION(value);
              prev_was_dot = type == "punc" && value == ".";
              var ret = {
                  type: type,
                  value: value,
                  line: S.tokline,
                  col: S.tokcol,
                  pos: S.tokpos,
                  endpos: S.pos,
                  nlb: S.newline_before,
                  file: filename
              };
              if (!is_comment) {
                  ret.comments_before = S.comments_before;
                  S.comments_before = [];
                  for (var i = 0, len = ret.comments_before.length; i < len; i++) {
                      ret.nlb = ret.nlb || ret.comments_before[i].nlb;
                  }
              }
              S.newline_before = false;
              return new AST_Token(ret);
          }
          function skip_whitespace() {
              while (WHITESPACE_CHARS(peek())) next();
          }
          function read_while(pred) {
              var ret = "", ch, i = 0;
              while ((ch = peek()) && pred(ch, i++)) ret += next();
              return ret;
          }
          function parse_error(err) {
              js_error(err, filename, S.tokline, S.tokcol, S.tokpos);
          }
          function read_num(prefix) {
              var has_e = false, after_e = false, has_x = false, has_dot = prefix == ".";
              var num = read_while(function(ch, i) {
                  var code = ch.charCodeAt(0);
                  switch (code) {
                    case 120:
                    case 88:
                      return has_x ? false : has_x = true;
  
                    case 101:
                    case 69:
                      return has_x ? true : has_e ? false : has_e = after_e = true;
  
                    case 45:
                      return after_e || i == 0 && !prefix;
  
                    case 43:
                      return after_e;
  
                    case after_e = false, 46:
                      return !has_dot && !has_x && !has_e ? has_dot = true : false;
                  }
                  return is_alphanumeric_char(code);
              });
              if (prefix) num = prefix + num;
              var valid = parse_js_number(num);
              if (!isNaN(valid)) {
                  return token("num", valid);
              } else {
                  parse_error("Invalid syntax: " + num);
              }
          }
          function read_escaped_char(in_string) {
              var ch = next(true, in_string);
              switch (ch.charCodeAt(0)) {
                case 110:
                  return "\n";
  
                case 114:
                  return "\r";
  
                case 116:
                  return "	";
  
                case 98:
                  return "\b";
  
                case 118:
                  return "";
  
                case 102:
                  return "\f";
  
                case 48:
                  return "\x00";
  
                case 120:
                  return String.fromCharCode(hex_bytes(2));
  
                case 117:
                  return String.fromCharCode(hex_bytes(4));
  
                case 10:
                  return "";
  
                default:
                  return ch;
              }
          }
          function hex_bytes(n) {
              var num = 0;
              for (;n > 0; --n) {
                  var digit = parseInt(next(true), 16);
                  if (isNaN(digit)) parse_error("Invalid hex-character pattern in string");
                  num = num << 4 | digit;
              }
              return num;
          }
          var read_string = with_eof_error("Unterminated string constant", function() {
              var quote = next(), ret = "";
              for (;;) {
                  var ch = next(true);
                  if (ch == "\\") {
                      var octal_len = 0, first = null;
                      ch = read_while(function(ch) {
                          if (ch >= "0" && ch <= "7") {
                              if (!first) {
                                  first = ch;
                                  return ++octal_len;
                              } else if (first <= "3" && octal_len <= 2) return ++octal_len; else if (first >= "4" && octal_len <= 1) return ++octal_len;
                          }
                          return false;
                      });
                      if (octal_len > 0) ch = String.fromCharCode(parseInt(ch, 8)); else ch = read_escaped_char(true);
                  } else if (ch == quote) break;
                  ret += ch;
              }
              return token("string", ret);
          });
          function skip_line_comment(type) {
              var regex_allowed = S.regex_allowed;
              var i = find("\n"), ret;
              if (i == -1) {
                  ret = S.text.substr(S.pos);
                  S.pos = S.text.length;
              } else {
                  ret = S.text.substring(S.pos, i);
                  S.pos = i;
              }
              S.comments_before.push(token(type, ret, true));
              S.regex_allowed = regex_allowed;
              return next_token();
          }
          var skip_multiline_comment = with_eof_error("Unterminated multiline comment", function() {
              var regex_allowed = S.regex_allowed;
              var i = find("*/", true);
              var text = S.text.substring(S.pos, i);
              var a = text.split("\n"), n = a.length;
              S.pos = i + 2;
              S.line += n - 1;
              if (n > 1) S.col = a[n - 1].length; else S.col += a[n - 1].length;
              S.col += 2;
              var nlb = S.newline_before = S.newline_before || text.indexOf("\n") >= 0;
              S.comments_before.push(token("comment2", text, true));
              S.regex_allowed = regex_allowed;
              S.newline_before = nlb;
              return next_token();
          });
          function read_name() {
              var backslash = false, name = "", ch, escaped = false, hex;
              while ((ch = peek()) != null) {
                  if (!backslash) {
                      if (ch == "\\") escaped = backslash = true, next(); else if (is_identifier_char(ch)) name += next(); else break;
                  } else {
                      if (ch != "u") parse_error("Expecting UnicodeEscapeSequence -- uXXXX");
                      ch = read_escaped_char();
                      if (!is_identifier_char(ch)) parse_error("Unicode char: " + ch.charCodeAt(0) + " is not valid in identifier");
                      name += ch;
                      backslash = false;
                  }
              }
              if (KEYWORDS(name) && escaped) {
                  hex = name.charCodeAt(0).toString(16).toUpperCase();
                  name = "\\u" + "0000".substr(hex.length) + hex + name.slice(1);
              }
              return name;
          }
          var read_regexp = with_eof_error("Unterminated regular expression", function(regexp) {
              var prev_backslash = false, ch, in_class = false;
              while (ch = next(true)) if (prev_backslash) {
                  regexp += "\\" + ch;
                  prev_backslash = false;
              } else if (ch == "[") {
                  in_class = true;
                  regexp += ch;
              } else if (ch == "]" && in_class) {
                  in_class = false;
                  regexp += ch;
              } else if (ch == "/" && !in_class) {
                  break;
              } else if (ch == "\\") {
                  prev_backslash = true;
              } else {
                  regexp += ch;
              }
              var mods = read_name();
              return token("regexp", new RegExp(regexp, mods));
          });
          function read_operator(prefix) {
              function grow(op) {
                  if (!peek()) return op;
                  var bigger = op + peek();
                  if (OPERATORS(bigger)) {
                      next();
                      return grow(bigger);
                  } else {
                      return op;
                  }
              }
              return token("operator", grow(prefix || next()));
          }
          function handle_slash() {
              next();
              switch (peek()) {
                case "/":
                  next();
                  return skip_line_comment("comment1");
  
                case "*":
                  next();
                  return skip_multiline_comment();
              }
              return S.regex_allowed ? read_regexp("") : read_operator("/");
          }
          function handle_dot() {
              next();
              return is_digit(peek().charCodeAt(0)) ? read_num(".") : token("punc", ".");
          }
          function read_word() {
              var word = read_name();
              if (prev_was_dot) return token("name", word);
              return KEYWORDS_ATOM(word) ? token("atom", word) : !KEYWORDS(word) ? token("name", word) : OPERATORS(word) ? token("operator", word) : token("keyword", word);
          }
          function with_eof_error(eof_error, cont) {
              return function(x) {
                  try {
                      return cont(x);
                  } catch (ex) {
                      if (ex === EX_EOF) parse_error(eof_error); else throw ex;
                  }
              };
          }
          function next_token(force_regexp) {
              if (force_regexp != null) return read_regexp(force_regexp);
              skip_whitespace();
              start_token();
              if (html5_comments) {
                  if (looking_at("<!--")) {
                      forward(4);
                      return skip_line_comment("comment3");
                  }
                  if (looking_at("-->") && S.newline_before) {
                      forward(3);
                      return skip_line_comment("comment4");
                  }
              }
              var ch = peek();
              if (!ch) return token("eof");
              var code = ch.charCodeAt(0);
              switch (code) {
                case 34:
                case 39:
                  return read_string();
  
                case 46:
                  return handle_dot();
  
                case 47:
                  return handle_slash();
              }
              if (is_digit(code)) return read_num();
              if (PUNC_CHARS(ch)) return token("punc", next());
              if (OPERATOR_CHARS(ch)) return read_operator();
              if (code == 92 || is_identifier_start(code)) return read_word();
              parse_error("Unexpected character '" + ch + "'");
          }
          next_token.context = function(nc) {
              if (nc) S = nc;
              return S;
          };
          return next_token;
      }
      var UNARY_PREFIX = makePredicate([ "typeof", "void", "delete", "--", "++", "!", "~", "-", "+" ]);
      var UNARY_POSTFIX = makePredicate([ "--", "++" ]);
      var ASSIGNMENT = makePredicate([ "=", "+=", "-=", "/=", "*=", "%=", ">>=", "<<=", ">>>=", "|=", "^=", "&=" ]);
      var PRECEDENCE = function(a, ret) {
          for (var i = 0; i < a.length; ++i) {
              var b = a[i];
              for (var j = 0; j < b.length; ++j) {
                  ret[b[j]] = i + 1;
              }
          }
          return ret;
      }([ [ "||" ], [ "&&" ], [ "|" ], [ "^" ], [ "&" ], [ "==", "===", "!=", "!==" ], [ "<", ">", "<=", ">=", "in", "instanceof" ], [ ">>", "<<", ">>>" ], [ "+", "-" ], [ "*", "/", "%" ] ], {});
      var STATEMENTS_WITH_LABELS = array_to_hash([ "for", "do", "while", "switch" ]);
      var ATOMIC_START_TOKEN = array_to_hash([ "atom", "num", "string", "regexp", "name" ]);
      function parse($TEXT, options) {
          options = defaults(options, {
              strict: false,
              filename: null,
              toplevel: null,
              expression: false,
              html5_comments: true
          });
          var S = {
              input: typeof $TEXT == "string" ? tokenizer($TEXT, options.filename, options.html5_comments) : $TEXT,
              token: null,
              prev: null,
              peeked: null,
              in_function: 0,
              in_directives: true,
              in_loop: 0,
              labels: []
          };
          S.token = next();
          function is(type, value) {
              return is_token(S.token, type, value);
          }
          function peek() {
              return S.peeked || (S.peeked = S.input());
          }
          function next() {
              S.prev = S.token;
              if (S.peeked) {
                  S.token = S.peeked;
                  S.peeked = null;
              } else {
                  S.token = S.input();
              }
              S.in_directives = S.in_directives && (S.token.type == "string" || is("punc", ";"));
              return S.token;
          }
          function prev() {
              return S.prev;
          }
          function croak(msg, line, col, pos) {
              var ctx = S.input.context();
              js_error(msg, ctx.filename, line != null ? line : ctx.tokline, col != null ? col : ctx.tokcol, pos != null ? pos : ctx.tokpos);
          }
          function token_error(token, msg) {
              croak(msg, token.line, token.col);
          }
          function unexpected(token) {
              if (token == null) token = S.token;
              token_error(token, "Unexpected token: " + token.type + " (" + token.value + ")");
          }
          function expect_token(type, val) {
              if (is(type, val)) {
                  return next();
              }
              token_error(S.token, "Unexpected token " + S.token.type + " «" + S.token.value + "»" + ", expected " + type + " «" + val + "»");
          }
          function expect(punc) {
              return expect_token("punc", punc);
          }
          function can_insert_semicolon() {
              return !options.strict && (S.token.nlb || is("eof") || is("punc", "}"));
          }
          function semicolon() {
              if (is("punc", ";")) next(); else if (!can_insert_semicolon()) unexpected();
          }
          function parenthesised() {
              expect("(");
              var exp = expression(true);
              expect(")");
              return exp;
          }
          function embed_tokens(parser) {
              return function() {
                  var start = S.token;
                  var expr = parser();
                  var end = prev();
                  expr.start = start;
                  expr.end = end;
                  return expr;
              };
          }
          function handle_regexp() {
              if (is("operator", "/") || is("operator", "/=")) {
                  S.peeked = null;
                  S.token = S.input(S.token.value.substr(1));
              }
          }
          var statement = embed_tokens(function() {
              var tmp;
              handle_regexp();
              switch (S.token.type) {
                case "string":
                  var dir = S.in_directives, stat = simple_statement();
                  if (dir && stat.body instanceof AST_String && !is("punc", ",")) return new AST_Directive({
                      value: stat.body.value
                  });
                  return stat;
  
                case "num":
                case "regexp":
                case "operator":
                case "atom":
                  return simple_statement();
  
                case "name":
                  return is_token(peek(), "punc", ":") ? labeled_statement() : simple_statement();
  
                case "punc":
                  switch (S.token.value) {
                    case "{":
                      return new AST_BlockStatement({
                          start: S.token,
                          body: block_(),
                          end: prev()
                      });
  
                    case "[":
                    case "(":
                      return simple_statement();
  
                    case ";":
                      next();
                      return new AST_EmptyStatement();
  
                    default:
                      unexpected();
                  }
  
                case "keyword":
                  switch (tmp = S.token.value, next(), tmp) {
                    case "break":
                      return break_cont(AST_Break);
  
                    case "continue":
                      return break_cont(AST_Continue);
  
                    case "debugger":
                      semicolon();
                      return new AST_Debugger();
  
                    case "do":
                      return new AST_Do({
                          body: in_loop(statement),
                          condition: (expect_token("keyword", "while"), tmp = parenthesised(), semicolon(), 
                          tmp)
                      });
  
                    case "while":
                      return new AST_While({
                          condition: parenthesised(),
                          body: in_loop(statement)
                      });
  
                    case "for":
                      return for_();
  
                    case "function":
                      return function_(AST_Defun);
  
                    case "if":
                      return if_();
  
                    case "return":
                      if (S.in_function == 0) croak("'return' outside of function");
                      return new AST_Return({
                          value: is("punc", ";") ? (next(), null) : can_insert_semicolon() ? null : (tmp = expression(true), 
                          semicolon(), tmp)
                      });
  
                    case "switch":
                      return new AST_Switch({
                          expression: parenthesised(),
                          body: in_loop(switch_body_)
                      });
  
                    case "throw":
                      if (S.token.nlb) croak("Illegal newline after 'throw'");
                      return new AST_Throw({
                          value: (tmp = expression(true), semicolon(), tmp)
                      });
  
                    case "try":
                      return try_();
  
                    case "var":
                      return tmp = var_(), semicolon(), tmp;
  
                    case "const":
                      return tmp = const_(), semicolon(), tmp;
  
                    case "with":
                      return new AST_With({
                          expression: parenthesised(),
                          body: statement()
                      });
  
                    default:
                      unexpected();
                  }
              }
          });
          function labeled_statement() {
              var label = as_symbol(AST_Label);
              if (find_if(function(l) {
                  return l.name == label.name;
              }, S.labels)) {
                  croak("Label " + label.name + " defined twice");
              }
              expect(":");
              S.labels.push(label);
              var stat = statement();
              S.labels.pop();
              if (!(stat instanceof AST_IterationStatement)) {
                  label.references.forEach(function(ref) {
                      if (ref instanceof AST_Continue) {
                          ref = ref.label.start;
                          croak("Continue label `" + label.name + "` refers to non-IterationStatement.", ref.line, ref.col, ref.pos);
                      }
                  });
              }
              return new AST_LabeledStatement({
                  body: stat,
                  label: label
              });
          }
          function simple_statement(tmp) {
              return new AST_SimpleStatement({
                  body: (tmp = expression(true), semicolon(), tmp)
              });
          }
          function break_cont(type) {
              var label = null, ldef;
              if (!can_insert_semicolon()) {
                  label = as_symbol(AST_LabelRef, true);
              }
              if (label != null) {
                  ldef = find_if(function(l) {
                      return l.name == label.name;
                  }, S.labels);
                  if (!ldef) croak("Undefined label " + label.name);
                  label.thedef = ldef;
              } else if (S.in_loop == 0) croak(type.TYPE + " not inside a loop or switch");
              semicolon();
              var stat = new type({
                  label: label
              });
              if (ldef) ldef.references.push(stat);
              return stat;
          }
          function for_() {
              expect("(");
              var init = null;
              if (!is("punc", ";")) {
                  init = is("keyword", "var") ? (next(), var_(true)) : expression(true, true);
                  if (is("operator", "in")) {
                      if (init instanceof AST_Var && init.definitions.length > 1) croak("Only one variable declaration allowed in for..in loop");
                      next();
                      return for_in(init);
                  }
              }
              return regular_for(init);
          }
          function regular_for(init) {
              expect(";");
              var test = is("punc", ";") ? null : expression(true);
              expect(";");
              var step = is("punc", ")") ? null : expression(true);
              expect(")");
              return new AST_For({
                  init: init,
                  condition: test,
                  step: step,
                  body: in_loop(statement)
              });
          }
          function for_in(init) {
              var lhs = init instanceof AST_Var ? init.definitions[0].name : null;
              var obj = expression(true);
              expect(")");
              return new AST_ForIn({
                  init: init,
                  name: lhs,
                  object: obj,
                  body: in_loop(statement)
              });
          }
          var function_ = function(ctor) {
              var in_statement = ctor === AST_Defun;
              var name = is("name") ? as_symbol(in_statement ? AST_SymbolDefun : AST_SymbolLambda) : null;
              if (in_statement && !name) unexpected();
              expect("(");
              return new ctor({
                  name: name,
                  argnames: function(first, a) {
                      while (!is("punc", ")")) {
                          if (first) first = false; else expect(",");
                          a.push(as_symbol(AST_SymbolFunarg));
                      }
                      next();
                      return a;
                  }(true, []),
                  body: function(loop, labels) {
                      ++S.in_function;
                      S.in_directives = true;
                      S.in_loop = 0;
                      S.labels = [];
                      var a = block_();
                      --S.in_function;
                      S.in_loop = loop;
                      S.labels = labels;
                      return a;
                  }(S.in_loop, S.labels)
              });
          };
          function if_() {
              var cond = parenthesised(), body = statement(), belse = null;
              if (is("keyword", "else")) {
                  next();
                  belse = statement();
              }
              return new AST_If({
                  condition: cond,
                  body: body,
                  alternative: belse
              });
          }
          function block_() {
              expect("{");
              var a = [];
              while (!is("punc", "}")) {
                  if (is("eof")) unexpected();
                  a.push(statement());
              }
              next();
              return a;
          }
          function switch_body_() {
              expect("{");
              var a = [], cur = null, branch = null, tmp;
              while (!is("punc", "}")) {
                  if (is("eof")) unexpected();
                  if (is("keyword", "case")) {
                      if (branch) branch.end = prev();
                      cur = [];
                      branch = new AST_Case({
                          start: (tmp = S.token, next(), tmp),
                          expression: expression(true),
                          body: cur
                      });
                      a.push(branch);
                      expect(":");
                  } else if (is("keyword", "default")) {
                      if (branch) branch.end = prev();
                      cur = [];
                      branch = new AST_Default({
                          start: (tmp = S.token, next(), expect(":"), tmp),
                          body: cur
                      });
                      a.push(branch);
                  } else {
                      if (!cur) unexpected();
                      cur.push(statement());
                  }
              }
              if (branch) branch.end = prev();
              next();
              return a;
          }
          function try_() {
              var body = block_(), bcatch = null, bfinally = null;
              if (is("keyword", "catch")) {
                  var start = S.token;
                  next();
                  expect("(");
                  var name = as_symbol(AST_SymbolCatch);
                  expect(")");
                  bcatch = new AST_Catch({
                      start: start,
                      argname: name,
                      body: block_(),
                      end: prev()
                  });
              }
              if (is("keyword", "finally")) {
                  var start = S.token;
                  next();
                  bfinally = new AST_Finally({
                      start: start,
                      body: block_(),
                      end: prev()
                  });
              }
              if (!bcatch && !bfinally) croak("Missing catch/finally blocks");
              return new AST_Try({
                  body: body,
                  bcatch: bcatch,
                  bfinally: bfinally
              });
          }
          function vardefs(no_in, in_const) {
              var a = [];
              for (;;) {
                  a.push(new AST_VarDef({
                      start: S.token,
                      name: as_symbol(in_const ? AST_SymbolConst : AST_SymbolVar),
                      value: is("operator", "=") ? (next(), expression(false, no_in)) : null,
                      end: prev()
                  }));
                  if (!is("punc", ",")) break;
                  next();
              }
              return a;
          }
          var var_ = function(no_in) {
              return new AST_Var({
                  start: prev(),
                  definitions: vardefs(no_in, false),
                  end: prev()
              });
          };
          var const_ = function() {
              return new AST_Const({
                  start: prev(),
                  definitions: vardefs(false, true),
                  end: prev()
              });
          };
          var new_ = function() {
              var start = S.token;
              expect_token("operator", "new");
              var newexp = expr_atom(false), args;
              if (is("punc", "(")) {
                  next();
                  args = expr_list(")");
              } else {
                  args = [];
              }
              return subscripts(new AST_New({
                  start: start,
                  expression: newexp,
                  args: args,
                  end: prev()
              }), true);
          };
          function as_atom_node() {
              var tok = S.token, ret;
              switch (tok.type) {
                case "name":
                case "keyword":
                  ret = _make_symbol(AST_SymbolRef);
                  break;
  
                case "num":
                  ret = new AST_Number({
                      start: tok,
                      end: tok,
                      value: tok.value
                  });
                  break;
  
                case "string":
                  ret = new AST_String({
                      start: tok,
                      end: tok,
                      value: tok.value
                  });
                  break;
  
                case "regexp":
                  ret = new AST_RegExp({
                      start: tok,
                      end: tok,
                      value: tok.value
                  });
                  break;
  
                case "atom":
                  switch (tok.value) {
                    case "false":
                      ret = new AST_False({
                          start: tok,
                          end: tok
                      });
                      break;
  
                    case "true":
                      ret = new AST_True({
                          start: tok,
                          end: tok
                      });
                      break;
  
                    case "null":
                      ret = new AST_Null({
                          start: tok,
                          end: tok
                      });
                      break;
                  }
                  break;
              }
              next();
              return ret;
          }
          var expr_atom = function(allow_calls) {
              if (is("operator", "new")) {
                  return new_();
              }
              var start = S.token;
              if (is("punc")) {
                  switch (start.value) {
                    case "(":
                      next();
                      var ex = expression(true);
                      ex.start = start;
                      ex.end = S.token;
                      expect(")");
                      return subscripts(ex, allow_calls);
  
                    case "[":
                      return subscripts(array_(), allow_calls);
  
                    case "{":
                      return subscripts(object_(), allow_calls);
                  }
                  unexpected();
              }
              if (is("keyword", "function")) {
                  next();
                  var func = function_(AST_Function);
                  func.start = start;
                  func.end = prev();
                  return subscripts(func, allow_calls);
              }
              if (ATOMIC_START_TOKEN[S.token.type]) {
                  return subscripts(as_atom_node(), allow_calls);
              }
              unexpected();
          };
          function expr_list(closing, allow_trailing_comma, allow_empty) {
              var first = true, a = [];
              while (!is("punc", closing)) {
                  if (first) first = false; else expect(",");
                  if (allow_trailing_comma && is("punc", closing)) break;
                  if (is("punc", ",") && allow_empty) {
                      a.push(new AST_Hole({
                          start: S.token,
                          end: S.token
                      }));
                  } else {
                      a.push(expression(false));
                  }
              }
              next();
              return a;
          }
          var array_ = embed_tokens(function() {
              expect("[");
              return new AST_Array({
                  elements: expr_list("]", !options.strict, true)
              });
          });
          var object_ = embed_tokens(function() {
              expect("{");
              var first = true, a = [];
              while (!is("punc", "}")) {
                  if (first) first = false; else expect(",");
                  if (!options.strict && is("punc", "}")) break;
                  var start = S.token;
                  var type = start.type;
                  var name = as_property_name();
                  if (type == "name" && !is("punc", ":")) {
                      if (name == "get") {
                          a.push(new AST_ObjectGetter({
                              start: start,
                              key: as_atom_node(),
                              value: function_(AST_Accessor),
                              end: prev()
                          }));
                          continue;
                      }
                      if (name == "set") {
                          a.push(new AST_ObjectSetter({
                              start: start,
                              key: as_atom_node(),
                              value: function_(AST_Accessor),
                              end: prev()
                          }));
                          continue;
                      }
                  }
                  expect(":");
                  a.push(new AST_ObjectKeyVal({
                      start: start,
                      key: name,
                      value: expression(false),
                      end: prev()
                  }));
              }
              next();
              return new AST_Object({
                  properties: a
              });
          });
          function as_property_name() {
              var tmp = S.token;
              next();
              switch (tmp.type) {
                case "num":
                case "string":
                case "name":
                case "operator":
                case "keyword":
                case "atom":
                  return tmp.value;
  
                default:
                  unexpected();
              }
          }
          function as_name() {
              var tmp = S.token;
              next();
              switch (tmp.type) {
                case "name":
                case "operator":
                case "keyword":
                case "atom":
                  return tmp.value;
  
                default:
                  unexpected();
              }
          }
          function _make_symbol(type) {
              var name = S.token.value;
              return new (name == "this" ? AST_This : type)({
                  name: String(name),
                  start: S.token,
                  end: S.token
              });
          }
          function as_symbol(type, noerror) {
              if (!is("name")) {
                  if (!noerror) croak("Name expected");
                  return null;
              }
              var sym = _make_symbol(type);
              next();
              return sym;
          }
          var subscripts = function(expr, allow_calls) {
              var start = expr.start;
              if (is("punc", ".")) {
                  next();
                  return subscripts(new AST_Dot({
                      start: start,
                      expression: expr,
                      property: as_name(),
                      end: prev()
                  }), allow_calls);
              }
              if (is("punc", "[")) {
                  next();
                  var prop = expression(true);
                  expect("]");
                  return subscripts(new AST_Sub({
                      start: start,
                      expression: expr,
                      property: prop,
                      end: prev()
                  }), allow_calls);
              }
              if (allow_calls && is("punc", "(")) {
                  next();
                  return subscripts(new AST_Call({
                      start: start,
                      expression: expr,
                      args: expr_list(")"),
                      end: prev()
                  }), true);
              }
              return expr;
          };
          var maybe_unary = function(allow_calls) {
              var start = S.token;
              if (is("operator") && UNARY_PREFIX(start.value)) {
                  next();
                  handle_regexp();
                  var ex = make_unary(AST_UnaryPrefix, start.value, maybe_unary(allow_calls));
                  ex.start = start;
                  ex.end = prev();
                  return ex;
              }
              var val = expr_atom(allow_calls);
              while (is("operator") && UNARY_POSTFIX(S.token.value) && !S.token.nlb) {
                  val = make_unary(AST_UnaryPostfix, S.token.value, val);
                  val.start = start;
                  val.end = S.token;
                  next();
              }
              return val;
          };
          function make_unary(ctor, op, expr) {
              if ((op == "++" || op == "--") && !is_assignable(expr)) croak("Invalid use of " + op + " operator");
              return new ctor({
                  operator: op,
                  expression: expr
              });
          }
          var expr_op = function(left, min_prec, no_in) {
              var op = is("operator") ? S.token.value : null;
              if (op == "in" && no_in) op = null;
              var prec = op != null ? PRECEDENCE[op] : null;
              if (prec != null && prec > min_prec) {
                  next();
                  var right = expr_op(maybe_unary(true), prec, no_in);
                  return expr_op(new AST_Binary({
                      start: left.start,
                      left: left,
                      operator: op,
                      right: right,
                      end: right.end
                  }), min_prec, no_in);
              }
              return left;
          };
          function expr_ops(no_in) {
              return expr_op(maybe_unary(true), 0, no_in);
          }
          var maybe_conditional = function(no_in) {
              var start = S.token;
              var expr = expr_ops(no_in);
              if (is("operator", "?")) {
                  next();
                  var yes = expression(false);
                  expect(":");
                  return new AST_Conditional({
                      start: start,
                      condition: expr,
                      consequent: yes,
                      alternative: expression(false, no_in),
                      end: prev()
                  });
              }
              return expr;
          };
          function is_assignable(expr) {
              if (!options.strict) return true;
              if (expr instanceof AST_This) return false;
              return expr instanceof AST_PropAccess || expr instanceof AST_Symbol;
          }
          var maybe_assign = function(no_in) {
              var start = S.token;
              var left = maybe_conditional(no_in), val = S.token.value;
              if (is("operator") && ASSIGNMENT(val)) {
                  if (is_assignable(left)) {
                      next();
                      return new AST_Assign({
                          start: start,
                          left: left,
                          operator: val,
                          right: maybe_assign(no_in),
                          end: prev()
                      });
                  }
                  croak("Invalid assignment");
              }
              return left;
          };
          var expression = function(commas, no_in) {
              var start = S.token;
              var expr = maybe_assign(no_in);
              if (commas && is("punc", ",")) {
                  next();
                  return new AST_Seq({
                      start: start,
                      car: expr,
                      cdr: expression(true, no_in),
                      end: peek()
                  });
              }
              return expr;
          };
          function in_loop(cont) {
              ++S.in_loop;
              var ret = cont();
              --S.in_loop;
              return ret;
          }
          if (options.expression) {
              return expression(true);
          }
          return function() {
              var start = S.token;
              var body = [];
              while (!is("eof")) body.push(statement());
              var end = prev();
              var toplevel = options.toplevel;
              if (toplevel) {
                  toplevel.body = toplevel.body.concat(body);
                  toplevel.end = end;
              } else {
                  toplevel = new AST_Toplevel({
                      start: start,
                      body: body,
                      end: end
                  });
              }
              return toplevel;
          }();
      }
      "use strict";
      function TreeTransformer(before, after) {
          TreeWalker.call(this);
          this.before = before;
          this.after = after;
      }
      TreeTransformer.prototype = new TreeWalker();
      (function(undefined) {
          function _(node, descend) {
              node.DEFMETHOD("transform", function(tw, in_list) {
                  var x, y;
                  tw.push(this);
                  if (tw.before) x = tw.before(this, descend, in_list);
                  if (x === undefined) {
                      if (!tw.after) {
                          x = this;
                          descend(x, tw);
                      } else {
                          tw.stack[tw.stack.length - 1] = x = this.clone();
                          descend(x, tw);
                          y = tw.after(x, in_list);
                          if (y !== undefined) x = y;
                      }
                  }
                  tw.pop();
                  return x;
              });
          }
          function do_list(list, tw) {
              return MAP(list, function(node) {
                  return node.transform(tw, true);
              });
          }
          _(AST_Node, noop);
          _(AST_LabeledStatement, function(self, tw) {
              self.label = self.label.transform(tw);
              self.body = self.body.transform(tw);
          });
          _(AST_SimpleStatement, function(self, tw) {
              self.body = self.body.transform(tw);
          });
          _(AST_Block, function(self, tw) {
              self.body = do_list(self.body, tw);
          });
          _(AST_DWLoop, function(self, tw) {
              self.condition = self.condition.transform(tw);
              self.body = self.body.transform(tw);
          });
          _(AST_For, function(self, tw) {
              if (self.init) self.init = self.init.transform(tw);
              if (self.condition) self.condition = self.condition.transform(tw);
              if (self.step) self.step = self.step.transform(tw);
              self.body = self.body.transform(tw);
          });
          _(AST_ForIn, function(self, tw) {
              self.init = self.init.transform(tw);
              self.object = self.object.transform(tw);
              self.body = self.body.transform(tw);
          });
          _(AST_With, function(self, tw) {
              self.expression = self.expression.transform(tw);
              self.body = self.body.transform(tw);
          });
          _(AST_Exit, function(self, tw) {
              if (self.value) self.value = self.value.transform(tw);
          });
          _(AST_LoopControl, function(self, tw) {
              if (self.label) self.label = self.label.transform(tw);
          });
          _(AST_If, function(self, tw) {
              self.condition = self.condition.transform(tw);
              self.body = self.body.transform(tw);
              if (self.alternative) self.alternative = self.alternative.transform(tw);
          });
          _(AST_Switch, function(self, tw) {
              self.expression = self.expression.transform(tw);
              self.body = do_list(self.body, tw);
          });
          _(AST_Case, function(self, tw) {
              self.expression = self.expression.transform(tw);
              self.body = do_list(self.body, tw);
          });
          _(AST_Try, function(self, tw) {
              self.body = do_list(self.body, tw);
              if (self.bcatch) self.bcatch = self.bcatch.transform(tw);
              if (self.bfinally) self.bfinally = self.bfinally.transform(tw);
          });
          _(AST_Catch, function(self, tw) {
              self.argname = self.argname.transform(tw);
              self.body = do_list(self.body, tw);
          });
          _(AST_Definitions, function(self, tw) {
              self.definitions = do_list(self.definitions, tw);
          });
          _(AST_VarDef, function(self, tw) {
              self.name = self.name.transform(tw);
              if (self.value) self.value = self.value.transform(tw);
          });
          _(AST_Lambda, function(self, tw) {
              if (self.name) self.name = self.name.transform(tw);
              self.argnames = do_list(self.argnames, tw);
              self.body = do_list(self.body, tw);
          });
          _(AST_Call, function(self, tw) {
              self.expression = self.expression.transform(tw);
              self.args = do_list(self.args, tw);
          });
          _(AST_Seq, function(self, tw) {
              self.car = self.car.transform(tw);
              self.cdr = self.cdr.transform(tw);
          });
          _(AST_Dot, function(self, tw) {
              self.expression = self.expression.transform(tw);
          });
          _(AST_Sub, function(self, tw) {
              self.expression = self.expression.transform(tw);
              self.property = self.property.transform(tw);
          });
          _(AST_Unary, function(self, tw) {
              self.expression = self.expression.transform(tw);
          });
          _(AST_Binary, function(self, tw) {
              self.left = self.left.transform(tw);
              self.right = self.right.transform(tw);
          });
          _(AST_Conditional, function(self, tw) {
              self.condition = self.condition.transform(tw);
              self.consequent = self.consequent.transform(tw);
              self.alternative = self.alternative.transform(tw);
          });
          _(AST_Array, function(self, tw) {
              self.elements = do_list(self.elements, tw);
          });
          _(AST_Object, function(self, tw) {
              self.properties = do_list(self.properties, tw);
          });
          _(AST_ObjectProperty, function(self, tw) {
              self.value = self.value.transform(tw);
          });
      })();
      "use strict";
      function SymbolDef(scope, index, orig) {
          this.name = orig.name;
          this.orig = [ orig ];
          this.scope = scope;
          this.references = [];
          this.global = false;
          this.mangled_name = null;
          this.undeclared = false;
          this.constant = false;
          this.index = index;
      }
      SymbolDef.prototype = {
          unmangleable: function(options) {
              return this.global && !(options && options.toplevel) || this.undeclared || !(options && options.eval) && (this.scope.uses_eval || this.scope.uses_with);
          },
          mangle: function(options) {
              if (!this.mangled_name && !this.unmangleable(options)) {
                  var s = this.scope;
                  if (!options.screw_ie8 && this.orig[0] instanceof AST_SymbolLambda) s = s.parent_scope;
                  this.mangled_name = s.next_mangled(options, this);
              }
          }
      };
      AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
          options = defaults(options, {
              screw_ie8: false
          });
          var self = this;
          var scope = self.parent_scope = null;
          var defun = null;
          var nesting = 0;
          var tw = new TreeWalker(function(node, descend) {
              if (options.screw_ie8 && node instanceof AST_Catch) {
                  var save_scope = scope;
                  scope = new AST_Scope(node);
                  scope.init_scope_vars(nesting);
                  scope.parent_scope = save_scope;
                  descend();
                  scope = save_scope;
                  return true;
              }
              if (node instanceof AST_Scope) {
                  node.init_scope_vars(nesting);
                  var save_scope = node.parent_scope = scope;
                  var save_defun = defun;
                  defun = scope = node;
                  ++nesting;
                  descend();
                  --nesting;
                  scope = save_scope;
                  defun = save_defun;
                  return true;
              }
              if (node instanceof AST_Directive) {
                  node.scope = scope;
                  push_uniq(scope.directives, node.value);
                  return true;
              }
              if (node instanceof AST_With) {
                  for (var s = scope; s; s = s.parent_scope) s.uses_with = true;
                  return;
              }
              if (node instanceof AST_Symbol) {
                  node.scope = scope;
              }
              if (node instanceof AST_SymbolLambda) {
                  defun.def_function(node);
              } else if (node instanceof AST_SymbolDefun) {
                  (node.scope = defun.parent_scope).def_function(node);
              } else if (node instanceof AST_SymbolVar || node instanceof AST_SymbolConst) {
                  var def = defun.def_variable(node);
                  def.constant = node instanceof AST_SymbolConst;
                  def.init = tw.parent().value;
              } else if (node instanceof AST_SymbolCatch) {
                  (options.screw_ie8 ? scope : defun).def_variable(node);
              }
          });
          self.walk(tw);
          var func = null;
          var globals = self.globals = new Dictionary();
          var tw = new TreeWalker(function(node, descend) {
              if (node instanceof AST_Lambda) {
                  var prev_func = func;
                  func = node;
                  descend();
                  func = prev_func;
                  return true;
              }
              if (node instanceof AST_SymbolRef) {
                  var name = node.name;
                  var sym = node.scope.find_variable(name);
                  if (!sym) {
                      var g;
                      if (globals.has(name)) {
                          g = globals.get(name);
                      } else {
                          g = new SymbolDef(self, globals.size(), node);
                          g.undeclared = true;
                          g.global = true;
                          globals.set(name, g);
                      }
                      node.thedef = g;
                      if (name == "eval" && tw.parent() instanceof AST_Call) {
                          for (var s = node.scope; s && !s.uses_eval; s = s.parent_scope) s.uses_eval = true;
                      }
                      if (func && name == "arguments") {
                          func.uses_arguments = true;
                      }
                  } else {
                      node.thedef = sym;
                  }
                  node.reference();
                  return true;
              }
          });
          self.walk(tw);
      });
      AST_Scope.DEFMETHOD("init_scope_vars", function(nesting) {
          this.directives = [];
          this.variables = new Dictionary();
          this.functions = new Dictionary();
          this.uses_with = false;
          this.uses_eval = false;
          this.parent_scope = null;
          this.enclosed = [];
          this.cname = -1;
          this.nesting = nesting;
      });
      AST_Scope.DEFMETHOD("strict", function() {
          return this.has_directive("use strict");
      });
      AST_Lambda.DEFMETHOD("init_scope_vars", function() {
          AST_Scope.prototype.init_scope_vars.apply(this, arguments);
          this.uses_arguments = false;
      });
      AST_SymbolRef.DEFMETHOD("reference", function() {
          var def = this.definition();
          def.references.push(this);
          var s = this.scope;
          while (s) {
              push_uniq(s.enclosed, def);
              if (s === def.scope) break;
              s = s.parent_scope;
          }
          this.frame = this.scope.nesting - def.scope.nesting;
      });
      AST_Scope.DEFMETHOD("find_variable", function(name) {
          if (name instanceof AST_Symbol) name = name.name;
          return this.variables.get(name) || this.parent_scope && this.parent_scope.find_variable(name);
      });
      AST_Scope.DEFMETHOD("has_directive", function(value) {
          return this.parent_scope && this.parent_scope.has_directive(value) || (this.directives.indexOf(value) >= 0 ? this : null);
      });
      AST_Scope.DEFMETHOD("def_function", function(symbol) {
          this.functions.set(symbol.name, this.def_variable(symbol));
      });
      AST_Scope.DEFMETHOD("def_variable", function(symbol) {
          var def;
          if (!this.variables.has(symbol.name)) {
              def = new SymbolDef(this, this.variables.size(), symbol);
              this.variables.set(symbol.name, def);
              def.global = !this.parent_scope;
          } else {
              def = this.variables.get(symbol.name);
              def.orig.push(symbol);
          }
          return symbol.thedef = def;
      });
      AST_Scope.DEFMETHOD("next_mangled", function(options) {
          var ext = this.enclosed;
          out: while (true) {
              var m = base54(++this.cname);
              if (!is_identifier(m)) continue;
              if (options.except.indexOf(m) >= 0) continue;
              for (var i = ext.length; --i >= 0; ) {
                  var sym = ext[i];
                  var name = sym.mangled_name || sym.unmangleable(options) && sym.name;
                  if (m == name) continue out;
              }
              return m;
          }
      });
      AST_Function.DEFMETHOD("next_mangled", function(options, def) {
          var tricky_def = def.orig[0] instanceof AST_SymbolFunarg && this.name && this.name.definition();
          while (true) {
              var name = AST_Lambda.prototype.next_mangled.call(this, options, def);
              if (!(tricky_def && tricky_def.mangled_name == name)) return name;
          }
      });
      AST_Scope.DEFMETHOD("references", function(sym) {
          if (sym instanceof AST_Symbol) sym = sym.definition();
          return this.enclosed.indexOf(sym) < 0 ? null : sym;
      });
      AST_Symbol.DEFMETHOD("unmangleable", function(options) {
          return this.definition().unmangleable(options);
      });
      AST_SymbolAccessor.DEFMETHOD("unmangleable", function() {
          return true;
      });
      AST_Label.DEFMETHOD("unmangleable", function() {
          return false;
      });
      AST_Symbol.DEFMETHOD("unreferenced", function() {
          return this.definition().references.length == 0 && !(this.scope.uses_eval || this.scope.uses_with);
      });
      AST_Symbol.DEFMETHOD("undeclared", function() {
          return this.definition().undeclared;
      });
      AST_LabelRef.DEFMETHOD("undeclared", function() {
          return false;
      });
      AST_Label.DEFMETHOD("undeclared", function() {
          return false;
      });
      AST_Symbol.DEFMETHOD("definition", function() {
          return this.thedef;
      });
      AST_Symbol.DEFMETHOD("global", function() {
          return this.definition().global;
      });
      AST_Toplevel.DEFMETHOD("_default_mangler_options", function(options) {
          return defaults(options, {
              except: [],
              eval: false,
              sort: false,
              toplevel: false,
              screw_ie8: false
          });
      });
      AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
          options = this._default_mangler_options(options);
          var lname = -1;
          var to_mangle = [];
          var tw = new TreeWalker(function(node, descend) {
              if (node instanceof AST_LabeledStatement) {
                  var save_nesting = lname;
                  descend();
                  lname = save_nesting;
                  return true;
              }
              if (node instanceof AST_Scope) {
                  var p = tw.parent(), a = [];
                  node.variables.each(function(symbol) {
                      if (options.except.indexOf(symbol.name) < 0) {
                          a.push(symbol);
                      }
                  });
                  if (options.sort) a.sort(function(a, b) {
                      return b.references.length - a.references.length;
                  });
                  to_mangle.push.apply(to_mangle, a);
                  return;
              }
              if (node instanceof AST_Label) {
                  var name;
                  do name = base54(++lname); while (!is_identifier(name));
                  node.mangled_name = name;
                  return true;
              }
              if (options.screw_ie8 && node instanceof AST_SymbolCatch) {
                  to_mangle.push(node.definition());
                  return;
              }
          });
          this.walk(tw);
          to_mangle.forEach(function(def) {
              def.mangle(options);
          });
      });
      AST_Toplevel.DEFMETHOD("compute_char_frequency", function(options) {
          options = this._default_mangler_options(options);
          var tw = new TreeWalker(function(node) {
              if (node instanceof AST_Constant) base54.consider(node.print_to_string()); else if (node instanceof AST_Return) base54.consider("return"); else if (node instanceof AST_Throw) base54.consider("throw"); else if (node instanceof AST_Continue) base54.consider("continue"); else if (node instanceof AST_Break) base54.consider("break"); else if (node instanceof AST_Debugger) base54.consider("debugger"); else if (node instanceof AST_Directive) base54.consider(node.value); else if (node instanceof AST_While) base54.consider("while"); else if (node instanceof AST_Do) base54.consider("do while"); else if (node instanceof AST_If) {
                  base54.consider("if");
                  if (node.alternative) base54.consider("else");
              } else if (node instanceof AST_Var) base54.consider("var"); else if (node instanceof AST_Const) base54.consider("const"); else if (node instanceof AST_Lambda) base54.consider("function"); else if (node instanceof AST_For) base54.consider("for"); else if (node instanceof AST_ForIn) base54.consider("for in"); else if (node instanceof AST_Switch) base54.consider("switch"); else if (node instanceof AST_Case) base54.consider("case"); else if (node instanceof AST_Default) base54.consider("default"); else if (node instanceof AST_With) base54.consider("with"); else if (node instanceof AST_ObjectSetter) base54.consider("set" + node.key); else if (node instanceof AST_ObjectGetter) base54.consider("get" + node.key); else if (node instanceof AST_ObjectKeyVal) base54.consider(node.key); else if (node instanceof AST_New) base54.consider("new"); else if (node instanceof AST_This) base54.consider("this"); else if (node instanceof AST_Try) base54.consider("try"); else if (node instanceof AST_Catch) base54.consider("catch"); else if (node instanceof AST_Finally) base54.consider("finally"); else if (node instanceof AST_Symbol && node.unmangleable(options)) base54.consider(node.name); else if (node instanceof AST_Unary || node instanceof AST_Binary) base54.consider(node.operator); else if (node instanceof AST_Dot) base54.consider(node.property);
          });
          this.walk(tw);
          base54.sort();
      });
      var base54 = function() {
          var string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789";
          var chars, frequency;
          function reset() {
              frequency = Object.create(null);
              chars = string.split("").map(function(ch) {
                  return ch.charCodeAt(0);
              });
              chars.forEach(function(ch) {
                  frequency[ch] = 0;
              });
          }
          base54.consider = function(str) {
              for (var i = str.length; --i >= 0; ) {
                  var code = str.charCodeAt(i);
                  if (code in frequency) ++frequency[code];
              }
          };
          base54.sort = function() {
              chars = mergeSort(chars, function(a, b) {
                  if (is_digit(a) && !is_digit(b)) return 1;
                  if (is_digit(b) && !is_digit(a)) return -1;
                  return frequency[b] - frequency[a];
              });
          };
          base54.reset = reset;
          reset();
          base54.get = function() {
              return chars;
          };
          base54.freq = function() {
              return frequency;
          };
          function base54(num) {
              var ret = "", base = 54;
              do {
                  ret += String.fromCharCode(chars[num % base]);
                  num = Math.floor(num / base);
                  base = 64;
              } while (num > 0);
              return ret;
          }
          return base54;
      }();
      AST_Toplevel.DEFMETHOD("scope_warnings", function(options) {
          options = defaults(options, {
              undeclared: false,
              unreferenced: true,
              assign_to_global: true,
              func_arguments: true,
              nested_defuns: true,
              eval: true
          });
          var tw = new TreeWalker(function(node) {
              if (options.undeclared && node instanceof AST_SymbolRef && node.undeclared()) {
                  AST_Node.warn("Undeclared symbol: {name} [{file}:{line},{col}]", {
                      name: node.name,
                      file: node.start.file,
                      line: node.start.line,
                      col: node.start.col
                  });
              }
              if (options.assign_to_global) {
                  var sym = null;
                  if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef) sym = node.left; else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef) sym = node.init;
                  if (sym && (sym.undeclared() || sym.global() && sym.scope !== sym.definition().scope)) {
                      AST_Node.warn("{msg}: {name} [{file}:{line},{col}]", {
                          msg: sym.undeclared() ? "Accidental global?" : "Assignment to global",
                          name: sym.name,
                          file: sym.start.file,
                          line: sym.start.line,
                          col: sym.start.col
                      });
                  }
              }
              if (options.eval && node instanceof AST_SymbolRef && node.undeclared() && node.name == "eval") {
                  AST_Node.warn("Eval is used [{file}:{line},{col}]", node.start);
              }
              if (options.unreferenced && (node instanceof AST_SymbolDeclaration || node instanceof AST_Label) && node.unreferenced()) {
                  AST_Node.warn("{type} {name} is declared but not referenced [{file}:{line},{col}]", {
                      type: node instanceof AST_Label ? "Label" : "Symbol",
                      name: node.name,
                      file: node.start.file,
                      line: node.start.line,
                      col: node.start.col
                  });
              }
              if (options.func_arguments && node instanceof AST_Lambda && node.uses_arguments) {
                  AST_Node.warn("arguments used in function {name} [{file}:{line},{col}]", {
                      name: node.name ? node.name.name : "anonymous",
                      file: node.start.file,
                      line: node.start.line,
                      col: node.start.col
                  });
              }
              if (options.nested_defuns && node instanceof AST_Defun && !(tw.parent() instanceof AST_Scope)) {
                  AST_Node.warn('Function {name} declared in nested statement "{type}" [{file}:{line},{col}]', {
                      name: node.name.name,
                      type: tw.parent().TYPE,
                      file: node.start.file,
                      line: node.start.line,
                      col: node.start.col
                  });
              }
          });
          this.walk(tw);
      });
      "use strict";
      function OutputStream(options) {
          options = defaults(options, {
              indent_start: 0,
              indent_level: 4,
              quote_keys: false,
              space_colon: true,
              ascii_only: false,
              unescape_regexps: false,
              inline_script: false,
              width: 80,
              max_line_len: 32e3,
              beautify: false,
              source_map: null,
              bracketize: false,
              semicolons: true,
              comments: false,
              preserve_line: false,
              screw_ie8: false,
              preamble: null
          }, true);
          var indentation = 0;
          var current_col = 0;
          var current_line = 1;
          var current_pos = 0;
          var OUTPUT = "";
          function to_ascii(str, identifier) {
              return str.replace(/[\u0080-\uffff]/g, function(ch) {
                  var code = ch.charCodeAt(0).toString(16);
                  if (code.length <= 2 && !identifier) {
                      while (code.length < 2) code = "0" + code;
                      return "\\x" + code;
                  } else {
                      while (code.length < 4) code = "0" + code;
                      return "\\u" + code;
                  }
              });
          }
          function make_string(str) {
              var dq = 0, sq = 0;
              str = str.replace(/[\\\b\f\n\r\t\x22\x27\u2028\u2029\0]/g, function(s) {
                  switch (s) {
                    case "\\":
                      return "\\\\";
  
                    case "\b":
                      return "\\b";
  
                    case "\f":
                      return "\\f";
  
                    case "\n":
                      return "\\n";
  
                    case "\r":
                      return "\\r";
  
                    case "\u2028":
                      return "\\u2028";
  
                    case "\u2029":
                      return "\\u2029";
  
                    case '"':
                      ++dq;
                      return '"';
  
                    case "'":
                      ++sq;
                      return "'";
  
                    case "\x00":
                      return "\\x00";
                  }
                  return s;
              });
              if (options.ascii_only) str = to_ascii(str);
              if (dq > sq) return "'" + str.replace(/\x27/g, "\\'") + "'"; else return '"' + str.replace(/\x22/g, '\\"') + '"';
          }
          function encode_string(str) {
              var ret = make_string(str);
              if (options.inline_script) ret = ret.replace(/<\x2fscript([>\/\t\n\f\r ])/gi, "<\\/script$1");
              return ret;
          }
          function make_name(name) {
              name = name.toString();
              if (options.ascii_only) name = to_ascii(name, true);
              return name;
          }
          function make_indent(back) {
              return repeat_string(" ", options.indent_start + indentation - back * options.indent_level);
          }
          var might_need_space = false;
          var might_need_semicolon = false;
          var last = null;
          function last_char() {
              return last.charAt(last.length - 1);
          }
          function maybe_newline() {
              if (options.max_line_len && current_col > options.max_line_len) print("\n");
          }
          var requireSemicolonChars = makePredicate("( [ + * / - , .");
          function print(str) {
              str = String(str);
              var ch = str.charAt(0);
              if (might_need_semicolon) {
                  if ((!ch || ";}".indexOf(ch) < 0) && !/[;]$/.test(last)) {
                      if (options.semicolons || requireSemicolonChars(ch)) {
                          OUTPUT += ";";
                          current_col++;
                          current_pos++;
                      } else {
                          OUTPUT += "\n";
                          current_pos++;
                          current_line++;
                          current_col = 0;
                      }
                      if (!options.beautify) might_need_space = false;
                  }
                  might_need_semicolon = false;
                  maybe_newline();
              }
              if (!options.beautify && options.preserve_line && stack[stack.length - 1]) {
                  var target_line = stack[stack.length - 1].start.line;
                  while (current_line < target_line) {
                      OUTPUT += "\n";
                      current_pos++;
                      current_line++;
                      current_col = 0;
                      might_need_space = false;
                  }
              }
              if (might_need_space) {
                  var prev = last_char();
                  if (is_identifier_char(prev) && (is_identifier_char(ch) || ch == "\\") || /^[\+\-\/]$/.test(ch) && ch == prev) {
                      OUTPUT += " ";
                      current_col++;
                      current_pos++;
                  }
                  might_need_space = false;
              }
              var a = str.split(/\r?\n/), n = a.length - 1;
              current_line += n;
              if (n == 0) {
                  current_col += a[n].length;
              } else {
                  current_col = a[n].length;
              }
              current_pos += str.length;
              last = str;
              OUTPUT += str;
          }
          var space = options.beautify ? function() {
              print(" ");
          } : function() {
              might_need_space = true;
          };
          var indent = options.beautify ? function(half) {
              if (options.beautify) {
                  print(make_indent(half ? .5 : 0));
              }
          } : noop;
          var with_indent = options.beautify ? function(col, cont) {
              if (col === true) col = next_indent();
              var save_indentation = indentation;
              indentation = col;
              var ret = cont();
              indentation = save_indentation;
              return ret;
          } : function(col, cont) {
              return cont();
          };
          var newline = options.beautify ? function() {
              print("\n");
          } : noop;
          var semicolon = options.beautify ? function() {
              print(";");
          } : function() {
              might_need_semicolon = true;
          };
          function force_semicolon() {
              might_need_semicolon = false;
              print(";");
          }
          function next_indent() {
              return indentation + options.indent_level;
          }
          function with_block(cont) {
              var ret;
              print("{");
              newline();
              with_indent(next_indent(), function() {
                  ret = cont();
              });
              indent();
              print("}");
              return ret;
          }
          function with_parens(cont) {
              print("(");
              var ret = cont();
              print(")");
              return ret;
          }
          function with_square(cont) {
              print("[");
              var ret = cont();
              print("]");
              return ret;
          }
          function comma() {
              print(",");
              space();
          }
          function colon() {
              print(":");
              if (options.space_colon) space();
          }
          var add_mapping = options.source_map ? function(token, name) {
              try {
                  if (token) options.source_map.add(token.file || "?", current_line, current_col, token.line, token.col, !name && token.type == "name" ? token.value : name);
              } catch (ex) {
                  AST_Node.warn("Couldn't figure out mapping for {file}:{line},{col} → {cline},{ccol} [{name}]", {
                      file: token.file,
                      line: token.line,
                      col: token.col,
                      cline: current_line,
                      ccol: current_col,
                      name: name || ""
                  });
              }
          } : noop;
          function get() {
              return OUTPUT;
          }
          if (options.preamble) {
              print(options.preamble.replace(/\r\n?|[\n\u2028\u2029]|\s*$/g, "\n"));
          }
          var stack = [];
          return {
              get: get,
              toString: get,
              indent: indent,
              indentation: function() {
                  return indentation;
              },
              current_width: function() {
                  return current_col - indentation;
              },
              should_break: function() {
                  return options.width && this.current_width() >= options.width;
              },
              newline: newline,
              print: print,
              space: space,
              comma: comma,
              colon: colon,
              last: function() {
                  return last;
              },
              semicolon: semicolon,
              force_semicolon: force_semicolon,
              to_ascii: to_ascii,
              print_name: function(name) {
                  print(make_name(name));
              },
              print_string: function(str) {
                  print(encode_string(str));
              },
              next_indent: next_indent,
              with_indent: with_indent,
              with_block: with_block,
              with_parens: with_parens,
              with_square: with_square,
              add_mapping: add_mapping,
              option: function(opt) {
                  return options[opt];
              },
              line: function() {
                  return current_line;
              },
              col: function() {
                  return current_col;
              },
              pos: function() {
                  return current_pos;
              },
              push_node: function(node) {
                  stack.push(node);
              },
              pop_node: function() {
                  return stack.pop();
              },
              stack: function() {
                  return stack;
              },
              parent: function(n) {
                  return stack[stack.length - 2 - (n || 0)];
              }
          };
      }
      (function() {
          function DEFPRINT(nodetype, generator) {
              nodetype.DEFMETHOD("_codegen", generator);
          }
          AST_Node.DEFMETHOD("print", function(stream, force_parens) {
              var self = this, generator = self._codegen;
              function doit() {
                  self.add_comments(stream);
                  self.add_source_map(stream);
                  generator(self, stream);
              }
              stream.push_node(self);
              if (force_parens || self.needs_parens(stream)) {
                  stream.with_parens(doit);
              } else {
                  doit();
              }
              stream.pop_node();
          });
          AST_Node.DEFMETHOD("print_to_string", function(options) {
              var s = OutputStream(options);
              this.print(s);
              return s.get();
          });
          AST_Node.DEFMETHOD("add_comments", function(output) {
              var c = output.option("comments"), self = this;
              if (c) {
                  var start = self.start;
                  if (start && !start._comments_dumped) {
                      start._comments_dumped = true;
                      var comments = start.comments_before || [];
                      if (self instanceof AST_Exit && self.value) {
                          self.value.walk(new TreeWalker(function(node) {
                              if (node.start && node.start.comments_before) {
                                  comments = comments.concat(node.start.comments_before);
                                  node.start.comments_before = [];
                              }
                              if (node instanceof AST_Function || node instanceof AST_Array || node instanceof AST_Object) {
                                  return true;
                              }
                          }));
                      }
                      if (c.test) {
                          comments = comments.filter(function(comment) {
                              return c.test(comment.value);
                          });
                      } else if (typeof c == "function") {
                          comments = comments.filter(function(comment) {
                              return c(self, comment);
                          });
                      }
                      comments.forEach(function(c) {
                          if (/comment[134]/.test(c.type)) {
                              output.print("//" + c.value + "\n");
                              output.indent();
                          } else if (c.type == "comment2") {
                              output.print("/*" + c.value + "*/");
                              if (start.nlb) {
                                  output.print("\n");
                                  output.indent();
                              } else {
                                  output.space();
                              }
                          }
                      });
                  }
              }
          });
          function PARENS(nodetype, func) {
              if (Array.isArray(nodetype)) {
                  nodetype.forEach(function(nodetype) {
                      PARENS(nodetype, func);
                  });
              } else {
                  nodetype.DEFMETHOD("needs_parens", func);
              }
          }
          PARENS(AST_Node, function() {
              return false;
          });
          PARENS(AST_Function, function(output) {
              return first_in_statement(output);
          });
          PARENS(AST_Object, function(output) {
              return first_in_statement(output);
          });
          PARENS([ AST_Unary, AST_Undefined ], function(output) {
              var p = output.parent();
              return p instanceof AST_PropAccess && p.expression === this;
          });
          PARENS(AST_Seq, function(output) {
              var p = output.parent();
              return p instanceof AST_Call || p instanceof AST_Unary || p instanceof AST_Binary || p instanceof AST_VarDef || p instanceof AST_PropAccess || p instanceof AST_Array || p instanceof AST_ObjectProperty || p instanceof AST_Conditional;
          });
          PARENS(AST_Binary, function(output) {
              var p = output.parent();
              if (p instanceof AST_Call && p.expression === this) return true;
              if (p instanceof AST_Unary) return true;
              if (p instanceof AST_PropAccess && p.expression === this) return true;
              if (p instanceof AST_Binary) {
                  var po = p.operator, pp = PRECEDENCE[po];
                  var so = this.operator, sp = PRECEDENCE[so];
                  if (pp > sp || pp == sp && this === p.right) {
                      return true;
                  }
              }
          });
          PARENS(AST_PropAccess, function(output) {
              var p = output.parent();
              if (p instanceof AST_New && p.expression === this) {
                  try {
                      this.walk(new TreeWalker(function(node) {
                          if (node instanceof AST_Call) throw p;
                      }));
                  } catch (ex) {
                      if (ex !== p) throw ex;
                      return true;
                  }
              }
          });
          PARENS(AST_Call, function(output) {
              var p = output.parent(), p1;
              if (p instanceof AST_New && p.expression === this) return true;
              return this.expression instanceof AST_Function && p instanceof AST_PropAccess && p.expression === this && (p1 = output.parent(1)) instanceof AST_Assign && p1.left === p;
          });
          PARENS(AST_New, function(output) {
              var p = output.parent();
              if (no_constructor_parens(this, output) && (p instanceof AST_PropAccess || p instanceof AST_Call && p.expression === this)) return true;
          });
          PARENS(AST_Number, function(output) {
              var p = output.parent();
              if (this.getValue() < 0 && p instanceof AST_PropAccess && p.expression === this) return true;
          });
          PARENS(AST_NaN, function(output) {
              var p = output.parent();
              if (p instanceof AST_PropAccess && p.expression === this) return true;
          });
          PARENS([ AST_Assign, AST_Conditional ], function(output) {
              var p = output.parent();
              if (p instanceof AST_Unary) return true;
              if (p instanceof AST_Binary && !(p instanceof AST_Assign)) return true;
              if (p instanceof AST_Call && p.expression === this) return true;
              if (p instanceof AST_Conditional && p.condition === this) return true;
              if (p instanceof AST_PropAccess && p.expression === this) return true;
          });
          DEFPRINT(AST_Directive, function(self, output) {
              output.print_string(self.value);
              output.semicolon();
          });
          DEFPRINT(AST_Debugger, function(self, output) {
              output.print("debugger");
              output.semicolon();
          });
          function display_body(body, is_toplevel, output) {
              var last = body.length - 1;
              body.forEach(function(stmt, i) {
                  if (!(stmt instanceof AST_EmptyStatement)) {
                      output.indent();
                      stmt.print(output);
                      if (!(i == last && is_toplevel)) {
                          output.newline();
                          if (is_toplevel) output.newline();
                      }
                  }
              });
          }
          AST_StatementWithBody.DEFMETHOD("_do_print_body", function(output) {
              force_statement(this.body, output);
          });
          DEFPRINT(AST_Statement, function(self, output) {
              self.body.print(output);
              output.semicolon();
          });
          DEFPRINT(AST_Toplevel, function(self, output) {
              display_body(self.body, true, output);
              output.print("");
          });
          DEFPRINT(AST_LabeledStatement, function(self, output) {
              self.label.print(output);
              output.colon();
              self.body.print(output);
          });
          DEFPRINT(AST_SimpleStatement, function(self, output) {
              self.body.print(output);
              output.semicolon();
          });
          function print_bracketed(body, output) {
              if (body.length > 0) output.with_block(function() {
                  display_body(body, false, output);
              }); else output.print("{}");
          }
          DEFPRINT(AST_BlockStatement, function(self, output) {
              print_bracketed(self.body, output);
          });
          DEFPRINT(AST_EmptyStatement, function(self, output) {
              output.semicolon();
          });
          DEFPRINT(AST_Do, function(self, output) {
              output.print("do");
              output.space();
              self._do_print_body(output);
              output.space();
              output.print("while");
              output.space();
              output.with_parens(function() {
                  self.condition.print(output);
              });
              output.semicolon();
          });
          DEFPRINT(AST_While, function(self, output) {
              output.print("while");
              output.space();
              output.with_parens(function() {
                  self.condition.print(output);
              });
              output.space();
              self._do_print_body(output);
          });
          DEFPRINT(AST_For, function(self, output) {
              output.print("for");
              output.space();
              output.with_parens(function() {
                  if (self.init && !(self.init instanceof AST_EmptyStatement)) {
                      if (self.init instanceof AST_Definitions) {
                          self.init.print(output);
                      } else {
                          parenthesize_for_noin(self.init, output, true);
                      }
                      output.print(";");
                      output.space();
                  } else {
                      output.print(";");
                  }
                  if (self.condition) {
                      self.condition.print(output);
                      output.print(";");
                      output.space();
                  } else {
                      output.print(";");
                  }
                  if (self.step) {
                      self.step.print(output);
                  }
              });
              output.space();
              self._do_print_body(output);
          });
          DEFPRINT(AST_ForIn, function(self, output) {
              output.print("for");
              output.space();
              output.with_parens(function() {
                  self.init.print(output);
                  output.space();
                  output.print("in");
                  output.space();
                  self.object.print(output);
              });
              output.space();
              self._do_print_body(output);
          });
          DEFPRINT(AST_With, function(self, output) {
              output.print("with");
              output.space();
              output.with_parens(function() {
                  self.expression.print(output);
              });
              output.space();
              self._do_print_body(output);
          });
          AST_Lambda.DEFMETHOD("_do_print", function(output, nokeyword) {
              var self = this;
              if (!nokeyword) {
                  output.print("function");
              }
              if (self.name) {
                  output.space();
                  self.name.print(output);
              }
              output.with_parens(function() {
                  self.argnames.forEach(function(arg, i) {
                      if (i) output.comma();
                      arg.print(output);
                  });
              });
              output.space();
              print_bracketed(self.body, output);
          });
          DEFPRINT(AST_Lambda, function(self, output) {
              self._do_print(output);
          });
          AST_Exit.DEFMETHOD("_do_print", function(output, kind) {
              output.print(kind);
              if (this.value) {
                  output.space();
                  this.value.print(output);
              }
              output.semicolon();
          });
          DEFPRINT(AST_Return, function(self, output) {
              self._do_print(output, "return");
          });
          DEFPRINT(AST_Throw, function(self, output) {
              self._do_print(output, "throw");
          });
          AST_LoopControl.DEFMETHOD("_do_print", function(output, kind) {
              output.print(kind);
              if (this.label) {
                  output.space();
                  this.label.print(output);
              }
              output.semicolon();
          });
          DEFPRINT(AST_Break, function(self, output) {
              self._do_print(output, "break");
          });
          DEFPRINT(AST_Continue, function(self, output) {
              self._do_print(output, "continue");
          });
          function make_then(self, output) {
              if (output.option("bracketize")) {
                  make_block(self.body, output);
                  return;
              }
              if (!self.body) return output.force_semicolon();
              if (self.body instanceof AST_Do && !output.option("screw_ie8")) {
                  make_block(self.body, output);
                  return;
              }
              var b = self.body;
              while (true) {
                  if (b instanceof AST_If) {
                      if (!b.alternative) {
                          make_block(self.body, output);
                          return;
                      }
                      b = b.alternative;
                  } else if (b instanceof AST_StatementWithBody) {
                      b = b.body;
                  } else break;
              }
              force_statement(self.body, output);
          }
          DEFPRINT(AST_If, function(self, output) {
              output.print("if");
              output.space();
              output.with_parens(function() {
                  self.condition.print(output);
              });
              output.space();
              if (self.alternative) {
                  make_then(self, output);
                  output.space();
                  output.print("else");
                  output.space();
                  force_statement(self.alternative, output);
              } else {
                  self._do_print_body(output);
              }
          });
          DEFPRINT(AST_Switch, function(self, output) {
              output.print("switch");
              output.space();
              output.with_parens(function() {
                  self.expression.print(output);
              });
              output.space();
              if (self.body.length > 0) output.with_block(function() {
                  self.body.forEach(function(stmt, i) {
                      if (i) output.newline();
                      output.indent(true);
                      stmt.print(output);
                  });
              }); else output.print("{}");
          });
          AST_SwitchBranch.DEFMETHOD("_do_print_body", function(output) {
              if (this.body.length > 0) {
                  output.newline();
                  this.body.forEach(function(stmt) {
                      output.indent();
                      stmt.print(output);
                      output.newline();
                  });
              }
          });
          DEFPRINT(AST_Default, function(self, output) {
              output.print("default:");
              self._do_print_body(output);
          });
          DEFPRINT(AST_Case, function(self, output) {
              output.print("case");
              output.space();
              self.expression.print(output);
              output.print(":");
              self._do_print_body(output);
          });
          DEFPRINT(AST_Try, function(self, output) {
              output.print("try");
              output.space();
              print_bracketed(self.body, output);
              if (self.bcatch) {
                  output.space();
                  self.bcatch.print(output);
              }
              if (self.bfinally) {
                  output.space();
                  self.bfinally.print(output);
              }
          });
          DEFPRINT(AST_Catch, function(self, output) {
              output.print("catch");
              output.space();
              output.with_parens(function() {
                  self.argname.print(output);
              });
              output.space();
              print_bracketed(self.body, output);
          });
          DEFPRINT(AST_Finally, function(self, output) {
              output.print("finally");
              output.space();
              print_bracketed(self.body, output);
          });
          AST_Definitions.DEFMETHOD("_do_print", function(output, kind) {
              output.print(kind);
              output.space();
              this.definitions.forEach(function(def, i) {
                  if (i) output.comma();
                  def.print(output);
              });
              var p = output.parent();
              var in_for = p instanceof AST_For || p instanceof AST_ForIn;
              var avoid_semicolon = in_for && p.init === this;
              if (!avoid_semicolon) output.semicolon();
          });
          DEFPRINT(AST_Var, function(self, output) {
              self._do_print(output, "var");
          });
          DEFPRINT(AST_Const, function(self, output) {
              self._do_print(output, "const");
          });
          function parenthesize_for_noin(node, output, noin) {
              if (!noin) node.print(output); else try {
                  node.walk(new TreeWalker(function(node) {
                      if (node instanceof AST_Binary && node.operator == "in") throw output;
                  }));
                  node.print(output);
              } catch (ex) {
                  if (ex !== output) throw ex;
                  node.print(output, true);
              }
          }
          DEFPRINT(AST_VarDef, function(self, output) {
              self.name.print(output);
              if (self.value) {
                  output.space();
                  output.print("=");
                  output.space();
                  var p = output.parent(1);
                  var noin = p instanceof AST_For || p instanceof AST_ForIn;
                  parenthesize_for_noin(self.value, output, noin);
              }
          });
          DEFPRINT(AST_Call, function(self, output) {
              self.expression.print(output);
              if (self instanceof AST_New && no_constructor_parens(self, output)) return;
              output.with_parens(function() {
                  self.args.forEach(function(expr, i) {
                      if (i) output.comma();
                      expr.print(output);
                  });
              });
          });
          DEFPRINT(AST_New, function(self, output) {
              output.print("new");
              output.space();
              AST_Call.prototype._codegen(self, output);
          });
          AST_Seq.DEFMETHOD("_do_print", function(output) {
              this.car.print(output);
              if (this.cdr) {
                  output.comma();
                  if (output.should_break()) {
                      output.newline();
                      output.indent();
                  }
                  this.cdr.print(output);
              }
          });
          DEFPRINT(AST_Seq, function(self, output) {
              self._do_print(output);
          });
          DEFPRINT(AST_Dot, function(self, output) {
              var expr = self.expression;
              expr.print(output);
              if (expr instanceof AST_Number && expr.getValue() >= 0) {
                  if (!/[xa-f.]/i.test(output.last())) {
                      output.print(".");
                  }
              }
              output.print(".");
              output.add_mapping(self.end);
              output.print_name(self.property);
          });
          DEFPRINT(AST_Sub, function(self, output) {
              self.expression.print(output);
              output.print("[");
              self.property.print(output);
              output.print("]");
          });
          DEFPRINT(AST_UnaryPrefix, function(self, output) {
              var op = self.operator;
              output.print(op);
              if (/^[a-z]/i.test(op) || /[+-]$/.test(op) && self.expression instanceof AST_UnaryPrefix && /^[+-]/.test(self.expression.operator)) {
                  output.space();
              }
              self.expression.print(output);
          });
          DEFPRINT(AST_UnaryPostfix, function(self, output) {
              self.expression.print(output);
              output.print(self.operator);
          });
          DEFPRINT(AST_Binary, function(self, output) {
              self.left.print(output);
              output.space();
              output.print(self.operator);
              if (self.operator == "<" && self.right instanceof AST_UnaryPrefix && self.right.operator == "!" && self.right.expression instanceof AST_UnaryPrefix && self.right.expression.operator == "--") {
                  output.print(" ");
              } else {
                  output.space();
              }
              self.right.print(output);
          });
          DEFPRINT(AST_Conditional, function(self, output) {
              self.condition.print(output);
              output.space();
              output.print("?");
              output.space();
              self.consequent.print(output);
              output.space();
              output.colon();
              self.alternative.print(output);
          });
          DEFPRINT(AST_Array, function(self, output) {
              output.with_square(function() {
                  var a = self.elements, len = a.length;
                  if (len > 0) output.space();
                  a.forEach(function(exp, i) {
                      if (i) output.comma();
                      exp.print(output);
                      if (i === len - 1 && exp instanceof AST_Hole) output.comma();
                  });
                  if (len > 0) output.space();
              });
          });
          DEFPRINT(AST_Object, function(self, output) {
              if (self.properties.length > 0) output.with_block(function() {
                  self.properties.forEach(function(prop, i) {
                      if (i) {
                          output.print(",");
                          output.newline();
                      }
                      output.indent();
                      prop.print(output);
                  });
                  output.newline();
              }); else output.print("{}");
          });
          DEFPRINT(AST_ObjectKeyVal, function(self, output) {
              var key = self.key;
              if (output.option("quote_keys")) {
                  output.print_string(key + "");
              } else if ((typeof key == "number" || !output.option("beautify") && +key + "" == key) && parseFloat(key) >= 0) {
                  output.print(make_num(key));
              } else if (RESERVED_WORDS(key) ? output.option("screw_ie8") : is_identifier_string(key)) {
                  output.print_name(key);
              } else {
                  output.print_string(key);
              }
              output.colon();
              self.value.print(output);
          });
          DEFPRINT(AST_ObjectSetter, function(self, output) {
              output.print("set");
              output.space();
              self.key.print(output);
              self.value._do_print(output, true);
          });
          DEFPRINT(AST_ObjectGetter, function(self, output) {
              output.print("get");
              output.space();
              self.key.print(output);
              self.value._do_print(output, true);
          });
          DEFPRINT(AST_Symbol, function(self, output) {
              var def = self.definition();
              output.print_name(def ? def.mangled_name || def.name : self.name);
          });
          DEFPRINT(AST_Undefined, function(self, output) {
              output.print("void 0");
          });
          DEFPRINT(AST_Hole, noop);
          DEFPRINT(AST_Infinity, function(self, output) {
              output.print("1/0");
          });
          DEFPRINT(AST_NaN, function(self, output) {
              output.print("0/0");
          });
          DEFPRINT(AST_This, function(self, output) {
              output.print("this");
          });
          DEFPRINT(AST_Constant, function(self, output) {
              output.print(self.getValue());
          });
          DEFPRINT(AST_String, function(self, output) {
              output.print_string(self.getValue());
          });
          DEFPRINT(AST_Number, function(self, output) {
              output.print(make_num(self.getValue()));
          });
          function regexp_safe_literal(code) {
              return [ 92, 47, 46, 43, 42, 63, 40, 41, 91, 93, 123, 125, 36, 94, 58, 124, 33, 10, 13, 0, 65279, 8232, 8233 ].indexOf(code) < 0;
          }
          DEFPRINT(AST_RegExp, function(self, output) {
              var str = self.getValue().toString();
              if (output.option("ascii_only")) {
                  str = output.to_ascii(str);
              } else if (output.option("unescape_regexps")) {
                  str = str.split("\\\\").map(function(str) {
                      return str.replace(/\\u[0-9a-fA-F]{4}|\\x[0-9a-fA-F]{2}/g, function(s) {
                          var code = parseInt(s.substr(2), 16);
                          return regexp_safe_literal(code) ? String.fromCharCode(code) : s;
                      });
                  }).join("\\\\");
              }
              output.print(str);
              var p = output.parent();
              if (p instanceof AST_Binary && /^in/.test(p.operator) && p.left === self) output.print(" ");
          });
          function force_statement(stat, output) {
              if (output.option("bracketize")) {
                  if (!stat || stat instanceof AST_EmptyStatement) output.print("{}"); else if (stat instanceof AST_BlockStatement) stat.print(output); else output.with_block(function() {
                      output.indent();
                      stat.print(output);
                      output.newline();
                  });
              } else {
                  if (!stat || stat instanceof AST_EmptyStatement) output.force_semicolon(); else stat.print(output);
              }
          }
          function first_in_statement(output) {
              var a = output.stack(), i = a.length, node = a[--i], p = a[--i];
              while (i > 0) {
                  if (p instanceof AST_Statement && p.body === node) return true;
                  if (p instanceof AST_Seq && p.car === node || p instanceof AST_Call && p.expression === node && !(p instanceof AST_New) || p instanceof AST_Dot && p.expression === node || p instanceof AST_Sub && p.expression === node || p instanceof AST_Conditional && p.condition === node || p instanceof AST_Binary && p.left === node || p instanceof AST_UnaryPostfix && p.expression === node) {
                      node = p;
                      p = a[--i];
                  } else {
                      return false;
                  }
              }
          }
          function no_constructor_parens(self, output) {
              return self.args.length == 0 && !output.option("beautify");
          }
          function best_of(a) {
              var best = a[0], len = best.length;
              for (var i = 1; i < a.length; ++i) {
                  if (a[i].length < len) {
                      best = a[i];
                      len = best.length;
                  }
              }
              return best;
          }
          function make_num(num) {
              var str = num.toString(10), a = [ str.replace(/^0\./, ".").replace("e+", "e") ], m;
              if (Math.floor(num) === num) {
                  if (num >= 0) {
                      a.push("0x" + num.toString(16).toLowerCase(), "0" + num.toString(8));
                  } else {
                      a.push("-0x" + (-num).toString(16).toLowerCase(), "-0" + (-num).toString(8));
                  }
                  if (m = /^(.*?)(0+)$/.exec(num)) {
                      a.push(m[1] + "e" + m[2].length);
                  }
              } else if (m = /^0?\.(0+)(.*)$/.exec(num)) {
                  a.push(m[2] + "e-" + (m[1].length + m[2].length), str.substr(str.indexOf(".")));
              }
              return best_of(a);
          }
          function make_block(stmt, output) {
              if (stmt instanceof AST_BlockStatement) {
                  stmt.print(output);
                  return;
              }
              output.with_block(function() {
                  output.indent();
                  stmt.print(output);
                  output.newline();
              });
          }
          function DEFMAP(nodetype, generator) {
              nodetype.DEFMETHOD("add_source_map", function(stream) {
                  generator(this, stream);
              });
          }
          DEFMAP(AST_Node, noop);
          function basic_sourcemap_gen(self, output) {
              output.add_mapping(self.start);
          }
          DEFMAP(AST_Directive, basic_sourcemap_gen);
          DEFMAP(AST_Debugger, basic_sourcemap_gen);
          DEFMAP(AST_Symbol, basic_sourcemap_gen);
          DEFMAP(AST_Jump, basic_sourcemap_gen);
          DEFMAP(AST_StatementWithBody, basic_sourcemap_gen);
          DEFMAP(AST_LabeledStatement, noop);
          DEFMAP(AST_Lambda, basic_sourcemap_gen);
          DEFMAP(AST_Switch, basic_sourcemap_gen);
          DEFMAP(AST_SwitchBranch, basic_sourcemap_gen);
          DEFMAP(AST_BlockStatement, basic_sourcemap_gen);
          DEFMAP(AST_Toplevel, noop);
          DEFMAP(AST_New, basic_sourcemap_gen);
          DEFMAP(AST_Try, basic_sourcemap_gen);
          DEFMAP(AST_Catch, basic_sourcemap_gen);
          DEFMAP(AST_Finally, basic_sourcemap_gen);
          DEFMAP(AST_Definitions, basic_sourcemap_gen);
          DEFMAP(AST_Constant, basic_sourcemap_gen);
          DEFMAP(AST_ObjectProperty, function(self, output) {
              output.add_mapping(self.start, self.key);
          });
      })();
      "use strict";
      function Compressor(options, false_by_default) {
          if (!(this instanceof Compressor)) return new Compressor(options, false_by_default);
          TreeTransformer.call(this, this.before, this.after);
          this.options = defaults(options, {
              sequences: !false_by_default,
              properties: !false_by_default,
              dead_code: !false_by_default,
              drop_debugger: !false_by_default,
              unsafe: false,
              unsafe_comps: false,
              conditionals: !false_by_default,
              comparisons: !false_by_default,
              evaluate: !false_by_default,
              booleans: !false_by_default,
              loops: !false_by_default,
              unused: !false_by_default,
              hoist_funs: !false_by_default,
              keep_fargs: false,
              hoist_vars: false,
              if_return: !false_by_default,
              join_vars: !false_by_default,
              cascade: !false_by_default,
              side_effects: !false_by_default,
              pure_getters: false,
              pure_funcs: null,
              negate_iife: !false_by_default,
              screw_ie8: false,
              drop_console: false,
              angular: false,
              warnings: true,
              global_defs: {}
          }, true);
      }
      Compressor.prototype = new TreeTransformer();
      merge(Compressor.prototype, {
          option: function(key) {
              return this.options[key];
          },
          warn: function() {
              if (this.options.warnings) AST_Node.warn.apply(AST_Node, arguments);
          },
          before: function(node, descend, in_list) {
              if (node._squeezed) return node;
              var was_scope = false;
              if (node instanceof AST_Scope) {
                  node = node.hoist_declarations(this);
                  was_scope = true;
              }
              descend(node, this);
              node = node.optimize(this);
              if (was_scope && node instanceof AST_Scope) {
                  node.drop_unused(this);
                  descend(node, this);
              }
              node._squeezed = true;
              return node;
          }
      });
      (function() {
          function OPT(node, optimizer) {
              node.DEFMETHOD("optimize", function(compressor) {
                  var self = this;
                  if (self._optimized) return self;
                  var opt = optimizer(self, compressor);
                  opt._optimized = true;
                  if (opt === self) return opt;
                  return opt.transform(compressor);
              });
          }
          OPT(AST_Node, function(self, compressor) {
              return self;
          });
          AST_Node.DEFMETHOD("equivalent_to", function(node) {
              return this.print_to_string() == node.print_to_string();
          });
          function make_node(ctor, orig, props) {
              if (!props) props = {};
              if (orig) {
                  if (!props.start) props.start = orig.start;
                  if (!props.end) props.end = orig.end;
              }
              return new ctor(props);
          }
          function make_node_from_constant(compressor, val, orig) {
              if (val instanceof AST_Node) return val.transform(compressor);
              switch (typeof val) {
                case "string":
                  return make_node(AST_String, orig, {
                      value: val
                  }).optimize(compressor);
  
                case "number":
                  return make_node(isNaN(val) ? AST_NaN : AST_Number, orig, {
                      value: val
                  }).optimize(compressor);
  
                case "boolean":
                  return make_node(val ? AST_True : AST_False, orig).optimize(compressor);
  
                case "undefined":
                  return make_node(AST_Undefined, orig).optimize(compressor);
  
                default:
                  if (val === null) {
                      return make_node(AST_Null, orig).optimize(compressor);
                  }
                  if (val instanceof RegExp) {
                      return make_node(AST_RegExp, orig).optimize(compressor);
                  }
                  throw new Error(string_template("Can't handle constant of type: {type}", {
                      type: typeof val
                  }));
              }
          }
          function as_statement_array(thing) {
              if (thing === null) return [];
              if (thing instanceof AST_BlockStatement) return thing.body;
              if (thing instanceof AST_EmptyStatement) return [];
              if (thing instanceof AST_Statement) return [ thing ];
              throw new Error("Can't convert thing to statement array");
          }
          function is_empty(thing) {
              if (thing === null) return true;
              if (thing instanceof AST_EmptyStatement) return true;
              if (thing instanceof AST_BlockStatement) return thing.body.length == 0;
              return false;
          }
          function loop_body(x) {
              if (x instanceof AST_Switch) return x;
              if (x instanceof AST_For || x instanceof AST_ForIn || x instanceof AST_DWLoop) {
                  return x.body instanceof AST_BlockStatement ? x.body : x;
              }
              return x;
          }
          function tighten_body(statements, compressor) {
              var CHANGED;
              do {
                  CHANGED = false;
                  if (compressor.option("angular")) {
                      statements = process_for_angular(statements);
                  }
                  statements = eliminate_spurious_blocks(statements);
                  if (compressor.option("dead_code")) {
                      statements = eliminate_dead_code(statements, compressor);
                  }
                  if (compressor.option("if_return")) {
                      statements = handle_if_return(statements, compressor);
                  }
                  if (compressor.option("sequences")) {
                      statements = sequencesize(statements, compressor);
                  }
                  if (compressor.option("join_vars")) {
                      statements = join_consecutive_vars(statements, compressor);
                  }
              } while (CHANGED);
              if (compressor.option("negate_iife")) {
                  negate_iifes(statements, compressor);
              }
              return statements;
              function process_for_angular(statements) {
                  function make_injector(func, name) {
                      return make_node(AST_SimpleStatement, func, {
                          body: make_node(AST_Assign, func, {
                              operator: "=",
                              left: make_node(AST_Dot, name, {
                                  expression: make_node(AST_SymbolRef, name, name),
                                  property: "$inject"
                              }),
                              right: make_node(AST_Array, func, {
                                  elements: func.argnames.map(function(sym) {
                                      return make_node(AST_String, sym, {
                                          value: sym.name
                                      });
                                  })
                              })
                          })
                      });
                  }
                  return statements.reduce(function(a, stat) {
                      a.push(stat);
                      var token = stat.start;
                      var comments = token.comments_before;
                      if (comments && comments.length > 0) {
                          var last = comments.pop();
                          if (/@ngInject/.test(last.value)) {
                              if (stat instanceof AST_Defun) {
                                  a.push(make_injector(stat, stat.name));
                              } else if (stat instanceof AST_Definitions) {
                                  stat.definitions.forEach(function(def) {
                                      if (def.value && def.value instanceof AST_Lambda) {
                                          a.push(make_injector(def.value, def.name));
                                      }
                                  });
                              } else {
                                  compressor.warn("Unknown statement marked with @ngInject [{file}:{line},{col}]", token);
                              }
                          }
                      }
                      return a;
                  }, []);
              }
              function eliminate_spurious_blocks(statements) {
                  var seen_dirs = [];
                  return statements.reduce(function(a, stat) {
                      if (stat instanceof AST_BlockStatement) {
                          CHANGED = true;
                          a.push.apply(a, eliminate_spurious_blocks(stat.body));
                      } else if (stat instanceof AST_EmptyStatement) {
                          CHANGED = true;
                      } else if (stat instanceof AST_Directive) {
                          if (seen_dirs.indexOf(stat.value) < 0) {
                              a.push(stat);
                              seen_dirs.push(stat.value);
                          } else {
                              CHANGED = true;
                          }
                      } else {
                          a.push(stat);
                      }
                      return a;
                  }, []);
              }
              function handle_if_return(statements, compressor) {
                  var self = compressor.self();
                  var in_lambda = self instanceof AST_Lambda;
                  var ret = [];
                  loop: for (var i = statements.length; --i >= 0; ) {
                      var stat = statements[i];
                      switch (true) {
                        case in_lambda && stat instanceof AST_Return && !stat.value && ret.length == 0:
                          CHANGED = true;
                          continue loop;
  
                        case stat instanceof AST_If:
                          if (stat.body instanceof AST_Return) {
                              if ((in_lambda && ret.length == 0 || ret[0] instanceof AST_Return && !ret[0].value) && !stat.body.value && !stat.alternative) {
                                  CHANGED = true;
                                  var cond = make_node(AST_SimpleStatement, stat.condition, {
                                      body: stat.condition
                                  });
                                  ret.unshift(cond);
                                  continue loop;
                              }
                              if (ret[0] instanceof AST_Return && stat.body.value && ret[0].value && !stat.alternative) {
                                  CHANGED = true;
                                  stat = stat.clone();
                                  stat.alternative = ret[0];
                                  ret[0] = stat.transform(compressor);
                                  continue loop;
                              }
                              if ((ret.length == 0 || ret[0] instanceof AST_Return) && stat.body.value && !stat.alternative && in_lambda) {
                                  CHANGED = true;
                                  stat = stat.clone();
                                  stat.alternative = ret[0] || make_node(AST_Return, stat, {
                                      value: make_node(AST_Undefined, stat)
                                  });
                                  ret[0] = stat.transform(compressor);
                                  continue loop;
                              }
                              if (!stat.body.value && in_lambda) {
                                  CHANGED = true;
                                  stat = stat.clone();
                                  stat.condition = stat.condition.negate(compressor);
                                  stat.body = make_node(AST_BlockStatement, stat, {
                                      body: as_statement_array(stat.alternative).concat(ret)
                                  });
                                  stat.alternative = null;
                                  ret = [ stat.transform(compressor) ];
                                  continue loop;
                              }
                              if (ret.length == 1 && in_lambda && ret[0] instanceof AST_SimpleStatement && (!stat.alternative || stat.alternative instanceof AST_SimpleStatement)) {
                                  CHANGED = true;
                                  ret.push(make_node(AST_Return, ret[0], {
                                      value: make_node(AST_Undefined, ret[0])
                                  }).transform(compressor));
                                  ret = as_statement_array(stat.alternative).concat(ret);
                                  ret.unshift(stat);
                                  continue loop;
                              }
                          }
                          var ab = aborts(stat.body);
                          var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                          if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) {
                              if (ab.label) {
                                  remove(ab.label.thedef.references, ab);
                              }
                              CHANGED = true;
                              var body = as_statement_array(stat.body).slice(0, -1);
                              stat = stat.clone();
                              stat.condition = stat.condition.negate(compressor);
                              stat.body = make_node(AST_BlockStatement, stat, {
                                  body: as_statement_array(stat.alternative).concat(ret)
                              });
                              stat.alternative = make_node(AST_BlockStatement, stat, {
                                  body: body
                              });
                              ret = [ stat.transform(compressor) ];
                              continue loop;
                          }
                          var ab = aborts(stat.alternative);
                          var lct = ab instanceof AST_LoopControl ? compressor.loopcontrol_target(ab.label) : null;
                          if (ab && (ab instanceof AST_Return && !ab.value && in_lambda || ab instanceof AST_Continue && self === loop_body(lct) || ab instanceof AST_Break && lct instanceof AST_BlockStatement && self === lct)) {
                              if (ab.label) {
                                  remove(ab.label.thedef.references, ab);
                              }
                              CHANGED = true;
                              stat = stat.clone();
                              stat.body = make_node(AST_BlockStatement, stat.body, {
                                  body: as_statement_array(stat.body).concat(ret)
                              });
                              stat.alternative = make_node(AST_BlockStatement, stat.alternative, {
                                  body: as_statement_array(stat.alternative).slice(0, -1)
                              });
                              ret = [ stat.transform(compressor) ];
                              continue loop;
                          }
                          ret.unshift(stat);
                          break;
  
                        default:
                          ret.unshift(stat);
                          break;
                      }
                  }
                  return ret;
              }
              function eliminate_dead_code(statements, compressor) {
                  var has_quit = false;
                  var orig = statements.length;
                  var self = compressor.self();
                  statements = statements.reduce(function(a, stat) {
                      if (has_quit) {
                          extract_declarations_from_unreachable_code(compressor, stat, a);
                      } else {
                          if (stat instanceof AST_LoopControl) {
                              var lct = compressor.loopcontrol_target(stat.label);
                              if (stat instanceof AST_Break && lct instanceof AST_BlockStatement && loop_body(lct) === self || stat instanceof AST_Continue && loop_body(lct) === self) {
                                  if (stat.label) {
                                      remove(stat.label.thedef.references, stat);
                                  }
                              } else {
                                  a.push(stat);
                              }
                          } else {
                              a.push(stat);
                          }
                          if (aborts(stat)) has_quit = true;
                      }
                      return a;
                  }, []);
                  CHANGED = statements.length != orig;
                  return statements;
              }
              function sequencesize(statements, compressor) {
                  if (statements.length < 2) return statements;
                  var seq = [], ret = [];
                  function push_seq() {
                      seq = AST_Seq.from_array(seq);
                      if (seq) ret.push(make_node(AST_SimpleStatement, seq, {
                          body: seq
                      }));
                      seq = [];
                  }
                  statements.forEach(function(stat) {
                      if (stat instanceof AST_SimpleStatement) seq.push(stat.body); else push_seq(), ret.push(stat);
                  });
                  push_seq();
                  ret = sequencesize_2(ret, compressor);
                  CHANGED = ret.length != statements.length;
                  return ret;
              }
              function sequencesize_2(statements, compressor) {
                  function cons_seq(right) {
                      ret.pop();
                      var left = prev.body;
                      if (left instanceof AST_Seq) {
                          left.add(right);
                      } else {
                          left = AST_Seq.cons(left, right);
                      }
                      return left.transform(compressor);
                  }
                  var ret = [], prev = null;
                  statements.forEach(function(stat) {
                      if (prev) {
                          if (stat instanceof AST_For) {
                              var opera = {};
                              try {
                                  prev.body.walk(new TreeWalker(function(node) {
                                      if (node instanceof AST_Binary && node.operator == "in") throw opera;
                                  }));
                                  if (stat.init && !(stat.init instanceof AST_Definitions)) {
                                      stat.init = cons_seq(stat.init);
                                  } else if (!stat.init) {
                                      stat.init = prev.body;
                                      ret.pop();
                                  }
                              } catch (ex) {
                                  if (ex !== opera) throw ex;
                              }
                          } else if (stat instanceof AST_If) {
                              stat.condition = cons_seq(stat.condition);
                          } else if (stat instanceof AST_With) {
                              stat.expression = cons_seq(stat.expression);
                          } else if (stat instanceof AST_Exit && stat.value) {
                              stat.value = cons_seq(stat.value);
                          } else if (stat instanceof AST_Exit) {
                              stat.value = cons_seq(make_node(AST_Undefined, stat));
                          } else if (stat instanceof AST_Switch) {
                              stat.expression = cons_seq(stat.expression);
                          }
                      }
                      ret.push(stat);
                      prev = stat instanceof AST_SimpleStatement ? stat : null;
                  });
                  return ret;
              }
              function join_consecutive_vars(statements, compressor) {
                  var prev = null;
                  return statements.reduce(function(a, stat) {
                      if (stat instanceof AST_Definitions && prev && prev.TYPE == stat.TYPE) {
                          prev.definitions = prev.definitions.concat(stat.definitions);
                          CHANGED = true;
                      } else if (stat instanceof AST_For && prev instanceof AST_Definitions && (!stat.init || stat.init.TYPE == prev.TYPE)) {
                          CHANGED = true;
                          a.pop();
                          if (stat.init) {
                              stat.init.definitions = prev.definitions.concat(stat.init.definitions);
                          } else {
                              stat.init = prev;
                          }
                          a.push(stat);
                          prev = stat;
                      } else {
                          prev = stat;
                          a.push(stat);
                      }
                      return a;
                  }, []);
              }
              function negate_iifes(statements, compressor) {
                  statements.forEach(function(stat) {
                      if (stat instanceof AST_SimpleStatement) {
                          stat.body = function transform(thing) {
                              return thing.transform(new TreeTransformer(function(node) {
                                  if (node instanceof AST_Call && node.expression instanceof AST_Function) {
                                      return make_node(AST_UnaryPrefix, node, {
                                          operator: "!",
                                          expression: node
                                      });
                                  } else if (node instanceof AST_Call) {
                                      node.expression = transform(node.expression);
                                  } else if (node instanceof AST_Seq) {
                                      node.car = transform(node.car);
                                  } else if (node instanceof AST_Conditional) {
                                      var expr = transform(node.condition);
                                      if (expr !== node.condition) {
                                          node.condition = expr;
                                          var tmp = node.consequent;
                                          node.consequent = node.alternative;
                                          node.alternative = tmp;
                                      }
                                  }
                                  return node;
                              }));
                          }(stat.body);
                      }
                  });
              }
          }
          function extract_declarations_from_unreachable_code(compressor, stat, target) {
              compressor.warn("Dropping unreachable code [{file}:{line},{col}]", stat.start);
              stat.walk(new TreeWalker(function(node) {
                  if (node instanceof AST_Definitions) {
                      compressor.warn("Declarations in unreachable code! [{file}:{line},{col}]", node.start);
                      node.remove_initializers();
                      target.push(node);
                      return true;
                  }
                  if (node instanceof AST_Defun) {
                      target.push(node);
                      return true;
                  }
                  if (node instanceof AST_Scope) {
                      return true;
                  }
              }));
          }
          (function(def) {
              var unary_bool = [ "!", "delete" ];
              var binary_bool = [ "in", "instanceof", "==", "!=", "===", "!==", "<", "<=", ">=", ">" ];
              def(AST_Node, function() {
                  return false;
              });
              def(AST_UnaryPrefix, function() {
                  return member(this.operator, unary_bool);
              });
              def(AST_Binary, function() {
                  return member(this.operator, binary_bool) || (this.operator == "&&" || this.operator == "||") && this.left.is_boolean() && this.right.is_boolean();
              });
              def(AST_Conditional, function() {
                  return this.consequent.is_boolean() && this.alternative.is_boolean();
              });
              def(AST_Assign, function() {
                  return this.operator == "=" && this.right.is_boolean();
              });
              def(AST_Seq, function() {
                  return this.cdr.is_boolean();
              });
              def(AST_True, function() {
                  return true;
              });
              def(AST_False, function() {
                  return true;
              });
          })(function(node, func) {
              node.DEFMETHOD("is_boolean", func);
          });
          (function(def) {
              def(AST_Node, function() {
                  return false;
              });
              def(AST_String, function() {
                  return true;
              });
              def(AST_UnaryPrefix, function() {
                  return this.operator == "typeof";
              });
              def(AST_Binary, function(compressor) {
                  return this.operator == "+" && (this.left.is_string(compressor) || this.right.is_string(compressor));
              });
              def(AST_Assign, function(compressor) {
                  return (this.operator == "=" || this.operator == "+=") && this.right.is_string(compressor);
              });
              def(AST_Seq, function(compressor) {
                  return this.cdr.is_string(compressor);
              });
              def(AST_Conditional, function(compressor) {
                  return this.consequent.is_string(compressor) && this.alternative.is_string(compressor);
              });
              def(AST_Call, function(compressor) {
                  return compressor.option("unsafe") && this.expression instanceof AST_SymbolRef && this.expression.name == "String" && this.expression.undeclared();
              });
          })(function(node, func) {
              node.DEFMETHOD("is_string", func);
          });
          function best_of(ast1, ast2) {
              return ast1.print_to_string().length > ast2.print_to_string().length ? ast2 : ast1;
          }
          (function(def) {
              AST_Node.DEFMETHOD("evaluate", function(compressor) {
                  if (!compressor.option("evaluate")) return [ this ];
                  try {
                      var val = this._eval(compressor);
                      return [ best_of(make_node_from_constant(compressor, val, this), this), val ];
                  } catch (ex) {
                      if (ex !== def) throw ex;
                      return [ this ];
                  }
              });
              def(AST_Statement, function() {
                  throw new Error(string_template("Cannot evaluate a statement [{file}:{line},{col}]", this.start));
              });
              def(AST_Function, function() {
                  throw def;
              });
              function ev(node, compressor) {
                  if (!compressor) throw new Error("Compressor must be passed");
                  return node._eval(compressor);
              }
              def(AST_Node, function() {
                  throw def;
              });
              def(AST_Constant, function() {
                  return this.getValue();
              });
              def(AST_UnaryPrefix, function(compressor) {
                  var e = this.expression;
                  switch (this.operator) {
                    case "!":
                      return !ev(e, compressor);
  
                    case "typeof":
                      if (e instanceof AST_Function) return typeof function() {};
                      e = ev(e, compressor);
                      if (e instanceof RegExp) throw def;
                      return typeof e;
  
                    case "void":
                      return void ev(e, compressor);
  
                    case "~":
                      return ~ev(e, compressor);
  
                    case "-":
                      e = ev(e, compressor);
                      if (e === 0) throw def;
                      return -e;
  
                    case "+":
                      return +ev(e, compressor);
                  }
                  throw def;
              });
              def(AST_Binary, function(c) {
                  var left = this.left, right = this.right;
                  switch (this.operator) {
                    case "&&":
                      return ev(left, c) && ev(right, c);
  
                    case "||":
                      return ev(left, c) || ev(right, c);
  
                    case "|":
                      return ev(left, c) | ev(right, c);
  
                    case "&":
                      return ev(left, c) & ev(right, c);
  
                    case "^":
                      return ev(left, c) ^ ev(right, c);
  
                    case "+":
                      return ev(left, c) + ev(right, c);
  
                    case "*":
                      return ev(left, c) * ev(right, c);
  
                    case "/":
                      return ev(left, c) / ev(right, c);
  
                    case "%":
                      return ev(left, c) % ev(right, c);
  
                    case "-":
                      return ev(left, c) - ev(right, c);
  
                    case "<<":
                      return ev(left, c) << ev(right, c);
  
                    case ">>":
                      return ev(left, c) >> ev(right, c);
  
                    case ">>>":
                      return ev(left, c) >>> ev(right, c);
  
                    case "==":
                      return ev(left, c) == ev(right, c);
  
                    case "===":
                      return ev(left, c) === ev(right, c);
  
                    case "!=":
                      return ev(left, c) != ev(right, c);
  
                    case "!==":
                      return ev(left, c) !== ev(right, c);
  
                    case "<":
                      return ev(left, c) < ev(right, c);
  
                    case "<=":
                      return ev(left, c) <= ev(right, c);
  
                    case ">":
                      return ev(left, c) > ev(right, c);
  
                    case ">=":
                      return ev(left, c) >= ev(right, c);
  
                    case "in":
                      return ev(left, c) in ev(right, c);
  
                    case "instanceof":
                      return ev(left, c) instanceof ev(right, c);
                  }
                  throw def;
              });
              def(AST_Conditional, function(compressor) {
                  return ev(this.condition, compressor) ? ev(this.consequent, compressor) : ev(this.alternative, compressor);
              });
              def(AST_SymbolRef, function(compressor) {
                  var d = this.definition();
                  if (d && d.constant && d.init) return ev(d.init, compressor);
                  throw def;
              });
              def(AST_Dot, function(compressor) {
                  if (compressor.option("unsafe") && this.property == "length") {
                      var str = ev(this.expression, compressor);
                      if (typeof str == "string") return str.length;
                  }
                  throw def;
              });
          })(function(node, func) {
              node.DEFMETHOD("_eval", func);
          });
          (function(def) {
              function basic_negation(exp) {
                  return make_node(AST_UnaryPrefix, exp, {
                      operator: "!",
                      expression: exp
                  });
              }
              def(AST_Node, function() {
                  return basic_negation(this);
              });
              def(AST_Statement, function() {
                  throw new Error("Cannot negate a statement");
              });
              def(AST_Function, function() {
                  return basic_negation(this);
              });
              def(AST_UnaryPrefix, function() {
                  if (this.operator == "!") return this.expression;
                  return basic_negation(this);
              });
              def(AST_Seq, function(compressor) {
                  var self = this.clone();
                  self.cdr = self.cdr.negate(compressor);
                  return self;
              });
              def(AST_Conditional, function(compressor) {
                  var self = this.clone();
                  self.consequent = self.consequent.negate(compressor);
                  self.alternative = self.alternative.negate(compressor);
                  return best_of(basic_negation(this), self);
              });
              def(AST_Binary, function(compressor) {
                  var self = this.clone(), op = this.operator;
                  if (compressor.option("unsafe_comps")) {
                      switch (op) {
                        case "<=":
                          self.operator = ">";
                          return self;
  
                        case "<":
                          self.operator = ">=";
                          return self;
  
                        case ">=":
                          self.operator = "<";
                          return self;
  
                        case ">":
                          self.operator = "<=";
                          return self;
                      }
                  }
                  switch (op) {
                    case "==":
                      self.operator = "!=";
                      return self;
  
                    case "!=":
                      self.operator = "==";
                      return self;
  
                    case "===":
                      self.operator = "!==";
                      return self;
  
                    case "!==":
                      self.operator = "===";
                      return self;
  
                    case "&&":
                      self.operator = "||";
                      self.left = self.left.negate(compressor);
                      self.right = self.right.negate(compressor);
                      return best_of(basic_negation(this), self);
  
                    case "||":
                      self.operator = "&&";
                      self.left = self.left.negate(compressor);
                      self.right = self.right.negate(compressor);
                      return best_of(basic_negation(this), self);
                  }
                  return basic_negation(this);
              });
          })(function(node, func) {
              node.DEFMETHOD("negate", function(compressor) {
                  return func.call(this, compressor);
              });
          });
          (function(def) {
              def(AST_Node, function(compressor) {
                  return true;
              });
              def(AST_EmptyStatement, function(compressor) {
                  return false;
              });
              def(AST_Constant, function(compressor) {
                  return false;
              });
              def(AST_This, function(compressor) {
                  return false;
              });
              def(AST_Call, function(compressor) {
                  var pure = compressor.option("pure_funcs");
                  if (!pure) return true;
                  return pure.indexOf(this.expression.print_to_string()) < 0;
              });
              def(AST_Block, function(compressor) {
                  for (var i = this.body.length; --i >= 0; ) {
                      if (this.body[i].has_side_effects(compressor)) return true;
                  }
                  return false;
              });
              def(AST_SimpleStatement, function(compressor) {
                  return this.body.has_side_effects(compressor);
              });
              def(AST_Defun, function(compressor) {
                  return true;
              });
              def(AST_Function, function(compressor) {
                  return false;
              });
              def(AST_Binary, function(compressor) {
                  return this.left.has_side_effects(compressor) || this.right.has_side_effects(compressor);
              });
              def(AST_Assign, function(compressor) {
                  return true;
              });
              def(AST_Conditional, function(compressor) {
                  return this.condition.has_side_effects(compressor) || this.consequent.has_side_effects(compressor) || this.alternative.has_side_effects(compressor);
              });
              def(AST_Unary, function(compressor) {
                  return this.operator == "delete" || this.operator == "++" || this.operator == "--" || this.expression.has_side_effects(compressor);
              });
              def(AST_SymbolRef, function(compressor) {
                  return false;
              });
              def(AST_Object, function(compressor) {
                  for (var i = this.properties.length; --i >= 0; ) if (this.properties[i].has_side_effects(compressor)) return true;
                  return false;
              });
              def(AST_ObjectProperty, function(compressor) {
                  return this.value.has_side_effects(compressor);
              });
              def(AST_Array, function(compressor) {
                  for (var i = this.elements.length; --i >= 0; ) if (this.elements[i].has_side_effects(compressor)) return true;
                  return false;
              });
              def(AST_Dot, function(compressor) {
                  if (!compressor.option("pure_getters")) return true;
                  return this.expression.has_side_effects(compressor);
              });
              def(AST_Sub, function(compressor) {
                  if (!compressor.option("pure_getters")) return true;
                  return this.expression.has_side_effects(compressor) || this.property.has_side_effects(compressor);
              });
              def(AST_PropAccess, function(compressor) {
                  return !compressor.option("pure_getters");
              });
              def(AST_Seq, function(compressor) {
                  return this.car.has_side_effects(compressor) || this.cdr.has_side_effects(compressor);
              });
          })(function(node, func) {
              node.DEFMETHOD("has_side_effects", func);
          });
          function aborts(thing) {
              return thing && thing.aborts();
          }
          (function(def) {
              def(AST_Statement, function() {
                  return null;
              });
              def(AST_Jump, function() {
                  return this;
              });
              function block_aborts() {
                  var n = this.body.length;
                  return n > 0 && aborts(this.body[n - 1]);
              }
              def(AST_BlockStatement, block_aborts);
              def(AST_SwitchBranch, block_aborts);
              def(AST_If, function() {
                  return this.alternative && aborts(this.body) && aborts(this.alternative);
              });
          })(function(node, func) {
              node.DEFMETHOD("aborts", func);
          });
          OPT(AST_Directive, function(self, compressor) {
              if (self.scope.has_directive(self.value) !== self.scope) {
                  return make_node(AST_EmptyStatement, self);
              }
              return self;
          });
          OPT(AST_Debugger, function(self, compressor) {
              if (compressor.option("drop_debugger")) return make_node(AST_EmptyStatement, self);
              return self;
          });
          OPT(AST_LabeledStatement, function(self, compressor) {
              if (self.body instanceof AST_Break && compressor.loopcontrol_target(self.body.label) === self.body) {
                  return make_node(AST_EmptyStatement, self);
              }
              return self.label.references.length == 0 ? self.body : self;
          });
          OPT(AST_Block, function(self, compressor) {
              self.body = tighten_body(self.body, compressor);
              return self;
          });
          OPT(AST_BlockStatement, function(self, compressor) {
              self.body = tighten_body(self.body, compressor);
              switch (self.body.length) {
                case 1:
                  return self.body[0];
  
                case 0:
                  return make_node(AST_EmptyStatement, self);
              }
              return self;
          });
          AST_Scope.DEFMETHOD("drop_unused", function(compressor) {
              var self = this;
              if (compressor.option("unused") && !(self instanceof AST_Toplevel) && !self.uses_eval) {
                  var in_use = [];
                  var initializations = new Dictionary();
                  var scope = this;
                  var tw = new TreeWalker(function(node, descend) {
                      if (node !== self) {
                          if (node instanceof AST_Defun) {
                              initializations.add(node.name.name, node);
                              return true;
                          }
                          if (node instanceof AST_Definitions && scope === self) {
                              node.definitions.forEach(function(def) {
                                  if (def.value) {
                                      initializations.add(def.name.name, def.value);
                                      if (def.value.has_side_effects(compressor)) {
                                          def.value.walk(tw);
                                      }
                                  }
                              });
                              return true;
                          }
                          if (node instanceof AST_SymbolRef) {
                              push_uniq(in_use, node.definition());
                              return true;
                          }
                          if (node instanceof AST_Scope) {
                              var save_scope = scope;
                              scope = node;
                              descend();
                              scope = save_scope;
                              return true;
                          }
                      }
                  });
                  self.walk(tw);
                  for (var i = 0; i < in_use.length; ++i) {
                      in_use[i].orig.forEach(function(decl) {
                          var init = initializations.get(decl.name);
                          if (init) init.forEach(function(init) {
                              var tw = new TreeWalker(function(node) {
                                  if (node instanceof AST_SymbolRef) {
                                      push_uniq(in_use, node.definition());
                                  }
                              });
                              init.walk(tw);
                          });
                      });
                  }
                  var tt = new TreeTransformer(function before(node, descend, in_list) {
                      if (node instanceof AST_Lambda && !(node instanceof AST_Accessor)) {
                          if (!compressor.option("keep_fargs")) {
                              for (var a = node.argnames, i = a.length; --i >= 0; ) {
                                  var sym = a[i];
                                  if (sym.unreferenced()) {
                                      a.pop();
                                      compressor.warn("Dropping unused function argument {name} [{file}:{line},{col}]", {
                                          name: sym.name,
                                          file: sym.start.file,
                                          line: sym.start.line,
                                          col: sym.start.col
                                      });
                                  } else break;
                              }
                          }
                      }
                      if (node instanceof AST_Defun && node !== self) {
                          if (!member(node.name.definition(), in_use)) {
                              compressor.warn("Dropping unused function {name} [{file}:{line},{col}]", {
                                  name: node.name.name,
                                  file: node.name.start.file,
                                  line: node.name.start.line,
                                  col: node.name.start.col
                              });
                              return make_node(AST_EmptyStatement, node);
                          }
                          return node;
                      }
                      if (node instanceof AST_Definitions && !(tt.parent() instanceof AST_ForIn)) {
                          var def = node.definitions.filter(function(def) {
                              if (member(def.name.definition(), in_use)) return true;
                              var w = {
                                  name: def.name.name,
                                  file: def.name.start.file,
                                  line: def.name.start.line,
                                  col: def.name.start.col
                              };
                              if (def.value && def.value.has_side_effects(compressor)) {
                                  def._unused_side_effects = true;
                                  compressor.warn("Side effects in initialization of unused variable {name} [{file}:{line},{col}]", w);
                                  return true;
                              }
                              compressor.warn("Dropping unused variable {name} [{file}:{line},{col}]", w);
                              return false;
                          });
                          def = mergeSort(def, function(a, b) {
                              if (!a.value && b.value) return -1;
                              if (!b.value && a.value) return 1;
                              return 0;
                          });
                          var side_effects = [];
                          for (var i = 0; i < def.length; ) {
                              var x = def[i];
                              if (x._unused_side_effects) {
                                  side_effects.push(x.value);
                                  def.splice(i, 1);
                              } else {
                                  if (side_effects.length > 0) {
                                      side_effects.push(x.value);
                                      x.value = AST_Seq.from_array(side_effects);
                                      side_effects = [];
                                  }
                                  ++i;
                              }
                          }
                          if (side_effects.length > 0) {
                              side_effects = make_node(AST_BlockStatement, node, {
                                  body: [ make_node(AST_SimpleStatement, node, {
                                      body: AST_Seq.from_array(side_effects)
                                  }) ]
                              });
                          } else {
                              side_effects = null;
                          }
                          if (def.length == 0 && !side_effects) {
                              return make_node(AST_EmptyStatement, node);
                          }
                          if (def.length == 0) {
                              return side_effects;
                          }
                          node.definitions = def;
                          if (side_effects) {
                              side_effects.body.unshift(node);
                              node = side_effects;
                          }
                          return node;
                      }
                      if (node instanceof AST_For) {
                          descend(node, this);
                          if (node.init instanceof AST_BlockStatement) {
                              var body = node.init.body.slice(0, -1);
                              node.init = node.init.body.slice(-1)[0].body;
                              body.push(node);
                              return in_list ? MAP.splice(body) : make_node(AST_BlockStatement, node, {
                                  body: body
                              });
                          }
                      }
                      if (node instanceof AST_Scope && node !== self) return node;
                  });
                  self.transform(tt);
              }
          });
          AST_Scope.DEFMETHOD("hoist_declarations", function(compressor) {
              var hoist_funs = compressor.option("hoist_funs");
              var hoist_vars = compressor.option("hoist_vars");
              var self = this;
              if (hoist_funs || hoist_vars) {
                  var dirs = [];
                  var hoisted = [];
                  var vars = new Dictionary(), vars_found = 0, var_decl = 0;
                  self.walk(new TreeWalker(function(node) {
                      if (node instanceof AST_Scope && node !== self) return true;
                      if (node instanceof AST_Var) {
                          ++var_decl;
                          return true;
                      }
                  }));
                  hoist_vars = hoist_vars && var_decl > 1;
                  var tt = new TreeTransformer(function before(node) {
                      if (node !== self) {
                          if (node instanceof AST_Directive) {
                              dirs.push(node);
                              return make_node(AST_EmptyStatement, node);
                          }
                          if (node instanceof AST_Defun && hoist_funs) {
                              hoisted.push(node);
                              return make_node(AST_EmptyStatement, node);
                          }
                          if (node instanceof AST_Var && hoist_vars) {
                              node.definitions.forEach(function(def) {
                                  vars.set(def.name.name, def);
                                  ++vars_found;
                              });
                              var seq = node.to_assignments();
                              var p = tt.parent();
                              if (p instanceof AST_ForIn && p.init === node) {
                                  if (seq == null) return node.definitions[0].name;
                                  return seq;
                              }
                              if (p instanceof AST_For && p.init === node) {
                                  return seq;
                              }
                              if (!seq) return make_node(AST_EmptyStatement, node);
                              return make_node(AST_SimpleStatement, node, {
                                  body: seq
                              });
                          }
                          if (node instanceof AST_Scope) return node;
                      }
                  });
                  self = self.transform(tt);
                  if (vars_found > 0) {
                      var defs = [];
                      vars.each(function(def, name) {
                          if (self instanceof AST_Lambda && find_if(function(x) {
                              return x.name == def.name.name;
                          }, self.argnames)) {
                              vars.del(name);
                          } else {
                              def = def.clone();
                              def.value = null;
                              defs.push(def);
                              vars.set(name, def);
                          }
                      });
                      if (defs.length > 0) {
                          for (var i = 0; i < self.body.length; ) {
                              if (self.body[i] instanceof AST_SimpleStatement) {
                                  var expr = self.body[i].body, sym, assign;
                                  if (expr instanceof AST_Assign && expr.operator == "=" && (sym = expr.left) instanceof AST_Symbol && vars.has(sym.name)) {
                                      var def = vars.get(sym.name);
                                      if (def.value) break;
                                      def.value = expr.right;
                                      remove(defs, def);
                                      defs.push(def);
                                      self.body.splice(i, 1);
                                      continue;
                                  }
                                  if (expr instanceof AST_Seq && (assign = expr.car) instanceof AST_Assign && assign.operator == "=" && (sym = assign.left) instanceof AST_Symbol && vars.has(sym.name)) {
                                      var def = vars.get(sym.name);
                                      if (def.value) break;
                                      def.value = assign.right;
                                      remove(defs, def);
                                      defs.push(def);
                                      self.body[i].body = expr.cdr;
                                      continue;
                                  }
                              }
                              if (self.body[i] instanceof AST_EmptyStatement) {
                                  self.body.splice(i, 1);
                                  continue;
                              }
                              if (self.body[i] instanceof AST_BlockStatement) {
                                  var tmp = [ i, 1 ].concat(self.body[i].body);
                                  self.body.splice.apply(self.body, tmp);
                                  continue;
                              }
                              break;
                          }
                          defs = make_node(AST_Var, self, {
                              definitions: defs
                          });
                          hoisted.push(defs);
                      }
                  }
                  self.body = dirs.concat(hoisted, self.body);
              }
              return self;
          });
          OPT(AST_SimpleStatement, function(self, compressor) {
              if (compressor.option("side_effects")) {
                  if (!self.body.has_side_effects(compressor)) {
                      compressor.warn("Dropping side-effect-free statement [{file}:{line},{col}]", self.start);
                      return make_node(AST_EmptyStatement, self);
                  }
              }
              return self;
          });
          OPT(AST_DWLoop, function(self, compressor) {
              var cond = self.condition.evaluate(compressor);
              self.condition = cond[0];
              if (!compressor.option("loops")) return self;
              if (cond.length > 1) {
                  if (cond[1]) {
                      return make_node(AST_For, self, {
                          body: self.body
                      });
                  } else if (self instanceof AST_While) {
                      if (compressor.option("dead_code")) {
                          var a = [];
                          extract_declarations_from_unreachable_code(compressor, self.body, a);
                          return make_node(AST_BlockStatement, self, {
                              body: a
                          });
                      }
                  }
              }
              return self;
          });
          function if_break_in_loop(self, compressor) {
              function drop_it(rest) {
                  rest = as_statement_array(rest);
                  if (self.body instanceof AST_BlockStatement) {
                      self.body = self.body.clone();
                      self.body.body = rest.concat(self.body.body.slice(1));
                      self.body = self.body.transform(compressor);
                  } else {
                      self.body = make_node(AST_BlockStatement, self.body, {
                          body: rest
                      }).transform(compressor);
                  }
                  if_break_in_loop(self, compressor);
              }
              var first = self.body instanceof AST_BlockStatement ? self.body.body[0] : self.body;
              if (first instanceof AST_If) {
                  if (first.body instanceof AST_Break && compressor.loopcontrol_target(first.body.label) === self) {
                      if (self.condition) {
                          self.condition = make_node(AST_Binary, self.condition, {
                              left: self.condition,
                              operator: "&&",
                              right: first.condition.negate(compressor)
                          });
                      } else {
                          self.condition = first.condition.negate(compressor);
                      }
                      drop_it(first.alternative);
                  } else if (first.alternative instanceof AST_Break && compressor.loopcontrol_target(first.alternative.label) === self) {
                      if (self.condition) {
                          self.condition = make_node(AST_Binary, self.condition, {
                              left: self.condition,
                              operator: "&&",
                              right: first.condition
                          });
                      } else {
                          self.condition = first.condition;
                      }
                      drop_it(first.body);
                  }
              }
          }
          OPT(AST_While, function(self, compressor) {
              if (!compressor.option("loops")) return self;
              self = AST_DWLoop.prototype.optimize.call(self, compressor);
              if (self instanceof AST_While) {
                  if_break_in_loop(self, compressor);
                  self = make_node(AST_For, self, self).transform(compressor);
              }
              return self;
          });
          OPT(AST_For, function(self, compressor) {
              var cond = self.condition;
              if (cond) {
                  cond = cond.evaluate(compressor);
                  self.condition = cond[0];
              }
              if (!compressor.option("loops")) return self;
              if (cond) {
                  if (cond.length > 1 && !cond[1]) {
                      if (compressor.option("dead_code")) {
                          var a = [];
                          if (self.init instanceof AST_Statement) {
                              a.push(self.init);
                          } else if (self.init) {
                              a.push(make_node(AST_SimpleStatement, self.init, {
                                  body: self.init
                              }));
                          }
                          extract_declarations_from_unreachable_code(compressor, self.body, a);
                          return make_node(AST_BlockStatement, self, {
                              body: a
                          });
                      }
                  }
              }
              if_break_in_loop(self, compressor);
              return self;
          });
          OPT(AST_If, function(self, compressor) {
              if (!compressor.option("conditionals")) return self;
              var cond = self.condition.evaluate(compressor);
              self.condition = cond[0];
              if (cond.length > 1) {
                  if (cond[1]) {
                      compressor.warn("Condition always true [{file}:{line},{col}]", self.condition.start);
                      if (compressor.option("dead_code")) {
                          var a = [];
                          if (self.alternative) {
                              extract_declarations_from_unreachable_code(compressor, self.alternative, a);
                          }
                          a.push(self.body);
                          return make_node(AST_BlockStatement, self, {
                              body: a
                          }).transform(compressor);
                      }
                  } else {
                      compressor.warn("Condition always false [{file}:{line},{col}]", self.condition.start);
                      if (compressor.option("dead_code")) {
                          var a = [];
                          extract_declarations_from_unreachable_code(compressor, self.body, a);
                          if (self.alternative) a.push(self.alternative);
                          return make_node(AST_BlockStatement, self, {
                              body: a
                          }).transform(compressor);
                      }
                  }
              }
              if (is_empty(self.alternative)) self.alternative = null;
              var negated = self.condition.negate(compressor);
              var negated_is_best = best_of(self.condition, negated) === negated;
              if (self.alternative && negated_is_best) {
                  negated_is_best = false;
                  self.condition = negated;
                  var tmp = self.body;
                  self.body = self.alternative || make_node(AST_EmptyStatement);
                  self.alternative = tmp;
              }
              if (is_empty(self.body) && is_empty(self.alternative)) {
                  return make_node(AST_SimpleStatement, self.condition, {
                      body: self.condition
                  }).transform(compressor);
              }
              if (self.body instanceof AST_SimpleStatement && self.alternative instanceof AST_SimpleStatement) {
                  return make_node(AST_SimpleStatement, self, {
                      body: make_node(AST_Conditional, self, {
                          condition: self.condition,
                          consequent: self.body.body,
                          alternative: self.alternative.body
                      })
                  }).transform(compressor);
              }
              if (is_empty(self.alternative) && self.body instanceof AST_SimpleStatement) {
                  if (negated_is_best) return make_node(AST_SimpleStatement, self, {
                      body: make_node(AST_Binary, self, {
                          operator: "||",
                          left: negated,
                          right: self.body.body
                      })
                  }).transform(compressor);
                  return make_node(AST_SimpleStatement, self, {
                      body: make_node(AST_Binary, self, {
                          operator: "&&",
                          left: self.condition,
                          right: self.body.body
                      })
                  }).transform(compressor);
              }
              if (self.body instanceof AST_EmptyStatement && self.alternative && self.alternative instanceof AST_SimpleStatement) {
                  return make_node(AST_SimpleStatement, self, {
                      body: make_node(AST_Binary, self, {
                          operator: "||",
                          left: self.condition,
                          right: self.alternative.body
                      })
                  }).transform(compressor);
              }
              if (self.body instanceof AST_Exit && self.alternative instanceof AST_Exit && self.body.TYPE == self.alternative.TYPE) {
                  return make_node(self.body.CTOR, self, {
                      value: make_node(AST_Conditional, self, {
                          condition: self.condition,
                          consequent: self.body.value || make_node(AST_Undefined, self.body).optimize(compressor),
                          alternative: self.alternative.value || make_node(AST_Undefined, self.alternative).optimize(compressor)
                      })
                  }).transform(compressor);
              }
              if (self.body instanceof AST_If && !self.body.alternative && !self.alternative) {
                  self.condition = make_node(AST_Binary, self.condition, {
                      operator: "&&",
                      left: self.condition,
                      right: self.body.condition
                  }).transform(compressor);
                  self.body = self.body.body;
              }
              if (aborts(self.body)) {
                  if (self.alternative) {
                      var alt = self.alternative;
                      self.alternative = null;
                      return make_node(AST_BlockStatement, self, {
                          body: [ self, alt ]
                      }).transform(compressor);
                  }
              }
              if (aborts(self.alternative)) {
                  var body = self.body;
                  self.body = self.alternative;
                  self.condition = negated_is_best ? negated : self.condition.negate(compressor);
                  self.alternative = null;
                  return make_node(AST_BlockStatement, self, {
                      body: [ self, body ]
                  }).transform(compressor);
              }
              return self;
          });
          OPT(AST_Switch, function(self, compressor) {
              if (self.body.length == 0 && compressor.option("conditionals")) {
                  return make_node(AST_SimpleStatement, self, {
                      body: self.expression
                  }).transform(compressor);
              }
              for (;;) {
                  var last_branch = self.body[self.body.length - 1];
                  if (last_branch) {
                      var stat = last_branch.body[last_branch.body.length - 1];
                      if (stat instanceof AST_Break && loop_body(compressor.loopcontrol_target(stat.label)) === self) last_branch.body.pop();
                      if (last_branch instanceof AST_Default && last_branch.body.length == 0) {
                          self.body.pop();
                          continue;
                      }
                  }
                  break;
              }
              var exp = self.expression.evaluate(compressor);
              out: if (exp.length == 2) try {
                  self.expression = exp[0];
                  if (!compressor.option("dead_code")) break out;
                  var value = exp[1];
                  var in_if = false;
                  var in_block = false;
                  var started = false;
                  var stopped = false;
                  var ruined = false;
                  var tt = new TreeTransformer(function(node, descend, in_list) {
                      if (node instanceof AST_Lambda || node instanceof AST_SimpleStatement) {
                          return node;
                      } else if (node instanceof AST_Switch && node === self) {
                          node = node.clone();
                          descend(node, this);
                          return ruined ? node : make_node(AST_BlockStatement, node, {
                              body: node.body.reduce(function(a, branch) {
                                  return a.concat(branch.body);
                              }, [])
                          }).transform(compressor);
                      } else if (node instanceof AST_If || node instanceof AST_Try) {
                          var save = in_if;
                          in_if = !in_block;
                          descend(node, this);
                          in_if = save;
                          return node;
                      } else if (node instanceof AST_StatementWithBody || node instanceof AST_Switch) {
                          var save = in_block;
                          in_block = true;
                          descend(node, this);
                          in_block = save;
                          return node;
                      } else if (node instanceof AST_Break && this.loopcontrol_target(node.label) === self) {
                          if (in_if) {
                              ruined = true;
                              return node;
                          }
                          if (in_block) return node;
                          stopped = true;
                          return in_list ? MAP.skip : make_node(AST_EmptyStatement, node);
                      } else if (node instanceof AST_SwitchBranch && this.parent() === self) {
                          if (stopped) return MAP.skip;
                          if (node instanceof AST_Case) {
                              var exp = node.expression.evaluate(compressor);
                              if (exp.length < 2) {
                                  throw self;
                              }
                              if (exp[1] === value || started) {
                                  started = true;
                                  if (aborts(node)) stopped = true;
                                  descend(node, this);
                                  return node;
                              }
                              return MAP.skip;
                          }
                          descend(node, this);
                          return node;
                      }
                  });
                  tt.stack = compressor.stack.slice();
                  self = self.transform(tt);
              } catch (ex) {
                  if (ex !== self) throw ex;
              }
              return self;
          });
          OPT(AST_Case, function(self, compressor) {
              self.body = tighten_body(self.body, compressor);
              return self;
          });
          OPT(AST_Try, function(self, compressor) {
              self.body = tighten_body(self.body, compressor);
              return self;
          });
          AST_Definitions.DEFMETHOD("remove_initializers", function() {
              this.definitions.forEach(function(def) {
                  def.value = null;
              });
          });
          AST_Definitions.DEFMETHOD("to_assignments", function() {
              var assignments = this.definitions.reduce(function(a, def) {
                  if (def.value) {
                      var name = make_node(AST_SymbolRef, def.name, def.name);
                      a.push(make_node(AST_Assign, def, {
                          operator: "=",
                          left: name,
                          right: def.value
                      }));
                  }
                  return a;
              }, []);
              if (assignments.length == 0) return null;
              return AST_Seq.from_array(assignments);
          });
          OPT(AST_Definitions, function(self, compressor) {
              if (self.definitions.length == 0) return make_node(AST_EmptyStatement, self);
              return self;
          });
          OPT(AST_Function, function(self, compressor) {
              self = AST_Lambda.prototype.optimize.call(self, compressor);
              if (compressor.option("unused")) {
                  if (self.name && self.name.unreferenced()) {
                      self.name = null;
                  }
              }
              return self;
          });
          OPT(AST_Call, function(self, compressor) {
              if (compressor.option("unsafe")) {
                  var exp = self.expression;
                  if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                      switch (exp.name) {
                        case "Array":
                          if (self.args.length != 1) {
                              return make_node(AST_Array, self, {
                                  elements: self.args
                              }).transform(compressor);
                          }
                          break;
  
                        case "Object":
                          if (self.args.length == 0) {
                              return make_node(AST_Object, self, {
                                  properties: []
                              });
                          }
                          break;
  
                        case "String":
                          if (self.args.length == 0) return make_node(AST_String, self, {
                              value: ""
                          });
                          if (self.args.length <= 1) return make_node(AST_Binary, self, {
                              left: self.args[0],
                              operator: "+",
                              right: make_node(AST_String, self, {
                                  value: ""
                              })
                          }).transform(compressor);
                          break;
  
                        case "Number":
                          if (self.args.length == 0) return make_node(AST_Number, self, {
                              value: 0
                          });
                          if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                              expression: self.args[0],
                              operator: "+"
                          }).transform(compressor);
  
                        case "Boolean":
                          if (self.args.length == 0) return make_node(AST_False, self);
                          if (self.args.length == 1) return make_node(AST_UnaryPrefix, self, {
                              expression: make_node(AST_UnaryPrefix, null, {
                                  expression: self.args[0],
                                  operator: "!"
                              }),
                              operator: "!"
                          }).transform(compressor);
                          break;
  
                        case "Function":
                          if (all(self.args, function(x) {
                              return x instanceof AST_String;
                          })) {
                              try {
                                  var code = "(function(" + self.args.slice(0, -1).map(function(arg) {
                                      return arg.value;
                                  }).join(",") + "){" + self.args[self.args.length - 1].value + "})()";
                                  var ast = parse(code);
                                  ast.figure_out_scope({
                                      screw_ie8: compressor.option("screw_ie8")
                                  });
                                  var comp = new Compressor(compressor.options);
                                  ast = ast.transform(comp);
                                  ast.figure_out_scope({
                                      screw_ie8: compressor.option("screw_ie8")
                                  });
                                  ast.mangle_names();
                                  var fun;
                                  try {
                                      ast.walk(new TreeWalker(function(node) {
                                          if (node instanceof AST_Lambda) {
                                              fun = node;
                                              throw ast;
                                          }
                                      }));
                                  } catch (ex) {
                                      if (ex !== ast) throw ex;
                                  }
                                  var args = fun.argnames.map(function(arg, i) {
                                      return make_node(AST_String, self.args[i], {
                                          value: arg.print_to_string()
                                      });
                                  });
                                  var code = OutputStream();
                                  AST_BlockStatement.prototype._codegen.call(fun, fun, code);
                                  code = code.toString().replace(/^\{|\}$/g, "");
                                  args.push(make_node(AST_String, self.args[self.args.length - 1], {
                                      value: code
                                  }));
                                  self.args = args;
                                  return self;
                              } catch (ex) {
                                  if (ex instanceof JS_Parse_Error) {
                                      compressor.warn("Error parsing code passed to new Function [{file}:{line},{col}]", self.args[self.args.length - 1].start);
                                      compressor.warn(ex.toString());
                                  } else {
                                      console.log(ex);
                                      throw ex;
                                  }
                              }
                          }
                          break;
                      }
                  } else if (exp instanceof AST_Dot && exp.property == "toString" && self.args.length == 0) {
                      return make_node(AST_Binary, self, {
                          left: make_node(AST_String, self, {
                              value: ""
                          }),
                          operator: "+",
                          right: exp.expression
                      }).transform(compressor);
                  } else if (exp instanceof AST_Dot && exp.expression instanceof AST_Array && exp.property == "join") EXIT: {
                      var separator = self.args.length == 0 ? "," : self.args[0].evaluate(compressor)[1];
                      if (separator == null) break EXIT;
                      var elements = exp.expression.elements.reduce(function(a, el) {
                          el = el.evaluate(compressor);
                          if (a.length == 0 || el.length == 1) {
                              a.push(el);
                          } else {
                              var last = a[a.length - 1];
                              if (last.length == 2) {
                                  var val = "" + last[1] + separator + el[1];
                                  a[a.length - 1] = [ make_node_from_constant(compressor, val, last[0]), val ];
                              } else {
                                  a.push(el);
                              }
                          }
                          return a;
                      }, []);
                      if (elements.length == 0) return make_node(AST_String, self, {
                          value: ""
                      });
                      if (elements.length == 1) return elements[0][0];
                      if (separator == "") {
                          var first;
                          if (elements[0][0] instanceof AST_String || elements[1][0] instanceof AST_String) {
                              first = elements.shift()[0];
                          } else {
                              first = make_node(AST_String, self, {
                                  value: ""
                              });
                          }
                          return elements.reduce(function(prev, el) {
                              return make_node(AST_Binary, el[0], {
                                  operator: "+",
                                  left: prev,
                                  right: el[0]
                              });
                          }, first).transform(compressor);
                      }
                      var node = self.clone();
                      node.expression = node.expression.clone();
                      node.expression.expression = node.expression.expression.clone();
                      node.expression.expression.elements = elements.map(function(el) {
                          return el[0];
                      });
                      return best_of(self, node);
                  }
              }
              if (compressor.option("side_effects")) {
                  if (self.expression instanceof AST_Function && self.args.length == 0 && !AST_Block.prototype.has_side_effects.call(self.expression, compressor)) {
                      return make_node(AST_Undefined, self).transform(compressor);
                  }
              }
              if (compressor.option("drop_console")) {
                  if (self.expression instanceof AST_PropAccess && self.expression.expression instanceof AST_SymbolRef && self.expression.expression.name == "console" && self.expression.expression.undeclared()) {
                      return make_node(AST_Undefined, self).transform(compressor);
                  }
              }
              return self.evaluate(compressor)[0];
          });
          OPT(AST_New, function(self, compressor) {
              if (compressor.option("unsafe")) {
                  var exp = self.expression;
                  if (exp instanceof AST_SymbolRef && exp.undeclared()) {
                      switch (exp.name) {
                        case "Object":
                        case "RegExp":
                        case "Function":
                        case "Error":
                        case "Array":
                          return make_node(AST_Call, self, self).transform(compressor);
                      }
                  }
              }
              return self;
          });
          OPT(AST_Seq, function(self, compressor) {
              if (!compressor.option("side_effects")) return self;
              if (!self.car.has_side_effects(compressor)) {
                  var p;
                  if (!(self.cdr instanceof AST_SymbolRef && self.cdr.name == "eval" && self.cdr.undeclared() && (p = compressor.parent()) instanceof AST_Call && p.expression === self)) {
                      return self.cdr;
                  }
              }
              if (compressor.option("cascade")) {
                  if (self.car instanceof AST_Assign && !self.car.left.has_side_effects(compressor)) {
                      if (self.car.left.equivalent_to(self.cdr)) {
                          return self.car;
                      }
                      if (self.cdr instanceof AST_Call && self.cdr.expression.equivalent_to(self.car.left)) {
                          self.cdr.expression = self.car;
                          return self.cdr;
                      }
                  }
                  if (!self.car.has_side_effects(compressor) && !self.cdr.has_side_effects(compressor) && self.car.equivalent_to(self.cdr)) {
                      return self.car;
                  }
              }
              if (self.cdr instanceof AST_UnaryPrefix && self.cdr.operator == "void" && !self.cdr.expression.has_side_effects(compressor)) {
                  self.cdr.operator = self.car;
                  return self.cdr;
              }
              if (self.cdr instanceof AST_Undefined) {
                  return make_node(AST_UnaryPrefix, self, {
                      operator: "void",
                      expression: self.car
                  });
              }
              return self;
          });
          AST_Unary.DEFMETHOD("lift_sequences", function(compressor) {
              if (compressor.option("sequences")) {
                  if (this.expression instanceof AST_Seq) {
                      var seq = this.expression;
                      var x = seq.to_array();
                      this.expression = x.pop();
                      x.push(this);
                      seq = AST_Seq.from_array(x).transform(compressor);
                      return seq;
                  }
              }
              return this;
          });
          OPT(AST_UnaryPostfix, function(self, compressor) {
              return self.lift_sequences(compressor);
          });
          OPT(AST_UnaryPrefix, function(self, compressor) {
              self = self.lift_sequences(compressor);
              var e = self.expression;
              if (compressor.option("booleans") && compressor.in_boolean_context()) {
                  switch (self.operator) {
                    case "!":
                      if (e instanceof AST_UnaryPrefix && e.operator == "!") {
                          return e.expression;
                      }
                      break;
  
                    case "typeof":
                      compressor.warn("Boolean expression always true [{file}:{line},{col}]", self.start);
                      return make_node(AST_True, self);
                  }
                  if (e instanceof AST_Binary && self.operator == "!") {
                      self = best_of(self, e.negate(compressor));
                  }
              }
              return self.evaluate(compressor)[0];
          });
          function has_side_effects_or_prop_access(node, compressor) {
              var save_pure_getters = compressor.option("pure_getters");
              compressor.options.pure_getters = false;
              var ret = node.has_side_effects(compressor);
              compressor.options.pure_getters = save_pure_getters;
              return ret;
          }
          AST_Binary.DEFMETHOD("lift_sequences", function(compressor) {
              if (compressor.option("sequences")) {
                  if (this.left instanceof AST_Seq) {
                      var seq = this.left;
                      var x = seq.to_array();
                      this.left = x.pop();
                      x.push(this);
                      seq = AST_Seq.from_array(x).transform(compressor);
                      return seq;
                  }
                  if (this.right instanceof AST_Seq && this instanceof AST_Assign && !has_side_effects_or_prop_access(this.left, compressor)) {
                      var seq = this.right;
                      var x = seq.to_array();
                      this.right = x.pop();
                      x.push(this);
                      seq = AST_Seq.from_array(x).transform(compressor);
                      return seq;
                  }
              }
              return this;
          });
          var commutativeOperators = makePredicate("== === != !== * & | ^");
          OPT(AST_Binary, function(self, compressor) {
              var reverse = compressor.has_directive("use asm") ? noop : function(op, force) {
                  if (force || !(self.left.has_side_effects(compressor) || self.right.has_side_effects(compressor))) {
                      if (op) self.operator = op;
                      var tmp = self.left;
                      self.left = self.right;
                      self.right = tmp;
                  }
              };
              if (commutativeOperators(self.operator)) {
                  if (self.right instanceof AST_Constant && !(self.left instanceof AST_Constant)) {
                      if (!(self.left instanceof AST_Binary && PRECEDENCE[self.left.operator] >= PRECEDENCE[self.operator])) {
                          reverse(null, true);
                      }
                  }
                  if (/^[!=]==?$/.test(self.operator)) {
                      if (self.left instanceof AST_SymbolRef && self.right instanceof AST_Conditional) {
                          if (self.right.consequent instanceof AST_SymbolRef && self.right.consequent.definition() === self.left.definition()) {
                              if (/^==/.test(self.operator)) return self.right.condition;
                              if (/^!=/.test(self.operator)) return self.right.condition.negate(compressor);
                          }
                          if (self.right.alternative instanceof AST_SymbolRef && self.right.alternative.definition() === self.left.definition()) {
                              if (/^==/.test(self.operator)) return self.right.condition.negate(compressor);
                              if (/^!=/.test(self.operator)) return self.right.condition;
                          }
                      }
                      if (self.right instanceof AST_SymbolRef && self.left instanceof AST_Conditional) {
                          if (self.left.consequent instanceof AST_SymbolRef && self.left.consequent.definition() === self.right.definition()) {
                              if (/^==/.test(self.operator)) return self.left.condition;
                              if (/^!=/.test(self.operator)) return self.left.condition.negate(compressor);
                          }
                          if (self.left.alternative instanceof AST_SymbolRef && self.left.alternative.definition() === self.right.definition()) {
                              if (/^==/.test(self.operator)) return self.left.condition.negate(compressor);
                              if (/^!=/.test(self.operator)) return self.left.condition;
                          }
                      }
                  }
              }
              self = self.lift_sequences(compressor);
              if (compressor.option("comparisons")) switch (self.operator) {
                case "===":
                case "!==":
                  if (self.left.is_string(compressor) && self.right.is_string(compressor) || self.left.is_boolean() && self.right.is_boolean()) {
                      self.operator = self.operator.substr(0, 2);
                  }
  
                case "==":
                case "!=":
                  if (self.left instanceof AST_String && self.left.value == "undefined" && self.right instanceof AST_UnaryPrefix && self.right.operator == "typeof" && compressor.option("unsafe")) {
                      if (!(self.right.expression instanceof AST_SymbolRef) || !self.right.expression.undeclared()) {
                          self.right = self.right.expression;
                          self.left = make_node(AST_Undefined, self.left).optimize(compressor);
                          if (self.operator.length == 2) self.operator += "=";
                      }
                  }
                  break;
              }
              if (compressor.option("booleans") && compressor.in_boolean_context()) switch (self.operator) {
                case "&&":
                  var ll = self.left.evaluate(compressor);
                  var rr = self.right.evaluate(compressor);
                  if (ll.length > 1 && !ll[1] || rr.length > 1 && !rr[1]) {
                      compressor.warn("Boolean && always false [{file}:{line},{col}]", self.start);
                      return make_node(AST_False, self);
                  }
                  if (ll.length > 1 && ll[1]) {
                      return rr[0];
                  }
                  if (rr.length > 1 && rr[1]) {
                      return ll[0];
                  }
                  break;
  
                case "||":
                  var ll = self.left.evaluate(compressor);
                  var rr = self.right.evaluate(compressor);
                  if (ll.length > 1 && ll[1] || rr.length > 1 && rr[1]) {
                      compressor.warn("Boolean || always true [{file}:{line},{col}]", self.start);
                      return make_node(AST_True, self);
                  }
                  if (ll.length > 1 && !ll[1]) {
                      return rr[0];
                  }
                  if (rr.length > 1 && !rr[1]) {
                      return ll[0];
                  }
                  break;
  
                case "+":
                  var ll = self.left.evaluate(compressor);
                  var rr = self.right.evaluate(compressor);
                  if (ll.length > 1 && ll[0] instanceof AST_String && ll[1] || rr.length > 1 && rr[0] instanceof AST_String && rr[1]) {
                      compressor.warn("+ in boolean context always true [{file}:{line},{col}]", self.start);
                      return make_node(AST_True, self);
                  }
                  break;
              }
              if (compressor.option("comparisons")) {
                  if (!(compressor.parent() instanceof AST_Binary) || compressor.parent() instanceof AST_Assign) {
                      var negated = make_node(AST_UnaryPrefix, self, {
                          operator: "!",
                          expression: self.negate(compressor)
                      });
                      self = best_of(self, negated);
                  }
                  switch (self.operator) {
                    case "<":
                      reverse(">");
                      break;
  
                    case "<=":
                      reverse(">=");
                      break;
                  }
              }
              if (self.operator == "+" && self.right instanceof AST_String && self.right.getValue() === "" && self.left instanceof AST_Binary && self.left.operator == "+" && self.left.is_string(compressor)) {
                  return self.left;
              }
              if (compressor.option("evaluate")) {
                  if (self.operator == "+") {
                      if (self.left instanceof AST_Constant && self.right instanceof AST_Binary && self.right.operator == "+" && self.right.left instanceof AST_Constant && self.right.is_string(compressor)) {
                          self = make_node(AST_Binary, self, {
                              operator: "+",
                              left: make_node(AST_String, null, {
                                  value: "" + self.left.getValue() + self.right.left.getValue(),
                                  start: self.left.start,
                                  end: self.right.left.end
                              }),
                              right: self.right.right
                          });
                      }
                      if (self.right instanceof AST_Constant && self.left instanceof AST_Binary && self.left.operator == "+" && self.left.right instanceof AST_Constant && self.left.is_string(compressor)) {
                          self = make_node(AST_Binary, self, {
                              operator: "+",
                              left: self.left.left,
                              right: make_node(AST_String, null, {
                                  value: "" + self.left.right.getValue() + self.right.getValue(),
                                  start: self.left.right.start,
                                  end: self.right.end
                              })
                          });
                      }
                      if (self.left instanceof AST_Binary && self.left.operator == "+" && self.left.is_string(compressor) && self.left.right instanceof AST_Constant && self.right instanceof AST_Binary && self.right.operator == "+" && self.right.left instanceof AST_Constant && self.right.is_string(compressor)) {
                          self = make_node(AST_Binary, self, {
                              operator: "+",
                              left: make_node(AST_Binary, self.left, {
                                  operator: "+",
                                  left: self.left.left,
                                  right: make_node(AST_String, null, {
                                      value: "" + self.left.right.getValue() + self.right.left.getValue(),
                                      start: self.left.right.start,
                                      end: self.right.left.end
                                  })
                              }),
                              right: self.right.right
                          });
                      }
                  }
              }
              if (self.right instanceof AST_Binary && self.right.operator == self.operator && (self.operator == "*" || self.operator == "&&" || self.operator == "||")) {
                  self.left = make_node(AST_Binary, self.left, {
                      operator: self.operator,
                      left: self.left,
                      right: self.right.left
                  });
                  self.right = self.right.right;
                  return self.transform(compressor);
              }
              return self.evaluate(compressor)[0];
          });
          OPT(AST_SymbolRef, function(self, compressor) {
              if (self.undeclared()) {
                  var defines = compressor.option("global_defs");
                  if (defines && defines.hasOwnProperty(self.name)) {
                      return make_node_from_constant(compressor, defines[self.name], self);
                  }
                  switch (self.name) {
                    case "undefined":
                      return make_node(AST_Undefined, self);
  
                    case "NaN":
                      return make_node(AST_NaN, self);
  
                    case "Infinity":
                      return make_node(AST_Infinity, self);
                  }
              }
              return self;
          });
          OPT(AST_Undefined, function(self, compressor) {
              if (compressor.option("unsafe")) {
                  var scope = compressor.find_parent(AST_Scope);
                  var undef = scope.find_variable("undefined");
                  if (undef) {
                      var ref = make_node(AST_SymbolRef, self, {
                          name: "undefined",
                          scope: scope,
                          thedef: undef
                      });
                      ref.reference();
                      return ref;
                  }
              }
              return self;
          });
          var ASSIGN_OPS = [ "+", "-", "/", "*", "%", ">>", "<<", ">>>", "|", "^", "&" ];
          OPT(AST_Assign, function(self, compressor) {
              self = self.lift_sequences(compressor);
              if (self.operator == "=" && self.left instanceof AST_SymbolRef && self.right instanceof AST_Binary && self.right.left instanceof AST_SymbolRef && self.right.left.name == self.left.name && member(self.right.operator, ASSIGN_OPS)) {
                  self.operator = self.right.operator + "=";
                  self.right = self.right.right;
              }
              return self;
          });
          OPT(AST_Conditional, function(self, compressor) {
              if (!compressor.option("conditionals")) return self;
              if (self.condition instanceof AST_Seq) {
                  var car = self.condition.car;
                  self.condition = self.condition.cdr;
                  return AST_Seq.cons(car, self);
              }
              var cond = self.condition.evaluate(compressor);
              if (cond.length > 1) {
                  if (cond[1]) {
                      compressor.warn("Condition always true [{file}:{line},{col}]", self.start);
                      return self.consequent;
                  } else {
                      compressor.warn("Condition always false [{file}:{line},{col}]", self.start);
                      return self.alternative;
                  }
              }
              var negated = cond[0].negate(compressor);
              if (best_of(cond[0], negated) === negated) {
                  self = make_node(AST_Conditional, self, {
                      condition: negated,
                      consequent: self.alternative,
                      alternative: self.consequent
                  });
              }
              var consequent = self.consequent;
              var alternative = self.alternative;
              if (consequent instanceof AST_Assign && alternative instanceof AST_Assign && consequent.operator == alternative.operator && consequent.left.equivalent_to(alternative.left)) {
                  return make_node(AST_Assign, self, {
                      operator: consequent.operator,
                      left: consequent.left,
                      right: make_node(AST_Conditional, self, {
                          condition: self.condition,
                          consequent: consequent.right,
                          alternative: alternative.right
                      })
                  });
              }
              if (consequent instanceof AST_Call && alternative.TYPE === consequent.TYPE && consequent.args.length == alternative.args.length && consequent.expression.equivalent_to(alternative.expression)) {
                  if (consequent.args.length == 0) {
                      return make_node(AST_Seq, self, {
                          car: self.condition,
                          cdr: consequent
                      });
                  }
                  if (consequent.args.length == 1) {
                      consequent.args[0] = make_node(AST_Conditional, self, {
                          condition: self.condition,
                          consequent: consequent.args[0],
                          alternative: alternative.args[0]
                      });
                      return consequent;
                  }
              }
              if (consequent instanceof AST_Conditional && consequent.alternative.equivalent_to(alternative)) {
                  return make_node(AST_Conditional, self, {
                      condition: make_node(AST_Binary, self, {
                          left: self.condition,
                          operator: "&&",
                          right: consequent.condition
                      }),
                      consequent: consequent.consequent,
                      alternative: alternative
                  });
              }
              return self;
          });
          OPT(AST_Boolean, function(self, compressor) {
              if (compressor.option("booleans")) {
                  var p = compressor.parent();
                  if (p instanceof AST_Binary && (p.operator == "==" || p.operator == "!=")) {
                      compressor.warn("Non-strict equality against boolean: {operator} {value} [{file}:{line},{col}]", {
                          operator: p.operator,
                          value: self.value,
                          file: p.start.file,
                          line: p.start.line,
                          col: p.start.col
                      });
                      return make_node(AST_Number, self, {
                          value: +self.value
                      });
                  }
                  return make_node(AST_UnaryPrefix, self, {
                      operator: "!",
                      expression: make_node(AST_Number, self, {
                          value: 1 - self.value
                      })
                  });
              }
              return self;
          });
          OPT(AST_Sub, function(self, compressor) {
              var prop = self.property;
              if (prop instanceof AST_String && compressor.option("properties")) {
                  prop = prop.getValue();
                  if (RESERVED_WORDS(prop) ? compressor.option("screw_ie8") : is_identifier_string(prop)) {
                      return make_node(AST_Dot, self, {
                          expression: self.expression,
                          property: prop
                      }).optimize(compressor);
                  }
                  var v = parseFloat(prop);
                  if (!isNaN(v) && v.toString() == prop) {
                      self.property = make_node(AST_Number, self.property, {
                          value: v
                      });
                  }
              }
              return self;
          });
          OPT(AST_Dot, function(self, compressor) {
              return self.evaluate(compressor)[0];
          });
          function literals_in_boolean_context(self, compressor) {
              if (compressor.option("booleans") && compressor.in_boolean_context()) {
                  return make_node(AST_True, self);
              }
              return self;
          }
          OPT(AST_Array, literals_in_boolean_context);
          OPT(AST_Object, literals_in_boolean_context);
          OPT(AST_RegExp, literals_in_boolean_context);
      })();
      "use strict";
      function SourceMap(options) {
          options = defaults(options, {
              file: null,
              root: null,
              orig: null,
              orig_line_diff: 0,
              dest_line_diff: 0
          });
          var generator = new MOZ_SourceMap.SourceMapGenerator({
              file: options.file,
              sourceRoot: options.root
          });
          var orig_map = options.orig && new MOZ_SourceMap.SourceMapConsumer(options.orig);
          function add(source, gen_line, gen_col, orig_line, orig_col, name) {
              if (orig_map) {
                  var info = orig_map.originalPositionFor({
                      line: orig_line,
                      column: orig_col
                  });
                  if (info.source === null) {
                      return;
                  }
                  source = info.source;
                  orig_line = info.line;
                  orig_col = info.column;
                  name = info.name;
              }
              generator.addMapping({
                  generated: {
                      line: gen_line + options.dest_line_diff,
                      column: gen_col
                  },
                  original: {
                      line: orig_line + options.orig_line_diff,
                      column: orig_col
                  },
                  source: source,
                  name: name
              });
          }
          return {
              add: add,
              get: function() {
                  return generator;
              },
              toString: function() {
                  return generator.toString();
              }
          };
      }
      "use strict";
      (function() {
          var MOZ_TO_ME = {
              ExpressionStatement: function(M) {
                  var expr = M.expression;
                  if (expr.type === "Literal" && typeof expr.value === "string") {
                      return new AST_Directive({
                          start: my_start_token(M),
                          end: my_end_token(M),
                          value: expr.value
                      });
                  }
                  return new AST_SimpleStatement({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      body: from_moz(expr)
                  });
              },
              TryStatement: function(M) {
                  var handlers = M.handlers || [ M.handler ];
                  if (handlers.length > 1 || M.guardedHandlers && M.guardedHandlers.length) {
                      throw new Error("Multiple catch clauses are not supported.");
                  }
                  return new AST_Try({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      body: from_moz(M.block).body,
                      bcatch: from_moz(handlers[0]),
                      bfinally: M.finalizer ? new AST_Finally(from_moz(M.finalizer)) : null
                  });
              },
              Property: function(M) {
                  var key = M.key;
                  var name = key.type == "Identifier" ? key.name : key.value;
                  var args = {
                      start: my_start_token(key),
                      end: my_end_token(M.value),
                      key: name,
                      value: from_moz(M.value)
                  };
                  switch (M.kind) {
                    case "init":
                      return new AST_ObjectKeyVal(args);
  
                    case "set":
                      args.value.name = from_moz(key);
                      return new AST_ObjectSetter(args);
  
                    case "get":
                      args.value.name = from_moz(key);
                      return new AST_ObjectGetter(args);
                  }
              },
              ObjectExpression: function(M) {
                  return new AST_Object({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      properties: M.properties.map(function(prop) {
                          prop.type = "Property";
                          return from_moz(prop);
                      })
                  });
              },
              SequenceExpression: function(M) {
                  return AST_Seq.from_array(M.expressions.map(from_moz));
              },
              MemberExpression: function(M) {
                  return new (M.computed ? AST_Sub : AST_Dot)({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      property: M.computed ? from_moz(M.property) : M.property.name,
                      expression: from_moz(M.object)
                  });
              },
              SwitchCase: function(M) {
                  return new (M.test ? AST_Case : AST_Default)({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      expression: from_moz(M.test),
                      body: M.consequent.map(from_moz)
                  });
              },
              VariableDeclaration: function(M) {
                  return new (M.kind === "const" ? AST_Const : AST_Var)({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      definitions: M.declarations.map(from_moz)
                  });
              },
              Literal: function(M) {
                  var val = M.value, args = {
                      start: my_start_token(M),
                      end: my_end_token(M)
                  };
                  if (val === null) return new AST_Null(args);
                  switch (typeof val) {
                    case "string":
                      args.value = val;
                      return new AST_String(args);
  
                    case "number":
                      args.value = val;
                      return new AST_Number(args);
  
                    case "boolean":
                      return new (val ? AST_True : AST_False)(args);
  
                    default:
                      args.value = val;
                      return new AST_RegExp(args);
                  }
              },
              Identifier: function(M) {
                  var p = FROM_MOZ_STACK[FROM_MOZ_STACK.length - 2];
                  return new (p.type == "LabeledStatement" ? AST_Label : p.type == "VariableDeclarator" && p.id === M ? p.kind == "const" ? AST_SymbolConst : AST_SymbolVar : p.type == "FunctionExpression" ? p.id === M ? AST_SymbolLambda : AST_SymbolFunarg : p.type == "FunctionDeclaration" ? p.id === M ? AST_SymbolDefun : AST_SymbolFunarg : p.type == "CatchClause" ? AST_SymbolCatch : p.type == "BreakStatement" || p.type == "ContinueStatement" ? AST_LabelRef : AST_SymbolRef)({
                      start: my_start_token(M),
                      end: my_end_token(M),
                      name: M.name
                  });
              }
          };
          MOZ_TO_ME.UpdateExpression = MOZ_TO_ME.UnaryExpression = function To_Moz_Unary(M) {
              var prefix = "prefix" in M ? M.prefix : M.type == "UnaryExpression" ? true : false;
              return new (prefix ? AST_UnaryPrefix : AST_UnaryPostfix)({
                  start: my_start_token(M),
                  end: my_end_token(M),
                  operator: M.operator,
                  expression: from_moz(M.argument)
              });
          };
          map("Program", AST_Toplevel, "body@body");
          map("EmptyStatement", AST_EmptyStatement);
          map("BlockStatement", AST_BlockStatement, "body@body");
          map("IfStatement", AST_If, "test>condition, consequent>body, alternate>alternative");
          map("LabeledStatement", AST_LabeledStatement, "label>label, body>body");
          map("BreakStatement", AST_Break, "label>label");
          map("ContinueStatement", AST_Continue, "label>label");
          map("WithStatement", AST_With, "object>expression, body>body");
          map("SwitchStatement", AST_Switch, "discriminant>expression, cases@body");
          map("ReturnStatement", AST_Return, "argument>value");
          map("ThrowStatement", AST_Throw, "argument>value");
          map("WhileStatement", AST_While, "test>condition, body>body");
          map("DoWhileStatement", AST_Do, "test>condition, body>body");
          map("ForStatement", AST_For, "init>init, test>condition, update>step, body>body");
          map("ForInStatement", AST_ForIn, "left>init, right>object, body>body");
          map("DebuggerStatement", AST_Debugger);
          map("FunctionDeclaration", AST_Defun, "id>name, params@argnames, body%body");
          map("VariableDeclarator", AST_VarDef, "id>name, init>value");
          map("CatchClause", AST_Catch, "param>argname, body%body");
          map("ThisExpression", AST_This);
          map("ArrayExpression", AST_Array, "elements@elements");
          map("FunctionExpression", AST_Function, "id>name, params@argnames, body%body");
          map("BinaryExpression", AST_Binary, "operator=operator, left>left, right>right");
          map("LogicalExpression", AST_Binary, "operator=operator, left>left, right>right");
          map("AssignmentExpression", AST_Assign, "operator=operator, left>left, right>right");
          map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
          map("NewExpression", AST_New, "callee>expression, arguments@args");
          map("CallExpression", AST_Call, "callee>expression, arguments@args");
          def_to_moz(AST_Directive, function To_Moz_Directive(M) {
              return {
                  type: "ExpressionStatement",
                  expression: {
                      type: "Literal",
                      value: M.value
                  }
              };
          });
          def_to_moz(AST_SimpleStatement, function To_Moz_ExpressionStatement(M) {
              return {
                  type: "ExpressionStatement",
                  expression: to_moz(M.body)
              };
          });
          def_to_moz(AST_SwitchBranch, function To_Moz_SwitchCase(M) {
              return {
                  type: "SwitchCase",
                  test: to_moz(M.expression),
                  consequent: M.body.map(to_moz)
              };
          });
          def_to_moz(AST_Try, function To_Moz_TryStatement(M) {
              return {
                  type: "TryStatement",
                  block: to_moz_block(M),
                  handler: to_moz(M.bcatch),
                  guardedHandlers: [],
                  finalizer: to_moz(M.bfinally)
              };
          });
          def_to_moz(AST_Catch, function To_Moz_CatchClause(M) {
              return {
                  type: "CatchClause",
                  param: to_moz(M.argname),
                  guard: null,
                  body: to_moz_block(M)
              };
          });
          def_to_moz(AST_Definitions, function To_Moz_VariableDeclaration(M) {
              return {
                  type: "VariableDeclaration",
                  kind: M instanceof AST_Const ? "const" : "var",
                  declarations: M.definitions.map(to_moz)
              };
          });
          def_to_moz(AST_Seq, function To_Moz_SequenceExpression(M) {
              return {
                  type: "SequenceExpression",
                  expressions: M.to_array().map(to_moz)
              };
          });
          def_to_moz(AST_PropAccess, function To_Moz_MemberExpression(M) {
              var isComputed = M instanceof AST_Sub;
              return {
                  type: "MemberExpression",
                  object: to_moz(M.expression),
                  computed: isComputed,
                  property: isComputed ? to_moz(M.property) : {
                      type: "Identifier",
                      name: M.property
                  }
              };
          });
          def_to_moz(AST_Unary, function To_Moz_Unary(M) {
              return {
                  type: M.operator == "++" || M.operator == "--" ? "UpdateExpression" : "UnaryExpression",
                  operator: M.operator,
                  prefix: M instanceof AST_UnaryPrefix,
                  argument: to_moz(M.expression)
              };
          });
          def_to_moz(AST_Binary, function To_Moz_BinaryExpression(M) {
              return {
                  type: M.operator == "&&" || M.operator == "||" ? "LogicalExpression" : "BinaryExpression",
                  left: to_moz(M.left),
                  operator: M.operator,
                  right: to_moz(M.right)
              };
          });
          def_to_moz(AST_Object, function To_Moz_ObjectExpression(M) {
              return {
                  type: "ObjectExpression",
                  properties: M.properties.map(to_moz)
              };
          });
          def_to_moz(AST_ObjectProperty, function To_Moz_Property(M) {
              var key = is_identifier(M.key) ? {
                  type: "Identifier",
                  name: M.key
              } : {
                  type: "Literal",
                  value: M.key
              };
              var kind;
              if (M instanceof AST_ObjectKeyVal) {
                  kind = "init";
              } else if (M instanceof AST_ObjectGetter) {
                  kind = "get";
              } else if (M instanceof AST_ObjectSetter) {
                  kind = "set";
              }
              return {
                  type: "Property",
                  kind: kind,
                  key: key,
                  value: to_moz(M.value)
              };
          });
          def_to_moz(AST_Symbol, function To_Moz_Identifier(M) {
              var def = M.definition();
              return {
                  type: "Identifier",
                  name: def ? def.mangled_name || def.name : M.name
              };
          });
          def_to_moz(AST_Constant, function To_Moz_Literal(M) {
              var value = M.value;
              if (typeof value === "number" && (value < 0 || value === 0 && 1 / value < 0)) {
                  return {
                      type: "UnaryExpression",
                      operator: "-",
                      prefix: true,
                      argument: {
                          type: "Literal",
                          value: -value
                      }
                  };
              }
              return {
                  type: "Literal",
                  value: value
              };
          });
          def_to_moz(AST_Atom, function To_Moz_Atom(M) {
              return {
                  type: "Identifier",
                  name: String(M.value)
              };
          });
          AST_Boolean.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
          AST_Null.DEFMETHOD("to_mozilla_ast", AST_Constant.prototype.to_mozilla_ast);
          AST_Hole.DEFMETHOD("to_mozilla_ast", function To_Moz_ArrayHole() {
              return null;
          });
          AST_Block.DEFMETHOD("to_mozilla_ast", AST_BlockStatement.prototype.to_mozilla_ast);
          AST_Lambda.DEFMETHOD("to_mozilla_ast", AST_Function.prototype.to_mozilla_ast);
          function my_start_token(moznode) {
              var loc = moznode.loc;
              var range = moznode.range;
              return new AST_Token({
                  file: loc && loc.source,
                  line: loc && loc.start.line,
                  col: loc && loc.start.column,
                  pos: range ? range[0] : moznode.start,
                  endpos: range ? range[0] : moznode.start
              });
          }
          function my_end_token(moznode) {
              var loc = moznode.loc;
              var range = moznode.range;
              return new AST_Token({
                  file: loc && loc.source,
                  line: loc && loc.end.line,
                  col: loc && loc.end.column,
                  pos: range ? range[1] : moznode.end,
                  endpos: range ? range[1] : moznode.end
              });
          }
          function map(moztype, mytype, propmap) {
              if (typeof UglifyJS_NoUnsafeEval !== "undefined") {
                  var prop_list = [];
                  if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
                      var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
                      if (!m) throw new Error("Can't understand property map: " + prop);
                      if ("=@>%".indexOf(m[2]) < 0) {
                          throw new Error("Can't understand operator in propmap: " + prop);
                      }
                      prop_list.push(m);
                  });
                  var moz_to_me = function(M) {
                      var props = {
                          start: my_start_token(M),
                          end: my_end_token(M)
                      };
                      for (var i = 0; i < prop_list.length; i++) {
                          var m = prop_list[i];
                          var moz = m[1], how = m[2], my = m[3];
                          var mozProp = M[moz];
                          var myProp;
                          switch (how) {
                            case "@":
                              myProp = mozProp.map(from_moz);
                              break;
  
                            case ">":
                              myProp = from_moz(mozProp);
                              break;
  
                            case "=":
                              myProp = mozProp;
                              break;
  
                            case "%":
                              myProp = from_moz(mozProp).body;
                              break;
                          }
                          props[my] = myProp;
                      }
                      return new mytype(props);
                  };
                  var me_to_moz = function(M) {
                      var props = {
                          type: moztype
                      };
                      for (var i = 0; i < prop_list.length; i++) {
                          var m = prop_list[i];
                          var moz = m[1], how = m[2], my = m[3];
                          var myProp = M[my];
                          var mozProp;
                          switch (how) {
                            case "@":
                              mozProp = myProp.map(to_moz);
                              break;
  
                            case ">":
                              mozProp = to_moz(myProp);
                              break;
  
                            case "=":
                              mozProp = myProp;
                              break;
  
                            case "%":
                              mozProp = to_moz_block(M);
                              break;
                          }
                          props[moz] = mozProp;
                      }
                      return props;
                  };
                  MOZ_TO_ME[moztype] = moz_to_me;
                  def_to_moz(mytype, me_to_moz);
                  return;
              }
              var moz_to_me = "function From_Moz_" + moztype + "(M){\n";
              moz_to_me += "return new " + mytype.name + "({\n" + "start: my_start_token(M),\n" + "end: my_end_token(M)";
              var me_to_moz = "function To_Moz_" + moztype + "(M){\n";
              me_to_moz += "return {\n" + "type: " + JSON.stringify(moztype);
              if (propmap) propmap.split(/\s*,\s*/).forEach(function(prop) {
                  var m = /([a-z0-9$_]+)(=|@|>|%)([a-z0-9$_]+)/i.exec(prop);
                  if (!m) throw new Error("Can't understand property map: " + prop);
                  var moz = m[1], how = m[2], my = m[3];
                  moz_to_me += ",\n" + my + ": ";
                  me_to_moz += ",\n" + moz + ": ";
                  switch (how) {
                    case "@":
                      moz_to_me += "M." + moz + ".map(from_moz)";
                      me_to_moz += "M." + my + ".map(to_moz)";
                      break;
  
                    case ">":
                      moz_to_me += "from_moz(M." + moz + ")";
                      me_to_moz += "to_moz(M." + my + ")";
                      break;
  
                    case "=":
                      moz_to_me += "M." + moz;
                      me_to_moz += "M." + my;
                      break;
  
                    case "%":
                      moz_to_me += "from_moz(M." + moz + ").body";
                      me_to_moz += "to_moz_block(M)";
                      break;
  
                    default:
                      throw new Error("Can't understand operator in propmap: " + prop);
                  }
              });
              moz_to_me += "\n})\n}";
              me_to_moz += "\n}\n}";
              moz_to_me = new Function("my_start_token", "my_end_token", "from_moz", "return(" + moz_to_me + ")")(my_start_token, my_end_token, from_moz);
              me_to_moz = new Function("to_moz", "to_moz_block", "return(" + me_to_moz + ")")(to_moz, to_moz_block);
              MOZ_TO_ME[moztype] = moz_to_me;
              def_to_moz(mytype, me_to_moz);
          }
          var FROM_MOZ_STACK = null;
          function from_moz(node) {
              FROM_MOZ_STACK.push(node);
              var ret = node != null ? MOZ_TO_ME[node.type](node) : null;
              FROM_MOZ_STACK.pop();
              return ret;
          }
          AST_Node.from_mozilla_ast = function(node) {
              var save_stack = FROM_MOZ_STACK;
              FROM_MOZ_STACK = [];
              var ast = from_moz(node);
              FROM_MOZ_STACK = save_stack;
              return ast;
          };
          function moz_sub_loc(token) {
              return token.line ? {
                  line: token.line,
                  column: token.col
              } : null;
          }
          function set_moz_loc(mynode, moznode) {
              var start = mynode.start;
              var end = mynode.end;
              if (start.pos != null && end.pos != null) {
                  moznode.range = [ start.pos, end.pos ];
              }
              if (start.line) {
                  moznode.loc = {
                      start: moz_sub_loc(start),
                      end: moz_sub_loc(end)
                  };
                  if (start.file) {
                      moznode.loc.source = start.file;
                  }
              }
              return moznode;
          }
          function def_to_moz(mytype, handler) {
              mytype.DEFMETHOD("to_mozilla_ast", function() {
                  return set_moz_loc(this, handler(this));
              });
          }
          function to_moz(node) {
              return node != null ? node.to_mozilla_ast() : null;
          }
          function to_moz_block(node) {
              return {
                  type: "BlockStatement",
                  body: node.body.map(to_moz)
              };
          }
      })();
      exports["array_to_hash"] = array_to_hash;
      exports["slice"] = slice;
      exports["characters"] = characters;
      exports["member"] = member;
      exports["find_if"] = find_if;
      exports["repeat_string"] = repeat_string;
      exports["DefaultsError"] = DefaultsError;
      exports["defaults"] = defaults;
      exports["merge"] = merge;
      exports["noop"] = noop;
      exports["MAP"] = MAP;
      exports["push_uniq"] = push_uniq;
      exports["string_template"] = string_template;
      exports["remove"] = remove;
      exports["mergeSort"] = mergeSort;
      exports["set_difference"] = set_difference;
      exports["set_intersection"] = set_intersection;
      exports["makePredicate"] = makePredicate;
      exports["all"] = all;
      exports["Dictionary"] = Dictionary;
      exports["DEFNODE"] = DEFNODE;
      exports["AST_Token"] = AST_Token;
      exports["AST_Node"] = AST_Node;
      exports["AST_Statement"] = AST_Statement;
      exports["AST_Debugger"] = AST_Debugger;
      exports["AST_Directive"] = AST_Directive;
      exports["AST_SimpleStatement"] = AST_SimpleStatement;
      exports["walk_body"] = walk_body;
      exports["AST_Block"] = AST_Block;
      exports["AST_BlockStatement"] = AST_BlockStatement;
      exports["AST_EmptyStatement"] = AST_EmptyStatement;
      exports["AST_StatementWithBody"] = AST_StatementWithBody;
      exports["AST_LabeledStatement"] = AST_LabeledStatement;
      exports["AST_IterationStatement"] = AST_IterationStatement;
      exports["AST_DWLoop"] = AST_DWLoop;
      exports["AST_Do"] = AST_Do;
      exports["AST_While"] = AST_While;
      exports["AST_For"] = AST_For;
      exports["AST_ForIn"] = AST_ForIn;
      exports["AST_With"] = AST_With;
      exports["AST_Scope"] = AST_Scope;
      exports["AST_Toplevel"] = AST_Toplevel;
      exports["AST_Lambda"] = AST_Lambda;
      exports["AST_Accessor"] = AST_Accessor;
      exports["AST_Function"] = AST_Function;
      exports["AST_Defun"] = AST_Defun;
      exports["AST_Jump"] = AST_Jump;
      exports["AST_Exit"] = AST_Exit;
      exports["AST_Return"] = AST_Return;
      exports["AST_Throw"] = AST_Throw;
      exports["AST_LoopControl"] = AST_LoopControl;
      exports["AST_Break"] = AST_Break;
      exports["AST_Continue"] = AST_Continue;
      exports["AST_If"] = AST_If;
      exports["AST_Switch"] = AST_Switch;
      exports["AST_SwitchBranch"] = AST_SwitchBranch;
      exports["AST_Default"] = AST_Default;
      exports["AST_Case"] = AST_Case;
      exports["AST_Try"] = AST_Try;
      exports["AST_Catch"] = AST_Catch;
      exports["AST_Finally"] = AST_Finally;
      exports["AST_Definitions"] = AST_Definitions;
      exports["AST_Var"] = AST_Var;
      exports["AST_Const"] = AST_Const;
      exports["AST_VarDef"] = AST_VarDef;
      exports["AST_Call"] = AST_Call;
      exports["AST_New"] = AST_New;
      exports["AST_Seq"] = AST_Seq;
      exports["AST_PropAccess"] = AST_PropAccess;
      exports["AST_Dot"] = AST_Dot;
      exports["AST_Sub"] = AST_Sub;
      exports["AST_Unary"] = AST_Unary;
      exports["AST_UnaryPrefix"] = AST_UnaryPrefix;
      exports["AST_UnaryPostfix"] = AST_UnaryPostfix;
      exports["AST_Binary"] = AST_Binary;
      exports["AST_Conditional"] = AST_Conditional;
      exports["AST_Assign"] = AST_Assign;
      exports["AST_Array"] = AST_Array;
      exports["AST_Object"] = AST_Object;
      exports["AST_ObjectProperty"] = AST_ObjectProperty;
      exports["AST_ObjectKeyVal"] = AST_ObjectKeyVal;
      exports["AST_ObjectSetter"] = AST_ObjectSetter;
      exports["AST_ObjectGetter"] = AST_ObjectGetter;
      exports["AST_Symbol"] = AST_Symbol;
      exports["AST_SymbolAccessor"] = AST_SymbolAccessor;
      exports["AST_SymbolDeclaration"] = AST_SymbolDeclaration;
      exports["AST_SymbolVar"] = AST_SymbolVar;
      exports["AST_SymbolConst"] = AST_SymbolConst;
      exports["AST_SymbolFunarg"] = AST_SymbolFunarg;
      exports["AST_SymbolDefun"] = AST_SymbolDefun;
      exports["AST_SymbolLambda"] = AST_SymbolLambda;
      exports["AST_SymbolCatch"] = AST_SymbolCatch;
      exports["AST_Label"] = AST_Label;
      exports["AST_SymbolRef"] = AST_SymbolRef;
      exports["AST_LabelRef"] = AST_LabelRef;
      exports["AST_This"] = AST_This;
      exports["AST_Constant"] = AST_Constant;
      exports["AST_String"] = AST_String;
      exports["AST_Number"] = AST_Number;
      exports["AST_RegExp"] = AST_RegExp;
      exports["AST_Atom"] = AST_Atom;
      exports["AST_Null"] = AST_Null;
      exports["AST_NaN"] = AST_NaN;
      exports["AST_Undefined"] = AST_Undefined;
      exports["AST_Hole"] = AST_Hole;
      exports["AST_Infinity"] = AST_Infinity;
      exports["AST_Boolean"] = AST_Boolean;
      exports["AST_False"] = AST_False;
      exports["AST_True"] = AST_True;
      exports["TreeWalker"] = TreeWalker;
      exports["KEYWORDS"] = KEYWORDS;
      exports["KEYWORDS_ATOM"] = KEYWORDS_ATOM;
      exports["RESERVED_WORDS"] = RESERVED_WORDS;
      exports["KEYWORDS_BEFORE_EXPRESSION"] = KEYWORDS_BEFORE_EXPRESSION;
      exports["OPERATOR_CHARS"] = OPERATOR_CHARS;
      exports["RE_HEX_NUMBER"] = RE_HEX_NUMBER;
      exports["RE_OCT_NUMBER"] = RE_OCT_NUMBER;
      exports["RE_DEC_NUMBER"] = RE_DEC_NUMBER;
      exports["OPERATORS"] = OPERATORS;
      exports["WHITESPACE_CHARS"] = WHITESPACE_CHARS;
      exports["PUNC_BEFORE_EXPRESSION"] = PUNC_BEFORE_EXPRESSION;
      exports["PUNC_CHARS"] = PUNC_CHARS;
      exports["REGEXP_MODIFIERS"] = REGEXP_MODIFIERS;
      exports["UNICODE"] = UNICODE;
      exports["is_letter"] = is_letter;
      exports["is_digit"] = is_digit;
      exports["is_alphanumeric_char"] = is_alphanumeric_char;
      exports["is_unicode_combining_mark"] = is_unicode_combining_mark;
      exports["is_unicode_connector_punctuation"] = is_unicode_connector_punctuation;
      exports["is_identifier"] = is_identifier;
      exports["is_identifier_start"] = is_identifier_start;
      exports["is_identifier_char"] = is_identifier_char;
      exports["is_identifier_string"] = is_identifier_string;
      exports["parse_js_number"] = parse_js_number;
      exports["JS_Parse_Error"] = JS_Parse_Error;
      exports["js_error"] = js_error;
      exports["is_token"] = is_token;
      exports["EX_EOF"] = EX_EOF;
      exports["tokenizer"] = tokenizer;
      exports["UNARY_PREFIX"] = UNARY_PREFIX;
      exports["UNARY_POSTFIX"] = UNARY_POSTFIX;
      exports["ASSIGNMENT"] = ASSIGNMENT;
      exports["PRECEDENCE"] = PRECEDENCE;
      exports["STATEMENTS_WITH_LABELS"] = STATEMENTS_WITH_LABELS;
      exports["ATOMIC_START_TOKEN"] = ATOMIC_START_TOKEN;
      exports["parse"] = parse;
      exports["TreeTransformer"] = TreeTransformer;
      exports["SymbolDef"] = SymbolDef;
      exports["base54"] = base54;
      exports["OutputStream"] = OutputStream;
      exports["Compressor"] = Compressor;
      exports["SourceMap"] = SourceMap;
  })({}, function() {
      return this;
  }());
  },{}],"OmegaPac":[function(require,module,exports){
  var name, ref, value;
  
  module.exports = {
    Conditions: require('./src/conditions'),
    PacGenerator: require('./src/pac_generator'),
    Profiles: require('./src/profiles'),
    RuleList: require('./src/rule_list'),
    ShexpUtils: require('./src/shexp_utils')
  };
  
  ref = require('./src/utils.coffee');
  for (name in ref) {
    value = ref[name];
    module.exports[name] = value;
  }
  
  
  },{"./src/conditions":61,"./src/pac_generator":62,"./src/profiles":63,"./src/rule_list":64,"./src/shexp_utils":65,"./src/utils.coffee":66}]},{},["OmegaPac"])("OmegaPac")
  });
  