From 1507a8cf2d8bce8c3596583b995fea4914a99203 Mon Sep 17 00:00:00 2001 From: Luca Casonato Date: Wed, 19 Aug 2020 14:43:20 +0200 Subject: [PATCH] refactor(op_crates/web): move abort signal (#7117) --- cli/build.rs | 2 +- cli/dts/lib.deno.shared_globals.d.ts | 48 ------------- cli/rt/11_streams.js | 1 - cli/rt/99_main.js | 3 - {cli/rt => op_crates/web}/02_abort_signal.js | 5 +- op_crates/web/abort_controller_test.js | 75 ++++++++++++++++++++ op_crates/web/lib.deno_web.d.ts | 50 +++++++++++++ op_crates/web/lib.rs | 19 +++++ 8 files changed, 148 insertions(+), 55 deletions(-) rename {cli/rt => op_crates/web}/02_abort_signal.js (91%) create mode 100644 op_crates/web/abort_controller_test.js diff --git a/cli/build.rs b/cli/build.rs index 3f4cd2a5b1..4c87d15e0c 100644 --- a/cli/build.rs +++ b/cli/build.rs @@ -146,7 +146,7 @@ fn get_js_files_for_rt() -> Vec { "rt/01_internals.js", "rt/01_version.js", "rt/01_web_util.js", - "rt/02_abort_signal.js", + &web_scripts.abort_signal, "rt/02_console.js", "rt/03_dom_iterable.js", "rt/06_util.js", diff --git a/cli/dts/lib.deno.shared_globals.d.ts b/cli/dts/lib.deno.shared_globals.d.ts index e21d6fc15d..672f8ada41 100644 --- a/cli/dts/lib.deno.shared_globals.d.ts +++ b/cli/dts/lib.deno.shared_globals.d.ts @@ -1473,54 +1473,6 @@ declare class CustomEvent extends Event { readonly detail: T; } -/** A controller object that allows you to abort one or more DOM requests as and - * when desired. */ -declare class AbortController { - /** Returns the AbortSignal object associated with this object. */ - readonly signal: AbortSignal; - /** Invoking this method will set this object's AbortSignal's aborted flag and - * signal to any observers that the associated activity is to be aborted. */ - abort(): void; -} - -interface AbortSignalEventMap { - abort: Event; -} - -/** A signal object that allows you to communicate with a DOM request (such as a - * Fetch) and abort it if required via an AbortController object. */ -interface AbortSignal extends EventTarget { - /** Returns true if this AbortSignal's AbortController has signaled to abort, - * and false otherwise. */ - readonly aborted: boolean; - onabort: ((this: AbortSignal, ev: Event) => any) | null; - addEventListener( - type: K, - listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, - options?: boolean | AddEventListenerOptions, - ): void; - addEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | AddEventListenerOptions, - ): void; - removeEventListener( - type: K, - listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, - options?: boolean | EventListenerOptions, - ): void; - removeEventListener( - type: string, - listener: EventListenerOrEventListenerObject, - options?: boolean | EventListenerOptions, - ): void; -} - -declare const AbortSignal: { - prototype: AbortSignal; - new (): AbortSignal; -}; - interface ErrorConstructor { /** See https://v8.dev/docs/stack-trace-api#stack-trace-collection-for-custom-exceptions. */ // eslint-disable-next-line @typescript-eslint/ban-types diff --git a/cli/rt/11_streams.js b/cli/rt/11_streams.js index 4bdbfbc5cc..e5a5732e5e 100644 --- a/cli/rt/11_streams.js +++ b/cli/rt/11_streams.js @@ -9,7 +9,6 @@ ((window) => { /* eslint-disable @typescript-eslint/no-explicit-any,require-await */ - const { AbortSignal } = window.__bootstrap.abortSignal; const { cloneValue, setFunctionName } = window.__bootstrap.webUtil; const { assert, AssertionError } = window.__bootstrap.util; const { customInspect, inspect } = window.__bootstrap.console; diff --git a/cli/rt/99_main.js b/cli/rt/99_main.js index d9cee0aa58..18cc1d2513 100644 --- a/cli/rt/99_main.js +++ b/cli/rt/99_main.js @@ -20,7 +20,6 @@ delete Object.prototype.__proto__; const worker = window.__bootstrap.worker; const signals = window.__bootstrap.signals; const { internalSymbol, internalObject } = window.__bootstrap.internals; - const abortSignal = window.__bootstrap.abortSignal; const performance = window.__bootstrap.performance; const crypto = window.__bootstrap.crypto; const url = window.__bootstrap.url; @@ -217,8 +216,6 @@ delete Object.prototype.__proto__; // Other properties shared between WindowScope and WorkerGlobalScope const windowOrWorkerGlobalScopeProperties = { console: util.writable(new Console(core.print)), - AbortController: util.nonEnumerable(abortSignal.AbortController), - AbortSignal: util.nonEnumerable(abortSignal.AbortSignal), Blob: util.nonEnumerable(blob.Blob), ByteLengthQueuingStrategy: util.nonEnumerable( queuingStrategy.ByteLengthQueuingStrategy, diff --git a/cli/rt/02_abort_signal.js b/op_crates/web/02_abort_signal.js similarity index 91% rename from cli/rt/02_abort_signal.js rename to op_crates/web/02_abort_signal.js index cd38fff640..908e85ac97 100644 --- a/cli/rt/02_abort_signal.js +++ b/op_crates/web/02_abort_signal.js @@ -65,11 +65,12 @@ } } + window.AbortSignal = AbortSignal; + window.AbortController = AbortController; + window.__bootstrap = window.__bootstrap || {}; window.__bootstrap.abortSignal = { - AbortSignal, add, signalAbort, remove, - AbortController, }; })(this); diff --git a/op_crates/web/abort_controller_test.js b/op_crates/web/abort_controller_test.js new file mode 100644 index 0000000000..a2fb12c65e --- /dev/null +++ b/op_crates/web/abort_controller_test.js @@ -0,0 +1,75 @@ +// Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +function assert(cond) { + if (!cond) { + throw Error("assert"); + } +} + +function assertEquals(left, right) { + assert(left === right); +} + +function basicAbortController() { + controller = new AbortController(); + assert(controller); + const { signal } = controller; + assert(signal); + assertEquals(signal.aborted, false); + controller.abort(); + assertEquals(signal.aborted, true); +} + +function signalCallsOnabort() { + const controller = new AbortController(); + const { signal } = controller; + let called = false; + signal.onabort = (evt) => { + assert(evt); + assertEquals(evt.type, "abort"); + called = true; + }; + controller.abort(); + assert(called); +} + +function signalEventListener() { + const controller = new AbortController(); + const { signal } = controller; + let called = false; + signal.addEventListener("abort", function (ev) { + assert(this === signal); + assertEquals(ev.type, "abort"); + called = true; + }); + controller.abort(); + assert(called); +} + +function onlyAbortsOnce() { + const controller = new AbortController(); + const { signal } = controller; + let called = 0; + signal.addEventListener("abort", () => called++); + signal.onabort = () => { + called++; + }; + controller.abort(); + assertEquals(called, 2); + controller.abort(); + assertEquals(called, 2); +} + +function controllerHasProperToString() { + const actual = Object.prototype.toString.call(new AbortController()); + assertEquals(actual, "[object AbortController]"); +} + +function main() { + basicAbortController(); + signalCallsOnabort(); + signalEventListener(); + onlyAbortsOnce(); + controllerHasProperToString(); +} + +main(); diff --git a/op_crates/web/lib.deno_web.d.ts b/op_crates/web/lib.deno_web.d.ts index b402529e2e..d24a3b76f5 100644 --- a/op_crates/web/lib.deno_web.d.ts +++ b/op_crates/web/lib.deno_web.d.ts @@ -1,5 +1,7 @@ // Copyright 2018-2020 the Deno authors. All rights reserved. MIT license. +/* eslint-disable @typescript-eslint/no-explicit-any */ + /// /// @@ -185,3 +187,51 @@ declare class TextEncoder { ): { read: number; written: number }; readonly [Symbol.toStringTag]: string; } + +/** A controller object that allows you to abort one or more DOM requests as and + * when desired. */ +declare class AbortController { + /** Returns the AbortSignal object associated with this object. */ + readonly signal: AbortSignal; + /** Invoking this method will set this object's AbortSignal's aborted flag and + * signal to any observers that the associated activity is to be aborted. */ + abort(): void; +} + +interface AbortSignalEventMap { + abort: Event; +} + +/** A signal object that allows you to communicate with a DOM request (such as a + * Fetch) and abort it if required via an AbortController object. */ +interface AbortSignal extends EventTarget { + /** Returns true if this AbortSignal's AbortController has signaled to abort, + * and false otherwise. */ + readonly aborted: boolean; + onabort: ((this: AbortSignal, ev: Event) => any) | null; + addEventListener( + type: K, + listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, + options?: boolean | AddEventListenerOptions, + ): void; + addEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ): void; + removeEventListener( + type: K, + listener: (this: AbortSignal, ev: AbortSignalEventMap[K]) => any, + options?: boolean | EventListenerOptions, + ): void; + removeEventListener( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | EventListenerOptions, + ): void; +} + +declare const AbortSignal: { + prototype: AbortSignal; + new (): AbortSignal; +}; diff --git a/op_crates/web/lib.rs b/op_crates/web/lib.rs index 4cfe8d090b..03c0c89af4 100644 --- a/op_crates/web/lib.rs +++ b/op_crates/web/lib.rs @@ -6,6 +6,7 @@ use std::path::PathBuf; crate_modules!(); pub struct WebScripts { + pub abort_signal: String, pub declaration: String, pub dom_exception: String, pub event: String, @@ -21,6 +22,7 @@ fn get_str_path(file_name: &str) -> String { pub fn get_scripts() -> WebScripts { WebScripts { + abort_signal: get_str_path("02_abort_signal.js"), declaration: get_str_path("lib.deno_web.d.ts"), dom_exception: get_str_path("00_dom_exception.js"), event: get_str_path("01_event.js"), @@ -52,6 +54,9 @@ mod tests { .execute("00_dom_exception.js", include_str!("00_dom_exception.js")), ); js_check(isolate.execute("01_event.js", include_str!("01_event.js"))); + js_check( + isolate.execute("02_abort_signal.js", include_str!("02_abort_signal.js")), + ); js_check( isolate .execute("08_text_encoding.js", include_str!("08_text_encoding.js")), @@ -59,6 +64,20 @@ mod tests { isolate } + #[test] + fn test_abort_controller() { + run_in_task(|mut cx| { + let mut isolate = setup(); + js_check(isolate.execute( + "abort_controller_test.js", + include_str!("abort_controller_test.js"), + )); + if let Poll::Ready(Err(_)) = isolate.poll_unpin(&mut cx) { + unreachable!(); + } + }); + } + #[test] fn test_event() { run_in_task(|mut cx| {