瀏覽代碼

LibWeb: Define PerformanceEventTiming

https://www.w3.org/TR/event-timing/#sec-performance-event-timing

Add idl, header and stubs for PerformanceEventTiming interface.

Two missing `PerformanceEntry` types that have come up in issues
are the `first-input` and the `event` entryTypes. Those are both
this.

Also, because both of those are this same interface, the static
methods from the parent class are difficult to implement because
of instance-specific details. Might either need subclasses or to
edit the parent and also everything that inherits from it :/
Noah Bright 10 月之前
父節點
當前提交
d30ae92b82

+ 1 - 0
Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp

@@ -4190,6 +4190,7 @@ static void generate_using_namespace_definitions(SourceGenerator& generator)
     using namespace Web::DOMURL;
     using namespace Web::Encoding;
     using namespace Web::EntriesAPI;
+    using namespace Web::EventTiming;
     using namespace Web::Fetch;
     using namespace Web::FileAPI;
     using namespace Web::Geometry;

+ 1 - 0
Tests/LibWeb/Text/expected/all-window-properties.txt

@@ -243,6 +243,7 @@ PageTransitionEvent
 Path2D
 Performance
 PerformanceEntry
+PerformanceEventTiming
 PerformanceMark
 PerformanceMeasure
 PerformanceNavigation

+ 1 - 0
Userland/Libraries/LibWeb/CMakeLists.txt

