ddv-restful-api
Version:
ddv-restful-api
490 lines (410 loc) • 13.1 kB
JavaScript
// 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 spliceOne
function EventEmitter () {
EventEmitter.init.call(this)
}
module.exports = EventEmitter
// Backwards-compat with node 0.10.x
EventEmitter.EventEmitter = EventEmitter
EventEmitter.usingDomains = false
EventEmitter.prototype._events = undefined
EventEmitter.prototype._eventsCount = 0
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.
var defaultMaxListeners = 10
var errors
function lazyErrors () {
if (errors === undefined) {
errors = {}
}
return errors
}
function checkListener (listener) {
if (typeof listener !== 'function') {
const errors = lazyErrors()
throw new errors.ERR_INVALID_ARG_TYPE('listener', 'Function', listener)
}
}
Object.defineProperty(EventEmitter, 'defaultMaxListeners', {
enumerable: true,
get: function () {
return defaultMaxListeners
},
set: function (arg) {
if (typeof arg !== 'number' || arg < 0 || Number.isNaN(arg)) {
const errors = lazyErrors()
throw new errors.ERR_OUT_OF_RANGE('defaultMaxListeners',
'a non-negative number',
arg)
}
defaultMaxListeners = arg
}
})
EventEmitter.init = function () {
if (this._events === undefined ||
this._events === Object.getPrototypeOf(this)._events) {
this._events = Object.create(null)
this._eventsCount = 0
}
this._maxListeners = this._maxListeners || undefined
}
// 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 setMaxListeners (n) {
if (typeof n !== 'number' || n < 0 || Number.isNaN(n)) {
const errors = lazyErrors()
throw new errors.ERR_OUT_OF_RANGE('n', 'a non-negative number', n)
}
this._maxListeners = n
return this
}
function _getMaxListeners (that) {
if (that._maxListeners === undefined) {
return EventEmitter.defaultMaxListeners
}
return that._maxListeners
}
EventEmitter.prototype.getMaxListeners = function getMaxListeners () {
return _getMaxListeners(this)
}
// Returns the length and line number of the first sequence of `a` that fully
// appears in `b` with a length of at least 4.
function identicalSequenceRange (a, b) {
for (var i = 0; i < a.length - 3; i++) {
// Find the first entry of b that matches the current entry of a.
const pos = b.indexOf(a[i])
if (pos !== -1) {
const rest = b.length - pos
if (rest > 3) {
let len = 1
const maxLen = Math.min(a.length - i, rest)
// Count the number of consecutive entries.
while (maxLen > len && a[i + len] === b[pos + len]) {
len++
}
if (len > 3) {
return [len, i]
}
}
}
}
return [0, 0]
}
function enhanceStackTrace (err, own) {
const sep = '\nEmitted \'error\' event at:\n'
const errStack = err.stack.split('\n').slice(1)
const ownStack = own.stack.split('\n').slice(1)
const [len, off] = identicalSequenceRange(ownStack, errStack)
if (len > 0) {
ownStack.splice(off + 1, len - 2,
' [... lines matching original stack trace ...]')
}
// Do this last, because it is the only operation with side effects.
err.stack = err.stack + sep + ownStack.join('\n')
}
EventEmitter.prototype.emit = function emit (type, ...args) {
let doError = (type === 'error')
const events = this._events
if (events !== undefined) {
doError = (doError && events.error === undefined)
} else if (!doError) {
return false
}
// If there is no 'error' event listener then throw.
if (doError) {
let er
if (args.length > 0) {
er = args[0]
}
throw er // Unhandled 'error' event
}
const handler = events[type]
if (handler === undefined) {
return false
}
if (typeof handler === 'function') {
Reflect.apply(handler, this, args)
} else {
const len = handler.length
const listeners = arrayClone(handler, len)
for (var i = 0; i < len; ++i) {
Reflect.apply(listeners[i], this, args)
}
}
return true
}
function _addListener (target, type, listener, prepend) {
var m
var events
var existing
checkListener(listener)
events = target._events
if (events === undefined) {
events = target._events = Object.create(null)
target._eventsCount = 0
} else {
// To avoid recursion in the case that type === "newListener"! Before
// adding it to the listeners, first emit "newListener".
if (events.newListener !== undefined) {
target.emit('newListener', type,
listener.listener ? listener.listener : listener)
// Re-assign `events` because a newListener handler could have caused the
// this._events to be assigned to a new object
events = target._events
}
existing = events[type]
}
if (existing === undefined) {
// Optimize the case of one listener. Don't need the extra array object.
events[type] = listener
++target._eventsCount
} else {
if (typeof existing === 'function') {
// Adding the second element, need to change to array.
existing = events[type] =
prepend ? [listener, existing] : [existing, listener]
// If we've already got an array, just append.
} else if (prepend) {
existing.unshift(listener)
} else {
existing.push(listener)
}
// Check for listener leak
m = _getMaxListeners(target)
if (m > 0 && existing.length > m && !existing.warned) {
existing.warned = true
// No error code for this since it is a Warning
// eslint-disable-next-line no-restricted-syntax
const w = new Error('Possible EventEmitter memory leak detected. ' +
`${existing.length} ${String(type)} listeners ` +
'added. Use emitter.setMaxListeners() to ' +
'increase limit')
w.name = 'MaxListenersExceededWarning'
w.emitter = target
w.type = type
w.count = existing.length
process.emitWarning(w)
}
}
return target
}
EventEmitter.prototype.addListener = function addListener (type, listener) {
return _addListener(this, type, listener, false)
}
EventEmitter.prototype.on = EventEmitter.prototype.addListener
EventEmitter.prototype.prependListener =
function prependListener (type, listener) {
return _addListener(this, type, listener, true)
}
function onceWrapper (...args) {
if (!this.fired) {
this.target.removeListener(this.type, this.wrapFn)
this.fired = true
Reflect.apply(this.listener, this.target, args)
}
}
function _onceWrap (target, type, listener) {
var state = {
fired: false,
wrapFn: undefined,
target,
type,
listener
}
var wrapped = onceWrapper.bind(state)
wrapped.listener = listener
state.wrapFn = wrapped
return wrapped
}
EventEmitter.prototype.once = function once (type, listener) {
checkListener(listener)
this.on(type, _onceWrap(this, type, listener))
return this
}
EventEmitter.prototype.prependOnceListener =
function prependOnceListener (type, listener) {
checkListener(listener)
this.prependListener(type, _onceWrap(this, type, listener))
return this
}
// Emits a 'removeListener' event if and only if the listener was removed.
EventEmitter.prototype.removeListener =
function removeListener (type, listener) {
var list, events, position, i, originalListener
checkListener(listener)
events = this._events
if (events === undefined) {
return this
}
list = events[type]
if (list === undefined) {
return this
}
if (list === listener || list.listener === listener) {
if (--this._eventsCount === 0) {
this._events = Object.create(null)
} else {
delete events[type]
if (events.removeListener) {
this.emit('removeListener', type, list.listener || listener)
}
}
} else if (typeof list !== 'function') {
position = -1
for (i = list.length - 1; i >= 0; i--) {
if (list[i] === listener || list[i].listener === listener) {
originalListener = list[i].listener
position = i
break
}
}
if (position < 0) {
return this
}
if (position === 0) {
list.shift()
} else {
if (spliceOne === undefined) {
spliceOne = function spliceOne (list, index) {
for (; index + 1 < list.length; index++)
{list[index] = list[index + 1];}
list.pop()
}
}
spliceOne(list, position)
}
if (list.length === 1) {
events[type] = list[0]
}
if (events.removeListener !== undefined) {
this.emit('removeListener', type, originalListener || listener)
}
}
return this
}
EventEmitter.prototype.off = EventEmitter.prototype.removeListener
EventEmitter.prototype.removeAllListeners =
function removeAllListeners (type) {
var listeners, events, i
events = this._events
if (events === undefined) {
return this
}
// not listening for removeListener, no need to emit
if (events.removeListener === undefined) {
if (arguments.length === 0) {
this._events = Object.create(null)
this._eventsCount = 0
} else if (events[type] !== undefined) {
if (--this._eventsCount === 0) {
this._events = Object.create(null)
} else {
delete events[type]
}
}
return this
}
// Emit removeListener for all listeners on all events
if (arguments.length === 0) {
var keys = Object.keys(events)
var key
for (i = 0; i < keys.length; ++i) {
key = keys[i]
if (key === 'removeListener') continue
this.removeAllListeners(key)
}
this.removeAllListeners('removeListener')
this._events = Object.create(null)
this._eventsCount = 0
return this
}
listeners = events[type]
if (typeof listeners === 'function') {
this.removeListener(type, listeners)
} else if (listeners !== undefined) {
// LIFO order
for (i = listeners.length - 1; i >= 0; i--) {
this.removeListener(type, listeners[i])
}
}
return this
}
function _listeners (target, type, unwrap) {
const events = target._events
if (events === undefined) {
return []
}
const evlistener = events[type]
if (evlistener === undefined) {
return []
}
if (typeof evlistener === 'function') {
return unwrap ? [evlistener.listener || evlistener] : [evlistener]
}
return unwrap
? unwrapListeners(evlistener) : arrayClone(evlistener, evlistener.length)
}
EventEmitter.prototype.listeners = function listeners (type) {
return _listeners(this, type, true)
}
EventEmitter.prototype.rawListeners = function rawListeners (type) {
return _listeners(this, type, false)
}
EventEmitter.listenerCount = function (emitter, type) {
if (typeof emitter.listenerCount === 'function') {
return emitter.listenerCount(type)
} else {
return listenerCount.call(emitter, type)
}
}
EventEmitter.prototype.listenerCount = listenerCount
function listenerCount (type) {
const events = this._events
if (events !== undefined) {
const evlistener = events[type]
if (typeof evlistener === 'function') {
return 1
} else if (evlistener !== undefined) {
return evlistener.length
}
}
return 0
}
EventEmitter.prototype.eventNames = function eventNames () {
return this._eventsCount > 0 ? Reflect.ownKeys(this._events) : []
}
function arrayClone (arr, n) {
var copy = new Array(n)
for (var i = 0; i < n; ++i) {
copy[i] = arr[i]
}
return copy
}
function unwrapListeners (arr) {
const ret = new Array(arr.length)
for (var i = 0; i < ret.length; ++i) {
ret[i] = arr[i].listener || arr[i]
}
return ret
}