mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
feat(web): FileReader API (#6673)
This commit is contained in:
parent
d7077b9073
commit
eed77aa020
8 changed files with 564 additions and 0 deletions
|
@ -165,6 +165,7 @@ fn get_js_files_for_rt() -> Vec<String> {
|
|||
"rt/20_headers.js",
|
||||
"rt/20_streams_queuing_strategy.js",
|
||||
"rt/21_dom_file.js",
|
||||
"rt/21_filereader.js",
|
||||
"rt/22_form_data.js",
|
||||
"rt/23_multipart.js",
|
||||
"rt/24_body.js",
|
||||
|
|
53
cli/dts/lib.deno.shared_globals.d.ts
vendored
53
cli/dts/lib.deno.shared_globals.d.ts
vendored
|
@ -569,6 +569,48 @@ declare const File: {
|
|||
new (fileBits: BlobPart[], fileName: string, options?: FilePropertyBag): File;
|
||||
};
|
||||
|
||||
interface FileReaderEventMap {
|
||||
"abort": ProgressEvent<FileReader>;
|
||||
"error": ProgressEvent<FileReader>;
|
||||
"load": ProgressEvent<FileReader>;
|
||||
"loadend": ProgressEvent<FileReader>;
|
||||
"loadstart": ProgressEvent<FileReader>;
|
||||
"progress": ProgressEvent<FileReader>;
|
||||
}
|
||||
|
||||
/** Lets web applications asynchronously read the contents of files (or raw data buffers) stored on the user's computer, using File or Blob objects to specify the file or data to read. */
|
||||
interface FileReader extends EventTarget {
|
||||
readonly error: DOMException | null;
|
||||
onabort: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
onerror: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
onload: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
onloadend: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
onloadstart: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
onprogress: ((this: FileReader, ev: ProgressEvent<FileReader>) => any) | null;
|
||||
readonly readyState: number;
|
||||
readonly result: string | ArrayBuffer | null;
|
||||
abort(): void;
|
||||
readAsArrayBuffer(blob: Blob): void;
|
||||
readAsBinaryString(blob: Blob): void;
|
||||
readAsDataURL(blob: Blob): void;
|
||||
readAsText(blob: Blob, encoding?: string): void;
|
||||
readonly DONE: number;
|
||||
readonly EMPTY: number;
|
||||
readonly LOADING: number;
|
||||
addEventListener<K extends keyof FileReaderEventMap>(type: K, listener: (this: FileReader, ev: FileReaderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
|
||||
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
|
||||
removeEventListener<K extends keyof FileReaderEventMap>(type: K, listener: (this: FileReader, ev: FileReaderEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
|
||||
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
|
||||
}
|
||||
|
||||
declare var FileReader: {
|
||||
prototype: FileReader;
|
||||
new(): FileReader;
|
||||
readonly DONE: number;
|
||||
readonly EMPTY: number;
|
||||
readonly LOADING: number;
|
||||
};
|
||||
|
||||
declare const isConsoleInstance: unique symbol;
|
||||
|
||||
declare class Console {
|
||||
|
@ -1234,6 +1276,12 @@ interface PostMessageOptions {
|
|||
transfer?: any[];
|
||||
}
|
||||
|
||||
interface ProgressEventInit extends EventInit {
|
||||
lengthComputable?: boolean;
|
||||
loaded?: number;
|
||||
total?: number;
|
||||
}
|
||||
|
||||
declare class Worker extends EventTarget {
|
||||
onerror?: (e: ErrorEvent) => void;
|
||||
onmessage?: (e: MessageEvent) => void;
|
||||
|
@ -1409,6 +1457,11 @@ interface ProgressEvent<T extends EventTarget = EventTarget> extends Event {
|
|||
readonly total: number;
|
||||
}
|
||||
|
||||
declare var ProgressEvent: {
|
||||
prototype: ProgressEvent;
|
||||
new(type:string, eventInitDict?: ProgressEventInit): ProgressEvent;
|
||||
};
|
||||
|
||||
interface CustomEventInit<T = any> extends EventInit {
|
||||
detail?: T;
|
||||
}
|
||||
|
|
264
cli/rt/21_filereader.js
Normal file
264
cli/rt/21_filereader.js
Normal file
|
@ -0,0 +1,264 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
((window) => {
|
||||
const base64 = window.__bootstrap.base64;
|
||||
const setTimeout = window.__bootstrap.timers.setTimeout;
|
||||
|
||||
// ProgressEvent could also be used in other DOM progress event emits.
|
||||
// Current use is for FileReader.
|
||||
class ProgressEvent extends Event {
|
||||
constructor(type, eventInitDict = {}) {
|
||||
super(type, eventInitDict);
|
||||
|
||||
this.lengthComputable = eventInitDict?.lengthComputable ?? false;
|
||||
this.loaded = eventInitDict?.loaded ?? 0;
|
||||
this.total = eventInitDict?.total ?? 0;
|
||||
}
|
||||
}
|
||||
window.__bootstrap.progressEvent = {
|
||||
ProgressEvent,
|
||||
};
|
||||
|
||||
async function readOperation(fr, blob, readtype) {
|
||||
// Implementation from https://w3c.github.io/FileAPI/ notes
|
||||
// And body of deno blob.ts readBytes
|
||||
|
||||
fr.aborting = false;
|
||||
|
||||
// 1. If fr’s state is "loading", throw an InvalidStateError DOMException.
|
||||
if (fr.readyState === FileReader.LOADING) {
|
||||
throw new DOMException(
|
||||
"Invalid FileReader state.",
|
||||
"InvalidStateError",
|
||||
);
|
||||
}
|
||||
// 2. Set fr’s state to "loading".
|
||||
fr.readyState = FileReader.LOADING;
|
||||
// 3. Set fr’s result to null.
|
||||
fr.result = null;
|
||||
// 4. Set fr’s error to null.
|
||||
fr.error = null;
|
||||
|
||||
// 5. Let stream be the result of calling get stream on blob.
|
||||
const stream /*: ReadableStream<ArrayBufferView>*/ = blob.stream();
|
||||
|
||||
// 6. Let reader be the result of getting a reader from stream.
|
||||
const reader = stream.getReader();
|
||||
|
||||
// 7. Let bytes be an empty byte sequence.
|
||||
//let bytes = new Uint8Array();
|
||||
const chunks /*: Uint8Array[]*/ = [];
|
||||
|
||||
// 8. Let chunkPromise be the result of reading a chunk from stream with reader.
|
||||
let chunkPromise = reader.read();
|
||||
|
||||
// 9. Let isFirstChunk be true.
|
||||
let isFirstChunk = true;
|
||||
|
||||
// 10 in parallel while true
|
||||
while (!fr.aborting) {
|
||||
// 1. Wait for chunkPromise to be fulfilled or rejected.
|
||||
try {
|
||||
const chunk = await chunkPromise;
|
||||
|
||||
// 2. If chunkPromise is fulfilled, and isFirstChunk is true, queue a task to fire a progress event called loadstart at fr.
|
||||
if (isFirstChunk) {
|
||||
setTimeout(() => {
|
||||
// fire a progress event for loadstart
|
||||
const ev = new ProgressEvent("loadstart", {});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onloadstart !== null) {
|
||||
fr.onloadstart(ev);
|
||||
}
|
||||
}, 0);
|
||||
}
|
||||
// 3. Set isFirstChunk to false.
|
||||
isFirstChunk = false;
|
||||
|
||||
// 4. If chunkPromise is fulfilled with an object whose done property is false
|
||||
// and whose value property is a Uint8Array object, run these steps:
|
||||
if (!chunk.done && chunk.value instanceof Uint8Array) {
|
||||
chunks.push(chunk.value);
|
||||
|
||||
// TODO: (only) If roughly 50ms have passed since last progress
|
||||
{
|
||||
const size = chunks.reduce((p, i) => p + i.byteLength, 0);
|
||||
const ev = new ProgressEvent("progress", {
|
||||
loaded: size,
|
||||
});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onprogress !== null) {
|
||||
fr.onprogress(ev);
|
||||
}
|
||||
}
|
||||
|
||||
chunkPromise = reader.read();
|
||||
} // 5 Otherwise, if chunkPromise is fulfilled with an object whose done property is true, queue a task to run the following steps and abort this algorithm:
|
||||
else if (chunk.done === true) {
|
||||
setTimeout(() => {
|
||||
if (fr.aborting) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 1. Set fr’s state to "done".
|
||||
fr.readyState = FileReader.DONE;
|
||||
// 2. Let result be the result of package data given bytes, type, blob’s type, and encodingName.
|
||||
const size = chunks.reduce((p, i) => p + i.byteLength, 0);
|
||||
const bytes = new Uint8Array(size);
|
||||
let offs = 0;
|
||||
for (const chunk of chunks) {
|
||||
bytes.set(chunk, offs);
|
||||
offs += chunk.byteLength;
|
||||
}
|
||||
switch (readtype.kind) {
|
||||
case "ArrayBuffer": {
|
||||
fr.result = bytes.buffer;
|
||||
break;
|
||||
}
|
||||
case "Text": {
|
||||
const decoder = new TextDecoder(readtype.encoding);
|
||||
fr.result = decoder.decode(bytes.buffer);
|
||||
break;
|
||||
}
|
||||
case "DataUrl": {
|
||||
fr.result = "data:application/octet-stream;base64," +
|
||||
base64.fromByteArray(bytes);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 4.2 Fire a progress event called load at the fr.
|
||||
{
|
||||
const ev = new ProgressEvent("load", {
|
||||
lengthComputable: true,
|
||||
loaded: size,
|
||||
total: size,
|
||||
});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onload !== null) {
|
||||
fr.onload(ev);
|
||||
}
|
||||
}
|
||||
|
||||
// 5. If fr’s state is not "loading", fire a progress event called loadend at the fr.
|
||||
//Note: Event handler for the load or error events could have started another load, if that happens the loadend event for this load is not fired.
|
||||
if (fr.readyState !== FileReader.LOADING) {
|
||||
const ev = new ProgressEvent("loadend", {
|
||||
lengthComputable: true,
|
||||
loaded: size,
|
||||
total: size,
|
||||
});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onloadend !== null) {
|
||||
fr.onloadend(ev);
|
||||
}
|
||||
}
|
||||
}, 0);
|
||||
|
||||
break;
|
||||
}
|
||||
} catch (err) {
|
||||
if (fr.aborting) {
|
||||
break;
|
||||
}
|
||||
|
||||
// chunkPromise rejected
|
||||
fr.readyState = FileReader.DONE;
|
||||
fr.error = err;
|
||||
|
||||
{
|
||||
const ev = new ProgressEvent("error", {});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onerror !== null) {
|
||||
fr.onerror(ev);
|
||||
}
|
||||
}
|
||||
|
||||
//If fr’s state is not "loading", fire a progress event called loadend at fr.
|
||||
//Note: Event handler for the error event could have started another load, if that happens the loadend event for this load is not fired.
|
||||
if (fr.readyState !== FileReader.LOADING) {
|
||||
const ev = new ProgressEvent("loadend", {});
|
||||
fr.dispatchEvent(ev);
|
||||
if (fr.onloadend !== null) {
|
||||
fr.onloadend(ev);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class FileReader extends EventTarget {
|
||||
error = null;
|
||||
onabort = null;
|
||||
onerror = null;
|
||||
onload = null;
|
||||
onloadend = null;
|
||||
onloadstart = null;
|
||||
onprogress = null;
|
||||
|
||||
readyState = FileReader.EMPTY;
|
||||
result = null;
|
||||
aborting = false;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
abort() {
|
||||
// If context object's state is "empty" or if context object's state is "done" set context object's result to null and terminate this algorithm.
|
||||
if (
|
||||
this.readyState === FileReader.EMPTY ||
|
||||
this.readyState === FileReader.DONE
|
||||
) {
|
||||
this.result = null;
|
||||
return;
|
||||
}
|
||||
// If context object's state is "loading" set context object's state to "done" and set context object's result to null.
|
||||
if (this.readyState === FileReader.LOADING) {
|
||||
this.readyState = FileReader.DONE;
|
||||
this.result = null;
|
||||
}
|
||||
// If there are any tasks from the context object on the file reading task source in an affiliated task queue, then remove those tasks from that task queue.
|
||||
// Terminate the algorithm for the read method being processed.
|
||||
this.aborting = true;
|
||||
|
||||
// Fire a progress event called abort at the context object.
|
||||
const ev = new ProgressEvent("abort", {});
|
||||
this.dispatchEvent(ev);
|
||||
if (this.onabort !== null) {
|
||||
this.onabort(ev);
|
||||
}
|
||||
|
||||
// If context object's state is not "loading", fire a progress event called loadend at the context object.
|
||||
if (this.readyState !== FileReader.LOADING) {
|
||||
const ev = new ProgressEvent("loadend", {});
|
||||
this.dispatchEvent(ev);
|
||||
if (this.onloadend !== null) {
|
||||
this.onloadend(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
readAsArrayBuffer(blob) {
|
||||
readOperation(this, blob, { kind: "ArrayBuffer" });
|
||||
}
|
||||
readAsBinaryString(blob) {
|
||||
// alias for readAsArrayBuffer
|
||||
readOperation(this, blob, { kind: "ArrayBuffer" });
|
||||
}
|
||||
readAsDataURL(blob) {
|
||||
readOperation(this, blob, { kind: "DataUrl" });
|
||||
}
|
||||
readAsText(blob, encoding) {
|
||||
readOperation(this, blob, { kind: "Text", encoding });
|
||||
}
|
||||
}
|
||||
|
||||
FileReader.EMPTY = 0;
|
||||
FileReader.LOADING = 1;
|
||||
FileReader.DONE = 2;
|
||||
|
||||
window.__bootstrap.fileReader = {
|
||||
FileReader,
|
||||
};
|
||||
})(this);
|
|
@ -29,6 +29,8 @@ delete Object.prototype.__proto__;
|
|||
const streams = window.__bootstrap.streams;
|
||||
const blob = window.__bootstrap.blob;
|
||||
const domFile = window.__bootstrap.domFile;
|
||||
const progressEvent = window.__bootstrap.progressEvent;
|
||||
const fileReader = window.__bootstrap.fileReader;
|
||||
const formData = window.__bootstrap.formData;
|
||||
const request = window.__bootstrap.request;
|
||||
const fetch = window.__bootstrap.fetch;
|
||||
|
@ -226,6 +228,7 @@ delete Object.prototype.__proto__;
|
|||
),
|
||||
crypto: util.readOnly(crypto),
|
||||
File: util.nonEnumerable(domFile.DomFile),
|
||||
FileReader: util.nonEnumerable(fileReader.FileReader),
|
||||
CustomEvent: util.nonEnumerable(CustomEvent),
|
||||
DOMException: util.nonEnumerable(DOMException),
|
||||
ErrorEvent: util.nonEnumerable(ErrorEvent),
|
||||
|
@ -241,6 +244,7 @@ delete Object.prototype.__proto__;
|
|||
PerformanceEntry: util.nonEnumerable(performance.PerformanceEntry),
|
||||
PerformanceMark: util.nonEnumerable(performance.PerformanceMark),
|
||||
PerformanceMeasure: util.nonEnumerable(performance.PerformanceMeasure),
|
||||
ProgressEvent: util.nonEnumerable(progressEvent.ProgressEvent),
|
||||
TextDecoder: util.nonEnumerable(TextDecoder),
|
||||
TextEncoder: util.nonEnumerable(TextEncoder),
|
||||
TransformStream: util.nonEnumerable(streams.TransformStream),
|
||||
|
|
220
cli/tests/unit/filereader_test.ts
Normal file
220
cli/tests/unit/filereader_test.ts
Normal file
|
@ -0,0 +1,220 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { unitTest, assertEquals } from "./test_util.ts";
|
||||
|
||||
unitTest(function fileReaderConstruct(): void {
|
||||
const fr = new FileReader();
|
||||
assertEquals(fr.readyState, FileReader.EMPTY);
|
||||
|
||||
assertEquals(FileReader.EMPTY, 0);
|
||||
assertEquals(FileReader.LOADING, 1);
|
||||
assertEquals(FileReader.DONE, 2);
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlob(): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["Hello World"]);
|
||||
|
||||
assertEquals(fr.readyState, FileReader.EMPTY);
|
||||
|
||||
const hasOnEvents = {
|
||||
load: false,
|
||||
loadend: false,
|
||||
loadstart: false,
|
||||
progress: 0,
|
||||
};
|
||||
const hasDispatchedEvents = {
|
||||
load: false,
|
||||
loadend: false,
|
||||
loadstart: false,
|
||||
progress: 0,
|
||||
};
|
||||
let result: string | null = null;
|
||||
|
||||
fr.addEventListener("load", () => {
|
||||
hasDispatchedEvents.load = true;
|
||||
});
|
||||
fr.addEventListener("loadend", () => {
|
||||
hasDispatchedEvents.loadend = true;
|
||||
});
|
||||
fr.addEventListener("loadstart", () => {
|
||||
hasDispatchedEvents.loadstart = true;
|
||||
});
|
||||
fr.addEventListener("progress", () => {
|
||||
hasDispatchedEvents.progress += 1;
|
||||
});
|
||||
|
||||
fr.onloadstart = (): void => {
|
||||
hasOnEvents.loadstart = true;
|
||||
};
|
||||
fr.onprogress = (): void => {
|
||||
assertEquals(fr.readyState, FileReader.LOADING);
|
||||
|
||||
hasOnEvents.progress += 1;
|
||||
};
|
||||
fr.onload = (): void => {
|
||||
hasOnEvents.load = true;
|
||||
};
|
||||
fr.onloadend = (ev): void => {
|
||||
hasOnEvents.loadend = true;
|
||||
result = fr.result as string;
|
||||
|
||||
assertEquals(hasOnEvents.loadstart, true);
|
||||
assertEquals(hasDispatchedEvents.loadstart, true);
|
||||
assertEquals(hasOnEvents.load, true);
|
||||
assertEquals(hasDispatchedEvents.load, true);
|
||||
assertEquals(hasOnEvents.loadend, true);
|
||||
assertEquals(hasDispatchedEvents.loadend, true);
|
||||
|
||||
assertEquals(fr.readyState, FileReader.DONE);
|
||||
|
||||
assertEquals(result, "Hello World");
|
||||
assertEquals(ev.lengthComputable, true);
|
||||
resolve();
|
||||
};
|
||||
|
||||
fr.readAsText(b1);
|
||||
});
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlobDouble(): Promise<void> {
|
||||
// impl note from https://w3c.github.io/FileAPI/
|
||||
// Event handler for the load or error events could have started another load,
|
||||
// if that happens the loadend event for the first load is not fired
|
||||
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["First load"]);
|
||||
const b2 = new Blob(["Second load"]);
|
||||
|
||||
await new Promise<void>((resolve) => {
|
||||
let result: string | null = null;
|
||||
|
||||
fr.onload = (): void => {
|
||||
result = fr.result as string;
|
||||
assertEquals(result === "First load" || result === "Second load", true);
|
||||
|
||||
if (result === "First load") {
|
||||
fr.readAsText(b2);
|
||||
}
|
||||
};
|
||||
fr.onloadend = (): void => {
|
||||
assertEquals(result, "Second load");
|
||||
|
||||
resolve();
|
||||
};
|
||||
|
||||
fr.readAsText(b1);
|
||||
});
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlobArrayBuffer(): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["Hello World"]);
|
||||
let result: ArrayBuffer | null = null;
|
||||
|
||||
fr.onloadend = (ev): void => {
|
||||
assertEquals(fr.result instanceof ArrayBuffer, true);
|
||||
result = fr.result as ArrayBuffer;
|
||||
|
||||
const decoder = new TextDecoder();
|
||||
const text = decoder.decode(result);
|
||||
|
||||
assertEquals(text, "Hello World");
|
||||
assertEquals(ev.lengthComputable, true);
|
||||
resolve();
|
||||
};
|
||||
|
||||
fr.readAsArrayBuffer(b1);
|
||||
});
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlobDataUrl(): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["Hello World"]);
|
||||
let result: string | null = null;
|
||||
|
||||
fr.onloadend = (ev): void => {
|
||||
result = fr.result as string;
|
||||
assertEquals(
|
||||
result,
|
||||
"data:application/octet-stream;base64,SGVsbG8gV29ybGQ=",
|
||||
);
|
||||
assertEquals(ev.lengthComputable, true);
|
||||
resolve();
|
||||
};
|
||||
|
||||
fr.readAsDataURL(b1);
|
||||
});
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlobAbort(): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["Hello World"]);
|
||||
|
||||
const hasOnEvents = {
|
||||
load: false,
|
||||
loadend: false,
|
||||
abort: false,
|
||||
};
|
||||
|
||||
fr.onload = (): void => {
|
||||
hasOnEvents.load = true;
|
||||
};
|
||||
fr.onloadend = (ev): void => {
|
||||
hasOnEvents.loadend = true;
|
||||
|
||||
assertEquals(hasOnEvents.load, false);
|
||||
assertEquals(hasOnEvents.loadend, true);
|
||||
assertEquals(hasOnEvents.abort, true);
|
||||
|
||||
assertEquals(fr.readyState, FileReader.DONE);
|
||||
assertEquals(fr.result, null);
|
||||
assertEquals(ev.lengthComputable, false);
|
||||
resolve();
|
||||
};
|
||||
fr.onabort = (): void => {
|
||||
hasOnEvents.abort = true;
|
||||
};
|
||||
|
||||
fr.readAsDataURL(b1);
|
||||
fr.abort();
|
||||
});
|
||||
});
|
||||
|
||||
unitTest(async function fileReaderLoadBlobAbort(): Promise<void> {
|
||||
await new Promise<void>((resolve) => {
|
||||
const fr = new FileReader();
|
||||
const b1 = new Blob(["Hello World"]);
|
||||
|
||||
const hasOnEvents = {
|
||||
load: false,
|
||||
loadend: false,
|
||||
abort: false,
|
||||
};
|
||||
|
||||
fr.onload = (): void => {
|
||||
hasOnEvents.load = true;
|
||||
};
|
||||
fr.onloadend = (ev): void => {
|
||||
hasOnEvents.loadend = true;
|
||||
|
||||
assertEquals(hasOnEvents.load, false);
|
||||
assertEquals(hasOnEvents.loadend, true);
|
||||
assertEquals(hasOnEvents.abort, true);
|
||||
|
||||
assertEquals(fr.readyState, FileReader.DONE);
|
||||
assertEquals(fr.result, null);
|
||||
assertEquals(ev.lengthComputable, false);
|
||||
resolve();
|
||||
};
|
||||
fr.onabort = (): void => {
|
||||
hasOnEvents.abort = true;
|
||||
};
|
||||
|
||||
fr.readAsDataURL(b1);
|
||||
fr.abort();
|
||||
});
|
||||
});
|
18
cli/tests/unit/progressevent_test.ts
Normal file
18
cli/tests/unit/progressevent_test.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license.
|
||||
import { unitTest, assertEquals } from "./test_util.ts";
|
||||
|
||||
unitTest(function progressEventConstruct(): void {
|
||||
const progressEventDefs = new ProgressEvent("progressEventType", {});
|
||||
assertEquals(progressEventDefs.lengthComputable, false);
|
||||
assertEquals(progressEventDefs.loaded, 0);
|
||||
assertEquals(progressEventDefs.total, 0);
|
||||
|
||||
const progressEvent = new ProgressEvent("progressEventType", {
|
||||
lengthComputable: true,
|
||||
loaded: 123,
|
||||
total: 456,
|
||||
});
|
||||
assertEquals(progressEvent.lengthComputable, true);
|
||||
assertEquals(progressEvent.loaded, 123);
|
||||
assertEquals(progressEvent.total, 456);
|
||||
});
|
|
@ -23,6 +23,7 @@ import "./event_test.ts";
|
|||
import "./event_target_test.ts";
|
||||
import "./fetch_test.ts";
|
||||
import "./file_test.ts";
|
||||
import "./filereader_test.ts";
|
||||
import "./files_test.ts";
|
||||
import "./filter_function_test.ts";
|
||||
import "./form_data_test.ts";
|
||||
|
@ -43,6 +44,7 @@ import "./os_test.ts";
|
|||
import "./permissions_test.ts";
|
||||
import "./path_from_url_test.ts";
|
||||
import "./process_test.ts";
|
||||
import "./progressevent_test.ts";
|
||||
import "./real_path_test.ts";
|
||||
import "./read_dir_test.ts";
|
||||
import "./read_text_file_test.ts";
|
||||
|
|
|
@ -835,4 +835,6 @@
|
|||
window.TextDecoder = TextDecoder;
|
||||
window.atob = atob;
|
||||
window.btoa = btoa;
|
||||
window.__bootstrap = (window.__bootstrap || {});
|
||||
window.__bootstrap.base64 = base64;
|
||||
})(this);
|
||||
|
|
Loading…
Reference in a new issue