Browse Source

LibWeb: Implement `AbortSignal.abort()`

This returns an AbortSignal that is already set as aborted.
Tim Ledbetter 1 year ago
parent
commit
3b7c252175

+ 4 - 0
Tests/LibWeb/Text/expected/abortsignal-abort.txt

@@ -0,0 +1,4 @@
+Aborted: true
+Reason: "[object DOMException]"
+Aborted: true
+Reason: "This is a test"

+ 19 - 0
Tests/LibWeb/Text/input/abortsignal-abort.html

@@ -0,0 +1,19 @@
+<script src="include.js"></script>
+<script>
+    asyncTest(async done => {
+        function testSignal(signal) {
+            return fetch("./basic.html", { signal })
+                .then(() => {
+                    println("FAIL");
+                })
+                .catch(error => {
+                    println(`Aborted: ${signal.aborted}`);
+                    println(`Reason: "${error}"`);
+                });
+        }
+
+        testSignal(AbortSignal.abort())
+            .then(() => testSignal(AbortSignal.abort("This is a test")))
+            .finally(done);
+    });
+</script>

+ 16 - 0
Userland/Libraries/LibWeb/DOM/AbortSignal.cpp

@@ -116,4 +116,20 @@ void AbortSignal::follow(JS::NonnullGCPtr<AbortSignal> parent_signal)
     });
 }
 
+// https://dom.spec.whatwg.org/#dom-abortsignal-abort
+WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> AbortSignal::abort(JS::VM& vm, JS::Value reason)
+{
+    // 1. Let signal be a new AbortSignal object.
+    auto signal = TRY(construct_impl(*vm.current_realm()));
+
+    // 2. Set signal’s abort reason to reason if it is given; otherwise to a new "AbortError" DOMException.
+    if (reason.is_undefined())
+        reason = WebIDL::AbortError::create(*vm.current_realm(), "Aborted without reason"_fly_string).ptr();
+
+    signal->set_reason(reason);
+
+    // 3. Return signal.
+    return signal;
+}
+
 }

+ 3 - 0
Userland/Libraries/LibWeb/DOM/AbortSignal.h

@@ -37,11 +37,14 @@ public:
 
     // https://dom.spec.whatwg.org/#dom-abortsignal-reason
     JS::Value reason() const { return m_abort_reason; }
+    void set_reason(JS::Value reason) { m_abort_reason = reason; }
 
     JS::ThrowCompletionOr<void> throw_if_aborted() const;
 
     void follow(JS::NonnullGCPtr<AbortSignal> parent_signal);
 
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<AbortSignal>> abort(JS::VM&, JS::Value reason);
+
 private:
     explicit AbortSignal(JS::Realm&);
 

+ 1 - 1
Userland/Libraries/LibWeb/DOM/AbortSignal.idl

@@ -4,7 +4,7 @@
 // https://dom.spec.whatwg.org/#interface-AbortSignal
 [Exposed=(Window,Worker), CustomVisit]
 interface AbortSignal : EventTarget {
-    // FIXME: [NewObject] static AbortSignal abort(optional any reason);
+    [NewObject] static AbortSignal abort(optional any reason);
     // FIXME: [Exposed=(Window,Worker), NewObject] static AbortSignal timeout([EnforceRange] unsigned long long milliseconds);
     // FIXME: [NewObject] static AbortSignal _any(sequence<AbortSignal> signals);