LibWeb/CSS: Add the TransitionEvent type

This commit is contained in:
Lucas CHOLLET 2024-12-22 15:12:13 -05:00 committed by Andreas Kling
commit 55b4a983a7
Notes: github-actions[bot] 2024-12-25 16:15:39 +00:00
8 changed files with 379 additions and 0 deletions

View file

@ -170,6 +170,7 @@ set(SOURCES
CSS/SystemColor.cpp CSS/SystemColor.cpp
CSS/Time.cpp CSS/Time.cpp
CSS/Transformation.cpp CSS/Transformation.cpp
CSS/TransitionEvent.cpp
CSS/VisualViewport.cpp CSS/VisualViewport.cpp
Cookie/Cookie.cpp Cookie/Cookie.cpp
Cookie/ParsedCookie.cpp Cookie/ParsedCookie.cpp

View file

@ -0,0 +1,43 @@
/*
* Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "TransitionEvent.h"
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/TransitionEventPrototype.h>
namespace Web::CSS {
GC_DEFINE_ALLOCATOR(TransitionEvent);
GC::Ref<TransitionEvent> TransitionEvent::create(JS::Realm& realm, FlyString const& type, TransitionEventInit const& event_init)
{
auto event = realm.create<TransitionEvent>(realm, type, event_init);
event->set_is_trusted(true);
return event;
}
GC::Ref<TransitionEvent> TransitionEvent::construct_impl(JS::Realm& realm, FlyString const& type, TransitionEventInit const& event_init)
{
return realm.create<TransitionEvent>(realm, type, event_init);
}
TransitionEvent::TransitionEvent(JS::Realm& realm, FlyString const& type, TransitionEventInit const& event_init)
: DOM::Event(realm, type, event_init)
, m_property_name(event_init.property_name)
, m_elapsed_time(event_init.elapsed_time)
, m_pseudo_element(event_init.pseudo_element)
{
}
TransitionEvent::~TransitionEvent() = default;
void TransitionEvent::initialize(JS::Realm& realm)
{
Base::initialize(realm);
WEB_SET_PROTOTYPE_FOR_INTERFACE(TransitionEvent);
}
}

View file

@ -0,0 +1,42 @@
/*
* Copyright (c) 2024, Lucas Chollet <lucas.chollet@serenityos.org>.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/DOM/Event.h>
namespace Web::CSS {
struct TransitionEventInit : public DOM::EventInit {
String property_name {};
double elapsed_time = 0.0;
String pseudo_element {};
};
class TransitionEvent final : public DOM::Event {
WEB_PLATFORM_OBJECT(TransitionEvent, DOM::Event);
GC_DECLARE_ALLOCATOR(TransitionEvent);
public:
[[nodiscard]] static GC::Ref<TransitionEvent> create(JS::Realm&, FlyString const& event_name, TransitionEventInit const& = {});
[[nodiscard]] static GC::Ref<TransitionEvent> construct_impl(JS::Realm&, FlyString const& event_name, TransitionEventInit const& = {});
virtual ~TransitionEvent() override;
String const& property_name() const { return m_property_name; }
double elapsed_time() const { return m_elapsed_time; }
String const& pseudo_element() const { return m_pseudo_element; }
private:
TransitionEvent(JS::Realm&, FlyString const& event_name, TransitionEventInit const& event_init);
virtual void initialize(JS::Realm&) override;
String m_property_name {};
double m_elapsed_time {};
String m_pseudo_element {};
};
}

View file

@ -0,0 +1,16 @@
#import <DOM/Event.idl>
// https://drafts.csswg.org/css-transitions/#transitionevent
[Exposed=Window]
interface TransitionEvent : Event {
constructor(CSSOMString type, optional TransitionEventInit transitionEventInitDict = {});
readonly attribute CSSOMString propertyName;
readonly attribute double elapsedTime;
readonly attribute CSSOMString pseudoElement;
};
dictionary TransitionEventInit : EventInit {
CSSOMString propertyName = "";
double elapsedTime = 0.0;
CSSOMString pseudoElement = "";
};

View file

@ -46,6 +46,7 @@ libweb_js_bindings(CSS/Screen)
libweb_js_bindings(CSS/ScreenOrientation) libweb_js_bindings(CSS/ScreenOrientation)
libweb_js_bindings(CSS/StyleSheet) libweb_js_bindings(CSS/StyleSheet)
libweb_js_bindings(CSS/StyleSheetList) libweb_js_bindings(CSS/StyleSheetList)
libweb_js_bindings(CSS/TransitionEvent)
libweb_js_bindings(CSS/VisualViewport) libweb_js_bindings(CSS/VisualViewport)
libweb_js_bindings(DOM/AbstractRange) libweb_js_bindings(DOM/AbstractRange)
libweb_js_bindings(DOM/Attr) libweb_js_bindings(DOM/Attr)

View file

@ -381,6 +381,7 @@ ToggleEvent
TrackEvent TrackEvent
TransformStream TransformStream
TransformStreamDefaultController TransformStreamDefaultController
TransitionEvent
TreeWalker TreeWalker
TypeError TypeError
UIEvent UIEvent

View file

@ -0,0 +1,46 @@
Harness status: OK
Found 41 tests
41 Pass
Pass the event is an instance of TransitionEvent
Pass the event inherts from Event
Pass Missing type argument
Pass type argument is string
Pass type argument is null
Pass event type set to undefined
Pass propertyName has default value of empty string
Pass elapsedTime has default value of 0.0
Pass propertyName is readonly
Pass elapsedTime is readonly
Pass animationEventInit argument is null
Pass animationEventInit argument is undefined
Pass animationEventInit argument is empty dictionary
Pass TransitionEvent.pseudoElement initialized from the dictionary
Pass propertyName set to 'sample'
Pass propertyName set to undefined
Pass propertyName set to null
Pass propertyName set to false
Pass propertyName set to true
Pass propertyName set to a number
Pass propertyName set to []
Pass propertyName set to [1, 2, 3]
Pass propertyName set to an object
Pass propertyName set to an object with a valueOf function
Pass elapsedTime set to 0.5
Pass elapsedTime set to -0.5
Pass elapsedTime set to undefined
Pass elapsedTime set to null
Pass elapsedTime set to false
Pass elapsedTime set to true
Pass elapsedTime set to ''
Pass elapsedTime set to []
Pass elapsedTime set to [0.5]
Pass elapsedTime set to an object with a valueOf function
Pass elapsedTime cannot be set to NaN
Pass elapsedTime cannot be set to Infinity
Pass elapsedTime cannot be set to -Infinity
Pass elapsedTime cannot be set to 'sample'
Pass elapsedTime cannot be set to [0.5, 1.0]
Pass elapsedTime cannot be set to an object
Pass TransitionEventInit properties set value

View file

@ -0,0 +1,229 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>CSS Transitions Test: TransitionEvent interface</title>
<link rel="help" href="https://drafts.csswg.org/css-transitions-1/#interface-transitionevent">
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="transitionevent-interface.js"></script>
<script>
test(function() {
var event = new TransitionEvent("");
assert_true(event instanceof window.TransitionEvent);
}, "the event is an instance of TransitionEvent");
test(function() {
var event = new TransitionEvent("");
assert_true(event instanceof window.Event);
}, "the event inherts from Event");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent();
}, 'First argument is required, so was expecting a TypeError.');
}, 'Missing type argument');
test(function() {
var event = new TransitionEvent("test");
assert_equals(event.type, "test");
}, "type argument is string");
test(function() {
var event = new TransitionEvent(null);
assert_equals(event.type, "null");
}, "type argument is null");
test(function() {
var event = new TransitionEvent(undefined);
assert_equals(event.type, "undefined");
}, "event type set to undefined");
test(function() {
var event = new TransitionEvent("test");
assert_equals(event.propertyName, "");
}, "propertyName has default value of empty string");
test(function() {
var event = new TransitionEvent("test");
assert_equals(event.elapsedTime, 0.0);
}, "elapsedTime has default value of 0.0");
test(function() {
var event = new TransitionEvent("test");
assert_readonly(event, "propertyName", "readonly attribute value");
}, "propertyName is readonly");
test(function() {
var event = new TransitionEvent("test");
assert_readonly(event, "elapsedTime", "readonly attribute value");
}, "elapsedTime is readonly");
test(function() {
var event = new TransitionEvent("test", null);
assert_equals(event.propertyName, "");
assert_equals(event.elapsedTime, 0.0);
}, "animationEventInit argument is null");
test(function() {
var event = new TransitionEvent("test", undefined);
assert_equals(event.propertyName, "");
assert_equals(event.elapsedTime, 0.0);
}, "animationEventInit argument is undefined");
test(function() {
var event = new TransitionEvent("test", {});
assert_equals(event.propertyName, "");
assert_equals(event.elapsedTime, 0.0);
}, "animationEventInit argument is empty dictionary");
test(function() {
var event = new TransitionEvent("test", {pseudoElement: "::testPseudo"});
assert_equals(event.pseudoElement, "::testPseudo");
}, "TransitionEvent.pseudoElement initialized from the dictionary");
test(function() {
var event = new TransitionEvent("test", {propertyName: "sample"});
assert_equals(event.propertyName, "sample");
}, "propertyName set to 'sample'");
test(function() {
var event = new TransitionEvent("test", {propertyName: undefined});
assert_equals(event.propertyName, "");
}, "propertyName set to undefined");
test(function() {
var event = new TransitionEvent("test", {propertyName: null});
assert_equals(event.propertyName, "null");
}, "propertyName set to null");
test(function() {
var event = new TransitionEvent("test", {propertyName: false});
assert_equals(event.propertyName, "false");
}, "propertyName set to false");
test(function() {
var event = new TransitionEvent("test", {propertyName: true});
assert_equals(event.propertyName, "true");
}, "propertyName set to true");
test(function() {
var event = new TransitionEvent("test", {propertyName: 0.5});
assert_equals(event.propertyName, "0.5");
}, "propertyName set to a number");
test(function() {
var event = new TransitionEvent("test", {propertyName: []});
assert_equals(event.propertyName, "");
}, "propertyName set to []");
test(function() {
var event = new TransitionEvent("test", {propertyName: [1, 2, 3]});
assert_equals(event.propertyName, "1,2,3");
}, "propertyName set to [1, 2, 3]");
test(function() {
var event = new TransitionEvent("test", {propertyName: {sample: 0.5}});
assert_equals(event.propertyName, "[object Object]");
}, "propertyName set to an object");
test(function() {
var event = new TransitionEvent("test",
{propertyName: {valueOf: function () { return 'sample'; }}});
assert_equals(event.propertyName, "[object Object]");
}, "propertyName set to an object with a valueOf function");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: 0.5});
assert_equals(event.elapsedTime, 0.5);
}, "elapsedTime set to 0.5");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: -0.5});
assert_equals(event.elapsedTime, -0.5);
}, "elapsedTime set to -0.5");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: undefined});
assert_equals(event.elapsedTime, 0);
}, "elapsedTime set to undefined");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: null});
assert_equals(event.elapsedTime, 0);
}, "elapsedTime set to null");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: false});
assert_equals(event.elapsedTime, 0);
}, "elapsedTime set to false");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: true});
assert_equals(event.elapsedTime, 1);
}, "elapsedTime set to true");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: ""});
assert_equals(event.elapsedTime, 0);
}, "elapsedTime set to ''");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: []});
assert_equals(event.elapsedTime, 0);
}, "elapsedTime set to []");
test(function() {
var event = new TransitionEvent("test", {elapsedTime: [0.5]});
assert_equals(event.elapsedTime, 0.5);
}, "elapsedTime set to [0.5]");
test(function() {
var event = new TransitionEvent(
"test", {elapsedTime: { valueOf: function() { return 0.5; }}});
assert_equals(event.elapsedTime, 0.5);
}, "elapsedTime set to an object with a valueOf function");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: NaN});
}, 'elapsedTime cannot be NaN so was expecting a TypeError');
}, "elapsedTime cannot be set to NaN");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: Infinity});
}, 'elapsedTime cannot be Infinity so was expecting a TypeError');
}, "elapsedTime cannot be set to Infinity");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: -Infinity});
}, 'elapsedTime cannot be -Infinity so was expecting a TypeError');
}, "elapsedTime cannot be set to -Infinity");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: "sample"});
}, 'elapsedTime cannot be a string so was expecting a TypeError');
}, "elapsedTime cannot be set to 'sample'");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: [0.5, 1.0]});
}, 'elapsedTime cannot be a multi-element array so was expecting a TypeError');
}, "elapsedTime cannot be set to [0.5, 1.0]");
test(function() {
assert_throws_js(TypeError, function() {
new TransitionEvent("test", {elapsedTime: { sample: 0.5}});
}, 'elapsedTime cannot be an object so was expecting a TypeError');
}, "elapsedTime cannot be set to an object");
test(function() {
var eventInit = {propertyName: "sample", elapsedTime: 0.5};
var event = new TransitionEvent("test", eventInit);
assert_equals(event.propertyName, "sample");
assert_equals(event.elapsedTime, 0.5);
}, "TransitionEventInit properties set value");
</script>