Pārlūkot izejas kodu

LibWeb: Introduce Performance Timeline and its Performance functions

Luke Wilde 2 gadi atpakaļ
vecāks
revīzija
31b507afbf

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

@@ -44,6 +44,7 @@ static bool is_platform_object(Type const& type)
         "NamedNodeMap"sv,
         "Node"sv,
         "Path2D"sv,
+        "PerformanceEntry"sv,
         "Range"sv,
         "ReadableStream"sv,
         "Request"sv,
@@ -3145,6 +3146,7 @@ using namespace Web::Geometry;
 using namespace Web::HighResolutionTime;
 using namespace Web::HTML;
 using namespace Web::IntersectionObserver;
+using namespace Web::PerformanceTimeline;
 using namespace Web::RequestIdleCallback;
 using namespace Web::ResizeObserver;
 using namespace Web::Selection;
@@ -3377,6 +3379,7 @@ using namespace Web::HighResolutionTime;
 using namespace Web::HTML;
 using namespace Web::IntersectionObserver;
 using namespace Web::NavigationTiming;
+using namespace Web::PerformanceTimeline;
 using namespace Web::RequestIdleCallback;
 using namespace Web::ResizeObserver;
 using namespace Web::Selection;
@@ -3506,6 +3509,7 @@ using namespace Web::HighResolutionTime;
 using namespace Web::HTML;
 using namespace Web::IntersectionObserver;
 using namespace Web::NavigationTiming;
+using namespace Web::PerformanceTimeline;
 using namespace Web::RequestIdleCallback;
 using namespace Web::ResizeObserver;
 using namespace Web::Selection;
@@ -3636,6 +3640,7 @@ using namespace Web::HighResolutionTime;
 using namespace Web::HTML;
 using namespace Web::IntersectionObserver;
 using namespace Web::NavigationTiming;
+using namespace Web::PerformanceTimeline;
 using namespace Web::RequestIdleCallback;
 using namespace Web::ResizeObserver;
 using namespace Web::Selection;

+ 2 - 0
Userland/Libraries/LibWeb/Bindings/MainThreadVM.cpp

@@ -32,6 +32,7 @@
 #include <LibWeb/HTML/Window.h>
 #include <LibWeb/HTML/WindowProxy.h>
 #include <LibWeb/Namespace.h>
+#include <LibWeb/PerformanceTimeline/EntryTypes.h>
 #include <LibWeb/Platform/EventLoopPlugin.h>
 #include <LibWeb/SVG/AttributeNames.h>
 #include <LibWeb/SVG/TagNames.h>
@@ -79,6 +80,7 @@ ErrorOr<void> initialize_main_thread_vm()
     TRY(HTML::EventNames::initialize_strings());
     TRY(HTML::TagNames::initialize_strings());
     TRY(Namespace::initialize_strings());
+    TRY(PerformanceTimeline::EntryTypes::initialize_strings());
     TRY(SVG::AttributeNames::initialize_strings());
     TRY(SVG::TagNames::initialize_strings());
     TRY(UIEvents::EventNames::initialize_strings());

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

