Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v8.0.20240630 #14

Merged
merged 1 commit into from
Jun 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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