Parcourir la source

LibWeb: Allow using queuing strategies on globals other than Window

These interfaces are exposed on *, meaning it should work for workers
and our newly added shadow realm global object by being stored on the
universal global scope mixin.
Shannon Booth il y a 8 mois
Parent
commit
d527c5df5d

+ 1 - 0
Libraries/LibWeb/HTML/ShadowRealmGlobalScope.cpp

@@ -41,6 +41,7 @@ void ShadowRealmGlobalScope::initialize_web_interfaces()
 void ShadowRealmGlobalScope::visit_edges(Cell::Visitor& visitor)
 {
     Base::visit_edges(visitor);
+    UniversalGlobalScopeMixin::visit_edges(visitor);
 }
 
 }

+ 53 - 0
Libraries/LibWeb/HTML/UniversalGlobalScope.cpp

@@ -12,6 +12,7 @@
 #include <AK/Utf8View.h>
 #include <AK/Vector.h>
 #include <LibGC/Function.h>
+#include <LibJS/Runtime/NativeFunction.h>
 #include <LibWeb/HTML/Scripting/ExceptionReporter.h>
 #include <LibWeb/HTML/StructuredSerialize.h>
 #include <LibWeb/HTML/StructuredSerializeOptions.h>
@@ -27,6 +28,12 @@ namespace Web::HTML {
 
 UniversalGlobalScopeMixin::~UniversalGlobalScopeMixin() = default;
 
+void UniversalGlobalScopeMixin::visit_edges(GC::Cell::Visitor& visitor)
+{
+    visitor.visit(m_count_queuing_strategy_size_function);
+    visitor.visit(m_byte_length_queuing_strategy_size_function);
+}
+
 // https://html.spec.whatwg.org/multipage/webappapis.html#dom-btoa
 WebIDL::ExceptionOr<String> UniversalGlobalScopeMixin::btoa(String const& data) const
 {
@@ -101,4 +108,50 @@ WebIDL::ExceptionOr<JS::Value> UniversalGlobalScopeMixin::structured_clone(JS::V
     return deserialized;
 }
 
+// https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
+GC::Ref<WebIDL::CallbackType> UniversalGlobalScopeMixin::count_queuing_strategy_size_function()
+{
+    auto& realm = HTML::relevant_realm(this_impl());
+
+    if (!m_count_queuing_strategy_size_function) {
+        // 1. Let steps be the following steps:
+        auto steps = [](auto const&) {
+            // 1. Return 1.
+            return 1.0;
+        };
+
+        // 2. Let F be ! CreateBuiltinFunction(steps, 0, "size", « », globalObject’s relevant Realm).
+        auto function = JS::NativeFunction::create(realm, move(steps), 0, "size", &realm);
+
+        // 3. Set globalObject’s count queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObject’s relevant settings object.
+        m_count_queuing_strategy_size_function = realm.create<WebIDL::CallbackType>(*function, relevant_settings_object(this_impl()));
+    }
+
+    return GC::Ref { *m_count_queuing_strategy_size_function };
+}
+
+// https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
+GC::Ref<WebIDL::CallbackType> UniversalGlobalScopeMixin::byte_length_queuing_strategy_size_function()
+{
+    auto& realm = HTML::relevant_realm(this_impl());
+
+    if (!m_byte_length_queuing_strategy_size_function) {
+        // 1. Let steps be the following steps, given chunk:
+        auto steps = [](JS::VM& vm) {
+            auto chunk = vm.argument(0);
+
+            // 1. Return ? GetV(chunk, "byteLength").
+            return chunk.get(vm, vm.names.byteLength);
+        };
+
+        // 2. Let F be ! CreateBuiltinFunction(steps, 1, "size", « », globalObject’s relevant Realm).
+        auto function = JS::NativeFunction::create(realm, move(steps), 1, "size", &realm);
+
+        // 3. Set globalObject’s byte length queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObject’s relevant settings object.
+        m_byte_length_queuing_strategy_size_function = realm.create<WebIDL::CallbackType>(*function, relevant_settings_object(this_impl()));
+    }
+
+    return GC::Ref { *m_byte_length_queuing_strategy_size_function };
+}
+
 }

+ 13 - 0
Libraries/LibWeb/HTML/UniversalGlobalScope.h

@@ -28,6 +28,19 @@ public:
     WebIDL::ExceptionOr<String> atob(String const& data) const;
     void queue_microtask(WebIDL::CallbackType&);
     WebIDL::ExceptionOr<JS::Value> structured_clone(JS::Value, StructuredSerializeOptions const&) const;
+
+    GC::Ref<WebIDL::CallbackType> count_queuing_strategy_size_function();
+    GC::Ref<WebIDL::CallbackType> byte_length_queuing_strategy_size_function();
+
+protected:
+    void visit_edges(GC::Cell::Visitor&);
+
+private:
+    // https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
+    GC::Ptr<WebIDL::CallbackType> m_count_queuing_strategy_size_function;
+
+    // https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
+    GC::Ptr<WebIDL::CallbackType> m_byte_length_queuing_strategy_size_function;
 };
 
 }

