Skip to content

Commit

Permalink
v8.0.20240630
Browse files Browse the repository at this point in the history
  • Loading branch information
bjornstar committed Jun 30, 2024
1 parent 53d1119 commit e761582
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 120 deletions.
7 changes: 4 additions & 3 deletions .github/workflows/node.js.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,15 @@ jobs:

strategy:
matrix:
node-version: [12, 14, 16, 17]
node-version: [12, 14, 16, 18, 20, 22]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
- run: npm i
- run: npm run build --if-present
- run: npm run lint
- run: npm test
205 changes: 106 additions & 99 deletions Blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,40 @@
* See https://github.com/eligrey/Blob.js/blob/master/LICENSE.md
*/

function array2base64 (input) {
var byteToCharMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

var output = [];

for (var i = 0; i < input.length; i += 3) {
var byte1 = input[i];
var haveByte2 = i + 1 < input.length;
var byte2 = haveByte2 ? input[i + 1] : 0;
var haveByte3 = i + 2 < input.length;
var byte3 = haveByte3 ? input[i + 2] : 0;

var outByte1 = byte1 >> 2;
var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
var outByte4 = byte3 & 0x3F;

if (!haveByte3) {
outByte4 = 64;

if (!haveByte2) {
outByte3 = 64;
}
}

output.push(
byteToCharMap[outByte1], byteToCharMap[outByte2],
byteToCharMap[outByte3], byteToCharMap[outByte4]
);
}

return output.join("");
}

(function(global) {
(function (factory) {
if (typeof define === "function" && define.amd) {
Expand Down Expand Up @@ -263,39 +297,6 @@
}
return view;
}
function array2base64 (input) {
var byteToCharMap = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

var output = [];

for (var i = 0; i < input.length; i += 3) {
var byte1 = input[i];
var haveByte2 = i + 1 < input.length;
var byte2 = haveByte2 ? input[i + 1] : 0;
var haveByte3 = i + 2 < input.length;
var byte3 = haveByte3 ? input[i + 2] : 0;

var outByte1 = byte1 >> 2;
var outByte2 = ((byte1 & 0x03) << 4) | (byte2 >> 4);
var outByte3 = ((byte2 & 0x0F) << 2) | (byte3 >> 6);
var outByte4 = byte3 & 0x3F;

if (!haveByte3) {
outByte4 = 64;

if (!haveByte2) {
outByte3 = 64;
}
}

output.push(
byteToCharMap[outByte1], byteToCharMap[outByte2],
byteToCharMap[outByte3], byteToCharMap[outByte4]
);
}

return output.join("");
}

var create = Object.create || function (a) {
function c () {}
Expand Down Expand Up @@ -384,6 +385,7 @@
this.type = this.type.toLowerCase();
}
}
Blob.isPolyfill = true;

Blob.prototype.arrayBuffer = function () {
return Promise.resolve(this._buffer.buffer || this._buffer);
Expand Down Expand Up @@ -415,6 +417,7 @@
return a;
}

File.isPolyfill = true;
File.prototype = create(Blob.prototype);
File.prototype.constructor = File;

Expand All @@ -430,79 +433,21 @@
return "[object File]";
};

/********************************************************/
/* FileReader constructor */
/********************************************************/
function FileReader () {
if (!(this instanceof FileReader)) {
throw new TypeError("Failed to construct 'FileReader': Please use the 'new' operator, this DOM object constructor cannot be called as a function.");
}

var delegate = document.createDocumentFragment();
this.addEventListener = delegate.addEventListener;
this.dispatchEvent = function (evt) {
var local = this["on" + evt.type];
if (typeof local === "function") local(evt);
delegate.dispatchEvent(evt);
};
this.removeEventListener = delegate.removeEventListener;
}

function _read (fr, blob, kind) {
if (!(blob instanceof Blob)) {
throw new TypeError("Failed to execute '" + kind + "' on 'FileReader': parameter 1 is not of type 'Blob'.");
}

fr.result = "";

setTimeout(function () {
this.readyState = FileReader.LOADING;
fr.dispatchEvent(new Event("load"));
fr.dispatchEvent(new Event("loadend"));
});
}

FileReader.EMPTY = 0;
FileReader.LOADING = 1;
FileReader.DONE = 2;
FileReader.prototype.error = null;
FileReader.prototype.onabort = null;
FileReader.prototype.onerror = null;
FileReader.prototype.onload = null;
FileReader.prototype.onloadend = null;
FileReader.prototype.onloadstart = null;
FileReader.prototype.onprogress = null;

FileReader.prototype.readAsDataURL = function (blob) {
_read(this, blob, "readAsDataURL");
this.result = "data:" + blob.type + ";base64," + array2base64(blob._buffer);
};

FileReader.prototype.readAsText = function (blob) {
_read(this, blob, "readAsText");
this.result = textDecode(blob._buffer);
};

FileReader.prototype.readAsArrayBuffer = function (blob) {
_read(this, blob, "readAsText");
// return ArrayBuffer when possible
this.result = (blob._buffer.buffer || blob._buffer).slice();
};

FileReader.prototype.abort = function () {};

/********************************************************/
/* URL */
/********************************************************/

URL.createObjectURL = function (blob) {
return blob instanceof Blob
? "data:" + blob.type + ";base64," + array2base64(blob._buffer)
: createObjectURL.call(URL, blob);
};
URL.createObjectURL.isPolyfill = true;

URL.revokeObjectURL = function (url) {
revokeObjectURL && revokeObjectURL.call(URL, url);
};
URL.revokeObjectURL.isPolyfill = true;

/********************************************************/
/* XHR */
Expand All @@ -521,12 +466,10 @@

exports.Blob = Blob;
exports.File = File;
exports.FileReader = FileReader;
exports.URL = URL;
}

