LibWeb: Port document.execCommand and InputEvent to UTF-16

This commit is contained in:
Timothy Flynn 2025-07-25 15:57:20 -04:00 committed by Jelle Raaijmakers
commit 2da615ed31
Notes: github-actions[bot] 2025-07-25 22:41:42 +00:00
8 changed files with 25 additions and 24 deletions

View file

@ -665,7 +665,7 @@ public:
void set_previous_document_unload_timing(DocumentUnloadTimingInfo const& previous_document_unload_timing) { m_previous_document_unload_timing = previous_document_unload_timing; }
// https://w3c.github.io/editing/docs/execCommand/
WebIDL::ExceptionOr<bool> exec_command(FlyString const& command, bool show_ui, String const& value);
WebIDL::ExceptionOr<bool> exec_command(FlyString const& command, bool show_ui, Utf16String const& value);
WebIDL::ExceptionOr<bool> query_command_enabled(FlyString const& command);
WebIDL::ExceptionOr<bool> query_command_indeterm(FlyString const& command);
WebIDL::ExceptionOr<bool> query_command_state(FlyString const& command);

View file

@ -146,7 +146,7 @@ interface Document : Node {
// https://w3c.github.io/editing/docs/execCommand/
// FIXME: [CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional (TrustedHTML or DOMString) value = "");
[CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional DOMString value = "");
[CEReactions] boolean execCommand(DOMString commandId, optional boolean showUI = false, optional Utf16DOMString value = "");
boolean queryCommandEnabled(DOMString commandId);
boolean queryCommandIndeterm(DOMString commandId);
boolean queryCommandState(DOMString commandId);

View file

@ -43,7 +43,7 @@ void EditingHostManager::handle_insert(Utf16String const& value)
// once or in quick succession, this specification does not define whether it is treated as one insertion or several
// consecutive insertions.
auto editing_result = m_document->exec_command(Editing::CommandNames::insertText, false, value.to_utf8_but_should_be_ported_to_utf16());
auto editing_result = m_document->exec_command(Editing::CommandNames::insertText, false, value);
if (editing_result.is_exception())
dbgln("handle_insert(): editing resulted in exception: {}", editing_result.exception());
}

View file

