Commit f8224e8c authored by Kent Tamura's avatar Kent Tamura Committed by Commit Bot

Add a shadow element to each of menulist SELECTs

This CL introduces blink::MenuListInnerElement, which will replace the
anonymous block in LayoutMenuList. For now, we just add the element to
UA shadow tree with display:none. So this CL doesn't have any changes
on SELECT rendering.

* UpdateUserAgentShadowTree()
 Add MenuListInnerElement as the first child of ShadowRoot
 if UsesMenuList().
 Otherwise, remove it from the UA shadow tree.

* Update some test expectations for the new shadow element.

Bug: 1040828
Change-Id: I6c59c45dcc41baa41ff0e0ab060c14c2eefb6cff
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2032645Reviewed-by: default avatarKoji Ishii <kojii@chromium.org>
Commit-Queue: Kent Tamura <tkent@chromium.org>
Cr-Commit-Position: refs/heads/master@{#737248}
parent 10dc9c96
......@@ -391,6 +391,7 @@ TEST_P(ParameterizedTextOffsetMappingTest, RangeWithNestedPosition) {
TEST_P(ParameterizedTextOffsetMappingTest, RangeWithSelect) {
EXPECT_EQ(
"^<select>"
"<div></div>"
"<slot name=\"user-agent-custom-assign-slot\"></slot>"
"</select>foo|",
GetRange("<select>|</select>foo"));
......
......@@ -220,6 +220,8 @@ blink_core_sources("html") {
"forms/labels_node_list.h",
"forms/listed_element.cc",
"forms/listed_element.h",
"forms/menu_list_inner_element.cc",
"forms/menu_list_inner_element.h",
"forms/month_input_type.cc",
"forms/month_input_type.h",
"forms/multiple_fields_temporal_input_type_view.cc",
......
......@@ -58,6 +58,7 @@
#include "third_party/blink/renderer/core/html/forms/html_form_element.h"
#include "third_party/blink/renderer/core/html/forms/html_opt_group_element.h"
#include "third_party/blink/renderer/core/html/forms/html_option_element.h"
#include "third_party/blink/renderer/core/html/forms/menu_list_inner_element.h"
#include "third_party/blink/renderer/core/html/forms/popup_menu.h"
#include "third_party/blink/renderer/core/html/html_hr_element.h"
#include "third_party/blink/renderer/core/html/html_slot_element.h"
......@@ -317,6 +318,7 @@ void HTMLSelectElement::ParseAttribute(
if (size_ != old_size) {
ChangeRendering();
ResetToDefaultSelection();
UpdateUserAgentShadowTree(*UserAgentShadowRoot());
if (!UsesMenuList())
SaveListboxActiveSelection();
}
......@@ -1283,6 +1285,7 @@ void HTMLSelectElement::ParseMultipleAttribute(const AtomicString& value) {
else
ResetToDefaultSelection();
}
UpdateUserAgentShadowTree(*UserAgentShadowRoot());
}
void HTMLSelectElement::AppendToFormData(FormData& form_data) {
......@@ -1983,8 +1986,37 @@ void HTMLSelectElement::Trace(Visitor* visitor) {
}
void HTMLSelectElement::DidAddUserAgentShadowRoot(ShadowRoot& root) {
// Even if UsesMenuList(), the <slot> is necessary to have ComputedStyles
// for <option>s. LayoutMenuList::IsChildAllowed() rejects all of
// LayoutObject children except for MenuListInnerElement's.
root.AppendChild(
HTMLSlotElement::CreateUserAgentCustomAssignSlot(GetDocument()));
UpdateUserAgentShadowTree(root);
}
void HTMLSelectElement::UpdateUserAgentShadowTree(ShadowRoot& root) {
// Remove all children of the ShadowRoot except for <slot>.
Node* node = root.firstChild();
while (node) {
if (IsA<HTMLSlotElement>(node)) {
node = node->nextSibling();
} else {
auto* will_be_removed = node;
node = node->nextSibling();
will_be_removed->remove();
}
}
if (UsesMenuList()) {
root.insertBefore(MakeGarbageCollected<MenuListInnerElement>(GetDocument()),
root.firstChild());
}
}
Element& HTMLSelectElement::InnerElement() const {
DCHECK(UsesMenuList());
auto* inner_element = DynamicTo<Element>(UserAgentShadowRoot()->firstChild());
DCHECK(inner_element);
return *inner_element;
}
HTMLOptionElement* HTMLSelectElement::SpatialNavigationFocusedOption() {
......
......@@ -181,6 +181,9 @@ class CORE_EXPORT HTMLSelectElement final
void CloneNonAttributePropertiesFrom(const Element&,
CloneChildrenFlag) override;
// This should be called only if UsesMenuList().
Element& InnerElement() const;
private:
const AtomicString& FormControlType() const override;
void UpdateFromElement();
......@@ -299,6 +302,7 @@ class CORE_EXPORT HTMLSelectElement final
// Apply changes to rendering as a result of attribute changes (multiple,
// size).
void ChangeRendering();
void UpdateUserAgentShadowTree(ShadowRoot& root);
// list_items_ contains HTMLOptionElement, HTMLOptGroupElement, and
// HTMLHRElement objects.
......
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/core/html/forms/menu_list_inner_element.h"
#include "third_party/blink/renderer/core/dom/node_computed_style.h"
#include "third_party/blink/renderer/core/style/computed_style.h"
namespace blink {
MenuListInnerElement::MenuListInnerElement(Document& document)
: HTMLDivElement(document) {
SetHasCustomStyleCallbacks();
}
scoped_refptr<ComputedStyle>
MenuListInnerElement::CustomStyleForLayoutObject() {
const ComputedStyle& parent_style = OwnerShadowHost()->ComputedStyleRef();
scoped_refptr<ComputedStyle> style =
ComputedStyle::CreateAnonymousStyleWithDisplay(parent_style,
EDisplay::kNone);
return style;
}
} // namespace blink
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MENU_LIST_INNER_ELEMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MENU_LIST_INNER_ELEMENT_H_
#include "third_party/blink/renderer/core/html/html_div_element.h"
namespace blink {
class MenuListInnerElement : public HTMLDivElement {
public:
explicit MenuListInnerElement(Document& document);
private:
scoped_refptr<ComputedStyle> CustomStyleForLayoutObject() override;
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_FORMS_MENU_LIST_INNER_ELEMENT_H_
......@@ -64,6 +64,7 @@ Input before setting suggested values:
| <shadow:root>
| "TX"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......@@ -153,6 +154,7 @@ Input after setting suggestedValue:
| <shadow:root>
| "TX"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......@@ -240,6 +242,7 @@ After resetting suggestedValue value:
| <shadow:root>
| "TX"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......
......@@ -90,6 +90,7 @@ instead of "initial value".
| <shadow:root>
| "inserted value"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......
......@@ -43,7 +43,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"childNodeIndexes": [
4,
5,
33
34
],
"attributes": [
{
......@@ -67,11 +67,10 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"childNodeIndexes": [
6,
7,
13,
14,
17,
15,
18,
20,
19,
21,
22,
23,
......@@ -81,7 +80,8 @@ Tests DOMSnapshot.getSnapshot method returning input values.
27,
28,
29,
32
30,
33
],
"attributes": [
{
......@@ -103,18 +103,26 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"nodeValue": "",
"backendNodeId": "<number>",
"childNodeIndexes": [
8
8,
9
],
"layoutNodeIndex": 4
},
{
"nodeType": 1,
"nodeName": "DIV",
"nodeValue": "",
"backendNodeId": "<number>",
"shadowRootType": "user-agent"
},
{
"nodeType": 1,
"nodeName": "SLOT",
"nodeValue": "",
"backendNodeId": "<number>",
"childNodeIndexes": [
9,
11
10,
12
],
"attributes": [
{
......@@ -131,7 +139,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"optionSelected": true,
"backendNodeId": "<number>",
"childNodeIndexes": [
10
11
],
"attributes": [
{
......@@ -154,7 +162,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"optionSelected": false,
"backendNodeId": "<number>",
"childNodeIndexes": [
12
13
],
"attributes": [
{
......@@ -184,7 +192,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"inputValue": "InputValue",
"backendNodeId": "<number>",
"childNodeIndexes": [
15
16
],
"attributes": [
{
......@@ -205,7 +213,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"nodeValue": "",
"backendNodeId": "<number>",
"childNodeIndexes": [
16
17
],
"layoutNodeIndex": 7,
"shadowRootType": "user-agent",
......@@ -234,7 +242,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"inputValue": "ButtonValue",
"backendNodeId": "<number>",
"childNodeIndexes": [
19
20
],
"attributes": [
{
......@@ -403,7 +411,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"textValue": "TextAreaValue",
"backendNodeId": "<number>",
"childNodeIndexes": [
30
31
],
"attributes": [
{
......@@ -419,7 +427,7 @@ Tests DOMSnapshot.getSnapshot method returning input values.
"nodeValue": "",
"backendNodeId": "<number>",
"childNodeIndexes": [
31
32
],
"layoutNodeIndex": 22,
"shadowRootType": "user-agent",
......
......@@ -81,6 +81,7 @@ instead of "initial value".
| <shadow:root>
| "inserted value"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......
......@@ -90,6 +90,7 @@ instead of "initial value".
| <shadow:root>
| "inserted value"
| <shadow:root>
| <div>
| <slot>
| name="user-agent-custom-assign-slot"
| "input.value: initial value"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment