ladybird/Libraries/LibWeb/HTML/MessageEvent.cpp

149 lines
5 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/MessageEventPrototype.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, MessageEventInit const& event_init)
{
return realm.create<MessageEvent>(realm, event_name, event_init);
}
WebIDL::ExceptionOr<GC::Ref<MessageEvent>> MessageEvent::construct_impl(JS::Realm& realm, FlyString const& event_name, 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, MessageEventInit const& event_init)
: DOM::Event(realm, event_name, event_init)
, m_data(event_init.data)
, m_origin(event_init.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 {};
});
}
}