Skip to content

Commit d33ff53

Browse files
rubennortefacebook-github-bot
authored andcommitted
Ship refactor of XHR, FileReader and WebSocket to use the built-in EventTarget implementation (#50485)
Summary: Pull Request resolved: #50485 Changelog: [internal] This cleans up the experiment to test the new implementations of `XMLHttpRequest`, `FileReader` and `WebSocket` using the built-in `EventTarget` definition. This effectively replaces the legacy implementations with the ones using the built-in `EventTarget` class in stable. Reviewed By: yungsters Differential Revision: D68625225 fbshipit-source-id: 7ccefe5d8612baca283146cdbca7f7f1d51b4ffa
1 parent cbf1169 commit d33ff53

File tree

13 files changed

+1583
-3060
lines changed

13 files changed

+1583
-3060
lines changed

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

Lines changed: 219 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,224 @@
88
* @format
99
*/
1010

11-
import typeof FileReader from './FileReader_old';
11+
import type {EventCallback} from '../../src/private/webapis/dom/events/EventTarget';
12+
import type Blob from './Blob';
1213

13-
// Use a global instead of a flag from ReactNativeFeatureFlags because this will
14-
// be read before apps have a chance to set overrides.
15-
const useBuiltInEventTarget = global.RN$useBuiltInEventTarget?.();
14+
import Event from '../../src/private/webapis/dom/events/Event';
15+
import {
16+
getEventHandlerAttribute,
17+
setEventHandlerAttribute,
18+
} from '../../src/private/webapis/dom/events/EventHandlerAttributes';
19+
import EventTarget from '../../src/private/webapis/dom/events/EventTarget';
20+
import NativeFileReaderModule from './NativeFileReaderModule';
21+
import {toByteArray} from 'base64-js';
1622

17-
export default (useBuiltInEventTarget
18-
? // $FlowExpectedError[incompatible-cast]
19-
require('./FileReader_new').default
20-
: require('./FileReader_old').default) as FileReader;
23+
type ReadyState =
24+
| 0 // EMPTY
25+
| 1 // LOADING
26+
| 2; // DONE
27+
28+
type ReaderResult = string | ArrayBuffer;
29+
30+
const EMPTY = 0;
31+
const LOADING = 1;
32+
const DONE = 2;
33+
34+
class FileReader extends EventTarget {
35+
static EMPTY: number = EMPTY;
36+
static LOADING: number = LOADING;
37+
static DONE: number = DONE;
38+
39+
EMPTY: number = EMPTY;
40+
LOADING: number = LOADING;
41+
DONE: number = DONE;
42+
43+
_readyState: ReadyState;
44+
_error: ?Error;
45+
_result: ?ReaderResult;
46+
_aborted: boolean = false;
47+
48+
constructor() {
49+
super();
50+
this._reset();
51+
}
52+
53+
_reset(): void {
54+
this._readyState = EMPTY;
55+
this._error = null;
56+
this._result = null;
57+
}
58+
59+
_setReadyState(newState: ReadyState) {
60+
this._readyState = newState;
61+
this.dispatchEvent(new Event('readystatechange'));
62+
if (newState === DONE) {
63+
if (this._aborted) {
64+
this.dispatchEvent(new Event('abort'));
65+
} else if (this._error) {
66+
this.dispatchEvent(new Event('error'));
67+
} else {
68+
this.dispatchEvent(new Event('load'));
69+
}
70+
this.dispatchEvent(new Event('loadend'));
71+
}
72+
}
73+
74+
readAsArrayBuffer(blob: ?Blob): void {
75+
this._aborted = false;
76+
77+
if (blob == null) {
78+
throw new TypeError(
79+
"Failed to execute 'readAsArrayBuffer' on 'FileReader': parameter 1 is not of type 'Blob'",
80+
);
81+
}
82+
83+
NativeFileReaderModule.readAsDataURL(blob.data).then(
84+
(text: string) => {
85+
if (this._aborted) {
86+
return;
87+
}
88+
89+
const base64 = text.split(',')[1];
90+
const typedArray = toByteArray(base64);
91+
92+
this._result = typedArray.buffer;
93+
this._setReadyState(DONE);
94+
},
95+
error => {
96+
if (this._aborted) {
97+
return;
98+
}
99+
this._error = error;
100+
this._setReadyState(DONE);
101+
},
102+
);
103+
}
104+
105+
readAsDataURL(blob: ?Blob): void {
106+
this._aborted = false;
107+
108+
if (blob == null) {
109+
throw new TypeError(
110+
"Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'",
111+
);
112+
}
113+
114+
NativeFileReaderModule.readAsDataURL(blob.data).then(
115+
(text: string) => {
116+
if (this._aborted) {
117+
return;
118+
}
119+
this._result = text;
120+
this._setReadyState(DONE);
121+
},
122+
error => {
123+
if (this._aborted) {
124+
return;
125+
}
126+
this._error = error;
127+
this._setReadyState(DONE);
128+
},
129+
);
130+
}
131+
132+
readAsText(blob: ?Blob, encoding: string = 'UTF-8'): void {
133+
this._aborted = false;
134+
135+
if (blob == null) {
136+
throw new TypeError(
137+
"Failed to execute 'readAsText' on 'FileReader': parameter 1 is not of type 'Blob'",
138+
);
139+
}
140+
141+
NativeFileReaderModule.readAsText(blob.data, encoding).then(
142+
(text: string) => {
143+
if (this._aborted) {
144+
return;
145+
}
146+
this._result = text;
147+
this._setReadyState(DONE);
148+
},
149+
error => {
150+
if (this._aborted) {
151+
return;
152+
}
153+
this._error = error;
154+
this._setReadyState(DONE);
155+
},
156+
);
157+
}
158+
159+
abort() {
160+
this._aborted = true;
161+
// only call onreadystatechange if there is something to abort, as per spec
162+
if (this._readyState !== EMPTY && this._readyState !== DONE) {
163+
this._reset();
164+
this._setReadyState(DONE);
165+
}
166+
// Reset again after, in case modified in handler
167+
this._reset();
168+
}
169+
170+
get readyState(): ReadyState {
171+
return this._readyState;
172+
}
173+
174+
get error(): ?Error {
175+
return this._error;
176+
}
177+
178+
get result(): ?ReaderResult {
179+
return this._result;
180+
}
181+
182+
get onabort(): EventCallback | null {
183+
return getEventHandlerAttribute(this, 'abort');
184+
}
185+
186+
set onabort(listener: ?EventCallback) {
187+
setEventHandlerAttribute(this, 'abort', listener);
188+
}
189+
190+
get onerror(): EventCallback | null {
191+
return getEventHandlerAttribute(this, 'error');
192+
}
193+
194+
set onerror(listener: ?EventCallback) {
195+
setEventHandlerAttribute(this, 'error', listener);
196+
}
197+
198+
get onload(): EventCallback | null {
199+
return getEventHandlerAttribute(this, 'load');
200+
}
201+
202+
set onload(listener: ?EventCallback) {
203+
setEventHandlerAttribute(this, 'load', listener);
204+
}
205+
206+
get onloadstart(): EventCallback | null {
207+
return getEventHandlerAttribute(this, 'loadstart');
208+
}
209+
210+
set onloadstart(listener: ?EventCallback) {
211+
setEventHandlerAttribute(this, 'loadstart', listener);
212+
}
213+
214+
get onloadend(): EventCallback | null {
215+
return getEventHandlerAttribute(this, 'loadend');
216+
}
217+
218+
set onloadend(listener: ?EventCallback) {
219+
setEventHandlerAttribute(this, 'loadend', listener);
220+
}
221+
222+
get onprogress(): EventCallback | null {
223+
return getEventHandlerAttribute(this, 'progress');
224+
}
225+
226+
set onprogress(listener: ?EventCallback) {
227+
setEventHandlerAttribute(this, 'progress', listener);
228+
}
229+
}
230+
231+
export default FileReader;

0 commit comments

Comments
 (0)