diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp
index 31ba38b5622..8a74eefbcea 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp
+++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.cpp
@@ -584,4 +584,34 @@ void HTMLScriptElement::unmark_as_parser_inserted(Badge)
m_parser_document = nullptr;
}
+// https://html.spec.whatwg.org/multipage/scripting.html#dom-script-async
+bool HTMLScriptElement::async() const
+{
+ // 1. If this's force async is true, then return true.
+ if (m_force_async)
+ return true;
+
+ // 2. If this's async content attribute is present, then return true.
+ if (has_attribute(HTML::AttributeNames::async))
+ return true;
+
+ // 3. Return false.
+ return false;
+}
+
+void HTMLScriptElement::set_async(bool async)
+{
+ // 1. Set this's force async to false.
+ m_force_async = false;
+
+ // 2. If the given value is true, then set this's async content attribute to the empty string.
+ if (async) {
+ MUST(set_attribute(HTML::AttributeNames::async, ""_string));
+ }
+ // 3. Otherwise, remove this's async content attribute.
+ else {
+ remove_attribute(HTML::AttributeNames::async);
+ }
+}
+
}
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h
index f89fc2bd773..14dc6e1f709 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h
+++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.h
@@ -58,6 +58,9 @@ public:
String text() { return child_text_content(); }
void set_text(String const& text) { string_replace_all(text); }
+ [[nodiscard]] bool async() const;
+ void set_async(bool);
+
private:
HTMLScriptElement(DOM::Document&, DOM::QualifiedName);
diff --git a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.idl b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.idl
index b3dffc7e2ae..c4ac9c81080 100644
--- a/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.idl
+++ b/Userland/Libraries/LibWeb/HTML/HTMLScriptElement.idl
@@ -10,7 +10,7 @@ interface HTMLScriptElement : HTMLElement {
[CEReactions, Reflect] attribute DOMString src;
[CEReactions, Reflect] attribute DOMString type;
[CEReactions, Reflect=nomodule] attribute boolean noModule;
- // FIXME: [CEReactions] attribute boolean async;
+ [CEReactions] attribute boolean async;
[CEReactions, Reflect] attribute boolean defer;
[CEReactions, Reflect=crossorigin, Enumerated=CORSSettingsAttribute] attribute DOMString? crossOrigin;
[CEReactions] attribute DOMString text;