3636import org .htmlunit .javascript .configuration .JsxSetter ;
3737import org .htmlunit .javascript .host .event .Event ;
3838import org .htmlunit .javascript .host .event .EventTarget ;
39+ import org .htmlunit .javascript .host .event .ProgressEvent ;
3940import org .htmlunit .protocol .data .DataURLConnection ;
4041import org .htmlunit .util .MimeType ;
4142import org .htmlunit .util .StringUtils ;
@@ -103,21 +104,29 @@ public Object getResult() {
103104 public void readAsDataURL (final Object object ) throws IOException {
104105 readyState_ = LOADING ;
105106
107+ if (!(object instanceof Blob blob )) {
108+ throw JavaScriptEngine .typeError (
109+ "FileReader.readAsDataURL: Argument 1 does not implement interface Blob." );
110+ }
111+
106112 result_ = DataURLConnection .DATA_PREFIX ;
107113
108- final byte [] bytes = ((Blob ) object ).getBytes ();
114+ final byte [] bytes = blob .getBytes ();
115+ fireEvent (new ProgressEvent (this , Event .TYPE_LOAD_START , true , 0 , bytes .length ));
116+ fireEvent (new ProgressEvent (this , Event .TYPE_PROGRESS , true , bytes .length , bytes .length ));
117+
109118 final String value = new String (Base64 .getEncoder ().encode (bytes ), StandardCharsets .US_ASCII );
110119
111- String contentType = (( Blob ) object ) .getType ();
120+ String contentType = blob .getType ();
112121 if (StringUtils .isEmptyOrNull (contentType )) {
113122 contentType = MimeType .APPLICATION_OCTET_STREAM ;
114123 }
115124
116125 result_ += contentType + ";base64," + value ;
117126 readyState_ = DONE ;
118127
119- final Event event = new Event (this , Event .TYPE_LOAD );
120- fireEvent (event );
128+ fireEvent ( new ProgressEvent (this , Event .TYPE_LOAD , true , bytes . length , bytes . length ) );
129+ fireEvent (new ProgressEvent ( this , Event . TYPE_LOAD_END , true , bytes . length , bytes . length ) );
121130 }
122131
123132 /**
@@ -128,21 +137,25 @@ public void readAsDataURL(final Object object) throws IOException {
128137 public void readAsArrayBuffer (final Object object ) {
129138 readyState_ = LOADING ;
130139
131- if (object instanceof Blob blob ) {
132- final byte [] bytes = blob .getBytes ();
140+ if (!(object instanceof Blob blob )) {
141+ throw JavaScriptEngine .typeError (
142+ "FileReader.readAsArrayBuffer: Argument 1 does not implement interface Blob." );
143+ }
133144
134- final NativeArrayBuffer buffer = new NativeArrayBuffer (bytes .length );
135- System .arraycopy (bytes , 0 , buffer .getBuffer (), 0 , bytes .length );
136- buffer .setParentScope (getParentScope ());
137- buffer .setPrototype (ScriptableObject .getClassPrototype (getWindow (), buffer .getClassName ()));
145+ final byte [] bytes = blob .getBytes ();
146+ fireEvent (new ProgressEvent (this , Event .TYPE_LOAD_START , true , 0 , bytes .length ));
147+ fireEvent (new ProgressEvent (this , Event .TYPE_PROGRESS , true , bytes .length , bytes .length ));
138148
139- result_ = buffer ;
140- }
149+ final NativeArrayBuffer buffer = new NativeArrayBuffer (bytes .length );
150+ System .arraycopy (bytes , 0 , buffer .getBuffer (), 0 , bytes .length );
151+ buffer .setParentScope (getParentScope ());
152+ buffer .setPrototype (ScriptableObject .getClassPrototype (getWindow (), buffer .getClassName ()));
141153
154+ result_ = buffer ;
142155 readyState_ = DONE ;
143156
144- final Event event = new Event (this , Event .TYPE_LOAD );
145- fireEvent (event );
157+ fireEvent ( new ProgressEvent (this , Event .TYPE_LOAD , true , bytes . length , bytes . length ) );
158+ fireEvent (new ProgressEvent ( this , Event . TYPE_LOAD_END , true , bytes . length , bytes . length ) );
146159 }
147160
148161 /**
@@ -157,6 +170,11 @@ public void readAsArrayBuffer(final Object object) {
157170 public void readAsText (final Object object , final Object encoding ) {
158171 readyState_ = LOADING ;
159172
173+ if (!(object instanceof Blob blob )) {
174+ throw JavaScriptEngine .typeError (
175+ "FileReader.readAsText: Argument 1 does not implement interface Blob." );
176+ }
177+
160178 Charset charset = StandardCharsets .UTF_8 ;
161179 if (encoding != null && !JavaScriptEngine .isUndefined (encoding )) {
162180 final String encAsString = JavaScriptEngine .toString (encoding );
@@ -173,14 +191,51 @@ public void readAsText(final Object object, final Object encoding) {
173191 }
174192 }
175193
176- if ( object instanceof Blob blob ) {
177- result_ = new String ( blob . getBytes (), charset );
178- }
194+ final byte [] bytes = blob . getBytes ();
195+ fireEvent ( new ProgressEvent ( this , Event . TYPE_LOAD_START , true , 0 , bytes . length ) );
196+ fireEvent ( new ProgressEvent ( this , Event . TYPE_PROGRESS , true , bytes . length , bytes . length ));
179197
198+ result_ = new String (bytes , charset );
180199 readyState_ = DONE ;
181200
182- final Event event = new Event (this , Event .TYPE_LOAD );
183- fireEvent (event );
201+ fireEvent (new ProgressEvent (this , Event .TYPE_LOAD , true , bytes .length , bytes .length ));
202+ fireEvent (new ProgressEvent (this , Event .TYPE_LOAD_END , true , bytes .length , bytes .length ));
203+ }
204+
205+ /**
206+ * Returns the {@code onloadstart} event handler for this {@link FileReader}.
207+ * @return the {@code onloadstart} event handler for this {@link FileReader}
208+ */
209+ @ JsxGetter
210+ public Function getOnloadstart () {
211+ return getEventHandler (Event .TYPE_LOAD_START );
212+ }
213+
214+ /**
215+ * Sets the {@code onloadstart} event handler for this {@link FileReader}.
216+ * @param onloadstart the {@code onloadstart} event handler for this {@link FileReader}
217+ */
218+ @ JsxSetter
219+ public void setOnloadstart (final Object onloadstart ) {
220+ setEventHandler (Event .TYPE_LOAD_START , onloadstart );
221+ }
222+
223+ /**
224+ * Returns the {@code onprogress} event handler for this {@link FileReader}.
225+ * @return the {@code onprogress} event handler for this {@link FileReader}
226+ */
227+ @ JsxGetter
228+ public Function getOnprogress () {
229+ return getEventHandler (Event .TYPE_PROGRESS );
230+ }
231+
232+ /**
233+ * Sets the {@code onprogress} event handler for this {@link FileReader}.
234+ * @param onprogress the {@code onprogress} event handler for this {@link FileReader}
235+ */
236+ @ JsxSetter
237+ public void setOnprogress (final Object onprogress ) {
238+ setEventHandler (Event .TYPE_PROGRESS , onprogress );
184239 }
185240
186241 /**
@@ -201,6 +256,24 @@ public void setOnload(final Object onload) {
201256 setEventHandler (Event .TYPE_LOAD , onload );
202257 }
203258
259+ /**
260+ * Returns the {@code onloadend} event handler for this {@link FileReader}.
261+ * @return the {@code onloadend} event handler for this {@link FileReader}
262+ */
263+ @ JsxGetter
264+ public Function getOnloadend () {
265+ return getEventHandler (Event .TYPE_LOAD_END );
266+ }
267+
268+ /**
269+ * Sets the {@code onloadend} event handler for this {@link FileReader}.
270+ * @param onloadend the {@code onloadend} event handler for this {@link FileReader}
271+ */
272+ @ JsxSetter
273+ public void setOnloadend (final Object onloadend ) {
274+ setEventHandler (Event .TYPE_LOAD_END , onloadend );
275+ }
276+
204277 /**
205278 * Returns the {@code onerror} event handler for this {@link FileReader}.
206279 * @return the {@code onerror} event handler for this {@link FileReader}
0 commit comments