Files
ladybird/Libraries/LibWeb/HTML/MessageEvent.cpp
Shannon Booth 5adfd1c43a LibWeb/Bindings: Generate struct definitions from IDL dictionaries
Previously we were inconsistent by generating code for enum definitions
but not generating code for dictionaries. With future changes to the
IDL generator to expose helpers to convert to and from IDL values
this produced circular depdendencies. To solve this problem, also
generate the dictionary definitions in bindings headers.
2026-05-09 10:49:49 +02:00

166 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* Copyright (c) 2022, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2024, Jamie Mansfield <jmansfield@cadixdev.org>
* Copyright (c) 2026, Sam Atkins <sam@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibJS/Runtime/Array.h>
#include <LibWeb/Bindings/Intrinsics.h>
#include <LibWeb/Bindings/MessageEvent.h>
#include <LibWeb/HTML/MessageEvent.h>
#include <LibWeb/HTML/MessagePort.h>
#include <LibWeb/HTML/WindowProxy.h>
namespace Web::HTML {
GC_DEFINE_ALLOCATOR(MessageEvent);
GC::Ref<MessageEvent> MessageEvent::create(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init)
{
return realm.create<MessageEvent>(realm, event_name, event_init);
}
GC::Ref<MessageEvent> MessageEvent::create(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init, URL::Origin const& origin)
{
return realm.create<MessageEvent>(realm, event_name, event_init, origin);
}
WebIDL::ExceptionOr<GC::Ref<MessageEvent>> MessageEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init)
{
return create(realm, event_name, event_init);
}
MessageEvent::MessageEventSourceInternal MessageEvent::to_message_event_source_internal(NullableMessageEventSource const& source)
{
return source.visit(
[](Empty) -> MessageEventSourceInternal { return Empty {}; },
[](auto const& root) -> MessageEventSourceInternal { return GC::Ref { *root }; });
}
MessageEvent::MessageEvent(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init)
: MessageEvent(realm, event_name, event_init, String { event_init.origin })
{
}
MessageEvent::MessageEvent(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init, URL::Origin const& origin)
: MessageEvent(realm, event_name, event_init, Variant<URL::Origin, String, Empty> { origin })
{
}
MessageEvent::MessageEvent(JS::Realm& realm, FlyString const& event_name, Bindings::MessageEventInit const& event_init, Variant<URL::Origin, String, Empty> origin)
: DOM::Event(realm, event_name, event_init)
, m_data(event_init.data)
, m_origin(move(origin))
, m_last_event_id(event_init.last_event_id)
, m_source(to_message_event_source_internal(event_init.source))
{
m_ports.ensure_capacity(event_init.ports.size());
for (auto const& port : event_init.ports) {
VERIFY(port);
m_ports.unchecked_append(static_cast<JS::Object&>(*port));
}
}
MessageEvent::~MessageEvent() = default;
void MessageEvent::initialize(JS::Realm& realm)
{
WEB_SET_PROTOTYPE_FOR_INTERFACE(MessageEvent);
Base::initialize(realm);
}
void MessageEvent::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_data);
visitor.visit(m_ports_array);
visitor.visit(m_ports);
m_source.visit(
[](Empty) {},
[&](auto const& ref) { visitor.visit(ref); });
}
// https://html.spec.whatwg.org/multipage/comms.html#dom-messageevent-origin
String MessageEvent::origin() const
{
return m_origin.visit(
// 1. If this's origin is an origin, then return the serialization of this's origin.
[](URL::Origin const& origin) {
return origin.serialize();
},
// 2. If this's origin is null, then return the empty string.
[](Empty) {
return String {};
},
// 3. Return this's origin.
[](String const& origin) {
return origin;
});
}
NullableMessageEventSource MessageEvent::source() const
{
return m_source.visit(
[](Empty) -> NullableMessageEventSource { return Empty {}; },
[](auto const& ref) -> NullableMessageEventSource { return GC::Root { *ref }; });
}
GC::Ref<JS::Object> MessageEvent::ports() const
{
if (!m_ports_array) {
GC::RootVector<JS::Value> port_vector(heap());
for (auto const& port : m_ports)
port_vector.append(port);
m_ports_array = JS::Array::create_from(realm(), port_vector);
MUST(m_ports_array->set_integrity_level(IntegrityLevel::Frozen));
}
return *m_ports_array;
}
// https://html.spec.whatwg.org/multipage/comms.html#dom-messageevent-initmessageevent
void MessageEvent::init_message_event(String const& type, bool bubbles, bool cancelable, JS::Value data, String const& origin, String const& last_event_id, NullableMessageEventSource source, Vector<GC::Root<MessagePort>> const& ports)
{
// The initMessageEvent(type, bubbles, cancelable, data, origin, lastEventId, source, ports) method must initialize the event in a
// manner analogous to the similarly-named initEvent() method.
// 1. If thiss dispatch flag is set, then return.
if (dispatched())
return;
// 2. Initialize this with type, bubbles, and cancelable.
initialize_event(type, bubbles, cancelable);
// Implementation Defined: Initialise other values.
m_data = data;
m_origin = origin;
m_last_event_id = last_event_id;
m_source = to_message_event_source_internal(source);
m_ports_array = nullptr;
m_ports.clear();
m_ports.ensure_capacity(ports.size());
for (auto const& port : ports) {
VERIFY(port);
m_ports.unchecked_append(static_cast<JS::Object&>(*port));
}
}
// https://html.spec.whatwg.org/multipage/comms.html#the-messageevent-interface:extract-an-origin
Optional<URL::Origin> MessageEvent::extract_an_origin() const
{
// Objects implementing the MessageEvent interface's extract an origin steps are to return this's origin if it is an origin; otherwise null.
return m_origin.visit(
[](URL::Origin const& origin) -> Optional<URL::Origin> {
return origin;
},
[](auto const&) -> Optional<URL::Origin> {
return {};
});
}
}