@@ -371,6 +371,7 @@ set(SOURCES
     Loader/ResourceLoader.cpp
     MimeSniff/MimeType.cpp
     Namespace.cpp
+    NavigationTiming/EntryNames.cpp
     NavigationTiming/PerformanceTiming.cpp
     Page/EditEventHandler.cpp
     Page/EventHandler.cpp
@@ -400,6 +401,8 @@ set(SOURCES
     Painting/ShadowPainting.cpp
     Painting/StackingContext.cpp
     Painting/TextPaintable.cpp
+    PerformanceTimeline/EntryTypes.cpp
+    PerformanceTimeline/PerformanceEntry.cpp
     Platform/EventLoopPlugin.cpp
     Platform/EventLoopPluginSerenity.cpp
     Platform/FontPlugin.cpp

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

@@ -387,6 +387,10 @@ struct BorderRadiiData;
 struct LinearGradientData;
 }
 
+namespace Web::PerformanceTimeline {
+class PerformanceEntry;
+}
+
 namespace Web::Platform {
 class Timer;
 }

+ 79 - 0
Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp

@@ -1,11 +1,13 @@
 /*
  * Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
  * Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
 #include <AK/Base64.h>
+#include <AK/QuickSort.h>
 #include <AK/String.h>
 #include <AK/Utf8View.h>
 #include <AK/Vector.h>
@@ -264,4 +266,81 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
     return id;
 }
 
+// https://www.w3.org/TR/performance-timeline/#dfn-filter-buffer-by-name-and-type
+static ErrorOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> filter_buffer_by_name_and_type(Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>> const& buffer, Optional<String> name, Optional<String> type)
+{
+    // 1. Let result be an initially empty list.
+    Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>> result;
+
+    // 2. For each PerformanceEntry entry in buffer, run the following steps:
+    for (auto const& entry : buffer) {
+        // 1. If type is not null and if type is not identical to entry's entryType attribute, continue to next entry.
+        if (type.has_value() && type.value() != entry->entry_type())
+            continue;
+
+        // 2. If name is not null and if name is not identical to entry's name attribute, continue to next entry.
+        if (name.has_value() && name.value() != entry->name())
+            continue;
+
+        // 3. append entry to result.
+        TRY(result.try_append(entry));
+    }
+
+    // 3. Sort results's entries in chronological order with respect to startTime
+    quick_sort(result, [](auto const& left_entry, auto const& right_entry) {
+        return left_entry->start_time() < right_entry->start_time();
+    });
+
+    // 4. Return result.
+    return result;
+}
+
+// https://www.w3.org/TR/performance-timeline/#dfn-filter-buffer-map-by-name-and-type
+ErrorOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> WindowOrWorkerGlobalScopeMixin::filter_buffer_map_by_name_and_type(Optional<String> name, Optional<String> type) const
+{
+    // 1. Let result be an initially empty list.
+    Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>> result;
+
+    // 2. Let map be the performance entry buffer map associated with the relevant global object of this.
+    auto const& map = m_performance_entry_buffer_map;
+
+    // 3. Let tuple list be an empty list.
+    Vector<PerformanceTimeline::PerformanceEntryTuple const&> tuple_list;
+
+    // 4. If type is not null, append the result of getting the value of entry on map given type as key to tuple list.
+    //    Otherwise, assign the result of get the values on map to tuple list.
+    if (type.has_value()) {
+        auto maybe_tuple = map.get(type.value());
+        if (maybe_tuple.has_value())
+            TRY(tuple_list.try_append(maybe_tuple.release_value()));
+    } else {
+        for (auto const& it : map)
+            TRY(tuple_list.try_append(it.value));
+    }
+
+    // 5. For each tuple in tuple list, run the following steps:
+    for (auto const& tuple : tuple_list) {
+        // 1. Let buffer be tuple's performance entry buffer.
+        auto const& buffer = tuple.performance_entry_buffer;
+
+        // 2. If tuple's availableFromTimeline is false, continue to the next tuple.
+        if (tuple.available_from_timeline == PerformanceTimeline::AvailableFromTimeline::No)
+            continue;
+
+        // 3. Let entries be the result of running filter buffer by name and type with buffer, name and type as inputs.
+        auto entries = TRY(filter_buffer_by_name_and_type(buffer, name, type));
+
+        // 4. For each entry in entries, append entry to result.
+        TRY(result.try_extend(entries));
+    }
+
+    // 6. Sort results's entries in chronological order with respect to startTime
+    quick_sort(result, [](auto const& left_entry, auto const& right_entry) {
+        return left_entry->start_time() < right_entry->start_time();
+    });
+
+    // 7. Return result.
+    return result;
+}
+
 }

+ 16 - 0
Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h

@@ -1,11 +1,13 @@
 /*
  * Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
 
 #pragma once
 
+#include <AK/FlyString.h>
 #include <AK/Forward.h>
 #include <AK/HashMap.h>
 #include <AK/IDAllocator.h>
@@ -14,6 +16,8 @@
 #include <LibWeb/Fetch/Request.h>
 #include <LibWeb/Forward.h>
 #include <LibWeb/HTML/MessagePort.h>
+#include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
+#include <LibWeb/PerformanceTimeline/PerformanceEntryTuple.h>
 
 namespace Web::HTML {
 
@@ -43,6 +47,8 @@ public:
     void clear_timeout(i32);
     void clear_interval(i32);
 
+    ErrorOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> filter_buffer_map_by_name_and_type(Optional<String> name, Optional<String> type) const;
+
 protected:
     void visit_edges(JS::Cell::Visitor&);
 
@@ -55,6 +61,16 @@ private:
 
     IDAllocator m_timer_id_allocator;
     HashMap<int, JS::NonnullGCPtr<Timer>> m_timers;
+
+    // https://www.w3.org/TR/performance-timeline/#performance-timeline
+    // Each global object has:
+    // FIXME: - a performance observer task queued flag
+    // FIXME: - a list of registered performance observer objects that is initially empty
+
+    // https://www.w3.org/TR/performance-timeline/#dfn-performance-entry-buffer-map
+    // a performance entry buffer map map, keyed on a DOMString, representing the entry type to which the buffer belongs. The map's value is the following tuple:
+    // NOTE: See the PerformanceEntryTuple struct above for the map's value tuple.
+    OrderedHashMap<FlyString, PerformanceTimeline::PerformanceEntryTuple> m_performance_entry_buffer_map;
 };
 
 }

+ 41 - 0
Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -49,4 +50,44 @@ double Performance::time_origin() const
     return static_cast<double>(m_timer.origin_time().to_milliseconds());
 }
 
+// https://www.w3.org/TR/performance-timeline/#getentries-method
+WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> Performance::get_entries() const
+{
+    auto& realm = this->realm();
+    auto& vm = this->vm();
+    auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object());
+    VERIFY(window_or_worker);
+
+    // Returns a PerformanceEntryList object returned by the filter buffer map by name and type algorithm with name and
+    // type set to null.
+    return TRY_OR_THROW_OOM(vm, window_or_worker->filter_buffer_map_by_name_and_type(/* name= */ Optional<String> {}, /* type= */ Optional<String> {}));
+}
+
+// https://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbytype
+WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> Performance::get_entries_by_type(String const& type) const
+{
+    auto& realm = this->realm();
+    auto& vm = this->vm();
+    auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object());
+    VERIFY(window_or_worker);
+
+    // Returns a PerformanceEntryList object returned by filter buffer map by name and type algorithm with name set to null,
+    // and type set to the method's input type parameter.
+    return TRY_OR_THROW_OOM(vm, window_or_worker->filter_buffer_map_by_name_and_type(/* name= */ Optional<String> {}, type));
+}
+
+// https://www.w3.org/TR/performance-timeline/#dom-performance-getentriesbyname
+WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> Performance::get_entries_by_name(String const& name, Optional<String> type) const
+{
+    auto& realm = this->realm();
+    auto& vm = this->vm();
+    auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object());
+    VERIFY(window_or_worker);
+
+    // Returns a PerformanceEntryList object returned by filter buffer map by name and type algorithm with name set to the
+    // method input name parameter, and type set to null if optional entryType is omitted, or set to the method's input type
+    // parameter otherwise.
+    return TRY_OR_THROW_OOM(vm, window_or_worker->filter_buffer_map_by_name_and_type(name, type));
+}
+
 }

+ 5 - 0
Userland/Libraries/LibWeb/HighResolutionTime/Performance.h

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
  *
  * SPDX-License-Identifier: BSD-2-Clause
  */
@@ -22,6 +23,10 @@ public:
 
     JS::GCPtr<NavigationTiming::PerformanceTiming> timing();
 
+    WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> get_entries() const;
+    WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> get_entries_by_type(String const& type) const;
+    WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> get_entries_by_name(String const& name, Optional<String> type) const;
+
 private:
     explicit Performance(HTML::Window&);
 

+ 10 - 1
Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl

@@ -1,12 +1,21 @@
 #import <DOM/EventTarget.idl>
 #import <HighResolutionTime/DOMHighResTimeStamp.idl>
 #import <NavigationTiming/PerformanceTiming.idl>
+#import <PerformanceTimeline/PerformanceEntry.idl>
+
+// https://www.w3.org/TR/performance-timeline/#dom-performanceentrylist
+typedef sequence<PerformanceEntry> PerformanceEntryList;
 
 // https://w3c.github.io/hr-time/#sec-performance
-[Exposed=(Window, Worker)]
+[Exposed=(Window, Worker), UseNewAKString]
 interface Performance : EventTarget {
     DOMHighResTimeStamp now();
     readonly attribute DOMHighResTimeStamp timeOrigin;
 
     readonly attribute PerformanceTiming timing;
+    // https://www.w3.org/TR/performance-timeline/#extensions-to-the-performance-interface
+    // "Performance Timeline" extensions to the Performance interface
+    PerformanceEntryList getEntries();
+    PerformanceEntryList getEntriesByType(DOMString type);
+    PerformanceEntryList getEntriesByName(DOMString name, optional DOMString type);
 };

