From ec174170ba090728ebb83b05450d5550a514f43f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Fri, 18 Sep 2020 16:01:50 +0200 Subject: [PATCH] refactor: move FileReader to op_crates/web (#7554) --- cli/dts/lib.deno.shared_globals.d.ts | 42 ------------- cli/rt/99_main.js | 3 +- op_crates/web/01_event.js | 13 ++++ .../web/21_filereader.js | 24 ++----- op_crates/web/lib.deno_web.d.ts | 62 ++++++++++++++++++- op_crates/web/lib.rs | 1 + 6 files changed, 80 insertions(+), 65 deletions(-) rename cli/rt/28_filereader.js => op_crates/web/21_filereader.js (92%) diff --git a/cli/dts/lib.deno.shared_globals.d.ts b/cli/dts/lib.deno.shared_globals.d.ts index 786b06f1bb..ba0719a837 100644 --- a/cli/dts/lib.deno.shared_globals.d.ts +++ b/cli/dts/lib.deno.shared_globals.d.ts @@ -240,48 +240,6 @@ interface DOMStringList { type BufferSource = ArrayBufferView | ArrayBuffer; -interface FileReaderEventMap { - "abort": ProgressEvent; - "error": ProgressEvent; - "load": ProgressEvent; - "loadend": ProgressEvent; - "loadstart": ProgressEvent; - "progress": ProgressEvent; -} - -/** 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) => any) | null; - onerror: ((this: FileReader, ev: ProgressEvent) => any) | null; - onload: ((this: FileReader, ev: ProgressEvent) => any) | null; - onloadend: ((this: FileReader, ev: ProgressEvent) => any) | null; - onloadstart: ((this: FileReader, ev: ProgressEvent) => any) | null; - onprogress: ((this: FileReader, ev: ProgressEvent) => 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(type: K, listener: (this: FileReader, ev: FileReaderEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void; - addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void; - removeEventListener(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 { diff --git a/cli/rt/99_main.js b/cli/rt/99_main.js index 8091823bba..a15de081c9 100644 --- a/cli/rt/99_main.js +++ b/cli/rt/99_main.js @@ -23,7 +23,6 @@ delete Object.prototype.__proto__; const url = window.__bootstrap.url; const headers = window.__bootstrap.headers; const streams = window.__bootstrap.streams; - const progressEvent = window.__bootstrap.progressEvent; const fileReader = window.__bootstrap.fileReader; const webSocket = window.__bootstrap.webSocket; const fetch = window.__bootstrap.fetch; @@ -215,7 +214,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), + ProgressEvent: util.nonEnumerable(ProgressEvent), ReadableStream: util.nonEnumerable(streams.ReadableStream), Request: util.nonEnumerable(fetch.Request), Response: util.nonEnumerable(fetch.Response), diff --git a/op_crates/web/01_event.js b/op_crates/web/01_event.js index 5b21d44025..b0d7f2939f 100644 --- a/op_crates/web/01_event.js +++ b/op_crates/web/01_event.js @@ -1083,12 +1083,25 @@ enumerable: true, }); + // 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.Event = Event; window.EventTarget = EventTarget; window.ErrorEvent = ErrorEvent; window.CloseEvent = CloseEvent; window.MessageEvent = MessageEvent; window.CustomEvent = CustomEvent; + window.ProgressEvent = ProgressEvent; window.dispatchEvent = EventTarget.prototype.dispatchEvent; window.addEventListener = EventTarget.prototype.addEventListener; window.removeEventListener = EventTarget.prototype.removeEventListener; diff --git a/cli/rt/28_filereader.js b/op_crates/web/21_filereader.js similarity index 92% rename from cli/rt/28_filereader.js rename to op_crates/web/21_filereader.js index ea1ca3e5f5..8a5262a7ef 100644 --- a/cli/rt/28_filereader.js +++ b/op_crates/web/21_filereader.js @@ -2,22 +2,6 @@ ((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 @@ -63,14 +47,14 @@ // 2. If chunkPromise is fulfilled, and isFirstChunk is true, queue a task to fire a progress event called loadstart at fr. if (isFirstChunk) { - setTimeout(() => { + queueMicrotask(() => { // 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; @@ -95,7 +79,7 @@ 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(() => { + queueMicrotask(() => { if (fr.aborting) { return; } @@ -152,7 +136,7 @@ fr.onloadend(ev); } } - }, 0); + }); break; } diff --git a/op_crates/web/lib.deno_web.d.ts b/op_crates/web/lib.deno_web.d.ts index d24a3b76f5..102fbf7187 100644 --- a/op_crates/web/lib.deno_web.d.ts +++ b/op_crates/web/lib.deno_web.d.ts @@ -1,6 +1,6 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. -/* eslint-disable @typescript-eslint/no-explicit-any */ +/* eslint-disable @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any, no-var */ /// /// @@ -235,3 +235,63 @@ declare const AbortSignal: { prototype: AbortSignal; new (): AbortSignal; }; + +interface FileReaderEventMap { + "abort": ProgressEvent; + "error": ProgressEvent; + "load": ProgressEvent; + "loadend": ProgressEvent; + "loadstart": ProgressEvent; + "progress": ProgressEvent; +} + +/** 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) => any) | null; + onerror: ((this: FileReader, ev: ProgressEvent) => any) | null; + onload: ((this: FileReader, ev: ProgressEvent) => any) | null; + onloadend: ((this: FileReader, ev: ProgressEvent) => any) | null; + onloadstart: + | ((this: FileReader, ev: ProgressEvent) => any) + | null; + onprogress: ((this: FileReader, ev: ProgressEvent) => 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( + type: K, + listener: (this: FileReader, ev: FileReaderEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + 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; +}; diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index f6c7137f72..278accd2f1 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -46,6 +46,7 @@ pub fn init(isolate: &mut JsRuntime) { manifest_dir.join("02_abort_signal.js"), manifest_dir.join("08_text_encoding.js"), manifest_dir.join("11_url.js"), + manifest_dir.join("21_filereader.js"), ]; // TODO(nayeemrmn): https://github.com/rust-lang/cargo/issues/3946 to get the // workspace root.