socketioMEANseed/server/node_modules/depd/index.js
server/node_modules/depd/index.jsRaw
1/*!
2 * depd
3 * Copyright(c) 2014 Douglas Christopher Wilson
4 * MIT Licensed
5 */
6
7/**
8 * Module dependencies.
9 */
10
11var callSiteToString = require('./lib/compat').callSiteToString
12var EventEmitter = require('events').EventEmitter
13var relative = require('path').relative
14
15/**
16 * Module exports.
17 */
18
19module.exports = depd
20
21/**
22 * Get the path to base files on.
23 */
24
25var basePath = process.cwd()
26
27/**
28 * Get listener count on event emitter.
29 */
30
31/*istanbul ignore next*/
32var eventListenerCount = EventEmitter.listenerCount
33 || function (emitter, type) { return emitter.listeners(type).length }
34
35/**
36 * Determine if namespace is contained in the string.
37 */
38
39function containsNamespace(str, namespace) {
40 var val = str.split(/[ ,]+/)
41
42 namespace = String(namespace).toLowerCase()
43
44 for (var i = 0 ; i < val.length; i++) {
45 if (!(str = val[i])) continue;
46
47 // namespace contained
48 if (str === '*' || str.toLowerCase() === namespace) {
49 return true
50 }
51 }
52
53 return false
54}
55
56/**
57 * Convert a data descriptor to accessor descriptor.
58 */
59
60function convertDataDescriptorToAccessor(obj, prop, message) {
61 var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
62 var value = descriptor.value
63
64 descriptor.get = function getter() { return value }
65
66 if (descriptor.writable) {
67 descriptor.set = function setter(val) { return value = val }
68 }
69
70 delete descriptor.value
71 delete descriptor.writable
72
73 Object.defineProperty(obj, prop, descriptor)
74
75 return descriptor
76}
77
78/**
79 * Create arguments string to keep arity.
80 */
81
82function createArgumentsString(arity) {
83 var str = ''
84
85 for (var i = 0; i < arity; i++) {
86 str += ', arg' + i
87 }
88
89 return str.substr(2)
90}
91
92/**
93 * Create stack string from stack.
94 */
95
96function createStackString(stack) {
97 var str = this.name + ': ' + this.namespace
98
99 if (this.message) {
100 str += ' deprecated ' + this.message
101 }
102
103 for (var i = 0; i < stack.length; i++) {
104 str += '\n at ' + callSiteToString(stack[i])
105 }
106
107 return str
108}
109
110/**
111 * Create deprecate for namespace in caller.
112 */
113
114function depd(namespace) {
115 if (!namespace) {
116 throw new TypeError('argument namespace is required')
117 }
118
119 var stack = getStack()
120 var site = callSiteLocation(stack[1])
121 var file = site[0]
122
123 function deprecate(message) {
124 // call to self as log
125 log.call(deprecate, message)
126 }
127
128 deprecate._file = file
129 deprecate._ignored = isignored(namespace)
130 deprecate._namespace = namespace
131 deprecate._traced = istraced(namespace)
132 deprecate._warned = Object.create(null)
133
134 deprecate.function = wrapfunction
135 deprecate.property = wrapproperty
136
137 return deprecate
138}
139
140/**
141 * Determine if namespace is ignored.
142 */
143
144function isignored(namespace) {
145 /* istanbul ignore next: tested in a child processs */
146 if (process.noDeprecation) {
147 // --no-deprecation support
148 return true
149 }
150
151 var str = process.env.NO_DEPRECATION || ''
152
153 // namespace ignored
154 return containsNamespace(str, namespace)
155}
156
157/**
158 * Determine if namespace is traced.
159 */
160
161function istraced(namespace) {
162 /* istanbul ignore next: tested in a child processs */
163 if (process.traceDeprecation) {
164 // --trace-deprecation support
165 return true
166 }
167
168 var str = process.env.TRACE_DEPRECATION || ''
169
170 // namespace traced
171 return containsNamespace(str, namespace)
172}
173
174/**
175 * Display deprecation message.
176 */
177
178function log(message, site) {
179 var haslisteners = eventListenerCount(process, 'deprecation') !== 0
180
181 // abort early if no destination
182 if (!haslisteners && this._ignored) {
183 return
184 }
185
186 var caller
187 var callFile
188 var callSite
189 var i = 0
190 var seen = false
191 var stack = getStack()
192 var file = this._file
193
194 if (site) {
195 // provided site
196 callSite = callSiteLocation(stack[1])
197 callSite.name = site.name
198 file = callSite[0]
199 } else {
200 // get call site
201 i = 2
202 site = callSiteLocation(stack[i])
203 callSite = site
204 }
205
206 // get caller of deprecated thing in relation to file
207 for (; i < stack.length; i++) {
208 caller = callSiteLocation(stack[i])
209 callFile = caller[0]
210
211 if (callFile === file) {
212 seen = true
213 } else if (callFile === this._file) {
214 file = this._file
215 } else if (seen) {
216 break
217 }
218 }
219
220 var key = caller
221 ? site.join(':') + '__' + caller.join(':')
222 : undefined
223
224 if (key !== undefined && key in this._warned) {
225 // already warned
226 return
227 }
228
229 this._warned[key] = true
230
231 // generate automatic message from call site
232 if (!message) {
233 message = callSite === site || !callSite.name
234 ? defaultMessage(site)
235 : defaultMessage(callSite)
236 }
237
238 // emit deprecation if listeners exist
239 if (haslisteners) {
240 var err = DeprecationError(this._namespace, message, stack.slice(i))
241 process.emit('deprecation', err)
242 return
243 }
244
245 // format and write message
246 var format = process.stderr.isTTY
247 ? formatColor
248 : formatPlain
249 var msg = format.call(this, message, caller, stack.slice(i))
250 process.stderr.write(msg + '\n', 'utf8')
251
252 return
253}
254
255/**
256 * Get call site location as array.
257 */
258
259function callSiteLocation(callSite) {
260 var file = callSite.getFileName() || '<anonymous>'
261 var line = callSite.getLineNumber()
262 var colm = callSite.getColumnNumber()
263
264 if (callSite.isEval()) {
265 file = callSite.getEvalOrigin() + ', ' + file
266 }
267
268 var site = [file, line, colm]
269
270 site.callSite = callSite
271 site.name = callSite.getFunctionName()
272
273 return site
274}
275
276/**
277 * Generate a default message from the site.
278 */
279
280function defaultMessage(site) {
281 var callSite = site.callSite
282 var funcName = site.name
283
284 // make useful anonymous name
285 if (!funcName) {
286 funcName = '<anonymous@' + formatLocation(site) + '>'
287 }
288
289 var context = callSite.getThis()
290 var typeName = context && callSite.getTypeName()
291
292 // ignore useless type name
293 if (typeName === 'Object') {
294 typeName = undefined
295 }
296
297 // make useful type name
298 if (typeName === 'Function') {
299 typeName = context.name || typeName
300 }
301
302 return typeName && callSite.getMethodName()
303 ? typeName + '.' + funcName
304 : funcName
305}
306
307/**
308 * Format deprecation message without color.
309 */
310
311function formatPlain(msg, caller, stack) {
312 var timestamp = new Date().toUTCString()
313
314 var formatted = timestamp
315 + ' ' + this._namespace
316 + ' deprecated ' + msg
317
318 // add stack trace
319 if (this._traced) {
320 for (var i = 0; i < stack.length; i++) {
321 formatted += '\n at ' + callSiteToString(stack[i])
322 }
323
324 return formatted
325 }
326
327 if (caller) {
328 formatted += ' at ' + formatLocation(caller)
329 }
330
331 return formatted
332}
333
334/**
335 * Format deprecation message with color.
336 */
337
338function formatColor(msg, caller, stack) {
339 var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' // bold cyan
340 + ' \x1b[33;1mdeprecated\x1b[22;39m' // bold yellow
341 + ' \x1b[0m' + msg + '\x1b[39m' // reset
342
343 // add stack trace
344 if (this._traced) {
345 for (var i = 0; i < stack.length; i++) {
346 formatted += '\n \x1b[36mat ' + callSiteToString(stack[i]) + '\x1b[39m' // cyan
347 }
348
349 return formatted
350 }
351
352 if (caller) {
353 formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
354 }
355
356 return formatted
357}
358
359/**
360 * Format call site location.
361 */
362
363function formatLocation(callSite) {
364 return relative(basePath, callSite[0])
365 + ':' + callSite[1]
366 + ':' + callSite[2]
367}
368
369/**
370 * Get the stack as array of call sites.
371 */
372
373function getStack() {
374 var limit = Error.stackTraceLimit
375 var obj = {}
376 var prep = Error.prepareStackTrace
377
378 Error.prepareStackTrace = prepareObjectStackTrace
379 Error.stackTraceLimit = Math.max(10, limit)
380
381 // capture the stack
382 Error.captureStackTrace(obj)
383
384 // slice this function off the top
385 var stack = obj.stack.slice(1)
386
387 Error.prepareStackTrace = prep
388 Error.stackTraceLimit = limit
389
390 return stack
391}
392
393/**
394 * Capture call site stack from v8.
395 */
396
397function prepareObjectStackTrace(obj, stack) {
398 return stack
399}
400
401/**
402 * Return a wrapped function in a deprecation message.
403 */
404
405function wrapfunction(fn, message) {
406 if (typeof fn !== 'function') {
407 throw new TypeError('argument fn must be a function')
408 }
409
410 var args = createArgumentsString(fn.length)
411 var deprecate = this
412 var stack = getStack()
413 var site = callSiteLocation(stack[1])
414
415 site.name = fn.name
416
417 var deprecatedfn = eval('(function (' + args + ') {\n'
418 + '"use strict"\n'
419 + 'log.call(deprecate, message, site)\n'
420 + 'return fn.apply(this, arguments)\n'
421 + '})')
422
423 return deprecatedfn
424}
425
426/**
427 * Wrap property in a deprecation message.
428 */
429
430function wrapproperty(obj, prop, message) {
431 if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
432 throw new TypeError('argument obj must be object')
433 }
434
435 var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
436
437 if (!descriptor) {
438 throw new TypeError('must call property on owner object')
439 }
440
441 if (!descriptor.configurable) {
442 throw new TypeError('property must be configurable')
443 }
444
445 var deprecate = this
446 var stack = getStack()
447 var site = callSiteLocation(stack[1])
448
449 // set site name
450 site.name = prop
451
452 // convert data descriptor
453 if ('value' in descriptor) {
454 descriptor = convertDataDescriptorToAccessor(obj, prop, message)
455 }
456
457 var get = descriptor.get
458 var set = descriptor.set
459
460 // wrap getter
461 if (typeof get === 'function') {
462 descriptor.get = function getter() {
463 log.call(deprecate, message, site)
464 return get.apply(this, arguments)
465 }
466 }
467
468 // wrap setter
469 if (typeof set === 'function') {
470 descriptor.set = function setter() {
471 log.call(deprecate, message, site)
472 return set.apply(this, arguments)
473 }
474 }
475
476 Object.defineProperty(obj, prop, descriptor)
477}
478
479/**
480 * Create DeprecationError for deprecation
481 */
482
483function DeprecationError(namespace, message, stack) {
484 var error = new Error()
485 var stackString
486
487 Object.defineProperty(error, 'constructor', {
488 value: DeprecationError
489 })
490
491 Object.defineProperty(error, 'message', {
492 configurable: true,
493 enumerable: false,
494 value: message,
495 writable: true
496 })
497
498 Object.defineProperty(error, 'name', {
499 enumerable: false,
500 configurable: true,
501 value: 'DeprecationError',
502 writable: true
503 })
504
505 Object.defineProperty(error, 'namespace', {
506 configurable: true,
507 enumerable: false,
508 value: namespace,
509 writable: true
510 })
511
512 Object.defineProperty(error, 'stack', {
513 configurable: true,
514 enumerable: false,
515 get: function () {
516 if (stackString !== undefined) {
517 return stackString
518 }
519
520 // prepare stack trace
521 return stackString = createStackString.call(this, stack)
522 },
523 set: function setter(val) {
524 stackString = val
525 }
526 })
527
528 return error
529}