mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 06:47:35 +00:00
LibWeb: Introduce Performance Timeline and its Performance functions
This commit is contained in:
parent
4c3f1481ea
commit
31b507afbf
16 changed files with 381 additions and 1 deletions
|
@ -44,6 +44,7 @@ static bool is_platform_object(Type const& type)
|
||||||
"NamedNodeMap"sv,
|
"NamedNodeMap"sv,
|
||||||
"Node"sv,
|
"Node"sv,
|
||||||
"Path2D"sv,
|
"Path2D"sv,
|
||||||
|
"PerformanceEntry"sv,
|
||||||
"Range"sv,
|
"Range"sv,
|
||||||
"ReadableStream"sv,
|
"ReadableStream"sv,
|
||||||
"Request"sv,
|
"Request"sv,
|
||||||
|
@ -3145,6 +3146,7 @@ using namespace Web::Geometry;
|
||||||
using namespace Web::HighResolutionTime;
|
using namespace Web::HighResolutionTime;
|
||||||
using namespace Web::HTML;
|
using namespace Web::HTML;
|
||||||
using namespace Web::IntersectionObserver;
|
using namespace Web::IntersectionObserver;
|
||||||
|
using namespace Web::PerformanceTimeline;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
@ -3377,6 +3379,7 @@ using namespace Web::HighResolutionTime;
|
||||||
using namespace Web::HTML;
|
using namespace Web::HTML;
|
||||||
using namespace Web::IntersectionObserver;
|
using namespace Web::IntersectionObserver;
|
||||||
using namespace Web::NavigationTiming;
|
using namespace Web::NavigationTiming;
|
||||||
|
using namespace Web::PerformanceTimeline;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
@ -3506,6 +3509,7 @@ using namespace Web::HighResolutionTime;
|
||||||
using namespace Web::HTML;
|
using namespace Web::HTML;
|
||||||
using namespace Web::IntersectionObserver;
|
using namespace Web::IntersectionObserver;
|
||||||
using namespace Web::NavigationTiming;
|
using namespace Web::NavigationTiming;
|
||||||
|
using namespace Web::PerformanceTimeline;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
@ -3636,6 +3640,7 @@ using namespace Web::HighResolutionTime;
|
||||||
using namespace Web::HTML;
|
using namespace Web::HTML;
|
||||||
using namespace Web::IntersectionObserver;
|
using namespace Web::IntersectionObserver;
|
||||||
using namespace Web::NavigationTiming;
|
using namespace Web::NavigationTiming;
|
||||||
|
using namespace Web::PerformanceTimeline;
|
||||||
using namespace Web::RequestIdleCallback;
|
using namespace Web::RequestIdleCallback;
|
||||||
using namespace Web::ResizeObserver;
|
using namespace Web::ResizeObserver;
|
||||||
using namespace Web::Selection;
|
using namespace Web::Selection;
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <LibWeb/HTML/Window.h>
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/HTML/WindowProxy.h>
|
#include <LibWeb/HTML/WindowProxy.h>
|
||||||
#include <LibWeb/Namespace.h>
|
#include <LibWeb/Namespace.h>
|
||||||
|
#include <LibWeb/PerformanceTimeline/EntryTypes.h>
|
||||||
#include <LibWeb/Platform/EventLoopPlugin.h>
|
#include <LibWeb/Platform/EventLoopPlugin.h>
|
||||||
#include <LibWeb/SVG/AttributeNames.h>
|
#include <LibWeb/SVG/AttributeNames.h>
|
||||||
#include <LibWeb/SVG/TagNames.h>
|
#include <LibWeb/SVG/TagNames.h>
|
||||||
|
@ -79,6 +80,7 @@ ErrorOr<void> initialize_main_thread_vm()
|
||||||
TRY(HTML::EventNames::initialize_strings());
|
TRY(HTML::EventNames::initialize_strings());
|
||||||
TRY(HTML::TagNames::initialize_strings());
|
TRY(HTML::TagNames::initialize_strings());
|
||||||
TRY(Namespace::initialize_strings());
|
TRY(Namespace::initialize_strings());
|
||||||
|
TRY(PerformanceTimeline::EntryTypes::initialize_strings());
|
||||||
TRY(SVG::AttributeNames::initialize_strings());
|
TRY(SVG::AttributeNames::initialize_strings());
|
||||||
TRY(SVG::TagNames::initialize_strings());
|
TRY(SVG::TagNames::initialize_strings());
|
||||||
TRY(UIEvents::EventNames::initialize_strings());
|
TRY(UIEvents::EventNames::initialize_strings());
|
||||||
|
|
|
@ -371,6 +371,7 @@ set(SOURCES
|
||||||
Loader/ResourceLoader.cpp
|
Loader/ResourceLoader.cpp
|
||||||
MimeSniff/MimeType.cpp
|
MimeSniff/MimeType.cpp
|
||||||
Namespace.cpp
|
Namespace.cpp
|
||||||
|
NavigationTiming/EntryNames.cpp
|
||||||
NavigationTiming/PerformanceTiming.cpp
|
NavigationTiming/PerformanceTiming.cpp
|
||||||
Page/EditEventHandler.cpp
|
Page/EditEventHandler.cpp
|
||||||
Page/EventHandler.cpp
|
Page/EventHandler.cpp
|
||||||
|
@ -400,6 +401,8 @@ set(SOURCES
|
||||||
Painting/ShadowPainting.cpp
|
Painting/ShadowPainting.cpp
|
||||||
Painting/StackingContext.cpp
|
Painting/StackingContext.cpp
|
||||||
Painting/TextPaintable.cpp
|
Painting/TextPaintable.cpp
|
||||||
|
PerformanceTimeline/EntryTypes.cpp
|
||||||
|
PerformanceTimeline/PerformanceEntry.cpp
|
||||||
Platform/EventLoopPlugin.cpp
|
Platform/EventLoopPlugin.cpp
|
||||||
Platform/EventLoopPluginSerenity.cpp
|
Platform/EventLoopPluginSerenity.cpp
|
||||||
Platform/FontPlugin.cpp
|
Platform/FontPlugin.cpp
|
||||||
|
|
|
@ -387,6 +387,10 @@ struct BorderRadiiData;
|
||||||
struct LinearGradientData;
|
struct LinearGradientData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Web::PerformanceTimeline {
|
||||||
|
class PerformanceEntry;
|
||||||
|
}
|
||||||
|
|
||||||
namespace Web::Platform {
|
namespace Web::Platform {
|
||||||
class Timer;
|
class Timer;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
* Copyright (c) 2022, Andrew Kaster <akaster@serenityos.org>
|
||||||
* Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
|
||||||
|
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/Base64.h>
|
#include <AK/Base64.h>
|
||||||
|
#include <AK/QuickSort.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <AK/Utf8View.h>
|
#include <AK/Utf8View.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
|
@ -264,4 +266,81 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler
|
||||||
return id;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
|
* Copyright (c) 2023, Linus Groh <linusg@serenityos.org>
|
||||||
|
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/FlyString.h>
|
||||||
#include <AK/Forward.h>
|
#include <AK/Forward.h>
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/IDAllocator.h>
|
#include <AK/IDAllocator.h>
|
||||||
|
@ -14,6 +16,8 @@
|
||||||
#include <LibWeb/Fetch/Request.h>
|
#include <LibWeb/Fetch/Request.h>
|
||||||
#include <LibWeb/Forward.h>
|
#include <LibWeb/Forward.h>
|
||||||
#include <LibWeb/HTML/MessagePort.h>
|
#include <LibWeb/HTML/MessagePort.h>
|
||||||
|
#include <LibWeb/PerformanceTimeline/PerformanceEntry.h>
|
||||||
|
#include <LibWeb/PerformanceTimeline/PerformanceEntryTuple.h>
|
||||||
|
|
||||||
namespace Web::HTML {
|
namespace Web::HTML {
|
||||||
|
|
||||||
|
@ -43,6 +47,8 @@ public:
|
||||||
void clear_timeout(i32);
|
void clear_timeout(i32);
|
||||||
void clear_interval(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:
|
protected:
|
||||||
void visit_edges(JS::Cell::Visitor&);
|
void visit_edges(JS::Cell::Visitor&);
|
||||||
|
|
||||||
|
@ -55,6 +61,16 @@ private:
|
||||||
|
|
||||||
IDAllocator m_timer_id_allocator;
|
IDAllocator m_timer_id_allocator;
|
||||||
HashMap<int, JS::NonnullGCPtr<Timer>> m_timers;
|
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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* 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());
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
* Copyright (c) 2020, Andreas Kling <kling@serenityos.org>
|
||||||
|
* Copyright (c) 2023, Luke Wilde <lukew@serenityos.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -22,6 +23,10 @@ public:
|
||||||
|
|
||||||
JS::GCPtr<NavigationTiming::PerformanceTiming> timing();
|
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:
|
private:
|
||||||
explicit Performance(HTML::Window&);
|
explicit Performance(HTML::Window&);
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,21 @@
|
||||||
#import <DOM/EventTarget.idl>
|
#import <DOM/EventTarget.idl>
|
||||||
#import <HighResolutionTime/DOMHighResTimeStamp.idl>
|
#import <HighResolutionTime/DOMHighResTimeStamp.idl>
|
||||||
#import <NavigationTiming/PerformanceTiming.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
|
// https://w3c.github.io/hr-time/#sec-performance
|
||||||
[Exposed=(Window, Worker)]
|
[Exposed=(Window, Worker), UseNewAKString]
|
||||||
interface Performance : EventTarget {
|
interface Performance : EventTarget {
|
||||||
DOMHighResTimeStamp now();
|
DOMHighResTimeStamp now();
|
||||||
readonly attribute DOMHighResTimeStamp timeOrigin;
|
readonly attribute DOMHighResTimeStamp timeOrigin;
|
||||||
|
|
||||||
readonly attribute PerformanceTiming timing;
|
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
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.cpp
Normal file
34
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.cpp
Normal file
|
@ -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
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.h
Normal file
33
Userland/Libraries/LibWeb/PerformanceTimeline/EntryTypes.h
Normal file
|
@ -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();
|
||||||
|
|
||||||
|
}
|
|
@ -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 {};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 };
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
};
|
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
|
@ -172,6 +172,7 @@ libweb_js_bindings(HTML/WorkerNavigator)
|
||||||
libweb_js_bindings(HighResolutionTime/Performance)
|
libweb_js_bindings(HighResolutionTime/Performance)
|
||||||
libweb_js_bindings(IntersectionObserver/IntersectionObserver)
|
libweb_js_bindings(IntersectionObserver/IntersectionObserver)
|
||||||
libweb_js_bindings(NavigationTiming/PerformanceTiming)
|
libweb_js_bindings(NavigationTiming/PerformanceTiming)
|
||||||
|
libweb_js_bindings(PerformanceTimeline/PerformanceEntry)
|
||||||
libweb_js_bindings(RequestIdleCallback/IdleDeadline)
|
libweb_js_bindings(RequestIdleCallback/IdleDeadline)
|
||||||
libweb_js_bindings(ResizeObserver/ResizeObserver)
|
libweb_js_bindings(ResizeObserver/ResizeObserver)
|
||||||
libweb_js_bindings(Streams/ReadableStream)
|
libweb_js_bindings(Streams/ReadableStream)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue