diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index cce5c4f496bfa..8f906c911321a 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -1101,6 +1101,8 @@ class Document GC::Ref m_editing_host_manager; + bool m_inside_exec_command { false }; + // https://w3c.github.io/editing/docs/execCommand/#default-single-line-container-name FlyString m_default_single_line_container_name { HTML::TagNames::div }; diff --git a/Libraries/LibWeb/Editing/ExecCommand.cpp b/Libraries/LibWeb/Editing/ExecCommand.cpp index b3a5bdc507c49..942970ba306d5 100644 --- a/Libraries/LibWeb/Editing/ExecCommand.cpp +++ b/Libraries/LibWeb/Editing/ExecCommand.cpp @@ -22,6 +22,12 @@ WebIDL::ExceptionOr Document::exec_command(FlyString const& command, [[may if (!is_html_document()) return WebIDL::InvalidStateError::create(realm(), "execCommand is only supported on HTML documents"_string); + // AD-HOC: All major browsers refuse to recursively execute execCommand() (e.g. inside input event handlers). + if (m_inside_exec_command) + return false; + ScopeGuard guard_recursion = [&] { m_inside_exec_command = false; }; + m_inside_exec_command = true; + // 1. If only one argument was provided, let show UI be false. // 2. If only one or two arguments were provided, let value be the empty string. // NOTE: these steps are dealt by the default values for both show_ui and value