@@ -219,6 +219,7 @@ set(SOURCES
     Encoding/TextDecoder.cpp
     Encoding/TextEncoder.cpp
     EntriesAPI/FileSystemEntry.cpp
+    EventTiming/PerformanceEventTiming.cpp
     Fetch/Body.cpp
     Fetch/BodyInit.cpp
     Fetch/Enums.cpp

+ 125 - 0
Userland/Libraries/LibWeb/EventTiming/PerformanceEventTiming.cpp

@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2024, Noah Bright <noah.bright.1@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/Bindings/PerformanceEventTimingPrototype.h>
+#include <LibWeb/DOM/Event.h>
+#include <LibWeb/EventTiming/PerformanceEventTiming.h>
+#include <LibWeb/PerformanceTimeline/EntryTypes.h>
+
+namespace Web::EventTiming {
+
+JS_DEFINE_ALLOCATOR(PerformanceEventTiming);
+
+// https://www.w3.org/TR/event-timing/#sec-init-event-timing
+PerformanceEventTiming::PerformanceEventTiming(JS::Realm& realm, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration,
+    DOM::Event const& event, HighResolutionTime::DOMHighResTimeStamp processing_start, unsigned long long interaction_id)
+    : PerformanceTimeline::PerformanceEntry(realm, name, start_time, duration)
+    , m_entry_type(PerformanceTimeline::EntryTypes::event)
+    , m_start_time(event.time_stamp())
+    , m_processing_start(processing_start)
+    , m_cancelable(event.cancelable())
+    , m_interaction_id(interaction_id)
+
+{
+}
+
+PerformanceEventTiming::~PerformanceEventTiming() = default;
+
+FlyString const& PerformanceEventTiming::entry_type() const
+{
+    return m_entry_type;
+}
+
+HighResolutionTime::DOMHighResTimeStamp PerformanceEventTiming::processing_end() const
+{
+    dbgln("FIXME: Implement PeformanceEventTiming processing_end()");
+    return 0;
+}
+
+HighResolutionTime::DOMHighResTimeStamp PerformanceEventTiming::processing_start() const
+{
+    dbgln("FIXME: Implement PeformanceEventTiming processing_start()");
+    return 0;
+}
+
+bool PerformanceEventTiming::cancelable() const
+{
+    return m_cancelable;
+}
+
+JS::ThrowCompletionOr<JS::GCPtr<DOM::Node>> PerformanceEventTiming::target()
+{
+    dbgln("FIXME: Implement PerformanceEventTiming::PeformanceEventTiming target()");
+    return nullptr;
+}
+
+unsigned long long PerformanceEventTiming::interaction_id()
+{
+    dbgln("FIXME: Implement PeformanceEventTiming interaction_id()");
+    return 0;
+}
+
+// https://www.w3.org/TR/event-timing/#sec-should-add-performanceeventtiming
+PerformanceTimeline::ShouldAddEntry PerformanceEventTiming::should_add_performance_event_timing() const
+{
+    dbgln("FIXME: Implement PeformanceEventTiming should_add_performance_event_timing()");
+    // 1. If entry’s entryType attribute value equals to "first-input", return true.
+    if (entry_type() == "first-input")
+        return PerformanceTimeline::ShouldAddEntry::Yes;
+
+    // 2. Assert that entry’s entryType attribute value equals "event".
+    VERIFY(entry_type() == "event");
+
+    // FIXME: 3. Let minDuration be computed as follows:
+    // FIXME: 3.1. If options is not present or if options’s durationThreshold is not present, let minDuration be 104.
+    // FIXME: 3.2. Otherwise, let minDuration be the maximum between 16 and options’s durationThreshold value.
+
+    // FIXME: 4. If entry’s duration attribute value is greater than or equal to minDuration, return true.
+
+    // 5. Otherwise, return false.
+    return PerformanceTimeline::ShouldAddEntry::No;
+}
+
+// https://w3c.github.io/timing-entrytypes-registry/#dfn-availablefromtimeline
+// FIXME: the output here depends on the type of the object instance, but this function is static
+//        the commented out if statement won't compile
+PerformanceTimeline::AvailableFromTimeline PerformanceEventTiming::available_from_timeline()
+{
+    dbgln("FIXME: Implement PeformanceEventTiming available_from_timeline()");
+    // if (entry_type() == "first-input")
+    return PerformanceTimeline::AvailableFromTimeline::Yes;
+}
+
+// https://w3c.github.io/timing-entrytypes-registry/#dfn-maxbuffersize
+// FIXME: Same issue as available_from_timeline() above
+Optional<u64> PerformanceEventTiming::max_buffer_size()
+{
+    dbgln("FIXME: Implement PeformanceEventTiming max_buffer_size()");
+    if (true) //(entry_type() == "first-input")
+        return 1;
+    // else return 150;
+}
+
+// https://w3c.github.io/timing-entrytypes-registry/#dfn-should-add-entry
+PerformanceTimeline::ShouldAddEntry PerformanceEventTiming::should_add_entry(Optional<PerformanceTimeline::PerformanceObserverInit const&>) const
+{
+    return should_add_performance_event_timing();
+}
+
+void PerformanceEventTiming::initialize(JS::Realm& realm)
+{
+    Base::initialize(realm);
+    WEB_SET_PROTOTYPE_FOR_INTERFACE(PerformanceEventTiming);
+}
+
+void PerformanceEventTiming::visit_edges(JS::Cell::Visitor& visitor)
+{
+    Base::visit_edges(visitor);
+    visitor.visit(m_event_target);
+}
+
+}

+ 66 - 0
Userland/Libraries/LibWeb/EventTiming/PerformanceEventTiming.h

@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2024, Noah Bright <noah.bright.1@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/DOM/Node.h>
+#include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
+
+namespace Web::EventTiming {
+
+// https://www.w3.org/TR/event-timing/#sec-performance-event-timing
+class PerformanceEventTiming final : public PerformanceTimeline::PerformanceEntry {
+    WEB_PLATFORM_OBJECT(PerformanceEventTiming, PerformanceTimeline::PerformanceEntry);
+    JS_DECLARE_ALLOCATOR(PerformanceEventTiming);
+
+public:
+    virtual ~PerformanceEventTiming();
+
+    HighResolutionTime::DOMHighResTimeStamp processing_start() const;
+    HighResolutionTime::DOMHighResTimeStamp processing_end() const;
+    bool cancelable() const;
+    JS::ThrowCompletionOr<JS::GCPtr<DOM::Node>> target();
+    unsigned long long interaction_id();
+
+    // from the registry:
+    // https://w3c.github.io/timing-entrytypes-registry/#dfn-availablefromtimeline
+    static PerformanceTimeline::AvailableFromTimeline available_from_timeline();
+    // https://w3c.github.io/timing-entrytypes-registry/#dfn-maxbuffersize
+    static Optional<u64> max_buffer_size();
+    // https://w3c.github.io/timing-entrytypes-registry/#dfn-should-add-entry
+    virtual PerformanceTimeline::ShouldAddEntry should_add_entry(Optional<PerformanceTimeline::PerformanceObserverInit const&> = {}) const override;
+
+    virtual FlyString const& entry_type() const override;
+
+private:
+    PerformanceEventTiming(JS::Realm& realm, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration,
+        DOM::Event const& event, HighResolutionTime::DOMHighResTimeStamp processing_start, unsigned long long interaction_id);
+
+    // m_entry_type defined here for both "event"s and "first-input"s
+    // this is the only PerformanceEntry that has two event types it could represent
+    // That complicates implementing the registry functions if they remain static
+    FlyString m_entry_type;
+    JS::GCPtr<DOM::EventTarget> m_event_target;
+    HighResolutionTime::DOMHighResTimeStamp m_start_time;
+    HighResolutionTime::DOMHighResTimeStamp m_processing_start;
+    bool m_cancelable;
+    unsigned long long m_interaction_id;
+
+    static WebIDL::ExceptionOr<JS::NonnullGCPtr<PerformanceEventTiming>> construct_impl(DOM::Event const&, HighResolutionTime::DOMHighResTimeStamp, unsigned long long);
+    virtual void initialize(JS::Realm&) override;
+
+    PerformanceTimeline::ShouldAddEntry should_add_performance_event_timing() const;
+
+    virtual void visit_edges(JS::Cell::Visitor&) override;
+
+    // FIXME: remaining algorithms described in this spec:
+    // https://www.w3.org/TR/event-timing/#sec-increasing-interaction-count
+    // https://www.w3.org/TR/event-timing/#sec-computing-interactionid
+    // https://www.w3.org/TR/event-timing/#sec-fin-event-timing
+    // https://www.w3.org/TR/event-timing/#sec-dispatch-pending
+};
+}

+ 18 - 0
Userland/Libraries/LibWeb/EventTiming/PerformanceEventTiming.idl

@@ -0,0 +1,18 @@
+#import <PerformanceTimeline/PerformanceEntry.idl>
+
+// https://www.w3.org/TR/event-timing/#sec-performance-event-timing
+[Exposed=Window]
+interface PerformanceEventTiming : PerformanceEntry {
+    readonly attribute DOMHighResTimeStamp processingStart;
+    readonly attribute DOMHighResTimeStamp processingEnd;
+    readonly attribute boolean cancelable;
+    readonly attribute Node? target;
+    readonly attribute unsigned long long interactionId;
+    [Default] object toJSON();
+};
+
+
+// Potential fixme: This spec has some more IDLs
+// https://www.w3.org/TR/event-timing/#sec-event-counts
+// https://www.w3.org/TR/event-timing/#sec-extensions
+// https://www.w3.org/TR/event-timing/#sec-modifications-perf-timeline

+ 4 - 0
Userland/Libraries/LibWeb/Forward.h

@@ -307,6 +307,10 @@ namespace Web::EntriesAPI {
 class FileSystemEntry;
 }
 
+namespace Web::EventTiming {
+class PerformanceEventTiming;
+}
+
 namespace Web::Fetch {
 class BodyMixin;
 class Headers;

+ 1 - 0
Userland/Libraries/LibWeb/idl_files.cmake

@@ -82,6 +82,7 @@ libweb_js_bindings(DOMURL/URLSearchParams ITERABLE)
 libweb_js_bindings(Encoding/TextDecoder)
 libweb_js_bindings(Encoding/TextEncoder)
 libweb_js_bindings(EntriesAPI/FileSystemEntry)
+libweb_js_bindings(EventTiming/PerformanceEventTiming)
 libweb_js_bindings(Fetch/Headers ITERABLE)
 libweb_js_bindings(Fetch/Request)
 libweb_js_bindings(Fetch/Response)