+ 1 - 48
Libraries/LibWeb/HTML/Window.cpp

@@ -116,6 +116,7 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
 {
     Base::visit_edges(visitor);
     WindowOrWorkerGlobalScopeMixin::visit_edges(visitor);
+    UniversalGlobalScopeMixin::visit_edges(visitor);
 
     visitor.visit(m_associated_document);
     visitor.visit(m_current_event);
@@ -127,8 +128,6 @@ void Window::visit_edges(JS::Cell::Visitor& visitor)
     visitor.visit(m_animation_frame_callback_driver);
     visitor.visit(m_pdf_viewer_plugin_objects);
     visitor.visit(m_pdf_viewer_mime_type_objects);
-    visitor.visit(m_count_queuing_strategy_size_function);
-    visitor.visit(m_byte_length_queuing_strategy_size_function);
     visitor.visit(m_close_watcher_manager);
 }
 
@@ -662,52 +661,6 @@ Vector<GC::Ref<MimeType>> Window::pdf_viewer_mime_type_objects()
     return m_pdf_viewer_mime_type_objects;
 }
 
-// https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
-GC::Ref<WebIDL::CallbackType> Window::count_queuing_strategy_size_function()
-{
-    auto& realm = this->realm();
-
-    if (!m_count_queuing_strategy_size_function) {
-        // 1. Let steps be the following steps:
-        auto steps = [](auto const&) {
-            // 1. Return 1.
-            return 1.0;
-        };
-
-        // 2. Let F be ! CreateBuiltinFunction(steps, 0, "size", « », globalObject’s relevant Realm).
-        auto function = JS::NativeFunction::create(realm, move(steps), 0, "size", &realm);
-
-        // 3. Set globalObject’s count queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObject’s relevant settings object.
-        m_count_queuing_strategy_size_function = realm.create<WebIDL::CallbackType>(*function, relevant_settings_object(*this));
-    }
-
-    return GC::Ref { *m_count_queuing_strategy_size_function };
-}
-
-// https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
-GC::Ref<WebIDL::CallbackType> Window::byte_length_queuing_strategy_size_function()
-{
-    auto& realm = this->realm();
-
-    if (!m_byte_length_queuing_strategy_size_function) {
-        // 1. Let steps be the following steps, given chunk:
-        auto steps = [](JS::VM& vm) {
-            auto chunk = vm.argument(0);
-
-            // 1. Return ? GetV(chunk, "byteLength").
-            return chunk.get(vm, vm.names.byteLength);
-        };
-
-        // 2. Let F be ! CreateBuiltinFunction(steps, 1, "size", « », globalObject’s relevant Realm).
-        auto function = JS::NativeFunction::create(realm, move(steps), 1, "size", &realm);
-
-        // 3. Set globalObject’s byte length queuing strategy size function to a Function that represents a reference to F, with callback context equal to globalObject’s relevant settings object.
-        m_byte_length_queuing_strategy_size_function = realm.create<WebIDL::CallbackType>(*function, relevant_settings_object(*this));
-    }
-
-    return GC::Ref { *m_byte_length_queuing_strategy_size_function };
-}
-
 static bool s_inspector_object_exposed = false;
 static bool s_internals_object_exposed = false;
 

+ 0 - 9
Libraries/LibWeb/HTML/Window.h

@@ -141,9 +141,6 @@ public:
     CrossOriginPropertyDescriptorMap const& cross_origin_property_descriptor_map() const { return m_cross_origin_property_descriptor_map; }
     CrossOriginPropertyDescriptorMap& cross_origin_property_descriptor_map() { return m_cross_origin_property_descriptor_map; }
 
-    GC::Ref<WebIDL::CallbackType> count_queuing_strategy_size_function();
-    GC::Ref<WebIDL::CallbackType> byte_length_queuing_strategy_size_function();
-
     // JS API functions
     GC::Ref<WindowProxy> window() const;
     GC::Ref<WindowProxy> self() const;
