Backed out 8 changesets (bug 1413836) for delegatesFocus related wpt failures. CLOSED TREE

Backed out changeset 53c86681259e (bug 1413836)
Backed out changeset dc6a694146fd (bug 1413836)
Backed out changeset ae89d15d28eb (bug 1413836)
Backed out changeset 979fef259e32 (bug 1413836)
Backed out changeset d829be6f2813 (bug 1413836)
Backed out changeset c1d1d4b5ab74 (bug 1413836)
Backed out changeset 19e3256ea07c (bug 1413836)
Backed out changeset dc8d5d9533e4 (bug 1413836)
This commit is contained in:
Cosmin Sabou 2021-09-03 20:48:24 +03:00
parent 71a718fbc8
commit efbb4a2760
27 changed files with 182 additions and 323 deletions

View File

@ -1183,13 +1183,11 @@ already_AddRefed<ShadowRoot> Element::AttachShadow(const ShadowRootInit& aInit,
OwnerDoc()->ReportShadowDOMUsage();
}
return AttachShadowWithoutNameChecks(aInit.mMode, aInit.mDelegatesFocus,
aInit.mSlotAssignment);
return AttachShadowWithoutNameChecks(aInit.mMode, aInit.mSlotAssignment);
}
already_AddRefed<ShadowRoot> Element::AttachShadowWithoutNameChecks(
ShadowRootMode aMode, bool aDelegatesFocus,
SlotAssignmentMode aSlotAssignment) {
ShadowRootMode aMode, SlotAssignmentMode aSlotAssignment) {
nsAutoScriptBlocker scriptBlocker;
RefPtr<mozilla::dom::NodeInfo> nodeInfo =
@ -1217,8 +1215,8 @@ already_AddRefed<ShadowRoot> Element::AttachShadowWithoutNameChecks(
* and mode is init's mode.
*/
auto* nim = nodeInfo->NodeInfoManager();
RefPtr<ShadowRoot> shadowRoot = new (nim) ShadowRoot(
this, aMode, aDelegatesFocus, aSlotAssignment, nodeInfo.forget());
RefPtr<ShadowRoot> shadowRoot =
new (nim) ShadowRoot(this, aMode, aSlotAssignment, nodeInfo.forget());
if (NodeOrAncestorHasDirAuto()) {
shadowRoot->SetAncestorHasDirAuto();

View File

@ -1269,7 +1269,7 @@ class Element : public FragmentOrElement {
bool CanAttachShadowDOM() const;
already_AddRefed<ShadowRoot> AttachShadowWithoutNameChecks(
ShadowRootMode aMode, bool aDelegatesFocus = false,
ShadowRootMode aMode,
SlotAssignmentMode aSlotAssignmentMode = SlotAssignmentMode::Named);
// Attach UA Shadow Root if it is not attached.

View File

@ -48,12 +48,11 @@ NS_IMPL_ADDREF_INHERITED(ShadowRoot, DocumentFragment)
NS_IMPL_RELEASE_INHERITED(ShadowRoot, DocumentFragment)
ShadowRoot::ShadowRoot(Element* aElement, ShadowRootMode aMode,
bool aDelegatesFocus, SlotAssignmentMode aSlotAssignment,
SlotAssignmentMode aSlotAssignment,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo)
: DocumentFragment(std::move(aNodeInfo)),
DocumentOrShadowRoot(this),
mMode(aMode),
mDelegatesFocus(aDelegatesFocus),
mSlotAssignment(aSlotAssignment),
mIsUAWidget(false),
mIsAvailableToElementInternals(false) {
@ -752,41 +751,6 @@ void ShadowRoot::MaybeUnslotHostChild(nsIContent& aChild) {
slot->EnqueueSlotChangeEvent();
}
Element* ShadowRoot::GetFirstFocusable(bool aWithMouse) const {
for (nsIContent* child = GetFirstChild(); child;
child = child->GetNextNode()) {
if (auto* slot = HTMLSlotElement::FromNode(child)) {
const nsTArray<RefPtr<nsINode>>& assignedNodes = slot->AssignedNodes();
for (const auto& node : assignedNodes) {
if (node->IsElement()) {
Element* assignedElement = node->AsElement();
if (nsIFrame* frame = assignedElement->GetPrimaryFrame()) {
if (frame->IsFocusable(aWithMouse)) {
return assignedElement;
}
}
}
}
}
if (child->IsElement()) {
if (nsIFrame* frame = child->GetPrimaryFrame()) {
if (frame->IsFocusable(aWithMouse)) {
return child->AsElement();
}
}
}
if (ShadowRoot* root = child->GetShadowRoot()) {
if (Element* firstFocusable = root->GetFirstFocusable(aWithMouse)) {
return firstFocusable;
}
}
}
return nullptr;
}
void ShadowRoot::MaybeSlotHostChild(nsIContent& aChild) {
MOZ_ASSERT(aChild.GetParent() == GetHost());
// Check to ensure that the child not an anonymous subtree root because even

View File

@ -52,7 +52,7 @@ class ShadowRoot final : public DocumentFragment,
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ShadowRoot, DocumentFragment)
NS_DECL_ISUPPORTS_INHERITED
ShadowRoot(Element* aElement, ShadowRootMode aMode, bool aDelegatesFocus,
ShadowRoot(Element* aElement, ShadowRootMode aMode,
SlotAssignmentMode aSlotAssignment,
already_AddRefed<mozilla::dom::NodeInfo>&& aNodeInfo);
@ -67,10 +67,6 @@ class ShadowRoot final : public DocumentFragment,
// child from the currently-assigned slot, if any.
void MaybeUnslotHostChild(nsIContent&);
// Loop through this tree (including slot assigned elements, nested shadow
// trees) to find the first focusable element.
Element* GetFirstFocusable(bool aWithMouse) const;
// Shadow DOM v1
Element* Host() const {
MOZ_ASSERT(GetHost(),
@ -80,7 +76,6 @@ class ShadowRoot final : public DocumentFragment,
}
ShadowRootMode Mode() const { return mMode; }
bool DelegatesFocus() const { return mDelegatesFocus; }
SlotAssignmentMode SlotAssignment() const { return mSlotAssignment; }
bool IsClosed() const { return mMode == ShadowRootMode::Closed; }
@ -278,8 +273,6 @@ class ShadowRoot final : public DocumentFragment,
const ShadowRootMode mMode;
bool mDelegatesFocus;
const SlotAssignmentMode mSlotAssignment;
// The computed data from the style sheets.

View File

@ -1311,20 +1311,10 @@ void nsFocusManager::NotifyFocusStateChange(Element* aElement,
eventStateToAdd |= NS_EVENT_STATE_FOCUSRING;
}
aElement->AddStates(eventStateToAdd);
for (nsIContent* host = aElement->GetContainingShadowHost(); host;
host = host->GetContainingShadowHost()) {
host->AsElement()->AddStates(NS_EVENT_STATE_FOCUS);
}
} else {
EventStates eventStateToRemove =
NS_EVENT_STATE_FOCUS | NS_EVENT_STATE_FOCUSRING;
aElement->RemoveStates(eventStateToRemove);
for (nsIContent* host = aElement->GetContainingShadowHost(); host;
host = host->GetContainingShadowHost()) {
host->AsElement()->RemoveStates(NS_EVENT_STATE_FOCUS);
}
}
for (nsIContent* content = aElement; content && content != commonAncestor;
@ -2116,36 +2106,7 @@ Element* nsFocusManager::FlushAndCheckIfFocusable(Element* aElement,
}
}
if (frame->IsFocusable(aFlags & FLAG_BYMOUSE)) {
return aElement;
}
if (ShadowRoot* root = aElement->GetShadowRoot()) {
if (root->DelegatesFocus()) {
// If focus target is a shadow-including inclusive ancestor of the
// currently focused area of a top-level browsing context's DOM anchor,
// then return null.
if (nsPIDOMWindowInner* innerWindow =
aElement->OwnerDoc()->GetInnerWindow()) {
BrowsingContext* bc = innerWindow->GetBrowsingContext();
if (bc && bc->IsTop()) {
if (Element* focusedElement = innerWindow->GetFocusedElement()) {
if (focusedElement->IsShadowIncludingInclusiveDescendantOf(
aElement)) {
return nullptr;
}
}
}
}
if (Element* firstFocusable =
root->GetFirstFocusable(aFlags & FLAG_BYMOUSE)) {
return firstFocusable;
}
}
}
return nullptr;
return frame->IsFocusable(aFlags & FLAG_BYMOUSE) ? aElement : nullptr;
}
bool nsFocusManager::Blur(BrowsingContext* aBrowsingContextToClear,

View File

@ -3438,16 +3438,6 @@ nsresult EventStateManager::PostHandleEvent(nsPresContext* aPresContext,
if (frame->IsFocusable(/* aWithMouse = */ true)) {
break;
}
if (ShadowRoot* root = newFocus->GetShadowRoot()) {
if (root->DelegatesFocus()) {
if (Element* firstFocusable =
root->GetFirstFocusable(/* aWithMouse */ true)) {
newFocus = firstFocusable;
break;
}
}
}
}
MOZ_ASSERT_IF(newFocus, newFocus->IsElement());

View File

@ -2381,13 +2381,6 @@ void nsGenericHTMLElement::Click(CallerType aCallerType) {
bool nsGenericHTMLElement::IsHTMLFocusable(bool aWithMouse, bool* aIsFocusable,
int32_t* aTabIndex) {
if (ShadowRoot* root = GetShadowRoot()) {
if (root->DelegatesFocus()) {
*aIsFocusable = false;
return true;
}
}
Document* doc = GetComposedDoc();
if (!doc || doc->HasFlag(NODE_IS_EDITABLE)) {
// In designMode documents we only allow focusing the document.

View File

@ -260,8 +260,6 @@ partial interface Element {
// https://dom.spec.whatwg.org/#dictdef-shadowrootinit
dictionary ShadowRootInit {
required ShadowRootMode mode;
[Pref="dom.shadowdom.delegatesFocus.enabled"]
boolean delegatesFocus = false;
[Pref="dom.shadowdom.slot.assign.enabled"]
SlotAssignmentMode slotAssignment = "named";
};

View File

@ -24,8 +24,6 @@ interface ShadowRoot : DocumentFragment
{
// Shadow DOM v1
readonly attribute ShadowRootMode mode;
[Pref="dom.shadowdom.delegatesFocus.enabled"]
readonly attribute boolean delegatesFocus;
[Pref="dom.shadowdom.slot.assign.enabled"]
readonly attribute SlotAssignmentMode slotAssignment;
readonly attribute Element host;

View File

@ -3765,12 +3765,6 @@
value: @IS_NOT_ANDROID@
mirror: always
# Is the 'delegatesFocus' attribute for shadow dom
- name: dom.shadowdom.delegatesFocus.enabled
type: bool
value: true
mirror: always
# Is the 'assign' API for slot element enabled?
- name: dom.shadowdom.slot.assign.enabled
type: bool

View File

@ -0,0 +1,10 @@
[ShadowRoot-delegatesFocus.html]
[default delegatesFocus value]
expected: FAIL
[delegatesFocus set to false in init dict]
expected: FAIL
[delegatesFocus set to true in init dict]
expected: FAIL

View File

@ -0,0 +1,4 @@
[click-focus-delegatesFocus-tabindex-varies.html]
[click on host with delegatesFocus, #aboveSlot tabindex = 2, #slot and #slotted tabindex = 1]
expected: FAIL

View File

@ -0,0 +1,4 @@
[click-focus-delegatesFocus-tabindex-zero.html]
[click on host with delegatesFocus, all tabindex=0 except spacer]
expected: FAIL

View File

@ -0,0 +1,37 @@
[focus-method-delegatesFocus.html]
[focus() on host with delegatesFocus & tabindex=0, #outside with tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & tabindex=0, #aboveSlots and #belowSlots with tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & tabindex = 0, all other tabindex=-1]
expected: FAIL
[focus() on host with delegatesFocus, all tabindex=-1]
expected: FAIL
[focus() on host with delegatesFocus, all tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & tabindex=0, #belowSlots with tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & tabindex =-1, all other tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & no tabindex, all other tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus & tabindex=0, #aboveSlots with tabindex=0 and #belowSlots with tabindex=1]
expected: FAIL
[focus() on host with delegatesFocus & tabindex=0, #slottedToFirstSlot, #slottedToSecondSlot, #belowSlots with tabindex=0]
expected: FAIL
[focus() on host with delegatesFocus with another host with no delegatesFocus and a focusable child]
expected: FAIL
[focus() on host with delegatesFocus with another host with delegatesFocus and a focusable child]
expected: FAIL

View File

@ -0,0 +1,10 @@
[focus-pseudo-matches-on-shadow-host.html]
[:focus must match a shadow host with open mode shadow root that contains the focused element]
expected: FAIL
[:focus must not match a shadow host with closed mode shadow root that does not contain the focused element]
expected: FAIL
[:focus must match a shadow host with closed mode shadow root that contains the focused element]
expected: FAIL

View File

@ -0,0 +1,2 @@
[focus-pseudo-on-shadow-host-1.html]
expected: FAIL

View File

@ -0,0 +1,2 @@
[focus-pseudo-on-shadow-host-2.html]
expected: FAIL

View File

@ -0,0 +1,19 @@
[focus-selector-delegatesFocus.html]
[:focus applies to host with delegatesFocus=false when an element in a nested shadow tree with delegatesFocus=false is focused]
expected: FAIL
[:focus applies to host with delegatesFocus=true when an element in a nested shadow tree with delegatesFocus=true is focused]
expected: FAIL
[:focus applies to host with delegatesFocus=true when an element in a nested shadow tree with delegatesFocus=false is focused]
expected: FAIL
[:focus applies to host with delegatesFocus=false when an element in a nested shadow tree with delegatesFocus=true is focused]
expected: FAIL
[:focus applies to host with delegatesFocus=true when the shadow root's descendant has focus]
expected: FAIL
[:focus applies to host with delegatesFocus=false when the shadow root's descendant has focus]
expected: FAIL

View File

@ -0,0 +1,4 @@
[focus-tabindex-order-shadow-negative-delegatesFocus.html]
[Order when all tabindex=-1 is and delegatesFocus = true]
expected: FAIL

View File

@ -0,0 +1,4 @@
[focus-tabindex-order-shadow-varying-delegatesFocus.html]
[Order when tabindex varies and delegatesFocus = true]
expected: FAIL

View File

@ -0,0 +1,4 @@
[focus-tabindex-order-shadow-zero-delegatesFocus.html]
[Order when all tabindex=0 is and delegatesFocus = true]
expected: FAIL

View File

@ -0,0 +1,67 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: click on shadow host with delegatesFocus</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="resources/shadow-utils.js"></script>
<body>
<div id="host">
<div id="slotted">slotted</div>
</div>
<div id="outside">outside</div>
</body>
<script>
const host = document.getElementById("host");
const slotted = document.getElementById("slotted");
const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: true });
const aboveSlot = document.createElement("div");
aboveSlot.innerText = "aboveSlot";
const slot = document.createElement("slot");
shadowRoot.appendChild(aboveSlot);
shadowRoot.appendChild(slot);
const elementsInFlatTreeOrder = [host, aboveSlot, slot, slotted, outside];
// Final structure:
// <div #host> (delegatesFocus=true)
// #shadowRoot
// <div #aboveSlot>
// <slot #slot>
// (slotted) <div #slotted>
// <div #outside>
function setAllTabIndex(value) {
setTabIndex(elementsInFlatTreeOrder, value);
}
function removeAllTabIndex() {
removeTabIndex(elementsInFlatTreeOrder);
}
function resetTabIndexAndFocus() {
removeAllTabIndex();
resetFocus(document);
resetFocus(shadowRoot);
}
test(() => {
resetTabIndexAndFocus();
setAllTabIndex(0);
host.click();
assert_equals(shadowRoot.activeElement, null);
assert_equals(document.activeElement, document.body);
}, "call click() on host with delegatesFocus, all tabindex=0");
test(() => {
resetTabIndexAndFocus();
setAllTabIndex(0);
slotted.click();
assert_equals(shadowRoot.activeElement, null);
assert_equals(document.activeElement, document.body);
}, "call click() on slotted element in delegatesFocus shadow tree, all tabindex=0");
</script>

View File

@ -1,138 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: click on shadow host with delegatesFocus</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="resources/shadow-utils.js"></script>
<body>
<div id="host">
<div id="slotted">slotted</div>
</div>
<div id="outside">outside</div>
</body>
<script>
const host = document.getElementById("host");
const slotted = document.getElementById("slotted");
const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: true });
const aboveSlot = document.createElement("div");
aboveSlot.innerText = "aboveSlot";
const slot = document.createElement("slot");
shadowRoot.appendChild(aboveSlot);
shadowRoot.appendChild(slot);
const elementsInFlatTreeOrder = [host, aboveSlot, slot, slotted, outside];
// Final structure:
// <div #host> (delegatesFocus=true)
// #shadowRoot
// <div #aboveSlot>
// <slot #slot>
// (slotted) <div #slotted>
// <div #outside>
function setAllTabIndex(value) {
setTabIndex(elementsInFlatTreeOrder, value);
}
function removeAllTabIndex() {
removeTabIndex(elementsInFlatTreeOrder);
}
function resetTabIndexAndFocus() {
removeAllTabIndex();
resetFocus(document);
resetFocus(shadowRoot);
}
test(() => {
resetTabIndexAndFocus();
setAllTabIndex(0);
host.click();
assert_equals(shadowRoot.activeElement, null);
assert_equals(document.activeElement, document.body);
}, "call click() on host with delegatesFocus, all tabindex=0");
test(() => {
resetTabIndexAndFocus();
setAllTabIndex(0);
slotted.click();
assert_equals(shadowRoot.activeElement, null);
assert_equals(document.activeElement, document.body);
}, "call click() on slotted element in delegatesFocus shadow tree, all tabindex=0");
function createNestedHosts(outerDelegatesFocus, innerDelegatesFocus) {
// Structure:
// <div> outerHost
// <input> outerLightChild
// #shadowRoot outerShadow delegatesFocus=true
// <div> spacer
// <span> innerHost
// #shadowRoot innerShadow delegatesFocus=true/false
// <input> innerShadowChild
// <input> outerShadowChild
const outerHost = document.createElement('div');
const outerLightChild = document.createElement('input');
outerHost.appendChild(outerLightChild);
const innerHost = document.createElement('span');
const outerShadow = outerHost.attachShadow({mode: 'closed', delegatesFocus:outerDelegatesFocus});
const spacer = document.createElement("div");
spacer.style = "height: 1000px;";
outerShadow.appendChild(spacer);
outerShadow.appendChild(innerHost);
const outerShadowChild = document.createElement('input');
outerShadow.appendChild(outerShadowChild);
const innerShadow = innerHost.attachShadow({mode: 'closed', delegatesFocus:innerDelegatesFocus});
const innerShadowChild = document.createElement('input');
innerShadow.appendChild(innerShadowChild);
document.body.insertBefore(outerHost, document.body.firstChild);
return {outerHost: outerHost,
outerLightChild: outerLightChild,
outerShadow: outerShadow,
outerShadowChild: outerShadowChild,
innerHost: innerHost,
innerShadow: innerShadow,
innerShadowChild: innerShadowChild};
}
promise_test(async function() {
const dom = createNestedHosts(true, true);
await test_driver.click(dom.outerHost);
assert_equals(document.activeElement, dom.outerHost);
assert_equals(dom.outerShadow.activeElement, dom.innerHost);
assert_equals(dom.innerShadow.activeElement, dom.innerShadowChild);
}, "click on the host with delegatesFocus with another host with delegatesFocus and a focusable child");
promise_test(async function() {
const dom = createNestedHosts(true, false);
await test_driver.click(dom.outerHost);
assert_equals(document.activeElement, dom.outerHost);
assert_equals(dom.outerShadow.activeElement, dom.innerHost);
assert_equals(dom.innerShadow.activeElement, dom.innerShadowChild);
}, "click on the host with delegatesFocus with another host with no delegatesFocus and a focusable child");
promise_test(async function() {
const dom = createNestedHosts(false, true);
await test_driver.click(dom.outerHost);
assert_equals(document.activeElement, document.body);
assert_equals(dom.outerShadow.activeElement, null);
assert_equals(dom.innerShadow.activeElement, null);
}, "click on the host with no delegatesFocus with another host with delegatesFocus and a focusable child");
promise_test(async function() {
const dom = createNestedHosts(false, false);
await test_driver.click(dom.outerHost);
assert_equals(document.activeElement, document.body);
assert_equals(dom.outerShadow.activeElement, null);
assert_equals(dom.innerShadow.activeElement, null);
}, "click on the host with no delegatesFocus with another host with no delegatesFocus and a focusable child");
</script>

View File

@ -16,21 +16,11 @@
let focusedDefault = false;
function didFocusDefault() { }
function handleFocus() {
if (!focusedDefault) {
// Use step_timeout here to avoid nested focusing steps.
// For example, <input id="defaultFocus" autofocus> could run scripts
// while it's autofocusing which may run the tests, so that the
// focus() usage in the tests becomes nested focusing steps.
step_timeout(function() {
testInMode('open');
testInMode('closed');
}, 0);
}
function checkFocusMatch() {
focusedDefault = true;
didFocusDefault();
}
defaultFocus.addEventListener('focus', handleFocus);
defaultFocus.addEventListener('focus', checkFocusMatch);
function prepare(test)
{
@ -85,6 +75,9 @@ function testInMode(mode) {
}
testInMode('open');
testInMode('closed');
</script>
</body>
</html>

View File

@ -6,14 +6,13 @@
<link rel="help" href="https://html.spec.whatwg.org/#element-has-the-focus">
<link rel="help=" href="https://bugs.webkit.org/show_bug.cgi?id=202432">
<link rel="match" href="/css/reference/ref-filled-green-100px-square.xht">
<link rel="stylesheet" type="text/css" href="/fonts/ahem.css" >
</head>
<body>
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
<div id="host"><span>FAIL</span></div>
<style>
#host { background: green; width: 100px; height: 100px; }
#host span { background: red; font: 10px/1 Ahem; }
#host span { background: red; }
#host:focus span { background: green; color: green; }
</style>
<script>

View File

@ -11,8 +11,6 @@
</head>
<body>
<input>
<script>
function createFocusableDiv() {
const div = document.createElement("div");
@ -65,27 +63,7 @@ for (const delegatesFocus of delegatesFocusValues) {
assert_true(nestedShadowChild.matches(":focus"), "element in nested shadow tree matches :focus");
assert_true(nestedHost.matches(":focus"), "host of nested shadow tree matches focus");
assert_true(host.matches(":focus"), "topmost host matches focus");
}, `:focus applies to host with delegatesFocus=${delegatesFocus} when an element in a nested shadow tree with delegatesFocus=${nestedDelegatesFocus} is focused`);
test(() => {
resetFocus();
const host = createShadowHost(delegatesFocus, document.body);
const nestedHost = createShadowHost(nestedDelegatesFocus, host.shadowRoot);
const nestedShadowChild = createFocusableDiv();
nestedHost.shadowRoot.appendChild(nestedShadowChild);
// All nested shadow hosts should has :focus applied
nestedShadowChild.focus();
const elementOutsideOfShadowDOM = document.querySelector("input");
// Move the focus to an element which is outside of the nested
// shadow DOM trees
elementOutsideOfShadowDOM.focus();
assert_false(nestedShadowChild.matches(":focus"), "element in nested shadow tree doesn't matche :focus");
assert_false(nestedHost.matches(":focus"), "host of nested shadow tree doesn't match focus");
assert_false(host.matches(":focus"), "topmost host matches focus");
assert_true(elementOutsideOfShadowDOM.matches(":focus"), "The element outside of shadow dom matches :focus");
}, `:focus should be removed from hosts with delegatesFocus=${delegatesFocus} when none of the elements in a nested shadow tree with delegatesFocus=${nestedDelegatesFocus} is focused`);
}, `:focus applies to host with delegatesFocus=${delegatesFocus} when an element in a nested shadow tree with delegatesFocus=${nestedDelegatesFocus} is focused`);
}
}
</script>

View File

@ -1,29 +0,0 @@
<!DOCTYPE html>
<meta charset="utf-8">
<title>HTML Test: Use tab to navigate the focus to an element inside shadow host with delegatesFocus</title>
<script src="/resources/testharness.js"></script>
<script src="/resources/testharnessreport.js"></script>
<script src="/resources/testdriver.js"></script>
<script src="/resources/testdriver-vendor.js"></script>
<script src="resources/shadow-utils.js"></script>
<body>
<div id="host"></div>
</body>
<script>
const host = document.getElementById("host");
const shadowRoot = host.attachShadow({ mode: "open", delegatesFocus: true });
const input = document.createElement("input");
shadowRoot.appendChild(input);
promise_test(async function() {
assert_equals(document.activeElement, document.body);
// Press <tab>
await navigateFocusForward();
assert_equals(document.activeElement, host);
assert_equals(shadowRoot.activeElement, input);
assert_true(host.matches(':focus'));
}, ":focus should be applied to the host when the focus is moved by <tab>");
</script>