diff --git a/components/script/dom/abortsignal.rs b/components/script/dom/abortsignal.rs new file mode 100644 index 00000000000..535e27c3e10 --- /dev/null +++ b/components/script/dom/abortsignal.rs @@ -0,0 +1,71 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +use dom_struct::dom_struct; +use js::jsapi::{Heap, Value}; +use js::jsval::JSVal; +use js::rust::{HandleObject, MutableHandleValue}; + +use crate::dom::bindings::codegen::Bindings::AbortSignalBinding::AbortSignalMethods; +use crate::dom::bindings::reflector::reflect_dom_object_with_proto; +use crate::dom::bindings::root::DomRoot; +use crate::dom::eventtarget::EventTarget; +use crate::dom::globalscope::GlobalScope; +use crate::script_runtime::{CanGc, JSContext}; + +/// +#[dom_struct] +pub(crate) struct AbortSignal { + eventtarget: EventTarget, + + /// + #[ignore_malloc_size_of = "mozjs"] + abort_reason: Heap, +} + +impl AbortSignal { + #[allow(dead_code)] + fn new_inherited() -> AbortSignal { + AbortSignal { + eventtarget: EventTarget::new_inherited(), + abort_reason: Default::default(), + } + } + + #[allow(dead_code)] + fn new_with_proto( + global: &GlobalScope, + proto: Option, + can_gc: CanGc, + ) -> DomRoot { + reflect_dom_object_with_proto( + Box::new(AbortSignal::new_inherited()), + global, + proto, + can_gc, + ) + } +} + +impl AbortSignalMethods for AbortSignal { + /// + fn Aborted(&self) -> bool { + // TODO + false + } + + /// + fn Reason(&self, _: JSContext, _rval: MutableHandleValue) { + // TODO + } + + /// + #[allow(unsafe_code)] + fn ThrowIfAborted(&self) { + // TODO + } + + /// + event_handler!(abort, GetOnabort, SetOnabort); +} diff --git a/components/script/dom/mod.rs b/components/script/dom/mod.rs index 388d8cfde2a..5d7f1966207 100644 --- a/components/script/dom/mod.rs +++ b/components/script/dom/mod.rs @@ -211,6 +211,7 @@ pub(crate) mod types { } pub(crate) mod abortcontroller; +pub(crate) mod abortsignal; #[allow(dead_code)] pub(crate) mod abstractrange; pub(crate) mod abstractworker; diff --git a/components/script_bindings/webidls/AbortSignal.webidl b/components/script_bindings/webidls/AbortSignal.webidl new file mode 100644 index 00000000000..bea70e41739 --- /dev/null +++ b/components/script_bindings/webidls/AbortSignal.webidl @@ -0,0 +1,14 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +// https://dom.spec.whatwg.org/#abortsignal + +[Exposed=*] +interface AbortSignal : EventTarget { + readonly attribute boolean aborted; + readonly attribute any reason; + undefined throwIfAborted(); + + attribute EventHandler onabort; +}; diff --git a/tests/wpt/meta/dom/abort/abort-signal-any.any.js.ini b/tests/wpt/meta/dom/abort/abort-signal-any.any.js.ini index f1013fd736d..8164c20ef3c 100644 --- a/tests/wpt/meta/dom/abort/abort-signal-any.any.js.ini +++ b/tests/wpt/meta/dom/abort/abort-signal-any.any.js.ini @@ -1,5 +1,10 @@ [abort-signal-any.any.worker.html] expected: ERROR + [AbortSignal.any() works with an empty array of signals] + expected: FAIL + [abort-signal-any.any.html] expected: ERROR + [AbortSignal.any() works with an empty array of signals] + expected: FAIL diff --git a/tests/wpt/meta/dom/idlharness.any.js.ini b/tests/wpt/meta/dom/idlharness.any.js.ini index c75d2d801bf..b494428e3f4 100644 --- a/tests/wpt/meta/dom/idlharness.any.js.ini +++ b/tests/wpt/meta/dom/idlharness.any.js.ini @@ -17,33 +17,9 @@ [AbortController interface: new AbortController() must inherit property "abort()" with the proper type] expected: FAIL - [AbortSignal interface: existence and properties of interface object] - expected: FAIL - - [AbortSignal interface object length] - expected: FAIL - - [AbortSignal interface object name] - expected: FAIL - - [AbortSignal interface: existence and properties of interface prototype object] - expected: FAIL - - [AbortSignal interface: existence and properties of interface prototype object's "constructor" property] - expected: FAIL - - [AbortSignal interface: existence and properties of interface prototype object's @@unscopables property] - expected: FAIL - [AbortSignal interface: operation abort()] expected: FAIL - [AbortSignal interface: attribute aborted] - expected: FAIL - - [AbortSignal interface: attribute onabort] - expected: FAIL - [AbortSignal must be primary interface of new AbortController().signal] expected: FAIL @@ -80,12 +56,6 @@ [AbortSignal interface: operation abort(optional any)] expected: FAIL - [AbortSignal interface: attribute reason] - expected: FAIL - - [AbortSignal interface: operation throwIfAborted()] - expected: FAIL - [AbortSignal interface: new AbortController().signal must inherit property "abort(optional any)" with the proper type] expected: FAIL diff --git a/tests/wpt/meta/dom/interface-objects.html.ini b/tests/wpt/meta/dom/interface-objects.html.ini index ddc761b4169..9b08fb2e7ce 100644 --- a/tests/wpt/meta/dom/interface-objects.html.ini +++ b/tests/wpt/meta/dom/interface-objects.html.ini @@ -1,6 +1,3 @@ [interface-objects.html] - [Should be able to delete AbortSignal.] - expected: FAIL - [Should be able to delete AbortController.] expected: FAIL diff --git a/tests/wpt/meta/streams/piping/abort.any.js.ini b/tests/wpt/meta/streams/piping/abort.any.js.ini index 703ed108ffb..fc936d9420b 100644 --- a/tests/wpt/meta/streams/piping/abort.any.js.ini +++ b/tests/wpt/meta/streams/piping/abort.any.js.ini @@ -5,7 +5,105 @@ expected: ERROR [abort.any.html] - expected: ERROR + [a signal argument 'null' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument 'AbortSignal' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument 'true' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument '-1' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument '[object AbortSignal\]' should cause pipeTo() to reject] + expected: FAIL + + [an aborted signal should cause the writable stream to reject with an AbortError] + expected: FAIL + + [(reason: 'null') all the error objects should be the same object] + expected: FAIL + + [(reason: 'undefined') all the error objects should be the same object] + expected: FAIL + + [(reason: 'error1: error1') all the error objects should be the same object] + expected: FAIL + + [preventCancel should prevent canceling the readable] + expected: FAIL + + [preventAbort should prevent aborting the readable] + expected: FAIL + + [preventCancel and preventAbort should prevent canceling the readable and aborting the readable] + expected: FAIL + + [(reason: 'null') abort should prevent further reads] + expected: FAIL + + [(reason: 'undefined') abort should prevent further reads] + expected: FAIL + + [(reason: 'error1: error1') abort should prevent further reads] + expected: FAIL + + [(reason: 'null') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'undefined') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'error1: error1') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'null') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [(reason: 'undefined') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [(reason: 'error1: error1') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [a rejection from underlyingSource.cancel() should be returned by pipeTo()] + expected: FAIL + + [a rejection from underlyingSink.abort() should be returned by pipeTo()] + expected: FAIL + + [a rejection from underlyingSink.abort() should be preferred to one from underlyingSource.cancel()] + expected: FAIL + + [abort signal takes priority over closed readable] + expected: FAIL + + [abort signal takes priority over errored readable] + expected: FAIL + + [abort signal takes priority over closed writable] + expected: FAIL + + [abort signal takes priority over errored writable] + expected: FAIL + + [abort should do nothing after the readable is closed] + expected: FAIL + + [abort should do nothing after the readable is errored] + expected: FAIL + + [abort should do nothing after the readable is errored, even with pending writes] + expected: FAIL + + [abort should do nothing after the writable is errored] + expected: FAIL + + [pipeTo on a teed readable byte stream should only be aborted when both branches are aborted] + expected: FAIL + [abort.any.shadowrealm-in-dedicatedworker.html] expected: ERROR @@ -20,7 +118,105 @@ expected: ERROR [abort.any.worker.html] - expected: ERROR + [a signal argument 'null' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument 'AbortSignal' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument 'true' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument '-1' should cause pipeTo() to reject] + expected: FAIL + + [a signal argument '[object AbortSignal\]' should cause pipeTo() to reject] + expected: FAIL + + [an aborted signal should cause the writable stream to reject with an AbortError] + expected: FAIL + + [(reason: 'null') all the error objects should be the same object] + expected: FAIL + + [(reason: 'undefined') all the error objects should be the same object] + expected: FAIL + + [(reason: 'error1: error1') all the error objects should be the same object] + expected: FAIL + + [preventCancel should prevent canceling the readable] + expected: FAIL + + [preventAbort should prevent aborting the readable] + expected: FAIL + + [preventCancel and preventAbort should prevent canceling the readable and aborting the readable] + expected: FAIL + + [(reason: 'null') abort should prevent further reads] + expected: FAIL + + [(reason: 'undefined') abort should prevent further reads] + expected: FAIL + + [(reason: 'error1: error1') abort should prevent further reads] + expected: FAIL + + [(reason: 'null') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'undefined') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'error1: error1') all pending writes should complete on abort] + expected: FAIL + + [(reason: 'null') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [(reason: 'undefined') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [(reason: 'error1: error1') underlyingSource.cancel() should called when abort, even with pending pull] + expected: FAIL + + [a rejection from underlyingSource.cancel() should be returned by pipeTo()] + expected: FAIL + + [a rejection from underlyingSink.abort() should be returned by pipeTo()] + expected: FAIL + + [a rejection from underlyingSink.abort() should be preferred to one from underlyingSource.cancel()] + expected: FAIL + + [abort signal takes priority over closed readable] + expected: FAIL + + [abort signal takes priority over errored readable] + expected: FAIL + + [abort signal takes priority over closed writable] + expected: FAIL + + [abort signal takes priority over errored writable] + expected: FAIL + + [abort should do nothing after the readable is closed] + expected: FAIL + + [abort should do nothing after the readable is errored] + expected: FAIL + + [abort should do nothing after the readable is errored, even with pending writes] + expected: FAIL + + [abort should do nothing after the writable is errored] + expected: FAIL + + [pipeTo on a teed readable byte stream should only be aborted when both branches are aborted] + expected: FAIL + [abort.https.any.shadowrealm-in-audioworklet.html] expected: ERROR diff --git a/tests/wpt/meta/streams/piping/pipe-through.any.js.ini b/tests/wpt/meta/streams/piping/pipe-through.any.js.ini index 1828ea894f4..83561f9eea2 100644 --- a/tests/wpt/meta/streams/piping/pipe-through.any.js.ini +++ b/tests/wpt/meta/streams/piping/pipe-through.any.js.ini @@ -5,7 +5,30 @@ expected: ERROR [pipe-through.any.worker.html] - expected: ERROR + [pipeThrough should accept a real AbortSignal] + expected: FAIL + + [pipeThrough should not care if readable is locked] + expected: FAIL + + [preventCancel should work] + expected: FAIL + + [preventClose should work] + expected: FAIL + + [preventAbort should work] + expected: FAIL + + [pipeThrough() should not throw if option is null] + expected: FAIL + + [pipeThrough() should not throw if signal is undefined] + expected: FAIL + + [pipeThrough() should throw if readable/writable getters throw] + expected: FAIL + [pipe-through.any.sharedworker.html] expected: ERROR @@ -26,4 +49,23 @@ expected: ERROR [pipe-through.any.html] - expected: ERROR + [pipeThrough should accept a real AbortSignal] + expected: FAIL + + [invalid values of signal should throw; specifically 'null'] + expected: FAIL + + [invalid values of signal should throw; specifically '0'] + expected: FAIL + + [invalid values of signal should throw; specifically 'NaN'] + expected: FAIL + + [invalid values of signal should throw; specifically 'true'] + expected: FAIL + + [invalid values of signal should throw; specifically 'AbortSignal'] + expected: FAIL + + [invalid values of signal should throw; specifically '[object AbortSignal\]'] + expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index bf19c365d17..e05f59524c5 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -13582,14 +13582,14 @@ ] ], "interfaces.https.html": [ - "eee8c799727b91e00b512795756b693a5f121f86", + "0689f4c2305d808471fa3f530595d407e92fda30", [ null, {} ] ], "interfaces.worker.js": [ - "e86f34f261442aeaa7074c525fb4b1206219769d", + "9e4c15823f1b19c70d9a64bde0074dfe4ba63f29", [ "mozilla/interfaces.worker.html", {} diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.https.html b/tests/wpt/mozilla/tests/mozilla/interfaces.https.html index eee8c799727..0689f4c2305 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.https.html +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.https.html @@ -11,6 +11,8 @@ // IMPORTANT: Do not change the list below without review from a DOM peer! test_interfaces([ + "AbortController", + "AbortSignal", "AbstractRange", "AnalyserNode", "AnimationEvent", diff --git a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js index e86f34f2614..9e4c15823f1 100644 --- a/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js +++ b/tests/wpt/mozilla/tests/mozilla/interfaces.worker.js @@ -7,6 +7,8 @@ importScripts("interfaces.js"); // IMPORTANT: Do not change the list below without review from a DOM peer! test_interfaces([ + "AbortController", + "AbortSignal", "Blob", "BroadcastChannel", "ByteLengthQueuingStrategy",