Skip to content

Commit 7180baa

Browse files
committed
refactor in sync with node-fetch
1 parent 870be1e commit 7180baa

File tree

3 files changed

+78
-56
lines changed

3 files changed

+78
-56
lines changed

index.d.ts

Lines changed: 0 additions & 4 deletions
This file was deleted.

index.js

Lines changed: 70 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,109 @@
11
// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
22
// (MIT licensed)
33

4-
const {Readable: ReadableStream} = require('stream');
4+
const { Readable } = require('stream');
5+
const { types } = require('util');
56

7+
/**
8+
* @type {WeakMap<Blob, { type: string, buffer: Buffer }}
9+
*/
610
const wm = new WeakMap();
711

812
class Blob {
9-
constructor(blobParts = [], options = {type: ''}) {
10-
const buffers = [];
11-
let size = 0;
12-
13-
blobParts.forEach(element => {
14-
let buffer;
15-
if (element instanceof Buffer) {
16-
buffer = element;
17-
} else if (ArrayBuffer.isView(element)) {
18-
buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
19-
} else if (element instanceof ArrayBuffer) {
20-
buffer = Buffer.from(element);
21-
} else if (element instanceof Blob) {
22-
buffer = wm.get(element).buffer;
23-
} else {
24-
buffer = Buffer.from(typeof element === 'string' ? element : String(element));
13+
/**
14+
* The Blob() constructor returns a new Blob object. The content of the blob consists of the concatenation of the values given in the parameter array.
15+
* @param {(ArrayBufferLike | ArrayBufferView | Blob | Buffer | string)[]} blobParts
16+
* @param {{ type?: string }} [options]
17+
*/
18+
constructor(blobParts = [], options = { type: '' }) {
19+
const buffers = blobParts.map(element => {
20+
if (Buffer.isBuffer(element)) {
21+
return element;
2522
}
2623

27-
size += buffer.length;
28-
buffers.push(buffer);
24+
if (ArrayBuffer.isView(element)) {
25+
return Buffer.from(element.buffer, element.byteOffset, element.byteLength);
26+
}
27+
28+
if (types.isAnyArrayBuffer(element)) {
29+
return Buffer.from(element);
30+
}
31+
32+
if (wm.has(element)) {
33+
return wm.get(element).buffer;
34+
}
35+
36+
return Buffer.from(typeof element === 'string' ? element : String(element));
2937
});
3038

31-
const buffer = Buffer.concat(buffers, size);
39+
const buffer = Buffer.concat(buffers);
3240

3341
const type = options.type === undefined ? '' : String(options.type).toLowerCase();
3442

3543
wm.set(this, {
3644
type: /[^\u0020-\u007E]/.test(type) ? '' : type,
37-
size,
3845
buffer
3946
});
4047
}
4148

49+
/**
50+
* The Blob interface's size property returns the size of the Blob in bytes.
51+
*/
4252
get size() {
43-
return wm.get(this).size;
53+
return wm.get(this).buffer.byteLength;
4454
}
4555

56+
/**
57+
* The type property of a Blob object returns the MIME type of the file.
58+
*/
4659
get type() {
4760
return wm.get(this).type;
4861
}
4962

50-
text() {
51-
return Promise.resolve(wm.get(this).buffer.toString());
63+
/**
64+
* The text() method in the Blob interface returns a Promise that resolves with a string containing the contents of the blob, interpreted as UTF-8.
65+
*/
66+
async text() {
67+
return wm.get(this).buffer.toString();
5268
}
5369

54-
arrayBuffer() {
70+
/**
71+
* The arrayBuffer() method in the Blob interface returns a Promise that resolves with the contents of the blob as binary data contained in an ArrayBuffer.
72+
*/
73+
async arrayBuffer() {
5574
const buf = wm.get(this).buffer;
5675
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
57-
return Promise.resolve(ab);
76+
return ab;
5877
}
5978

79+
/**
80+
* The Blob interface's stream() method returns a ReadableStream which upon reading returns the data contained within the Blob.
81+
*/
6082
stream() {
61-
const readable = new ReadableStream();
62-
readable._read = () => { };
63-
readable.push(wm.get(this).buffer);
64-
readable.push(null);
65-
return readable;
83+
return Readable.from(wm.get(this).buffer);
84+
}
85+
86+
get [Symbol.toStringTag]() {
87+
return 'Blob';
6688
}
6789

90+
/**
91+
* @returns {string}
92+
*/
6893
toString() {
69-
return '[object Blob]';
94+
return Object.prototype.toString.call(this);
7095
}
7196

72-
slice(...args) {
73-
const {size} = this;
97+
/**
98+
* The Blob interface's slice() method creates and returns a new Blob object which contains data from a subset of the blob on which it's called.
99+
*
100+
* @param {number} [start]
101+
* @param {number} [end]
102+
* @param {string} [contentType]
103+
*/
104+
slice(start, end, contentType) {
105+
const { size } = this;
74106

75-
const start = args[0];
76-
const end = args[1];
77107
let relativeStart;
78108
let relativeEnd;
79109

@@ -98,24 +128,17 @@ class Blob {
98128
relativeStart,
99129
relativeStart + span
100130
);
101-
const blob = new Blob([], {type: args[2]});
131+
const blob = new Blob([], { type: contentType });
102132
const _ = wm.get(blob);
103133
_.buffer = slicedBuffer;
104134
return blob;
105135
}
106136
}
107137

108138
Object.defineProperties(Blob.prototype, {
109-
size: {enumerable: true},
110-
type: {enumerable: true},
111-
slice: {enumerable: true}
112-
});
113-
114-
Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
115-
value: 'Blob',
116-
writable: false,
117-
enumerable: false,
118-
configurable: true
139+
size: { enumerable: true },
140+
type: { enumerable: true },
141+
slice: { enumerable: true }
119142
});
120143

121144
module.exports = Blob;

package.json

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
"lint": "xo",
1212
"test": "xo && ava",
1313
"report": "nyc ava",
14-
"coverage": "nyc --reporter json --reporter text ava && codecov -f coverage/coverage-final.json"
14+
"coverage": "nyc --reporter json --reporter text ava && codecov -f coverage/coverage-final.json",
15+
"prepublishOnly": "npx typescript --declaration --emitDeclarationOnly --allowJs index.js"
1516
},
1617
"repository": "https://github.com/node-fetch/fetch-blob.git",
1718
"keywords": [
1819
"blob",
1920
"node-fetch"
2021
],
2122
"engines": {
22-
"node": ">=6"
23+
"node": ">=10.17"
2324
},
2425
"author": "David Frank",
2526
"license": "MIT",
@@ -36,14 +37,16 @@
3637
"xo": "^0.30.0"
3738
},
3839
"xo": {
40+
"rules": {
41+
"node/no-unsupported-features/node-builtins": 0
42+
},
3943
"overrides": [
4044
{
4145
"files": "test.js",
4246
"rules": {
43-
"node/no-unsupported-features/es-syntax": 0,
44-
"node/no-unsupported-features/node-builtins": 0
47+
"node/no-unsupported-features/es-syntax": 0
4548
}
4649
}
4750
]
4851
}
49-
}
52+
}

0 commit comments

Comments
 (0)