newrelic 4.8.1 → 4.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/NEWS.md CHANGED
@@ -1,3 +1,56 @@
1
+ ### 4.9.0 (2018-10-01):
2
+
3
+ * Updated DT payload creation to use `primary_application_id` from connect response.
4
+
5
+ * Added protection against functions with modified prototypes in `shim.applySegment`.
6
+
7
+ * Replaced SQL ID hash generation algorithm with SHA1 instead of MD5 to allow usage
8
+ in FIPS compliant environments.
9
+
10
+ * Leveraged 16 hex digits for creation of SQL ID.
11
+
12
+ * Fixed `codec.decode()` callback bug that would re-call a callback with an error
13
+ thrown within the callback.
14
+
15
+ * Added `superagent` as built-in instrumentation.
16
+
17
+ This instrumentation just maintains transaction state when using the `superagent`
18
+ module to make HTTP requests with either callbacks or promises.
19
+
20
+ * Updated `noticeError` API method to be partially functional in High Security Mode.
21
+
22
+ In HSM, any custom attributes will be ignored, but the error will still be tracked.
23
+ This brings the Node agent in line with the behavior of other language agents.
24
+
25
+ * Upgraded ejs module to get rid of Github security warnings. The ejs module was
26
+ only used for tests and not in main agent code.
27
+
28
+ * Fixed bug requiring Cross Application Tracing (CAT) to be enabled for Distributed
29
+ Tracing (DT) `createDistributedTracePayload` and `acceptDistributedTracePayload`
30
+ APIs to function. DT configuration will no longer consider CAT configuration.
31
+
32
+ * Changes DT payload configuration log messages to debug level as it is not uncommon
33
+ for calls to occur before server configuration has been retrieved.
34
+
35
+ * Converted `net` instrumentation to use shim api.
36
+
37
+ * Converted child_process instrumentation to newer shim style.
38
+
39
+ * Converted Timers instrumentation to newer shim style.
40
+
41
+ * Fixed bug in wrap() that would fail to wrap callbacks if the callback index was 0.
42
+
43
+ * Added `PromiseShim` class for instrumenting promise libraries.
44
+
45
+ * Support for setting `transaction_tracer.transaction_threshold` to 0 has been added.
46
+
47
+ * The agent now respects `NEW_RELIC_TRACER_THRESHOLD`.
48
+
49
+ Previously, this environment variable was stored as a string. The environment
50
+ variable is now stored as a float.
51
+
52
+ * Converted zlib instrumentation to use shim API.
53
+
1
54
  ### 4.8.1 (2018-08-27):
2
55
 
3
56
  * Converted File System instrumentation to use newer shim style.
