@whatwg-node/node-fetch 0.7.20 → 0.7.21-alpha-20250516225908-e1b2bae5274598f7b85698826297f01ce1931e56

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/cjs/Body.js CHANGED
@@ -28,11 +28,11 @@ class PonyfillBody {
28
28
  bodyUsed = false;
29
29
  contentType = null;
30
30
  contentLength = null;
31
- signal = null;
31
+ _signal = null;
32
32
  constructor(bodyInit, options = {}) {
33
33
  this.bodyInit = bodyInit;
34
34
  this.options = options;
35
- this.signal = options.signal || null;
35
+ this._signal = options.signal || null;
36
36
  const { bodyFactory, contentType, contentLength, bodyType, buffer } = processBodyInit(bodyInit, options?.signal);
37
37
  this._bodyFactory = bodyFactory;
38
38
  this.contentType = contentType;
@@ -150,6 +150,13 @@ class PonyfillBody {
150
150
  if (this._blob) {
151
151
  return (0, utils_js_1.fakePromise)(this._blob);
152
152
  }
153
+ if (this.bodyType === BodyInitType.String) {
154
+ this._text = this.bodyInit;
155
+ this._blob = new Blob_js_1.PonyfillBlob([this._text], {
156
+ type: this.contentType || 'text/plain;charset=UTF-8',
157
+ size: this.contentLength,
158
+ });
159
+ }
153
160
  if (this.bodyType === BodyInitType.Blob) {
154
161
  this._blob = this.bodyInit;
155
162
  return (0, utils_js_1.fakePromise)(this._blob);
@@ -205,8 +212,8 @@ class PonyfillBody {
205
212
  limits: formDataLimits,
206
213
  defCharset: 'utf-8',
207
214
  });
208
- if (this.signal) {
209
- (0, node_stream_1.addAbortSignal)(this.signal, bb);
215
+ if (this._signal) {
216
+ (0, node_stream_1.addAbortSignal)(this._signal, bb);
210
217
  }
211
218
  let completed = false;
212
219
  const complete = (err) => {
@@ -279,6 +286,17 @@ class PonyfillBody {
279
286
  if (this._buffer) {
280
287
  return (0, utils_js_1.fakePromise)(this._buffer);
281
288
  }
289
+ if (this._text) {
290
+ this._buffer = node_buffer_1.Buffer.from(this._text, 'utf-8');
291
+ return (0, utils_js_1.fakePromise)(this._buffer);
292
+ }
293
+ if (this.bodyType === BodyInitType.String) {
294
+ return this.text().then(text => {
295
+ this._text = text;
296
+ this._buffer = node_buffer_1.Buffer.from(text, 'utf-8');
297
+ return this._buffer;
298
+ });
299
+ }
282
300
  if (this.bodyType === BodyInitType.Blob) {
283
301
  if ((0, Blob_js_1.hasBufferMethod)(this.bodyInit)) {
284
302
  return this.bodyInit.buffer().then(buf => {
@@ -358,15 +376,13 @@ function processBodyInit(bodyInit, signal) {
358
376
  };
359
377
  }
360
378
  if (typeof bodyInit === 'string') {
361
- const buffer = node_buffer_1.Buffer.from(bodyInit);
362
- const contentLength = buffer.byteLength;
379
+ const contentLength = node_buffer_1.Buffer.byteLength(bodyInit);
363
380
  return {
364
381
  bodyType: BodyInitType.String,
365
382
  contentType: 'text/plain;charset=UTF-8',
366
383
  contentLength,
367
- buffer,
368
384
  bodyFactory() {
369
- const readable = node_stream_1.Readable.from(buffer);
385
+ const readable = node_stream_1.Readable.from(node_buffer_1.Buffer.from(bodyInit, 'utf-8'));
370
386
  return new ReadableStream_js_1.PonyfillReadableStream(readable);
371
387
  },
372
388
  };
package/cjs/Headers.js CHANGED
@@ -66,7 +66,7 @@ class PonyfillHeaders {
66
66
  // I could do a getter here, but I'm too lazy to type `getter`.
67
67
  getMap() {
68
68
  if (!this._map) {
69
- this._setCookies = [];
69
+ this._setCookies ||= [];
70
70
  if (this.headersInit != null) {
71
71
  if (Array.isArray(this.headersInit)) {
72
72
  this._map = new Map();
@@ -131,7 +131,8 @@ class PonyfillHeaders {
131
131
  return value.toString();
132
132
  }
133
133
  has(name) {
134
- if (name === 'set-cookie') {
134
+ const key = name.toLowerCase();
135
+ if (key === 'set-cookie') {
135
136
  return !!this._setCookies?.length;
136
137
  }
137
138
  return !!this._get(name); // we might need to check if header exists and not just check if it's not nullable
@@ -142,6 +143,26 @@ class PonyfillHeaders {
142
143
  this._setCookies = [value];
143
144
  return;
144
145
  }
146
+ if (!this._map && this.headersInit != null) {
147
+ if (Array.isArray(this.headersInit)) {
148
+ const found = this.headersInit.find(([headerKey]) => headerKey.toLowerCase() === key);
149
+ if (found) {
150
+ found[1] = value;
151
+ }
152
+ else {
153
+ this.headersInit.push([key, value]);
154
+ }
155
+ return;
156
+ }
157
+ else if (isHeadersLike(this.headersInit)) {
158
+ this.headersInit.set(key, value);
159
+ return;
160
+ }
161
+ else {
162
+ this.headersInit[key] = value;
163
+ return;
164
+ }
165
+ }
145
166
  this.getMap().set(key, value);
146
167
  }
147
168
  delete(name) {
package/cjs/Request.js CHANGED
@@ -57,7 +57,6 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
57
57
  this.redirect = requestInit?.redirect || 'follow';
58
58
  this.referrer = requestInit?.referrer || 'about:client';
59
59
  this.referrerPolicy = requestInit?.referrerPolicy || 'no-referrer';
60
- this.signal = requestInit?.signal || new AbortController().signal;
61
60
  this.headersSerializer = requestInit?.headersSerializer;
62
61
  this.duplex = requestInit?.duplex || 'half';
63
62
  this.destination = 'document';
@@ -92,6 +91,10 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
92
91
  referrer;
93
92
  referrerPolicy;
94
93
  _url;
94
+ get signal() {
95
+ this._signal ||= new AbortController().signal;
96
+ return this._signal;
97
+ }
95
98
  get url() {
96
99
  if (this._url == null) {
97
100
  if (this._parsedUrl) {
@@ -117,7 +120,6 @@ class PonyfillRequest extends Body_js_1.PonyfillBody {
117
120
  }
118
121
  duplex;
119
122
  agent;
120
- signal;
121
123
  clone() {
122
124
  return this;
123
125
  }
package/cjs/Response.js CHANGED
@@ -18,7 +18,6 @@ class PonyfillResponse extends Body_js_1.PonyfillBody {
18
18
  this.url = init?.url || '';
19
19
  this.redirected = init?.redirected || false;
20
20
  this.type = init?.type || 'default';
21
- this.signal = init?.signal || null;
22
21
  this.handleContentLengthHeader();
23
22
  }
24
23
  get ok() {
@@ -49,13 +48,33 @@ class PonyfillResponse extends Body_js_1.PonyfillBody {
49
48
  status,
50
49
  });
51
50
  }
52
- static json(data, init = {}) {
53
- init.headers =
54
- init?.headers && (0, Headers_js_1.isHeadersLike)(init.headers)
55
- ? init.headers
56
- : new Headers_js_1.PonyfillHeaders(init?.headers);
57
- if (!init.headers.has('content-type')) {
58
- init.headers.set('content-type', JSON_CONTENT_TYPE);
51
+ static json(data, init) {
52
+ if (!init) {
53
+ init = {
54
+ headers: {
55
+ 'content-type': JSON_CONTENT_TYPE,
56
+ },
57
+ };
58
+ }
59
+ else if (!init.headers) {
60
+ init.headers = {
61
+ 'content-type': JSON_CONTENT_TYPE,
62
+ };
63
+ }
64
+ else if ((0, Headers_js_1.isHeadersLike)(init.headers)) {
65
+ if (!init.headers.has('content-type')) {
66
+ init.headers.set('content-type', JSON_CONTENT_TYPE);
67
+ }
68
+ }
69
+ else if (Array.isArray(init.headers)) {
70
+ if (!init.headers.some(([key]) => key.toLowerCase() === 'content-type')) {
71
+ init.headers.push(['content-type', JSON_CONTENT_TYPE]);
72
+ }
73
+ }
74
+ else if (typeof init.headers === 'object') {
75
+ if (init.headers?.['content-type'] == null) {
76
+ init.headers['content-type'] = JSON_CONTENT_TYPE;
77
+ }
59
78
  }
60
79
  return new PonyfillResponse(JSON.stringify(data), init);
61
80
  }
package/cjs/fetchCurl.js CHANGED
@@ -21,8 +21,18 @@ function fetchCurl(fetchRequest) {
21
21
  curlHandle.setOpt('CAINFO_BLOB', node_tls_1.rootCertificates.join('\n'));
22
22
  }
23
23
  curlHandle.enable(CurlFeature.StreamResponse);
24
+ let signal;
25
+ if (fetchRequest._signal === null) {
26
+ signal = undefined;
27
+ }
28
+ else if (fetchRequest._signal) {
29
+ signal = fetchRequest._signal;
30
+ }
31
+ else {
32
+ signal = fetchRequest.signal;
33
+ }
24
34
  curlHandle.setStreamProgressCallback(function () {
25
- return fetchRequest.signal.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
35
+ return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
26
36
  });
27
37
  if (fetchRequest['bodyType'] === 'String') {
28
38
  curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
@@ -69,9 +79,7 @@ function fetchCurl(fetchRequest) {
69
79
  }
70
80
  }
71
81
  }
72
- if (fetchRequest.signal) {
73
- fetchRequest.signal.addEventListener('abort', onAbort, { once: true });
74
- }
82
+ signal?.addEventListener('abort', onAbort, { once: true });
75
83
  curlHandle.once('end', function endListener() {
76
84
  try {
77
85
  curlHandle.close();
@@ -79,9 +87,7 @@ function fetchCurl(fetchRequest) {
79
87
  catch (e) {
80
88
  deferredPromise.reject(e);
81
89
  }
82
- if (fetchRequest.signal) {
83
- fetchRequest.signal.removeEventListener('abort', onAbort);
84
- }
90
+ signal?.removeEventListener('abort', onAbort);
85
91
  });
86
92
  curlHandle.once('error', function errorListener(error) {
87
93
  if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
@@ -103,7 +109,7 @@ function fetchCurl(fetchRequest) {
103
109
  curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
104
110
  const outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
105
111
  incomingMessage: stream,
106
- signal: fetchRequest.signal,
112
+ signal,
107
113
  onError: deferredPromise.reject,
108
114
  });
109
115
  const headersFlat = headersBuf
@@ -28,13 +28,23 @@ function fetchNodeHttp(fetchRequest) {
28
28
  if (nodeHeaders['accept-encoding'] == null) {
29
29
  nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
30
30
  }
31
+ let signal;
32
+ if (fetchRequest._signal === null) {
33
+ signal = undefined;
34
+ }
35
+ else if (fetchRequest._signal) {
36
+ signal = fetchRequest._signal;
37
+ }
38
+ else {
39
+ signal = fetchRequest.signal;
40
+ }
31
41
  let nodeRequest;
32
42
  // If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
33
43
  if (fetchRequest.parsedUrl) {
34
44
  nodeRequest = requestFn(fetchRequest.parsedUrl, {
35
45
  method: fetchRequest.method,
36
46
  headers: nodeHeaders,
37
- signal: fetchRequest.signal,
47
+ signal,
38
48
  agent: fetchRequest.agent,
39
49
  });
40
50
  }
@@ -42,7 +52,7 @@ function fetchNodeHttp(fetchRequest) {
42
52
  nodeRequest = requestFn(fetchRequest.url, {
43
53
  method: fetchRequest.method,
44
54
  headers: nodeHeaders,
45
- signal: fetchRequest.signal,
55
+ signal,
46
56
  agent: fetchRequest.agent,
47
57
  });
48
58
  }
@@ -89,7 +99,7 @@ function fetchNodeHttp(fetchRequest) {
89
99
  outputStream = (0, utils_js_1.wrapIncomingMessageWithPassthrough)({
90
100
  incomingMessage: nodeResponse,
91
101
  passThrough: outputStream,
92
- signal: fetchRequest.signal,
102
+ signal,
93
103
  onError: reject,
94
104
  });
95
105
  }
@@ -103,12 +113,12 @@ function fetchNodeHttp(fetchRequest) {
103
113
  statusText,
104
114
  headers: nodeResponse.headers,
105
115
  url: fetchRequest.url,
106
- signal: fetchRequest.signal,
116
+ signal,
107
117
  });
108
118
  resolve(ponyfillResponse);
109
119
  });
110
120
  if (fetchRequest['_buffer'] != null) {
111
- (0, promise_helpers_1.handleMaybePromise)(() => (0, utils_js_1.safeWrite)(fetchRequest['_buffer'], nodeRequest, fetchRequest.signal), () => (0, utils_js_1.endStream)(nodeRequest), reject);
121
+ (0, promise_helpers_1.handleMaybePromise)(() => (0, utils_js_1.safeWrite)(fetchRequest['_buffer'], nodeRequest, signal), () => (0, utils_js_1.endStream)(nodeRequest), reject);
112
122
  }
113
123
  else {
114
124
  const nodeReadable = (fetchRequest.body != null
package/cjs/utils.js CHANGED
@@ -20,6 +20,11 @@ function getHeadersObj(headers) {
20
20
  if (headers == null || !isHeadersInstance(headers)) {
21
21
  return headers;
22
22
  }
23
+ // @ts-expect-error - `headersInit` is not a public property
24
+ if (headers.headersInit && !headers._map && !isHeadersInstance(headers.headersInit)) {
25
+ // @ts-expect-error - `headersInit` is not a public property
26
+ return headers.headersInit;
27
+ }
23
28
  return Object.fromEntries(headers.entries());
24
29
  }
25
30
  function defaultHeadersSerializer(headers, onContentLength) {
package/esm/Body.js CHANGED
@@ -25,11 +25,11 @@ export class PonyfillBody {
25
25
  bodyUsed = false;
26
26
  contentType = null;
27
27
  contentLength = null;
28
- signal = null;
28
+ _signal = null;
29
29
  constructor(bodyInit, options = {}) {
30
30
  this.bodyInit = bodyInit;
31
31
  this.options = options;
32
- this.signal = options.signal || null;
32
+ this._signal = options.signal || null;
33
33
  const { bodyFactory, contentType, contentLength, bodyType, buffer } = processBodyInit(bodyInit, options?.signal);
34
34
  this._bodyFactory = bodyFactory;
35
35
  this.contentType = contentType;
@@ -147,6 +147,13 @@ export class PonyfillBody {
147
147
  if (this._blob) {
148
148
  return fakePromise(this._blob);
149
149
  }
150
+ if (this.bodyType === BodyInitType.String) {
151
+ this._text = this.bodyInit;
152
+ this._blob = new PonyfillBlob([this._text], {
153
+ type: this.contentType || 'text/plain;charset=UTF-8',
154
+ size: this.contentLength,
155
+ });
156
+ }
150
157
  if (this.bodyType === BodyInitType.Blob) {
151
158
  this._blob = this.bodyInit;
152
159
  return fakePromise(this._blob);
@@ -202,8 +209,8 @@ export class PonyfillBody {
202
209
  limits: formDataLimits,
203
210
  defCharset: 'utf-8',
204
211
  });
205
- if (this.signal) {
206
- addAbortSignal(this.signal, bb);
212
+ if (this._signal) {
213
+ addAbortSignal(this._signal, bb);
207
214
  }
208
215
  let completed = false;
209
216
  const complete = (err) => {
@@ -276,6 +283,17 @@ export class PonyfillBody {
276
283
  if (this._buffer) {
277
284
  return fakePromise(this._buffer);
278
285
  }
286
+ if (this._text) {
287
+ this._buffer = Buffer.from(this._text, 'utf-8');
288
+ return fakePromise(this._buffer);
289
+ }
290
+ if (this.bodyType === BodyInitType.String) {
291
+ return this.text().then(text => {
292
+ this._text = text;
293
+ this._buffer = Buffer.from(text, 'utf-8');
294
+ return this._buffer;
295
+ });
296
+ }
279
297
  if (this.bodyType === BodyInitType.Blob) {
280
298
  if (hasBufferMethod(this.bodyInit)) {
281
299
  return this.bodyInit.buffer().then(buf => {
@@ -354,15 +372,13 @@ function processBodyInit(bodyInit, signal) {
354
372
  };
355
373
  }
356
374
  if (typeof bodyInit === 'string') {
357
- const buffer = Buffer.from(bodyInit);
358
- const contentLength = buffer.byteLength;
375
+ const contentLength = Buffer.byteLength(bodyInit);
359
376
  return {
360
377
  bodyType: BodyInitType.String,
361
378
  contentType: 'text/plain;charset=UTF-8',
362
379
  contentLength,
363
- buffer,
364
380
  bodyFactory() {
365
- const readable = Readable.from(buffer);
381
+ const readable = Readable.from(Buffer.from(bodyInit, 'utf-8'));
366
382
  return new PonyfillReadableStream(readable);
367
383
  },
368
384
  };
package/esm/Headers.js CHANGED
@@ -62,7 +62,7 @@ export class PonyfillHeaders {
62
62
  // I could do a getter here, but I'm too lazy to type `getter`.
63
63
  getMap() {
64
64
  if (!this._map) {
65
- this._setCookies = [];
65
+ this._setCookies ||= [];
66
66
  if (this.headersInit != null) {
67
67
  if (Array.isArray(this.headersInit)) {
68
68
  this._map = new Map();
@@ -127,7 +127,8 @@ export class PonyfillHeaders {
127
127
  return value.toString();
128
128
  }
129
129
  has(name) {
130
- if (name === 'set-cookie') {
130
+ const key = name.toLowerCase();
131
+ if (key === 'set-cookie') {
131
132
  return !!this._setCookies?.length;
132
133
  }
133
134
  return !!this._get(name); // we might need to check if header exists and not just check if it's not nullable
@@ -138,6 +139,26 @@ export class PonyfillHeaders {
138
139
  this._setCookies = [value];
139
140
  return;
140
141
  }
142
+ if (!this._map && this.headersInit != null) {
143
+ if (Array.isArray(this.headersInit)) {
144
+ const found = this.headersInit.find(([headerKey]) => headerKey.toLowerCase() === key);
145
+ if (found) {
146
+ found[1] = value;
147
+ }
148
+ else {
149
+ this.headersInit.push([key, value]);
150
+ }
151
+ return;
152
+ }
153
+ else if (isHeadersLike(this.headersInit)) {
154
+ this.headersInit.set(key, value);
155
+ return;
156
+ }
157
+ else {
158
+ this.headersInit[key] = value;
159
+ return;
160
+ }
161
+ }
141
162
  this.getMap().set(key, value);
142
163
  }
143
164
  delete(name) {
package/esm/Request.js CHANGED
@@ -54,7 +54,6 @@ export class PonyfillRequest extends PonyfillBody {
54
54
  this.redirect = requestInit?.redirect || 'follow';
55
55
  this.referrer = requestInit?.referrer || 'about:client';
56
56
  this.referrerPolicy = requestInit?.referrerPolicy || 'no-referrer';
57
- this.signal = requestInit?.signal || new AbortController().signal;
58
57
  this.headersSerializer = requestInit?.headersSerializer;
59
58
  this.duplex = requestInit?.duplex || 'half';
60
59
  this.destination = 'document';
@@ -89,6 +88,10 @@ export class PonyfillRequest extends PonyfillBody {
89
88
  referrer;
90
89
  referrerPolicy;
91
90
  _url;
91
+ get signal() {
92
+ this._signal ||= new AbortController().signal;
93
+ return this._signal;
94
+ }
92
95
  get url() {
93
96
  if (this._url == null) {
94
97
  if (this._parsedUrl) {
@@ -114,7 +117,6 @@ export class PonyfillRequest extends PonyfillBody {
114
117
  }
115
118
  duplex;
116
119
  agent;
117
- signal;
118
120
  clone() {
119
121
  return this;
120
122
  }
package/esm/Response.js CHANGED
@@ -15,7 +15,6 @@ export class PonyfillResponse extends PonyfillBody {
15
15
  this.url = init?.url || '';
16
16
  this.redirected = init?.redirected || false;
17
17
  this.type = init?.type || 'default';
18
- this.signal = init?.signal || null;
19
18
  this.handleContentLengthHeader();
20
19
  }
21
20
  get ok() {
@@ -46,13 +45,33 @@ export class PonyfillResponse extends PonyfillBody {
46
45
  status,
47
46
  });
48
47
  }
49
- static json(data, init = {}) {
50
- init.headers =
51
- init?.headers && isHeadersLike(init.headers)
52
- ? init.headers
53
- : new PonyfillHeaders(init?.headers);
54
- if (!init.headers.has('content-type')) {
55
- init.headers.set('content-type', JSON_CONTENT_TYPE);
48
+ static json(data, init) {
49
+ if (!init) {
50
+ init = {
51
+ headers: {
52
+ 'content-type': JSON_CONTENT_TYPE,
53
+ },
54
+ };
55
+ }
56
+ else if (!init.headers) {
57
+ init.headers = {
58
+ 'content-type': JSON_CONTENT_TYPE,
59
+ };
60
+ }
61
+ else if (isHeadersLike(init.headers)) {
62
+ if (!init.headers.has('content-type')) {
63
+ init.headers.set('content-type', JSON_CONTENT_TYPE);
64
+ }
65
+ }
66
+ else if (Array.isArray(init.headers)) {
67
+ if (!init.headers.some(([key]) => key.toLowerCase() === 'content-type')) {
68
+ init.headers.push(['content-type', JSON_CONTENT_TYPE]);
69
+ }
70
+ }
71
+ else if (typeof init.headers === 'object') {
72
+ if (init.headers?.['content-type'] == null) {
73
+ init.headers['content-type'] = JSON_CONTENT_TYPE;
74
+ }
56
75
  }
57
76
  return new PonyfillResponse(JSON.stringify(data), init);
58
77
  }
package/esm/fetchCurl.js CHANGED
@@ -18,8 +18,18 @@ export function fetchCurl(fetchRequest) {
18
18
  curlHandle.setOpt('CAINFO_BLOB', rootCertificates.join('\n'));
19
19
  }
20
20
  curlHandle.enable(CurlFeature.StreamResponse);
21
+ let signal;
22
+ if (fetchRequest._signal === null) {
23
+ signal = undefined;
24
+ }
25
+ else if (fetchRequest._signal) {
26
+ signal = fetchRequest._signal;
27
+ }
28
+ else {
29
+ signal = fetchRequest.signal;
30
+ }
21
31
  curlHandle.setStreamProgressCallback(function () {
22
- return fetchRequest.signal.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
32
+ return signal?.aborted ? (process.env.DEBUG ? CurlProgressFunc.Continue : 1) : 0;
23
33
  });
24
34
  if (fetchRequest['bodyType'] === 'String') {
25
35
  curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
@@ -66,9 +76,7 @@ export function fetchCurl(fetchRequest) {
66
76
  }
67
77
  }
68
78
  }
69
- if (fetchRequest.signal) {
70
- fetchRequest.signal.addEventListener('abort', onAbort, { once: true });
71
- }
79
+ signal?.addEventListener('abort', onAbort, { once: true });
72
80
  curlHandle.once('end', function endListener() {
73
81
  try {
74
82
  curlHandle.close();
@@ -76,9 +84,7 @@ export function fetchCurl(fetchRequest) {
76
84
  catch (e) {
77
85
  deferredPromise.reject(e);
78
86
  }
79
- if (fetchRequest.signal) {
80
- fetchRequest.signal.removeEventListener('abort', onAbort);
81
- }
87
+ signal?.removeEventListener('abort', onAbort);
82
88
  });
83
89
  curlHandle.once('error', function errorListener(error) {
84
90
  if (streamResolved && !streamResolved.closed && !streamResolved.destroyed) {
@@ -100,7 +106,7 @@ export function fetchCurl(fetchRequest) {
100
106
  curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
101
107
  const outputStream = wrapIncomingMessageWithPassthrough({
102
108
  incomingMessage: stream,
103
- signal: fetchRequest.signal,
109
+ signal,
104
110
  onError: deferredPromise.reject,
105
111
  });
106
112
  const headersFlat = headersBuf
@@ -25,13 +25,23 @@ export function fetchNodeHttp(fetchRequest) {
25
25
  if (nodeHeaders['accept-encoding'] == null) {
26
26
  nodeHeaders['accept-encoding'] = 'gzip, deflate, br';
27
27
  }
28
+ let signal;
29
+ if (fetchRequest._signal === null) {
30
+ signal = undefined;
31
+ }
32
+ else if (fetchRequest._signal) {
33
+ signal = fetchRequest._signal;
34
+ }
35
+ else {
36
+ signal = fetchRequest.signal;
37
+ }
28
38
  let nodeRequest;
29
39
  // If it is our ponyfilled Request, it should have `parsedUrl` which is a `URL` object
30
40
  if (fetchRequest.parsedUrl) {
31
41
  nodeRequest = requestFn(fetchRequest.parsedUrl, {
32
42
  method: fetchRequest.method,
33
43
  headers: nodeHeaders,
34
- signal: fetchRequest.signal,
44
+ signal,
35
45
  agent: fetchRequest.agent,
36
46
  });
37
47
  }
@@ -39,7 +49,7 @@ export function fetchNodeHttp(fetchRequest) {
39
49
  nodeRequest = requestFn(fetchRequest.url, {
40
50
  method: fetchRequest.method,
41
51
  headers: nodeHeaders,
42
- signal: fetchRequest.signal,
52
+ signal,
43
53
  agent: fetchRequest.agent,
44
54
  });
45
55
  }
@@ -86,7 +96,7 @@ export function fetchNodeHttp(fetchRequest) {
86
96
  outputStream = wrapIncomingMessageWithPassthrough({
87
97
  incomingMessage: nodeResponse,
88
98
  passThrough: outputStream,
89
- signal: fetchRequest.signal,
99
+ signal,
90
100
  onError: reject,
91
101
  });
92
102
  }
@@ -100,12 +110,12 @@ export function fetchNodeHttp(fetchRequest) {
100
110
  statusText,
101
111
  headers: nodeResponse.headers,
102
112
  url: fetchRequest.url,
103
- signal: fetchRequest.signal,
113
+ signal,
104
114
  });
105
115
  resolve(ponyfillResponse);
106
116
  });
107
117
  if (fetchRequest['_buffer'] != null) {
108
- handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest, fetchRequest.signal), () => endStream(nodeRequest), reject);
118
+ handleMaybePromise(() => safeWrite(fetchRequest['_buffer'], nodeRequest, signal), () => endStream(nodeRequest), reject);
109
119
  }
110
120
  else {
111
121
  const nodeReadable = (fetchRequest.body != null
package/esm/utils.js CHANGED
@@ -8,6 +8,11 @@ export function getHeadersObj(headers) {
8
8
  if (headers == null || !isHeadersInstance(headers)) {
9
9
  return headers;
10
10
  }
11
+ // @ts-expect-error - `headersInit` is not a public property
12
+ if (headers.headersInit && !headers._map && !isHeadersInstance(headers.headersInit)) {
13
+ // @ts-expect-error - `headersInit` is not a public property
14
+ return headers.headersInit;
15
+ }
11
16
  return Object.fromEntries(headers.entries());
12
17
  }
13
18
  export function defaultHeadersSerializer(headers, onContentLength) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@whatwg-node/node-fetch",
3
- "version": "0.7.20",
3
+ "version": "0.7.21-alpha-20250516225908-e1b2bae5274598f7b85698826297f01ce1931e56",
4
4
  "description": "Fetch API implementation for Node",
5
5
  "sideEffects": false,
6
6
  "dependencies": {
@@ -16,7 +16,7 @@ export interface FormDataLimits {
16
16
  }
17
17
  export interface PonyfillBodyOptions {
18
18
  formDataLimits?: FormDataLimits;
19
- signal?: AbortSignal;
19
+ signal?: AbortSignal | undefined;
20
20
  }
21
21
  export declare class PonyfillBody<TJSON = any> implements Body {
22
22
  private bodyInit;
@@ -24,7 +24,7 @@ export declare class PonyfillBody<TJSON = any> implements Body {
24
24
  bodyUsed: boolean;
25
25
  contentType: string | null;
26
26
  contentLength: number | null;
27
- signal?: AbortSignal | null;
27
+ _signal?: AbortSignal | null;
28
28
  constructor(bodyInit: BodyPonyfillInit | null, options?: PonyfillBodyOptions);
29
29
  private bodyType?;
30
30
  private _bodyFactory;
package/typings/Body.d.ts CHANGED
@@ -16,7 +16,7 @@ export interface FormDataLimits {
16
16
  }
17
17
  export interface PonyfillBodyOptions {
18
18
  formDataLimits?: FormDataLimits;
19
- signal?: AbortSignal;
19
+ signal?: AbortSignal | undefined;
20
20
  }
21
21
  export declare class PonyfillBody<TJSON = any> implements Body {
22
22
  private bodyInit;
@@ -24,7 +24,7 @@ export declare class PonyfillBody<TJSON = any> implements Body {
24
24
  bodyUsed: boolean;
25
25
  contentType: string | null;
26
26
  contentLength: number | null;
27
- signal?: AbortSignal | null;
27
+ _signal?: AbortSignal | null;
28
28
  constructor(bodyInit: BodyPonyfillInit | null, options?: PonyfillBodyOptions);
29
29
  private bodyType?;
30
30
  private _bodyFactory;
@@ -26,12 +26,12 @@ export declare class PonyfillRequest<TJSON = any> extends PonyfillBody<TJSON> im
26
26
  referrer: string;
27
27
  referrerPolicy: ReferrerPolicy;
28
28
  _url: string | undefined;
29
+ get signal(): AbortSignal;
29
30
  get url(): string;
30
31
  _parsedUrl: URL | undefined;
31
32
  get parsedUrl(): URL;
32
33
  duplex: 'half' | 'full';
33
34
  agent: HTTPAgent | HTTPSAgent | false | undefined;
34
- signal: AbortSignal;
35
35
  clone(): PonyfillRequest<TJSON>;
36
36
  [Symbol.toStringTag]: string;
37
37
  }
@@ -26,12 +26,12 @@ export declare class PonyfillRequest<TJSON = any> extends PonyfillBody<TJSON> im
26
26
  referrer: string;
27
27
  referrerPolicy: ReferrerPolicy;
28
28
  _url: string | undefined;
29
+ get signal(): AbortSignal;
29
30
  get url(): string;
30
31
  _parsedUrl: URL | undefined;
31
32
  get parsedUrl(): URL;
32
33
  duplex: 'half' | 'full';
33
34
  agent: HTTPAgent | HTTPSAgent | false | undefined;
34
- signal: AbortSignal;
35
35
  clone(): PonyfillRequest<TJSON>;
36
36
  [Symbol.toStringTag]: string;
37
37
  }