[DOM] Handle blur on Fragments below Document (#37062)

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
Sebastian "Sebbie" Silbermann
2026-07-21 10:26:07 +02:00
committed by GitHub
co-authored by Hanzo Dev
parent ca4c265151
commit ce0ca3ecd0
2 changed files with 73 additions and 2 deletions
@@ -3232,8 +3232,11 @@ FragmentInstance.prototype.blur = function (this: FragmentInstanceType): void {
const parentInstanceOrContainer = getInstanceFromHostFiber<
Instance | Container,
>(parentHostFiber);
// TODO: Handle parentInstanceOrContainer being a document
const activeElement = parentInstanceOrContainer.ownerDocument.activeElement;
// Instance is included in the Container type for DOM.
const ownerDocument = getOwnerDocumentFromRootContainer(
parentInstanceOrContainer,
);
const activeElement = ownerDocument.activeElement;
if (
activeElement === null ||
!parentInstanceOrContainer.contains(activeElement)
@@ -0,0 +1,68 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @emails reactcore
* @jest-environment node
*/
'use strict';
let JSDOM;
let React;
let ReactDOMClient;
let act;
let document;
let Fragment;
describe('FragmentRefs', () => {
beforeEach(() => {
jest.resetModules();
JSDOM = require('jsdom');
React = require('react');
Fragment = React.Fragment;
ReactDOMClient = require('react-dom/client');
act = require('internal-test-utils').act;
const jsdom = new JSDOM.JSDOM('');
document = jsdom.window.document;
global.window = jsdom.window;
global.document = global.window.document;
});
describe('focus methods', () => {
describe('blur()', () => {
// @gate enableFragmentRefs
it('throws when the nearest host parent is a Document container', async () => {
const fragmentRef = React.createRef();
const root = ReactDOMClient.createRoot(document);
await act(() => {
root.render(
<Fragment ref={fragmentRef}>
<html>
<body>
<a id="child-a" href="/">
A
</a>
</body>
</html>
</Fragment>,
);
});
await act(() => {
fragmentRef.current.focus();
});
expect(document.activeElement.id).toEqual('child-a');
await act(() => {
fragmentRef.current.blur();
});
expect(document.activeElement).toEqual(document.body);
});
});
});
});