@@ -313,12 +310,6 @@ private:
     // https://html.spec.whatwg.org/multipage/interaction.html#last-history-action-activation-timestamp
     HighResolutionTime::DOMHighResTimeStamp m_last_history_action_activation_timestamp { AK::Infinity<double> };
 
-    // https://streams.spec.whatwg.org/#count-queuing-strategy-size-function
-    GC::Ptr<WebIDL::CallbackType> m_count_queuing_strategy_size_function;
-
-    // https://streams.spec.whatwg.org/#byte-length-queuing-strategy-size-function
-    GC::Ptr<WebIDL::CallbackType> m_byte_length_queuing_strategy_size_function;
-
     // https://html.spec.whatwg.org/multipage/nav-history-apis.html#dom-window-status
     // When the Window object is created, the attribute must be set to the empty string. It does not do anything else.
     String m_status;

+ 1 - 0
Libraries/LibWeb/HTML/WorkerGlobalScope.cpp

@@ -45,6 +45,7 @@ void WorkerGlobalScope::visit_edges(Cell::Visitor& visitor)
 {
     Base::visit_edges(visitor);
     WindowOrWorkerGlobalScopeMixin::visit_edges(visitor);
+    UniversalGlobalScopeMixin::visit_edges(visitor);
 
     visitor.visit(m_location);
     visitor.visit(m_navigator);

+ 4 - 2
Libraries/LibWeb/Streams/ByteLengthQueuingStrategy.cpp

@@ -7,7 +7,7 @@
 
 #include <LibWeb/Bindings/ByteLengthQueuingStrategyPrototype.h>
 #include <LibWeb/Bindings/Intrinsics.h>
-#include <LibWeb/HTML/Window.h>
+#include <LibWeb/HTML/UniversalGlobalScope.h>
 #include <LibWeb/Streams/ByteLengthQueuingStrategy.h>
 
 namespace Web::Streams {
@@ -34,7 +34,9 @@ ByteLengthQueuingStrategy::~ByteLengthQueuingStrategy() = default;
 GC::Ref<WebIDL::CallbackType> ByteLengthQueuingStrategy::size()
 {
     // 1. Return this's relevant global object's byte length queuing strategy size function.
-    return verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).byte_length_queuing_strategy_size_function();
+    auto* global = dynamic_cast<HTML::UniversalGlobalScopeMixin*>(&HTML::relevant_global_object(*this));
+    VERIFY(global);
+    return global->byte_length_queuing_strategy_size_function();
 }
 
 void ByteLengthQueuingStrategy::initialize(JS::Realm& realm)

+ 4 - 2
Libraries/LibWeb/Streams/CountQueuingStrategy.cpp

@@ -7,7 +7,7 @@
 
 #include <LibWeb/Bindings/CountQueuingStrategyPrototype.h>
 #include <LibWeb/Bindings/Intrinsics.h>
-#include <LibWeb/HTML/Window.h>
+#include <LibWeb/HTML/UniversalGlobalScope.h>
 #include <LibWeb/Streams/CountQueuingStrategy.h>
 
 namespace Web::Streams {
@@ -34,7 +34,9 @@ CountQueuingStrategy::~CountQueuingStrategy() = default;
 GC::Ref<WebIDL::CallbackType> CountQueuingStrategy::size()
 {
     // 1. Return this's relevant global object's count queuing strategy size function.
-    return verify_cast<HTML::Window>(HTML::relevant_global_object(*this)).count_queuing_strategy_size_function();
+    auto* global = dynamic_cast<HTML::UniversalGlobalScopeMixin*>(&HTML::relevant_global_object(*this));
+    VERIFY(global);
+    return global->count_queuing_strategy_size_function();
 }
 
 void CountQueuingStrategy::initialize(JS::Realm& realm)

+ 2 - 0
Tests/LibWeb/Text/expected/Streams/QueuingStrategy-same-instance.txt

@@ -0,0 +1,2 @@
+CountQueuingStrategy | size1 === size2 -> true
+ByteLengthQueuingStrategy | size1 === size2 -> true

+ 10 - 0
Tests/LibWeb/Text/input/Streams/QueuingStrategy-same-instance.html

@@ -0,0 +1,10 @@
+<script src="../include.js"></script>
+<script>
+    test(() => {
+        for (const QueuingStrategy of [CountQueuingStrategy, ByteLengthQueuingStrategy]) {
+            const size1 = (new QueuingStrategy({ highWaterMark: 5 })).size;
+            const size2 = (new QueuingStrategy({ highWaterMark: 10 })).size;
+            println(`${QueuingStrategy.name} | size1 === size2 -> ${size1 === size2}`);
+        }
+    })
+</script>