diff options
author | Luke Wilde <lukew@serenityos.org> | 2023-03-23 17:07:52 +0000 |
---|---|---|
committer | Linus Groh <mail@linusgroh.de> | 2023-03-23 21:00:43 +0000 |
commit | cbe090170629b7e207153ad98c0cdec4762e77b0 (patch) | |
tree | 74debe986e8cbbce0c1f1a5e362f9a664231b82d | |
parent | 89ebef9730797a25a9d6263deda4b17e18fb1905 (diff) | |
download | serenity-cbe090170629b7e207153ad98c0cdec4762e77b0.zip |
LibWeb: Implement performance.mark and performance.clearMarks
13 files changed, 341 insertions, 0 deletions
diff --git a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp index 1a63e2cf94..664bda2c73 100644 --- a/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp +++ b/Meta/Lagom/Tools/CodeGenerators/LibWeb/BindingsGenerator/IDLGenerators.cpp @@ -45,6 +45,7 @@ static bool is_platform_object(Type const& type) "Node"sv, "Path2D"sv, "PerformanceEntry"sv, + "PerformanceMark"sv, "Range"sv, "ReadableStream"sv, "Request"sv, @@ -3152,6 +3153,7 @@ using namespace Web::ResizeObserver; using namespace Web::Selection; using namespace Web::Streams; using namespace Web::UIEvents; +using namespace Web::UserTiming; using namespace Web::URL; using namespace Web::XHR; using namespace Web::WebAssembly; @@ -3387,6 +3389,7 @@ using namespace Web::Streams; using namespace Web::SVG; using namespace Web::UIEvents; using namespace Web::URL; +using namespace Web::UserTiming; using namespace Web::WebSockets; using namespace Web::XHR; using namespace Web::WebAssembly; @@ -3516,6 +3519,7 @@ using namespace Web::Selection; using namespace Web::XHR; using namespace Web::UIEvents; using namespace Web::URL; +using namespace Web::UserTiming; using namespace Web::WebGL; using namespace Web::WebIDL; @@ -3648,6 +3652,7 @@ using namespace Web::Streams; using namespace Web::SVG; using namespace Web::UIEvents; using namespace Web::URL; +using namespace Web::UserTiming; using namespace Web::WebSockets; using namespace Web::XHR; using namespace Web::WebGL; diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 50315e8ad7..e38b852908 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -448,6 +448,7 @@ set(SOURCES URL/URL.cpp URL/URLSearchParams.cpp URL/URLSearchParamsIterator.cpp + UserTiming/PerformanceMark.cpp WebAssembly/Instance.cpp WebAssembly/Memory.cpp WebAssembly/Module.cpp diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 60d29430dd..b46ef74990 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -519,6 +519,10 @@ class URLSearchParams; class URLSearchParamsIterator; } +namespace Web::UserTiming { +class PerformanceMark; +} + namespace Web::Bindings { class Intrinsics; class OptionConstructor; diff --git a/Userland/Libraries/LibWeb/HTML/Window.cpp b/Userland/Libraries/LibWeb/HTML/Window.cpp index abdea88a59..37a7e5c4c6 100644 --- a/Userland/Libraries/LibWeb/HTML/Window.cpp +++ b/Userland/Libraries/LibWeb/HTML/Window.cpp @@ -747,6 +747,7 @@ WebIDL::ExceptionOr<void> Window::initialize_web_interfaces(Badge<WindowEnvironm Object::set_prototype(&Bindings::ensure_web_prototype<Bindings::WindowPrototype>(realm, "Window")); MUST_OR_THROW_OOM(Bindings::WindowGlobalMixin::initialize(realm, *this)); + MUST_OR_THROW_OOM(WindowOrWorkerGlobalScopeMixin::initialize(realm)); return {}; } diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp index c5b85db129..5d9cc077d8 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.cpp @@ -24,6 +24,8 @@ #include <LibWeb/HTML/Window.h> #include <LibWeb/HTML/WindowOrWorkerGlobalScope.h> #include <LibWeb/Infra/Base64.h> +#include <LibWeb/PerformanceTimeline/EntryTypes.h> +#include <LibWeb/UserTiming/PerformanceMark.h> #include <LibWeb/WebIDL/AbstractOperations.h> #include <LibWeb/WebIDL/DOMException.h> #include <LibWeb/WebIDL/ExceptionOr.h> @@ -32,6 +34,27 @@ namespace Web::HTML { WindowOrWorkerGlobalScopeMixin::~WindowOrWorkerGlobalScopeMixin() = default; +// Please keep these in alphabetical order based on the entry type :^) +#define ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES \ + __ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES(PerformanceTimeline::EntryTypes::mark, UserTiming::PerformanceMark) + +JS::ThrowCompletionOr<void> WindowOrWorkerGlobalScopeMixin::initialize(JS::Realm& realm) +{ + auto& vm = realm.vm(); + +#define __ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES(entry_type, cpp_class) \ + TRY_OR_THROW_OOM(vm, m_performance_entry_buffer_map.try_set(entry_type, PerformanceTimeline::PerformanceEntryTuple { \ + .performance_entry_buffer = {}, \ + .max_buffer_size = cpp_class::max_buffer_size(), \ + .available_from_timeline = cpp_class::available_from_timeline(), \ + .dropped_entries_count = 0, \ + })); + ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES +#undef __ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES + + return {}; +} + void WindowOrWorkerGlobalScopeMixin::visit_edges(JS::Cell::Visitor& visitor) { for (auto& it : m_timers) @@ -266,6 +289,72 @@ i32 WindowOrWorkerGlobalScopeMixin::run_timer_initialization_steps(TimerHandler return id; } +// 1. https://www.w3.org/TR/performance-timeline/#dfn-relevant-performance-entry-tuple +PerformanceTimeline::PerformanceEntryTuple& WindowOrWorkerGlobalScopeMixin::relevant_performance_entry_tuple(FlyString const& entry_type) +{ + // 1. Let map be the performance entry buffer map associated with globalObject. + // 2. Return the result of getting the value of an entry from map, given entryType as the key. + auto tuple = m_performance_entry_buffer_map.get(entry_type); + + // This shouldn't be called with entry types that aren't in `ENUMERATE_SUPPORTED_PERFORMANCE_ENTRY_TYPES`. + VERIFY(tuple.has_value()); + return tuple.value(); +} + +// https://www.w3.org/TR/performance-timeline/#dfn-queue-a-performanceentry +WebIDL::ExceptionOr<void> WindowOrWorkerGlobalScopeMixin::queue_performance_entry(JS::NonnullGCPtr<PerformanceTimeline::PerformanceEntry> new_entry) +{ + auto& vm = new_entry->vm(); + + // FIXME: 1. Let interested observers be an initially empty set of PerformanceObserver objects. + + // 2. Let entryType be newEntry’s entryType value. + auto const& entry_type = new_entry->entry_type(); + + // 3. Let relevantGlobal be newEntry's relevant global object. + // NOTE: Already is `this`. + + // FIXME: 4. For each registered performance observer regObs in relevantGlobal's list of registered performance observer + // objects: + // 1. If regObs's options list contains a PerformanceObserverInit options whose entryTypes member includes entryType + // or whose type member equals to entryType: + // 1. If should add entry with newEntry and options returns true, append regObs's observer to interested observers. + + // FIXME: 5. For each observer in interested observers: + // 1. Append newEntry to observer's observer buffer. + + // 6. Let tuple be the relevant performance entry tuple of entryType and relevantGlobal. + auto& tuple = relevant_performance_entry_tuple(entry_type); + + // 7. Let isBufferFull be the return value of the determine if a performance entry buffer is full algorithm with tuple + // as input. + bool is_buffer_full = tuple.is_full(); + + // 8. Let shouldAdd be the result of should add entry with newEntry as input. + auto should_add = new_entry->should_add_entry(); + + // 9. If isBufferFull is false and shouldAdd is true, append newEntry to tuple's performance entry buffer. + if (!is_buffer_full && should_add == PerformanceTimeline::ShouldAddEntry::Yes) + TRY_OR_THROW_OOM(vm, tuple.performance_entry_buffer.try_append(JS::make_handle(new_entry))); + + // FIXME: 10. Queue the PerformanceObserver task with relevantGlobal as input. + return {}; +} + +void WindowOrWorkerGlobalScopeMixin::clear_performance_entry_buffer(Badge<HighResolutionTime::Performance>, FlyString const& entry_type) +{ + auto& tuple = relevant_performance_entry_tuple(entry_type); + tuple.performance_entry_buffer.clear(); +} + +void WindowOrWorkerGlobalScopeMixin::remove_entries_from_performance_entry_buffer(Badge<HighResolutionTime::Performance>, FlyString const& entry_type, String entry_name) +{ + auto& tuple = relevant_performance_entry_tuple(entry_type); + tuple.performance_entry_buffer.remove_all_matching([&entry_name](JS::Handle<PerformanceTimeline::PerformanceEntry> const& entry) { + return entry->name() == entry_name; + }); +} + // 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) { diff --git a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h index c6c9133866..49328a5eb3 100644 --- a/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h +++ b/Userland/Libraries/LibWeb/HTML/WindowOrWorkerGlobalScope.h @@ -47,9 +47,15 @@ public: void clear_timeout(i32); void clear_interval(i32); + PerformanceTimeline::PerformanceEntryTuple& relevant_performance_entry_tuple(FlyString const& entry_type); + WebIDL::ExceptionOr<void> queue_performance_entry(JS::NonnullGCPtr<PerformanceTimeline::PerformanceEntry> new_entry); + void clear_performance_entry_buffer(Badge<HighResolutionTime::Performance>, FlyString const& entry_type); + void remove_entries_from_performance_entry_buffer(Badge<HighResolutionTime::Performance>, FlyString const& entry_type, String entry_name); + ErrorOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> filter_buffer_map_by_name_and_type(Optional<String> name, Optional<String> type) const; protected: + JS::ThrowCompletionOr<void> initialize(JS::Realm&); void visit_edges(JS::Cell::Visitor&); private: diff --git a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp index d3fc604d06..89a2178930 100644 --- a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp +++ b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.cpp @@ -11,6 +11,7 @@ #include <LibWeb/HTML/Window.h> #include <LibWeb/HighResolutionTime/Performance.h> #include <LibWeb/NavigationTiming/PerformanceTiming.h> +#include <LibWeb/PerformanceTimeline/EntryTypes.h> namespace Web::HighResolutionTime { @@ -50,6 +51,44 @@ double Performance::time_origin() const return static_cast<double>(m_timer.origin_time().to_milliseconds()); } +// https://w3c.github.io/user-timing/#mark-method +WebIDL::ExceptionOr<JS::NonnullGCPtr<UserTiming::PerformanceMark>> Performance::mark(String const& mark_name, UserTiming::PerformanceMarkOptions const& mark_options) +{ + auto& realm = this->realm(); + + // 1. Run the PerformanceMark constructor and let entry be the newly created object. + auto entry = TRY(UserTiming::PerformanceMark::construct_impl(realm, mark_name, mark_options)); + + // 2. Queue entry. + auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object()); + VERIFY(window_or_worker); + TRY(window_or_worker->queue_performance_entry(entry)); + + // 3. Add entry to the performance entry buffer. + // FIXME: This seems to be a holdover from moving to the `queue` structure for PerformanceObserver, as this would cause a double append. + + // 4. Return entry. + return entry; +} + +void Performance::clear_marks(Optional<String> mark_name) +{ + auto& realm = this->realm(); + auto* window_or_worker = dynamic_cast<HTML::WindowOrWorkerGlobalScopeMixin*>(&realm.global_object()); + VERIFY(window_or_worker); + + // 1. If markName is omitted, remove all PerformanceMark objects from the performance entry buffer. + if (!mark_name.has_value()) { + window_or_worker->clear_performance_entry_buffer({}, PerformanceTimeline::EntryTypes::mark); + return; + } + + // 2. Otherwise, remove all PerformanceMark objects listed in the performance entry buffer whose name is markName. + window_or_worker->remove_entries_from_performance_entry_buffer({}, PerformanceTimeline::EntryTypes::mark, mark_name.value()); + + // 3. Return undefined. +} + // https://www.w3.org/TR/performance-timeline/#getentries-method WebIDL::ExceptionOr<Vector<JS::Handle<PerformanceTimeline::PerformanceEntry>>> Performance::get_entries() const { diff --git a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h index 8aa087c89a..c49fdaeb33 100644 --- a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h +++ b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.h @@ -9,6 +9,7 @@ #include <LibCore/ElapsedTimer.h> #include <LibWeb/DOM/EventTarget.h> +#include <LibWeb/UserTiming/PerformanceMark.h> namespace Web::HighResolutionTime { @@ -23,6 +24,9 @@ public: JS::GCPtr<NavigationTiming::PerformanceTiming> timing(); + WebIDL::ExceptionOr<JS::NonnullGCPtr<UserTiming::PerformanceMark>> mark(String const& mark_name, UserTiming::PerformanceMarkOptions const& mark_options = {}); + void clear_marks(Optional<String> mark_name); + 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; diff --git a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl index 544026fb9b..9a8e74aaf1 100644 --- a/Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl +++ b/Userland/Libraries/LibWeb/HighResolutionTime/Performance.idl @@ -2,6 +2,7 @@ #import <HighResolutionTime/DOMHighResTimeStamp.idl> #import <NavigationTiming/PerformanceTiming.idl> #import <PerformanceTimeline/PerformanceEntry.idl> +#import <UserTiming/PerformanceMark.idl> // https://www.w3.org/TR/performance-timeline/#dom-performanceentrylist typedef sequence<PerformanceEntry> PerformanceEntryList; @@ -13,6 +14,14 @@ interface Performance : EventTarget { readonly attribute DOMHighResTimeStamp timeOrigin; readonly attribute PerformanceTiming timing; + + // https://w3c.github.io/user-timing/#extensions-performance-interface + // "User Timing" extensions to the Performance interface + PerformanceMark mark(DOMString markName, optional PerformanceMarkOptions markOptions = {}); + undefined clearMarks(optional DOMString markName); + // FIXME: PerformanceMeasure measure(DOMString measureName, optional (DOMString or PerformanceMeasureOptions) startOrMeasureOptions = {}, optional DOMString endMark); + // FIXME: undefined clearMeasures(optional DOMString measureName); + // https://www.w3.org/TR/performance-timeline/#extensions-to-the-performance-interface // "Performance Timeline" extensions to the Performance interface PerformanceEntryList getEntries(); diff --git a/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.cpp b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.cpp new file mode 100644 index 0000000000..d2da66c87f --- /dev/null +++ b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibWeb/Bindings/Intrinsics.h> +#include <LibWeb/Bindings/PerformanceMarkPrototype.h> +#include <LibWeb/HTML/StructuredSerialize.h> +#include <LibWeb/HTML/Window.h> +#include <LibWeb/HighResolutionTime/TimeOrigin.h> +#include <LibWeb/NavigationTiming/EntryNames.h> +#include <LibWeb/PerformanceTimeline/EntryTypes.h> +#include <LibWeb/UserTiming/PerformanceMark.h> +#include <LibWeb/WebIDL/ExceptionOr.h> + +namespace Web::UserTiming { + +PerformanceMark::PerformanceMark(JS::Realm& realm, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration, JS::Value detail) + : PerformanceTimeline::PerformanceEntry(realm, name, start_time, duration) + , m_detail(detail) +{ +} + +PerformanceMark::~PerformanceMark() = default; + +// https://w3c.github.io/user-timing/#dfn-performancemark-constructor +WebIDL::ExceptionOr<JS::NonnullGCPtr<PerformanceMark>> PerformanceMark::construct_impl(JS::Realm& realm, String const& mark_name, Web::UserTiming::PerformanceMarkOptions const& mark_options) +{ + auto& current_global_object = realm.global_object(); + auto& vm = realm.vm(); + + // 1. If the current global object is a Window object and markName uses the same name as a read only attribute in the PerformanceTiming interface, throw a SyntaxError. + if (is<HTML::Window>(current_global_object)) { + bool matched = false; + +#define __ENUMERATE_NAVIGATION_TIMING_ENTRY_NAME(name) \ + if (mark_name == NavigationTiming::EntryNames::name) \ + matched = true; + ENUMERATE_NAVIGATION_TIMING_ENTRY_NAMES +#undef __ENUMERATE_NAVIGATION_TIMING_ENTRY_NAME + + if (matched) + return WebIDL::SyntaxError::create(realm, DeprecatedString::formatted("'{}' markName cannot be used in a Window context because it is part of the PerformanceTiming interface", mark_name)); + } + + // NOTE: Step 2 (creating the entry) is done after determining values, as we set the values once during creation and never change them after. + + // 3. Set entry's name attribute to markName. + auto const& name = mark_name; + + // 4. Set entry's entryType attribute to DOMString "mark". + // NOTE: Already done via the `entry_type` virtual function. + + // 5. Set entry's startTime attribute as follows: + HighResolutionTime::DOMHighResTimeStamp start_time { 0.0 }; + + // 1. If markOptions's startTime member is present, then: + if (mark_options.start_time.has_value()) { + // 1. If markOptions's startTime is negative, throw a TypeError. + if (mark_options.start_time.value() < 0.0) + return WebIDL::SimpleException { WebIDL::SimpleExceptionType::TypeError, "startTime cannot be negative"sv }; + + // 2. Otherwise, set entry's startTime to the value of markOptions's startTime. + start_time = mark_options.start_time.value(); + } + // 2. Otherwise, set it to the value that would be returned by the Performance object's now() method. + else { + // FIXME: Performance#now doesn't currently use TimeOrigin's functions, update this and Performance#now to match Performance#now's specification. + start_time = HighResolutionTime::unsafe_shared_current_time(); + } + + // 6. Set entry's duration attribute to 0. + constexpr HighResolutionTime::DOMHighResTimeStamp duration = 0.0; + + // 7. If markOptions's detail is null, set entry's detail to null. + JS::Value detail; + if (mark_options.detail.is_null()) { + detail = JS::js_null(); + } + // 8. Otherwise: + else { + // 1. Let record be the result of calling the StructuredSerialize algorithm on markOptions's detail. + auto record = TRY(HTML::structured_serialize(vm, mark_options.detail)); + + // 2. Set entry's detail to the result of calling the StructuredDeserialize algorithm on record and the current realm. + detail = TRY(HTML::structured_deserialize(vm, record, realm, Optional<HTML::SerializationMemory> {})); + } + + // 2. Create a new PerformanceMark object (entry) with the current global object's realm. + return MUST_OR_THROW_OOM(realm.heap().allocate<PerformanceMark>(realm, realm, name, start_time, duration, detail)); +} + +FlyString const& PerformanceMark::entry_type() const +{ + return PerformanceTimeline::EntryTypes::mark; +} + +JS::ThrowCompletionOr<void> PerformanceMark::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype<Bindings::PerformanceMarkPrototype>(realm, "PerformanceMark")); + + return {}; +} + +void PerformanceMark::visit_edges(JS::Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_detail); +} + +} diff --git a/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.h b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.h new file mode 100644 index 0000000000..8a731739d9 --- /dev/null +++ b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2023, Luke Wilde <lukew@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/PerformanceTimeline/PerformanceEntry.h> + +namespace Web::UserTiming { + +// https://w3c.github.io/user-timing/#ref-for-dom-performancemarkoptions-1 +struct PerformanceMarkOptions { + JS::Value detail { JS::js_null() }; + Optional<HighResolutionTime::DOMHighResTimeStamp> start_time; +}; + +// https://w3c.github.io/user-timing/#dom-performancemark +class PerformanceMark final : public PerformanceTimeline::PerformanceEntry { + WEB_PLATFORM_OBJECT(PerformanceMark, PerformanceTimeline::PerformanceEntry); + +public: + virtual ~PerformanceMark(); + + static WebIDL::ExceptionOr<JS::NonnullGCPtr<PerformanceMark>> construct_impl(JS::Realm&, String const& mark_name, PerformanceMarkOptions const& mark_options = {}); + + // NOTE: These three functions are answered by the registry for the given entry type. + // https://w3c.github.io/timing-entrytypes-registry/#registry + + // https://w3c.github.io/timing-entrytypes-registry/#dfn-availablefromtimeline + static PerformanceTimeline::AvailableFromTimeline available_from_timeline() { return PerformanceTimeline::AvailableFromTimeline::Yes; } + + // https://w3c.github.io/timing-entrytypes-registry/#dfn-maxbuffersize + // NOTE: The empty state represents Infinite size. + static Optional<u64> max_buffer_size() { return OptionalNone {}; } + + // https://w3c.github.io/timing-entrytypes-registry/#dfn-should-add-entry + virtual PerformanceTimeline::ShouldAddEntry should_add_entry() const override { return PerformanceTimeline::ShouldAddEntry::Yes; } + + virtual FlyString const& entry_type() const override; + + JS::Value detail() const { return m_detail; } + +private: + PerformanceMark(JS::Realm&, String const& name, HighResolutionTime::DOMHighResTimeStamp start_time, HighResolutionTime::DOMHighResTimeStamp duration, JS::Value detail); + + virtual JS::ThrowCompletionOr<void> initialize(JS::Realm&) override; + virtual void visit_edges(JS::Cell::Visitor&) override; + + // https://w3c.github.io/user-timing/#dom-performancemark-detail + JS::Value m_detail { JS::js_null() }; +}; + +} diff --git a/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.idl b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.idl new file mode 100644 index 0000000000..0b93a6c636 --- /dev/null +++ b/Userland/Libraries/LibWeb/UserTiming/PerformanceMark.idl @@ -0,0 +1,14 @@ +#import <PerformanceTimeline/PerformanceEntry.idl> + +// https://w3c.github.io/user-timing/#dom-performancemark +[Exposed=(Window,Worker), UseNewAKString] +interface PerformanceMark : PerformanceEntry { + constructor(DOMString markName, optional PerformanceMarkOptions markOptions = {}); + readonly attribute any detail; +}; + +// https://w3c.github.io/user-timing/#ref-for-dom-performancemarkoptions-1 +dictionary PerformanceMarkOptions { + any detail; + DOMHighResTimeStamp startTime; +}; diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 126ff30302..9d79256c25 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -201,6 +201,7 @@ libweb_js_bindings(UIEvents/UIEvent) libweb_js_bindings(UIEvents/WheelEvent) libweb_js_bindings(URL/URL) libweb_js_bindings(URL/URLSearchParams ITERABLE) +libweb_js_bindings(UserTiming/PerformanceMark) libweb_js_bindings(WebAssembly/Instance) libweb_js_bindings(WebAssembly/Memory) libweb_js_bindings(WebAssembly/Module) |