@ -17,7 +17,7 @@
namespace Web::DOM {
// https://w3c.github.io/editing/docs/execCommand/#execcommand()
WebIDL::ExceptionOr<bool> Document::exec_command(FlyString const& command, [[maybe_unused]] bool show_ui, String const& value)
WebIDL::ExceptionOr<bool> Document::exec_command(FlyString const& command, [[maybe_unused]] bool show_ui, Utf16String const& value)
{
// AD-HOC: This is not directly mentioned in the spec, but all major browsers limit editing API calls to HTML documents
if (!is_html_document())
@ -101,8 +101,7 @@ WebIDL::ExceptionOr<bool> Document::exec_command(FlyString const& command, [[may
auto old_character_data_version = character_data_version();
// 5. Take the action for command, passing value to the instructions as an argument.
auto utf16_value = Utf16String::from_utf8_without_validation(value);
auto command_result = command_definition.action(*this, utf16_value.utf16_view());
auto command_result = command_definition.action(*this, value);
// https://w3c.github.io/editing/docs/execCommand/#preserves-overrides
// After taking the action, if the active range is collapsed, it must restore states and values from the recorded

View file

@ -1129,7 +1129,7 @@ static GC::RootVector<GC::Ref<DOM::StaticRange>> target_ranges_for_input_event(D
return target_ranges;
}
EventResult EventHandler::input_event(FlyString const& event_name, FlyString const& input_type, HTML::Navigable& navigable, Variant<u32, String> code_point_or_string)
EventResult EventHandler::input_event(FlyString const& event_name, FlyString const& input_type, HTML::Navigable& navigable, Variant<u32, Utf16String> code_point_or_string)
{
auto document = navigable.active_document();
if (!document)
@ -1139,14 +1139,14 @@ EventResult EventHandler::input_event(FlyString const& event_name, FlyString con
UIEvents::InputEventInit input_event_init;
if (code_point_or_string.has<u32>()) {
auto code_point = code_point_or_string.get<u32>();
if (!is_unicode_control(code_point)) {
input_event_init.data = String::from_code_point(code_point);
}
} else {
input_event_init.data = code_point_or_string.get<String>();
}
code_point_or_string.visit(
[&](u32 code_point) {
if (!is_unicode_control(code_point))
input_event_init.data = Utf16String::from_code_point(code_point);
},
[&](Utf16String const& string) {
input_event_init.data = string;
});
input_event_init.input_type = input_type;
@ -1154,7 +1154,7 @@ EventResult EventHandler::input_event(FlyString const& event_name, FlyString con
if (is<HTML::NavigableContainer>(*focused_element)) {
auto& navigable_container = as<HTML::NavigableContainer>(*focused_element);
if (navigable_container.content_navigable())
return input_event(event_name, input_type, *navigable_container.content_navigable(), code_point_or_string);
return input_event(event_name, input_type, *navigable_container.content_navigable(), move(code_point_or_string));
}
auto event = UIEvents::InputEvent::create_from_platform_event(document->realm(), event_name, input_event_init, target_ranges_for_input_event(*document));
@ -1385,8 +1385,10 @@ EventResult EventHandler::handle_paste(String const& text)
if (!target)
return EventResult::Dropped;
FIRE(input_event(UIEvents::EventNames::beforeinput, UIEvents::InputTypes::insertFromPaste, m_navigable, text));
target->handle_insert(Utf16String::from_utf8(text));
auto utf16_string = Utf16String::from_utf8(text);
FIRE(input_event(UIEvents::EventNames::beforeinput, UIEvents::InputTypes::insertFromPaste, m_navigable, utf16_string));
target->handle_insert(utf16_string);
return EventResult::Handled;
}

View file

@ -50,7 +50,7 @@ private:
EventResult focus_previous_element();
EventResult fire_keyboard_event(FlyString const& event_name, HTML::Navigable&, UIEvents::KeyCode, unsigned modifiers, u32 code_point, bool repeat);
[[nodiscard]] EventResult input_event(FlyString const& event_name, FlyString const& input_type, HTML::Navigable&, Variant<u32, String> code_point_or_string);
[[nodiscard]] EventResult input_event(FlyString const& event_name, FlyString const& input_type, HTML::Navigable&, Variant<u32, Utf16String> code_point_or_string);
CSSPixelPoint compute_mouse_event_client_offset(CSSPixelPoint event_page_position) const;
CSSPixelPoint compute_mouse_event_page_offset(CSSPixelPoint event_client_offset) const;
CSSPixelPoint compute_mouse_event_movement(CSSPixelPoint event_client_offset) const;

View file

@ -12,7 +12,7 @@
namespace Web::UIEvents {
struct InputEventInit : public UIEventInit {
Optional<String> data;
Optional<Utf16String> data;
bool is_composing { false };
FlyString input_type {};
};
@ -28,7 +28,7 @@ public:
virtual ~InputEvent() override;
// https://w3c.github.io/uievents/#dom-inputevent-data
Optional<String> data() const { return m_data; }
Optional<Utf16String> data() const { return m_data; }
// https://w3c.github.io/uievents/#dom-inputevent-iscomposing
bool is_composing() const { return m_is_composing; }
@ -44,7 +44,7 @@ private:
virtual void initialize(JS::Realm&) override;
virtual void visit_edges(Visitor&) override;
Optional<String> m_data;
Optional<Utf16String> m_data;
bool m_is_composing;
FlyString m_input_type;
Vector<GC::Ref<DOM::StaticRange>> m_target_ranges;

View file

@ -5,7 +5,7 @@
[Exposed=Window]
interface InputEvent : UIEvent {
constructor(DOMString type, optional InputEventInit eventInitDict = {});
readonly attribute USVString? data;
readonly attribute Utf16USVString? data;
readonly attribute boolean isComposing;
readonly attribute DOMString inputType;
@ -14,7 +14,7 @@ interface InputEvent : UIEvent {
// https://w3c.github.io/uievents/#dictdef-inputeventinit
dictionary InputEventInit : UIEventInit {
DOMString? data = null;
Utf16DOMString? data = null;
boolean isComposing = false;
DOMString inputType = "";
};