function fixFileAndXHR () {
var isIE = !!global.ActiveXObject || (
var isIE = !!global.ActiveXObject || (typeof document !== "undefined" &&
"-ms-scroll-limit" in document.documentElement.style &&
"-ms-ime-align" in document.documentElement.style
);
Expand All @@ -549,7 +492,6 @@
try {
new File([], "");
exports.File = global.File;
exports.FileReader = global.FileReader;
} catch (e) {
try {
exports.File = new Function("class File extends Blob {" +
Expand All @@ -563,7 +505,7 @@
"return new File([], \"\"), File"
)();
} catch (e) {
exports.File = function (b, d, c) {
exports.File = function File(b, d, c) {
var blob = new Blob(b, c);
var t = c && void 0 !== c.lastModified ? new Date(c.lastModified) : new Date();

Expand All @@ -581,6 +523,7 @@
return blob;
};
}
exports.File.isPolyfill = true;
}
}

Expand All @@ -594,6 +537,70 @@
FakeBlobBuilder();
}

/********************************************************/
/* FileReader constructor */
/********************************************************/
function FileReader () {
if (!(this instanceof FileReader)) {
throw new TypeError("Failed to construct 'FileReader': Please use the 'new' operator, this DOM object constructor cannot be called as a function.");
}

var delegate = document.createDocumentFragment();
this.addEventListener = delegate.addEventListener;
this.dispatchEvent = function (evt) {
var local = this["on" + evt.type];
if (typeof local === "function") local(evt);
delegate.dispatchEvent(evt);
};
this.removeEventListener = delegate.removeEventListener;
}

function _read (fr, blob, kind) {
if (!(blob instanceof exports.Blob)) {
throw new TypeError("Failed to execute '" + kind + "' on 'FileReader': parameter 1 is not of type 'Blob'.");
}

fr.result = "";

setTimeout(function () {
this.readyState = FileReader.LOADING;
fr.dispatchEvent(new Event("load"));
fr.dispatchEvent(new Event("loadend"));
});
}

FileReader.EMPTY = 0;
FileReader.LOADING = 1;
FileReader.DONE = 2;
FileReader.prototype.error = null;
FileReader.prototype.onabort = null;
FileReader.prototype.onerror = null;
FileReader.prototype.onload = null;
FileReader.prototype.onloadend = null;
FileReader.prototype.onloadstart = null;
FileReader.prototype.onprogress = null;

FileReader.prototype.readAsDataURL = function (blob) {
_read(this, blob, "readAsDataURL");
this.result = "data:" + blob.type + ";base64," + array2base64(blob._buffer);
};

FileReader.prototype.readAsText = function (blob) {
_read(this, blob, "readAsText");
this.result = textDecode(blob._buffer);
};

FileReader.prototype.readAsArrayBuffer = function (blob) {
_read(this, blob, "readAsText");
// return ArrayBuffer when possible
this.result = (blob._buffer.buffer || blob._buffer).slice();
};

FileReader.prototype.abort = function () {};

exports.FileReader = global.FileReader || FileReader;
exports.URL = global.URL || URL;

if (strTag) {
if (!exports.File.prototype[strTag]) exports.File.prototype[strTag] = "File";
if (!exports.Blob.prototype[strTag]) exports.Blob.prototype[strTag] = "Blob";
Expand Down
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# `blob-polyfill` CHANGELOG

## v8.0.20240630
* [Blob.js] Change Blob.prototype to global.Blob.prototype (@tmisirpash)
* [Blob.js] Make it work in environments where global.Blob exists, but global.FileReader does not (@bjornstar)
* [Blob.js] Add `isPolyfill` property to the polyfilled versions so we can differentiate them (@bjornstar)
* [test] Unskip tests and update to work in environments with global.Blob & global.File & global.URL (@bjornstar)
* [.github] Update action versions and test node v12-v22 (@bjornstar)

## v7.0.20220408
* [Blob.js] Do not modify array that is passed into constructor (@zyrong)
* [.github] Start automated tests on github (@bjornstar)
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "blob-polyfill",
"version": "7.0.20220408",
"version": "8.0.20240630",
"description": "Blob.js implements the W3C Blob interface in browsers that do not natively support it.",
"main": "Blob.js",
"scripts": {
Expand Down
Loading

0 comments on commit e761582

Please sign in to comment.