Skip to content

Commit

Permalink
refactor in sync with node-fetch
Browse files Browse the repository at this point in the history
  • Loading branch information
tinovyatkin committed Jun 7, 2020
1 parent 870be1e commit a320b45
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 82 deletions.
4 changes: 0 additions & 4 deletions index.d.ts

This file was deleted.

152 changes: 79 additions & 73 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,107 +1,120 @@
// Based on https://github.com/tmpvar/jsdom/blob/aa85b2abf07766ff7bf5c1f6daafb3726f2f2db5/lib/jsdom/living/blob.js
// (MIT licensed)

const {Readable: ReadableStream} = require('stream');
const {Readable} = require('stream');
const {types} = require('util');

/**
* @type {WeakMap<Blob, { type: string, buffer: Buffer }}
*/
const wm = new WeakMap();

class Blob {
/**
* 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.
* @param {(ArrayBufferLike | ArrayBufferView | Blob | Buffer | string)[]} blobParts
* @param {{ type?: string }} [options]
*/
constructor(blobParts = [], options = {type: ''}) {
const buffers = [];
let size = 0;

blobParts.forEach(element => {
let buffer;
if (element instanceof Buffer) {
buffer = element;
} else if (ArrayBuffer.isView(element)) {
buffer = Buffer.from(element.buffer, element.byteOffset, element.byteLength);
} else if (element instanceof ArrayBuffer) {
buffer = Buffer.from(element);
} else if (element instanceof Blob) {
buffer = wm.get(element).buffer;
} else {
buffer = Buffer.from(typeof element === 'string' ? element : String(element));
const buffers = blobParts.map(element => {
if (Buffer.isBuffer(element)) {
return element;
}

size += buffer.length;
buffers.push(buffer);
if (ArrayBuffer.isView(element)) {
return Buffer.from(
element.buffer,
element.byteOffset,
element.byteLength
);
}

if (types.isAnyArrayBuffer(element)) {
return Buffer.from(element);
}

if (wm.has(element)) {
return wm.get(element).buffer;
}

return Buffer.from(
typeof element === 'string' ? element : String(element)
);
});

const buffer = Buffer.concat(buffers, size);
const buffer = Buffer.concat(buffers);

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

wm.set(this, {
type: /[^\u0020-\u007E]/.test(type) ? '' : type,
size,
buffer
});
}

/**
* The Blob interface's size property returns the size of the Blob in bytes.
*/
get size() {
return wm.get(this).size;
return wm.get(this).buffer.byteLength;
}

/**
* The type property of a Blob object returns the MIME type of the file.
*/
get type() {
return wm.get(this).type;
}

text() {
return Promise.resolve(wm.get(this).buffer.toString());
/**
* 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.
*/
async text() {
return wm.get(this).buffer.toString();
}

arrayBuffer() {
/**
* 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.
*/
async arrayBuffer() {
const buf = wm.get(this).buffer;
const ab = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
return Promise.resolve(ab);
const ab = buf.buffer.slice(
buf.byteOffset,
buf.byteOffset + buf.byteLength
);
return ab;
}

/**
* The Blob interface's stream() method returns a ReadableStream which upon reading returns the data contained within the Blob.
*/
stream() {
const readable = new ReadableStream();
readable._read = () => { };
readable.push(wm.get(this).buffer);
readable.push(null);
return readable;
return Readable.from(wm.get(this).buffer);
}

get [Symbol.toStringTag]() {
return 'Blob';
}

/**
* @returns {string}
*/
toString() {
return '[object Blob]';
return Object.prototype.toString.call(this);
}

slice(...args) {
const {size} = this;

const start = args[0];
const end = args[1];
let relativeStart;
let relativeEnd;

if (start === undefined) {
relativeStart = 0; //
} else if (start < 0) {
relativeStart = Math.max(size + start, 0); //
} else {
relativeStart = Math.min(start, size);
}

if (end === undefined) {
relativeEnd = size; //
} else if (end < 0) {
relativeEnd = Math.max(size + end, 0); //
} else {
relativeEnd = Math.min(end, size);
}

const span = Math.max(relativeEnd - relativeStart, 0);
const slicedBuffer = wm.get(this).buffer.slice(
relativeStart,
relativeStart + span
);
const blob = new Blob([], {type: args[2]});
const _ = wm.get(blob);
_.buffer = slicedBuffer;
return blob;
/**
* 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.
*
* @param {number} [start]
* @param {number} [end]
* @param {string} [contentType]
*/
slice(start, end, contentType) {
return new Blob([wm
.get(this)
.buffer.subarray(start, end)], {type: contentType});
}
}

Expand All @@ -111,11 +124,4 @@ Object.defineProperties(Blob.prototype, {
slice: {enumerable: true}
});

Object.defineProperty(Blob.prototype, Symbol.toStringTag, {
value: 'Blob',
writable: false,
enumerable: false,
configurable: true
});

module.exports = Blob;
13 changes: 8 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,16 @@
"lint": "xo",
"test": "xo && ava",
"report": "nyc ava",
"coverage": "nyc --reporter json --reporter text ava && codecov -f coverage/coverage-final.json"
"coverage": "nyc --reporter json --reporter text ava && codecov -f coverage/coverage-final.json",
"prepublishOnly": "npx typescript --declaration --emitDeclarationOnly --allowJs index.js"
},
"repository": "https://github.com/node-fetch/fetch-blob.git",
"keywords": [
"blob",
"node-fetch"
],
"engines": {
"node": ">=6"
"node": ">=10.17"
},
"author": "David Frank",
"license": "MIT",
Expand All @@ -36,14 +37,16 @@
"xo": "^0.30.0"
},
"xo": {
"rules": {
"node/no-unsupported-features/node-builtins": 0
},
"overrides": [
{
"files": "test.js",
"rules": {
"node/no-unsupported-features/es-syntax": 0,
"node/no-unsupported-features/node-builtins": 0
"node/no-unsupported-features/es-syntax": 0
}
}
]
}
}
}

0 comments on commit a320b45

Please sign in to comment.