Skip to content

Commit f968bda

Browse files
committed
Set FileReader to LOADING state while a read is in progress
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.
1 parent b364490 commit f968bda

2 files changed

Lines changed: 31 additions & 0 deletions

File tree

packages/react-native/Libraries/Blob/FileReader.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class FileReader extends EventTarget {
8080
);
8181
}
8282

83+
this._setReadyState(LOADING);
84+
8385
NativeFileReaderModule.readAsDataURL(blob.data).then(
8486
(text: string) => {
8587
if (this._aborted) {
@@ -111,6 +113,8 @@ class FileReader extends EventTarget {
111113
);
112114
}
113115

116+
this._setReadyState(LOADING);
117+
114118
NativeFileReaderModule.readAsDataURL(blob.data).then(
115119
(text: string) => {
116120
if (this._aborted) {
@@ -138,6 +142,8 @@ class FileReader extends EventTarget {
138142
);
139143
}
140144

145+
this._setReadyState(LOADING);
146+
141147
NativeFileReaderModule.readAsText(blob.data, encoding).then(
142148
(text: string) => {
143149
if (this._aborted) {

packages/react-native/Libraries/Blob/__tests__/FileReader-test.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,31 @@ describe('FileReader', function () {
4646
expect(e.target?.result).toBe('data:text/plain;base64,NDI=');
4747
});
4848

49+
it('should be in the LOADING state while a read is in progress', () => {
50+
const reader = new FileReader();
51+
expect(reader.readyState).toBe(FileReader.EMPTY);
52+
reader.readAsText(new Blob());
53+
// The native read resolves on a later microtask, so the reader should
54+
// report LOADING synchronously after the read starts.
55+
expect(reader.readyState).toBe(FileReader.LOADING);
56+
});
57+
58+
it('should dispatch abort and loadend when aborted during a read', () => {
59+
const reader = new FileReader();
60+
let aborted = false;
61+
let loadended = false;
62+
reader.onabort = () => {
63+
aborted = true;
64+
};
65+
reader.onloadend = () => {
66+
loadended = true;
67+
};
68+
reader.readAsText(new Blob());
69+
reader.abort();
70+
expect(aborted).toBe(true);
71+
expect(loadended).toBe(true);
72+
});
73+
4974
it('should read blob as ArrayBuffer', async () => {
5075
const e = await new Promise<Event>((resolve, reject) => {
5176
const reader = new FileReader();

0 commit comments

Comments
 (0)