)
-
- if (tag === HostComponent && stateNode !== null) {
- lastHostComponent = stateNode; // createEventHandle listeners
-
- if (reactEventName !== null) {
- var listener = getListener(instance, reactEventName);
- if (listener != null) {
- listeners.push(createDispatchListener(instance, listener, lastHostComponent));
- }
- }
- } // If we are only accumulating events for the target, then we don't
- // continue to propagate through the React fiber tree to find other
- // listeners.
-
- if (accumulateTargetOnly) {
- break;
- } // If we are processing the onBeforeBlur event, then we need to take
-
- instance = instance.return;
- }
- return listeners;
- } // We should only use this function for:
- // - BeforeInputEventPlugin
- // - ChangeEventPlugin
- // - SelectEventPlugin
- // This is because we only process these plugins
- // in the bubble phase, so we need to accumulate two
- // phase event listeners (via emulation).
-
- function accumulateTwoPhaseListeners(targetFiber, reactName) {
- var captureName = reactName + 'Capture';
- var listeners = [];
- var instance = targetFiber; // Accumulate all instances and listeners via the target -> root path.
-
- while (instance !== null) {
- var _instance3 = instance,
- stateNode = _instance3.stateNode,
- tag = _instance3.tag; // Handle listeners that are on HostComponents (i.e.
)
-
- if (tag === HostComponent && stateNode !== null) {
- var currentTarget = stateNode;
- var captureListener = getListener(instance, captureName);
- if (captureListener != null) {
- listeners.unshift(createDispatchListener(instance, captureListener, currentTarget));
- }
- var bubbleListener = getListener(instance, reactName);
- if (bubbleListener != null) {
- listeners.push(createDispatchListener(instance, bubbleListener, currentTarget));
- }
- }
- instance = instance.return;
- }
- return listeners;
- }
- function getParent(inst) {
- if (inst === null) {
- return null;
- }
- do {
- inst = inst.return; // TODO: If this is a HostRoot we might want to bail out.
- // That is depending on if we want nested subtrees (layers) to bubble
- // events to their parent. We could also go through parentNode on the
- // host node but that wouldn't work for React Native and doesn't let us
- // do the portal feature.
- } while (inst && inst.tag !== HostComponent);
- if (inst) {
- return inst;
- }
- return null;
- }
- /**
- * Return the lowest common ancestor of A and B, or null if they are in
- * different trees.
- */
-
- function getLowestCommonAncestor(instA, instB) {
- var nodeA = instA;
- var nodeB = instB;
- var depthA = 0;
- for (var tempA = nodeA; tempA; tempA = getParent(tempA)) {
- depthA++;
- }
- var depthB = 0;
- for (var tempB = nodeB; tempB; tempB = getParent(tempB)) {
- depthB++;
- } // If A is deeper, crawl up.
-
- while (depthA - depthB > 0) {
- nodeA = getParent(nodeA);
- depthA--;
- } // If B is deeper, crawl up.
-
- while (depthB - depthA > 0) {
- nodeB = getParent(nodeB);
- depthB--;
- } // Walk in lockstep until we find a match.
-
- var depth = depthA;
- while (depth--) {
- if (nodeA === nodeB || nodeB !== null && nodeA === nodeB.alternate) {
- return nodeA;
- }
- nodeA = getParent(nodeA);
- nodeB = getParent(nodeB);
- }
- return null;
- }
- function accumulateEnterLeaveListenersForEvent(dispatchQueue, event, target, common, inCapturePhase) {
- var registrationName = event._reactName;
- var listeners = [];
- var instance = target;
- while (instance !== null) {
- if (instance === common) {
- break;
- }
- var _instance4 = instance,
- alternate = _instance4.alternate,
- stateNode = _instance4.stateNode,
- tag = _instance4.tag;
- if (alternate !== null && alternate === common) {
- break;
- }
- if (tag === HostComponent && stateNode !== null) {
- var currentTarget = stateNode;
- if (inCapturePhase) {
- var captureListener = getListener(instance, registrationName);
- if (captureListener != null) {
- listeners.unshift(createDispatchListener(instance, captureListener, currentTarget));
- }
- } else if (!inCapturePhase) {
- var bubbleListener = getListener(instance, registrationName);
- if (bubbleListener != null) {
- listeners.push(createDispatchListener(instance, bubbleListener, currentTarget));
- }
- }
- }
- instance = instance.return;
- }
- if (listeners.length !== 0) {
- dispatchQueue.push({
- event: event,
- listeners: listeners
- });
- }
- } // We should only use this function for:
- // - EnterLeaveEventPlugin
- // This is because we only process this plugin
- // in the bubble phase, so we need to accumulate two
- // phase event listeners.
-
- function accumulateEnterLeaveTwoPhaseListeners(dispatchQueue, leaveEvent, enterEvent, from, to) {
- var common = from && to ? getLowestCommonAncestor(from, to) : null;
- if (from !== null) {
- accumulateEnterLeaveListenersForEvent(dispatchQueue, leaveEvent, from, common, false);
- }
- if (to !== null && enterEvent !== null) {
- accumulateEnterLeaveListenersForEvent(dispatchQueue, enterEvent, to, common, true);
- }
- }
- function getListenerSetKey(domEventName, capture) {
- return domEventName + "__" + (capture ? 'capture' : 'bubble');
- }
- var didWarnInvalidHydration = false;
- var DANGEROUSLY_SET_INNER_HTML = 'dangerouslySetInnerHTML';
- var SUPPRESS_CONTENT_EDITABLE_WARNING = 'suppressContentEditableWarning';
- var SUPPRESS_HYDRATION_WARNING = 'suppressHydrationWarning';
- var AUTOFOCUS = 'autoFocus';
- var CHILDREN = 'children';
- var STYLE = 'style';
- var HTML$1 = '__html';
- var warnedUnknownTags;
- var validatePropertiesInDevelopment;
- var warnForPropDifference;
- var warnForExtraAttributes;
- var warnForInvalidEventListener;
- var canDiffStyleForHydrationWarning;
- var normalizeHTML;
- {
- warnedUnknownTags = {
- // There are working polyfills for . Let people use it.
- dialog: true,
- // Electron ships a custom tag to display external web content in
- // an isolated frame and process.
- // This tag is not present in non Electron environments such as JSDom which
- // is often used for testing purposes.
- // @see https://electronjs.org/docs/api/webview-tag
- webview: true
- };
- validatePropertiesInDevelopment = function (type, props) {
- validateProperties(type, props);
- validateProperties$1(type, props);
- validateProperties$2(type, props, {
- registrationNameDependencies: registrationNameDependencies,
- possibleRegistrationNames: possibleRegistrationNames
- });
- }; // IE 11 parses & normalizes the style attribute as opposed to other
- // browsers. It adds spaces and sorts the properties in some
- // non-alphabetical order. Handling that would require sorting CSS
- // properties in the client & server versions or applying
- // `expectedStyle` to a temporary DOM node to read its `style` attribute
- // normalized. Since it only affects IE, we're skipping style warnings
- // in that browser completely in favor of doing all that work.
- // See https://github.com/facebook/react/issues/11807
-
- canDiffStyleForHydrationWarning = canUseDOM && !document.documentMode;
- warnForPropDifference = function (propName, serverValue, clientValue) {
- if (didWarnInvalidHydration) {
- return;
- }
- var normalizedClientValue = normalizeMarkupForTextOrAttribute(clientValue);
- var normalizedServerValue = normalizeMarkupForTextOrAttribute(serverValue);
- if (normalizedServerValue === normalizedClientValue) {
- return;
- }
- didWarnInvalidHydration = true;
- error('Prop `%s` did not match. Server: %s Client: %s', propName, JSON.stringify(normalizedServerValue), JSON.stringify(normalizedClientValue));
- };
- warnForExtraAttributes = function (attributeNames) {
- if (didWarnInvalidHydration) {
- return;
- }
- didWarnInvalidHydration = true;
- var names = [];
- attributeNames.forEach(function (name) {
- names.push(name);
- });
- error('Extra attributes from the server: %s', names);
- };
- warnForInvalidEventListener = function (registrationName, listener) {
- if (listener === false) {
- error('Expected `%s` listener to be a function, instead got `false`.\n\n' + 'If you used to conditionally omit it with %s={condition && value}, ' + 'pass %s={condition ? value : undefined} instead.', registrationName, registrationName, registrationName);
- } else {
- error('Expected `%s` listener to be a function, instead got a value of `%s` type.', registrationName, typeof listener);
- }
- }; // Parse the HTML and read it back to normalize the HTML string so that it
- // can be used for comparison.
-
- normalizeHTML = function (parent, html) {
- // We could have created a separate document here to avoid
- // re-initializing custom elements if they exist. But this breaks
- // how is being handled. So we use the same document.
- // See the discussion in https://github.com/facebook/react/pull/11157.
- var testElement = parent.namespaceURI === HTML_NAMESPACE ? parent.ownerDocument.createElement(parent.tagName) : parent.ownerDocument.createElementNS(parent.namespaceURI, parent.tagName);
- testElement.innerHTML = html;
- return testElement.innerHTML;
- };
- } // HTML parsing normalizes CR and CRLF to LF.
- // It also can turn \u0000 into \uFFFD inside attributes.
- // https://www.w3.org/TR/html5/single-page.html#preprocessing-the-input-stream
- // If we have a mismatch, it might be caused by that.
- // We will still patch up in this case but not fire the warning.
-
- var NORMALIZE_NEWLINES_REGEX = /\r\n?/g;
- var NORMALIZE_NULL_AND_REPLACEMENT_REGEX = /\u0000|\uFFFD/g;
- function normalizeMarkupForTextOrAttribute(markup) {
- {
- checkHtmlStringCoercion(markup);
- }
- var markupString = typeof markup === 'string' ? markup : '' + markup;
- return markupString.replace(NORMALIZE_NEWLINES_REGEX, '\n').replace(NORMALIZE_NULL_AND_REPLACEMENT_REGEX, '');
- }
- function checkForUnmatchedText(serverText, clientText, isConcurrentMode, shouldWarnDev) {
- var normalizedClientText = normalizeMarkupForTextOrAttribute(clientText);
- var normalizedServerText = normalizeMarkupForTextOrAttribute(serverText);
- if (normalizedServerText === normalizedClientText) {
- return;
- }
- if (shouldWarnDev) {
- {
- if (!didWarnInvalidHydration) {
- didWarnInvalidHydration = true;
- error('Text content did not match. Server: "%s" Client: "%s"', normalizedServerText, normalizedClientText);
- }
- }
- }
- if (isConcurrentMode && enableClientRenderFallbackOnTextMismatch) {
- // In concurrent roots, we throw when there's a text mismatch and revert to
- // client rendering, up to the nearest Suspense boundary.
- throw new Error('Text content does not match server-rendered HTML.');
- }
- }
- function getOwnerDocumentFromRootContainer(rootContainerElement) {
- return rootContainerElement.nodeType === DOCUMENT_NODE ? rootContainerElement : rootContainerElement.ownerDocument;
- }
- function noop() {}
- function trapClickOnNonInteractiveElement(node) {
- // Mobile Safari does not fire properly bubble click events on
- // non-interactive elements, which means delegated click listeners do not
- // fire. The workaround for this bug involves attaching an empty click
- // listener on the target node.
- // https://www.quirksmode.org/blog/archives/2010/09/click_event_del.html
- // Just set it using the onclick property so that we don't have to manage any
- // bookkeeping for it. Not sure if we need to clear it when the listener is
- // removed.
- // TODO: Only do this for the relevant Safaris maybe?
- node.onclick = noop;
- }
- function setInitialDOMProperties(tag, domElement, rootContainerElement, nextProps, isCustomComponentTag) {
- for (var propKey in nextProps) {
- if (!nextProps.hasOwnProperty(propKey)) {
- continue;
- }
- var nextProp = nextProps[propKey];
- if (propKey === STYLE) {
- {
- if (nextProp) {
- // Freeze the next style object so that we can assume it won't be
- // mutated. We have already warned for this in the past.
- Object.freeze(nextProp);
- }
- } // Relies on `updateStylesByID` not mutating `styleUpdates`.
-
- setValueForStyles(domElement, nextProp);
- } else if (propKey === DANGEROUSLY_SET_INNER_HTML) {
- var nextHtml = nextProp ? nextProp[HTML$1] : undefined;
- if (nextHtml != null) {
- setInnerHTML(domElement, nextHtml);
- }
- } else if (propKey === CHILDREN) {
- if (typeof nextProp === 'string') {
- // Avoid setting initial textContent when the text is empty. In IE11 setting
- // textContent on a