diff --git a/moli-renderer-v8/src/native_bridge/element.rs b/moli-renderer-v8/src/native_bridge/element.rs index fd8b134c16..36c55c55dd 100644 --- a/moli-renderer-v8/src/native_bridge/element.rs +++ b/moli-renderer-v8/src/native_bridge/element.rs @@ -441,8 +441,10 @@ pub(super) use global_attributes::{ node_credentialless_getter_function, node_credentialless_setter_function, node_dir_getter_function, node_dir_setter_function, node_draggable_getter_function, node_draggable_setter_function, node_enter_key_hint_getter_function, - node_enter_key_hint_setter_function, node_hidden_getter_function, node_hidden_setter_function, - node_input_mode_getter_function, node_input_mode_setter_function, + node_enter_key_hint_setter_function, node_focus_group_getter_function, + node_focus_group_setter_function, node_focus_group_start_getter_function, + node_focus_group_start_setter_function, node_hidden_getter_function, + node_hidden_setter_function, node_input_mode_getter_function, node_input_mode_setter_function, node_is_content_editable_getter_function, node_lang_getter_function, node_lang_setter_function, node_sandbox_getter_function, node_sandbox_setter_function, node_spellcheck_getter_function, node_spellcheck_setter_function, node_tab_index_getter_function, @@ -1560,6 +1562,20 @@ struct HtmlOrForeignElementPrototypeDeclaration { setter = node_nonce_setter_function )] nonce: (), + #[webapi( + accessor_property = "focusGroup", + enumerable, + getter = node_focus_group_getter_function, + setter = node_focus_group_setter_function + )] + focus_group: (), + #[webapi( + accessor_property = "focusGroupStart", + enumerable, + getter = node_focus_group_start_getter_function, + setter = node_focus_group_start_setter_function + )] + focus_group_start: (), #[webapi( accessor_property, enumerable, diff --git a/moli-renderer-v8/src/native_bridge/element/global_attributes.rs b/moli-renderer-v8/src/native_bridge/element/global_attributes.rs index b22b1dac48..fa2430f7bf 100644 --- a/moli-renderer-v8/src/native_bridge/element/global_attributes.rs +++ b/moli-renderer-v8/src/native_bridge/element/global_attributes.rs @@ -2216,6 +2216,57 @@ pub(in crate::native_bridge) fn node_autofocus_getter_function<'s>( boolean_attribute_property_getter_from_object_or_detached(scope, args.this(), "autofocus", rv); } +pub(in crate::native_bridge) fn node_focus_group_getter_function<'s>( + scope: &mut v8::PinScope<'s, '_>, + args: v8::FunctionCallbackArguments<'s>, + rv: v8::ReturnValue<'s, v8::Value>, +) { + attribute_property_getter_from_object_or_detached(scope, args.this(), "focusgroup", rv); +} + +pub(in crate::native_bridge) fn node_focus_group_setter_function<'s>( + scope: &mut v8::PinScope<'s, '_>, + args: v8::FunctionCallbackArguments<'s>, + mut rv: v8::ReturnValue<'s, v8::Value>, +) { + set_dom_string_attribute_property_on_object( + scope, + args.this(), + "focusgroup", + args.get(0), + "HTMLOrSVGOrMathMLElement", + "focusGroup", + ); + rv.set_undefined(); +} + +pub(in crate::native_bridge) fn node_focus_group_start_getter_function<'s>( + scope: &mut v8::PinScope<'s, '_>, + args: v8::FunctionCallbackArguments<'s>, + rv: v8::ReturnValue<'s, v8::Value>, +) { + boolean_attribute_property_getter_from_object_or_detached( + scope, + args.this(), + "focusgroupstart", + rv, + ); +} + +pub(in crate::native_bridge) fn node_focus_group_start_setter_function<'s>( + scope: &mut v8::PinScope<'s, '_>, + args: v8::FunctionCallbackArguments<'s>, + mut rv: v8::ReturnValue<'s, v8::Value>, +) { + set_boolean_attribute_property_on_object_or_detached( + scope, + args.this(), + "focusgroupstart", + args.get(0), + ); + rv.set_undefined(); +} + pub(in crate::native_bridge) fn node_autofocus_setter_function<'s>( scope: &mut v8::PinScope<'s, '_>, args: v8::FunctionCallbackArguments<'s>, diff --git a/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs b/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs index e996e45a0c..546ec9f42e 100644 --- a/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs +++ b/moli-renderer-v8/src/script_vm/tests/dom_elements/live_document.rs @@ -733,7 +733,7 @@ fn htmlelement_standard_accessors_live_on_owner_prototypes() { assert(!own(HTMLDivElement.prototype, name), `${name} duplicated on HTMLDivElement.prototype`); } - const mixinNames = ["autofocus", "tabIndex"]; + const mixinNames = ["focusGroup", "focusGroupStart", "autofocus", "tabIndex"]; for (const prototype of [HTMLElement.prototype, SVGElement.prototype, MathMLElement.prototype]) { for (const name of mixinNames) { accessor(prototype, name); @@ -765,6 +765,8 @@ fn htmlelement_standard_accessors_live_on_owner_prototypes() { div.inputMode = "NUMERIC"; div.innerText = "hello text"; div.popover = "hint"; + div.focusGroup = "toolbar"; + div.focusGroupStart = true; div.autofocus = true; div.tabIndex = 5; @@ -783,7 +785,15 @@ fn htmlelement_standard_accessors_live_on_owner_prototypes() { assert(div.inputMode === "numeric", "inputMode behavior"); assert(div.innerText === "hello text" && div.outerText === "hello text", "innerText/outerText behavior"); assert(div.popover === "hint", "popover behavior"); - assert(div.autofocus === true && div.tabIndex === 5, "HTMLOrForeignElement behavior"); + assert( + div.focusGroup === "toolbar" && + div.getAttribute("focusgroup") === "toolbar" && + div.focusGroupStart === true && + div.hasAttribute("focusgroupstart") && + div.autofocus === true && + div.tabIndex === 5, + "HTMLOrSVGOrMathMLElement behavior" + ); const holder = document.createElement("section"); const para = document.createElement("p"); @@ -794,8 +804,18 @@ fn htmlelement_standard_accessors_live_on_owner_prototypes() { svg.tabIndex = 9; svg.autofocus = true; + svg.focusGroup = "grid"; + svg.focusGroupStart = true; assert(svg.tabIndex === 9 && svg.getAttribute("tabindex") === "9", "svg tabIndex behavior"); assert(svg.autofocus === true && svg.hasAttribute("autofocus"), "svg autofocus behavior"); + assert(svg.focusGroup === "grid" && svg.focusGroupStart === true, "svg focusgroup behavior"); + const math = document.createElementNS("http://www.w3.org/1998/Math/MathML", "math"); + math.focusGroup = "tablist inline"; + math.focusGroupStart = true; + assert( + math.focusGroup === "tablist inline" && math.focusGroupStart === true, + "MathML focusgroup behavior" + ); return "ok"; })() "#,