undici 6.1.0 → 6.2.1

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/lib/agent.js CHANGED
@@ -7,7 +7,6 @@ const Pool = require('./pool')
7
7
  const Client = require('./client')
8
8
  const util = require('./core/util')
9
9
  const createRedirectInterceptor = require('./interceptor/redirectInterceptor')
10
- const { WeakRef, FinalizationRegistry } = require('./compat/dispatcher-weakref')()
11
10
 
12
11
  const kOnConnect = Symbol('onConnect')
13
12
  const kOnDisconnect = Symbol('onDisconnect')
@@ -15,7 +14,6 @@ const kOnConnectionError = Symbol('onConnectionError')
15
14
  const kMaxRedirections = Symbol('maxRedirections')
16
15
  const kOnDrain = Symbol('onDrain')
17
16
  const kFactory = Symbol('factory')
18
- const kFinalizer = Symbol('finalizer')
19
17
  const kOptions = Symbol('options')
20
18
 
21
19
  function defaultFactory (origin, opts) {
@@ -55,12 +53,6 @@ class Agent extends DispatcherBase {
55
53
  this[kMaxRedirections] = maxRedirections
56
54
  this[kFactory] = factory
57
55
  this[kClients] = new Map()
58
- this[kFinalizer] = new FinalizationRegistry(/* istanbul ignore next: gc is undeterministic */ key => {
59
- const ref = this[kClients].get(key)
60
- if (ref !== undefined && ref.deref() === undefined) {
61
- this[kClients].delete(key)
62
- }
63
- })
64
56
 
65
57
  const agent = this
66
58
 
@@ -83,12 +75,8 @@ class Agent extends DispatcherBase {
83
75
 
84
76
  get [kRunning] () {
85
77
  let ret = 0
86
- for (const ref of this[kClients].values()) {
87
- const client = ref.deref()
88
- /* istanbul ignore next: gc is undeterministic */
89
- if (client) {
90
- ret += client[kRunning]
91
- }
78
+ for (const client of this[kClients].values()) {
79
+ ret += client[kRunning]
92
80
  }
93
81
  return ret
94
82
  }
@@ -101,9 +89,8 @@ class Agent extends DispatcherBase {
101
89
  throw new InvalidArgumentError('opts.origin must be a non-empty string or URL.')
102
90
  }
103
91
 
104
- const ref = this[kClients].get(key)
92
+ let dispatcher = this[kClients].get(key)
105
93
 
106
- let dispatcher = ref ? ref.deref() : null
107
94
  if (!dispatcher) {
108
95
  dispatcher = this[kFactory](opts.origin, this[kOptions])
109
96
  .on('drain', this[kOnDrain])
@@ -111,8 +98,10 @@ class Agent extends DispatcherBase {
111
98
  .on('disconnect', this[kOnDisconnect])
112
99
  .on('connectionError', this[kOnConnectionError])
113
100
 
114
- this[kClients].set(key, new WeakRef(dispatcher))
115
- this[kFinalizer].register(dispatcher, key)
101
+ // This introduces a tiny memory leak, as dispatchers are never removed from the map.
102
+ // TODO(mcollina): remove te timer when the client/pool do not have any more
103
+ // active connections.
104
+ this[kClients].set(key, dispatcher)
116
105
  }
117
106
 
118
107
  return dispatcher.dispatch(opts, handler)
@@ -120,28 +109,20 @@ class Agent extends DispatcherBase {
120
109
 
121
110
  async [kClose] () {
122
111
  const closePromises = []
123
- for (const ref of this[kClients].values()) {
124
- const client = ref.deref()
125
- /* istanbul ignore else: gc is undeterministic */
126
- if (client) {
127
- this[kFinalizer].unregister(client)
128
- closePromises.push(client.close())
129
- }
112
+ for (const client of this[kClients].values()) {
113
+ closePromises.push(client.close())
130
114
  }
115
+ this[kClients].clear()
131
116
 
132
117
  await Promise.all(closePromises)
133
118
  }
134
119
 
135
120
  async [kDestroy] (err) {
136
121
  const destroyPromises = []
137
- for (const ref of this[kClients].values()) {
138
- const client = ref.deref()
139
- /* istanbul ignore else: gc is undeterministic */
140
- if (client) {
141
- this[kFinalizer].unregister(client)
142
- destroyPromises.push(client.destroy(err))
143
- }
122
+ for (const client of this[kClients].values()) {
123
+ destroyPromises.push(client.destroy(err))
144
124
  }
125
+ this[kClients].clear()
145
126
 
146
127
  await Promise.all(destroyPromises)
147
128
  }
@@ -176,7 +176,7 @@ function parseLocation (statusCode, headers) {
176
176
  }
177
177
 
178
178
  for (let i = 0; i < headers.length; i += 2) {
179
- if (headers[i].toString().toLowerCase() === 'location') {
179
+ if (headers[i].length === 8 && util.headerNameToString(headers[i]) === 'location') {
180
180
  return headers[i + 1]
181
181
  }
182
182
  }
@@ -184,12 +184,17 @@ function parseLocation (statusCode, headers) {
184
184
 
185
185
  // https://tools.ietf.org/html/rfc7231#section-6.4.4
186
186
  function shouldRemoveHeader (header, removeContent, unknownOrigin) {
187
- return (
188
- (header.length === 4 && header.toString().toLowerCase() === 'host') ||
189
- (removeContent && header.toString().toLowerCase().indexOf('content-') === 0) ||
190
- (unknownOrigin && header.length === 13 && header.toString().toLowerCase() === 'authorization') ||
191
- (unknownOrigin && header.length === 6 && header.toString().toLowerCase() === 'cookie')
192
- )
187
+ if (header.length === 4) {
188
+ return util.headerNameToString(header) === 'host'
189
+ }
190
+ if (removeContent && util.headerNameToString(header).startsWith('content-')) {
191
+ return true
192
+ }
193
+ if (unknownOrigin && (header.length === 13 || header.length === 6)) {
194
+ const name = util.headerNameToString(header)
195
+ return name === 'authorization' || name === 'cookie'
196
+ }
197
+ return false
193
198
  }
194
199
 
195
200
  // https://tools.ietf.org/html/rfc7231#section-6.4
@@ -21,16 +21,6 @@ const Dispatcher = require('../dispatcher')
21
21
  const Pluralizer = require('./pluralizer')
22
22
  const PendingInterceptorsFormatter = require('./pending-interceptors-formatter')
23
23
 
24
- class FakeWeakRef {
25
- constructor (value) {
26
- this.value = value
27
- }
28
-
29
- deref () {
30
- return this.value
31
- }
32
- }
33
-
34
24
  class MockAgent extends Dispatcher {
35
25
  constructor (opts) {
36
26
  super(opts)
@@ -103,7 +93,7 @@ class MockAgent extends Dispatcher {
103
93
  }
104
94
 
105
95
  [kMockAgentSet] (origin, dispatcher) {
106
- this[kClients].set(origin, new FakeWeakRef(dispatcher))
96
+ this[kClients].set(origin, dispatcher)
107
97
  }
108
98
 
109
99
  [kFactory] (origin) {
@@ -115,9 +105,9 @@ class MockAgent extends Dispatcher {
115
105
 
116
106
  [kMockAgentGet] (origin) {
117
107
  // First check if we can immediately find it
118
- const ref = this[kClients].get(origin)
119
- if (ref) {
120
- return ref.deref()
108
+ const client = this[kClients].get(origin)
109
+ if (client) {
110
+ return client
121
111
  }
122
112
 
123
113
  // If the origin is not a string create a dummy parent pool and return to user
@@ -128,8 +118,7 @@ class MockAgent extends Dispatcher {
128
118
  }
129
119
 
130
120
  // If we match, create a pool and assign the same dispatches
131
- for (const [keyMatcher, nonExplicitRef] of Array.from(this[kClients])) {
132
- const nonExplicitDispatcher = nonExplicitRef.deref()
121
+ for (const [keyMatcher, nonExplicitDispatcher] of Array.from(this[kClients])) {
133
122
  if (nonExplicitDispatcher && typeof keyMatcher !== 'string' && matchValue(keyMatcher, origin)) {
134
123
  const dispatcher = this[kFactory](origin)
135
124
  this[kMockAgentSet](origin, dispatcher)
@@ -147,7 +136,7 @@ class MockAgent extends Dispatcher {
147
136
  const mockAgentClients = this[kClients]
148
137
 
149
138
  return Array.from(mockAgentClients.entries())
150
- .flatMap(([origin, scope]) => scope.deref()[kDispatches].map(dispatch => ({ ...dispatch, origin })))
139
+ .flatMap(([origin, scope]) => scope[kDispatches].map(dispatch => ({ ...dispatch, origin })))
151
140
  .filter(({ pending }) => pending)
152
141
  }
153
142
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "undici",
3
- "version": "6.1.0",
3
+ "version": "6.2.1",
4
4
  "description": "An HTTP/1.1 client, written from scratch for Node.js",
5
5
  "homepage": "https://undici.nodejs.org",
6
6
  "bugs": {
@@ -119,7 +119,6 @@
119
119
  "jsfuzz": "^1.0.15",
120
120
  "mitata": "^0.1.6",
121
121
  "mocha": "^10.0.0",
122
- "mockttp": "^3.9.2",
123
122
  "p-timeout": "^3.2.0",
124
123
  "pre-commit": "^1.2.2",
125
124
  "proxy": "^1.0.2",