+ 34 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.cpp

@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/PerformanceTimeline/EntryTypes.h>
+
+namespace Web::PerformanceTimeline::EntryTypes {
+
+#define __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(name) FlyString name;
+ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPES
+#undef __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE
+
+ErrorOr<void> initialize_strings()
+{
+    static bool s_initialized = false;
+    VERIFY(!s_initialized);
+
+#define __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(name) \
+    name = TRY(#name##_fly_string);
+    ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPES
+#undef __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE
+
+    // NOTE: Special cases for attributes with dashes in them.
+    first_input = TRY("first-input"_fly_string);
+    largest_contentful_paint = TRY("largest-contentful-paint"_fly_string);
+    layout_shift = TRY("layout-shift"_fly_string);
+
+    s_initialized = true;
+    return {};
+}
+
+}

+ 33 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.h

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/FlyString.h>
+
+namespace Web::PerformanceTimeline::EntryTypes {
+
+// https://w3c.github.io/timing-entrytypes-registry/#registry
+#define ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPES                        \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(element)                  \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(event)                    \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(first_input)              \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(largest_contentful_paint) \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(layout_shift)             \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(longtask)                 \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(mark)                     \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(measure)                  \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(navigation)               \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(resource)                 \
+    __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(paint)
+
+#define __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE(name) extern FlyString name;
+ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPES
+#undef __ENUMERATE_PERFORMANCE_TIMELINE_ENTRY_TYPE
+
+ErrorOr<void> initialize_strings();
+
+}

+ 31 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/PerformanceEntry.cpp

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include <LibWeb/Bindings/Intrinsics.h>
+#include <LibWeb/Bindings/PerformanceEntryPrototype.h>
+#include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
+
+namespace Web::PerformanceTimeline {
+
+PerformanceEntry::PerformanceEntry(JS::Realm& realm, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration)
+    : Bindings::PlatformObject(realm)
+    , m_name(name)
+    , m_start_time(start_time)
+    , m_duration(duration)
+{
+}
+
+PerformanceEntry::~PerformanceEntry() = default;
+
+JS::ThrowCompletionOr<void> PerformanceEntry::initialize(JS::Realm& realm)
+{
+    MUST_OR_THROW_OOM(Base::initialize(realm));
+    set_prototype(&Bindings::ensure_web_prototype<Bindings::PerformanceEntryPrototype>(realm, "PerformanceEntry"));
+
+    return {};
+}
+
+}

+ 56 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/PerformanceEntry.h

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/Bindings/PlatformObject.h>
+#include <LibWeb/HighResolutionTime/DOMHighResTimeStamp.h>
+
+namespace Web::PerformanceTimeline {
+
+enum class AvailableFromTimeline {
+    No,
+    Yes,
+};
+
+enum class ShouldAddEntry {
+    No,
+    Yes,
+};
+
+// https://www.w3.org/TR/performance-timeline/#dom-performanceentry
+class PerformanceEntry : public Bindings::PlatformObject {
+    WEB_PLATFORM_OBJECT(PerformanceEntry, Bindings::PlatformObject);
+
+public:
+    virtual ~PerformanceEntry();
+
+    // https://www.w3.org/TR/performance-timeline/#dom-performanceentry-entrytype
+    virtual FlyString const& entry_type() const = 0;
+
+    String const& name() const { return m_name; }
+    HighResolutionTime::DOMHighResTimeStamp start_time() const { return m_start_time; }
+    HighResolutionTime::DOMHighResTimeStamp duration() const { return m_duration; }
+
+    // https://w3c.github.io/timing-entrytypes-registry/#dfn-should-add-entry
+    virtual PerformanceTimeline::ShouldAddEntry should_add_entry() const = 0;
+
+protected:
+    PerformanceEntry(JS::Realm&, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration);
+    virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override;
+
+private:
+    // https://www.w3.org/TR/performance-timeline/#dom-performanceentry-name
+    String m_name;
+
+    // https://www.w3.org/TR/performance-timeline/#dom-performanceentry-starttime
+    HighResolutionTime::DOMHighResTimeStamp m_start_time { 0.0 };
+
+    // https://www.w3.org/TR/performance-timeline/#dom-performanceentry-duration
+    HighResolutionTime::DOMHighResTimeStamp m_duration { 0.0 };
+};
+
+}

+ 11 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/PerformanceEntry.idl

@@ -0,0 +1,11 @@
+#import <HighResolutionTime/DOMHighResTimeStamp.idl>
+
+// https://www.w3.org/TR/performance-timeline/#dom-performanceentry
+[Exposed=(Window,Worker), UseNewAKString]
+interface PerformanceEntry {
+    readonly attribute DOMString name;
+    readonly attribute DOMString entryType;
+    readonly attribute DOMHighResTimeStamp startTime;
+    readonly attribute DOMHighResTimeStamp duration;
+    [Default] object toJSON();
+};

+ 50 - 0
Userland/Libraries/LibWeb/PerformanceTimeline/PerformanceEntryTuple.h

@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
+
+namespace Web::PerformanceTimeline {
+
+// https://www.w3.org/TR/performance-timeline/#dfn-performance-entry-buffer-map
+struct PerformanceEntryTuple {
+    // https://www.w3.org/TR/performance-timeline/#dfn-performance-entry-buffer
+    // A performance entry buffer to store PerformanceEntry objects, that is initially empty.
+    Vector<JS::Handle<PerformanceEntry>> performance_entry_buffer;
+
+    // https://www.w3.org/TR/performance-timeline/#dfn-maxbuffersize
+    // An integer maxBufferSize, initialized to the registry value for this entry type.
+    // NOTE: The empty state represents Infinite size.
+    Optional<u64> max_buffer_size;
+
+    // https://www.w3.org/TR/performance-timeline/#dfn-availablefromtimeline
+    // A boolean availableFromTimeline, initialized to the registry value for this entry type.
+    AvailableFromTimeline available_from_timeline { AvailableFromTimeline::No };
+
+    // https://www.w3.org/TR/performance-timeline/#dfn-dropped-entries-count
+    // An integer dropped entries count that is initially 0.
+    u64 dropped_entries_count { 0 };
+
+    // https://www.w3.org/TR/performance-timeline/#dfn-determine-if-a-performance-entry-buffer-is-full
+    bool is_full()
+    {
+        // 1. Let num current entries be the size of tuple's performance entry buffer.
+        auto num_current_entries = performance_entry_buffer.size();
+
+        // 2. If num current entries is less than tuples's maxBufferSize, return false.
+        if (!max_buffer_size.has_value() || num_current_entries < max_buffer_size.value())
+            return false;
+
+        // 3. Increase tuple's dropped entries count by 1.
+        ++dropped_entries_count;
+
+        // 4. Return true.
+        return true;
+    }
+};
+
+}

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

@@ -172,6 +172,7 @@ libweb_js_bindings(HTML/WorkerNavigator)
 libweb_js_bindings(HighResolutionTime/Performance)
 libweb_js_bindings(IntersectionObserver/IntersectionObserver)
 libweb_js_bindings(NavigationTiming/PerformanceTiming)
+libweb_js_bindings(PerformanceTimeline/PerformanceEntry)
 libweb_js_bindings(RequestIdleCallback/IdleDeadline)
 libweb_js_bindings(ResizeObserver/ResizeObserver)
 libweb_js_bindings(Streams/ReadableStream)