From f968bdaec35548e901b623add75eb77e3e24edaa Mon Sep 17 00:00:00 2001 From: Durvesh Pilankar Date: Mon, 29 Jun 2026 22:30:40 -0700 Subject: [PATCH] Set FileReader to LOADING state while a read is in progress MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit FileReader's readAs* methods went straight from EMPTY to DONE: they never set readyState to LOADING. As a result readyState was never observably LOADING, and abort() — which only emits events when readyState is neither EMPTY nor DONE — silently did nothing when called during an in-progress read, so no 'abort'/'loadend' events fired. Set the LOADING state when each read starts (via _setReadyState, which also fires 'readystatechange'), matching the FileReader spec and making abort() during a read work as its own code already anticipated. Add tests for the LOADING state and for abort() dispatching abort/loadend during a read. --- .../react-native/Libraries/Blob/FileReader.js | 6 +++++ .../Blob/__tests__/FileReader-test.js | 25 +++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/packages/react-native/Libraries/Blob/FileReader.js b/packages/react-native/Libraries/Blob/FileReader.js index 9cb37e5ca487..3745c00923a8 100644 --- a/packages/react-native/Libraries/Blob/FileReader.js +++ b/packages/react-native/Libraries/Blob/FileReader.js @@ -80,6 +80,8 @@ class FileReader extends EventTarget { ); } + this._setReadyState(LOADING); + NativeFileReaderModule.readAsDataURL(blob.data).then( (text: string) => { if (this._aborted) { @@ -111,6 +113,8 @@ class FileReader extends EventTarget { ); } + this._setReadyState(LOADING); + NativeFileReaderModule.readAsDataURL(blob.data).then( (text: string) => { if (this._aborted) { @@ -138,6 +142,8 @@ class FileReader extends EventTarget { ); } + this._setReadyState(LOADING); + NativeFileReaderModule.readAsText(blob.data, encoding).then( (text: string) => { if (this._aborted) { diff --git a/packages/react-native/Libraries/Blob/__tests__/FileReader-test.js b/packages/react-native/Libraries/Blob/__tests__/FileReader-test.js index 549d027bc3a0..36d55849c487 100644 --- a/packages/react-native/Libraries/Blob/__tests__/FileReader-test.js +++ b/packages/react-native/Libraries/Blob/__tests__/FileReader-test.js @@ -46,6 +46,31 @@ describe('FileReader', function () { expect(e.target?.result).toBe('data:text/plain;base64,NDI='); }); + it('should be in the LOADING state while a read is in progress', () => { + const reader = new FileReader(); + expect(reader.readyState).toBe(FileReader.EMPTY); + reader.readAsText(new Blob()); + // The native read resolves on a later microtask, so the reader should + // report LOADING synchronously after the read starts. + expect(reader.readyState).toBe(FileReader.LOADING); + }); + + it('should dispatch abort and loadend when aborted during a read', () => { + const reader = new FileReader(); + let aborted = false; + let loadended = false; + reader.onabort = () => { + aborted = true; + }; + reader.onloadend = () => { + loadended = true; + }; + reader.readAsText(new Blob()); + reader.abort(); + expect(aborted).toBe(true); + expect(loadended).toBe(true); + }); + it('should read blob as ArrayBuffer', async () => { const e = await new Promise((resolve, reject) => { const reader = new FileReader();