From ee379aaaa0cd04f5c171e5a225adba2951fa7ba0 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Tue, 14 Mar 2023 11:58:11 -0700 Subject: [PATCH] FileReader#readAsArrayBuffer (#36332) Summary: Fixes a number of issues with third party libraries that use `Blob#arrayBuffer` or `FileReader#readAsArrayBuffer`, including https://github.com/facebook/react-native/issues/30769 #34402 https://github.com/facebook/react-native/issues/20091 #21209 ## Changelog [INTERNAL] [FIXED] - Implemented FileReader#readAsArrayBuffer Pull Request resolved: https://github.com/facebook/react-native/pull/36332 Test Plan: Added a test which fails against current release but passes after code changes. Reviewed By: christophpurrer Differential Revision: D43907171 Pulled By: javache fbshipit-source-id: 73d622ec569a282b6394732b9a0dc687b447fb62 --- Libraries/Blob/FileReader.js | 32 +++++++++++++++++++-- Libraries/Blob/__tests__/FileReader-test.js | 12 ++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/Libraries/Blob/FileReader.js b/Libraries/Blob/FileReader.js index 57b3093cf6b025..3e20afe5c6e1a7 100644 --- a/Libraries/Blob/FileReader.js +++ b/Libraries/Blob/FileReader.js @@ -11,6 +11,7 @@ import type Blob from './Blob'; import NativeFileReaderModule from './NativeFileReaderModule'; +import {toByteArray} from 'base64-js'; const EventTarget = require('event-target-shim'); @@ -74,8 +75,35 @@ class FileReader extends (EventTarget(...READER_EVENTS): any) { } } - readAsArrayBuffer(): any { - throw new Error('FileReader.readAsArrayBuffer is not implemented'); + readAsArrayBuffer(blob: ?Blob): void { + this._aborted = false; + + if (blob == null) { + throw new TypeError( + "Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1 is not of type 'Blob'", + ); + } + + NativeFileReaderModule.readAsDataURL(blob.data).then( + (text: string) => { + if (this._aborted) { + return; + } + + const base64 = text.split(',')[1]; + const typedArray = toByteArray(base64); + + this._result = typedArray.buffer; + this._setReadyState(DONE); + }, + error => { + if (this._aborted) { + return; + } + this._error = error; + this._setReadyState(DONE); + }, + ); } readAsDataURL(blob: ?Blob): void { diff --git a/Libraries/Blob/__tests__/FileReader-test.js b/Libraries/Blob/__tests__/FileReader-test.js index 1e1ac1ab7a4dd6..8e28b84c669f77 100644 --- a/Libraries/Blob/__tests__/FileReader-test.js +++ b/Libraries/Blob/__tests__/FileReader-test.js @@ -38,4 +38,16 @@ describe('FileReader', function () { }); expect(e.target.result).toBe('data:text/plain;base64,NDI='); }); + + it('should read blob as ArrayBuffer', async () => { + const e = await new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = resolve; + reader.onerror = reject; + reader.readAsArrayBuffer(new Blob()); + }); + const ab = e.target.result; + expect(ab.byteLength).toBe(2); + expect(new TextDecoder().decode(ab)).toBe('42'); + }); });