Skip to content
93 changes: 55 additions & 38 deletions packages/react-dom-bindings/src/client/ReactFiberConfigDOM.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ import {
getFragmentInstanceOrTextInstanceSiblings,
traverseFragmentInstancesAndTextInstancesDeeply,
fiberIsPortaledIntoHost,
getFragmentPortalContainerInfo,
isFiberContainedByFragment,
isFragmentContainedByFiber,
} from 'react-reconciler/src/ReactFiberTreeReflection';
Expand Down Expand Up @@ -3073,24 +3074,23 @@ FragmentInstance.prototype.removeEventListener = function (
if (listeners === null) {
return;
}
if (typeof listeners !== 'undefined' && listeners.length > 0) {
traverseFragmentInstancesAndTextInstances(
this._fragmentFiber,
removeEventListenerFromChild,
type,
listener,
optionsOrUseCapture,
);
const index = indexOfEventListener(
listeners,
type,
listener,
optionsOrUseCapture,
);
if (this._eventListeners !== null) {
this._eventListeners.splice(index, 1);
}
const index = indexOfEventListener(
listeners,
type,
listener,
optionsOrUseCapture,
);
if (index === -1) {
return;
}
traverseFragmentInstancesAndTextInstances(
this._fragmentFiber,
removeEventListenerFromChild,
type,
listener,
optionsOrUseCapture,
);
listeners.splice(index, 1);
};
function removeEventListenerFromChild(
child: Fiber,
Expand Down Expand Up @@ -3156,7 +3156,14 @@ FragmentInstance.prototype.dispatchEvent = function (
(eventListeners !== null && eventListeners.length > 0) ||
!event.bubbles
) {
const temp = document.createTextNode('');
// The temporary node stands in for the fragment's position so that its own
// listeners fire before the event propagates to the parent. A Document can
// only hold comments and processing instructions alongside its
// documentElement, so a Text node would be an invalid child there.
const temp =
parentHostInstance.nodeType === DOCUMENT_NODE
? (parentHostInstance as any as Document).createComment('')
: document.createTextNode('');
if (eventListeners) {
for (let i = 0; i < eventListeners.length; i++) {
const {type, listener, optionsOrUseCapture} = eventListeners[i];
Expand Down Expand Up @@ -3225,7 +3232,6 @@ function collectChildren(child: Fiber, collection: Array<Fiber>): boolean {
}
// $FlowFixMe[prop-missing]
FragmentInstance.prototype.blur = function (this: FragmentInstanceType): void {
// Early exit if activeElement is not within the fragment's parent
const parentHostFiber = getFragmentParentInstanceOrContainerFiber(
this._fragmentFiber,
);
Expand All @@ -3240,13 +3246,9 @@ FragmentInstance.prototype.blur = function (this: FragmentInstanceType): void {
parentInstanceOrContainer,
);
const activeElement = ownerDocument.activeElement;
if (
activeElement === null ||
!parentInstanceOrContainer.contains(activeElement)
) {
if (activeElement === null) {
return;
}

traverseFragmentInstancesAndTextInstances(
this._fragmentFiber,
blurActiveElementWithinFragment,
Expand Down Expand Up @@ -3426,9 +3428,20 @@ FragmentInstance.prototype.compareDocumentPosition = function (
);

if (children.length === 0) {
// Match non-empty CDP: when portaled, position against the portal
// container rather than the React host parent.
let emptyParentHostInstance = parentHostInstance;
if (fiberIsPortaledIntoHost(this._fragmentFiber)) {
const portalContainer = getFragmentPortalContainerInfo(
this._fragmentFiber,
);
if (portalContainer != null) {
emptyParentHostInstance = portalContainer;
}
}
return compareDocumentPositionForEmptyFragment(
this._fragmentFiber,
parentHostInstance,
emptyParentHostInstance,
otherNode,
getInstanceFromHostFiber,
);
Expand Down Expand Up @@ -3531,10 +3544,13 @@ function validateDocumentPositionWithFiberTree(
}
if (documentPosition & Node.DOCUMENT_POSITION_CONTAINS) {
if (otherFiber === null) {
// otherFiber could be null if its the document or body element
// otherFiber could be null if its the document, documentElement, or body
const ownerDocument = otherNode.ownerDocument;
// $FlowFixMe[invalid-compare]
return otherNode === ownerDocument || otherNode === ownerDocument.body;
return (
(otherNode as Instance | Document) === ownerDocument ||
otherNode === ownerDocument.documentElement ||
otherNode === ownerDocument.body
);
}
return isFragmentContainedByFiber(fragmentFiber, otherFiber);
}
Expand Down Expand Up @@ -3711,17 +3727,18 @@ export function commitNewChildToFragmentInstance(
childInstance: InstanceWithFragmentHandles | Text,
fragmentInstance: FragmentInstanceType,
): void {
if (childInstance.nodeType === TEXT_NODE) {
return;
}
const instance: InstanceWithFragmentHandles = childInstance as any;
const eventListeners = fragmentInstance._eventListeners;
if (eventListeners !== null) {
for (let i = 0; i < eventListeners.length; i++) {
const {type, listener, optionsOrUseCapture} = eventListeners[i];
instance.addEventListener(type, listener, optionsOrUseCapture);
childInstance.addEventListener(type, listener, optionsOrUseCapture);
}
}
// Observers and fragment handles only apply to element children.
if (childInstance.nodeType === TEXT_NODE) {
return;
}
const instance: InstanceWithFragmentHandles = childInstance as any;
if (fragmentInstance._observers !== null) {
fragmentInstance._observers.forEach(observer => {
observer.observe(instance);
Expand All @@ -3736,17 +3753,17 @@ export function deleteChildFromFragmentInstance(
childInstance: InstanceWithFragmentHandles | Text,
fragmentInstance: FragmentInstanceType,
): void {
if (childInstance.nodeType === TEXT_NODE) {
return;
}
const instance: InstanceWithFragmentHandles = childInstance as any;
const eventListeners = fragmentInstance._eventListeners;
if (eventListeners !== null) {
for (let i = 0; i < eventListeners.length; i++) {
const {type, listener, optionsOrUseCapture} = eventListeners[i];
instance.removeEventListener(type, listener, optionsOrUseCapture);
childInstance.removeEventListener(type, listener, optionsOrUseCapture);
}
}
if (childInstance.nodeType === TEXT_NODE) {
return;
}
const instance: InstanceWithFragmentHandles = childInstance as any;
if (enableFragmentRefsInstanceHandles) {
if (instance.reactFragments != null) {
instance.reactFragments.delete(fragmentInstance);
Expand Down
Loading
Loading