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

BlobManager: implement Blob from ArrayBuffer #39276

Closed
Closed
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
5 changes: 4 additions & 1 deletion packages/react-native/Libraries/Blob/Blob.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ class Blob {
* Currently we only support creating Blobs from other Blobs.
* Reference: https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob
*/
constructor(parts: Array<Blob | string> = [], options?: BlobOptions) {
constructor(
parts: Array<$ArrayBufferView | ArrayBuffer | Blob | string> = [],
options?: BlobOptions,
) {
const BlobManager = require('./BlobManager');
this.data = BlobManager.createFromParts(parts, options).data;
}
Expand Down
19 changes: 9 additions & 10 deletions packages/react-native/Libraries/Blob/BlobManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {BlobCollector, BlobData, BlobOptions} from './BlobTypes';

import NativeBlobModule from './NativeBlobModule';
import invariant from 'invariant';
import {fromByteArray} from 'base64-js';

const Blob = require('./Blob');
const BlobRegistry = require('./BlobRegistry');
Expand Down Expand Up @@ -59,22 +60,20 @@ class BlobManager {
* Create blob from existing array of blobs.
*/
static createFromParts(
parts: Array<Blob | string>,
parts: Array<$ArrayBufferView | ArrayBuffer | Blob | string>,
options?: BlobOptions,
): Blob {
invariant(NativeBlobModule, 'NativeBlobModule is available.');

const blobId = uuidv4();
const items = parts.map(part => {
if (
part instanceof ArrayBuffer ||
(global.ArrayBufferView && part instanceof global.ArrayBufferView)
) {
throw new Error(
"Creating blobs from 'ArrayBuffer' and 'ArrayBufferView' are not supported",
);
}
if (part instanceof Blob) {
if (part instanceof ArrayBuffer || ArrayBuffer.isView(part)) {
return {
// $FlowFixMe[incompatible-cast]
data: fromByteArray(new Uint8Array((part: ArrayBuffer))),
type: 'string',
};
} else if (part instanceof Blob) {
return {
data: part.data,
type: 'blob',
Expand Down
2 changes: 1 addition & 1 deletion packages/react-native/Libraries/Blob/File.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class File extends Blob {
* Constructor for JS consumers.
*/
constructor(
parts: Array<Blob | string>,
parts: Array<$ArrayBufferView | ArrayBuffer | Blob | string>,
name: string,
options?: BlobOptions,
) {
Expand Down
13 changes: 10 additions & 3 deletions packages/react-native/Libraries/Blob/__tests__/Blob-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ jest.setMock('../../BatchedBridge/NativeModules', {
});

const Blob = require('../Blob');
const {fromByteArray} = require('base64-js');

describe('Blob', function () {
it('should create empty blob', () => {
Expand All @@ -26,7 +27,7 @@ describe('Blob', function () {
expect(blob.type).toBe('');
});

it('should create blob from other blobs and strings', () => {
it('should create blob from ArrayBuffer, other blobs, strings', () => {
const blobA = new Blob();
const blobB = new Blob();
const textA = 'i \u2665 dogs';
Expand All @@ -43,14 +44,20 @@ describe('Blob', function () {
blobA.data.size = 34540;
blobB.data.size = 65452;

const blob = new Blob([blobA, blobB, textA, textB, textC]);
const buffer = new ArrayBuffer(4);

const blob = new Blob([blobA, blobB, textA, textB, textC, buffer]);

expect(blob.size).toBe(
blobA.size +
blobB.size +
global.Buffer.byteLength(textA, 'UTF-8') +
global.Buffer.byteLength(textB, 'UTF-8') +
global.Buffer.byteLength(textC, 'UTF-8'),
global.Buffer.byteLength(textC, 'UTF-8') +
global.Buffer.byteLength(
fromByteArray(new Uint8Array(buffer)),
'UTF-8',
),
);
expect(blob.type).toBe('');
});
Expand Down