@whatwg-node/node-fetch 0.5.0-alpha-20230710180612-32e574f → 0.5.0-alpha-20231025080723-49677d8
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/Blob.js +78 -58
- package/cjs/Body.js +83 -116
- package/cjs/FormData.js +3 -12
- package/cjs/Headers.js +1 -1
- package/cjs/ReadableStream.js +10 -4
- package/cjs/Request.js +4 -1
- package/cjs/TextEncoderDecoder.js +7 -0
- package/cjs/URLSearchParams.js +4 -1
- package/cjs/fetch.js +13 -8
- package/cjs/fetchCurl.js +89 -62
- package/cjs/fetchNodeHttp.js +2 -13
- package/cjs/utils.js +50 -6
- package/esm/Blob.js +79 -59
- package/esm/Body.js +84 -117
- package/esm/FormData.js +3 -12
- package/esm/Headers.js +1 -1
- package/esm/ReadableStream.js +10 -4
- package/esm/Request.js +4 -1
- package/esm/TextEncoderDecoder.js +7 -0
- package/esm/URLSearchParams.js +4 -1
- package/esm/fetch.js +13 -8
- package/esm/fetchCurl.js +90 -63
- package/esm/fetchNodeHttp.js +3 -14
- package/esm/utils.js +46 -4
- package/package.json +1 -1
- package/typings/Blob.d.cts +6 -2
- package/typings/Blob.d.ts +6 -2
- package/typings/Body.d.cts +2 -2
- package/typings/Body.d.ts +2 -2
- package/typings/FormData.d.cts +4 -2
- package/typings/FormData.d.ts +4 -2
- package/typings/TextEncoderDecoder.d.cts +2 -2
- package/typings/TextEncoderDecoder.d.ts +2 -2
- package/typings/utils.d.cts +5 -1
- package/typings/utils.d.ts +5 -1
package/cjs/fetch.js
CHANGED
@@ -3,11 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.fetchPonyfill = void 0;
|
4
4
|
const fs_1 = require("fs");
|
5
5
|
const url_1 = require("url");
|
6
|
-
const Blob_js_1 = require("./Blob.js");
|
7
6
|
const fetchCurl_js_1 = require("./fetchCurl.js");
|
8
7
|
const fetchNodeHttp_js_1 = require("./fetchNodeHttp.js");
|
9
8
|
const Request_js_1 = require("./Request.js");
|
10
9
|
const Response_js_1 = require("./Response.js");
|
10
|
+
const utils_js_1 = require("./utils.js");
|
11
11
|
const BASE64_SUFFIX = ';base64';
|
12
12
|
function getResponseForFile(url) {
|
13
13
|
const path = (0, url_1.fileURLToPath)(url);
|
@@ -15,15 +15,17 @@ function getResponseForFile(url) {
|
|
15
15
|
return new Response_js_1.PonyfillResponse(readable);
|
16
16
|
}
|
17
17
|
function getResponseForDataUri(url) {
|
18
|
-
const [mimeType = 'text/plain', ...datas] = url.split(',');
|
18
|
+
const [mimeType = 'text/plain', ...datas] = url.substring(5).split(',');
|
19
19
|
const data = decodeURIComponent(datas.join(','));
|
20
20
|
if (mimeType.endsWith(BASE64_SUFFIX)) {
|
21
21
|
const buffer = Buffer.from(data, 'base64url');
|
22
22
|
const realMimeType = mimeType.slice(0, -BASE64_SUFFIX.length);
|
23
|
-
|
24
|
-
return new Response_js_1.PonyfillResponse(file, {
|
23
|
+
return new Response_js_1.PonyfillResponse(buffer, {
|
25
24
|
status: 200,
|
26
25
|
statusText: 'OK',
|
26
|
+
headers: {
|
27
|
+
'content-type': realMimeType,
|
28
|
+
},
|
27
29
|
});
|
28
30
|
}
|
29
31
|
return new Response_js_1.PonyfillResponse(data, {
|
@@ -34,19 +36,22 @@ function getResponseForDataUri(url) {
|
|
34
36
|
},
|
35
37
|
});
|
36
38
|
}
|
37
|
-
|
38
|
-
|
39
|
+
function isURL(obj) {
|
40
|
+
return obj != null && obj.href != null;
|
41
|
+
}
|
42
|
+
function fetchPonyfill(info, init) {
|
43
|
+
if (typeof info === 'string' || isURL(info)) {
|
39
44
|
const ponyfillRequest = new Request_js_1.PonyfillRequest(info, init);
|
40
45
|
return fetchPonyfill(ponyfillRequest);
|
41
46
|
}
|
42
47
|
const fetchRequest = info;
|
43
48
|
if (fetchRequest.url.startsWith('data:')) {
|
44
49
|
const response = getResponseForDataUri(fetchRequest.url);
|
45
|
-
return
|
50
|
+
return (0, utils_js_1.fakePromise)(response);
|
46
51
|
}
|
47
52
|
if (fetchRequest.url.startsWith('file:')) {
|
48
53
|
const response = getResponseForFile(fetchRequest.url);
|
49
|
-
return
|
54
|
+
return (0, utils_js_1.fakePromise)(response);
|
50
55
|
}
|
51
56
|
if (globalThis.libcurl) {
|
52
57
|
return (0, fetchCurl_js_1.fetchCurl)(fetchRequest);
|
package/cjs/fetchCurl.js
CHANGED
@@ -1,79 +1,106 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
3
|
exports.fetchCurl = void 0;
|
4
|
-
|
5
|
-
const
|
6
|
-
const Headers_js_1 = require("./Headers.js");
|
4
|
+
const node_stream_1 = require("node:stream");
|
5
|
+
const AbortError_js_1 = require("./AbortError.js");
|
7
6
|
const Response_js_1 = require("./Response.js");
|
8
7
|
const utils_js_1 = require("./utils.js");
|
9
|
-
|
10
|
-
const
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
8
|
+
function fetchCurl(fetchRequest) {
|
9
|
+
const { Curl, CurlCode, CurlFeature, CurlPause, CurlProgressFunc } = globalThis['libcurl'];
|
10
|
+
const curlHandle = new Curl();
|
11
|
+
curlHandle.enable(CurlFeature.NoDataParsing);
|
12
|
+
curlHandle.setOpt('URL', fetchRequest.url);
|
13
|
+
curlHandle.setOpt('SSL_VERIFYPEER', false);
|
14
|
+
curlHandle.enable(CurlFeature.StreamResponse);
|
15
|
+
curlHandle.setStreamProgressCallback(function () {
|
16
|
+
return fetchRequest['_signal']?.aborted
|
17
|
+
? process.env.DEBUG
|
18
|
+
? CurlProgressFunc.Continue
|
19
|
+
: 1
|
20
|
+
: 0;
|
21
|
+
});
|
22
|
+
if (fetchRequest['bodyType'] === 'String') {
|
23
|
+
curlHandle.setOpt('POSTFIELDS', fetchRequest['bodyInit']);
|
24
|
+
}
|
25
|
+
else {
|
26
|
+
const nodeReadable = (fetchRequest.body != null
|
27
|
+
? (0, utils_js_1.isNodeReadable)(fetchRequest.body)
|
28
|
+
? fetchRequest.body
|
29
|
+
: node_stream_1.Readable.from(fetchRequest.body)
|
30
|
+
: null);
|
31
|
+
if (nodeReadable) {
|
32
|
+
curlHandle.setOpt('UPLOAD', true);
|
33
|
+
curlHandle.setUploadStream(nodeReadable);
|
34
|
+
}
|
35
|
+
}
|
36
|
+
if (process.env.DEBUG) {
|
37
|
+
curlHandle.setOpt('VERBOSE', true);
|
38
|
+
}
|
39
|
+
curlHandle.setOpt('TRANSFER_ENCODING', false);
|
40
|
+
curlHandle.setOpt('HTTP_TRANSFER_DECODING', true);
|
41
|
+
curlHandle.setOpt('FOLLOWLOCATION', fetchRequest.redirect === 'follow');
|
42
|
+
curlHandle.setOpt('MAXREDIRS', 20);
|
43
|
+
curlHandle.setOpt('ACCEPT_ENCODING', '');
|
44
|
+
curlHandle.setOpt('CUSTOMREQUEST', fetchRequest.method);
|
15
45
|
const headersSerializer = fetchRequest.headersSerializer || utils_js_1.defaultHeadersSerializer;
|
16
46
|
let size;
|
17
|
-
const
|
47
|
+
const curlHeaders = headersSerializer(fetchRequest.headers, value => {
|
18
48
|
size = Number(value);
|
19
49
|
});
|
20
|
-
let easyNativeBinding;
|
21
|
-
const curlyOptions = {
|
22
|
-
// we want the unparsed binary response to be returned as a stream to us
|
23
|
-
curlyStreamResponse: true,
|
24
|
-
curlyResponseBodyParser: false,
|
25
|
-
curlyProgressCallback() {
|
26
|
-
if (easyNativeBinding == null) {
|
27
|
-
easyNativeBinding = this;
|
28
|
-
}
|
29
|
-
return fetchRequest.signal.aborted ? 1 : 0;
|
30
|
-
},
|
31
|
-
upload: nodeReadable != null,
|
32
|
-
transferEncoding: false,
|
33
|
-
httpTransferDecoding: true,
|
34
|
-
followLocation: fetchRequest.redirect === 'follow',
|
35
|
-
maxRedirs: 20,
|
36
|
-
acceptEncoding: '',
|
37
|
-
curlyStreamUpload: nodeReadable,
|
38
|
-
// this will just make libcurl use their own progress function (which is pretty neat)
|
39
|
-
// curlyProgressCallback() { return CurlProgressFunc.Continue },
|
40
|
-
// verbose: true,
|
41
|
-
httpHeader: curlyHeaders,
|
42
|
-
customRequest: fetchRequest.method,
|
43
|
-
};
|
44
50
|
if (size != null) {
|
45
|
-
|
51
|
+
curlHandle.setOpt('INFILESIZE', size);
|
46
52
|
}
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
53
|
+
curlHandle.setOpt('HTTPHEADER', curlHeaders);
|
54
|
+
curlHandle.enable(CurlFeature.NoHeaderParsing);
|
55
|
+
return new Promise(function promiseResolver(resolve, reject) {
|
56
|
+
let streamResolved = false;
|
57
|
+
if (fetchRequest['_signal']) {
|
58
|
+
fetchRequest['_signal'].onabort = () => {
|
59
|
+
if (streamResolved) {
|
60
|
+
curlHandle.pause(CurlPause.Recv);
|
61
|
+
}
|
62
|
+
else {
|
63
|
+
reject(new AbortError_js_1.PonyfillAbortError());
|
64
|
+
curlHandle.close();
|
65
|
+
}
|
66
|
+
};
|
51
67
|
}
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
throw new Error('redirects are not allowed');
|
68
|
+
curlHandle.once('end', function endListener() {
|
69
|
+
curlHandle.close();
|
70
|
+
});
|
71
|
+
curlHandle.once('error', function errorListener(error) {
|
72
|
+
if (error.isCurlError && error.code === CurlCode.CURLE_ABORTED_BY_CALLBACK) {
|
73
|
+
// this is expected
|
59
74
|
}
|
60
|
-
|
61
|
-
|
75
|
+
else {
|
76
|
+
// this is unexpected
|
77
|
+
reject(error);
|
62
78
|
}
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
79
|
+
curlHandle.close();
|
80
|
+
});
|
81
|
+
curlHandle.once('stream', function streamListener(stream, status, headersBuf) {
|
82
|
+
const headersFlat = headersBuf
|
83
|
+
.toString('utf8')
|
84
|
+
.split(/\r?\n|\r/g)
|
85
|
+
.filter(headerFilter => {
|
86
|
+
if (headerFilter && !headerFilter.startsWith('HTTP/')) {
|
87
|
+
if (fetchRequest.redirect === 'error' &&
|
88
|
+
(headerFilter.includes('location') || headerFilter.includes('Location'))) {
|
89
|
+
reject(new Error('redirect is not allowed'));
|
90
|
+
}
|
91
|
+
return true;
|
92
|
+
}
|
93
|
+
return false;
|
94
|
+
});
|
95
|
+
const headersInit = headersFlat.map(headerFlat => headerFlat.split(/:\s(.+)/).slice(0, 2));
|
96
|
+
resolve(new Response_js_1.PonyfillResponse(stream, {
|
97
|
+
status,
|
98
|
+
headers: headersInit,
|
99
|
+
url: fetchRequest.url,
|
100
|
+
}));
|
101
|
+
streamResolved = true;
|
102
|
+
});
|
103
|
+
curlHandle.perform();
|
77
104
|
});
|
78
105
|
}
|
79
106
|
exports.fetchCurl = fetchCurl;
|
package/cjs/fetchNodeHttp.js
CHANGED
@@ -5,7 +5,6 @@ const http_1 = require("http");
|
|
5
5
|
const https_1 = require("https");
|
6
6
|
const stream_1 = require("stream");
|
7
7
|
const zlib_1 = require("zlib");
|
8
|
-
const AbortError_js_1 = require("./AbortError.js");
|
9
8
|
const Request_js_1 = require("./Request.js");
|
10
9
|
const Response_js_1 = require("./Response.js");
|
11
10
|
const URL_js_1 = require("./URL.js");
|
@@ -24,7 +23,7 @@ function fetchNodeHttp(fetchRequest) {
|
|
24
23
|
try {
|
25
24
|
const requestFn = getRequestFnForProtocol(fetchRequest.url);
|
26
25
|
const nodeReadable = (fetchRequest.body != null
|
27
|
-
?
|
26
|
+
? (0, utils_js_1.isNodeReadable)(fetchRequest.body)
|
28
27
|
? fetchRequest.body
|
29
28
|
: stream_1.Readable.from(fetchRequest.body)
|
30
29
|
: null);
|
@@ -33,19 +32,9 @@ function fetchNodeHttp(fetchRequest) {
|
|
33
32
|
const nodeRequest = requestFn(fetchRequest.url, {
|
34
33
|
method: fetchRequest.method,
|
35
34
|
headers: nodeHeaders,
|
36
|
-
signal: fetchRequest
|
35
|
+
signal: fetchRequest['_signal'] ?? undefined,
|
37
36
|
agent: fetchRequest.agent,
|
38
37
|
});
|
39
|
-
// TODO: will be removed after v16 reaches EOL
|
40
|
-
fetchRequest.signal?.addEventListener('abort', () => {
|
41
|
-
if (!nodeRequest.aborted) {
|
42
|
-
nodeRequest.abort();
|
43
|
-
}
|
44
|
-
});
|
45
|
-
// TODO: will be removed after v16 reaches EOL
|
46
|
-
nodeRequest.once('abort', (reason) => {
|
47
|
-
reject(new AbortError_js_1.PonyfillAbortError(reason));
|
48
|
-
});
|
49
38
|
nodeRequest.once('response', nodeResponse => {
|
50
39
|
let responseBody = nodeResponse;
|
51
40
|
const contentEncoding = nodeResponse.headers['content-encoding'];
|
package/cjs/utils.js
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
"use strict";
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
-
exports.
|
3
|
+
exports.isNodeReadable = exports.isArrayBufferView = exports.fakePromise = exports.defaultHeadersSerializer = exports.getHeadersObj = void 0;
|
4
|
+
function isHeadersInstance(obj) {
|
5
|
+
return obj?.forEach != null;
|
6
|
+
}
|
4
7
|
function getHeadersObj(headers) {
|
5
|
-
if (headers == null || !(
|
8
|
+
if (headers == null || !isHeadersInstance(headers)) {
|
6
9
|
return headers;
|
7
10
|
}
|
8
11
|
const obj = {};
|
@@ -12,10 +15,6 @@ function getHeadersObj(headers) {
|
|
12
15
|
return obj;
|
13
16
|
}
|
14
17
|
exports.getHeadersObj = getHeadersObj;
|
15
|
-
function uint8ArrayToArrayBuffer(uint8array) {
|
16
|
-
return uint8array.buffer.slice(uint8array.byteOffset, uint8array.byteOffset + uint8array.byteLength);
|
17
|
-
}
|
18
|
-
exports.uint8ArrayToArrayBuffer = uint8ArrayToArrayBuffer;
|
19
18
|
function defaultHeadersSerializer(headers, onContentLength) {
|
20
19
|
const headerArray = [];
|
21
20
|
headers.forEach((value, key) => {
|
@@ -27,3 +26,48 @@ function defaultHeadersSerializer(headers, onContentLength) {
|
|
27
26
|
return headerArray;
|
28
27
|
}
|
29
28
|
exports.defaultHeadersSerializer = defaultHeadersSerializer;
|
29
|
+
function isPromise(val) {
|
30
|
+
return val?.then != null;
|
31
|
+
}
|
32
|
+
function fakePromise(value) {
|
33
|
+
if (isPromise(value)) {
|
34
|
+
return value;
|
35
|
+
}
|
36
|
+
// Write a fake promise to avoid the promise constructor
|
37
|
+
// being called with `new Promise` in the browser.
|
38
|
+
return {
|
39
|
+
then(resolve) {
|
40
|
+
if (resolve) {
|
41
|
+
const callbackResult = resolve(value);
|
42
|
+
if (isPromise(callbackResult)) {
|
43
|
+
return callbackResult;
|
44
|
+
}
|
45
|
+
return fakePromise(callbackResult);
|
46
|
+
}
|
47
|
+
return this;
|
48
|
+
},
|
49
|
+
catch() {
|
50
|
+
return this;
|
51
|
+
},
|
52
|
+
finally(cb) {
|
53
|
+
if (cb) {
|
54
|
+
const callbackResult = cb();
|
55
|
+
if (isPromise(callbackResult)) {
|
56
|
+
return callbackResult.then(() => value);
|
57
|
+
}
|
58
|
+
return fakePromise(value);
|
59
|
+
}
|
60
|
+
return this;
|
61
|
+
},
|
62
|
+
[Symbol.toStringTag]: 'Promise',
|
63
|
+
};
|
64
|
+
}
|
65
|
+
exports.fakePromise = fakePromise;
|
66
|
+
function isArrayBufferView(obj) {
|
67
|
+
return obj != null && obj.buffer != null && obj.byteLength != null && obj.byteOffset != null;
|
68
|
+
}
|
69
|
+
exports.isArrayBufferView = isArrayBufferView;
|
70
|
+
function isNodeReadable(obj) {
|
71
|
+
return obj != null && obj.pipe != null;
|
72
|
+
}
|
73
|
+
exports.isNodeReadable = isNodeReadable;
|
package/esm/Blob.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-unsafe-declaration-merging */
|
1
2
|
import { PonyfillReadableStream } from './ReadableStream.js';
|
2
|
-
import {
|
3
|
+
import { fakePromise, isArrayBufferView } from './utils.js';
|
3
4
|
function getBlobPartAsBuffer(blobPart) {
|
4
5
|
if (typeof blobPart === 'string') {
|
5
6
|
return Buffer.from(blobPart);
|
@@ -7,10 +8,7 @@ function getBlobPartAsBuffer(blobPart) {
|
|
7
8
|
else if (Buffer.isBuffer(blobPart)) {
|
8
9
|
return blobPart;
|
9
10
|
}
|
10
|
-
else if (blobPart
|
11
|
-
return Buffer.from(blobPart);
|
12
|
-
}
|
13
|
-
else if ('buffer' in blobPart) {
|
11
|
+
else if (isArrayBufferView(blobPart)) {
|
14
12
|
return Buffer.from(blobPart.buffer, blobPart.byteOffset, blobPart.byteLength);
|
15
13
|
}
|
16
14
|
else {
|
@@ -18,93 +16,115 @@ function getBlobPartAsBuffer(blobPart) {
|
|
18
16
|
}
|
19
17
|
}
|
20
18
|
function isBlob(obj) {
|
21
|
-
return obj != null &&
|
19
|
+
return obj != null && obj.arrayBuffer != null;
|
22
20
|
}
|
23
21
|
// Will be removed after v14 reaches EOL
|
24
22
|
// Needed because v14 doesn't have .stream() implemented
|
25
23
|
export class PonyfillBlob {
|
26
24
|
constructor(blobParts, options) {
|
27
25
|
this.blobParts = blobParts;
|
26
|
+
this._size = null;
|
28
27
|
this.type = options?.type || 'application/octet-stream';
|
29
28
|
this.encoding = options?.encoding || 'utf8';
|
29
|
+
this._size = options?.size || null;
|
30
|
+
if (blobParts.length === 1 && isBlob(blobParts[0])) {
|
31
|
+
return blobParts[0];
|
32
|
+
}
|
30
33
|
}
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
arrayBuffer() {
|
35
|
+
if (this.blobParts.length === 1) {
|
36
|
+
const blobPart = this.blobParts[0];
|
34
37
|
if (isBlob(blobPart)) {
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
+
return blobPart.arrayBuffer();
|
39
|
+
}
|
40
|
+
return fakePromise(getBlobPartAsBuffer(blobPart));
|
41
|
+
}
|
42
|
+
const jobs = [];
|
43
|
+
const bufferChunks = this.blobParts.map((blobPart, i) => {
|
44
|
+
if (isBlob(blobPart)) {
|
45
|
+
jobs.push(blobPart.arrayBuffer().then(arrayBuf => {
|
46
|
+
bufferChunks[i] = Buffer.from(arrayBuf, undefined, blobPart.size);
|
47
|
+
}));
|
48
|
+
return undefined;
|
38
49
|
}
|
39
50
|
else {
|
40
|
-
|
41
|
-
bufferChunks.push(buf);
|
51
|
+
return getBlobPartAsBuffer(blobPart);
|
42
52
|
}
|
53
|
+
});
|
54
|
+
if (jobs.length > 0) {
|
55
|
+
return Promise.all(jobs).then(() => Buffer.concat(bufferChunks, this._size || undefined));
|
43
56
|
}
|
44
|
-
return Buffer.concat(bufferChunks);
|
57
|
+
return fakePromise(Buffer.concat(bufferChunks, this._size || undefined));
|
45
58
|
}
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
}
|
50
|
-
async text() {
|
51
|
-
let text = '';
|
52
|
-
for (const blobPart of this.blobParts) {
|
59
|
+
text() {
|
60
|
+
if (this.blobParts.length === 1) {
|
61
|
+
const blobPart = this.blobParts[0];
|
53
62
|
if (typeof blobPart === 'string') {
|
54
|
-
|
55
|
-
}
|
56
|
-
else if ('text' in blobPart) {
|
57
|
-
text += await blobPart.text();
|
63
|
+
return fakePromise(blobPart);
|
58
64
|
}
|
59
|
-
|
60
|
-
|
61
|
-
text += buf.toString(this.encoding);
|
65
|
+
if (isBlob(blobPart)) {
|
66
|
+
return blobPart.text();
|
62
67
|
}
|
68
|
+
const buf = getBlobPartAsBuffer(blobPart);
|
69
|
+
return fakePromise(buf.toString(this.encoding));
|
63
70
|
}
|
64
|
-
return
|
71
|
+
return this.arrayBuffer().then(buf => buf.toString(this.encoding));
|
65
72
|
}
|
66
73
|
get size() {
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
size += blobPart.byteLength;
|
74
|
+
if (this._size == null) {
|
75
|
+
this._size = 0;
|
76
|
+
for (const blobPart of this.blobParts) {
|
77
|
+
if (typeof blobPart === 'string') {
|
78
|
+
this._size += Buffer.byteLength(blobPart);
|
79
|
+
}
|
80
|
+
else if (isBlob(blobPart)) {
|
81
|
+
this._size += blobPart.size;
|
82
|
+
}
|
83
|
+
else if (isArrayBufferView(blobPart)) {
|
84
|
+
this._size += blobPart.byteLength;
|
85
|
+
}
|
80
86
|
}
|
81
87
|
}
|
82
|
-
return
|
88
|
+
return this._size;
|
83
89
|
}
|
84
90
|
stream() {
|
85
|
-
|
91
|
+
if (this.blobParts.length === 1) {
|
92
|
+
const blobPart = this.blobParts[0];
|
93
|
+
if (isBlob(blobPart)) {
|
94
|
+
return blobPart.stream();
|
95
|
+
}
|
96
|
+
const buf = getBlobPartAsBuffer(blobPart);
|
97
|
+
return new PonyfillReadableStream({
|
98
|
+
start: controller => {
|
99
|
+
controller.enqueue(buf);
|
100
|
+
controller.close();
|
101
|
+
},
|
102
|
+
});
|
103
|
+
}
|
104
|
+
let blobPartIterator;
|
86
105
|
return new PonyfillReadableStream({
|
87
106
|
start: controller => {
|
88
|
-
|
89
|
-
if (partQueue.length === 0) {
|
107
|
+
if (this.blobParts.length === 0) {
|
90
108
|
controller.close();
|
109
|
+
return;
|
91
110
|
}
|
111
|
+
blobPartIterator = this.blobParts[Symbol.iterator]();
|
92
112
|
},
|
93
|
-
pull:
|
94
|
-
const blobPart =
|
113
|
+
pull: controller => {
|
114
|
+
const { value: blobPart, done } = blobPartIterator.next();
|
115
|
+
if (done) {
|
116
|
+
controller.close();
|
117
|
+
return;
|
118
|
+
}
|
95
119
|
if (blobPart) {
|
96
120
|
if (isBlob(blobPart)) {
|
97
|
-
|
98
|
-
|
99
|
-
|
121
|
+
return blobPart.arrayBuffer().then(arrayBuffer => {
|
122
|
+
const buf = Buffer.from(arrayBuffer, undefined, blobPart.size);
|
123
|
+
controller.enqueue(buf);
|
124
|
+
});
|
100
125
|
}
|
101
|
-
|
102
|
-
|
103
|
-
controller.enqueue(buf);
|
104
|
-
}
|
105
|
-
}
|
106
|
-
else {
|
107
|
-
controller.close();
|
126
|
+
const buf = getBlobPartAsBuffer(blobPart);
|
127
|
+
controller.enqueue(buf);
|
108
128
|
}
|
109
129
|
},
|
110
130
|
});
|