9771 lines
282 KiB
JavaScript
9771 lines
282 KiB
JavaScript
// Get in there before browserify
|
|
|
|
var core_require = require;
|
|
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);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){
|
|
|
|
},{}],2:[function(require,module,exports){
|
|
(function (global){
|
|
/*!
|
|
* The buffer module from node.js, for the browser.
|
|
*
|
|
* @author Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
* @license MIT
|
|
*/
|
|
/* eslint-disable no-proto */
|
|
|
|
var base64 = require('base64-js')
|
|
var ieee754 = require('ieee754')
|
|
var isArray = require('is-array')
|
|
|
|
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)
|
|
}
|
|
|
|
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
|
|
}
|
|
|
|
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
|
|
|
|
// pre-set for values that may exist in the future
|
|
Buffer.prototype.length = undefined
|
|
Buffer.prototype.parent = undefined
|
|
|
|
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":3,"ieee754":4,"is-array":5}],3:[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))
|
|
|
|
},{}],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){
|
|
|
|
/**
|
|
* isArray
|
|
*/
|
|
|
|
var isArray = Array.isArray;
|
|
|
|
/**
|
|
* toString
|
|
*/
|
|
|
|
var str = Object.prototype.toString;
|
|
|
|
/**
|
|
* Whether or not the given `val`
|
|
* is an array.
|
|
*
|
|
* example:
|
|
*
|
|
* isArray([]);
|
|
* // > true
|
|
* isArray(arguments);
|
|
* // > false
|
|
* isArray('');
|
|
* // > false
|
|
*
|
|
* @param {mixed} val
|
|
* @return {bool}
|
|
*/
|
|
|
|
module.exports = isArray || function (val) {
|
|
return !! val && '[object Array]' == str.call(val);
|
|
};
|
|
|
|
},{}],6:[function(require,module,exports){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
function EventEmitter() {
|
|
this._events = this._events || {};
|
|
this._maxListeners = this._maxListeners || undefined;
|
|
}
|
|
module.exports = EventEmitter;
|
|
|
|
// Backwards-compat with node 0.10.x
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
EventEmitter.prototype._events = undefined;
|
|
EventEmitter.prototype._maxListeners = undefined;
|
|
|
|
// By default EventEmitters will print a warning if more than 10 listeners are
|
|
// added to it. This is a useful default which helps finding memory leaks.
|
|
EventEmitter.defaultMaxListeners = 10;
|
|
|
|
// Obviously not all Emitters should be limited to 10. This function allows
|
|
// that to be increased. Set to zero for unlimited.
|
|
EventEmitter.prototype.setMaxListeners = function(n) {
|
|
if (!isNumber(n) || n < 0 || isNaN(n))
|
|
throw TypeError('n must be a positive number');
|
|
this._maxListeners = n;
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.emit = function(type) {
|
|
var er, handler, len, args, i, listeners;
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// If there is no 'error' event listener then throw.
|
|
if (type === 'error') {
|
|
if (!this._events.error ||
|
|
(isObject(this._events.error) && !this._events.error.length)) {
|
|
er = arguments[1];
|
|
if (er instanceof Error) {
|
|
throw er; // Unhandled 'error' event
|
|
}
|
|
throw TypeError('Uncaught, unspecified "error" event.');
|
|
}
|
|
}
|
|
|
|
handler = this._events[type];
|
|
|
|
if (isUndefined(handler))
|
|
return false;
|
|
|
|
if (isFunction(handler)) {
|
|
switch (arguments.length) {
|
|
// fast cases
|
|
case 1:
|
|
handler.call(this);
|
|
break;
|
|
case 2:
|
|
handler.call(this, arguments[1]);
|
|
break;
|
|
case 3:
|
|
handler.call(this, arguments[1], arguments[2]);
|
|
break;
|
|
// slower
|
|
default:
|
|
len = arguments.length;
|
|
args = new Array(len - 1);
|
|
for (i = 1; i < len; i++)
|
|
args[i - 1] = arguments[i];
|
|
handler.apply(this, args);
|
|
}
|
|
} else if (isObject(handler)) {
|
|
len = arguments.length;
|
|
args = new Array(len - 1);
|
|
for (i = 1; i < len; i++)
|
|
args[i - 1] = arguments[i];
|
|
|
|
listeners = handler.slice();
|
|
len = listeners.length;
|
|
for (i = 0; i < len; i++)
|
|
listeners[i].apply(this, args);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
EventEmitter.prototype.addListener = function(type, listener) {
|
|
var m;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events)
|
|
this._events = {};
|
|
|
|
// To avoid recursion in the case that type === "newListener"! Before
|
|
// adding it to the listeners, first emit "newListener".
|
|
if (this._events.newListener)
|
|
this.emit('newListener', type,
|
|
isFunction(listener.listener) ?
|
|
listener.listener : listener);
|
|
|
|
if (!this._events[type])
|
|
// Optimize the case of one listener. Don't need the extra array object.
|
|
this._events[type] = listener;
|
|
else if (isObject(this._events[type]))
|
|
// If we've already got an array, just append.
|
|
this._events[type].push(listener);
|
|
else
|
|
// Adding the second element, need to change to array.
|
|
this._events[type] = [this._events[type], listener];
|
|
|
|
// Check for listener leak
|
|
if (isObject(this._events[type]) && !this._events[type].warned) {
|
|
var m;
|
|
if (!isUndefined(this._maxListeners)) {
|
|
m = this._maxListeners;
|
|
} else {
|
|
m = EventEmitter.defaultMaxListeners;
|
|
}
|
|
|
|
if (m && m > 0 && this._events[type].length > m) {
|
|
this._events[type].warned = true;
|
|
console.error('(node) warning: possible EventEmitter memory ' +
|
|
'leak detected. %d listeners added. ' +
|
|
'Use emitter.setMaxListeners() to increase limit.',
|
|
this._events[type].length);
|
|
if (typeof console.trace === 'function') {
|
|
// not supported in IE 10
|
|
console.trace();
|
|
}
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.on = EventEmitter.prototype.addListener;
|
|
|
|
EventEmitter.prototype.once = function(type, listener) {
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
var fired = false;
|
|
|
|
function g() {
|
|
this.removeListener(type, g);
|
|
|
|
if (!fired) {
|
|
fired = true;
|
|
listener.apply(this, arguments);
|
|
}
|
|
}
|
|
|
|
g.listener = listener;
|
|
this.on(type, g);
|
|
|
|
return this;
|
|
};
|
|
|
|
// emits a 'removeListener' event iff the listener was removed
|
|
EventEmitter.prototype.removeListener = function(type, listener) {
|
|
var list, position, length, i;
|
|
|
|
if (!isFunction(listener))
|
|
throw TypeError('listener must be a function');
|
|
|
|
if (!this._events || !this._events[type])
|
|
return this;
|
|
|
|
list = this._events[type];
|
|
length = list.length;
|
|
position = -1;
|
|
|
|
if (list === listener ||
|
|
(isFunction(list.listener) && list.listener === listener)) {
|
|
delete this._events[type];
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
|
|
} else if (isObject(list)) {
|
|
for (i = length; i-- > 0;) {
|
|
if (list[i] === listener ||
|
|
(list[i].listener && list[i].listener === listener)) {
|
|
position = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (position < 0)
|
|
return this;
|
|
|
|
if (list.length === 1) {
|
|
list.length = 0;
|
|
delete this._events[type];
|
|
} else {
|
|
list.splice(position, 1);
|
|
}
|
|
|
|
if (this._events.removeListener)
|
|
this.emit('removeListener', type, listener);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.removeAllListeners = function(type) {
|
|
var key, listeners;
|
|
|
|
if (!this._events)
|
|
return this;
|
|
|
|
// not listening for removeListener, no need to emit
|
|
if (!this._events.removeListener) {
|
|
if (arguments.length === 0)
|
|
this._events = {};
|
|
else if (this._events[type])
|
|
delete this._events[type];
|
|
return this;
|
|
}
|
|
|
|
// emit removeListener for all listeners on all events
|
|
if (arguments.length === 0) {
|
|
for (key in this._events) {
|
|
if (key === 'removeListener') continue;
|
|
this.removeAllListeners(key);
|
|
}
|
|
this.removeAllListeners('removeListener');
|
|
this._events = {};
|
|
return this;
|
|
}
|
|
|
|
listeners = this._events[type];
|
|
|
|
if (isFunction(listeners)) {
|
|
this.removeListener(type, listeners);
|
|
} else {
|
|
// LIFO order
|
|
while (listeners.length)
|
|
this.removeListener(type, listeners[listeners.length - 1]);
|
|
}
|
|
delete this._events[type];
|
|
|
|
return this;
|
|
};
|
|
|
|
EventEmitter.prototype.listeners = function(type) {
|
|
var ret;
|
|
if (!this._events || !this._events[type])
|
|
ret = [];
|
|
else if (isFunction(this._events[type]))
|
|
ret = [this._events[type]];
|
|
else
|
|
ret = this._events[type].slice();
|
|
return ret;
|
|
};
|
|
|
|
EventEmitter.listenerCount = function(emitter, type) {
|
|
var ret;
|
|
if (!emitter._events || !emitter._events[type])
|
|
ret = 0;
|
|
else if (isFunction(emitter._events[type]))
|
|
ret = 1;
|
|
else
|
|
ret = emitter._events[type].length;
|
|
return ret;
|
|
};
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
|
|
},{}],7:[function(require,module,exports){
|
|
if (typeof Object.create === 'function') {
|
|
// implementation from standard node.js 'util' module
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
ctor.prototype = Object.create(superCtor.prototype, {
|
|
constructor: {
|
|
value: ctor,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
};
|
|
} else {
|
|
// old school shim for old browsers
|
|
module.exports = function inherits(ctor, superCtor) {
|
|
ctor.super_ = superCtor
|
|
var TempCtor = function () {}
|
|
TempCtor.prototype = superCtor.prototype
|
|
ctor.prototype = new TempCtor()
|
|
ctor.prototype.constructor = ctor
|
|
}
|
|
}
|
|
|
|
},{}],8:[function(require,module,exports){
|
|
/**
|
|
* Determine if an object is Buffer
|
|
*
|
|
* Author: Feross Aboukhadijeh <feross@feross.org> <http://feross.org>
|
|
* License: MIT
|
|
*
|
|
* `npm install is-buffer`
|
|
*/
|
|
|
|
module.exports = function (obj) {
|
|
return !!(obj != null &&
|
|
(obj._isBuffer || // For Safari 5-7 (missing Object.prototype.constructor)
|
|
(obj.constructor &&
|
|
typeof obj.constructor.isBuffer === 'function' &&
|
|
obj.constructor.isBuffer(obj))
|
|
))
|
|
}
|
|
|
|
},{}],9:[function(require,module,exports){
|
|
module.exports = Array.isArray || function (arr) {
|
|
return Object.prototype.toString.call(arr) == '[object Array]';
|
|
};
|
|
|
|
},{}],10:[function(require,module,exports){
|
|
// shim for using process in browser
|
|
|
|
var process = module.exports = {};
|
|
var queue = [];
|
|
var draining = false;
|
|
var currentQueue;
|
|
var queueIndex = -1;
|
|
|
|
function cleanUpNextTick() {
|
|
draining = false;
|
|
if (currentQueue.length) {
|
|
queue = currentQueue.concat(queue);
|
|
} else {
|
|
queueIndex = -1;
|
|
}
|
|
if (queue.length) {
|
|
drainQueue();
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
var timeout = setTimeout(cleanUpNextTick);
|
|
draining = true;
|
|
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
while (++queueIndex < len) {
|
|
if (currentQueue) {
|
|
currentQueue[queueIndex].run();
|
|
}
|
|
}
|
|
queueIndex = -1;
|
|
len = queue.length;
|
|
}
|
|
currentQueue = null;
|
|
draining = false;
|
|
clearTimeout(timeout);
|
|
}
|
|
|
|
process.nextTick = function (fun) {
|
|
var args = new Array(arguments.length - 1);
|
|
if (arguments.length > 1) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
}
|
|
queue.push(new Item(fun, args));
|
|
if (queue.length === 1 && !draining) {
|
|
setTimeout(drainQueue, 0);
|
|
}
|
|
};
|
|
|
|
// v8 likes predictible objects
|
|
function Item(fun, array) {
|
|
this.fun = fun;
|
|
this.array = array;
|
|
}
|
|
Item.prototype.run = function () {
|
|
this.fun.apply(null, this.array);
|
|
};
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
},{}],11:[function(require,module,exports){
|
|
(function (global){
|
|
/*! https://mths.be/punycode v1.3.2 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 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.
|
|
* http://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.3.2',
|
|
/**
|
|
* 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 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 : {})
|
|
},{}],12:[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]';
|
|
};
|
|
|
|
},{}],13:[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;
|
|
};
|
|
|
|
},{}],14:[function(require,module,exports){
|
|
'use strict';
|
|
|
|
exports.decode = exports.parse = require('./decode');
|
|
exports.encode = exports.stringify = require('./encode');
|
|
|
|
},{"./decode":12,"./encode":13}],15:[function(require,module,exports){
|
|
module.exports = require("./lib/_stream_duplex.js")
|
|
|
|
},{"./lib/_stream_duplex.js":16}],16:[function(require,module,exports){
|
|
(function (process){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
// a duplex stream is just a stream that is both readable and writable.
|
|
// Since JS doesn't have multiple prototypal inheritance, this class
|
|
// prototypally inherits from Readable, and then parasitically from
|
|
// Writable.
|
|
|
|
module.exports = Duplex;
|
|
|
|
/*<replacement>*/
|
|
var objectKeys = Object.keys || function (obj) {
|
|
var keys = [];
|
|
for (var key in obj) keys.push(key);
|
|
return keys;
|
|
}
|
|
/*</replacement>*/
|
|
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
var Readable = require('./_stream_readable');
|
|
var Writable = require('./_stream_writable');
|
|
|
|
util.inherits(Duplex, Readable);
|
|
|
|
forEach(objectKeys(Writable.prototype), function(method) {
|
|
if (!Duplex.prototype[method])
|
|
Duplex.prototype[method] = Writable.prototype[method];
|
|
});
|
|
|
|
function Duplex(options) {
|
|
if (!(this instanceof Duplex))
|
|
return new Duplex(options);
|
|
|
|
Readable.call(this, options);
|
|
Writable.call(this, options);
|
|
|
|
if (options && options.readable === false)
|
|
this.readable = false;
|
|
|
|
if (options && options.writable === false)
|
|
this.writable = false;
|
|
|
|
this.allowHalfOpen = true;
|
|
if (options && options.allowHalfOpen === false)
|
|
this.allowHalfOpen = false;
|
|
|
|
this.once('end', onend);
|
|
}
|
|
|
|
// the no-half-open enforcer
|
|
function onend() {
|
|
// if we allow half-open state, or if the writable side ended,
|
|
// then we're ok.
|
|
if (this.allowHalfOpen || this._writableState.ended)
|
|
return;
|
|
|
|
// no more data can be written.
|
|
// But allow more writes to happen in this tick.
|
|
process.nextTick(this.end.bind(this));
|
|
}
|
|
|
|
function forEach (xs, f) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
f(xs[i], i);
|
|
}
|
|
}
|
|
|
|
}).call(this,require('_process'))
|
|
},{"./_stream_readable":18,"./_stream_writable":20,"_process":10,"core-util-is":21,"inherits":7}],17:[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.
|
|
|
|
// a passthrough stream.
|
|
// basically just the most minimal sort of Transform stream.
|
|
// Every written chunk gets output as-is.
|
|
|
|
module.exports = PassThrough;
|
|
|
|
var Transform = require('./_stream_transform');
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
util.inherits(PassThrough, Transform);
|
|
|
|
function PassThrough(options) {
|
|
if (!(this instanceof PassThrough))
|
|
return new PassThrough(options);
|
|
|
|
Transform.call(this, options);
|
|
}
|
|
|
|
PassThrough.prototype._transform = function(chunk, encoding, cb) {
|
|
cb(null, chunk);
|
|
};
|
|
|
|
},{"./_stream_transform":19,"core-util-is":21,"inherits":7}],18:[function(require,module,exports){
|
|
(function (process){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
module.exports = Readable;
|
|
|
|
/*<replacement>*/
|
|
var isArray = require('isarray');
|
|
/*</replacement>*/
|
|
|
|
|
|
/*<replacement>*/
|
|
var Buffer = require('buffer').Buffer;
|
|
/*</replacement>*/
|
|
|
|
Readable.ReadableState = ReadableState;
|
|
|
|
var EE = require('events').EventEmitter;
|
|
|
|
/*<replacement>*/
|
|
if (!EE.listenerCount) EE.listenerCount = function(emitter, type) {
|
|
return emitter.listeners(type).length;
|
|
};
|
|
/*</replacement>*/
|
|
|
|
var Stream = require('stream');
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
var StringDecoder;
|
|
|
|
|
|
/*<replacement>*/
|
|
var debug = require('util');
|
|
if (debug && debug.debuglog) {
|
|
debug = debug.debuglog('stream');
|
|
} else {
|
|
debug = function () {};
|
|
}
|
|
/*</replacement>*/
|
|
|
|
|
|
util.inherits(Readable, Stream);
|
|
|
|
function ReadableState(options, stream) {
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
options = options || {};
|
|
|
|
// the point at which it stops calling _read() to fill the buffer
|
|
// Note: 0 is a valid value, means "don't call _read preemptively ever"
|
|
var hwm = options.highWaterMark;
|
|
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
|
|
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
|
|
|
|
// cast to ints.
|
|
this.highWaterMark = ~~this.highWaterMark;
|
|
|
|
this.buffer = [];
|
|
this.length = 0;
|
|
this.pipes = null;
|
|
this.pipesCount = 0;
|
|
this.flowing = null;
|
|
this.ended = false;
|
|
this.endEmitted = false;
|
|
this.reading = false;
|
|
|
|
// a flag to be able to tell if the onwrite cb is called immediately,
|
|
// or on a later tick. We set this to true at first, because any
|
|
// actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first write call.
|
|
this.sync = true;
|
|
|
|
// whenever we return null, then we set a flag to say
|
|
// that we're awaiting a 'readable' event emission.
|
|
this.needReadable = false;
|
|
this.emittedReadable = false;
|
|
this.readableListening = false;
|
|
|
|
|
|
// object stream flag. Used to make read(n) ignore n and to
|
|
// make all the buffer merging and length checks go away
|
|
this.objectMode = !!options.objectMode;
|
|
|
|
if (stream instanceof Duplex)
|
|
this.objectMode = this.objectMode || !!options.readableObjectMode;
|
|
|
|
// Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
|
|
// when piping, we only care about 'readable' events that happen
|
|
// after read()ing all the bytes and not getting any pushback.
|
|
this.ranOut = false;
|
|
|
|
// the number of writers that are awaiting a drain event in .pipe()s
|
|
this.awaitDrain = 0;
|
|
|
|
// if true, a maybeReadMore has been scheduled
|
|
this.readingMore = false;
|
|
|
|
this.decoder = null;
|
|
this.encoding = null;
|
|
if (options.encoding) {
|
|
if (!StringDecoder)
|
|
StringDecoder = require('string_decoder/').StringDecoder;
|
|
this.decoder = new StringDecoder(options.encoding);
|
|
this.encoding = options.encoding;
|
|
}
|
|
}
|
|
|
|
function Readable(options) {
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
if (!(this instanceof Readable))
|
|
return new Readable(options);
|
|
|
|
this._readableState = new ReadableState(options, this);
|
|
|
|
// legacy
|
|
this.readable = true;
|
|
|
|
Stream.call(this);
|
|
}
|
|
|
|
// Manually shove something into the read() buffer.
|
|
// This returns true if the highWaterMark has not been hit yet,
|
|
// similar to how Writable.write() returns true if you should
|
|
// write() some more.
|
|
Readable.prototype.push = function(chunk, encoding) {
|
|
var state = this._readableState;
|
|
|
|
if (util.isString(chunk) && !state.objectMode) {
|
|
encoding = encoding || state.defaultEncoding;
|
|
if (encoding !== state.encoding) {
|
|
chunk = new Buffer(chunk, encoding);
|
|
encoding = '';
|
|
}
|
|
}
|
|
|
|
return readableAddChunk(this, state, chunk, encoding, false);
|
|
};
|
|
|
|
// Unshift should *always* be something directly out of read()
|
|
Readable.prototype.unshift = function(chunk) {
|
|
var state = this._readableState;
|
|
return readableAddChunk(this, state, chunk, '', true);
|
|
};
|
|
|
|
function readableAddChunk(stream, state, chunk, encoding, addToFront) {
|
|
var er = chunkInvalid(state, chunk);
|
|
if (er) {
|
|
stream.emit('error', er);
|
|
} else if (util.isNullOrUndefined(chunk)) {
|
|
state.reading = false;
|
|
if (!state.ended)
|
|
onEofChunk(stream, state);
|
|
} else if (state.objectMode || chunk && chunk.length > 0) {
|
|
if (state.ended && !addToFront) {
|
|
var e = new Error('stream.push() after EOF');
|
|
stream.emit('error', e);
|
|
} else if (state.endEmitted && addToFront) {
|
|
var e = new Error('stream.unshift() after end event');
|
|
stream.emit('error', e);
|
|
} else {
|
|
if (state.decoder && !addToFront && !encoding)
|
|
chunk = state.decoder.write(chunk);
|
|
|
|
if (!addToFront)
|
|
state.reading = false;
|
|
|
|
// if we want the data now, just emit it.
|
|
if (state.flowing && state.length === 0 && !state.sync) {
|
|
stream.emit('data', chunk);
|
|
stream.read(0);
|
|
} else {
|
|
// update the buffer info.
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
if (addToFront)
|
|
state.buffer.unshift(chunk);
|
|
else
|
|
state.buffer.push(chunk);
|
|
|
|
if (state.needReadable)
|
|
emitReadable(stream);
|
|
}
|
|
|
|
maybeReadMore(stream, state);
|
|
}
|
|
} else if (!addToFront) {
|
|
state.reading = false;
|
|
}
|
|
|
|
return needMoreData(state);
|
|
}
|
|
|
|
|
|
|
|
// if it's past the high water mark, we can push in some more.
|
|
// Also, if we have no data yet, we can stand some
|
|
// more bytes. This is to work around cases where hwm=0,
|
|
// such as the repl. Also, if the push() triggered a
|
|
// readable event, and the user called read(largeNumber) such that
|
|
// needReadable was set, then we ought to push more, so that another
|
|
// 'readable' event will be triggered.
|
|
function needMoreData(state) {
|
|
return !state.ended &&
|
|
(state.needReadable ||
|
|
state.length < state.highWaterMark ||
|
|
state.length === 0);
|
|
}
|
|
|
|
// backwards compatibility.
|
|
Readable.prototype.setEncoding = function(enc) {
|
|
if (!StringDecoder)
|
|
StringDecoder = require('string_decoder/').StringDecoder;
|
|
this._readableState.decoder = new StringDecoder(enc);
|
|
this._readableState.encoding = enc;
|
|
return this;
|
|
};
|
|
|
|
// Don't raise the hwm > 128MB
|
|
var MAX_HWM = 0x800000;
|
|
function roundUpToNextPowerOf2(n) {
|
|
if (n >= MAX_HWM) {
|
|
n = MAX_HWM;
|
|
} else {
|
|
// Get the next highest power of 2
|
|
n--;
|
|
for (var p = 1; p < 32; p <<= 1) n |= n >> p;
|
|
n++;
|
|
}
|
|
return n;
|
|
}
|
|
|
|
function howMuchToRead(n, state) {
|
|
if (state.length === 0 && state.ended)
|
|
return 0;
|
|
|
|
if (state.objectMode)
|
|
return n === 0 ? 0 : 1;
|
|
|
|
if (isNaN(n) || util.isNull(n)) {
|
|
// only flow one buffer at a time
|
|
if (state.flowing && state.buffer.length)
|
|
return state.buffer[0].length;
|
|
else
|
|
return state.length;
|
|
}
|
|
|
|
if (n <= 0)
|
|
return 0;
|
|
|
|
// If we're asking for more than the target buffer level,
|
|
// then raise the water mark. Bump up to the next highest
|
|
// power of 2, to prevent increasing it excessively in tiny
|
|
// amounts.
|
|
if (n > state.highWaterMark)
|
|
state.highWaterMark = roundUpToNextPowerOf2(n);
|
|
|
|
// don't have that much. return null, unless we've ended.
|
|
if (n > state.length) {
|
|
if (!state.ended) {
|
|
state.needReadable = true;
|
|
return 0;
|
|
} else
|
|
return state.length;
|
|
}
|
|
|
|
return n;
|
|
}
|
|
|
|
// you can override either this method, or the async _read(n) below.
|
|
Readable.prototype.read = function(n) {
|
|
debug('read', n);
|
|
var state = this._readableState;
|
|
var nOrig = n;
|
|
|
|
if (!util.isNumber(n) || n > 0)
|
|
state.emittedReadable = false;
|
|
|
|
// if we're doing read(0) to trigger a readable event, but we
|
|
// already have a bunch of data in the buffer, then just trigger
|
|
// the 'readable' event and move on.
|
|
if (n === 0 &&
|
|
state.needReadable &&
|
|
(state.length >= state.highWaterMark || state.ended)) {
|
|
debug('read: emitReadable', state.length, state.ended);
|
|
if (state.length === 0 && state.ended)
|
|
endReadable(this);
|
|
else
|
|
emitReadable(this);
|
|
return null;
|
|
}
|
|
|
|
n = howMuchToRead(n, state);
|
|
|
|
// if we've ended, and we're now clear, then finish it up.
|
|
if (n === 0 && state.ended) {
|
|
if (state.length === 0)
|
|
endReadable(this);
|
|
return null;
|
|
}
|
|
|
|
// All the actual chunk generation logic needs to be
|
|
// *below* the call to _read. The reason is that in certain
|
|
// synthetic stream cases, such as passthrough streams, _read
|
|
// may be a completely synchronous operation which may change
|
|
// the state of the read buffer, providing enough data when
|
|
// before there was *not* enough.
|
|
//
|
|
// So, the steps are:
|
|
// 1. Figure out what the state of things will be after we do
|
|
// a read from the buffer.
|
|
//
|
|
// 2. If that resulting state will trigger a _read, then call _read.
|
|
// Note that this may be asynchronous, or synchronous. Yes, it is
|
|
// deeply ugly to write APIs this way, but that still doesn't mean
|
|
// that the Readable class should behave improperly, as streams are
|
|
// designed to be sync/async agnostic.
|
|
// Take note if the _read call is sync or async (ie, if the read call
|
|
// has returned yet), so that we know whether or not it's safe to emit
|
|
// 'readable' etc.
|
|
//
|
|
// 3. Actually pull the requested chunks out of the buffer and return.
|
|
|
|
// if we need a readable event, then we need to do some reading.
|
|
var doRead = state.needReadable;
|
|
debug('need readable', doRead);
|
|
|
|
// if we currently have less than the highWaterMark, then also read some
|
|
if (state.length === 0 || state.length - n < state.highWaterMark) {
|
|
doRead = true;
|
|
debug('length less than watermark', doRead);
|
|
}
|
|
|
|
// however, if we've ended, then there's no point, and if we're already
|
|
// reading, then it's unnecessary.
|
|
if (state.ended || state.reading) {
|
|
doRead = false;
|
|
debug('reading or ended', doRead);
|
|
}
|
|
|
|
if (doRead) {
|
|
debug('do read');
|
|
state.reading = true;
|
|
state.sync = true;
|
|
// if the length is currently zero, then we *need* a readable event.
|
|
if (state.length === 0)
|
|
state.needReadable = true;
|
|
// call internal read method
|
|
this._read(state.highWaterMark);
|
|
state.sync = false;
|
|
}
|
|
|
|
// If _read pushed data synchronously, then `reading` will be false,
|
|
// and we need to re-evaluate how much data we can return to the user.
|
|
if (doRead && !state.reading)
|
|
n = howMuchToRead(nOrig, state);
|
|
|
|
var ret;
|
|
if (n > 0)
|
|
ret = fromList(n, state);
|
|
else
|
|
ret = null;
|
|
|
|
if (util.isNull(ret)) {
|
|
state.needReadable = true;
|
|
n = 0;
|
|
}
|
|
|
|
state.length -= n;
|
|
|
|
// If we have nothing in the buffer, then we want to know
|
|
// as soon as we *do* get something into the buffer.
|
|
if (state.length === 0 && !state.ended)
|
|
state.needReadable = true;
|
|
|
|
// If we tried to read() past the EOF, then emit end on the next tick.
|
|
if (nOrig !== n && state.ended && state.length === 0)
|
|
endReadable(this);
|
|
|
|
if (!util.isNull(ret))
|
|
this.emit('data', ret);
|
|
|
|
return ret;
|
|
};
|
|
|
|
function chunkInvalid(state, chunk) {
|
|
var er = null;
|
|
if (!util.isBuffer(chunk) &&
|
|
!util.isString(chunk) &&
|
|
!util.isNullOrUndefined(chunk) &&
|
|
!state.objectMode) {
|
|
er = new TypeError('Invalid non-string/buffer chunk');
|
|
}
|
|
return er;
|
|
}
|
|
|
|
|
|
function onEofChunk(stream, state) {
|
|
if (state.decoder && !state.ended) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length) {
|
|
state.buffer.push(chunk);
|
|
state.length += state.objectMode ? 1 : chunk.length;
|
|
}
|
|
}
|
|
state.ended = true;
|
|
|
|
// emit 'readable' now to make sure it gets picked up.
|
|
emitReadable(stream);
|
|
}
|
|
|
|
// Don't emit readable right away in sync mode, because this can trigger
|
|
// another read() call => stack overflow. This way, it might trigger
|
|
// a nextTick recursion warning, but that's not so bad.
|
|
function emitReadable(stream) {
|
|
var state = stream._readableState;
|
|
state.needReadable = false;
|
|
if (!state.emittedReadable) {
|
|
debug('emitReadable', state.flowing);
|
|
state.emittedReadable = true;
|
|
if (state.sync)
|
|
process.nextTick(function() {
|
|
emitReadable_(stream);
|
|
});
|
|
else
|
|
emitReadable_(stream);
|
|
}
|
|
}
|
|
|
|
function emitReadable_(stream) {
|
|
debug('emit readable');
|
|
stream.emit('readable');
|
|
flow(stream);
|
|
}
|
|
|
|
|
|
// at this point, the user has presumably seen the 'readable' event,
|
|
// and called read() to consume some data. that may have triggered
|
|
// in turn another _read(n) call, in which case reading = true if
|
|
// it's in progress.
|
|
// However, if we're not ended, or reading, and the length < hwm,
|
|
// then go ahead and try to read some more preemptively.
|
|
function maybeReadMore(stream, state) {
|
|
if (!state.readingMore) {
|
|
state.readingMore = true;
|
|
process.nextTick(function() {
|
|
maybeReadMore_(stream, state);
|
|
});
|
|
}
|
|
}
|
|
|
|
function maybeReadMore_(stream, state) {
|
|
var len = state.length;
|
|
while (!state.reading && !state.flowing && !state.ended &&
|
|
state.length < state.highWaterMark) {
|
|
debug('maybeReadMore read 0');
|
|
stream.read(0);
|
|
if (len === state.length)
|
|
// didn't get any data, stop spinning.
|
|
break;
|
|
else
|
|
len = state.length;
|
|
}
|
|
state.readingMore = false;
|
|
}
|
|
|
|
// abstract method. to be overridden in specific implementation classes.
|
|
// call cb(er, data) where data is <= n in length.
|
|
// for virtual (non-string, non-buffer) streams, "length" is somewhat
|
|
// arbitrary, and perhaps not very meaningful.
|
|
Readable.prototype._read = function(n) {
|
|
this.emit('error', new Error('not implemented'));
|
|
};
|
|
|
|
Readable.prototype.pipe = function(dest, pipeOpts) {
|
|
var src = this;
|
|
var state = this._readableState;
|
|
|
|
switch (state.pipesCount) {
|
|
case 0:
|
|
state.pipes = dest;
|
|
break;
|
|
case 1:
|
|
state.pipes = [state.pipes, dest];
|
|
break;
|
|
default:
|
|
state.pipes.push(dest);
|
|
break;
|
|
}
|
|
state.pipesCount += 1;
|
|
debug('pipe count=%d opts=%j', state.pipesCount, pipeOpts);
|
|
|
|
var doEnd = (!pipeOpts || pipeOpts.end !== false) &&
|
|
dest !== process.stdout &&
|
|
dest !== process.stderr;
|
|
|
|
var endFn = doEnd ? onend : cleanup;
|
|
if (state.endEmitted)
|
|
process.nextTick(endFn);
|
|
else
|
|
src.once('end', endFn);
|
|
|
|
dest.on('unpipe', onunpipe);
|
|
function onunpipe(readable) {
|
|
debug('onunpipe');
|
|
if (readable === src) {
|
|
cleanup();
|
|
}
|
|
}
|
|
|
|
function onend() {
|
|
debug('onend');
|
|
dest.end();
|
|
}
|
|
|
|
// when the dest drains, it reduces the awaitDrain counter
|
|
// on the source. This would be more elegant with a .once()
|
|
// handler in flow(), but adding and removing repeatedly is
|
|
// too slow.
|
|
var ondrain = pipeOnDrain(src);
|
|
dest.on('drain', ondrain);
|
|
|
|
function cleanup() {
|
|
debug('cleanup');
|
|
// cleanup event handlers once the pipe is broken
|
|
dest.removeListener('close', onclose);
|
|
dest.removeListener('finish', onfinish);
|
|
dest.removeListener('drain', ondrain);
|
|
dest.removeListener('error', onerror);
|
|
dest.removeListener('unpipe', onunpipe);
|
|
src.removeListener('end', onend);
|
|
src.removeListener('end', cleanup);
|
|
src.removeListener('data', ondata);
|
|
|
|
// if the reader is waiting for a drain event from this
|
|
// specific writer, then it would cause it to never start
|
|
// flowing again.
|
|
// So, if this is awaiting a drain, then we just call it now.
|
|
// If we don't know, then assume that we are waiting for one.
|
|
if (state.awaitDrain &&
|
|
(!dest._writableState || dest._writableState.needDrain))
|
|
ondrain();
|
|
}
|
|
|
|
src.on('data', ondata);
|
|
function ondata(chunk) {
|
|
debug('ondata');
|
|
var ret = dest.write(chunk);
|
|
if (false === ret) {
|
|
debug('false write response, pause',
|
|
src._readableState.awaitDrain);
|
|
src._readableState.awaitDrain++;
|
|
src.pause();
|
|
}
|
|
}
|
|
|
|
// if the dest has an error, then stop piping into it.
|
|
// however, don't suppress the throwing behavior for this.
|
|
function onerror(er) {
|
|
debug('onerror', er);
|
|
unpipe();
|
|
dest.removeListener('error', onerror);
|
|
if (EE.listenerCount(dest, 'error') === 0)
|
|
dest.emit('error', er);
|
|
}
|
|
// This is a brutally ugly hack to make sure that our error handler
|
|
// is attached before any userland ones. NEVER DO THIS.
|
|
if (!dest._events || !dest._events.error)
|
|
dest.on('error', onerror);
|
|
else if (isArray(dest._events.error))
|
|
dest._events.error.unshift(onerror);
|
|
else
|
|
dest._events.error = [onerror, dest._events.error];
|
|
|
|
|
|
|
|
// Both close and finish should trigger unpipe, but only once.
|
|
function onclose() {
|
|
dest.removeListener('finish', onfinish);
|
|
unpipe();
|
|
}
|
|
dest.once('close', onclose);
|
|
function onfinish() {
|
|
debug('onfinish');
|
|
dest.removeListener('close', onclose);
|
|
unpipe();
|
|
}
|
|
dest.once('finish', onfinish);
|
|
|
|
function unpipe() {
|
|
debug('unpipe');
|
|
src.unpipe(dest);
|
|
}
|
|
|
|
// tell the dest that it's being piped to
|
|
dest.emit('pipe', src);
|
|
|
|
// start the flow if it hasn't been started already.
|
|
if (!state.flowing) {
|
|
debug('pipe resume');
|
|
src.resume();
|
|
}
|
|
|
|
return dest;
|
|
};
|
|
|
|
function pipeOnDrain(src) {
|
|
return function() {
|
|
var state = src._readableState;
|
|
debug('pipeOnDrain', state.awaitDrain);
|
|
if (state.awaitDrain)
|
|
state.awaitDrain--;
|
|
if (state.awaitDrain === 0 && EE.listenerCount(src, 'data')) {
|
|
state.flowing = true;
|
|
flow(src);
|
|
}
|
|
};
|
|
}
|
|
|
|
|
|
Readable.prototype.unpipe = function(dest) {
|
|
var state = this._readableState;
|
|
|
|
// if we're not piping anywhere, then do nothing.
|
|
if (state.pipesCount === 0)
|
|
return this;
|
|
|
|
// just one destination. most common case.
|
|
if (state.pipesCount === 1) {
|
|
// passed in one, but it's not the right one.
|
|
if (dest && dest !== state.pipes)
|
|
return this;
|
|
|
|
if (!dest)
|
|
dest = state.pipes;
|
|
|
|
// got a match.
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
if (dest)
|
|
dest.emit('unpipe', this);
|
|
return this;
|
|
}
|
|
|
|
// slow case. multiple pipe destinations.
|
|
|
|
if (!dest) {
|
|
// remove all.
|
|
var dests = state.pipes;
|
|
var len = state.pipesCount;
|
|
state.pipes = null;
|
|
state.pipesCount = 0;
|
|
state.flowing = false;
|
|
|
|
for (var i = 0; i < len; i++)
|
|
dests[i].emit('unpipe', this);
|
|
return this;
|
|
}
|
|
|
|
// try to find the right one.
|
|
var i = indexOf(state.pipes, dest);
|
|
if (i === -1)
|
|
return this;
|
|
|
|
state.pipes.splice(i, 1);
|
|
state.pipesCount -= 1;
|
|
if (state.pipesCount === 1)
|
|
state.pipes = state.pipes[0];
|
|
|
|
dest.emit('unpipe', this);
|
|
|
|
return this;
|
|
};
|
|
|
|
// set up data events if they are asked for
|
|
// Ensure readable listeners eventually get something
|
|
Readable.prototype.on = function(ev, fn) {
|
|
var res = Stream.prototype.on.call(this, ev, fn);
|
|
|
|
// If listening to data, and it has not explicitly been paused,
|
|
// then call resume to start the flow of data on the next tick.
|
|
if (ev === 'data' && false !== this._readableState.flowing) {
|
|
this.resume();
|
|
}
|
|
|
|
if (ev === 'readable' && this.readable) {
|
|
var state = this._readableState;
|
|
if (!state.readableListening) {
|
|
state.readableListening = true;
|
|
state.emittedReadable = false;
|
|
state.needReadable = true;
|
|
if (!state.reading) {
|
|
var self = this;
|
|
process.nextTick(function() {
|
|
debug('readable nexttick read 0');
|
|
self.read(0);
|
|
});
|
|
} else if (state.length) {
|
|
emitReadable(this, state);
|
|
}
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
Readable.prototype.addListener = Readable.prototype.on;
|
|
|
|
// pause() and resume() are remnants of the legacy readable stream API
|
|
// If the user uses them, then switch into old mode.
|
|
Readable.prototype.resume = function() {
|
|
var state = this._readableState;
|
|
if (!state.flowing) {
|
|
debug('resume');
|
|
state.flowing = true;
|
|
if (!state.reading) {
|
|
debug('resume read 0');
|
|
this.read(0);
|
|
}
|
|
resume(this, state);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
function resume(stream, state) {
|
|
if (!state.resumeScheduled) {
|
|
state.resumeScheduled = true;
|
|
process.nextTick(function() {
|
|
resume_(stream, state);
|
|
});
|
|
}
|
|
}
|
|
|
|
function resume_(stream, state) {
|
|
state.resumeScheduled = false;
|
|
stream.emit('resume');
|
|
flow(stream);
|
|
if (state.flowing && !state.reading)
|
|
stream.read(0);
|
|
}
|
|
|
|
Readable.prototype.pause = function() {
|
|
debug('call pause flowing=%j', this._readableState.flowing);
|
|
if (false !== this._readableState.flowing) {
|
|
debug('pause');
|
|
this._readableState.flowing = false;
|
|
this.emit('pause');
|
|
}
|
|
return this;
|
|
};
|
|
|
|
function flow(stream) {
|
|
var state = stream._readableState;
|
|
debug('flow', state.flowing);
|
|
if (state.flowing) {
|
|
do {
|
|
var chunk = stream.read();
|
|
} while (null !== chunk && state.flowing);
|
|
}
|
|
}
|
|
|
|
// wrap an old-style stream as the async data source.
|
|
// This is *not* part of the readable stream interface.
|
|
// It is an ugly unfortunate mess of history.
|
|
Readable.prototype.wrap = function(stream) {
|
|
var state = this._readableState;
|
|
var paused = false;
|
|
|
|
var self = this;
|
|
stream.on('end', function() {
|
|
debug('wrapped end');
|
|
if (state.decoder && !state.ended) {
|
|
var chunk = state.decoder.end();
|
|
if (chunk && chunk.length)
|
|
self.push(chunk);
|
|
}
|
|
|
|
self.push(null);
|
|
});
|
|
|
|
stream.on('data', function(chunk) {
|
|
debug('wrapped data');
|
|
if (state.decoder)
|
|
chunk = state.decoder.write(chunk);
|
|
if (!chunk || !state.objectMode && !chunk.length)
|
|
return;
|
|
|
|
var ret = self.push(chunk);
|
|
if (!ret) {
|
|
paused = true;
|
|
stream.pause();
|
|
}
|
|
});
|
|
|
|
// proxy all the other methods.
|
|
// important when wrapping filters and duplexes.
|
|
for (var i in stream) {
|
|
if (util.isFunction(stream[i]) && util.isUndefined(this[i])) {
|
|
this[i] = function(method) { return function() {
|
|
return stream[method].apply(stream, arguments);
|
|
}}(i);
|
|
}
|
|
}
|
|
|
|
// proxy certain important events.
|
|
var events = ['error', 'close', 'destroy', 'pause', 'resume'];
|
|
forEach(events, function(ev) {
|
|
stream.on(ev, self.emit.bind(self, ev));
|
|
});
|
|
|
|
// when we try to consume some more bytes, simply unpause the
|
|
// underlying stream.
|
|
self._read = function(n) {
|
|
debug('wrapped _read', n);
|
|
if (paused) {
|
|
paused = false;
|
|
stream.resume();
|
|
}
|
|
};
|
|
|
|
return self;
|
|
};
|
|
|
|
|
|
|
|
// exposed for testing purposes only.
|
|
Readable._fromList = fromList;
|
|
|
|
// Pluck off n bytes from an array of buffers.
|
|
// Length is the combined lengths of all the buffers in the list.
|
|
function fromList(n, state) {
|
|
var list = state.buffer;
|
|
var length = state.length;
|
|
var stringMode = !!state.decoder;
|
|
var objectMode = !!state.objectMode;
|
|
var ret;
|
|
|
|
// nothing in the list, definitely empty.
|
|
if (list.length === 0)
|
|
return null;
|
|
|
|
if (length === 0)
|
|
ret = null;
|
|
else if (objectMode)
|
|
ret = list.shift();
|
|
else if (!n || n >= length) {
|
|
// read it all, truncate the array.
|
|
if (stringMode)
|
|
ret = list.join('');
|
|
else
|
|
ret = Buffer.concat(list, length);
|
|
list.length = 0;
|
|
} else {
|
|
// read just some of it.
|
|
if (n < list[0].length) {
|
|
// just take a part of the first list item.
|
|
// slice is the same for buffers and strings.
|
|
var buf = list[0];
|
|
ret = buf.slice(0, n);
|
|
list[0] = buf.slice(n);
|
|
} else if (n === list[0].length) {
|
|
// first list is a perfect match
|
|
ret = list.shift();
|
|
} else {
|
|
// complex case.
|
|
// we have enough to cover it, but it spans past the first buffer.
|
|
if (stringMode)
|
|
ret = '';
|
|
else
|
|
ret = new Buffer(n);
|
|
|
|
var c = 0;
|
|
for (var i = 0, l = list.length; i < l && c < n; i++) {
|
|
var buf = list[0];
|
|
var cpy = Math.min(n - c, buf.length);
|
|
|
|
if (stringMode)
|
|
ret += buf.slice(0, cpy);
|
|
else
|
|
buf.copy(ret, c, 0, cpy);
|
|
|
|
if (cpy < buf.length)
|
|
list[0] = buf.slice(cpy);
|
|
else
|
|
list.shift();
|
|
|
|
c += cpy;
|
|
}
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
function endReadable(stream) {
|
|
var state = stream._readableState;
|
|
|
|
// If we get here before consuming all the bytes, then that is a
|
|
// bug in node. Should never happen.
|
|
if (state.length > 0)
|
|
throw new Error('endReadable called on non-empty stream');
|
|
|
|
if (!state.endEmitted) {
|
|
state.ended = true;
|
|
process.nextTick(function() {
|
|
// Check that we didn't get one last unshift.
|
|
if (!state.endEmitted && state.length === 0) {
|
|
state.endEmitted = true;
|
|
stream.readable = false;
|
|
stream.emit('end');
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
function forEach (xs, f) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
f(xs[i], i);
|
|
}
|
|
}
|
|
|
|
function indexOf (xs, x) {
|
|
for (var i = 0, l = xs.length; i < l; i++) {
|
|
if (xs[i] === x) return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
}).call(this,require('_process'))
|
|
},{"./_stream_duplex":16,"_process":10,"buffer":2,"core-util-is":21,"events":6,"inherits":7,"isarray":9,"stream":26,"string_decoder/":27,"util":1}],19:[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.
|
|
|
|
|
|
// a transform stream is a readable/writable stream where you do
|
|
// something with the data. Sometimes it's called a "filter",
|
|
// but that's not a great name for it, since that implies a thing where
|
|
// some bits pass through, and others are simply ignored. (That would
|
|
// be a valid example of a transform, of course.)
|
|
//
|
|
// While the output is causally related to the input, it's not a
|
|
// necessarily symmetric or synchronous transformation. For example,
|
|
// a zlib stream might take multiple plain-text writes(), and then
|
|
// emit a single compressed chunk some time in the future.
|
|
//
|
|
// Here's how this works:
|
|
//
|
|
// The Transform stream has all the aspects of the readable and writable
|
|
// stream classes. When you write(chunk), that calls _write(chunk,cb)
|
|
// internally, and returns false if there's a lot of pending writes
|
|
// buffered up. When you call read(), that calls _read(n) until
|
|
// there's enough pending readable data buffered up.
|
|
//
|
|
// In a transform stream, the written data is placed in a buffer. When
|
|
// _read(n) is called, it transforms the queued up data, calling the
|
|
// buffered _write cb's as it consumes chunks. If consuming a single
|
|
// written chunk would result in multiple output chunks, then the first
|
|
// outputted bit calls the readcb, and subsequent chunks just go into
|
|
// the read buffer, and will cause it to emit 'readable' if necessary.
|
|
//
|
|
// This way, back-pressure is actually determined by the reading side,
|
|
// since _read has to be called to start processing a new chunk. However,
|
|
// a pathological inflate type of transform can cause excessive buffering
|
|
// here. For example, imagine a stream where every byte of input is
|
|
// interpreted as an integer from 0-255, and then results in that many
|
|
// bytes of output. Writing the 4 bytes {ff,ff,ff,ff} would result in
|
|
// 1kb of data being output. In this case, you could write a very small
|
|
// amount of input, and end up with a very large amount of output. In
|
|
// such a pathological inflating mechanism, there'd be no way to tell
|
|
// the system to stop doing the transform. A single 4MB write could
|
|
// cause the system to run out of memory.
|
|
//
|
|
// However, even in such a pathological case, only a single written chunk
|
|
// would be consumed, and then the rest would wait (un-transformed) until
|
|
// the results of the previous transformed chunk were consumed.
|
|
|
|
module.exports = Transform;
|
|
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
util.inherits(Transform, Duplex);
|
|
|
|
|
|
function TransformState(options, stream) {
|
|
this.afterTransform = function(er, data) {
|
|
return afterTransform(stream, er, data);
|
|
};
|
|
|
|
this.needTransform = false;
|
|
this.transforming = false;
|
|
this.writecb = null;
|
|
this.writechunk = null;
|
|
}
|
|
|
|
function afterTransform(stream, er, data) {
|
|
var ts = stream._transformState;
|
|
ts.transforming = false;
|
|
|
|
var cb = ts.writecb;
|
|
|
|
if (!cb)
|
|
return stream.emit('error', new Error('no writecb in Transform class'));
|
|
|
|
ts.writechunk = null;
|
|
ts.writecb = null;
|
|
|
|
if (!util.isNullOrUndefined(data))
|
|
stream.push(data);
|
|
|
|
if (cb)
|
|
cb(er);
|
|
|
|
var rs = stream._readableState;
|
|
rs.reading = false;
|
|
if (rs.needReadable || rs.length < rs.highWaterMark) {
|
|
stream._read(rs.highWaterMark);
|
|
}
|
|
}
|
|
|
|
|
|
function Transform(options) {
|
|
if (!(this instanceof Transform))
|
|
return new Transform(options);
|
|
|
|
Duplex.call(this, options);
|
|
|
|
this._transformState = new TransformState(options, this);
|
|
|
|
// when the writable side finishes, then flush out anything remaining.
|
|
var stream = this;
|
|
|
|
// start out asking for a readable event once data is transformed.
|
|
this._readableState.needReadable = true;
|
|
|
|
// we have implemented the _read method, and done the other things
|
|
// that Readable wants before the first _read call, so unset the
|
|
// sync guard flag.
|
|
this._readableState.sync = false;
|
|
|
|
this.once('prefinish', function() {
|
|
if (util.isFunction(this._flush))
|
|
this._flush(function(er) {
|
|
done(stream, er);
|
|
});
|
|
else
|
|
done(stream);
|
|
});
|
|
}
|
|
|
|
Transform.prototype.push = function(chunk, encoding) {
|
|
this._transformState.needTransform = false;
|
|
return Duplex.prototype.push.call(this, chunk, encoding);
|
|
};
|
|
|
|
// This is the part where you do stuff!
|
|
// override this function in implementation classes.
|
|
// 'chunk' is an input chunk.
|
|
//
|
|
// Call `push(newChunk)` to pass along transformed output
|
|
// to the readable side. You may call 'push' zero or more times.
|
|
//
|
|
// Call `cb(err)` when you are done with this chunk. If you pass
|
|
// an error, then that'll put the hurt on the whole operation. If you
|
|
// never call cb(), then you'll never get another chunk.
|
|
Transform.prototype._transform = function(chunk, encoding, cb) {
|
|
throw new Error('not implemented');
|
|
};
|
|
|
|
Transform.prototype._write = function(chunk, encoding, cb) {
|
|
var ts = this._transformState;
|
|
ts.writecb = cb;
|
|
ts.writechunk = chunk;
|
|
ts.writeencoding = encoding;
|
|
if (!ts.transforming) {
|
|
var rs = this._readableState;
|
|
if (ts.needTransform ||
|
|
rs.needReadable ||
|
|
rs.length < rs.highWaterMark)
|
|
this._read(rs.highWaterMark);
|
|
}
|
|
};
|
|
|
|
// Doesn't matter what the args are here.
|
|
// _transform does all the work.
|
|
// That we got here means that the readable side wants more data.
|
|
Transform.prototype._read = function(n) {
|
|
var ts = this._transformState;
|
|
|
|
if (!util.isNull(ts.writechunk) && ts.writecb && !ts.transforming) {
|
|
ts.transforming = true;
|
|
this._transform(ts.writechunk, ts.writeencoding, ts.afterTransform);
|
|
} else {
|
|
// mark that we need a transform, so that any data that comes in
|
|
// will get processed, now that we've asked for it.
|
|
ts.needTransform = true;
|
|
}
|
|
};
|
|
|
|
|
|
function done(stream, er) {
|
|
if (er)
|
|
return stream.emit('error', er);
|
|
|
|
// if there's nothing in the write buffer, then that means
|
|
// that nothing more will ever be provided
|
|
var ws = stream._writableState;
|
|
var ts = stream._transformState;
|
|
|
|
if (ws.length)
|
|
throw new Error('calling transform done when ws.length != 0');
|
|
|
|
if (ts.transforming)
|
|
throw new Error('calling transform done when still transforming');
|
|
|
|
return stream.push(null);
|
|
}
|
|
|
|
},{"./_stream_duplex":16,"core-util-is":21,"inherits":7}],20:[function(require,module,exports){
|
|
(function (process){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
// A bit simpler than readable streams.
|
|
// Implement an async ._write(chunk, cb), and it'll handle all
|
|
// the drain event emission and buffering.
|
|
|
|
module.exports = Writable;
|
|
|
|
/*<replacement>*/
|
|
var Buffer = require('buffer').Buffer;
|
|
/*</replacement>*/
|
|
|
|
Writable.WritableState = WritableState;
|
|
|
|
|
|
/*<replacement>*/
|
|
var util = require('core-util-is');
|
|
util.inherits = require('inherits');
|
|
/*</replacement>*/
|
|
|
|
var Stream = require('stream');
|
|
|
|
util.inherits(Writable, Stream);
|
|
|
|
function WriteReq(chunk, encoding, cb) {
|
|
this.chunk = chunk;
|
|
this.encoding = encoding;
|
|
this.callback = cb;
|
|
}
|
|
|
|
function WritableState(options, stream) {
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
options = options || {};
|
|
|
|
// the point at which write() starts returning false
|
|
// Note: 0 is a valid value, means that we always return false if
|
|
// the entire buffer is not flushed immediately on write()
|
|
var hwm = options.highWaterMark;
|
|
var defaultHwm = options.objectMode ? 16 : 16 * 1024;
|
|
this.highWaterMark = (hwm || hwm === 0) ? hwm : defaultHwm;
|
|
|
|
// object stream flag to indicate whether or not this stream
|
|
// contains buffers or objects.
|
|
this.objectMode = !!options.objectMode;
|
|
|
|
if (stream instanceof Duplex)
|
|
this.objectMode = this.objectMode || !!options.writableObjectMode;
|
|
|
|
// cast to ints.
|
|
this.highWaterMark = ~~this.highWaterMark;
|
|
|
|
this.needDrain = false;
|
|
// at the start of calling end()
|
|
this.ending = false;
|
|
// when end() has been called, and returned
|
|
this.ended = false;
|
|
// when 'finish' is emitted
|
|
this.finished = false;
|
|
|
|
// should we decode strings into buffers before passing to _write?
|
|
// this is here so that some node-core streams can optimize string
|
|
// handling at a lower level.
|
|
var noDecode = options.decodeStrings === false;
|
|
this.decodeStrings = !noDecode;
|
|
|
|
// Crypto is kind of old and crusty. Historically, its default string
|
|
// encoding is 'binary' so we have to make this configurable.
|
|
// Everything else in the universe uses 'utf8', though.
|
|
this.defaultEncoding = options.defaultEncoding || 'utf8';
|
|
|
|
// not an actual buffer we keep track of, but a measurement
|
|
// of how much we're waiting to get pushed to some underlying
|
|
// socket or file.
|
|
this.length = 0;
|
|
|
|
// a flag to see when we're in the middle of a write.
|
|
this.writing = false;
|
|
|
|
// when true all writes will be buffered until .uncork() call
|
|
this.corked = 0;
|
|
|
|
// a flag to be able to tell if the onwrite cb is called immediately,
|
|
// or on a later tick. We set this to true at first, because any
|
|
// actions that shouldn't happen until "later" should generally also
|
|
// not happen before the first write call.
|
|
this.sync = true;
|
|
|
|
// a flag to know if we're processing previously buffered items, which
|
|
// may call the _write() callback in the same tick, so that we don't
|
|
// end up in an overlapped onwrite situation.
|
|
this.bufferProcessing = false;
|
|
|
|
// the callback that's passed to _write(chunk,cb)
|
|
this.onwrite = function(er) {
|
|
onwrite(stream, er);
|
|
};
|
|
|
|
// the callback that the user supplies to write(chunk,encoding,cb)
|
|
this.writecb = null;
|
|
|
|
// the amount that is being written when _write is called.
|
|
this.writelen = 0;
|
|
|
|
this.buffer = [];
|
|
|
|
// number of pending user-supplied write callbacks
|
|
// this must be 0 before 'finish' can be emitted
|
|
this.pendingcb = 0;
|
|
|
|
// emit prefinish if the only thing we're waiting for is _write cbs
|
|
// This is relevant for synchronous Transform streams
|
|
this.prefinished = false;
|
|
|
|
// True if the error was already emitted and should not be thrown again
|
|
this.errorEmitted = false;
|
|
}
|
|
|
|
function Writable(options) {
|
|
var Duplex = require('./_stream_duplex');
|
|
|
|
// Writable ctor is applied to Duplexes, though they're not
|
|
// instanceof Writable, they're instanceof Readable.
|
|
if (!(this instanceof Writable) && !(this instanceof Duplex))
|
|
return new Writable(options);
|
|
|
|
this._writableState = new WritableState(options, this);
|
|
|
|
// legacy.
|
|
this.writable = true;
|
|
|
|
Stream.call(this);
|
|
}
|
|
|
|
// Otherwise people can pipe Writable streams, which is just wrong.
|
|
Writable.prototype.pipe = function() {
|
|
this.emit('error', new Error('Cannot pipe. Not readable.'));
|
|
};
|
|
|
|
|
|
function writeAfterEnd(stream, state, cb) {
|
|
var er = new Error('write after end');
|
|
// TODO: defer error events consistently everywhere, not just the cb
|
|
stream.emit('error', er);
|
|
process.nextTick(function() {
|
|
cb(er);
|
|
});
|
|
}
|
|
|
|
// If we get something that is not a buffer, string, null, or undefined,
|
|
// and we're not in objectMode, then that's an error.
|
|
// Otherwise stream chunks are all considered to be of length=1, and the
|
|
// watermarks determine how many objects to keep in the buffer, rather than
|
|
// how many bytes or characters.
|
|
function validChunk(stream, state, chunk, cb) {
|
|
var valid = true;
|
|
if (!util.isBuffer(chunk) &&
|
|
!util.isString(chunk) &&
|
|
!util.isNullOrUndefined(chunk) &&
|
|
!state.objectMode) {
|
|
var er = new TypeError('Invalid non-string/buffer chunk');
|
|
stream.emit('error', er);
|
|
process.nextTick(function() {
|
|
cb(er);
|
|
});
|
|
valid = false;
|
|
}
|
|
return valid;
|
|
}
|
|
|
|
Writable.prototype.write = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
var ret = false;
|
|
|
|
if (util.isFunction(encoding)) {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (util.isBuffer(chunk))
|
|
encoding = 'buffer';
|
|
else if (!encoding)
|
|
encoding = state.defaultEncoding;
|
|
|
|
if (!util.isFunction(cb))
|
|
cb = function() {};
|
|
|
|
if (state.ended)
|
|
writeAfterEnd(this, state, cb);
|
|
else if (validChunk(this, state, chunk, cb)) {
|
|
state.pendingcb++;
|
|
ret = writeOrBuffer(this, state, chunk, encoding, cb);
|
|
}
|
|
|
|
return ret;
|
|
};
|
|
|
|
Writable.prototype.cork = function() {
|
|
var state = this._writableState;
|
|
|
|
state.corked++;
|
|
};
|
|
|
|
Writable.prototype.uncork = function() {
|
|
var state = this._writableState;
|
|
|
|
if (state.corked) {
|
|
state.corked--;
|
|
|
|
if (!state.writing &&
|
|
!state.corked &&
|
|
!state.finished &&
|
|
!state.bufferProcessing &&
|
|
state.buffer.length)
|
|
clearBuffer(this, state);
|
|
}
|
|
};
|
|
|
|
function decodeChunk(state, chunk, encoding) {
|
|
if (!state.objectMode &&
|
|
state.decodeStrings !== false &&
|
|
util.isString(chunk)) {
|
|
chunk = new Buffer(chunk, encoding);
|
|
}
|
|
return chunk;
|
|
}
|
|
|
|
// if we're already writing something, then just put this
|
|
// in the queue, and wait our turn. Otherwise, call _write
|
|
// If we return false, then we need a drain event, so set that flag.
|
|
function writeOrBuffer(stream, state, chunk, encoding, cb) {
|
|
chunk = decodeChunk(state, chunk, encoding);
|
|
if (util.isBuffer(chunk))
|
|
encoding = 'buffer';
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
|
|
state.length += len;
|
|
|
|
var ret = state.length < state.highWaterMark;
|
|
// we must ensure that previous needDrain will not be reset to false.
|
|
if (!ret)
|
|
state.needDrain = true;
|
|
|
|
if (state.writing || state.corked)
|
|
state.buffer.push(new WriteReq(chunk, encoding, cb));
|
|
else
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
|
|
return ret;
|
|
}
|
|
|
|
function doWrite(stream, state, writev, len, chunk, encoding, cb) {
|
|
state.writelen = len;
|
|
state.writecb = cb;
|
|
state.writing = true;
|
|
state.sync = true;
|
|
if (writev)
|
|
stream._writev(chunk, state.onwrite);
|
|
else
|
|
stream._write(chunk, encoding, state.onwrite);
|
|
state.sync = false;
|
|
}
|
|
|
|
function onwriteError(stream, state, sync, er, cb) {
|
|
if (sync)
|
|
process.nextTick(function() {
|
|
state.pendingcb--;
|
|
cb(er);
|
|
});
|
|
else {
|
|
state.pendingcb--;
|
|
cb(er);
|
|
}
|
|
|
|
stream._writableState.errorEmitted = true;
|
|
stream.emit('error', er);
|
|
}
|
|
|
|
function onwriteStateUpdate(state) {
|
|
state.writing = false;
|
|
state.writecb = null;
|
|
state.length -= state.writelen;
|
|
state.writelen = 0;
|
|
}
|
|
|
|
function onwrite(stream, er) {
|
|
var state = stream._writableState;
|
|
var sync = state.sync;
|
|
var cb = state.writecb;
|
|
|
|
onwriteStateUpdate(state);
|
|
|
|
if (er)
|
|
onwriteError(stream, state, sync, er, cb);
|
|
else {
|
|
// Check if we're actually ready to finish, but don't emit yet
|
|
var finished = needFinish(stream, state);
|
|
|
|
if (!finished &&
|
|
!state.corked &&
|
|
!state.bufferProcessing &&
|
|
state.buffer.length) {
|
|
clearBuffer(stream, state);
|
|
}
|
|
|
|
if (sync) {
|
|
process.nextTick(function() {
|
|
afterWrite(stream, state, finished, cb);
|
|
});
|
|
} else {
|
|
afterWrite(stream, state, finished, cb);
|
|
}
|
|
}
|
|
}
|
|
|
|
function afterWrite(stream, state, finished, cb) {
|
|
if (!finished)
|
|
onwriteDrain(stream, state);
|
|
state.pendingcb--;
|
|
cb();
|
|
finishMaybe(stream, state);
|
|
}
|
|
|
|
// Must force callback to be called on nextTick, so that we don't
|
|
// emit 'drain' before the write() consumer gets the 'false' return
|
|
// value, and has a chance to attach a 'drain' listener.
|
|
function onwriteDrain(stream, state) {
|
|
if (state.length === 0 && state.needDrain) {
|
|
state.needDrain = false;
|
|
stream.emit('drain');
|
|
}
|
|
}
|
|
|
|
|
|
// if there's something in the buffer waiting, then process it
|
|
function clearBuffer(stream, state) {
|
|
state.bufferProcessing = true;
|
|
|
|
if (stream._writev && state.buffer.length > 1) {
|
|
// Fast case, write everything using _writev()
|
|
var cbs = [];
|
|
for (var c = 0; c < state.buffer.length; c++)
|
|
cbs.push(state.buffer[c].callback);
|
|
|
|
// count the one we are adding, as well.
|
|
// TODO(isaacs) clean this up
|
|
state.pendingcb++;
|
|
doWrite(stream, state, true, state.length, state.buffer, '', function(err) {
|
|
for (var i = 0; i < cbs.length; i++) {
|
|
state.pendingcb--;
|
|
cbs[i](err);
|
|
}
|
|
});
|
|
|
|
// Clear buffer
|
|
state.buffer = [];
|
|
} else {
|
|
// Slow case, write chunks one-by-one
|
|
for (var c = 0; c < state.buffer.length; c++) {
|
|
var entry = state.buffer[c];
|
|
var chunk = entry.chunk;
|
|
var encoding = entry.encoding;
|
|
var cb = entry.callback;
|
|
var len = state.objectMode ? 1 : chunk.length;
|
|
|
|
doWrite(stream, state, false, len, chunk, encoding, cb);
|
|
|
|
// if we didn't call the onwrite immediately, then
|
|
// it means that we need to wait until it does.
|
|
// also, that means that the chunk and cb are currently
|
|
// being processed, so move the buffer counter past them.
|
|
if (state.writing) {
|
|
c++;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (c < state.buffer.length)
|
|
state.buffer = state.buffer.slice(c);
|
|
else
|
|
state.buffer.length = 0;
|
|
}
|
|
|
|
state.bufferProcessing = false;
|
|
}
|
|
|
|
Writable.prototype._write = function(chunk, encoding, cb) {
|
|
cb(new Error('not implemented'));
|
|
|
|
};
|
|
|
|
Writable.prototype._writev = null;
|
|
|
|
Writable.prototype.end = function(chunk, encoding, cb) {
|
|
var state = this._writableState;
|
|
|
|
if (util.isFunction(chunk)) {
|
|
cb = chunk;
|
|
chunk = null;
|
|
encoding = null;
|
|
} else if (util.isFunction(encoding)) {
|
|
cb = encoding;
|
|
encoding = null;
|
|
}
|
|
|
|
if (!util.isNullOrUndefined(chunk))
|
|
this.write(chunk, encoding);
|
|
|
|
// .end() fully uncorks
|
|
if (state.corked) {
|
|
state.corked = 1;
|
|
this.uncork();
|
|
}
|
|
|
|
// ignore unnecessary end() calls.
|
|
if (!state.ending && !state.finished)
|
|
endWritable(this, state, cb);
|
|
};
|
|
|
|
|
|
function needFinish(stream, state) {
|
|
return (state.ending &&
|
|
state.length === 0 &&
|
|
!state.finished &&
|
|
!state.writing);
|
|
}
|
|
|
|
function prefinish(stream, state) {
|
|
if (!state.prefinished) {
|
|
state.prefinished = true;
|
|
stream.emit('prefinish');
|
|
}
|
|
}
|
|
|
|
function finishMaybe(stream, state) {
|
|
var need = needFinish(stream, state);
|
|
if (need) {
|
|
if (state.pendingcb === 0) {
|
|
prefinish(stream, state);
|
|
state.finished = true;
|
|
stream.emit('finish');
|
|
} else
|
|
prefinish(stream, state);
|
|
}
|
|
return need;
|
|
}
|
|
|
|
function endWritable(stream, state, cb) {
|
|
state.ending = true;
|
|
finishMaybe(stream, state);
|
|
if (cb) {
|
|
if (state.finished)
|
|
process.nextTick(cb);
|
|
else
|
|
stream.once('finish', cb);
|
|
}
|
|
state.ended = true;
|
|
}
|
|
|
|
}).call(this,require('_process'))
|
|
},{"./_stream_duplex":16,"_process":10,"buffer":2,"core-util-is":21,"inherits":7,"stream":26}],21:[function(require,module,exports){
|
|
(function (Buffer){
|
|
// Copyright Joyent, Inc. and other Node contributors.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to permit
|
|
// persons to whom the Software is furnished to do so, subject to the
|
|
// following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included
|
|
// in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
|
|
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
|
|
// USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
// NOTE: These type checking functions intentionally don't use `instanceof`
|
|
// because it is fragile and can be easily faked with `Object.create()`.
|
|
function isArray(ar) {
|
|
return Array.isArray(ar);
|
|
}
|
|
exports.isArray = isArray;
|
|
|
|
function isBoolean(arg) {
|
|
return typeof arg === 'boolean';
|
|
}
|
|
exports.isBoolean = isBoolean;
|
|
|
|
function isNull(arg) {
|
|
return arg === null;
|
|
}
|
|
exports.isNull = isNull;
|
|
|
|
function isNullOrUndefined(arg) {
|
|
return arg == null;
|
|
}
|
|
exports.isNullOrUndefined = isNullOrUndefined;
|
|
|
|
function isNumber(arg) {
|
|
return typeof arg === 'number';
|
|
}
|
|
exports.isNumber = isNumber;
|
|
|
|
function isString(arg) {
|
|
return typeof arg === 'string';
|
|
}
|
|
exports.isString = isString;
|
|
|
|
function isSymbol(arg) {
|
|
return typeof arg === 'symbol';
|
|
}
|
|
exports.isSymbol = isSymbol;
|
|
|
|
function isUndefined(arg) {
|
|
return arg === void 0;
|
|
}
|
|
exports.isUndefined = isUndefined;
|
|
|
|
function isRegExp(re) {
|
|
return isObject(re) && objectToString(re) === '[object RegExp]';
|
|
}
|
|
exports.isRegExp = isRegExp;
|
|
|
|
function isObject(arg) {
|
|
return typeof arg === 'object' && arg !== null;
|
|
}
|
|
exports.isObject = isObject;
|
|
|
|
function isDate(d) {
|
|
return isObject(d) && objectToString(d) === '[object Date]';
|
|
}
|
|
exports.isDate = isDate;
|
|
|
|
function isError(e) {
|
|
return isObject(e) &&
|
|
(objectToString(e) === '[object Error]' || e instanceof Error);
|
|
}
|
|
exports.isError = isError;
|
|
|
|
function isFunction(arg) {
|
|
return typeof arg === 'function';
|
|
}
|
|
exports.isFunction = isFunction;
|
|
|
|
function isPrimitive(arg) {
|
|
return arg === null ||
|
|
typeof arg === 'boolean' ||
|
|
typeof arg === 'number' ||
|
|
typeof arg === 'string' ||
|
|
typeof arg === 'symbol' || // ES6 symbol
|
|
typeof arg === 'undefined';
|
|
}
|
|
exports.isPrimitive = isPrimitive;
|
|
|
|
function isBuffer(arg) {
|
|
return Buffer.isBuffer(arg);
|
|
}
|
|
exports.isBuffer = isBuffer;
|
|
|
|
function objectToString(o) {
|
|
return Object.prototype.toString.call(o);
|
|
}
|
|
}).call(this,{"isBuffer":require("../../../../insert-module-globals/node_modules/is-buffer/index.js")})
|
|
},{"../../../../insert-module-globals/node_modules/is-buffer/index.js":8}],22:[function(require,module,exports){
|
|
module.exports = require("./lib/_stream_passthrough.js")
|
|
|
|
},{"./lib/_stream_passthrough.js":17}],23:[function(require,module,exports){
|
|
exports = module.exports = require('./lib/_stream_readable.js');
|
|
exports.Stream = require('stream');
|
|
exports.Readable = exports;
|
|
exports.Writable = require('./lib/_stream_writable.js');
|
|
exports.Duplex = require('./lib/_stream_duplex.js');
|
|
exports.Transform = require('./lib/_stream_transform.js');
|
|
exports.PassThrough = require('./lib/_stream_passthrough.js');
|
|
|
|
},{"./lib/_stream_duplex.js":16,"./lib/_stream_passthrough.js":17,"./lib/_stream_readable.js":18,"./lib/_stream_transform.js":19,"./lib/_stream_writable.js":20,"stream":26}],24:[function(require,module,exports){
|
|
module.exports = require("./lib/_stream_transform.js")
|
|
|
|
},{"./lib/_stream_transform.js":19}],25:[function(require,module,exports){
|
|
module.exports = require("./lib/_stream_writable.js")
|
|
|
|
},{"./lib/_stream_writable.js":20}],26:[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.
|
|
|
|
module.exports = Stream;
|
|
|
|
var EE = require('events').EventEmitter;
|
|
var inherits = require('inherits');
|
|
|
|
inherits(Stream, EE);
|
|
Stream.Readable = require('readable-stream/readable.js');
|
|
Stream.Writable = require('readable-stream/writable.js');
|
|
Stream.Duplex = require('readable-stream/duplex.js');
|
|
Stream.Transform = require('readable-stream/transform.js');
|
|
Stream.PassThrough = require('readable-stream/passthrough.js');
|
|
|
|
// Backwards-compat with node 0.4.x
|
|
Stream.Stream = Stream;
|
|
|
|
|
|
|
|
// old-style streams. Note that the pipe method (the only relevant
|
|
// part of this class) is overridden in the Readable class.
|
|
|
|
function Stream() {
|
|
EE.call(this);
|
|
}
|
|
|
|
Stream.prototype.pipe = function(dest, options) {
|
|
var source = this;
|
|
|
|
function ondata(chunk) {
|
|
if (dest.writable) {
|
|
if (false === dest.write(chunk) && source.pause) {
|
|
source.pause();
|
|
}
|
|
}
|
|
}
|
|
|
|
source.on('data', ondata);
|
|
|
|
function ondrain() {
|
|
if (source.readable && source.resume) {
|
|
source.resume();
|
|
}
|
|
}
|
|
|
|
dest.on('drain', ondrain);
|
|
|
|
// If the 'end' option is not supplied, dest.end() will be called when
|
|
// source gets the 'end' or 'close' events. Only dest.end() once.
|
|
if (!dest._isStdio && (!options || options.end !== false)) {
|
|
source.on('end', onend);
|
|
source.on('close', onclose);
|
|
}
|
|
|
|
var didOnEnd = false;
|
|
function onend() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
dest.end();
|
|
}
|
|
|
|
|
|
function onclose() {
|
|
if (didOnEnd) return;
|
|
didOnEnd = true;
|
|
|
|
if (typeof dest.destroy === 'function') dest.destroy();
|
|
}
|
|
|
|
// don't leave dangling pipes when there are errors.
|
|
function onerror(er) {
|
|
cleanup();
|
|
if (EE.listenerCount(this, 'error') === 0) {
|
|
throw er; // Unhandled stream error in pipe.
|
|
}
|
|
}
|
|
|
|
source.on('error', onerror);
|
|
dest.on('error', onerror);
|
|
|
|
// remove all the event listeners that were added.
|
|
function cleanup() {
|
|
source.removeListener('data', ondata);
|
|
dest.removeListener('drain', ondrain);
|
|
|
|
source.removeListener('end', onend);
|
|
source.removeListener('close', onclose);
|
|
|
|
source.removeListener('error', onerror);
|
|
dest.removeListener('error', onerror);
|
|
|
|
source.removeListener('end', cleanup);
|
|
source.removeListener('close', cleanup);
|
|
|
|
dest.removeListener('close', cleanup);
|
|
}
|
|
|
|
source.on('end', cleanup);
|
|
source.on('close', cleanup);
|
|
|
|
dest.on('close', cleanup);
|
|
|
|
dest.emit('pipe', source);
|
|
|
|
// Allow for unix-like usage: A.pipe(B).pipe(C)
|
|
return dest;
|
|
};
|
|
|
|
},{"events":6,"inherits":7,"readable-stream/duplex.js":15,"readable-stream/passthrough.js":22,"readable-stream/readable.js":23,"readable-stream/transform.js":24,"readable-stream/writable.js":25}],27:[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 Buffer = require('buffer').Buffer;
|
|
|
|
var isBufferEncoding = Buffer.isEncoding
|
|
|| function(encoding) {
|
|
switch (encoding && encoding.toLowerCase()) {
|
|
case 'hex': case 'utf8': case 'utf-8': case 'ascii': case 'binary': case 'base64': case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': case 'raw': return true;
|
|
default: return false;
|
|
}
|
|
}
|
|
|
|
|
|
function assertEncoding(encoding) {
|
|
if (encoding && !isBufferEncoding(encoding)) {
|
|
throw new Error('Unknown encoding: ' + encoding);
|
|
}
|
|
}
|
|
|
|
// StringDecoder provides an interface for efficiently splitting a series of
|
|
// buffers into a series of JS strings without breaking apart multi-byte
|
|
// characters. CESU-8 is handled as part of the UTF-8 encoding.
|
|
//
|
|
// @TODO Handling all encodings inside a single object makes it very difficult
|
|
// to reason about this code, so it should be split up in the future.
|
|
// @TODO There should be a utf8-strict encoding that rejects invalid UTF-8 code
|
|
// points as used by CESU-8.
|
|
var StringDecoder = exports.StringDecoder = function(encoding) {
|
|
this.encoding = (encoding || 'utf8').toLowerCase().replace(/[-_]/, '');
|
|
assertEncoding(encoding);
|
|
switch (this.encoding) {
|
|
case 'utf8':
|
|
// CESU-8 represents each of Surrogate Pair by 3-bytes
|
|
this.surrogateSize = 3;
|
|
break;
|
|
case 'ucs2':
|
|
case 'utf16le':
|
|
// UTF-16 represents each of Surrogate Pair by 2-bytes
|
|
this.surrogateSize = 2;
|
|
this.detectIncompleteChar = utf16DetectIncompleteChar;
|
|
break;
|
|
case 'base64':
|
|
// Base-64 stores 3 bytes in 4 chars, and pads the remainder.
|
|
this.surrogateSize = 3;
|
|
this.detectIncompleteChar = base64DetectIncompleteChar;
|
|
break;
|
|
default:
|
|
this.write = passThroughWrite;
|
|
return;
|
|
}
|
|
|
|
// Enough space to store all bytes of a single character. UTF-8 needs 4
|
|
// bytes, but CESU-8 may require up to 6 (3 bytes per surrogate).
|
|
this.charBuffer = new Buffer(6);
|
|
// Number of bytes received for the current incomplete multi-byte character.
|
|
this.charReceived = 0;
|
|
// Number of bytes expected for the current incomplete multi-byte character.
|
|
this.charLength = 0;
|
|
};
|
|
|
|
|
|
// write decodes the given buffer and returns it as JS string that is
|
|
// guaranteed to not contain any partial multi-byte characters. Any partial
|
|
// character found at the end of the buffer is buffered up, and will be
|
|
// returned when calling write again with the remaining bytes.
|
|
//
|
|
// Note: Converting a Buffer containing an orphan surrogate to a String
|
|
// currently works, but converting a String to a Buffer (via `new Buffer`, or
|
|
// Buffer#write) will replace incomplete surrogates with the unicode
|
|
// replacement character. See https://codereview.chromium.org/121173009/ .
|
|
StringDecoder.prototype.write = function(buffer) {
|
|
var charStr = '';
|
|
// if our last write ended with an incomplete multibyte character
|
|
while (this.charLength) {
|
|
// determine how many remaining bytes this buffer has to offer for this char
|
|
var available = (buffer.length >= this.charLength - this.charReceived) ?
|
|
this.charLength - this.charReceived :
|
|
buffer.length;
|
|
|
|
// add the new bytes to the char buffer
|
|
buffer.copy(this.charBuffer, this.charReceived, 0, available);
|
|
this.charReceived += available;
|
|
|
|
if (this.charReceived < this.charLength) {
|
|
// still not enough chars in this buffer? wait for more ...
|
|
return '';
|
|
}
|
|
|
|
// remove bytes belonging to the current character from the buffer
|
|
buffer = buffer.slice(available, buffer.length);
|
|
|
|
// get the character that was split
|
|
charStr = this.charBuffer.slice(0, this.charLength).toString(this.encoding);
|
|
|
|
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
var charCode = charStr.charCodeAt(charStr.length - 1);
|
|
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
this.charLength += this.surrogateSize;
|
|
charStr = '';
|
|
continue;
|
|
}
|
|
this.charReceived = this.charLength = 0;
|
|
|
|
// if there are no more bytes in this buffer, just emit our char
|
|
if (buffer.length === 0) {
|
|
return charStr;
|
|
}
|
|
break;
|
|
}
|
|
|
|
// determine and set charLength / charReceived
|
|
this.detectIncompleteChar(buffer);
|
|
|
|
var end = buffer.length;
|
|
if (this.charLength) {
|
|
// buffer the incomplete character bytes we got
|
|
buffer.copy(this.charBuffer, 0, buffer.length - this.charReceived, end);
|
|
end -= this.charReceived;
|
|
}
|
|
|
|
charStr += buffer.toString(this.encoding, 0, end);
|
|
|
|
var end = charStr.length - 1;
|
|
var charCode = charStr.charCodeAt(end);
|
|
// CESU-8: lead surrogate (D800-DBFF) is also the incomplete character
|
|
if (charCode >= 0xD800 && charCode <= 0xDBFF) {
|
|
var size = this.surrogateSize;
|
|
this.charLength += size;
|
|
this.charReceived += size;
|
|
this.charBuffer.copy(this.charBuffer, size, 0, size);
|
|
buffer.copy(this.charBuffer, 0, 0, size);
|
|
return charStr.substring(0, end);
|
|
}
|
|
|
|
// or just emit the charStr
|
|
return charStr;
|
|
};
|
|
|
|
// detectIncompleteChar determines if there is an incomplete UTF-8 character at
|
|
// the end of the given buffer. If so, it sets this.charLength to the byte
|
|
// length that character, and sets this.charReceived to the number of bytes
|
|
// that are available for this character.
|
|
StringDecoder.prototype.detectIncompleteChar = function(buffer) {
|
|
// determine how many bytes we have to check at the end of this buffer
|
|
var i = (buffer.length >= 3) ? 3 : buffer.length;
|
|
|
|
// Figure out if one of the last i bytes of our buffer announces an
|
|
// incomplete char.
|
|
for (; i > 0; i--) {
|
|
var c = buffer[buffer.length - i];
|
|
|
|
// See http://en.wikipedia.org/wiki/UTF-8#Description
|
|
|
|
// 110XXXXX
|
|
if (i == 1 && c >> 5 == 0x06) {
|
|
this.charLength = 2;
|
|
break;
|
|
}
|
|
|
|
// 1110XXXX
|
|
if (i <= 2 && c >> 4 == 0x0E) {
|
|
this.charLength = 3;
|
|
break;
|
|
}
|
|
|
|
// 11110XXX
|
|
if (i <= 3 && c >> 3 == 0x1E) {
|
|
this.charLength = 4;
|
|
break;
|
|
}
|
|
}
|
|
this.charReceived = i;
|
|
};
|
|
|
|
StringDecoder.prototype.end = function(buffer) {
|
|
var res = '';
|
|
if (buffer && buffer.length)
|
|
res = this.write(buffer);
|
|
|
|
if (this.charReceived) {
|
|
var cr = this.charReceived;
|
|
var buf = this.charBuffer;
|
|
var enc = this.encoding;
|
|
res += buf.slice(0, cr).toString(enc);
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
function passThroughWrite(buffer) {
|
|
return buffer.toString(this.encoding);
|
|
}
|
|
|
|
function utf16DetectIncompleteChar(buffer) {
|
|
this.charReceived = buffer.length % 2;
|
|
this.charLength = this.charReceived ? 2 : 0;
|
|
}
|
|
|
|
function base64DetectIncompleteChar(buffer) {
|
|
this.charReceived = buffer.length % 3;
|
|
this.charLength = this.charReceived ? 3 : 0;
|
|
}
|
|
|
|
},{"buffer":2}],28:[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":11,"querystring":14}],29:[function(require,module,exports){
|
|
var dnode = require('./lib/dnode');
|
|
|
|
module.exports = function (cons, opts) {
|
|
return new dnode(cons, opts);
|
|
};
|
|
|
|
},{"./lib/dnode":30}],30:[function(require,module,exports){
|
|
(function (process){
|
|
var protocol = require('dnode-protocol');
|
|
var Stream = require('stream');
|
|
var json = typeof JSON === 'object' ? JSON : require('jsonify');
|
|
|
|
module.exports = dnode;
|
|
dnode.prototype = {};
|
|
(function () { // browsers etc
|
|
for (var key in Stream.prototype) {
|
|
dnode.prototype[key] = Stream.prototype[key];
|
|
}
|
|
})();
|
|
|
|
function dnode (cons, opts) {
|
|
Stream.call(this);
|
|
var self = this;
|
|
|
|
self.opts = opts || {};
|
|
|
|
self.cons = typeof cons === 'function'
|
|
? cons
|
|
: function () { return cons || {} }
|
|
;
|
|
|
|
self.readable = true;
|
|
self.writable = true;
|
|
|
|
process.nextTick(function () {
|
|
if (self._ended) return;
|
|
self.proto = self._createProto();
|
|
self.proto.start();
|
|
|
|
if (!self._handleQueue) return;
|
|
for (var i = 0; i < self._handleQueue.length; i++) {
|
|
self.handle(self._handleQueue[i]);
|
|
}
|
|
});
|
|
}
|
|
|
|
dnode.prototype._createProto = function () {
|
|
var self = this;
|
|
var proto = protocol(function (remote) {
|
|
if (self._ended) return;
|
|
|
|
var ref = self.cons.call(this, remote, self);
|
|
if (typeof ref !== 'object') ref = this;
|
|
|
|
self.emit('local', ref, self);
|
|
|
|
return ref;
|
|
}, self.opts.proto);
|
|
|
|
proto.on('remote', function (remote) {
|
|
self.emit('remote', remote, self);
|
|
self.emit('ready'); // backwards compatability, deprecated
|
|
});
|
|
|
|
proto.on('request', function (req) {
|
|
if (!self.readable) return;
|
|
|
|
if (self.opts.emit === 'object') {
|
|
self.emit('data', req);
|
|
}
|
|
else self.emit('data', json.stringify(req) + '\n');
|
|
});
|
|
|
|
proto.on('fail', function (err) {
|
|
// errors that the remote end was responsible for
|
|
self.emit('fail', err);
|
|
});
|
|
|
|
proto.on('error', function (err) {
|
|
// errors that the local code was responsible for
|
|
self.emit('error', err);
|
|
});
|
|
|
|
return proto;
|
|
};
|
|
|
|
dnode.prototype.write = function (buf) {
|
|
if (this._ended) return;
|
|
var self = this;
|
|
var row;
|
|
|
|
if (buf && typeof buf === 'object'
|
|
&& buf.constructor && buf.constructor.name === 'Buffer'
|
|
&& buf.length
|
|
&& typeof buf.slice === 'function') {
|
|
// treat like a buffer
|
|
if (!self._bufs) self._bufs = [];
|
|
|
|
// treat like a buffer
|
|
for (var i = 0, j = 0; i < buf.length; i++) {
|
|
if (buf[i] === 0x0a) {
|
|
self._bufs.push(buf.slice(j, i));
|
|
|
|
var line = '';
|
|
for (var k = 0; k < self._bufs.length; k++) {
|
|
line += String(self._bufs[k]);
|
|
}
|
|
|
|
try { row = json.parse(line) }
|
|
catch (err) { return self.end() }
|
|
|
|
j = i + 1;
|
|
|
|
self.handle(row);
|
|
self._bufs = [];
|
|
}
|
|
}
|
|
|
|
if (j < buf.length) self._bufs.push(buf.slice(j, buf.length));
|
|
}
|
|
else if (buf && typeof buf === 'object') {
|
|
// .isBuffer() without the Buffer
|
|
// Use self to pipe JSONStream.parse() streams.
|
|
self.handle(buf);
|
|
}
|
|
else {
|
|
if (typeof buf !== 'string') buf = String(buf);
|
|
if (!self._line) self._line = '';
|
|
|
|
for (var i = 0; i < buf.length; i++) {
|
|
if (buf.charCodeAt(i) === 0x0a) {
|
|
try { row = json.parse(self._line) }
|
|
catch (err) { return self.end() }
|
|
|
|
self._line = '';
|
|
self.handle(row);
|
|
}
|
|
else self._line += buf.charAt(i)
|
|
}
|
|
}
|
|
};
|
|
|
|
dnode.prototype.handle = function (row) {
|
|
if (!this.proto) {
|
|
if (!this._handleQueue) this._handleQueue = [];
|
|
this._handleQueue.push(row);
|
|
}
|
|
else this.proto.handle(row);
|
|
};
|
|
|
|
dnode.prototype.end = function () {
|
|
if (this._ended) return;
|
|
this._ended = true;
|
|
this.writable = false;
|
|
this.readable = false;
|
|
this.emit('end');
|
|
};
|
|
|
|
dnode.prototype.destroy = function () {
|
|
this.end();
|
|
};
|
|
|
|
}).call(this,require('_process'))
|
|
},{"_process":10,"dnode-protocol":31,"jsonify":36,"stream":26}],31:[function(require,module,exports){
|
|
var EventEmitter = require('events').EventEmitter;
|
|
var scrubber = require('./lib/scrub');
|
|
var objectKeys = require('./lib/keys');
|
|
var forEach = require('./lib/foreach');
|
|
var isEnumerable = require('./lib/is_enum');
|
|
|
|
module.exports = function (cons, opts) {
|
|
return new Proto(cons, opts);
|
|
};
|
|
|
|
(function () { // browsers bleh
|
|
for (var key in EventEmitter.prototype) {
|
|
Proto.prototype[key] = EventEmitter.prototype[key];
|
|
}
|
|
})();
|
|
|
|
function Proto (cons, opts) {
|
|
var self = this;
|
|
EventEmitter.call(self);
|
|
if (!opts) opts = {};
|
|
|
|
self.remote = {};
|
|
self.callbacks = { local : [], remote : [] };
|
|
self.wrap = opts.wrap;
|
|
self.unwrap = opts.unwrap;
|
|
|
|
self.scrubber = scrubber(self.callbacks.local);
|
|
|
|
if (typeof cons === 'function') {
|
|
self.instance = new cons(self.remote, self);
|
|
}
|
|
else self.instance = cons || {};
|
|
}
|
|
|
|
Proto.prototype.start = function () {
|
|
this.request('methods', [ this.instance ]);
|
|
};
|
|
|
|
Proto.prototype.cull = function (id) {
|
|
delete this.callbacks.remote[id];
|
|
this.emit('request', {
|
|
method : 'cull',
|
|
arguments : [ id ]
|
|
});
|
|
};
|
|
|
|
Proto.prototype.request = function (method, args) {
|
|
var scrub = this.scrubber.scrub(args);
|
|
|
|
this.emit('request', {
|
|
method : method,
|
|
arguments : scrub.arguments,
|
|
callbacks : scrub.callbacks,
|
|
links : scrub.links
|
|
});
|
|
};
|
|
|
|
Proto.prototype.handle = function (req) {
|
|
var self = this;
|
|
var args = self.scrubber.unscrub(req, function (id) {
|
|
if (self.callbacks.remote[id] === undefined) {
|
|
// create a new function only if one hasn't already been created
|
|
// for a particular id
|
|
var cb = function () {
|
|
self.request(id, [].slice.apply(arguments));
|
|
};
|
|
self.callbacks.remote[id] = self.wrap ? self.wrap(cb, id) : cb;
|
|
return cb;
|
|
}
|
|
return self.unwrap
|
|
? self.unwrap(self.callbacks.remote[id], id)
|
|
: self.callbacks.remote[id]
|
|
;
|
|
});
|
|
|
|
if (req.method === 'methods') {
|
|
self.handleMethods(args[0]);
|
|
}
|
|
else if (req.method === 'cull') {
|
|
forEach(args, function (id) {
|
|
delete self.callbacks.local[id];
|
|
});
|
|
}
|
|
else if (typeof req.method === 'string') {
|
|
if (isEnumerable(self.instance, req.method)) {
|
|
self.apply(self.instance[req.method], args);
|
|
}
|
|
else {
|
|
self.emit('fail', new Error(
|
|
'request for non-enumerable method: ' + req.method
|
|
));
|
|
}
|
|
}
|
|
else if (typeof req.method == 'number') {
|
|
var fn = self.callbacks.local[req.method];
|
|
if (!fn) {
|
|
self.emit('fail', new Error('no such method'));
|
|
}
|
|
else self.apply(fn, args);
|
|
}
|
|
};
|
|
|
|
Proto.prototype.handleMethods = function (methods) {
|
|
var self = this;
|
|
if (typeof methods != 'object') {
|
|
methods = {};
|
|
}
|
|
|
|
// copy since assignment discards the previous refs
|
|
forEach(objectKeys(self.remote), function (key) {
|
|
delete self.remote[key];
|
|
});
|
|
|
|
forEach(objectKeys(methods), function (key) {
|
|
self.remote[key] = methods[key];
|
|
});
|
|
|
|
self.emit('remote', self.remote);
|
|
self.emit('ready');
|
|
};
|
|
|
|
Proto.prototype.apply = function (f, args) {
|
|
try { f.apply(undefined, args) }
|
|
catch (err) { this.emit('error', err) }
|
|
};
|
|
|
|
},{"./lib/foreach":32,"./lib/is_enum":33,"./lib/keys":34,"./lib/scrub":35,"events":6}],32:[function(require,module,exports){
|
|
module.exports = function forEach (xs, f) {
|
|
if (xs.forEach) return xs.forEach(f)
|
|
for (var i = 0; i < xs.length; i++) {
|
|
f.call(xs, xs[i], i);
|
|
}
|
|
}
|
|
|
|
},{}],33:[function(require,module,exports){
|
|
var objectKeys = require('./keys');
|
|
|
|
module.exports = function (obj, key) {
|
|
if (Object.prototype.propertyIsEnumerable) {
|
|
return Object.prototype.propertyIsEnumerable.call(obj, key);
|
|
}
|
|
var keys = objectKeys(obj);
|
|
for (var i = 0; i < keys.length; i++) {
|
|
if (key === keys[i]) return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
},{"./keys":34}],34:[function(require,module,exports){
|
|
module.exports = Object.keys || function (obj) {
|
|
var keys = [];
|
|
for (var key in obj) keys.push(key);
|
|
return keys;
|
|
};
|
|
|
|
},{}],35:[function(require,module,exports){
|
|
var traverse = require('traverse');
|
|
var objectKeys = require('./keys');
|
|
var forEach = require('./foreach');
|
|
|
|
function indexOf (xs, x) {
|
|
if (xs.indexOf) return xs.indexOf(x);
|
|
for (var i = 0; i < xs.length; i++) if (xs[i] === x) return i;
|
|
return -1;
|
|
}
|
|
|
|
// scrub callbacks out of requests in order to call them again later
|
|
module.exports = function (callbacks) {
|
|
return new Scrubber(callbacks);
|
|
};
|
|
|
|
function Scrubber (callbacks) {
|
|
this.callbacks = callbacks;
|
|
}
|
|
|
|
// Take the functions out and note them for future use
|
|
Scrubber.prototype.scrub = function (obj) {
|
|
var self = this;
|
|
var paths = {};
|
|
var links = [];
|
|
|
|
var args = traverse(obj).map(function (node) {
|
|
if (typeof node === 'function') {
|
|
var i = indexOf(self.callbacks, node);
|
|
if (i >= 0 && !(i in paths)) {
|
|
// Keep previous function IDs only for the first function
|
|
// found. This is somewhat suboptimal but the alternatives
|
|
// are worse.
|
|
paths[i] = this.path;
|
|
}
|
|
else {
|
|
var id = self.callbacks.length;
|
|
self.callbacks.push(node);
|
|
paths[id] = this.path;
|
|
}
|
|
|
|
this.update('[Function]');
|
|
}
|
|
else if (this.circular) {
|
|
links.push({ from : this.circular.path, to : this.path });
|
|
this.update('[Circular]');
|
|
}
|
|
});
|
|
|
|
return {
|
|
arguments : args,
|
|
callbacks : paths,
|
|
links : links
|
|
};
|
|
};
|
|
|
|
// Replace callbacks. The supplied function should take a callback id and
|
|
// return a callback of its own.
|
|
Scrubber.prototype.unscrub = function (msg, f) {
|
|
var args = msg.arguments || [];
|
|
forEach(objectKeys(msg.callbacks || {}), function (sid) {
|
|
var id = parseInt(sid, 10);
|
|
var path = msg.callbacks[id];
|
|
traverse.set(args, path, f(id));
|
|
});
|
|
|
|
forEach(msg.links || [], function (link) {
|
|
var value = traverse.get(args, link.from);
|
|
traverse.set(args, link.to, value);
|
|
});
|
|
|
|
return args;
|
|
};
|
|
|
|
},{"./foreach":32,"./keys":34,"traverse":41}],36:[function(require,module,exports){
|
|
exports.parse = require('./lib/parse');
|
|
exports.stringify = require('./lib/stringify');
|
|
|
|
},{"./lib/parse":37,"./lib/stringify":38}],37:[function(require,module,exports){
|
|
var at, // The index of the current character
|
|
ch, // The current character
|
|
escapee = {
|
|
'"': '"',
|
|
'\\': '\\',
|
|
'/': '/',
|
|
b: '\b',
|
|
f: '\f',
|
|
n: '\n',
|
|
r: '\r',
|
|
t: '\t'
|
|
},
|
|
text,
|
|
|
|
error = function (m) {
|
|
// Call error when something is wrong.
|
|
throw {
|
|
name: 'SyntaxError',
|
|
message: m,
|
|
at: at,
|
|
text: text
|
|
};
|
|
},
|
|
|
|
next = function (c) {
|
|
// If a c parameter is provided, verify that it matches the current character.
|
|
if (c && c !== ch) {
|
|
error("Expected '" + c + "' instead of '" + ch + "'");
|
|
}
|
|
|
|
// Get the next character. When there are no more characters,
|
|
// return the empty string.
|
|
|
|
ch = text.charAt(at);
|
|
at += 1;
|
|
return ch;
|
|
},
|
|
|
|
number = function () {
|
|
// Parse a number value.
|
|
var number,
|
|
string = '';
|
|
|
|
if (ch === '-') {
|
|
string = '-';
|
|
next('-');
|
|
}
|
|
while (ch >= '0' && ch <= '9') {
|
|
string += ch;
|
|
next();
|
|
}
|
|
if (ch === '.') {
|
|
string += '.';
|
|
while (next() && ch >= '0' && ch <= '9') {
|
|
string += ch;
|
|
}
|
|
}
|
|
if (ch === 'e' || ch === 'E') {
|
|
string += ch;
|
|
next();
|
|
if (ch === '-' || ch === '+') {
|
|
string += ch;
|
|
next();
|
|
}
|
|
while (ch >= '0' && ch <= '9') {
|
|
string += ch;
|
|
next();
|
|
}
|
|
}
|
|
number = +string;
|
|
if (!isFinite(number)) {
|
|
error("Bad number");
|
|
} else {
|
|
return number;
|
|
}
|
|
},
|
|
|
|
string = function () {
|
|
// Parse a string value.
|
|
var hex,
|
|
i,
|
|
string = '',
|
|
uffff;
|
|
|
|
// When parsing for string values, we must look for " and \ characters.
|
|
if (ch === '"') {
|
|
while (next()) {
|
|
if (ch === '"') {
|
|
next();
|
|
return string;
|
|
} else if (ch === '\\') {
|
|
next();
|
|
if (ch === 'u') {
|
|
uffff = 0;
|
|
for (i = 0; i < 4; i += 1) {
|
|
hex = parseInt(next(), 16);
|
|
if (!isFinite(hex)) {
|
|
break;
|
|
}
|
|
uffff = uffff * 16 + hex;
|
|
}
|
|
string += String.fromCharCode(uffff);
|
|
} else if (typeof escapee[ch] === 'string') {
|
|
string += escapee[ch];
|
|
} else {
|
|
break;
|
|
}
|
|
} else {
|
|
string += ch;
|
|
}
|
|
}
|
|
}
|
|
error("Bad string");
|
|
},
|
|
|
|
white = function () {
|
|
|
|
// Skip whitespace.
|
|
|
|
while (ch && ch <= ' ') {
|
|
next();
|
|
}
|
|
},
|
|
|
|
word = function () {
|
|
|
|
// true, false, or null.
|
|
|
|
switch (ch) {
|
|
case 't':
|
|
next('t');
|
|
next('r');
|
|
next('u');
|
|
next('e');
|
|
return true;
|
|
case 'f':
|
|
next('f');
|
|
next('a');
|
|
next('l');
|
|
next('s');
|
|
next('e');
|
|
return false;
|
|
case 'n':
|
|
next('n');
|
|
next('u');
|
|
next('l');
|
|
next('l');
|
|
return null;
|
|
}
|
|
error("Unexpected '" + ch + "'");
|
|
},
|
|
|
|
value, // Place holder for the value function.
|
|
|
|
array = function () {
|
|
|
|
// Parse an array value.
|
|
|
|
var array = [];
|
|
|
|
if (ch === '[') {
|
|
next('[');
|
|
white();
|
|
if (ch === ']') {
|
|
next(']');
|
|
return array; // empty array
|
|
}
|
|
while (ch) {
|
|
array.push(value());
|
|
white();
|
|
if (ch === ']') {
|
|
next(']');
|
|
return array;
|
|
}
|
|
next(',');
|
|
white();
|
|
}
|
|
}
|
|
error("Bad array");
|
|
},
|
|
|
|
object = function () {
|
|
|
|
// Parse an object value.
|
|
|
|
var key,
|
|
object = {};
|
|
|
|
if (ch === '{') {
|
|
next('{');
|
|
white();
|
|
if (ch === '}') {
|
|
next('}');
|
|
return object; // empty object
|
|
}
|
|
while (ch) {
|
|
key = string();
|
|
white();
|
|
next(':');
|
|
if (Object.hasOwnProperty.call(object, key)) {
|
|
error('Duplicate key "' + key + '"');
|
|
}
|
|
object[key] = value();
|
|
white();
|
|
if (ch === '}') {
|
|
next('}');
|
|
return object;
|
|
}
|
|
next(',');
|
|
white();
|
|
}
|
|
}
|
|
error("Bad object");
|
|
};
|
|
|
|
value = function () {
|
|
|
|
// Parse a JSON value. It could be an object, an array, a string, a number,
|
|
// or a word.
|
|
|
|
white();
|
|
switch (ch) {
|
|
case '{':
|
|
return object();
|
|
case '[':
|
|
return array();
|
|
case '"':
|
|
return string();
|
|
case '-':
|
|
return number();
|
|
default:
|
|
return ch >= '0' && ch <= '9' ? number() : word();
|
|
}
|
|
};
|
|
|
|
// Return the json_parse function. It will have access to all of the above
|
|
// functions and variables.
|
|
|
|
module.exports = function (source, reviver) {
|
|
var result;
|
|
|
|
text = source;
|
|
at = 0;
|
|
ch = ' ';
|
|
result = value();
|
|
white();
|
|
if (ch) {
|
|
error("Syntax error");
|
|
}
|
|
|
|
// If there is a reviver function, we recursively walk the new structure,
|
|
// passing each name/value pair to the reviver function for possible
|
|
// transformation, starting with a temporary root object that holds the result
|
|
// in an empty key. If there is not a reviver function, we simply return the
|
|
// result.
|
|
|
|
return typeof reviver === 'function' ? (function walk(holder, key) {
|
|
var k, v, value = holder[key];
|
|
if (value && typeof value === 'object') {
|
|
for (k in value) {
|
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
|
v = walk(value, k);
|
|
if (v !== undefined) {
|
|
value[k] = v;
|
|
} else {
|
|
delete value[k];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return reviver.call(holder, key, value);
|
|
}({'': result}, '')) : result;
|
|
};
|
|
|
|
},{}],38:[function(require,module,exports){
|
|
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
gap,
|
|
indent,
|
|
meta = { // table of character substitutions
|
|
'\b': '\\b',
|
|
'\t': '\\t',
|
|
'\n': '\\n',
|
|
'\f': '\\f',
|
|
'\r': '\\r',
|
|
'"' : '\\"',
|
|
'\\': '\\\\'
|
|
},
|
|
rep;
|
|
|
|
function quote(string) {
|
|
// If the string contains no control characters, no quote characters, and no
|
|
// backslash characters, then we can safely slap some quotes around it.
|
|
// Otherwise we must also replace the offending characters with safe escape
|
|
// sequences.
|
|
|
|
escapable.lastIndex = 0;
|
|
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
|
|
var c = meta[a];
|
|
return typeof c === 'string' ? c :
|
|
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
}) + '"' : '"' + string + '"';
|
|
}
|
|
|
|
function str(key, holder) {
|
|
// Produce a string from holder[key].
|
|
var i, // The loop counter.
|
|
k, // The member key.
|
|
v, // The member value.
|
|
length,
|
|
mind = gap,
|
|
partial,
|
|
value = holder[key];
|
|
|
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
|
if (value && typeof value === 'object' &&
|
|
typeof value.toJSON === 'function') {
|
|
value = value.toJSON(key);
|
|
}
|
|
|
|
// If we were called with a replacer function, then call the replacer to
|
|
// obtain a replacement value.
|
|
if (typeof rep === 'function') {
|
|
value = rep.call(holder, key, value);
|
|
}
|
|
|
|
// What happens next depends on the value's type.
|
|
switch (typeof value) {
|
|
case 'string':
|
|
return quote(value);
|
|
|
|
case 'number':
|
|
// JSON numbers must be finite. Encode non-finite numbers as null.
|
|
return isFinite(value) ? String(value) : 'null';
|
|
|
|
case 'boolean':
|
|
case 'null':
|
|
// If the value is a boolean or null, convert it to a string. Note:
|
|
// typeof null does not produce 'null'. The case is included here in
|
|
// the remote chance that this gets fixed someday.
|
|
return String(value);
|
|
|
|
case 'object':
|
|
if (!value) return 'null';
|
|
gap += indent;
|
|
partial = [];
|
|
|
|
// Array.isArray
|
|
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
|
length = value.length;
|
|
for (i = 0; i < length; i += 1) {
|
|
partial[i] = str(i, value) || 'null';
|
|
}
|
|
|
|
// Join all of the elements together, separated with commas, and
|
|
// wrap them in brackets.
|
|
v = partial.length === 0 ? '[]' : gap ?
|
|
'[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
|
|
'[' + partial.join(',') + ']';
|
|
gap = mind;
|
|
return v;
|
|
}
|
|
|
|
// If the replacer is an array, use it to select the members to be
|
|
// stringified.
|
|
if (rep && typeof rep === 'object') {
|
|
length = rep.length;
|
|
for (i = 0; i < length; i += 1) {
|
|
k = rep[i];
|
|
if (typeof k === 'string') {
|
|
v = str(k, value);
|
|
if (v) {
|
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// Otherwise, iterate through all of the keys in the object.
|
|
for (k in value) {
|
|
if (Object.prototype.hasOwnProperty.call(value, k)) {
|
|
v = str(k, value);
|
|
if (v) {
|
|
partial.push(quote(k) + (gap ? ': ' : ':') + v);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Join all of the member texts together, separated with commas,
|
|
// and wrap them in braces.
|
|
|
|
v = partial.length === 0 ? '{}' : gap ?
|
|
'{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
|
|
'{' + partial.join(',') + '}';
|
|
gap = mind;
|
|
return v;
|
|
}
|
|
}
|
|
|
|
module.exports = function (value, replacer, space) {
|
|
var i;
|
|
gap = '';
|
|
indent = '';
|
|
|
|
// If the space parameter is a number, make an indent string containing that
|
|
// many spaces.
|
|
if (typeof space === 'number') {
|
|
for (i = 0; i < space; i += 1) {
|
|
indent += ' ';
|
|
}
|
|
}
|
|
// If the space parameter is a string, it will be used as the indent string.
|
|
else if (typeof space === 'string') {
|
|
indent = space;
|
|
}
|
|
|
|
// If there is a replacer, it must be a function or an array.
|
|
// Otherwise, throw an error.
|
|
rep = replacer;
|
|
if (replacer && typeof replacer !== 'function'
|
|
&& (typeof replacer !== 'object' || typeof replacer.length !== 'number')) {
|
|
throw new Error('JSON.stringify');
|
|
}
|
|
|
|
// Make a fake root object containing our value under the key of ''.
|
|
// Return the result of stringifying the value.
|
|
return str('', {'': value});
|
|
};
|
|
|
|
},{}],39:[function(require,module,exports){
|
|
var Stream = require('stream');
|
|
var sockjs = require('sockjs-client');
|
|
var resolve = require('url').resolve;
|
|
var parse = require('url').parse;
|
|
|
|
module.exports = function (u, cb) {
|
|
var uri = parse(u).protocol ? u : resolve(window.location.href, u);
|
|
|
|
var stream = new Stream;
|
|
stream.readable = true;
|
|
stream.writable = true;
|
|
|
|
var ready = false;
|
|
var buffer = [];
|
|
|
|
var sock = sockjs(uri);
|
|
stream.sock = sock;
|
|
|
|
stream.write = function (msg) {
|
|
if (!ready || buffer.length) buffer.push(msg)
|
|
else sock.send(msg)
|
|
};
|
|
|
|
stream.end = function (msg) {
|
|
if (msg !== undefined) stream.write(msg);
|
|
if (!ready) {
|
|
stream._ended = true;
|
|
return;
|
|
}
|
|
stream.writable = false;
|
|
sock.close();
|
|
};
|
|
|
|
stream.destroy = function () {
|
|
stream._ended = true;
|
|
stream.writable = stream.readable = false;
|
|
buffer.length = 0
|
|
sock.close();
|
|
};
|
|
|
|
sock.onopen = function () {
|
|
if (typeof cb === 'function') cb();
|
|
ready = true;
|
|
for (var i = 0; i < buffer.length; i++) {
|
|
sock.send(buffer[i]);
|
|
}
|
|
buffer = [];
|
|
stream.emit('connect');
|
|
if (stream._ended) stream.end();
|
|
};
|
|
|
|
sock.onmessage = function (e) {
|
|
stream.emit('data', e.data);
|
|
};
|
|
|
|
sock.onclose = function () {
|
|
stream.emit('end');
|
|
stream.writable = false;
|
|
stream.readable = false;
|
|
};
|
|
|
|
return stream;
|
|
};
|
|
|
|
},{"sockjs-client":40,"stream":26,"url":28}],40:[function(require,module,exports){
|
|
/* SockJS client, version 0.3.1.7.ga67f.dirty, http://sockjs.org, MIT License
|
|
|
|
Copyright (c) 2011-2012 VMware, Inc.
|
|
|
|
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.
|
|
*/
|
|
|
|
// JSON2 by Douglas Crockford (minified).
|
|
var JSON;JSON||(JSON={}),function(){function str(a,b){var c,d,e,f,g=gap,h,i=b[a];i&&typeof i=="object"&&typeof i.toJSON=="function"&&(i=i.toJSON(a)),typeof rep=="function"&&(i=rep.call(b,a,i));switch(typeof i){case"string":return quote(i);case"number":return isFinite(i)?String(i):"null";case"boolean":case"null":return String(i);case"object":if(!i)return"null";gap+=indent,h=[];if(Object.prototype.toString.apply(i)==="[object Array]"){f=i.length;for(c=0;c<f;c+=1)h[c]=str(c,i)||"null";e=h.length===0?"[]":gap?"[\n"+gap+h.join(",\n"+gap)+"\n"+g+"]":"["+h.join(",")+"]",gap=g;return e}if(rep&&typeof rep=="object"){f=rep.length;for(c=0;c<f;c+=1)typeof rep[c]=="string"&&(d=rep[c],e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e))}else for(d in i)Object.prototype.hasOwnProperty.call(i,d)&&(e=str(d,i),e&&h.push(quote(d)+(gap?": ":":")+e));e=h.length===0?"{}":gap?"{\n"+gap+h.join(",\n"+gap)+"\n"+g+"}":"{"+h.join(",")+"}",gap=g;return e}}function quote(a){escapable.lastIndex=0;return escapable.test(a)?'"'+a.replace(escapable,function(a){var b=meta[a];return typeof b=="string"?b:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+a+'"'}function f(a){return a<10?"0"+a:a}"use strict",typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(a){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(a){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(a,b,c){var d;gap="",indent="";if(typeof c=="number")for(d=0;d<c;d+=1)indent+=" ";else typeof c=="string"&&(indent=c);rep=b;if(!b||typeof b=="function"||typeof b=="object"&&typeof b.length=="number")return str("",{"":a});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(a,b){var c,d,e=a[b];if(e&&typeof e=="object")for(c in e)Object.prototype.hasOwnProperty.call(e,c)&&(d=walk(e,c),d!==undefined?e[c]=d:delete e[c]);return reviver.call(a,b,e)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver=="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")})}()
|
|
|
|
|
|
// [*] Including lib/index.js
|
|
// Public object
|
|
var SockJS = (function(){
|
|
var _document = document;
|
|
var _window = window;
|
|
var utils = {};
|
|
|
|
|
|
// [*] Including lib/reventtarget.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
/* Simplified implementation of DOM2 EventTarget.
|
|
* http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget
|
|
*/
|
|
var REventTarget = function() {};
|
|
REventTarget.prototype.addEventListener = function (eventType, listener) {
|
|
if(!this._listeners) {
|
|
this._listeners = {};
|
|
}
|
|
if(!(eventType in this._listeners)) {
|
|
this._listeners[eventType] = [];
|
|
}
|
|
var arr = this._listeners[eventType];
|
|
if(utils.arrIndexOf(arr, listener) === -1) {
|
|
arr.push(listener);
|
|
}
|
|
return;
|
|
};
|
|
|
|
REventTarget.prototype.removeEventListener = function (eventType, listener) {
|
|
if(!(this._listeners && (eventType in this._listeners))) {
|
|
return;
|
|
}
|
|
var arr = this._listeners[eventType];
|
|
var idx = utils.arrIndexOf(arr, listener);
|
|
if (idx !== -1) {
|
|
if(arr.length > 1) {
|
|
this._listeners[eventType] = arr.slice(0, idx).concat( arr.slice(idx+1) );
|
|
} else {
|
|
delete this._listeners[eventType];
|
|
}
|
|
return;
|
|
}
|
|
return;
|
|
};
|
|
|
|
REventTarget.prototype.dispatchEvent = function (event) {
|
|
var t = event.type;
|
|
var args = Array.prototype.slice.call(arguments, 0);
|
|
if (this['on'+t]) {
|
|
this['on'+t].apply(this, args);
|
|
}
|
|
if (this._listeners && t in this._listeners) {
|
|
for(var i=0; i < this._listeners[t].length; i++) {
|
|
this._listeners[t][i].apply(this, args);
|
|
}
|
|
}
|
|
};
|
|
// [*] End of lib/reventtarget.js
|
|
|
|
|
|
// [*] Including lib/simpleevent.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var SimpleEvent = function(type, obj) {
|
|
this.type = type;
|
|
if (typeof obj !== 'undefined') {
|
|
for(var k in obj) {
|
|
if (!obj.hasOwnProperty(k)) continue;
|
|
this[k] = obj[k];
|
|
}
|
|
}
|
|
};
|
|
|
|
SimpleEvent.prototype.toString = function() {
|
|
var r = [];
|
|
for(var k in this) {
|
|
if (!this.hasOwnProperty(k)) continue;
|
|
var v = this[k];
|
|
if (typeof v === 'function') v = '[function]';
|
|
r.push(k + '=' + v);
|
|
}
|
|
return 'SimpleEvent(' + r.join(', ') + ')';
|
|
};
|
|
// [*] End of lib/simpleevent.js
|
|
|
|
|
|
// [*] Including lib/eventemitter.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var EventEmitter = function(events) {
|
|
this.events = events || [];
|
|
};
|
|
EventEmitter.prototype.emit = function(type) {
|
|
var that = this;
|
|
var args = Array.prototype.slice.call(arguments, 1);
|
|
if (!that.nuked && that['on'+type]) {
|
|
that['on'+type].apply(that, args);
|
|
}
|
|
if (utils.arrIndexOf(that.events, type) === -1) {
|
|
utils.log('Event ' + JSON.stringify(type) +
|
|
' not listed ' + JSON.stringify(that.events) +
|
|
' in ' + that);
|
|
}
|
|
};
|
|
|
|
EventEmitter.prototype.nuke = function(type) {
|
|
var that = this;
|
|
that.nuked = true;
|
|
for(var i=0; i<that.events.length; i++) {
|
|
delete that[that.events[i]];
|
|
}
|
|
};
|
|
// [*] End of lib/eventemitter.js
|
|
|
|
|
|
// [*] Including lib/utils.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var random_string_chars = 'abcdefghijklmnopqrstuvwxyz0123456789_';
|
|
utils.random_string = function(length, max) {
|
|
max = max || random_string_chars.length;
|
|
var i, ret = [];
|
|
for(i=0; i < length; i++) {
|
|
ret.push( random_string_chars.substr(Math.floor(Math.random() * max),1) );
|
|
}
|
|
return ret.join('');
|
|
};
|
|
utils.random_number = function(max) {
|
|
return Math.floor(Math.random() * max);
|
|
};
|
|
utils.random_number_string = function(max) {
|
|
var t = (''+(max - 1)).length;
|
|
var p = Array(t+1).join('0');
|
|
return (p + utils.random_number(max)).slice(-t);
|
|
};
|
|
|
|
// Assuming that url looks like: http://asdasd:111/asd
|
|
utils.getOrigin = function(url) {
|
|
url += '/';
|
|
var parts = url.split('/').slice(0, 3);
|
|
return parts.join('/');
|
|
};
|
|
|
|
utils.isSameOriginUrl = function(url_a, url_b) {
|
|
// location.origin would do, but it's not always available.
|
|
if (!url_b) url_b = _window.location.href;
|
|
|
|
return (url_a.split('/').slice(0,3).join('/')
|
|
===
|
|
url_b.split('/').slice(0,3).join('/'));
|
|
};
|
|
|
|
utils.getParentDomain = function(url) {
|
|
// ipv4 ip address
|
|
if (/^[0-9.]*$/.test(url)) return url;
|
|
// ipv6 ip address
|
|
if (/^\[/.test(url)) return url;
|
|
// no dots
|
|
if (!(/[.]/.test(url))) return url;
|
|
|
|
var parts = url.split('.').slice(1);
|
|
return parts.join('.');
|
|
};
|
|
|
|
utils.objectExtend = function(dst, src) {
|
|
for(var k in src) {
|
|
if (src.hasOwnProperty(k)) {
|
|
dst[k] = src[k];
|
|
}
|
|
}
|
|
return dst;
|
|
};
|
|
|
|
var WPrefix = '_jp';
|
|
|
|
utils.polluteGlobalNamespace = function() {
|
|
if (!(WPrefix in _window)) {
|
|
_window[WPrefix] = {};
|
|
}
|
|
};
|
|
|
|
utils.closeFrame = function (code, reason) {
|
|
return 'c'+JSON.stringify([code, reason]);
|
|
};
|
|
|
|
utils.userSetCode = function (code) {
|
|
return code === 1000 || (code >= 3000 && code <= 4999);
|
|
};
|
|
|
|
// See: http://www.erg.abdn.ac.uk/~gerrit/dccp/notes/ccid2/rto_estimator/
|
|
// and RFC 2988.
|
|
utils.countRTO = function (rtt) {
|
|
var rto;
|
|
if (rtt > 100) {
|
|
rto = 3 * rtt; // rto > 300msec
|
|
} else {
|
|
rto = rtt + 200; // 200msec < rto <= 300msec
|
|
}
|
|
return rto;
|
|
}
|
|
|
|
utils.log = function() {
|
|
if (_window.console && console.log && console.log.apply) {
|
|
console.log.apply(console, arguments);
|
|
}
|
|
};
|
|
|
|
utils.bind = function(fun, that) {
|
|
if (fun.bind) {
|
|
return fun.bind(that);
|
|
} else {
|
|
return function() {
|
|
return fun.apply(that, arguments);
|
|
};
|
|
}
|
|
};
|
|
|
|
utils.flatUrl = function(url) {
|
|
return url.indexOf('?') === -1 && url.indexOf('#') === -1;
|
|
};
|
|
|
|
utils.amendUrl = function(url) {
|
|
var dl = _document.location;
|
|
if (!url) {
|
|
throw new Error('Wrong url for SockJS');
|
|
}
|
|
if (!utils.flatUrl(url)) {
|
|
throw new Error('Only basic urls are supported in SockJS');
|
|
}
|
|
|
|
// '//abc' --> 'http://abc'
|
|
if (url.indexOf('//') === 0) {
|
|
url = dl.protocol + url;
|
|
}
|
|
// '/abc' --> 'http://localhost:80/abc'
|
|
if (url.indexOf('/') === 0) {
|
|
url = dl.protocol + '//' + dl.host + url;
|
|
}
|
|
// strip trailing slashes
|
|
url = url.replace(/[/]+$/,'');
|
|
return url;
|
|
};
|
|
|
|
// IE doesn't support [].indexOf.
|
|
utils.arrIndexOf = function(arr, obj){
|
|
for(var i=0; i < arr.length; i++){
|
|
if(arr[i] === obj){
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
|
|
utils.arrSkip = function(arr, obj) {
|
|
var idx = utils.arrIndexOf(arr, obj);
|
|
if (idx === -1) {
|
|
return arr.slice();
|
|
} else {
|
|
var dst = arr.slice(0, idx);
|
|
return dst.concat(arr.slice(idx+1));
|
|
}
|
|
};
|
|
|
|
// Via: https://gist.github.com/1133122/2121c601c5549155483f50be3da5305e83b8c5df
|
|
utils.isArray = Array.isArray || function(value) {
|
|
return {}.toString.call(value).indexOf('Array') >= 0
|
|
};
|
|
|
|
utils.delay = function(t, fun) {
|
|
if(typeof t === 'function') {
|
|
fun = t;
|
|
t = 0;
|
|
}
|
|
return setTimeout(fun, t);
|
|
};
|
|
|
|
|
|
// Chars worth escaping, as defined by Douglas Crockford:
|
|
// https://github.com/douglascrockford/JSON-js/blob/47a9882cddeb1e8529e07af9736218075372b8ac/json2.js#L196
|
|
var json_escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
|
|
json_lookup = {
|
|
"\u0000":"\\u0000","\u0001":"\\u0001","\u0002":"\\u0002","\u0003":"\\u0003",
|
|
"\u0004":"\\u0004","\u0005":"\\u0005","\u0006":"\\u0006","\u0007":"\\u0007",
|
|
"\b":"\\b","\t":"\\t","\n":"\\n","\u000b":"\\u000b","\f":"\\f","\r":"\\r",
|
|
"\u000e":"\\u000e","\u000f":"\\u000f","\u0010":"\\u0010","\u0011":"\\u0011",
|
|
"\u0012":"\\u0012","\u0013":"\\u0013","\u0014":"\\u0014","\u0015":"\\u0015",
|
|
"\u0016":"\\u0016","\u0017":"\\u0017","\u0018":"\\u0018","\u0019":"\\u0019",
|
|
"\u001a":"\\u001a","\u001b":"\\u001b","\u001c":"\\u001c","\u001d":"\\u001d",
|
|
"\u001e":"\\u001e","\u001f":"\\u001f","\"":"\\\"","\\":"\\\\",
|
|
"\u007f":"\\u007f","\u0080":"\\u0080","\u0081":"\\u0081","\u0082":"\\u0082",
|
|
"\u0083":"\\u0083","\u0084":"\\u0084","\u0085":"\\u0085","\u0086":"\\u0086",
|
|
"\u0087":"\\u0087","\u0088":"\\u0088","\u0089":"\\u0089","\u008a":"\\u008a",
|
|
"\u008b":"\\u008b","\u008c":"\\u008c","\u008d":"\\u008d","\u008e":"\\u008e",
|
|
"\u008f":"\\u008f","\u0090":"\\u0090","\u0091":"\\u0091","\u0092":"\\u0092",
|
|
"\u0093":"\\u0093","\u0094":"\\u0094","\u0095":"\\u0095","\u0096":"\\u0096",
|
|
"\u0097":"\\u0097","\u0098":"\\u0098","\u0099":"\\u0099","\u009a":"\\u009a",
|
|
"\u009b":"\\u009b","\u009c":"\\u009c","\u009d":"\\u009d","\u009e":"\\u009e",
|
|
"\u009f":"\\u009f","\u00ad":"\\u00ad","\u0600":"\\u0600","\u0601":"\\u0601",
|
|
"\u0602":"\\u0602","\u0603":"\\u0603","\u0604":"\\u0604","\u070f":"\\u070f",
|
|
"\u17b4":"\\u17b4","\u17b5":"\\u17b5","\u200c":"\\u200c","\u200d":"\\u200d",
|
|
"\u200e":"\\u200e","\u200f":"\\u200f","\u2028":"\\u2028","\u2029":"\\u2029",
|
|
"\u202a":"\\u202a","\u202b":"\\u202b","\u202c":"\\u202c","\u202d":"\\u202d",
|
|
"\u202e":"\\u202e","\u202f":"\\u202f","\u2060":"\\u2060","\u2061":"\\u2061",
|
|
"\u2062":"\\u2062","\u2063":"\\u2063","\u2064":"\\u2064","\u2065":"\\u2065",
|
|
"\u2066":"\\u2066","\u2067":"\\u2067","\u2068":"\\u2068","\u2069":"\\u2069",
|
|
"\u206a":"\\u206a","\u206b":"\\u206b","\u206c":"\\u206c","\u206d":"\\u206d",
|
|
"\u206e":"\\u206e","\u206f":"\\u206f","\ufeff":"\\ufeff","\ufff0":"\\ufff0",
|
|
"\ufff1":"\\ufff1","\ufff2":"\\ufff2","\ufff3":"\\ufff3","\ufff4":"\\ufff4",
|
|
"\ufff5":"\\ufff5","\ufff6":"\\ufff6","\ufff7":"\\ufff7","\ufff8":"\\ufff8",
|
|
"\ufff9":"\\ufff9","\ufffa":"\\ufffa","\ufffb":"\\ufffb","\ufffc":"\\ufffc",
|
|
"\ufffd":"\\ufffd","\ufffe":"\\ufffe","\uffff":"\\uffff"};
|
|
|
|
// Some extra characters that Chrome gets wrong, and substitutes with
|
|
// something else on the wire.
|
|
var extra_escapable = /[\x00-\x1f\ud800-\udfff\ufffe\uffff\u0300-\u0333\u033d-\u0346\u034a-\u034c\u0350-\u0352\u0357-\u0358\u035c-\u0362\u0374\u037e\u0387\u0591-\u05af\u05c4\u0610-\u0617\u0653-\u0654\u0657-\u065b\u065d-\u065e\u06df-\u06e2\u06eb-\u06ec\u0730\u0732-\u0733\u0735-\u0736\u073a\u073d\u073f-\u0741\u0743\u0745\u0747\u07eb-\u07f1\u0951\u0958-\u095f\u09dc-\u09dd\u09df\u0a33\u0a36\u0a59-\u0a5b\u0a5e\u0b5c-\u0b5d\u0e38-\u0e39\u0f43\u0f4d\u0f52\u0f57\u0f5c\u0f69\u0f72-\u0f76\u0f78\u0f80-\u0f83\u0f93\u0f9d\u0fa2\u0fa7\u0fac\u0fb9\u1939-\u193a\u1a17\u1b6b\u1cda-\u1cdb\u1dc0-\u1dcf\u1dfc\u1dfe\u1f71\u1f73\u1f75\u1f77\u1f79\u1f7b\u1f7d\u1fbb\u1fbe\u1fc9\u1fcb\u1fd3\u1fdb\u1fe3\u1feb\u1fee-\u1fef\u1ff9\u1ffb\u1ffd\u2000-\u2001\u20d0-\u20d1\u20d4-\u20d7\u20e7-\u20e9\u2126\u212a-\u212b\u2329-\u232a\u2adc\u302b-\u302c\uaab2-\uaab3\uf900-\ufa0d\ufa10\ufa12\ufa15-\ufa1e\ufa20\ufa22\ufa25-\ufa26\ufa2a-\ufa2d\ufa30-\ufa6d\ufa70-\ufad9\ufb1d\ufb1f\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40-\ufb41\ufb43-\ufb44\ufb46-\ufb4e\ufff0-\uffff]/g,
|
|
extra_lookup;
|
|
|
|
// JSON Quote string. Use native implementation when possible.
|
|
var JSONQuote = (JSON && JSON.stringify) || function(string) {
|
|
json_escapable.lastIndex = 0;
|
|
if (json_escapable.test(string)) {
|
|
string = string.replace(json_escapable, function(a) {
|
|
return json_lookup[a];
|
|
});
|
|
}
|
|
return '"' + string + '"';
|
|
};
|
|
|
|
// This may be quite slow, so let's delay until user actually uses bad
|
|
// characters.
|
|
var unroll_lookup = function(escapable) {
|
|
var i;
|
|
var unrolled = {}
|
|
var c = []
|
|
for(i=0; i<65536; i++) {
|
|
c.push( String.fromCharCode(i) );
|
|
}
|
|
escapable.lastIndex = 0;
|
|
c.join('').replace(escapable, function (a) {
|
|
unrolled[ a ] = '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
|
return '';
|
|
});
|
|
escapable.lastIndex = 0;
|
|
return unrolled;
|
|
};
|
|
|
|
// Quote string, also taking care of unicode characters that browsers
|
|
// often break. Especially, take care of unicode surrogates:
|
|
// http://en.wikipedia.org/wiki/Mapping_of_Unicode_characters#Surrogates
|
|
utils.quote = function(string) {
|
|
var quoted = JSONQuote(string);
|
|
|
|
// In most cases this should be very fast and good enough.
|
|
extra_escapable.lastIndex = 0;
|
|
if(!extra_escapable.test(quoted)) {
|
|
return quoted;
|
|
}
|
|
|
|
if(!extra_lookup) extra_lookup = unroll_lookup(extra_escapable);
|
|
|
|
return quoted.replace(extra_escapable, function(a) {
|
|
return extra_lookup[a];
|
|
});
|
|
}
|
|
|
|
var _all_protocols = ['websocket',
|
|
'xdr-streaming',
|
|
'xhr-streaming',
|
|
'iframe-eventsource',
|
|
'iframe-htmlfile',
|
|
'xdr-polling',
|
|
'xhr-polling',
|
|
'iframe-xhr-polling',
|
|
'jsonp-polling'];
|
|
|
|
utils.probeProtocols = function() {
|
|
var probed = {};
|
|
for(var i=0; i<_all_protocols.length; i++) {
|
|
var protocol = _all_protocols[i];
|
|
// User can have a typo in protocol name.
|
|
probed[protocol] = SockJS[protocol] &&
|
|
SockJS[protocol].enabled();
|
|
}
|
|
return probed;
|
|
};
|
|
|
|
utils.detectProtocols = function(probed, protocols_whitelist, info) {
|
|
var pe = {},
|
|
protocols = [];
|
|
if (!protocols_whitelist) protocols_whitelist = _all_protocols;
|
|
for(var i=0; i<protocols_whitelist.length; i++) {
|
|
var protocol = protocols_whitelist[i];
|
|
pe[protocol] = probed[protocol];
|
|
}
|
|
var maybe_push = function(protos) {
|
|
var proto = protos.shift();
|
|
if (pe[proto]) {
|
|
protocols.push(proto);
|
|
} else {
|
|
if (protos.length > 0) {
|
|
maybe_push(protos);
|
|
}
|
|
}
|
|
}
|
|
|
|
// 1. Websocket
|
|
if (info.websocket !== false) {
|
|
maybe_push(['websocket']);
|
|
}
|
|
|
|
// 2. Streaming
|
|
if (pe['xhr-streaming'] && !info.null_origin) {
|
|
protocols.push('xhr-streaming');
|
|
} else {
|
|
if (pe['xdr-streaming'] && !info.cookie_needed && !info.null_origin) {
|
|
protocols.push('xdr-streaming');
|
|
} else {
|
|
maybe_push(['iframe-eventsource',
|
|
'iframe-htmlfile']);
|
|
}
|
|
}
|
|
|
|
// 3. Polling
|
|
if (pe['xhr-polling'] && !info.null_origin) {
|
|
protocols.push('xhr-polling');
|
|
} else {
|
|
if (pe['xdr-polling'] && !info.cookie_needed && !info.null_origin) {
|
|
protocols.push('xdr-polling');
|
|
} else {
|
|
maybe_push(['iframe-xhr-polling',
|
|
'jsonp-polling']);
|
|
}
|
|
}
|
|
return protocols;
|
|
}
|
|
// [*] End of lib/utils.js
|
|
|
|
|
|
// [*] Including lib/dom.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// May be used by htmlfile jsonp and transports.
|
|
var MPrefix = '_sockjs_global';
|
|
utils.createHook = function() {
|
|
var window_id = 'a' + utils.random_string(8);
|
|
if (!(MPrefix in _window)) {
|
|
var map = {};
|
|
_window[MPrefix] = function(window_id) {
|
|
if (!(window_id in map)) {
|
|
map[window_id] = {
|
|
id: window_id,
|
|
del: function() {delete map[window_id];}
|
|
};
|
|
}
|
|
return map[window_id];
|
|
}
|
|
}
|
|
return _window[MPrefix](window_id);
|
|
};
|
|
|
|
|
|
|
|
utils.attachMessage = function(listener) {
|
|
utils.attachEvent('message', listener);
|
|
};
|
|
utils.attachEvent = function(event, listener) {
|
|
if (typeof _window.addEventListener !== 'undefined') {
|
|
_window.addEventListener(event, listener, false);
|
|
} else {
|
|
// IE quirks.
|
|
// According to: http://stevesouders.com/misc/test-postmessage.php
|
|
// the message gets delivered only to 'document', not 'window'.
|
|
_document.attachEvent("on" + event, listener);
|
|
// I get 'window' for ie8.
|
|
_window.attachEvent("on" + event, listener);
|
|
}
|
|
};
|
|
|
|
utils.detachMessage = function(listener) {
|
|
utils.detachEvent('message', listener);
|
|
};
|
|
utils.detachEvent = function(event, listener) {
|
|
if (typeof _window.addEventListener !== 'undefined') {
|
|
_window.removeEventListener(event, listener, false);
|
|
} else {
|
|
_document.detachEvent("on" + event, listener);
|
|
_window.detachEvent("on" + event, listener);
|
|
}
|
|
};
|
|
|
|
|
|
var on_unload = {};
|
|
// Things registered after beforeunload are to be called immediately.
|
|
var after_unload = false;
|
|
|
|
var trigger_unload_callbacks = function() {
|
|
for(var ref in on_unload) {
|
|
on_unload[ref]();
|
|
delete on_unload[ref];
|
|
};
|
|
};
|
|
|
|
var unload_triggered = function() {
|
|
if(after_unload) return;
|
|
after_unload = true;
|
|
trigger_unload_callbacks();
|
|
};
|
|
|
|
// Onbeforeunload alone is not reliable. We could use only 'unload'
|
|
// but it's not working in opera within an iframe. Let's use both.
|
|
utils.attachEvent('beforeunload', unload_triggered);
|
|
utils.attachEvent('unload', unload_triggered);
|
|
|
|
utils.unload_add = function(listener) {
|
|
var ref = utils.random_string(8);
|
|
on_unload[ref] = listener;
|
|
if (after_unload) {
|
|
utils.delay(trigger_unload_callbacks);
|
|
}
|
|
return ref;
|
|
};
|
|
utils.unload_del = function(ref) {
|
|
if (ref in on_unload)
|
|
delete on_unload[ref];
|
|
};
|
|
|
|
|
|
utils.createIframe = function (iframe_url, error_callback) {
|
|
var iframe = _document.createElement('iframe');
|
|
var tref, unload_ref;
|
|
var unattach = function() {
|
|
clearTimeout(tref);
|
|
// Explorer had problems with that.
|
|
try {iframe.onload = null;} catch (x) {}
|
|
iframe.onerror = null;
|
|
};
|
|
var cleanup = function() {
|
|
if (iframe) {
|
|
unattach();
|
|
// This timeout makes chrome fire onbeforeunload event
|
|
// within iframe. Without the timeout it goes straight to
|
|
// onunload.
|
|
setTimeout(function() {
|
|
if(iframe) {
|
|
iframe.parentNode.removeChild(iframe);
|
|
}
|
|
iframe = null;
|
|
}, 0);
|
|
utils.unload_del(unload_ref);
|
|
}
|
|
};
|
|
var onerror = function(r) {
|
|
if (iframe) {
|
|
cleanup();
|
|
error_callback(r);
|
|
}
|
|
};
|
|
var post = function(msg, origin) {
|
|
try {
|
|
// When the iframe is not loaded, IE raises an exception
|
|
// on 'contentWindow'.
|
|
if (iframe && iframe.contentWindow) {
|
|
iframe.contentWindow.postMessage(msg, origin);
|
|
}
|
|
} catch (x) {};
|
|
};
|
|
|
|
iframe.src = iframe_url;
|
|
iframe.style.display = 'none';
|
|
iframe.style.position = 'absolute';
|
|
iframe.onerror = function(){onerror('onerror');};
|
|
iframe.onload = function() {
|
|
// `onload` is triggered before scripts on the iframe are
|
|
// executed. Give it few seconds to actually load stuff.
|
|
clearTimeout(tref);
|
|
tref = setTimeout(function(){onerror('onload timeout');}, 2000);
|
|
};
|
|
_document.body.appendChild(iframe);
|
|
tref = setTimeout(function(){onerror('timeout');}, 15000);
|
|
unload_ref = utils.unload_add(cleanup);
|
|
return {
|
|
post: post,
|
|
cleanup: cleanup,
|
|
loaded: unattach
|
|
};
|
|
};
|
|
|
|
utils.createHtmlfile = function (iframe_url, error_callback) {
|
|
var doc = new ActiveXObject('htmlfile');
|
|
var tref, unload_ref;
|
|
var iframe;
|
|
var unattach = function() {
|
|
clearTimeout(tref);
|
|
};
|
|
var cleanup = function() {
|
|
if (doc) {
|
|
unattach();
|
|
utils.unload_del(unload_ref);
|
|
iframe.parentNode.removeChild(iframe);
|
|
iframe = doc = null;
|
|
CollectGarbage();
|
|
}
|
|
};
|
|
var onerror = function(r) {
|
|
if (doc) {
|
|
cleanup();
|
|
error_callback(r);
|
|
}
|
|
};
|
|
var post = function(msg, origin) {
|
|
try {
|
|
// When the iframe is not loaded, IE raises an exception
|
|
// on 'contentWindow'.
|
|
if (iframe && iframe.contentWindow) {
|
|
iframe.contentWindow.postMessage(msg, origin);
|
|
}
|
|
} catch (x) {};
|
|
};
|
|
|
|
doc.open();
|
|
doc.write('<html><s' + 'cript>' +
|
|
'document.domain="' + document.domain + '";' +
|
|
'</s' + 'cript></html>');
|
|
doc.close();
|
|
doc.parentWindow[WPrefix] = _window[WPrefix];
|
|
var c = doc.createElement('div');
|
|
doc.body.appendChild(c);
|
|
iframe = doc.createElement('iframe');
|
|
c.appendChild(iframe);
|
|
iframe.src = iframe_url;
|
|
tref = setTimeout(function(){onerror('timeout');}, 15000);
|
|
unload_ref = utils.unload_add(cleanup);
|
|
return {
|
|
post: post,
|
|
cleanup: cleanup,
|
|
loaded: unattach
|
|
};
|
|
};
|
|
// [*] End of lib/dom.js
|
|
|
|
|
|
// [*] Including lib/dom2.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var AbstractXHRObject = function(){};
|
|
AbstractXHRObject.prototype = new EventEmitter(['chunk', 'finish']);
|
|
|
|
AbstractXHRObject.prototype._start = function(method, url, payload, opts) {
|
|
var that = this;
|
|
|
|
try {
|
|
that.xhr = new XMLHttpRequest();
|
|
} catch(x) {};
|
|
|
|
if (!that.xhr) {
|
|
try {
|
|
that.xhr = new _window.ActiveXObject('Microsoft.XMLHTTP');
|
|
} catch(x) {};
|
|
}
|
|
if (_window.ActiveXObject || _window.XDomainRequest) {
|
|
// IE8 caches even POSTs
|
|
url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
|
|
}
|
|
|
|
// Explorer tends to keep connection open, even after the
|
|
// tab gets closed: http://bugs.jquery.com/ticket/5280
|
|
that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
|
|
try {
|
|
that.xhr.open(method, url, true);
|
|
} catch(e) {
|
|
// IE raises an exception on wrong port.
|
|
that.emit('finish', 0, '');
|
|
that._cleanup();
|
|
return;
|
|
};
|
|
|
|
if (!opts || !opts.no_credentials) {
|
|
// Mozilla docs says https://developer.mozilla.org/en/XMLHttpRequest :
|
|
// "This never affects same-site requests."
|
|
that.xhr.withCredentials = 'true';
|
|
}
|
|
if (opts && opts.headers) {
|
|
for(var key in opts.headers) {
|
|
that.xhr.setRequestHeader(key, opts.headers[key]);
|
|
}
|
|
}
|
|
|
|
that.xhr.onreadystatechange = function() {
|
|
if (that.xhr) {
|
|
var x = that.xhr;
|
|
switch (x.readyState) {
|
|
case 3:
|
|
// IE doesn't like peeking into responseText or status
|
|
// on Microsoft.XMLHTTP and readystate=3
|
|
try {
|
|
var status = x.status;
|
|
var text = x.responseText;
|
|
} catch (x) {};
|
|
// IE does return readystate == 3 for 404 answers.
|
|
if (text && text.length > 0) {
|
|
that.emit('chunk', status, text);
|
|
}
|
|
break;
|
|
case 4:
|
|
that.emit('finish', x.status, x.responseText);
|
|
that._cleanup(false);
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
that.xhr.send(payload);
|
|
};
|
|
|
|
AbstractXHRObject.prototype._cleanup = function(abort) {
|
|
var that = this;
|
|
if (!that.xhr) return;
|
|
utils.unload_del(that.unload_ref);
|
|
|
|
// IE needs this field to be a function
|
|
that.xhr.onreadystatechange = function(){};
|
|
|
|
if (abort) {
|
|
try {
|
|
that.xhr.abort();
|
|
} catch(x) {};
|
|
}
|
|
that.unload_ref = that.xhr = null;
|
|
};
|
|
|
|
AbstractXHRObject.prototype.close = function() {
|
|
var that = this;
|
|
that.nuke();
|
|
that._cleanup(true);
|
|
};
|
|
|
|
var XHRCorsObject = utils.XHRCorsObject = function() {
|
|
var that = this, args = arguments;
|
|
utils.delay(function(){that._start.apply(that, args);});
|
|
};
|
|
XHRCorsObject.prototype = new AbstractXHRObject();
|
|
|
|
var XHRLocalObject = utils.XHRLocalObject = function(method, url, payload) {
|
|
var that = this;
|
|
utils.delay(function(){
|
|
that._start(method, url, payload, {
|
|
no_credentials: true
|
|
});
|
|
});
|
|
};
|
|
XHRLocalObject.prototype = new AbstractXHRObject();
|
|
|
|
|
|
|
|
// References:
|
|
// http://ajaxian.com/archives/100-line-ajax-wrapper
|
|
// http://msdn.microsoft.com/en-us/library/cc288060(v=VS.85).aspx
|
|
var XDRObject = utils.XDRObject = function(method, url, payload) {
|
|
var that = this;
|
|
utils.delay(function(){that._start(method, url, payload);});
|
|
};
|
|
XDRObject.prototype = new EventEmitter(['chunk', 'finish']);
|
|
XDRObject.prototype._start = function(method, url, payload) {
|
|
var that = this;
|
|
var xdr = new XDomainRequest();
|
|
// IE caches even POSTs
|
|
url += ((url.indexOf('?') === -1) ? '?' : '&') + 't='+(+new Date);
|
|
|
|
var onerror = xdr.ontimeout = xdr.onerror = function() {
|
|
that.emit('finish', 0, '');
|
|
that._cleanup(false);
|
|
};
|
|
xdr.onprogress = function() {
|
|
that.emit('chunk', 200, xdr.responseText);
|
|
};
|
|
xdr.onload = function() {
|
|
that.emit('finish', 200, xdr.responseText);
|
|
that._cleanup(false);
|
|
};
|
|
that.xdr = xdr;
|
|
that.unload_ref = utils.unload_add(function(){that._cleanup(true);});
|
|
try {
|
|
// Fails with AccessDenied if port number is bogus
|
|
that.xdr.open(method, url);
|
|
that.xdr.send(payload);
|
|
} catch(x) {
|
|
onerror();
|
|
}
|
|
};
|
|
|
|
XDRObject.prototype._cleanup = function(abort) {
|
|
var that = this;
|
|
if (!that.xdr) return;
|
|
utils.unload_del(that.unload_ref);
|
|
|
|
that.xdr.ontimeout = that.xdr.onerror = that.xdr.onprogress =
|
|
that.xdr.onload = null;
|
|
if (abort) {
|
|
try {
|
|
that.xdr.abort();
|
|
} catch(x) {};
|
|
}
|
|
that.unload_ref = that.xdr = null;
|
|
};
|
|
|
|
XDRObject.prototype.close = function() {
|
|
var that = this;
|
|
that.nuke();
|
|
that._cleanup(true);
|
|
};
|
|
|
|
// 1. Is natively via XHR
|
|
// 2. Is natively via XDR
|
|
// 3. Nope, but postMessage is there so it should work via the Iframe.
|
|
// 4. Nope, sorry.
|
|
utils.isXHRCorsCapable = function() {
|
|
if (_window.XMLHttpRequest && 'withCredentials' in new XMLHttpRequest()) {
|
|
return 1;
|
|
}
|
|
// XDomainRequest doesn't work if page is served from file://
|
|
if (_window.XDomainRequest && _document.domain) {
|
|
return 2;
|
|
}
|
|
if (IframeTransport.enabled()) {
|
|
return 3;
|
|
}
|
|
return 4;
|
|
};
|
|
// [*] End of lib/dom2.js
|
|
|
|
|
|
// [*] Including lib/sockjs.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var SockJS = function(url, dep_protocols_whitelist, options) {
|
|
if (this === window) {
|
|
// makes `new` optional
|
|
return new SockJS(url, dep_protocols_whitelist, options);
|
|
}
|
|
|
|
var that = this, protocols_whitelist;
|
|
that._options = {devel: false, debug: false, protocols_whitelist: [],
|
|
info: undefined, rtt: undefined};
|
|
if (options) {
|
|
utils.objectExtend(that._options, options);
|
|
}
|
|
that._base_url = utils.amendUrl(url);
|
|
that._server = that._options.server || utils.random_number_string(1000);
|
|
if (that._options.protocols_whitelist &&
|
|
that._options.protocols_whitelist.length) {
|
|
protocols_whitelist = that._options.protocols_whitelist;
|
|
} else {
|
|
// Deprecated API
|
|
if (typeof dep_protocols_whitelist === 'string' &&
|
|
dep_protocols_whitelist.length > 0) {
|
|
protocols_whitelist = [dep_protocols_whitelist];
|
|
} else if (utils.isArray(dep_protocols_whitelist)) {
|
|
protocols_whitelist = dep_protocols_whitelist
|
|
} else {
|
|
protocols_whitelist = null;
|
|
}
|
|
if (protocols_whitelist) {
|
|
that._debug('Deprecated API: Use "protocols_whitelist" option ' +
|
|
'instead of supplying protocol list as a second ' +
|
|
'parameter to SockJS constructor.');
|
|
}
|
|
}
|
|
that._protocols = [];
|
|
that.protocol = null;
|
|
that.readyState = SockJS.CONNECTING;
|
|
that._ir = createInfoReceiver(that._base_url);
|
|
that._ir.onfinish = function(info, rtt) {
|
|
that._ir = null;
|
|
if (info) {
|
|
if (that._options.info) {
|
|
// Override if user supplies the option
|
|
info = utils.objectExtend(info, that._options.info);
|
|
}
|
|
if (that._options.rtt) {
|
|
rtt = that._options.rtt;
|
|
}
|
|
that._applyInfo(info, rtt, protocols_whitelist);
|
|
that._didClose();
|
|
} else {
|
|
that._didClose(1002, 'Can\'t connect to server', true);
|
|
}
|
|
};
|
|
};
|
|
// Inheritance
|
|
SockJS.prototype = new REventTarget();
|
|
|
|
SockJS.version = "0.3.1.7.ga67f.dirty";
|
|
|
|
SockJS.CONNECTING = 0;
|
|
SockJS.OPEN = 1;
|
|
SockJS.CLOSING = 2;
|
|
SockJS.CLOSED = 3;
|
|
|
|
SockJS.prototype._debug = function() {
|
|
if (this._options.debug)
|
|
utils.log.apply(utils, arguments);
|
|
};
|
|
|
|
SockJS.prototype._dispatchOpen = function() {
|
|
var that = this;
|
|
if (that.readyState === SockJS.CONNECTING) {
|
|
if (that._transport_tref) {
|
|
clearTimeout(that._transport_tref);
|
|
that._transport_tref = null;
|
|
}
|
|
that.readyState = SockJS.OPEN;
|
|
that.dispatchEvent(new SimpleEvent("open"));
|
|
} else {
|
|
// The server might have been restarted, and lost track of our
|
|
// connection.
|
|
that._didClose(1006, "Server lost session");
|
|
}
|
|
};
|
|
|
|
SockJS.prototype._dispatchMessage = function(data) {
|
|
var that = this;
|
|
if (that.readyState !== SockJS.OPEN)
|
|
return;
|
|
that.dispatchEvent(new SimpleEvent("message", {data: data}));
|
|
};
|
|
|
|
SockJS.prototype._dispatchHeartbeat = function(data) {
|
|
var that = this;
|
|
if (that.readyState !== SockJS.OPEN)
|
|
return;
|
|
that.dispatchEvent(new SimpleEvent('heartbeat', {}));
|
|
};
|
|
|
|
SockJS.prototype._didClose = function(code, reason, force) {
|
|
var that = this;
|
|
if (that.readyState !== SockJS.CONNECTING &&
|
|
that.readyState !== SockJS.OPEN &&
|
|
that.readyState !== SockJS.CLOSING)
|
|
throw new Error('INVALID_STATE_ERR');
|
|
if (that._ir) {
|
|
that._ir.nuke();
|
|
that._ir = null;
|
|
}
|
|
|
|
if (that._transport) {
|
|
that._transport.doCleanup();
|
|
that._transport = null;
|
|
}
|
|
|
|
var close_event = new SimpleEvent("close", {
|
|
code: code,
|
|
reason: reason,
|
|
wasClean: utils.userSetCode(code)});
|
|
|
|
if (!utils.userSetCode(code) &&
|
|
that.readyState === SockJS.CONNECTING && !force) {
|
|
if (that._try_next_protocol(close_event)) {
|
|
return;
|
|
}
|
|
close_event = new SimpleEvent("close", {code: 2000,
|
|
reason: "All transports failed",
|
|
wasClean: false,
|
|
last_event: close_event});
|
|
}
|
|
that.readyState = SockJS.CLOSED;
|
|
|
|
utils.delay(function() {
|
|
that.dispatchEvent(close_event);
|
|
});
|
|
};
|
|
|
|
SockJS.prototype._didMessage = function(data) {
|
|
var that = this;
|
|
var type = data.slice(0, 1);
|
|
switch(type) {
|
|
case 'o':
|
|
that._dispatchOpen();
|
|
break;
|
|
case 'a':
|
|
var payload = JSON.parse(data.slice(1) || '[]');
|
|
for(var i=0; i < payload.length; i++){
|
|
that._dispatchMessage(payload[i]);
|
|
}
|
|
break;
|
|
case 'm':
|
|
var payload = JSON.parse(data.slice(1) || 'null');
|
|
that._dispatchMessage(payload);
|
|
break;
|
|
case 'c':
|
|
var payload = JSON.parse(data.slice(1) || '[]');
|
|
that._didClose(payload[0], payload[1]);
|
|
break;
|
|
case 'h':
|
|
that._dispatchHeartbeat();
|
|
break;
|
|
}
|
|
};
|
|
|
|
SockJS.prototype._try_next_protocol = function(close_event) {
|
|
var that = this;
|
|
if (that.protocol) {
|
|
that._debug('Closed transport:', that.protocol, ''+close_event);
|
|
that.protocol = null;
|
|
}
|
|
if (that._transport_tref) {
|
|
clearTimeout(that._transport_tref);
|
|
that._transport_tref = null;
|
|
}
|
|
|
|
while(1) {
|
|
var protocol = that.protocol = that._protocols.shift();
|
|
if (!protocol) {
|
|
return false;
|
|
}
|
|
// Some protocols require access to `body`, what if were in
|
|
// the `head`?
|
|
if (SockJS[protocol] &&
|
|
SockJS[protocol].need_body === true &&
|
|
(!_document.body ||
|
|
(typeof _document.readyState !== 'undefined'
|
|
&& _document.readyState !== 'complete'))) {
|
|
that._protocols.unshift(protocol);
|
|
that.protocol = 'waiting-for-load';
|
|
utils.attachEvent('load', function(){
|
|
that._try_next_protocol();
|
|
});
|
|
return true;
|
|
}
|
|
|
|
if (!SockJS[protocol] ||
|
|
!SockJS[protocol].enabled(that._options)) {
|
|
that._debug('Skipping transport:', protocol);
|
|
} else {
|
|
var roundTrips = SockJS[protocol].roundTrips || 1;
|
|
var to = ((that._options.rto || 0) * roundTrips) || 5000;
|
|
that._transport_tref = utils.delay(to, function() {
|
|
if (that.readyState === SockJS.CONNECTING) {
|
|
// I can't understand how it is possible to run
|
|
// this timer, when the state is CLOSED, but
|
|
// apparently in IE everythin is possible.
|
|
that._didClose(2007, "Transport timeouted");
|
|
}
|
|
});
|
|
|
|
var connid = utils.random_string(8);
|
|
var trans_url = that._base_url + '/' + that._server + '/' + connid;
|
|
that._debug('Opening transport:', protocol, ' url:'+trans_url,
|
|
' RTO:'+that._options.rto);
|
|
that._transport = new SockJS[protocol](that, trans_url,
|
|
that._base_url);
|
|
return true;
|
|
}
|
|
}
|
|
};
|
|
|
|
SockJS.prototype.close = function(code, reason) {
|
|
var that = this;
|
|
if (code && !utils.userSetCode(code))
|
|
throw new Error("INVALID_ACCESS_ERR");
|
|
if(that.readyState !== SockJS.CONNECTING &&
|
|
that.readyState !== SockJS.OPEN) {
|
|
return false;
|
|
}
|
|
that.readyState = SockJS.CLOSING;
|
|
that._didClose(code || 1000, reason || "Normal closure");
|
|
return true;
|
|
};
|
|
|
|
SockJS.prototype.send = function(data) {
|
|
var that = this;
|
|
if (that.readyState === SockJS.CONNECTING)
|
|
throw new Error('INVALID_STATE_ERR');
|
|
if (that.readyState === SockJS.OPEN) {
|
|
that._transport.doSend(utils.quote('' + data));
|
|
}
|
|
return true;
|
|
};
|
|
|
|
SockJS.prototype._applyInfo = function(info, rtt, protocols_whitelist) {
|
|
var that = this;
|
|
that._options.info = info;
|
|
that._options.rtt = rtt;
|
|
that._options.rto = utils.countRTO(rtt);
|
|
that._options.info.null_origin = !_document.domain;
|
|
var probed = utils.probeProtocols();
|
|
that._protocols = utils.detectProtocols(probed, protocols_whitelist, info);
|
|
};
|
|
// [*] End of lib/sockjs.js
|
|
|
|
|
|
// [*] Including lib/trans-websocket.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var WebSocketTransport = SockJS.websocket = function(ri, trans_url) {
|
|
var that = this;
|
|
var url = trans_url + '/websocket';
|
|
if (url.slice(0, 5) === 'https') {
|
|
url = 'wss' + url.slice(5);
|
|
} else {
|
|
url = 'ws' + url.slice(4);
|
|
}
|
|
that.ri = ri;
|
|
that.url = url;
|
|
var Constructor = _window.WebSocket || _window.MozWebSocket;
|
|
|
|
that.ws = new Constructor(that.url);
|
|
that.ws.onmessage = function(e) {
|
|
that.ri._didMessage(e.data);
|
|
};
|
|
// Firefox has an interesting bug. If a websocket connection is
|
|
// created after onbeforeunload, it stays alive even when user
|
|
// navigates away from the page. In such situation let's lie -
|
|
// let's not open the ws connection at all. See:
|
|
// https://github.com/sockjs/sockjs-client/issues/28
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=696085
|
|
that.unload_ref = utils.unload_add(function(){that.ws.close()});
|
|
that.ws.onclose = function() {
|
|
that.ri._didMessage(utils.closeFrame(1006, "WebSocket connection broken"));
|
|
};
|
|
};
|
|
|
|
WebSocketTransport.prototype.doSend = function(data) {
|
|
this.ws.send('[' + data + ']');
|
|
};
|
|
|
|
WebSocketTransport.prototype.doCleanup = function() {
|
|
var that = this;
|
|
var ws = that.ws;
|
|
if (ws) {
|
|
ws.onmessage = ws.onclose = null;
|
|
ws.close();
|
|
utils.unload_del(that.unload_ref);
|
|
that.unload_ref = that.ri = that.ws = null;
|
|
}
|
|
};
|
|
|
|
WebSocketTransport.enabled = function() {
|
|
return !!(_window.WebSocket || _window.MozWebSocket);
|
|
};
|
|
|
|
// In theory, ws should require 1 round trip. But in chrome, this is
|
|
// not very stable over SSL. Most likely a ws connection requires a
|
|
// separate SSL connection, in which case 2 round trips are an
|
|
// absolute minumum.
|
|
WebSocketTransport.roundTrips = 2;
|
|
// [*] End of lib/trans-websocket.js
|
|
|
|
|
|
// [*] Including lib/trans-sender.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var BufferedSender = function() {};
|
|
BufferedSender.prototype.send_constructor = function(sender) {
|
|
var that = this;
|
|
that.send_buffer = [];
|
|
that.sender = sender;
|
|
};
|
|
BufferedSender.prototype.doSend = function(message) {
|
|
var that = this;
|
|
that.send_buffer.push(message);
|
|
if (!that.send_stop) {
|
|
that.send_schedule();
|
|
}
|
|
};
|
|
|
|
// For polling transports in a situation when in the message callback,
|
|
// new message is being send. If the sending connection was started
|
|
// before receiving one, it is possible to saturate the network and
|
|
// timeout due to the lack of receiving socket. To avoid that we delay
|
|
// sending messages by some small time, in order to let receiving
|
|
// connection be started beforehand. This is only a halfmeasure and
|
|
// does not fix the big problem, but it does make the tests go more
|
|
// stable on slow networks.
|
|
BufferedSender.prototype.send_schedule_wait = function() {
|
|
var that = this;
|
|
var tref;
|
|
that.send_stop = function() {
|
|
that.send_stop = null;
|
|
clearTimeout(tref);
|
|
};
|
|
tref = utils.delay(25, function() {
|
|
that.send_stop = null;
|
|
that.send_schedule();
|
|
});
|
|
};
|
|
|
|
BufferedSender.prototype.send_schedule = function() {
|
|
var that = this;
|
|
if (that.send_buffer.length > 0) {
|
|
var payload = '[' + that.send_buffer.join(',') + ']';
|
|
that.send_stop = that.sender(that.trans_url,
|
|
payload,
|
|
function() {
|
|
that.send_stop = null;
|
|
that.send_schedule_wait();
|
|
});
|
|
that.send_buffer = [];
|
|
}
|
|
};
|
|
|
|
BufferedSender.prototype.send_destructor = function() {
|
|
var that = this;
|
|
if (that._send_stop) {
|
|
that._send_stop();
|
|
}
|
|
that._send_stop = null;
|
|
};
|
|
|
|
var jsonPGenericSender = function(url, payload, callback) {
|
|
var that = this;
|
|
|
|
if (!('_send_form' in that)) {
|
|
var form = that._send_form = _document.createElement('form');
|
|
var area = that._send_area = _document.createElement('textarea');
|
|
area.name = 'd';
|
|
form.style.display = 'none';
|
|
form.style.position = 'absolute';
|
|
form.method = 'POST';
|
|
form.enctype = 'application/x-www-form-urlencoded';
|
|
form.acceptCharset = "UTF-8";
|
|
form.appendChild(area);
|
|
_document.body.appendChild(form);
|
|
}
|
|
var form = that._send_form;
|
|
var area = that._send_area;
|
|
var id = 'a' + utils.random_string(8);
|
|
form.target = id;
|
|
form.action = url + '/jsonp_send?i=' + id;
|
|
|
|
var iframe;
|
|
try {
|
|
// ie6 dynamic iframes with target="" support (thanks Chris Lambacher)
|
|
iframe = _document.createElement('<iframe name="'+ id +'">');
|
|
} catch(x) {
|
|
iframe = _document.createElement('iframe');
|
|
iframe.name = id;
|
|
}
|
|
iframe.id = id;
|
|
form.appendChild(iframe);
|
|
iframe.style.display = 'none';
|
|
|
|
try {
|
|
area.value = payload;
|
|
} catch(e) {
|
|
utils.log('Your browser is seriously broken. Go home! ' + e.message);
|
|
}
|
|
form.submit();
|
|
|
|
var completed = function(e) {
|
|
if (!iframe.onerror) return;
|
|
iframe.onreadystatechange = iframe.onerror = iframe.onload = null;
|
|
// Opera mini doesn't like if we GC iframe
|
|
// immediately, thus this timeout.
|
|
utils.delay(500, function() {
|
|
iframe.parentNode.removeChild(iframe);
|
|
iframe = null;
|
|
});
|
|
area.value = '';
|
|
callback();
|
|
};
|
|
iframe.onerror = iframe.onload = completed;
|
|
iframe.onreadystatechange = function(e) {
|
|
if (iframe.readyState == 'complete') completed();
|
|
};
|
|
return completed;
|
|
};
|
|
|
|
var createAjaxSender = function(AjaxObject) {
|
|
return function(url, payload, callback) {
|
|
var xo = new AjaxObject('POST', url + '/xhr_send', payload);
|
|
xo.onfinish = function(status, text) {
|
|
callback(status);
|
|
};
|
|
return function(abort_reason) {
|
|
callback(0, abort_reason);
|
|
};
|
|
};
|
|
};
|
|
// [*] End of lib/trans-sender.js
|
|
|
|
|
|
// [*] Including lib/trans-jsonp-receiver.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// Parts derived from Socket.io:
|
|
// https://github.com/LearnBoost/socket.io/blob/0.6.17/lib/socket.io/transports/jsonp-polling.js
|
|
// and jQuery-JSONP:
|
|
// https://code.google.com/p/jquery-jsonp/source/browse/trunk/core/jquery.jsonp.js
|
|
var jsonPGenericReceiver = function(url, callback) {
|
|
var tref;
|
|
var script = _document.createElement('script');
|
|
var script2; // Opera synchronous load trick.
|
|
var close_script = function(frame) {
|
|
if (script2) {
|
|
script2.parentNode.removeChild(script2);
|
|
script2 = null;
|
|
}
|
|
if (script) {
|
|
clearTimeout(tref);
|
|
script.parentNode.removeChild(script);
|
|
script.onreadystatechange = script.onerror =
|
|
script.onload = script.onclick = null;
|
|
script = null;
|
|
callback(frame);
|
|
callback = null;
|
|
}
|
|
};
|
|
|
|
// IE9 fires 'error' event after orsc or before, in random order.
|
|
var loaded_okay = false;
|
|
var error_timer = null;
|
|
|
|
script.id = 'a' + utils.random_string(8);
|
|
script.src = url;
|
|
script.type = 'text/javascript';
|
|
script.charset = 'UTF-8';
|
|
script.onerror = function(e) {
|
|
if (!error_timer) {
|
|
// Delay firing close_script.
|
|
error_timer = setTimeout(function() {
|
|
if (!loaded_okay) {
|
|
close_script(utils.closeFrame(
|
|
1006,
|
|
"JSONP script loaded abnormally (onerror)"));
|
|
}
|
|
}, 1000);
|
|
}
|
|
};
|
|
script.onload = function(e) {
|
|
close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onload)"));
|
|
};
|
|
|
|
script.onreadystatechange = function(e) {
|
|
if (/loaded|closed/.test(script.readyState)) {
|
|
if (script && script.htmlFor && script.onclick) {
|
|
loaded_okay = true;
|
|
try {
|
|
// In IE, actually execute the script.
|
|
script.onclick();
|
|
} catch (x) {}
|
|
}
|
|
if (script) {
|
|
close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (onreadystatechange)"));
|
|
}
|
|
}
|
|
};
|
|
// IE: event/htmlFor/onclick trick.
|
|
// One can't rely on proper order for onreadystatechange. In order to
|
|
// make sure, set a 'htmlFor' and 'event' properties, so that
|
|
// script code will be installed as 'onclick' handler for the
|
|
// script object. Later, onreadystatechange, manually execute this
|
|
// code. FF and Chrome doesn't work with 'event' and 'htmlFor'
|
|
// set. For reference see:
|
|
// http://jaubourg.net/2010/07/loading-script-as-onclick-handler-of.html
|
|
// Also, read on that about script ordering:
|
|
// http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
|
|
if (typeof script.async === 'undefined' && _document.attachEvent) {
|
|
// According to mozilla docs, in recent browsers script.async defaults
|
|
// to 'true', so we may use it to detect a good browser:
|
|
// https://developer.mozilla.org/en/HTML/Element/script
|
|
if (!/opera/i.test(navigator.userAgent)) {
|
|
// Naively assume we're in IE
|
|
try {
|
|
script.htmlFor = script.id;
|
|
script.event = "onclick";
|
|
} catch (x) {}
|
|
script.async = true;
|
|
} else {
|
|
// Opera, second sync script hack
|
|
script2 = _document.createElement('script');
|
|
script2.text = "try{var a = document.getElementById('"+script.id+"'); if(a)a.onerror();}catch(x){};";
|
|
script.async = script2.async = false;
|
|
}
|
|
}
|
|
if (typeof script.async !== 'undefined') {
|
|
script.async = true;
|
|
}
|
|
|
|
// Fallback mostly for Konqueror - stupid timer, 35 seconds shall be plenty.
|
|
tref = setTimeout(function() {
|
|
close_script(utils.closeFrame(1006, "JSONP script loaded abnormally (timeout)"));
|
|
}, 35000);
|
|
|
|
var head = _document.getElementsByTagName('head')[0];
|
|
head.insertBefore(script, head.firstChild);
|
|
if (script2) {
|
|
head.insertBefore(script2, head.firstChild);
|
|
}
|
|
return close_script;
|
|
};
|
|
// [*] End of lib/trans-jsonp-receiver.js
|
|
|
|
|
|
// [*] Including lib/trans-jsonp-polling.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// The simplest and most robust transport, using the well-know cross
|
|
// domain hack - JSONP. This transport is quite inefficient - one
|
|
// mssage could use up to one http request. But at least it works almost
|
|
// everywhere.
|
|
// Known limitations:
|
|
// o you will get a spinning cursor
|
|
// o for Konqueror a dumb timer is needed to detect errors
|
|
|
|
|
|
var JsonPTransport = SockJS['jsonp-polling'] = function(ri, trans_url) {
|
|
utils.polluteGlobalNamespace();
|
|
var that = this;
|
|
that.ri = ri;
|
|
that.trans_url = trans_url;
|
|
that.send_constructor(jsonPGenericSender);
|
|
that._schedule_recv();
|
|
};
|
|
|
|
// Inheritnace
|
|
JsonPTransport.prototype = new BufferedSender();
|
|
|
|
JsonPTransport.prototype._schedule_recv = function() {
|
|
var that = this;
|
|
var callback = function(data) {
|
|
that._recv_stop = null;
|
|
if (data) {
|
|
// no data - heartbeat;
|
|
if (!that._is_closing) {
|
|
that.ri._didMessage(data);
|
|
}
|
|
}
|
|
// The message can be a close message, and change is_closing state.
|
|
if (!that._is_closing) {
|
|
that._schedule_recv();
|
|
}
|
|
};
|
|
that._recv_stop = jsonPReceiverWrapper(that.trans_url + '/jsonp',
|
|
jsonPGenericReceiver, callback);
|
|
};
|
|
|
|
JsonPTransport.enabled = function() {
|
|
return true;
|
|
};
|
|
|
|
JsonPTransport.need_body = true;
|
|
|
|
|
|
JsonPTransport.prototype.doCleanup = function() {
|
|
var that = this;
|
|
that._is_closing = true;
|
|
if (that._recv_stop) {
|
|
that._recv_stop();
|
|
}
|
|
that.ri = that._recv_stop = null;
|
|
that.send_destructor();
|
|
};
|
|
|
|
|
|
// Abstract away code that handles global namespace pollution.
|
|
var jsonPReceiverWrapper = function(url, constructReceiver, user_callback) {
|
|
var id = 'a' + utils.random_string(6);
|
|
var url_id = url + '?c=' + escape(WPrefix + '.' + id);
|
|
// Callback will be called exactly once.
|
|
var callback = function(frame) {
|
|
delete _window[WPrefix][id];
|
|
user_callback(frame);
|
|
};
|
|
|
|
var close_script = constructReceiver(url_id, callback);
|
|
_window[WPrefix][id] = close_script;
|
|
var stop = function() {
|
|
if (_window[WPrefix][id]) {
|
|
_window[WPrefix][id](utils.closeFrame(1000, "JSONP user aborted read"));
|
|
}
|
|
};
|
|
return stop;
|
|
};
|
|
// [*] End of lib/trans-jsonp-polling.js
|
|
|
|
|
|
// [*] Including lib/trans-xhr.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var AjaxBasedTransport = function() {};
|
|
AjaxBasedTransport.prototype = new BufferedSender();
|
|
|
|
AjaxBasedTransport.prototype.run = function(ri, trans_url,
|
|
url_suffix, Receiver, AjaxObject) {
|
|
var that = this;
|
|
that.ri = ri;
|
|
that.trans_url = trans_url;
|
|
that.send_constructor(createAjaxSender(AjaxObject));
|
|
that.poll = new Polling(ri, Receiver,
|
|
trans_url + url_suffix, AjaxObject);
|
|
};
|
|
|
|
AjaxBasedTransport.prototype.doCleanup = function() {
|
|
var that = this;
|
|
if (that.poll) {
|
|
that.poll.abort();
|
|
that.poll = null;
|
|
}
|
|
};
|
|
|
|
// xhr-streaming
|
|
var XhrStreamingTransport = SockJS['xhr-streaming'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XHRCorsObject);
|
|
};
|
|
|
|
XhrStreamingTransport.prototype = new AjaxBasedTransport();
|
|
|
|
XhrStreamingTransport.enabled = function() {
|
|
// Support for CORS Ajax aka Ajax2? Opera 12 claims CORS but
|
|
// doesn't do streaming.
|
|
return (_window.XMLHttpRequest &&
|
|
'withCredentials' in new XMLHttpRequest() &&
|
|
(!/opera/i.test(navigator.userAgent)));
|
|
};
|
|
XhrStreamingTransport.roundTrips = 2; // preflight, ajax
|
|
|
|
// Safari gets confused when a streaming ajax request is started
|
|
// before onload. This causes the load indicator to spin indefinetely.
|
|
XhrStreamingTransport.need_body = true;
|
|
|
|
|
|
// According to:
|
|
// http://stackoverflow.com/questions/1641507/detect-browser-support-for-cross-domain-xmlhttprequests
|
|
// http://hacks.mozilla.org/2009/07/cross-site-xmlhttprequest-with-cors/
|
|
|
|
|
|
// xdr-streaming
|
|
var XdrStreamingTransport = SockJS['xdr-streaming'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/xhr_streaming', XhrReceiver, utils.XDRObject);
|
|
};
|
|
|
|
XdrStreamingTransport.prototype = new AjaxBasedTransport();
|
|
|
|
XdrStreamingTransport.enabled = function() {
|
|
return !!_window.XDomainRequest;
|
|
};
|
|
XdrStreamingTransport.roundTrips = 2; // preflight, ajax
|
|
|
|
|
|
|
|
// xhr-polling
|
|
var XhrPollingTransport = SockJS['xhr-polling'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRCorsObject);
|
|
};
|
|
|
|
XhrPollingTransport.prototype = new AjaxBasedTransport();
|
|
|
|
XhrPollingTransport.enabled = XhrStreamingTransport.enabled;
|
|
XhrPollingTransport.roundTrips = 2; // preflight, ajax
|
|
|
|
|
|
// xdr-polling
|
|
var XdrPollingTransport = SockJS['xdr-polling'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XDRObject);
|
|
};
|
|
|
|
XdrPollingTransport.prototype = new AjaxBasedTransport();
|
|
|
|
XdrPollingTransport.enabled = XdrStreamingTransport.enabled;
|
|
XdrPollingTransport.roundTrips = 2; // preflight, ajax
|
|
// [*] End of lib/trans-xhr.js
|
|
|
|
|
|
// [*] Including lib/trans-iframe.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// Few cool transports do work only for same-origin. In order to make
|
|
// them working cross-domain we shall use iframe, served form the
|
|
// remote domain. New browsers, have capabilities to communicate with
|
|
// cross domain iframe, using postMessage(). In IE it was implemented
|
|
// from IE 8+, but of course, IE got some details wrong:
|
|
// http://msdn.microsoft.com/en-us/library/cc197015(v=VS.85).aspx
|
|
// http://stevesouders.com/misc/test-postmessage.php
|
|
|
|
var IframeTransport = function() {};
|
|
|
|
IframeTransport.prototype.i_constructor = function(ri, trans_url, base_url) {
|
|
var that = this;
|
|
that.ri = ri;
|
|
that.origin = utils.getOrigin(base_url);
|
|
that.base_url = base_url;
|
|
that.trans_url = trans_url;
|
|
|
|
var iframe_url = base_url + '/iframe.html';
|
|
if (that.ri._options.devel) {
|
|
iframe_url += '?t=' + (+new Date);
|
|
}
|
|
that.window_id = utils.random_string(8);
|
|
iframe_url += '#' + that.window_id;
|
|
|
|
that.iframeObj = utils.createIframe(iframe_url, function(r) {
|
|
that.ri._didClose(1006, "Unable to load an iframe (" + r + ")");
|
|
});
|
|
|
|
that.onmessage_cb = utils.bind(that.onmessage, that);
|
|
utils.attachMessage(that.onmessage_cb);
|
|
};
|
|
|
|
IframeTransport.prototype.doCleanup = function() {
|
|
var that = this;
|
|
if (that.iframeObj) {
|
|
utils.detachMessage(that.onmessage_cb);
|
|
try {
|
|
// When the iframe is not loaded, IE raises an exception
|
|
// on 'contentWindow'.
|
|
if (that.iframeObj.iframe.contentWindow) {
|
|
that.postMessage('c');
|
|
}
|
|
} catch (x) {}
|
|
that.iframeObj.cleanup();
|
|
that.iframeObj = null;
|
|
that.onmessage_cb = that.iframeObj = null;
|
|
}
|
|
};
|
|
|
|
IframeTransport.prototype.onmessage = function(e) {
|
|
var that = this;
|
|
if (e.origin !== that.origin) return;
|
|
var window_id = e.data.slice(0, 8);
|
|
var type = e.data.slice(8, 9);
|
|
var data = e.data.slice(9);
|
|
|
|
if (window_id !== that.window_id) return;
|
|
|
|
switch(type) {
|
|
case 's':
|
|
that.iframeObj.loaded();
|
|
that.postMessage('s', JSON.stringify([SockJS.version, that.protocol, that.trans_url, that.base_url]));
|
|
break;
|
|
case 't':
|
|
that.ri._didMessage(data);
|
|
break;
|
|
}
|
|
};
|
|
|
|
IframeTransport.prototype.postMessage = function(type, data) {
|
|
var that = this;
|
|
that.iframeObj.post(that.window_id + type + (data || ''), that.origin);
|
|
};
|
|
|
|
IframeTransport.prototype.doSend = function (message) {
|
|
this.postMessage('m', message);
|
|
};
|
|
|
|
IframeTransport.enabled = function() {
|
|
// postMessage misbehaves in konqueror 4.6.5 - the messages are delivered with
|
|
// huge delay, or not at all.
|
|
var konqueror = navigator && navigator.userAgent && navigator.userAgent.indexOf('Konqueror') !== -1;
|
|
return ((typeof _window.postMessage === 'function' ||
|
|
typeof _window.postMessage === 'object') && (!konqueror));
|
|
};
|
|
// [*] End of lib/trans-iframe.js
|
|
|
|
|
|
// [*] Including lib/trans-iframe-within.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var curr_window_id;
|
|
|
|
var postMessage = function (type, data) {
|
|
if(parent !== _window) {
|
|
parent.postMessage(curr_window_id + type + (data || ''), '*');
|
|
} else {
|
|
utils.log("Can't postMessage, no parent window.", type, data);
|
|
}
|
|
};
|
|
|
|
var FacadeJS = function() {};
|
|
FacadeJS.prototype._didClose = function (code, reason) {
|
|
postMessage('t', utils.closeFrame(code, reason));
|
|
};
|
|
FacadeJS.prototype._didMessage = function (frame) {
|
|
postMessage('t', frame);
|
|
};
|
|
FacadeJS.prototype._doSend = function (data) {
|
|
this._transport.doSend(data);
|
|
};
|
|
FacadeJS.prototype._doCleanup = function () {
|
|
this._transport.doCleanup();
|
|
};
|
|
|
|
utils.parent_origin = undefined;
|
|
|
|
SockJS.bootstrap_iframe = function() {
|
|
var facade;
|
|
curr_window_id = _document.location.hash.slice(1);
|
|
var onMessage = function(e) {
|
|
if(e.source !== parent) return;
|
|
if(typeof utils.parent_origin === 'undefined')
|
|
utils.parent_origin = e.origin;
|
|
if (e.origin !== utils.parent_origin) return;
|
|
|
|
var window_id = e.data.slice(0, 8);
|
|
var type = e.data.slice(8, 9);
|
|
var data = e.data.slice(9);
|
|
if (window_id !== curr_window_id) return;
|
|
switch(type) {
|
|
case 's':
|
|
var p = JSON.parse(data);
|
|
var version = p[0];
|
|
var protocol = p[1];
|
|
var trans_url = p[2];
|
|
var base_url = p[3];
|
|
if (version !== SockJS.version) {
|
|
utils.log("Incompatibile SockJS! Main site uses:" +
|
|
" \"" + version + "\", the iframe:" +
|
|
" \"" + SockJS.version + "\".");
|
|
}
|
|
if (!utils.flatUrl(trans_url) || !utils.flatUrl(base_url)) {
|
|
utils.log("Only basic urls are supported in SockJS");
|
|
return;
|
|
}
|
|
|
|
if (!utils.isSameOriginUrl(trans_url) ||
|
|
!utils.isSameOriginUrl(base_url)) {
|
|
utils.log("Can't connect to different domain from within an " +
|
|
"iframe. (" + JSON.stringify([_window.location.href, trans_url, base_url]) +
|
|
")");
|
|
return;
|
|
}
|
|
facade = new FacadeJS();
|
|
facade._transport = new FacadeJS[protocol](facade, trans_url, base_url);
|
|
break;
|
|
case 'm':
|
|
facade._doSend(data);
|
|
break;
|
|
case 'c':
|
|
if (facade)
|
|
facade._doCleanup();
|
|
facade = null;
|
|
break;
|
|
}
|
|
};
|
|
|
|
// alert('test ticker');
|
|
// facade = new FacadeJS();
|
|
// facade._transport = new FacadeJS['w-iframe-xhr-polling'](facade, 'http://host.com:9999/ticker/12/basd');
|
|
|
|
utils.attachMessage(onMessage);
|
|
|
|
// Start
|
|
postMessage('s');
|
|
};
|
|
// [*] End of lib/trans-iframe-within.js
|
|
|
|
|
|
// [*] Including lib/info.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var InfoReceiver = function(base_url, AjaxObject) {
|
|
var that = this;
|
|
utils.delay(function(){that.doXhr(base_url, AjaxObject);});
|
|
};
|
|
|
|
InfoReceiver.prototype = new EventEmitter(['finish']);
|
|
|
|
InfoReceiver.prototype.doXhr = function(base_url, AjaxObject) {
|
|
var that = this;
|
|
var t0 = (new Date()).getTime();
|
|
var xo = new AjaxObject('GET', base_url + '/info');
|
|
|
|
var tref = utils.delay(8000,
|
|
function(){xo.ontimeout();});
|
|
|
|
xo.onfinish = function(status, text) {
|
|
clearTimeout(tref);
|
|
tref = null;
|
|
if (status === 200) {
|
|
var rtt = (new Date()).getTime() - t0;
|
|
var info = JSON.parse(text);
|
|
if (typeof info !== 'object') info = {};
|
|
that.emit('finish', info, rtt);
|
|
} else {
|
|
that.emit('finish');
|
|
}
|
|
};
|
|
xo.ontimeout = function() {
|
|
xo.close();
|
|
that.emit('finish');
|
|
};
|
|
};
|
|
|
|
var InfoReceiverIframe = function(base_url) {
|
|
var that = this;
|
|
var go = function() {
|
|
var ifr = new IframeTransport();
|
|
ifr.protocol = 'w-iframe-info-receiver';
|
|
var fun = function(r) {
|
|
if (typeof r === 'string' && r.substr(0,1) === 'm') {
|
|
var d = JSON.parse(r.substr(1));
|
|
var info = d[0], rtt = d[1];
|
|
that.emit('finish', info, rtt);
|
|
} else {
|
|
that.emit('finish');
|
|
}
|
|
ifr.doCleanup();
|
|
ifr = null;
|
|
};
|
|
var mock_ri = {
|
|
_options: {},
|
|
_didClose: fun,
|
|
_didMessage: fun
|
|
};
|
|
ifr.i_constructor(mock_ri, base_url, base_url);
|
|
}
|
|
if(!_document.body) {
|
|
utils.attachEvent('load', go);
|
|
} else {
|
|
go();
|
|
}
|
|
};
|
|
InfoReceiverIframe.prototype = new EventEmitter(['finish']);
|
|
|
|
|
|
var InfoReceiverFake = function() {
|
|
// It may not be possible to do cross domain AJAX to get the info
|
|
// data, for example for IE7. But we want to run JSONP, so let's
|
|
// fake the response, with rtt=2s (rto=6s).
|
|
var that = this;
|
|
utils.delay(function() {
|
|
that.emit('finish', {}, 2000);
|
|
});
|
|
};
|
|
InfoReceiverFake.prototype = new EventEmitter(['finish']);
|
|
|
|
var createInfoReceiver = function(base_url) {
|
|
if (utils.isSameOriginUrl(base_url)) {
|
|
// If, for some reason, we have SockJS locally - there's no
|
|
// need to start up the complex machinery. Just use ajax.
|
|
return new InfoReceiver(base_url, utils.XHRLocalObject);
|
|
}
|
|
switch (utils.isXHRCorsCapable()) {
|
|
case 1:
|
|
return new InfoReceiver(base_url, utils.XHRCorsObject);
|
|
case 2:
|
|
return new InfoReceiver(base_url, utils.XDRObject);
|
|
case 3:
|
|
// Opera
|
|
return new InfoReceiverIframe(base_url);
|
|
default:
|
|
// IE 7
|
|
return new InfoReceiverFake();
|
|
};
|
|
};
|
|
|
|
|
|
var WInfoReceiverIframe = FacadeJS['w-iframe-info-receiver'] = function(ri, _trans_url, base_url) {
|
|
var ir = new InfoReceiver(base_url, utils.XHRLocalObject);
|
|
ir.onfinish = function(info, rtt) {
|
|
ri._didMessage('m'+JSON.stringify([info, rtt]));
|
|
ri._didClose();
|
|
}
|
|
};
|
|
WInfoReceiverIframe.prototype.doCleanup = function() {};
|
|
// [*] End of lib/info.js
|
|
|
|
|
|
// [*] Including lib/trans-iframe-eventsource.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var EventSourceIframeTransport = SockJS['iframe-eventsource'] = function () {
|
|
var that = this;
|
|
that.protocol = 'w-iframe-eventsource';
|
|
that.i_constructor.apply(that, arguments);
|
|
};
|
|
|
|
EventSourceIframeTransport.prototype = new IframeTransport();
|
|
|
|
EventSourceIframeTransport.enabled = function () {
|
|
return ('EventSource' in _window) && IframeTransport.enabled();
|
|
};
|
|
|
|
EventSourceIframeTransport.need_body = true;
|
|
EventSourceIframeTransport.roundTrips = 3; // html, javascript, eventsource
|
|
|
|
|
|
// w-iframe-eventsource
|
|
var EventSourceTransport = FacadeJS['w-iframe-eventsource'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/eventsource', EventSourceReceiver, utils.XHRLocalObject);
|
|
}
|
|
EventSourceTransport.prototype = new AjaxBasedTransport();
|
|
// [*] End of lib/trans-iframe-eventsource.js
|
|
|
|
|
|
// [*] Including lib/trans-iframe-xhr-polling.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var XhrPollingIframeTransport = SockJS['iframe-xhr-polling'] = function () {
|
|
var that = this;
|
|
that.protocol = 'w-iframe-xhr-polling';
|
|
that.i_constructor.apply(that, arguments);
|
|
};
|
|
|
|
XhrPollingIframeTransport.prototype = new IframeTransport();
|
|
|
|
XhrPollingIframeTransport.enabled = function () {
|
|
return _window.XMLHttpRequest && IframeTransport.enabled();
|
|
};
|
|
|
|
XhrPollingIframeTransport.need_body = true;
|
|
XhrPollingIframeTransport.roundTrips = 3; // html, javascript, xhr
|
|
|
|
|
|
// w-iframe-xhr-polling
|
|
var XhrPollingITransport = FacadeJS['w-iframe-xhr-polling'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/xhr', XhrReceiver, utils.XHRLocalObject);
|
|
};
|
|
|
|
XhrPollingITransport.prototype = new AjaxBasedTransport();
|
|
// [*] End of lib/trans-iframe-xhr-polling.js
|
|
|
|
|
|
// [*] Including lib/trans-iframe-htmlfile.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// This transport generally works in any browser, but will cause a
|
|
// spinning cursor to appear in any browser other than IE.
|
|
// We may test this transport in all browsers - why not, but in
|
|
// production it should be only run in IE.
|
|
|
|
var HtmlFileIframeTransport = SockJS['iframe-htmlfile'] = function () {
|
|
var that = this;
|
|
that.protocol = 'w-iframe-htmlfile';
|
|
that.i_constructor.apply(that, arguments);
|
|
};
|
|
|
|
// Inheritance.
|
|
HtmlFileIframeTransport.prototype = new IframeTransport();
|
|
|
|
HtmlFileIframeTransport.enabled = function() {
|
|
return IframeTransport.enabled();
|
|
};
|
|
|
|
HtmlFileIframeTransport.need_body = true;
|
|
HtmlFileIframeTransport.roundTrips = 3; // html, javascript, htmlfile
|
|
|
|
|
|
// w-iframe-htmlfile
|
|
var HtmlFileTransport = FacadeJS['w-iframe-htmlfile'] = function(ri, trans_url) {
|
|
this.run(ri, trans_url, '/htmlfile', HtmlfileReceiver, utils.XHRLocalObject);
|
|
};
|
|
HtmlFileTransport.prototype = new AjaxBasedTransport();
|
|
// [*] End of lib/trans-iframe-htmlfile.js
|
|
|
|
|
|
// [*] Including lib/trans-polling.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var Polling = function(ri, Receiver, recv_url, AjaxObject) {
|
|
var that = this;
|
|
that.ri = ri;
|
|
that.Receiver = Receiver;
|
|
that.recv_url = recv_url;
|
|
that.AjaxObject = AjaxObject;
|
|
that._scheduleRecv();
|
|
};
|
|
|
|
Polling.prototype._scheduleRecv = function() {
|
|
var that = this;
|
|
var poll = that.poll = new that.Receiver(that.recv_url, that.AjaxObject);
|
|
var msg_counter = 0;
|
|
poll.onmessage = function(e) {
|
|
msg_counter += 1;
|
|
that.ri._didMessage(e.data);
|
|
};
|
|
poll.onclose = function(e) {
|
|
that.poll = poll = poll.onmessage = poll.onclose = null;
|
|
if (!that.poll_is_closing) {
|
|
if (e.reason === 'permanent') {
|
|
that.ri._didClose(1006, 'Polling error (' + e.reason + ')');
|
|
} else {
|
|
that._scheduleRecv();
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
Polling.prototype.abort = function() {
|
|
var that = this;
|
|
that.poll_is_closing = true;
|
|
if (that.poll) {
|
|
that.poll.abort();
|
|
}
|
|
};
|
|
// [*] End of lib/trans-polling.js
|
|
|
|
|
|
// [*] Including lib/trans-receiver-eventsource.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var EventSourceReceiver = function(url) {
|
|
var that = this;
|
|
var es = new EventSource(url);
|
|
es.onmessage = function(e) {
|
|
that.dispatchEvent(new SimpleEvent('message',
|
|
{'data': unescape(e.data)}));
|
|
};
|
|
that.es_close = es.onerror = function(e, abort_reason) {
|
|
// ES on reconnection has readyState = 0 or 1.
|
|
// on network error it's CLOSED = 2
|
|
var reason = abort_reason ? 'user' :
|
|
(es.readyState !== 2 ? 'network' : 'permanent');
|
|
that.es_close = es.onmessage = es.onerror = null;
|
|
// EventSource reconnects automatically.
|
|
es.close();
|
|
es = null;
|
|
// Safari and chrome < 15 crash if we close window before
|
|
// waiting for ES cleanup. See:
|
|
// https://code.google.com/p/chromium/issues/detail?id=89155
|
|
utils.delay(200, function() {
|
|
that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
|
|
});
|
|
};
|
|
};
|
|
|
|
EventSourceReceiver.prototype = new REventTarget();
|
|
|
|
EventSourceReceiver.prototype.abort = function() {
|
|
var that = this;
|
|
if (that.es_close) {
|
|
that.es_close({}, true);
|
|
}
|
|
};
|
|
// [*] End of lib/trans-receiver-eventsource.js
|
|
|
|
|
|
// [*] Including lib/trans-receiver-htmlfile.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var _is_ie_htmlfile_capable;
|
|
var isIeHtmlfileCapable = function() {
|
|
if (_is_ie_htmlfile_capable === undefined) {
|
|
if ('ActiveXObject' in _window) {
|
|
try {
|
|
_is_ie_htmlfile_capable = !!new ActiveXObject('htmlfile');
|
|
} catch (x) {}
|
|
} else {
|
|
_is_ie_htmlfile_capable = false;
|
|
}
|
|
}
|
|
return _is_ie_htmlfile_capable;
|
|
};
|
|
|
|
|
|
var HtmlfileReceiver = function(url) {
|
|
var that = this;
|
|
utils.polluteGlobalNamespace();
|
|
|
|
that.id = 'a' + utils.random_string(6, 26);
|
|
url += ((url.indexOf('?') === -1) ? '?' : '&') +
|
|
'c=' + escape(WPrefix + '.' + that.id);
|
|
|
|
var constructor = isIeHtmlfileCapable() ?
|
|
utils.createHtmlfile : utils.createIframe;
|
|
|
|
var iframeObj;
|
|
_window[WPrefix][that.id] = {
|
|
start: function () {
|
|
iframeObj.loaded();
|
|
},
|
|
message: function (data) {
|
|
that.dispatchEvent(new SimpleEvent('message', {'data': data}));
|
|
},
|
|
stop: function () {
|
|
that.iframe_close({}, 'network');
|
|
}
|
|
};
|
|
that.iframe_close = function(e, abort_reason) {
|
|
iframeObj.cleanup();
|
|
that.iframe_close = iframeObj = null;
|
|
delete _window[WPrefix][that.id];
|
|
that.dispatchEvent(new SimpleEvent('close', {reason: abort_reason}));
|
|
};
|
|
iframeObj = constructor(url, function(e) {
|
|
that.iframe_close({}, 'permanent');
|
|
});
|
|
};
|
|
|
|
HtmlfileReceiver.prototype = new REventTarget();
|
|
|
|
HtmlfileReceiver.prototype.abort = function() {
|
|
var that = this;
|
|
if (that.iframe_close) {
|
|
that.iframe_close({}, 'user');
|
|
}
|
|
};
|
|
// [*] End of lib/trans-receiver-htmlfile.js
|
|
|
|
|
|
// [*] Including lib/trans-receiver-xhr.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
var XhrReceiver = function(url, AjaxObject) {
|
|
var that = this;
|
|
var buf_pos = 0;
|
|
|
|
that.xo = new AjaxObject('POST', url, null);
|
|
that.xo.onchunk = function(status, text) {
|
|
if (status !== 200) return;
|
|
while (1) {
|
|
var buf = text.slice(buf_pos);
|
|
var p = buf.indexOf('\n');
|
|
if (p === -1) break;
|
|
buf_pos += p+1;
|
|
var msg = buf.slice(0, p);
|
|
that.dispatchEvent(new SimpleEvent('message', {data: msg}));
|
|
}
|
|
};
|
|
that.xo.onfinish = function(status, text) {
|
|
that.xo.onchunk(status, text);
|
|
that.xo = null;
|
|
var reason = status === 200 ? 'network' : 'permanent';
|
|
that.dispatchEvent(new SimpleEvent('close', {reason: reason}));
|
|
}
|
|
};
|
|
|
|
XhrReceiver.prototype = new REventTarget();
|
|
|
|
XhrReceiver.prototype.abort = function() {
|
|
var that = this;
|
|
if (that.xo) {
|
|
that.xo.close();
|
|
that.dispatchEvent(new SimpleEvent('close', {reason: 'user'}));
|
|
that.xo = null;
|
|
}
|
|
};
|
|
// [*] End of lib/trans-receiver-xhr.js
|
|
|
|
|
|
// [*] Including lib/test-hooks.js
|
|
/*
|
|
* ***** BEGIN LICENSE BLOCK *****
|
|
* Copyright (c) 2011-2012 VMware, Inc.
|
|
*
|
|
* For the license see COPYING.
|
|
* ***** END LICENSE BLOCK *****
|
|
*/
|
|
|
|
// For testing
|
|
SockJS.getUtils = function(){
|
|
return utils;
|
|
};
|
|
|
|
SockJS.getIframeTransport = function(){
|
|
return IframeTransport;
|
|
};
|
|
// [*] End of lib/test-hooks.js
|
|
|
|
return SockJS;
|
|
})();
|
|
if ('_sockjs_onload' in window) setTimeout(_sockjs_onload, 1);
|
|
|
|
// AMD compliance
|
|
if (typeof define === 'function' && define.amd) {
|
|
define('sockjs', [], function(){return SockJS;});
|
|
}
|
|
|
|
if (typeof module === 'object' && module && module.exports) {
|
|
module.exports = SockJS;
|
|
}
|
|
// [*] End of lib/index.js
|
|
|
|
// [*] End of lib/all.js
|
|
|
|
|
|
},{}],41:[function(require,module,exports){
|
|
var traverse = module.exports = function (obj) {
|
|
return new Traverse(obj);
|
|
};
|
|
|
|
function Traverse (obj) {
|
|
this.value = obj;
|
|
}
|
|
|
|
Traverse.prototype.get = function (ps) {
|
|
var node = this.value;
|
|
for (var i = 0; i < ps.length; i ++) {
|
|
var key = ps[i];
|
|
if (!node || !hasOwnProperty.call(node, key)) {
|
|
node = undefined;
|
|
break;
|
|
}
|
|
node = node[key];
|
|
}
|
|
return node;
|
|
};
|
|
|
|
Traverse.prototype.has = function (ps) {
|
|
var node = this.value;
|
|
for (var i = 0; i < ps.length; i ++) {
|
|
var key = ps[i];
|
|
if (!node || !hasOwnProperty.call(node, key)) {
|
|
return false;
|
|
}
|
|
node = node[key];
|
|
}
|
|
return true;
|
|
};
|
|
|
|
Traverse.prototype.set = function (ps, value) {
|
|
var node = this.value;
|
|
for (var i = 0; i < ps.length - 1; i ++) {
|
|
var key = ps[i];
|
|
if (!hasOwnProperty.call(node, key)) node[key] = {};
|
|
node = node[key];
|
|
}
|
|
node[ps[i]] = value;
|
|
return value;
|
|
};
|
|
|
|
Traverse.prototype.map = function (cb) {
|
|
return walk(this.value, cb, true);
|
|
};
|
|
|
|
Traverse.prototype.forEach = function (cb) {
|
|
this.value = walk(this.value, cb, false);
|
|
return this.value;
|
|
};
|
|
|
|
Traverse.prototype.reduce = function (cb, init) {
|
|
var skip = arguments.length === 1;
|
|
var acc = skip ? this.value : init;
|
|
this.forEach(function (x) {
|
|
if (!this.isRoot || !skip) {
|
|
acc = cb.call(this, acc, x);
|
|
}
|
|
});
|
|
return acc;
|
|
};
|
|
|
|
Traverse.prototype.paths = function () {
|
|
var acc = [];
|
|
this.forEach(function (x) {
|
|
acc.push(this.path);
|
|
});
|
|
return acc;
|
|
};
|
|
|
|
Traverse.prototype.nodes = function () {
|
|
var acc = [];
|
|
this.forEach(function (x) {
|
|
acc.push(this.node);
|
|
});
|
|
return acc;
|
|
};
|
|
|
|
Traverse.prototype.clone = function () {
|
|
var parents = [], nodes = [];
|
|
|
|
return (function clone (src) {
|
|
for (var i = 0; i < parents.length; i++) {
|
|
if (parents[i] === src) {
|
|
return nodes[i];
|
|
}
|
|
}
|
|
|
|
if (typeof src === 'object' && src !== null) {
|
|
var dst = copy(src);
|
|
|
|
parents.push(src);
|
|
nodes.push(dst);
|
|
|
|
forEach(objectKeys(src), function (key) {
|
|
dst[key] = clone(src[key]);
|
|
});
|
|
|
|
parents.pop();
|
|
nodes.pop();
|
|
return dst;
|
|
}
|
|
else {
|
|
return src;
|
|
}
|
|
})(this.value);
|
|
};
|
|
|
|
function walk (root, cb, immutable) {
|
|
var path = [];
|
|
var parents = [];
|
|
var alive = true;
|
|
|
|
return (function walker (node_) {
|
|
var node = immutable ? copy(node_) : node_;
|
|
var modifiers = {};
|
|
|
|
var keepGoing = true;
|
|
|
|
var state = {
|
|
node : node,
|
|
node_ : node_,
|
|
path : [].concat(path),
|
|
parent : parents[parents.length - 1],
|
|
parents : parents,
|
|
key : path.slice(-1)[0],
|
|
isRoot : path.length === 0,
|
|
level : path.length,
|
|
circular : null,
|
|
update : function (x, stopHere) {
|
|
if (!state.isRoot) {
|
|
state.parent.node[state.key] = x;
|
|
}
|
|
state.node = x;
|
|
if (stopHere) keepGoing = false;
|
|
},
|
|
'delete' : function (stopHere) {
|
|
delete state.parent.node[state.key];
|
|
if (stopHere) keepGoing = false;
|
|
},
|
|
remove : function (stopHere) {
|
|
if (isArray(state.parent.node)) {
|
|
state.parent.node.splice(state.key, 1);
|
|
}
|
|
else {
|
|
delete state.parent.node[state.key];
|
|
}
|
|
if (stopHere) keepGoing = false;
|
|
},
|
|
keys : null,
|
|
before : function (f) { modifiers.before = f },
|
|
after : function (f) { modifiers.after = f },
|
|
pre : function (f) { modifiers.pre = f },
|
|
post : function (f) { modifiers.post = f },
|
|
stop : function () { alive = false },
|
|
block : function () { keepGoing = false }
|
|
};
|
|
|
|
if (!alive) return state;
|
|
|
|
function updateState() {
|
|
if (typeof state.node === 'object' && state.node !== null) {
|
|
if (!state.keys || state.node_ !== state.node) {
|
|
state.keys = objectKeys(state.node)
|
|
}
|
|
|
|
state.isLeaf = state.keys.length == 0;
|
|
|
|
for (var i = 0; i < parents.length; i++) {
|
|
if (parents[i].node_ === node_) {
|
|
state.circular = parents[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
state.isLeaf = true;
|
|
state.keys = null;
|
|
}
|
|
|
|
state.notLeaf = !state.isLeaf;
|
|
state.notRoot = !state.isRoot;
|
|
}
|
|
|
|
updateState();
|
|
|
|
// use return values to update if defined
|
|
var ret = cb.call(state, state.node);
|
|
if (ret !== undefined && state.update) state.update(ret);
|
|
|
|
if (modifiers.before) modifiers.before.call(state, state.node);
|
|
|
|
if (!keepGoing) return state;
|
|
|
|
if (typeof state.node == 'object'
|
|
&& state.node !== null && !state.circular) {
|
|
parents.push(state);
|
|
|
|
updateState();
|
|
|
|
forEach(state.keys, function (key, i) {
|
|
path.push(key);
|
|
|
|
if (modifiers.pre) modifiers.pre.call(state, state.node[key], key);
|
|
|
|
var child = walker(state.node[key]);
|
|
if (immutable && hasOwnProperty.call(state.node, key)) {
|
|
state.node[key] = child.node;
|
|
}
|
|
|
|
child.isLast = i == state.keys.length - 1;
|
|
child.isFirst = i == 0;
|
|
|
|
if (modifiers.post) modifiers.post.call(state, child);
|
|
|
|
path.pop();
|
|
});
|
|
parents.pop();
|
|
}
|
|
|
|
if (modifiers.after) modifiers.after.call(state, state.node);
|
|
|
|
return state;
|
|
})(root).node;
|
|
}
|
|
|
|
function copy (src) {
|
|
if (typeof src === 'object' && src !== null) {
|
|
var dst;
|
|
|
|
if (isArray(src)) {
|
|
dst = [];
|
|
}
|
|
else if (isDate(src)) {
|
|
dst = new Date(src.getTime ? src.getTime() : src);
|
|
}
|
|
else if (isRegExp(src)) {
|
|
dst = new RegExp(src);
|
|
}
|
|
else if (isError(src)) {
|
|
dst = { message: src.message };
|
|
}
|
|
else if (isBoolean(src)) {
|
|
dst = new Boolean(src);
|
|
}
|
|
else if (isNumber(src)) {
|
|
dst = new Number(src);
|
|
}
|
|
else if (isString(src)) {
|
|
dst = new String(src);
|
|
}
|
|
else if (Object.create && Object.getPrototypeOf) {
|
|
dst = Object.create(Object.getPrototypeOf(src));
|
|
}
|
|
else if (src.constructor === Object) {
|
|
dst = {};
|
|
}
|
|
else {
|
|
var proto =
|
|
(src.constructor && src.constructor.prototype)
|
|
|| src.__proto__
|
|
|| {}
|
|
;
|
|
var T = function () {};
|
|
T.prototype = proto;
|
|
dst = new T;
|
|
}
|
|
|
|
forEach(objectKeys(src), function (key) {
|
|
dst[key] = src[key];
|
|
});
|
|
return dst;
|
|
}
|
|
else return src;
|
|
}
|
|
|
|
var objectKeys = Object.keys || function keys (obj) {
|
|
var res = [];
|
|
for (var key in obj) res.push(key)
|
|
return res;
|
|
};
|
|
|
|
function toS (obj) { return Object.prototype.toString.call(obj) }
|
|
function isDate (obj) { return toS(obj) === '[object Date]' }
|
|
function isRegExp (obj) { return toS(obj) === '[object RegExp]' }
|
|
function isError (obj) { return toS(obj) === '[object Error]' }
|
|
function isBoolean (obj) { return toS(obj) === '[object Boolean]' }
|
|
function isNumber (obj) { return toS(obj) === '[object Number]' }
|
|
function isString (obj) { return toS(obj) === '[object String]' }
|
|
|
|
var isArray = Array.isArray || function isArray (xs) {
|
|
return Object.prototype.toString.call(xs) === '[object Array]';
|
|
};
|
|
|
|
var forEach = function (xs, fn) {
|
|
if (xs.forEach) return xs.forEach(fn)
|
|
else for (var i = 0; i < xs.length; i++) {
|
|
fn(xs[i], i, xs);
|
|
}
|
|
};
|
|
|
|
forEach(objectKeys(Traverse.prototype), function (key) {
|
|
traverse[key] = function (obj) {
|
|
var args = [].slice.call(arguments, 1);
|
|
var t = new Traverse(obj);
|
|
return t[key].apply(t, args);
|
|
};
|
|
});
|
|
|
|
var hasOwnProperty = Object.hasOwnProperty || function (obj, key) {
|
|
return key in obj;
|
|
};
|
|
|
|
},{}],42:[function(require,module,exports){
|
|
var _phantom, _transform, d, descend, dnode, fnwrap, hostname, mkwrap, pageWrap, port, shoe, stream, system, transform, webpage,
|
|
slice = [].slice,
|
|
hasProp = {}.hasOwnProperty;
|
|
|
|
webpage = core_require('webpage');
|
|
|
|
shoe = require('shoe');
|
|
|
|
dnode = require('dnode');
|
|
|
|
system = core_require('system');
|
|
|
|
port = system.args[1];
|
|
|
|
hostname = system.args[2];
|
|
|
|
fnwrap = function(target) {
|
|
return function() {
|
|
return target.apply(this, arguments);
|
|
};
|
|
};
|
|
|
|
descend = function(op, obj, key, val) {
|
|
var cur, keys;
|
|
cur = obj;
|
|
keys = key.split('.');
|
|
while (keys.length > 1) {
|
|
cur = cur[keys.shift()];
|
|
}
|
|
if (op === 'set') {
|
|
cur[keys[0]] = val;
|
|
}
|
|
return cur[keys[0]];
|
|
};
|
|
|
|
_transform = function(val) {
|
|
if (typeof val === "string" && val.indexOf('__phantomCallback__') === 0) {
|
|
val = 'return ' + val.replace('__phantomCallback__', '');
|
|
val = phantom.callback(new Function(val)());
|
|
}
|
|
return val;
|
|
};
|
|
|
|
transform = function(obj) {
|
|
var key;
|
|
if (typeof obj === "string") {
|
|
_transform(obj);
|
|
} else if (typeof obj === "object") {
|
|
for (key in obj) {
|
|
if (typeof obj[key] === "object") {
|
|
transform(obj[key]);
|
|
} else {
|
|
obj[key] = _transform(obj[key]);
|
|
}
|
|
}
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
mkwrap = function(src, pass, special) {
|
|
var fn1, j, k, len, obj;
|
|
if (pass == null) {
|
|
pass = [];
|
|
}
|
|
if (special == null) {
|
|
special = {};
|
|
}
|
|
obj = {
|
|
set: function(key, val, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
if (typeof val === "function") {
|
|
val = fnwrap(val);
|
|
}
|
|
val = transform(val);
|
|
return cb(descend('set', src, key, val));
|
|
},
|
|
get: function(key, cb) {
|
|
return cb(descend('get', src, key));
|
|
}
|
|
};
|
|
fn1 = function(k) {
|
|
return obj[k] = function() {
|
|
var arg, args, i, l, len1;
|
|
args = 1 <= arguments.length ? slice.call(arguments, 0) : [];
|
|
for (i = l = 0, len1 = args.length; l < len1; i = ++l) {
|
|
arg = args[i];
|
|
if (typeof arg === 'function') {
|
|
args[i] = fnwrap(arg);
|
|
}
|
|
}
|
|
return src[k].apply(src, args);
|
|
};
|
|
};
|
|
for (j = 0, len = pass.length; j < len; j++) {
|
|
k = pass[j];
|
|
fn1(k);
|
|
}
|
|
for (k in special) {
|
|
if (!hasProp.call(special, k)) continue;
|
|
obj[k] = special[k];
|
|
}
|
|
return obj;
|
|
};
|
|
|
|
pageWrap = function(page) {
|
|
return mkwrap(page, ['open', 'close', 'includeJs', 'sendEvent', 'release', 'uploadFile', 'goBack', 'goForward', 'reload', 'switchToFrame', 'switchToMainFrame', 'switchToParentFrame', 'switchToFocusedFrame'], {
|
|
onPageCreated: function(cb) {
|
|
if (cb == null) {
|
|
cb = (function() {});
|
|
}
|
|
return page.onPageCreated = function(newpage) {
|
|
return cb(pageWrap(newpage));
|
|
};
|
|
},
|
|
onConsoleMessage: function(fn, cb) {
|
|
if (cb == null) {
|
|
cb = (function() {});
|
|
}
|
|
page.onConsoleMessage = function() {
|
|
return fn.apply(this, arguments);
|
|
};
|
|
return cb();
|
|
},
|
|
onError: function(fn, cb) {
|
|
if (cb == null) {
|
|
cb = (function() {});
|
|
}
|
|
page.onError = function() {
|
|
return fn.apply(this, arguments);
|
|
};
|
|
return cb();
|
|
},
|
|
onResourceRequested: function() {
|
|
var args, cb, fn;
|
|
fn = arguments[0], cb = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
|
|
if (cb == null) {
|
|
cb = (function() {});
|
|
}
|
|
return page.onResourceRequested = function() {
|
|
var argumentsWithExtraArgs;
|
|
argumentsWithExtraArgs = [].slice.apply(arguments).concat(args);
|
|
fn = fn.replace(/function.*\(/, 'function x(');
|
|
eval(fn);
|
|
x.apply(this, argumentsWithExtraArgs);
|
|
return cb.apply(this, argumentsWithExtraArgs);
|
|
};
|
|
},
|
|
injectJs: function(js, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(page.injectJs(js));
|
|
},
|
|
evaluate: function() {
|
|
var args, cb, fn;
|
|
fn = arguments[0], cb = arguments[1], args = 3 <= arguments.length ? slice.call(arguments, 2) : [];
|
|
if (cb == null) {
|
|
cb = (function() {});
|
|
}
|
|
return cb(page.evaluate.apply(page, [fn].concat(args)));
|
|
},
|
|
render: function(file, opts, cb) {
|
|
if (opts == null) {
|
|
opts = {};
|
|
}
|
|
if (cb == null) {
|
|
if (typeof opts === 'function') {
|
|
cb = opts;
|
|
opts = {};
|
|
} else {
|
|
cb = function() {};
|
|
}
|
|
}
|
|
page.render(file, opts);
|
|
return cb();
|
|
},
|
|
getContent: function(cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(page.content);
|
|
},
|
|
getCookies: function(cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(page.cookies);
|
|
},
|
|
renderBase64: function(type, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(page.renderBase64(type));
|
|
},
|
|
setHeaders: function(headers, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
page.customHeaders = headers;
|
|
return cb();
|
|
},
|
|
setContent: function(html, url, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
page.onLoadFinished = function(status) {
|
|
page.onLoadFinished = null;
|
|
return cb(status);
|
|
};
|
|
return page.setContent(html, url);
|
|
},
|
|
setViewportSize: function(width, height, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
page.viewportSize = {
|
|
width: width,
|
|
height: height
|
|
};
|
|
return cb();
|
|
},
|
|
setPaperSize: function(options, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
page.paperSize = transform(options);
|
|
return cb();
|
|
},
|
|
setZoomFactor: function(zoomFactor, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
page.zoomFactor = zoomFactor;
|
|
return cb();
|
|
},
|
|
setFileOnPicker: function(fileName, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return page.onFilePicker = function() {
|
|
cb.apply(this, arguments);
|
|
return fileName;
|
|
};
|
|
}
|
|
});
|
|
};
|
|
|
|
_phantom = mkwrap(phantom, ['exit'], {
|
|
injectJs: function(js, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(phantom.injectJs(js));
|
|
},
|
|
getCookies: function(cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(phantom.cookies);
|
|
},
|
|
addCookie: function(cookie, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(phantom.addCookie(cookie));
|
|
},
|
|
clearCookies: function(cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(phantom.clearCookies());
|
|
},
|
|
createPage: function(cb) {
|
|
return cb(pageWrap(webpage.create()));
|
|
},
|
|
setProxy: function(host, port, type, user, password, cb) {
|
|
if (cb == null) {
|
|
cb = function() {};
|
|
}
|
|
return cb(phantom.setProxy(host, port, type, user, password));
|
|
}
|
|
});
|
|
|
|
stream = shoe('http://' + hostname + ':' + port + '/dnode');
|
|
|
|
d = dnode(_phantom);
|
|
|
|
d.pipe(stream);
|
|
|
|
stream.pipe(d);
|
|
|
|
|
|
|
|
},{"dnode":29,"shoe":39}]},{},[42]);
|