@samitouri / QOS-React / commits / cd515d7e22

Minor DOM FragmentInstance refactors (#35641)

Handles TODOs, small follow up refactors

Jack Pope committed Feb 11, 2026 at 10:03 UTC cd515d7e22636238adef912356f522168946313d
1 file changed +44 -26
packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
+44 -26
@@ -3056,13 +3056,16 @@ function indexOfEventListener(
3056 listener: EventListener,
3057 optionsOrUseCapture: void | EventListenerOptionsOrUseCapture,
3058 ): number {
3059 + if (eventListeners.length === 0) {
3060 + return -1;
3061 + }
3062 + const normalizedOptions = normalizeListenerOptions(optionsOrUseCapture);
3063 for (let i = 0; i < eventListeners.length; i++) {
3064 const item = eventListeners[i];
3065 if (
3066 item.type === type &&
3067 item.listener === listener &&
3064 - normalizeListenerOptions(item.optionsOrUseCapture) ===
3065 - normalizeListenerOptions(optionsOrUseCapture)
3068 + normalizeListenerOptions(item.optionsOrUseCapture) === normalizedOptions
3069 ) {
3070 return i;
3071 }
@@ -3154,18 +3157,34 @@ function collectChildren(child: Fiber, collection: Array<Fiber>): boolean {
3157 }
3158 // $FlowFixMe[prop-missing]
3159 FragmentInstance.prototype.blur = function (this: FragmentInstanceType): void {
3157 - // TODO: When we have a parent element reference, we can skip traversal if the fragment's parent
3158 - // does not contain document.activeElement
3160 + // Early exit if activeElement is not within the fragment's parent
3161 + const parentHostFiber = getFragmentParentHostFiber(this._fragmentFiber);
3162 + if (parentHostFiber === null) {
3163 + return;
3164 + }
3165 + const parentHostInstance =
3166 + getInstanceFromHostFiber<Instance>(parentHostFiber);
3167 + const activeElement = parentHostInstance.ownerDocument.activeElement;
3168 + if (activeElement === null || !parentHostInstance.contains(activeElement)) {
3169 + return;
3170 + }
3171 +
3172 traverseFragmentInstance(
3173 this._fragmentFiber,
3174 blurActiveElementWithinFragment,
3175 + activeElement,
3176 );
3177 };
3164 -function blurActiveElementWithinFragment(child: Fiber): boolean {
3165 - // TODO: We can get the activeElement from the parent outside of the loop when we have a reference.
3178 +function blurActiveElementWithinFragment(
3179 + child: Fiber,
3180 + activeElement: Element,
3181 +): boolean {
3182 + // Skip text nodes - they can't be focused
3183 + if (enableFragmentRefsTextNodes && child.tag === HostText) {
3184 + return false;
3185 + }
3186 const instance = getInstanceFromHostFiber<Instance>(child);
3167 - const ownerDocument = instance.ownerDocument;
3168 - if (instance === ownerDocument.activeElement) {
3187 + if (instance === activeElement) {
3188 // $FlowFixMe[prop-missing]
3189 instance.blur();
3190 return true;
@@ -3312,46 +3331,45 @@ FragmentInstance.prototype.compareDocumentPosition = function (
3331 );
3332 }
3333
3315 - const firstElement = getInstanceFromHostFiber<Instance>(children[0]);
3316 - const lastElement = getInstanceFromHostFiber<Instance>(
3334 + const firstNode = getInstanceFromHostFiber<Instance>(children[0]);
3335 + const lastNode = getInstanceFromHostFiber<Instance>(
3336 children[children.length - 1],
3337 );
3338
3339 // If the fragment has been portaled into another host instance, we need to
3340 // our best guess is to use the parent of the child instance, rather than
3341 // the fiber tree host parent.
3323 - const firstInstance = getInstanceFromHostFiber<Instance>(children[0]);
3342 const parentHostInstanceFromDOM = fiberIsPortaledIntoHost(this._fragmentFiber)
3325 - ? (firstInstance.parentElement: ?Instance)
3343 + ? (firstNode.parentElement: ?Instance)
3344 : parentHostInstance;
3345
3346 if (parentHostInstanceFromDOM == null) {
3347 return Node.DOCUMENT_POSITION_DISCONNECTED;
3348 }
3349
3332 - // Check if first and last element are actually in the expected document position
3333 - // before relying on them as source of truth for other contained elements
3334 - const firstElementIsContained =
3335 - parentHostInstanceFromDOM.compareDocumentPosition(firstElement) &
3350 + // Check if first and last node are actually in the expected document position
3351 + // before relying on them as source of truth for other contained nodes
3352 + const firstNodeIsContained =
3353 + parentHostInstanceFromDOM.compareDocumentPosition(firstNode) &
3354 Node.DOCUMENT_POSITION_CONTAINED_BY;
3337 - const lastElementIsContained =
3338 - parentHostInstanceFromDOM.compareDocumentPosition(lastElement) &
3355 + const lastNodeIsContained =
3356 + parentHostInstanceFromDOM.compareDocumentPosition(lastNode) &
3357 Node.DOCUMENT_POSITION_CONTAINED_BY;
3340 - const firstResult = firstElement.compareDocumentPosition(otherNode);
3341 - const lastResult = lastElement.compareDocumentPosition(otherNode);
3358 + const firstResult = firstNode.compareDocumentPosition(otherNode);
3359 + const lastResult = lastNode.compareDocumentPosition(otherNode);
3360
3361 const otherNodeIsFirstOrLastChild =
3344 - (firstElementIsContained && firstElement === otherNode) ||
3345 - (lastElementIsContained && lastElement === otherNode);
3362 + (firstNodeIsContained && firstNode === otherNode) ||
3363 + (lastNodeIsContained && lastNode === otherNode);
3364 const otherNodeIsFirstOrLastChildDisconnected =
3347 - (!firstElementIsContained && firstElement === otherNode) ||
3348 - (!lastElementIsContained && lastElement === otherNode);
3365 + (!firstNodeIsContained && firstNode === otherNode) ||
3366 + (!lastNodeIsContained && lastNode === otherNode);
3367 const otherNodeIsWithinFirstOrLastChild =
3368 firstResult & Node.DOCUMENT_POSITION_CONTAINED_BY ||
3369 lastResult & Node.DOCUMENT_POSITION_CONTAINED_BY;
3370 const otherNodeIsBetweenFirstAndLastChildren =
3353 - firstElementIsContained &&
3354 - lastElementIsContained &&
3371 + firstNodeIsContained &&
3372 + lastNodeIsContained &&
3373 firstResult & Node.DOCUMENT_POSITION_FOLLOWING &&
3374 lastResult & Node.DOCUMENT_POSITION_PRECEDING;
3375