package/api.js CHANGED
@@ -397,29 +397,35 @@ API.prototype.setIgnoreTransaction = function setIgnoreTransaction(ignored) {
397
397
  * Optional. Any custom attributes to be displayed in the New Relic UI.
398
398
  */
399
399
  API.prototype.noticeError = function noticeError(error, customAttributes) {
400
- var metric = this.agent.metrics.getOrCreateMetric(
400
+ const metric = this.agent.metrics.getOrCreateMetric(
401
401
  NAMES.SUPPORTABILITY.API + '/noticeError'
402
402
  )
403
403
  metric.incrementCallCount()
404
404
 
405
- // If high security mode is on, noticeError is disabled.
406
- if (this.agent.config.high_security === true) {
407
- logger.warnOnce(
408
- 'Notice Error',
409
- 'Notice error API is disabled by high security mode.'
410
- )
411
- return false
412
- } else if (!this.agent.config.api.notice_error_enabled) {
405
+ if (!this.agent.config.api.notice_error_enabled) {
413
406
  logger.debug(
414
407
  'Config.api.notice_error_enabled set to false, not collecting error'
415
408
  )
416
409
  return false
417
410
  }
418
411
 
412
+ // If high security mode is on or custom attributes are disabled,
413
+ // noticeError does not collect custom attributes.
414
+ if (this.agent.config.high_security === true) {
415
+ logger.debug(
416
+ 'Passing custom attributes to notice error API is disabled in high security mode.'
417
+ )
418
+ } else if (!this.agent.config.api.custom_attributes_enabled) {
419
+ logger.debug(
420
+ 'Config.api.custom_attributes_enabled set to false, ' +
421
+ 'ignoring custom error attributes.'
422
+ )
423
+ }
424
+
419
425
  if (typeof error === 'string') {
420
426
  error = new Error(error)
421
427
  }
422
- var transaction = this.agent.tracer.getTransaction()
428
+ const transaction = this.agent.tracer.getTransaction()
423
429
 
424
430
  this.agent.errors.addUserError(transaction, error, customAttributes)
425
431
  }
@@ -1,9 +1,10 @@
1
1
  #! /bin/bash
2
2
 
3
- function get_gcc_version {
4
- local gcc_version_match='[[:digit:]]\.[[:digit:]]\.[[:digit:]]'
5
- local gcc_version=`$CC --version 2>/dev/null | grep -o "$gcc_version_match" | head -1`
6
- echo $gcc_version | grep -o '[[:digit:]]' | head -1
3
+
4
+ function get_version {
5
+ local num='[[:digit:]][[:digit:]]*' # Grep doesn't have `+` operator.
6
+ local version=`$1 --version 2>/dev/null | grep -o "$num\.$num\.$num" | head -1`
7
+ echo $version | grep -o "$num" | head -1
7
8
  }
8
9
 
9
10
  TOOLCHAIN_ADDED="false"
@@ -15,15 +16,25 @@ function add_toolchain {
15
16
  TOOLCHAIN_ADDED="true"
16
17
  }
17
18
 
18
- # Only upgrade GCC if we need to.
19
19
 
20
20
  if [ "$SUITE" = "versioned" ]; then
21
- if [ "$(get_gcc_version)" != "5" ]; then
21
+
22
+ # GCC 5 is the lowest version of GCC we can use.
23
+ if [ "$(get_version gcc)" == "4" ]; then
22
24
  echo " --- upgrading GCC --- "
23
25
  add_toolchain
24
26
  ./bin/travis-install-gcc5.sh > /dev/null
25
27
  else
26
- echo " --- not upgrading GCC --- "
28
+ echo " --- not upgrading GCC ($(gcc --version)) --- "
29
+ fi
30
+
31
+ # npm 2 has an issue installing correctly for the superagent versioned tests.
32
+ # TODO: Remove this check when deprecating Node <5.
33
+ if [ "$(get_version npm)" == "2" ]; then
34
+ echo " -- upgrading npm --- "
35
+ npm install -g npm@3
36
+ else
37
+ echo " --- not upgrading npm ($(npm --version)) --- "
27
38
  fi
28
39
 
29
40
  echo " --- installing $SUITE requirements --- "
package/lib/config/env.js CHANGED
@@ -184,7 +184,8 @@ const BOOLEAN_VARS = new Set([
184
184
  ])
185
185
 
186
186
  const FLOAT_VARS = new Set([
187
- 'NEW_RELIC_APDEX'
187
+ 'NEW_RELIC_APDEX',
188
+ 'NEW_RELIC_TRACER_THRESHOLD'
188
189
  ])
189
190
 
190
191
  const INT_VARS = new Set([
@@ -123,6 +123,7 @@ function Config(config) {
123
123
  this.cross_process_id = null
124
124
  this.encoding_key = null
125
125
  this.obfuscatedId = null
126
+ this.primary_application_id = null
126
127
  this.trusted_account_ids = null
127
128
  this.trusted_account_key = null
128
129
  this.sampling_target = 10
@@ -274,6 +275,7 @@ Config.prototype._fromServer = function _fromServer(params, key) {
274
275
  case 'application_id':
275
276
  case 'collect_errors':
276
277
  case 'collect_traces':
278
+ case 'primary_application_id':
277
279
  case 'product_level':
278
280
  case 'max_payload_size_in_bytes':
279
281
  case 'sampling_target':
package/lib/db/tracer.js CHANGED
@@ -186,7 +186,9 @@ function SlowQuery(segment, type, query, trace) {
186
186
  }
187
187
 
188
188
  function normalizedHash(value) {
189
- return parseInt(crypto.createHash('md5').update(value).digest('hex').slice(-4), 16)
189
+ // We leverage the last 16 hex digits of which would mostly fit in a long and
190
+ // rely on parseInt to drop bits that do not fit in a JS number
191
+ return parseInt(crypto.createHash('sha1').update(value).digest('hex').slice(-16), 16)
190
192
  }
191
193
 
192
194
  function formatTrace(trace) {
@@ -74,7 +74,7 @@ function createError(transaction, exception, customAttributes, config) {
74
74
  }
75
75
  }
76
76
 
77
- if (!config.high_security && customAttributes) {
77
+ if (!config.high_security && config.api.custom_attributes_enabled && customAttributes) {
78
78
  for (var key in customAttributes) {
79
79
  if (props.hasOwn(customAttributes, key)) {
80
80
  var dest = config.attributeFilter.filter(DESTINATIONS.ERROR_EVENT, key)
@@ -1,39 +1,5 @@
1
1
  'use strict'
2
2
 
3
- var promInit = require('./promise')
4
- var shimmer = require('../shimmer')
5
-
6
- var BLUEBIRD_SPEC = {
7
- name: 'bluebird',
8
- constructor: 'Promise',
9
- $proto: {
10
- cast: [
11
- 'all', 'any', 'bind', 'call', 'catchReturn', 'catchThrow', 'delay', 'get',
12
- 'props', 'race', 'reflect', 'return', 'some', 'thenReturn', 'thenThrow',
13
- 'throw', 'timeout'
14
- ],
15
- then: [
16
- 'asCallback', 'done', 'each', 'filter', 'finally', 'lastly', 'map',
17
- 'mapSeries', 'nodeify', 'reduce', 'spread', 'tap', 'tapCatch', 'then'
18
- ],
19
- catch: ['catch', 'caught', 'error'],
20
-
21
- // _resolveFromResolver is in bluebird 2.x
22
- // _execute is in bluebird 3.x
23
- executor: ['_execute', '_resolveFromResolver']
24
- },
25
- $static: {
26
- cast: [
27
- 'all', 'any', 'attempt', 'bind', 'cast', 'delay', 'each', 'filter',
28
- 'fromCallback', 'fromNode', 'fulfilled', 'join', 'map', 'mapSeries',
29
- 'props', 'race', 'reduce', 'reject', 'rejected', 'resolve', 'some', 'try'
30
- ],
31
- promisify: [
32
- 'coroutine', 'method', 'promisify'
33
- ]
34
- }
35
- }
36
-
37
3
  // XXX We are not instrumenting bluebird's cancellation feature because it seems
38
4
  // rather like an edge case feature. It is not enabled by default and has strange
39
5
  // effects on the interface. If our lack of support for cancellation becomes an
@@ -41,31 +7,55 @@ var BLUEBIRD_SPEC = {
41
7
  //
42
8
  // http://bluebirdjs.com/docs/api/cancellation.html
43
9
 
10
+ module.exports = function initialize(agent, bluebird, moduleName, shim) {
11
+ const Promise = bluebird.Promise
12
+ const proto = Promise && Promise.prototype
13
+ if (!proto) {
14
+ shim.logger.debug('Could not find promise prototype, not instrumenting.')
15
+ return false
16
+ }
44
17
 
45
- module.exports = function initialize(agent, bluebird) {
46
- promInit(agent, bluebird, BLUEBIRD_SPEC)
18
+ shim.setClass(Promise)
19
+
20
+ // _resolveFromResolver is in bluebird 2.x
21
+ // _execute is in bluebird 3.x
22
+ shim.wrapExecutorCaller(proto, ['_execute', '_resolveFromResolver'])
23
+ shim.wrapThen(proto, [
24
+ 'asCallback', 'done', 'each', 'filter', 'finally', 'lastly', 'map',
25
+ 'mapSeries', 'nodeify', 'reduce', 'spread', 'tap', 'tapCatch', 'then'
26
+ ])
27
+ shim.wrapCatch(proto, ['catch', 'caught', 'error'])
28
+ shim.wrapCast(proto, [
29
+ 'all', 'any', 'bind', 'call', 'catchReturn', 'catchThrow', 'delay', 'get',
30
+ 'props', 'race', 'reflect', 'return', 'some', 'thenReturn', 'thenThrow',
31
+ 'throw', 'timeout'
32
+ ])
33
+
34
+ shim.wrapCast(Promise, [
35
+ 'all', 'any', 'attempt', 'bind', 'cast', 'delay', 'each', 'filter',
36
+ 'fromCallback', 'fromNode', 'fulfilled', 'join', 'map', 'mapSeries',
37
+ 'props', 'race', 'reduce', 'reject', 'rejected', 'resolve', 'some', 'try'
38
+ ])
39
+ shim.wrapPromisify(Promise, ['coroutine', 'method', 'promisify'])
47
40
 
48
41
  // Using `getNewLibraryCopy` needs to trigger re-instrumenting.
49
- shimmer.wrapMethod(
42
+ shim.wrap(
50
43
  bluebird.Promise,
51
- 'bluebird',
52
44
  'getNewLibraryCopy',
53
- function wrapNewCopy(original) {
45
+ function wrapNewCopy(shim, original) {
54
46
  return function wrappedNewCopy() {
47
+ shim.logger.trace('Instrumenting new library copy...')
55
48
  var copy = original.apply(this, arguments)
56
- module.exports(agent, copy)
49
+ module.exports(agent, copy, moduleName, shim)
57
50
  return copy
58
51
  }
59
52
  }
60
53
  )
61
54
 
62
55
  // Need to copy over `coroutine.addYieldHandler`
63
- var Promise = bluebird.Promise
64
56
  var coroutine = Promise && Promise.coroutine
65
- if (shimmer.isWrapped(coroutine)) {
66
- var original = agent.tracer.getOriginal(coroutine)
57
+ if (shim.isWrapped(coroutine)) {
58
+ var original = shim.getOriginal(coroutine)
67
59
  coroutine.addYieldHandler = original && original.addYieldHandler
68
60
  }
69
61
  }
70
-
71
- module.exports.SPEC = BLUEBIRD_SPEC
@@ -1,54 +1,57 @@
1
1
  'use strict'
2
2
 
3
- var wrap = require('../../shimmer').wrapMethod
4
- var isWrapped = require('../../shimmer').isWrapped
5
-
6
3
  module.exports = initialize
7
4
 
8
- function initialize(agent, childProcess) {
9
- var methods = ['exec', 'execFile']
5
+ function initialize(agent, childProcess, moduleName, shim) {
6
+ if (!childProcess) {
7
+ shim.log.debug('Could not find child_process, not instrumenting')
8
+ return false
9
+ }
10
10
 
11
- wrap(childProcess, 'childProcess', methods, wrapMethod)
11
+ const methods = ['exec', 'execFile']
12
12
 
13
- function wrapMethod(fn, method) {
14
- var wrapped = agent.tracer.wrapFunctionLast('child_process.' + method, null, fn)
15
- Object.getOwnPropertySymbols(fn).forEach((symbol) => {
16
- wrapped[symbol] = fn[symbol]
17
- })
18
- return wrapped
19
- }
13
+ shim.record(
14
+ childProcess,
15
+ methods,
16
+ function recordExec(shim, fn, name) {
17
+ return {name: 'child_process.' + name, callback: shim.LAST}
18
+ }
19
+ )
20
20
 
21
- var childProcessProto = childProcess && childProcess.ChildProcess
22
- // ChildProcess is exposed on Node 4 and higher
23
- if (childProcessProto) {
24
- wrapChildProcessCls(childProcess.ChildProcess)
21
+ if (childProcess.ChildProcess) {
22
+ wrapChildProcessClass(shim, childProcess.ChildProcess)
25
23
  } else {
26
- wrap(childProcess, 'childProcess', ['fork', 'spawn'], wrapSpawn)
24
+ shim.logger.warn('childProcess.ChildProcess should be available in v2.2.0 or higher')
27
25
  }
28
26
 
29
- function wrapSpawn(fn) {
30
- return function wrapped() {
31
- var child = fn.apply(this, arguments)
32
- if (child && child.constructor && child.constructor.prototype) {
33
- wrapChildProcessCls(child.constructor)
34
- }
35
- return child
36
- }
37
- }
27
+ function wrapChildProcessClass(shim, childProcessClass) {
28
+ shim.wrap(
29
+ childProcessClass.prototype,
30
+ 'on',
31
+ function wrapChildProcessClassOn(shim, fn) {
32
+ return function wrappedChildProcessOn() {
33
+ const args = shim.argsToArray.apply(shim, arguments)
34
+ const cbIndex = args.length - 1
38
35
 
39
- function wrapChildProcessCls(childProcessCls) {
40
- if (!childProcessCls || !childProcessCls.prototype ||
41
- isWrapped(childProcessCls.prototype.on)) {
42
- return
43
- }
36
+ shim.bindSegment(args, cbIndex)
44
37
 
45
- wrap(
46
- childProcessCls.prototype,
47
- 'childProcess.ChildProcess.prototype',
48
- 'on',
49
- function wrapEmit(fn) {
50
- return agent.tracer.wrapFunctionNoSegment(fn, ['on', 'addListener'])
38
+ return fn.apply(this, args)
39
+ }
51
40
  }
52
41
  )
53
42
  }
43
+
44
+ makePromisifyCompatible(shim, childProcess)
45
+ }
46
+
47
+ function makePromisifyCompatible(shim, childProcess) {
48
+ const originalExec = shim.getOriginal(childProcess.exec)
49
+ Object.getOwnPropertySymbols(originalExec).forEach((symbol) => {
50
+ childProcess.exec[symbol] = originalExec[symbol]
51
+ })
52
+
53
+ const originalExecFile = shim.getOriginal(childProcess.execFile)
54
+ Object.getOwnPropertySymbols(originalExecFile).forEach((symbol) => {
55
+ childProcess.execFile[symbol] = originalExecFile[symbol]
56
+ })
54
57
  }
@@ -12,19 +12,20 @@ function initialize(agent, domain, name, shim) {
12
12
 
13
13
  function wrapEmit(shim, original) {
14
14
  return function wrappedEmit(ev) {
15
- var shouldRestoreContext = ev === 'error' &&
16
- shim.getActiveSegment() === null &&
17
- this.__NR_transactionSegment
15
+ var shouldRestoreContext =
16
+ ev === 'error' &&
17
+ shim.getActiveSegment() === null &&
18
+ shim.getSegment(this)
19
+
18
20
  if (!shouldRestoreContext) {
19
21
  return original.apply(this, arguments)
20
22
  }
21
23
 
22
- shim.setActiveSegment(this.__NR_transactionSegment)
24
+ shim.setActiveSegment(shim.getSegment(this))
23
25
  try {
24
26
  return original.apply(this, arguments)
25
27
  } finally {
26
28
  shim.setActiveSegment(null)
27
- this.__NR_transactionSegment = null
28
29
  }
29
30
  }
30
31
  }
@@ -1,108 +1,104 @@
1
1
  'use strict'
2
2
 
3
- var shimmer = require('../../shimmer')
4
-
5
-
6
- module.exports = function initialize(agent, net) {
7
- shimmer.wrapMethod(net, 'net', ['connect', 'createConnection'], wrapCreate)
8
- function wrapCreate(original, name) {
3
+ module.exports = function initialize(agent, net, moduleName, shim) {
4
+ shim.wrap(net, ['connect', 'createConnection'], wrapCreate)
5
+ function wrapCreate(shim, fn, name) {
9
6
  return function wrappedCreateConnection() {
10
- if (!agent.getTransaction()) {
11
- return original.apply(this, arguments)
7
+ const segment = shim.getActiveSegment()
8
+ if (!segment) {
9
+ return fn.apply(this, arguments)
12
10
  }
13
11
 
14
- var segment = agent.tracer.createSegment('net.' + name)
15
- var sock = agent.tracer.bindFunction(original, segment, true).apply(this, arguments)
16
- wrapSocket(sock, segment)
12
+ const child = shim.createSegment('net.' + name, null, segment)
13
+ const sock = shim.applySegment(fn, child, true, this, arguments)
14
+ wrapSocket(sock, child)
17
15
  return sock
18
16
  }
19
17
  }
20
18
 
21
- net.Server.prototype.listen = agent.tracer.wrapFunctionNoSegment(
22
- net.Server.prototype.listen,
23
- 'net.Server.prototype.listen'
24
- )
25
-
26
- net.Server.prototype.close = agent.tracer.wrapFunctionNoSegment(
27
- net.Server.prototype.close,
28
- 'net.Server.prototype.close'
29
- )
30
-
31
- shimmer.wrapMethod(
32
- net.Server.prototype,
33
- 'net.Server.prototype',
34
- '_listen2',
35
- wrapListen2
36
- )
37
- shimmer.wrapMethod(
38
- net.Socket.prototype,
39
- 'net.Socket.prototype',
40
- 'connect',
41
- wrapConnect
42
- )
43
-
44
- function wrapListen2(original) {
19
+ const serverProto = net.Server.prototype
20
+
21
+ shim.wrap(serverProto, ['listen', 'close'], function wrapNoRecord(shim, fn) {
22
+ return function wrappedNoRecord() {
23
+ if (!shim.getActiveSegment()) {
24
+ return fn.apply(this, arguments)
25
+ }
26
+
27
+ const args = shim.argsToArray.apply(shim, arguments)
28
+ const cbIndex = args.length - 1
29
+
30
+ shim.bindSegment(args, cbIndex)
31
+
32
+ return fn.apply(this, args)
33
+ }
34
+ })
35
+
36
+ shim.wrap(serverProto, '_listen2', wrapListen2)
37
+ shim.wrap(net.Socket.prototype, 'connect', wrapConnect)
38
+
39
+ function wrapListen2(shim, fn) {
45
40
  return function wrappedListen2() {
46
- var segment = agent.tracer.getSegment()
47
- var emit = this.emit
41
+ const segment = shim.getActiveSegment()
42
+ const emit = this.emit
48
43
 
49
- if (!segment || !emit) return original.apply(this, arguments)
44
+ if (!segment || !emit) return fn.apply(this, arguments)
50
45
 
51
46
  this.emit = wrappedEmit
52
47
 
53
- return original.apply(this, arguments)
48
+ return fn.apply(this, arguments)
54
49
 
55
50
  function wrappedEmit(ev, socket) {
56
51
  if (ev !== 'connection' || !socket || !socket._handle) {
57
52
  return emit.apply(this, arguments)
58
53
  }
59
54
 
60
- var child = agent.tracer.createSegment('net.Server.onconnection', null, segment)
55
+ const child = shim.createSegment('net.Server.onconnection', segment)
61
56
 
62
57
  if (socket._handle.onread) {
63
- socket._handle.onread = agent.tracer.bindFunction(socket._handle.onread, child)
58
+ shim.bindSegment(socket._handle, 'onread', child)
64
59
  }
65
60
 
66
- return agent.tracer.bindFunction(emit, child, true).apply(this, arguments)
61
+ return shim.applySegment(emit, child, true, this, arguments)
67
62
  }
68
63
  }
69
64
  }
70
65
 
71
- function wrapConnect(original) {
66
+ function wrapConnect(shim, fn) {
72
67
  return function connectWrapper() {
73
- if (!agent.getTransaction()) return original.apply(this, arguments)
74
- var socket = this
75
- var args = normalizeConnectArgs(arguments)
76
- return agent.tracer.addSegment(
77
- 'net.Socket.connect',
78
- null,
79
- null,
80
- true,
81
- wrappedConnect
82
- )
83
-
84
- function wrappedConnect(child) {
85
- if (args[1]) args[1] = agent.tracer.bindFunction(args[1], child)
86
- var result = original.apply(socket, args)
87
- if (socket._handle) {
88
- socket._handle.onread = agent.tracer.bindFunction(socket._handle.onread, child)
89
- }
90
- agent.tracer.bindEmitter(socket, child)
91
- return result
68
+ if (!agent.getTransaction()) {
69
+ return fn.apply(this, arguments)
70
+ }
71
+
72
+ const socket = this
73
+ const args = normalizeConnectArgs(arguments)
74
+
75
+ const segment = shim.createSegment('net.Socket.connect')
76
+
77
+ if (args[1]) {
78
+ args[1] = shim.bindSegment(args[1], segment)
92
79
  }
80
+
81
+ const result = shim.applySegment(fn, segment, true, this, args)
82
+
83
+ if (socket._handle) {
84
+ shim.bindSegment(socket._handle, 'onread', segment)
85
+ }
86
+ shim.bindSegment(socket, 'emit', segment)
87
+
88
+ return result
93
89
  }
94
90
  }
95
91
 
96
92
  function wrapSocket(sock, segment) {
97
- shimmer.wrapMethod(sock, 'net.Socket', 'emit', function emitWrapper(emit) {
98
- return agent.tracer.bindFunction(emit, segment)
93
+ shim.wrap(sock, 'emit', function emitWrapper(shim, fn) {
94
+ return shim.bindSegment(fn, segment)
99
95
  })
100
96
  }
101
97
  }
102
98
 
103
99
  // taken from node master on 2013/10/30
104
100
  function normalizeConnectArgs(args) {
105
- var options = Object.create(null)
101
+ let options = Object.create(null)
106
102
 
107
103
  function toNumber(x) {
108
104
  return (x = Number(x)) >= 0 ? x : false
@@ -121,6 +117,6 @@ function normalizeConnectArgs(args) {
121
117
  }
122
118
  }
123
119
 
124
- var cb = args[args.length - 1]
120
+ const cb = args[args.length - 1]
125
121
  return typeof cb === 'function' ? [options, cb] : [options]
126
122
  }