/** * 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. * * @noflow * @nolint * @preventMunge * @preserve-invariant-messages */ "use strict"; if (__DEV__) { (function () { "use strict"; var Scheduler = require("scheduler"); var React = require("react"); var assign = Object.assign; // This refers to a WWW module. var warningWWW = require("warning"); var suppressWarning = false; function setSuppressWarning(newSuppressWarning) { { suppressWarning = newSuppressWarning; } } function warn(format) { { if (!suppressWarning) { for ( var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++ ) { args[_key - 1] = arguments[_key]; } printWarning("warn", format, args); } } } function error(format) { { if (!suppressWarning) { for ( var _len2 = arguments.length, args = new Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++ ) { args[_key2 - 1] = arguments[_key2]; } printWarning("error", format, args); } } } function printWarning(level, format, args) { { var React = require("react"); var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Defensive in case this is fired before React is initialized. if (ReactSharedInternals != null) { var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; var stack = ReactDebugCurrentFrame.getStackAddendum(); if (stack !== "") { format += "%s"; args.push(stack); } } // TODO: don't ignore level and pass it down somewhere too. args.unshift(format); args.unshift(false); warningWWW.apply(null, args); } } /** * `ReactInstanceMap` maintains a mapping from a public facing stateful * instance (key) and the internal representation (value). This allows public * methods to accept the user facing instance as an argument and map them back * to internal methods. * * Note that this module is currently shared and assumed to be stateless. * If this becomes an actual Map, that will break. */ function get(key) { return key._reactInternals; } function has(key) { return key._reactInternals !== undefined; } function set(key, value) { key._reactInternals = value; } var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED; // Re-export dynamic flags from the www version. var dynamicFeatureFlags = require("ReactFeatureFlags"); var disableInputAttributeSyncing = dynamicFeatureFlags.disableInputAttributeSyncing, disableIEWorkarounds = dynamicFeatureFlags.disableIEWorkarounds, enableTrustedTypesIntegration = dynamicFeatureFlags.enableTrustedTypesIntegration, replayFailedUnitOfWorkWithInvokeGuardedCallback = dynamicFeatureFlags.replayFailedUnitOfWorkWithInvokeGuardedCallback, enableLegacyFBSupport = dynamicFeatureFlags.enableLegacyFBSupport, enableDebugTracing = dynamicFeatureFlags.enableDebugTracing, enableUseRefAccessWarning = dynamicFeatureFlags.enableUseRefAccessWarning, enableLazyContextPropagation = dynamicFeatureFlags.enableLazyContextPropagation, enableUnifiedSyncLane = dynamicFeatureFlags.enableUnifiedSyncLane, enableRetryLaneExpiration = dynamicFeatureFlags.enableRetryLaneExpiration, enableTransitionTracing = dynamicFeatureFlags.enableTransitionTracing, enableDeferRootSchedulingToMicrotask = dynamicFeatureFlags.enableDeferRootSchedulingToMicrotask, alwaysThrottleRetries = dynamicFeatureFlags.alwaysThrottleRetries, enableDO_NOT_USE_disableStrictPassiveEffect = dynamicFeatureFlags.enableDO_NOT_USE_disableStrictPassiveEffect, disableSchedulerTimeoutInWorkLoop = dynamicFeatureFlags.disableSchedulerTimeoutInWorkLoop, enableUseDeferredValueInitialArg = dynamicFeatureFlags.enableUseDeferredValueInitialArg, retryLaneExpirationMs = dynamicFeatureFlags.retryLaneExpirationMs, syncLaneExpirationMs = dynamicFeatureFlags.syncLaneExpirationMs, transitionLaneExpirationMs = dynamicFeatureFlags.transitionLaneExpirationMs, enableInfiniteRenderLoopDetection = dynamicFeatureFlags.enableInfiniteRenderLoopDetection, enableRenderableContext = dynamicFeatureFlags.enableRenderableContext, useModernStrictMode = dynamicFeatureFlags.useModernStrictMode; // On WWW, false is used for a new modern build. var enableProfilerTimer = true; var enableProfilerCommitHooks = true; var enableProfilerNestedUpdatePhase = true; var enableProfilerNestedUpdateScheduledHook = dynamicFeatureFlags.enableProfilerNestedUpdateScheduledHook; var enableClientRenderFallbackOnTextMismatch = false; var enableFormActions = true; var enableAsyncActions = true; // Logs additional User Timing API marks for use with an experimental profiling tool. var enableSchedulingProfiler = dynamicFeatureFlags.enableSchedulingProfiler; var enableSuspenseCallback = true; var FunctionComponent = 0; var ClassComponent = 1; var IndeterminateComponent = 2; // Before we know whether it is function or class var HostRoot = 3; // Root of a host tree. Could be nested inside another node. var HostPortal = 4; // A subtree. Could be an entry point to a different renderer. var HostComponent = 5; var HostText = 6; var Fragment = 7; var Mode = 8; var ContextConsumer = 9; var ContextProvider = 10; var ForwardRef = 11; var Profiler = 12; var SuspenseComponent = 13; var MemoComponent = 14; var SimpleMemoComponent = 15; var LazyComponent = 16; var IncompleteClassComponent = 17; var DehydratedFragment = 18; var SuspenseListComponent = 19; var ScopeComponent = 21; var OffscreenComponent = 22; var LegacyHiddenComponent = 23; var CacheComponent = 24; var TracingMarkerComponent = 25; var HostHoistable = 26; var HostSingleton = 27; // ATTENTION // When adding new symbols to this file, // Please consider also adding to 'react-devtools-shared/src/backend/ReactSymbols' // The Symbol used to tag the ReactElement-like types. var REACT_ELEMENT_TYPE = Symbol.for("react.element"); var REACT_PORTAL_TYPE = Symbol.for("react.portal"); var REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); var REACT_STRICT_MODE_TYPE = Symbol.for("react.strict_mode"); var REACT_PROFILER_TYPE = Symbol.for("react.profiler"); var REACT_PROVIDER_TYPE = Symbol.for("react.provider"); // TODO: Delete with enableRenderableContext var REACT_CONSUMER_TYPE = Symbol.for("react.consumer"); var REACT_CONTEXT_TYPE = Symbol.for("react.context"); var REACT_FORWARD_REF_TYPE = Symbol.for("react.forward_ref"); var REACT_SUSPENSE_TYPE = Symbol.for("react.suspense"); var REACT_SUSPENSE_LIST_TYPE = Symbol.for("react.suspense_list"); var REACT_MEMO_TYPE = Symbol.for("react.memo"); var REACT_LAZY_TYPE = Symbol.for("react.lazy"); var REACT_SCOPE_TYPE = Symbol.for("react.scope"); var REACT_DEBUG_TRACING_MODE_TYPE = Symbol.for("react.debug_trace_mode"); var REACT_OFFSCREEN_TYPE = Symbol.for("react.offscreen"); var REACT_LEGACY_HIDDEN_TYPE = Symbol.for("react.legacy_hidden"); var REACT_CACHE_TYPE = Symbol.for("react.cache"); var REACT_TRACING_MARKER_TYPE = Symbol.for("react.tracing_marker"); var REACT_MEMO_CACHE_SENTINEL = Symbol.for("react.memo_cache_sentinel"); var MAYBE_ITERATOR_SYMBOL = Symbol.iterator; var FAUX_ITERATOR_SYMBOL = "@@iterator"; function getIteratorFn(maybeIterable) { if (maybeIterable === null || typeof maybeIterable !== "object") { return null; } var maybeIterator = (MAYBE_ITERATOR_SYMBOL && maybeIterable[MAYBE_ITERATOR_SYMBOL]) || maybeIterable[FAUX_ITERATOR_SYMBOL]; if (typeof maybeIterator === "function") { return maybeIterator; } return null; } function getWrappedName$1(outerType, innerType, wrapperName) { var displayName = outerType.displayName; if (displayName) { return displayName; } var functionName = innerType.displayName || innerType.name || ""; return functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName; } // Keep in sync with react-reconciler/getComponentNameFromFiber function getContextName$1(type) { return type.displayName || "Context"; } var REACT_CLIENT_REFERENCE = Symbol.for("react.client.reference"); // Note that the reconciler package should generally prefer to use getComponentNameFromFiber() instead. function getComponentNameFromType(type) { if (type == null) { // Host root, text node or just invalid type. return null; } if (typeof type === "function") { if (type.$$typeof === REACT_CLIENT_REFERENCE) { // TODO: Create a convention for naming client references with debug info. return null; } return type.displayName || type.name || null; } if (typeof type === "string") { return type; } switch (type) { case REACT_FRAGMENT_TYPE: return "Fragment"; case REACT_PORTAL_TYPE: return "Portal"; case REACT_PROFILER_TYPE: return "Profiler"; case REACT_STRICT_MODE_TYPE: return "StrictMode"; case REACT_SUSPENSE_TYPE: return "Suspense"; case REACT_SUSPENSE_LIST_TYPE: return "SuspenseList"; case REACT_CACHE_TYPE: { return "Cache"; } // Fall through case REACT_TRACING_MARKER_TYPE: if (enableTransitionTracing) { return "TracingMarker"; } } if (typeof type === "object") { { if (typeof type.tag === "number") { error( "Received an unexpected object in getComponentNameFromType(). " + "This is likely a bug in React. Please file an issue." ); } } switch (type.$$typeof) { case REACT_PROVIDER_TYPE: if (enableRenderableContext) { return null; } else { var provider = type; return getContextName$1(provider._context) + ".Provider"; } case REACT_CONTEXT_TYPE: var context = type; if (enableRenderableContext) { return getContextName$1(context) + ".Provider"; } else { return getContextName$1(context) + ".Consumer"; } case REACT_CONSUMER_TYPE: if (enableRenderableContext) { var consumer = type; return getContextName$1(consumer._context) + ".Consumer"; } else { return null; } case REACT_FORWARD_REF_TYPE: return getWrappedName$1(type, type.render, "ForwardRef"); case REACT_MEMO_TYPE: var outerName = type.displayName || null; if (outerName !== null) { return outerName; } return getComponentNameFromType(type.type) || "Memo"; case REACT_LAZY_TYPE: { var lazyComponent = type; var payload = lazyComponent._payload; var init = lazyComponent._init; try { return getComponentNameFromType(init(payload)); } catch (x) { return null; } } } } return null; } function getWrappedName(outerType, innerType, wrapperName) { var functionName = innerType.displayName || innerType.name || ""; return ( outerType.displayName || (functionName !== "" ? wrapperName + "(" + functionName + ")" : wrapperName) ); } // Keep in sync with shared/getComponentNameFromType function getContextName(type) { return type.displayName || "Context"; } function getComponentNameFromFiber(fiber) { var tag = fiber.tag, type = fiber.type; switch (tag) { case CacheComponent: return "Cache"; case ContextConsumer: if (enableRenderableContext) { var consumer = type; return getContextName(consumer._context) + ".Consumer"; } else { var context = type; return getContextName(context) + ".Consumer"; } case ContextProvider: if (enableRenderableContext) { var _context = type; return getContextName(_context) + ".Provider"; } else { var provider = type; return getContextName(provider._context) + ".Provider"; } case DehydratedFragment: return "DehydratedFragment"; case ForwardRef: return getWrappedName(type, type.render, "ForwardRef"); case Fragment: return "Fragment"; case HostHoistable: case HostSingleton: case HostComponent: // Host component type is the display name (e.g. "div", "View") return type; case HostPortal: return "Portal"; case HostRoot: return "Root"; case HostText: return "Text"; case LazyComponent: // Name comes from the type in this case; we don't have a tag. return getComponentNameFromType(type); case Mode: if (type === REACT_STRICT_MODE_TYPE) { // Don't be less specific than shared/getComponentNameFromType return "StrictMode"; } return "Mode"; case OffscreenComponent: return "Offscreen"; case Profiler: return "Profiler"; case ScopeComponent: return "Scope"; case SuspenseComponent: return "Suspense"; case SuspenseListComponent: return "SuspenseList"; case TracingMarkerComponent: return "TracingMarker"; // The display name for this tags come from the user-provided type: case ClassComponent: case FunctionComponent: case IncompleteClassComponent: case IndeterminateComponent: case MemoComponent: case SimpleMemoComponent: if (typeof type === "function") { return type.displayName || type.name || null; } if (typeof type === "string") { return type; } break; case LegacyHiddenComponent: { return "LegacyHidden"; } } return null; } var NoFlags$1 = /* */ 0; var PerformedWork = /* */ 1; var Placement = /* */ 2; var DidCapture = /* */ 128; var Hydrating = /* */ 4096; // You can change the rest (and add more). var Update = /* */ 4; /* Skipped value: 0b0000000000000000000000001000; */ var ChildDeletion = /* */ 16; var ContentReset = /* */ 32; var Callback = /* */ 64; /* Used by DidCapture: 0b0000000000000000000010000000; */ var ForceClientRender = /* */ 256; var Ref = /* */ 512; var Snapshot = /* */ 1024; var Passive$1 = /* */ 2048; /* Used by Hydrating: 0b0000000000000001000000000000; */ var Visibility = /* */ 8192; var StoreConsistency = /* */ 16384; // It's OK to reuse these bits because these flags are mutually exclusive for // different fiber types. We should really be doing this for as many flags as // possible, because we're about to run out of bits. var ScheduleRetry = StoreConsistency; var ShouldSuspendCommit = Visibility; var DidDefer = ContentReset; var LifecycleEffectMask = Passive$1 | Update | Callback | Ref | Snapshot | StoreConsistency; // Union of all commit flags (flags with the lifetime of a particular commit) var HostEffectMask = /* */ 32767; // These are not really side effects, but we still reuse this field. var Incomplete = /* */ 32768; var ShouldCapture = /* */ 65536; var ForceUpdateForLegacySuspense = /* */ 131072; var DidPropagateContext = /* */ 262144; var NeedsPropagation = /* */ 524288; var Forked = /* */ 1048576; // Static tags describe aspects of a fiber that are not specific to a render, // e.g. a fiber uses a passive effect (even if there are no updates on this particular render). // This enables us to defer more work in the unmount case, // since we can defer traversing the tree during layout to look for Passive effects, // and instead rely on the static flag as a signal that there may be cleanup work. var RefStatic = /* */ 2097152; var LayoutStatic = /* */ 4194304; var PassiveStatic = /* */ 8388608; var MaySuspendCommit = /* */ 16777216; // Flag used to identify newly inserted fibers. It isn't reset after commit unlike `Placement`. var PlacementDEV = /* */ 33554432; var MountLayoutDev = /* */ 67108864; var MountPassiveDev = /* */ 134217728; // Groups of flags that are used in the commit phase to skip over trees that // don't contain effects, by checking subtreeFlags. var BeforeMutationMask = // TODO: Remove Update flag from before mutation phase by re-landing Visibility // flag logic (see #20043) Update | Snapshot | // createEventHandle needs to visit deleted and hidden trees to // fire beforeblur // TODO: Only need to visit Deletions during BeforeMutation phase if an // element is focused. (ChildDeletion | Visibility); var MutationMask = Placement | Update | ChildDeletion | ContentReset | Ref | Hydrating | Visibility; var LayoutMask = Update | Callback | Ref | Visibility; // TODO: Split into PassiveMountMask and PassiveUnmountMask var PassiveMask = Passive$1 | Visibility | ChildDeletion; // Union of tags that don't get reset on clones. // This allows certain concepts to persist without recalculating them, // e.g. whether a subtree contains passive effects or portals. var StaticMask = LayoutStatic | PassiveStatic | RefStatic | MaySuspendCommit; var ReactCurrentOwner$3 = ReactSharedInternals.ReactCurrentOwner; function getNearestMountedFiber(fiber) { var node = fiber; var nearestMounted = fiber; if (!fiber.alternate) { // If there is no alternate, this might be a new tree that isn't inserted // yet. If it is, then it will have a pending insertion effect on it. var nextNode = node; do { node = nextNode; if ((node.flags & (Placement | Hydrating)) !== NoFlags$1) { // This is an insertion or in-progress hydration. The nearest possible // mounted fiber is the parent but we need to continue to figure out // if that one is still mounted. nearestMounted = node.return; } // $FlowFixMe[incompatible-type] we bail out when we get a null nextNode = node.return; } while (nextNode); } else { while (node.return) { node = node.return; } } if (node.tag === HostRoot) { // TODO: Check if this was a nested HostRoot when used with // renderContainerIntoSubtree. return nearestMounted; } // If we didn't hit the root, that means that we're in an disconnected tree // that has been unmounted. return null; } function getSuspenseInstanceFromFiber(fiber) { if (fiber.tag === SuspenseComponent) { var suspenseState = fiber.memoizedState; if (suspenseState === null) { var current = fiber.alternate; if (current !== null) { suspenseState = current.memoizedState; } } if (suspenseState !== null) { return suspenseState.dehydrated; } } return null; } function getContainerFromFiber(fiber) { return fiber.tag === HostRoot ? fiber.stateNode.containerInfo : null; } function isFiberMounted(fiber) { return getNearestMountedFiber(fiber) === fiber; } function isMounted(component) { { var owner = ReactCurrentOwner$3.current; if (owner !== null && owner.tag === ClassComponent) { var ownerFiber = owner; var instance = ownerFiber.stateNode; if (!instance._warnedAboutRefsInRender) { error( "%s is accessing isMounted inside its render() function. " + "render() should be a pure function of props and state. It should " + "never access something that requires stale data from the previous " + "render, such as refs. Move this logic to componentDidMount and " + "componentDidUpdate instead.", getComponentNameFromFiber(ownerFiber) || "A component" ); } instance._warnedAboutRefsInRender = true; } } var fiber = get(component); if (!fiber) { return false; } return getNearestMountedFiber(fiber) === fiber; } function assertIsMounted(fiber) { if (getNearestMountedFiber(fiber) !== fiber) { throw new Error("Unable to find node on an unmounted component."); } } function findCurrentFiberUsingSlowPath(fiber) { var alternate = fiber.alternate; if (!alternate) { // If there is no alternate, then we only need to check if it is mounted. var nearestMounted = getNearestMountedFiber(fiber); if (nearestMounted === null) { throw new Error("Unable to find node on an unmounted component."); } if (nearestMounted !== fiber) { return null; } return fiber; } // If we have two possible branches, we'll walk backwards up to the root // to see what path the root points to. On the way we may hit one of the // special cases and we'll deal with them. var a = fiber; var b = alternate; while (true) { var parentA = a.return; if (parentA === null) { // We're at the root. break; } var parentB = parentA.alternate; if (parentB === null) { // There is no alternate. This is an unusual case. Currently, it only // happens when a Suspense component is hidden. An extra fragment fiber // is inserted in between the Suspense fiber and its children. Skip // over this extra fragment fiber and proceed to the next parent. var nextParent = parentA.return; if (nextParent !== null) { a = b = nextParent; continue; } // If there's no parent, we're at the root. break; } // If both copies of the parent fiber point to the same child, we can // assume that the child is current. This happens when we bailout on low // priority: the bailed out fiber's child reuses the current child. if (parentA.child === parentB.child) { var child = parentA.child; while (child) { if (child === a) { // We've determined that A is the current branch. assertIsMounted(parentA); return fiber; } if (child === b) { // We've determined that B is the current branch. assertIsMounted(parentA); return alternate; } child = child.sibling; } // We should never have an alternate for any mounting node. So the only // way this could possibly happen is if this was unmounted, if at all. throw new Error("Unable to find node on an unmounted component."); } if (a.return !== b.return) { // The return pointer of A and the return pointer of B point to different // fibers. We assume that return pointers never criss-cross, so A must // belong to the child set of A.return, and B must belong to the child // set of B.return. a = parentA; b = parentB; } else { // The return pointers point to the same fiber. We'll have to use the // default, slow path: scan the child sets of each parent alternate to see // which child belongs to which set. // // Search parent A's child set var didFindChild = false; var _child = parentA.child; while (_child) { if (_child === a) { didFindChild = true; a = parentA; b = parentB; break; } if (_child === b) { didFindChild = true; b = parentA; a = parentB; break; } _child = _child.sibling; } if (!didFindChild) { // Search parent B's child set _child = parentB.child; while (_child) { if (_child === a) { didFindChild = true; a = parentB; b = parentA; break; } if (_child === b) { didFindChild = true; b = parentB; a = parentA; break; } _child = _child.sibling; } if (!didFindChild) { throw new Error( "Child was not found in either parent set. This indicates a bug " + "in React related to the return pointer. Please file an issue." ); } } } if (a.alternate !== b) { throw new Error( "Return fibers should always be each others' alternates. " + "This error is likely caused by a bug in React. Please file an issue." ); } } // If the root is not a host container, we're in a disconnected tree. I.e. // unmounted. if (a.tag !== HostRoot) { throw new Error("Unable to find node on an unmounted component."); } if (a.stateNode.current === a) { // We've determined that A is the current branch. return fiber; } // Otherwise B has to be current branch. return alternate; } function findCurrentHostFiber(parent) { var currentParent = findCurrentFiberUsingSlowPath(parent); return currentParent !== null ? findCurrentHostFiberImpl(currentParent) : null; } function findCurrentHostFiberImpl(node) { // Next we'll drill down this component to find the first HostComponent/Text. var tag = node.tag; if ( tag === HostComponent || tag === HostHoistable || tag === HostSingleton || tag === HostText ) { return node; } var child = node.child; while (child !== null) { var match = findCurrentHostFiberImpl(child); if (match !== null) { return match; } child = child.sibling; } return null; } function findCurrentHostFiberWithNoPortals(parent) { var currentParent = findCurrentFiberUsingSlowPath(parent); return currentParent !== null ? findCurrentHostFiberWithNoPortalsImpl(currentParent) : null; } function findCurrentHostFiberWithNoPortalsImpl(node) { // Next we'll drill down this component to find the first HostComponent/Text. var tag = node.tag; if ( tag === HostComponent || tag === HostHoistable || tag === HostSingleton || tag === HostText ) { return node; } var child = node.child; while (child !== null) { if (child.tag !== HostPortal) { var match = findCurrentHostFiberWithNoPortalsImpl(child); if (match !== null) { return match; } } child = child.sibling; } return null; } function isFiberSuspenseAndTimedOut(fiber) { var memoizedState = fiber.memoizedState; return ( fiber.tag === SuspenseComponent && memoizedState !== null && memoizedState.dehydrated === null ); } function doesFiberContain(parentFiber, childFiber) { var node = childFiber; var parentFiberAlternate = parentFiber.alternate; while (node !== null) { if (node === parentFiber || node === parentFiberAlternate) { return true; } node = node.return; } return false; } // This exists to avoid circular dependency between ReactDOMEventReplaying // and DOMPluginEventSystem. var currentReplayingEvent = null; function setReplayingEvent(event) { { if (currentReplayingEvent !== null) { error( "Expected currently replaying event to be null. This error " + "is likely caused by a bug in React. Please file an issue." ); } } currentReplayingEvent = event; } function resetReplayingEvent() { { if (currentReplayingEvent === null) { error( "Expected currently replaying event to not be null. This error " + "is likely caused by a bug in React. Please file an issue." ); } } currentReplayingEvent = null; } function isReplayingEvent(event) { return event === currentReplayingEvent; } var ReactCurrentDispatcher$3 = ReactSharedInternals.ReactCurrentDispatcher; // Since the "not pending" value is always the same, we can reuse the // same object across all transitions. var sharedNotPendingObject = { pending: false, data: null, method: null, action: null }; var NotPending = Object.freeze(sharedNotPendingObject); function resolveDispatcher() { // Copied from react/src/ReactHooks.js. It's the same thing but in a // different package. var dispatcher = ReactCurrentDispatcher$3.current; { if (dispatcher === null) { error( "Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for" + " one of the following reasons:\n" + "1. You might have mismatching versions of React and the renderer (such as React DOM)\n" + "2. You might be breaking the Rules of Hooks\n" + "3. You might have more than one copy of React in the same app\n" + "See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem." ); } } // Will result in a null access error if accessed outside render phase. We // intentionally don't throw our own error because this is in a hot path. // Also helps ensure this is inlined. return dispatcher; } function useFormStatus() { { var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] We know this exists because of the feature check above. return dispatcher.useHostTransitionStatus(); } } function useFormState(action, initialState, permalink) { { var dispatcher = resolveDispatcher(); // $FlowFixMe[not-a-function] This is unstable, thus optional return dispatcher.useFormState(action, initialState, permalink); } } var valueStack = []; var fiberStack; { fiberStack = []; } var index = -1; function createCursor(defaultValue) { return { current: defaultValue }; } function pop(cursor, fiber) { if (index < 0) { { error("Unexpected pop."); } return; } { if (fiber !== fiberStack[index]) { error("Unexpected Fiber popped."); } } cursor.current = valueStack[index]; valueStack[index] = null; { fiberStack[index] = null; } index--; } function push(cursor, value, fiber) { index++; valueStack[index] = cursor.current; { fiberStack[index] = fiber; } cursor.current = value; } var contextStackCursor$1 = createCursor(null); var contextFiberStackCursor = createCursor(null); var rootInstanceStackCursor = createCursor(null); // Represents the nearest host transition provider (in React DOM, a
) // NOTE: Since forms cannot be nested, and this feature is only implemented by // React DOM, we don't technically need this to be a stack. It could be a single // module variable instead. var hostTransitionProviderCursor = createCursor(null); // TODO: This should initialize to NotPendingTransition, a constant // imported from the fiber config. However, because of a cycle in the module // graph, that value isn't defined during this module's initialization. I can't // think of a way to work around this without moving that value out of the // fiber config. For now, the "no provider" case is handled when reading, // inside useHostTransitionStatus. var HostTransitionContext = { $$typeof: REACT_CONTEXT_TYPE, _currentValue: null, _currentValue2: null, _threadCount: 0, Provider: null, Consumer: null }; function requiredContext(c) { { if (c === null) { error( "Expected host context to exist. This error is likely caused by a bug " + "in React. Please file an issue." ); } } return c; } function getCurrentRootHostContainer() { return rootInstanceStackCursor.current; } function getRootHostContainer() { var rootInstance = requiredContext(rootInstanceStackCursor.current); return rootInstance; } function getHostTransitionProvider() { return hostTransitionProviderCursor.current; } function pushHostContainer(fiber, nextRootInstance) { // Push current root instance onto the stack; // This allows us to reset root when portals are popped. push(rootInstanceStackCursor, nextRootInstance, fiber); // Track the context and the Fiber that provided it. // This enables us to pop only Fibers that provide unique contexts. push(contextFiberStackCursor, fiber, fiber); // Finally, we need to push the host context to the stack. // However, we can't just call getRootHostContext() and push it because // we'd have a different number of entries on the stack depending on // whether getRootHostContext() throws somewhere in renderer code or not. // So we push an empty value first. This lets us safely unwind on errors. push(contextStackCursor$1, null, fiber); var nextRootContext = getRootHostContext(nextRootInstance); // Now that we know this function doesn't throw, replace it. pop(contextStackCursor$1, fiber); push(contextStackCursor$1, nextRootContext, fiber); } function popHostContainer(fiber) { pop(contextStackCursor$1, fiber); pop(contextFiberStackCursor, fiber); pop(rootInstanceStackCursor, fiber); } function getHostContext() { var context = requiredContext(contextStackCursor$1.current); return context; } function pushHostContext(fiber) { { var stateHook = fiber.memoizedState; if (stateHook !== null) { // Only provide context if this fiber has been upgraded by a host // transition. We use the same optimization for regular host context below. push(hostTransitionProviderCursor, fiber, fiber); } } var context = requiredContext(contextStackCursor$1.current); var nextContext = getChildHostContext(context, fiber.type); // Don't push this Fiber's context unless it's unique. if (context !== nextContext) { // Track the context and the Fiber that provided it. // This enables us to pop only Fibers that provide unique contexts. push(contextFiberStackCursor, fiber, fiber); push(contextStackCursor$1, nextContext, fiber); } } function popHostContext(fiber) { if (contextFiberStackCursor.current === fiber) { // Do not pop unless this Fiber provided the current context. // pushHostContext() only pushes Fibers that provide unique contexts. pop(contextStackCursor$1, fiber); pop(contextFiberStackCursor, fiber); } { if (hostTransitionProviderCursor.current === fiber) { // Do not pop unless this Fiber provided the current context. This is mostly // a performance optimization, but conveniently it also prevents a potential // data race where a host provider is upgraded (i.e. memoizedState becomes // non-null) during a concurrent event. This is a bit of a flaw in the way // we upgrade host components, but because we're accounting for it here, it // should be fine. pop(hostTransitionProviderCursor, fiber); // When popping the transition provider, we reset the context value back // to `null`. We can do this because you're not allowd to nest forms. If // we allowed for multiple nested host transition providers, then we'd // need to reset this to the parent provider's status. { HostTransitionContext._currentValue = null; } } } } // This module only exists as an ESM wrapper around the external CommonJS var scheduleCallback$3 = Scheduler.unstable_scheduleCallback; var cancelCallback$1 = Scheduler.unstable_cancelCallback; var shouldYield = Scheduler.unstable_shouldYield; var requestPaint = Scheduler.unstable_requestPaint; var now$1 = Scheduler.unstable_now; var getCurrentPriorityLevel = Scheduler.unstable_getCurrentPriorityLevel; var ImmediatePriority = Scheduler.unstable_ImmediatePriority; var UserBlockingPriority = Scheduler.unstable_UserBlockingPriority; var NormalPriority$1 = Scheduler.unstable_NormalPriority; var LowPriority = Scheduler.unstable_LowPriority; var IdlePriority = Scheduler.unstable_IdlePriority; // this doesn't actually exist on the scheduler, but it *does* // on scheduler/unstable_mock, which we'll need for internal testing var log$2 = Scheduler.log; var unstable_setDisableYieldValue = Scheduler.unstable_setDisableYieldValue; // Helpers to patch console.logs to avoid logging during side-effect free // replaying on render function. This currently only patches the object // lazily which won't cover if the log function was extracted eagerly. // We could also eagerly patch the method. var disabledDepth = 0; var prevLog; var prevInfo; var prevWarn; var prevError; var prevGroup; var prevGroupCollapsed; var prevGroupEnd; function disabledLog() {} disabledLog.__reactDisabledLog = true; function disableLogs() { { if (disabledDepth === 0) { /* eslint-disable react-internal/no-production-logging */ prevLog = console.log; prevInfo = console.info; prevWarn = console.warn; prevError = console.error; prevGroup = console.group; prevGroupCollapsed = console.groupCollapsed; prevGroupEnd = console.groupEnd; // https://github.com/facebook/react/issues/19099 var props = { configurable: true, enumerable: true, value: disabledLog, writable: true }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. Object.defineProperties(console, { info: props, log: props, warn: props, error: props, group: props, groupCollapsed: props, groupEnd: props }); /* eslint-enable react-internal/no-production-logging */ } disabledDepth++; } } function reenableLogs() { { disabledDepth--; if (disabledDepth === 0) { /* eslint-disable react-internal/no-production-logging */ var props = { configurable: true, enumerable: true, writable: true }; // $FlowFixMe[cannot-write] Flow thinks console is immutable. Object.defineProperties(console, { log: assign({}, props, { value: prevLog }), info: assign({}, props, { value: prevInfo }), warn: assign({}, props, { value: prevWarn }), error: assign({}, props, { value: prevError }), group: assign({}, props, { value: prevGroup }), groupCollapsed: assign({}, props, { value: prevGroupCollapsed }), groupEnd: assign({}, props, { value: prevGroupEnd }) }); /* eslint-enable react-internal/no-production-logging */ } if (disabledDepth < 0) { error( "disabledDepth fell below zero. " + "This is a bug in React. Please file an issue." ); } } } var rendererID = null; var injectedHook = null; var injectedProfilingHooks = null; var hasLoggedError = false; var isDevToolsPresent = typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ !== "undefined"; function injectInternals(internals) { if (typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === "undefined") { // No DevTools return false; } var hook = __REACT_DEVTOOLS_GLOBAL_HOOK__; if (hook.isDisabled) { // This isn't a real property on the hook, but it can be set to opt out // of DevTools integration and associated warnings and logs. // https://github.com/facebook/react/issues/3877 return true; } if (!hook.supportsFiber) { { error( "The installed version of React DevTools is too old and will not work " + "with the current version of React. Please update React DevTools. " + "https://reactjs.org/link/react-devtools" ); } // DevTools exists, even though it doesn't support Fiber. return true; } try { if (enableSchedulingProfiler) { // Conditionally inject these hooks only if Timeline profiler is supported by this build. // This gives DevTools a way to feature detect that isn't tied to version number // (since profiling and timeline are controlled by different feature flags). internals = assign({}, internals, { getLaneLabelMap: getLaneLabelMap, injectProfilingHooks: injectProfilingHooks }); } rendererID = hook.inject(internals); // We have successfully injected, so now it is safe to set up hooks. injectedHook = hook; } catch (err) { // Catch all errors because it is unsafe to throw during initialization. { error("React instrumentation encountered an error: %s.", err); } } if (hook.checkDCE) { // This is the real DevTools. return true; } else { // This is likely a hook installed by Fast Refresh runtime. return false; } } function onScheduleRoot(root, children) { { if ( injectedHook && typeof injectedHook.onScheduleFiberRoot === "function" ) { try { injectedHook.onScheduleFiberRoot(rendererID, root, children); } catch (err) { if (!hasLoggedError) { hasLoggedError = true; error("React instrumentation encountered an error: %s", err); } } } } } function onCommitRoot$1(root, eventPriority) { if ( injectedHook && typeof injectedHook.onCommitFiberRoot === "function" ) { try { var didError = (root.current.flags & DidCapture) === DidCapture; if (enableProfilerTimer) { var schedulerPriority; switch (eventPriority) { case DiscreteEventPriority: schedulerPriority = ImmediatePriority; break; case ContinuousEventPriority: schedulerPriority = UserBlockingPriority; break; case DefaultEventPriority: schedulerPriority = NormalPriority$1; break; case IdleEventPriority: schedulerPriority = IdlePriority; break; default: schedulerPriority = NormalPriority$1; break; } injectedHook.onCommitFiberRoot( rendererID, root, schedulerPriority, didError ); } } catch (err) { { if (!hasLoggedError) { hasLoggedError = true; error("React instrumentation encountered an error: %s", err); } } } } } function onPostCommitRoot(root) { if ( injectedHook && typeof injectedHook.onPostCommitFiberRoot === "function" ) { try { injectedHook.onPostCommitFiberRoot(rendererID, root); } catch (err) { { if (!hasLoggedError) { hasLoggedError = true; error("React instrumentation encountered an error: %s", err); } } } } } function onCommitUnmount(fiber) { if ( injectedHook && typeof injectedHook.onCommitFiberUnmount === "function" ) { try { injectedHook.onCommitFiberUnmount(rendererID, fiber); } catch (err) { { if (!hasLoggedError) { hasLoggedError = true; error("React instrumentation encountered an error: %s", err); } } } } } function setIsStrictModeForDevtools(newIsStrictMode) { { if (typeof log$2 === "function") { // We're in a test because Scheduler.log only exists // in SchedulerMock. To reduce the noise in strict mode tests, // suppress warnings and disable scheduler yielding during the double render unstable_setDisableYieldValue(newIsStrictMode); setSuppressWarning(newIsStrictMode); } if (injectedHook && typeof injectedHook.setStrictMode === "function") { try { injectedHook.setStrictMode(rendererID, newIsStrictMode); } catch (err) { { if (!hasLoggedError) { hasLoggedError = true; error("React instrumentation encountered an error: %s", err); } } } } } } // Profiler API hooks function injectProfilingHooks(profilingHooks) { injectedProfilingHooks = profilingHooks; } function getLaneLabelMap() { if (enableSchedulingProfiler) { var map = new Map(); var lane = 1; for (var index = 0; index < TotalLanes; index++) { var label = getLabelForLane(lane); map.set(lane, label); lane *= 2; } return map; } else { return null; } } function markCommitStarted(lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStarted === "function" ) { injectedProfilingHooks.markCommitStarted(lanes); } } } function markCommitStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markCommitStopped === "function" ) { injectedProfilingHooks.markCommitStopped(); } } } function markComponentRenderStarted(fiber) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStarted === "function" ) { injectedProfilingHooks.markComponentRenderStarted(fiber); } } } function markComponentRenderStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentRenderStopped === "function" ) { injectedProfilingHooks.markComponentRenderStopped(); } } } function markComponentPassiveEffectMountStarted(fiber) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStarted === "function" ) { injectedProfilingHooks.markComponentPassiveEffectMountStarted(fiber); } } } function markComponentPassiveEffectMountStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectMountStopped === "function" ) { injectedProfilingHooks.markComponentPassiveEffectMountStopped(); } } } function markComponentPassiveEffectUnmountStarted(fiber) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStarted === "function" ) { injectedProfilingHooks.markComponentPassiveEffectUnmountStarted( fiber ); } } } function markComponentPassiveEffectUnmountStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentPassiveEffectUnmountStopped === "function" ) { injectedProfilingHooks.markComponentPassiveEffectUnmountStopped(); } } } function markComponentLayoutEffectMountStarted(fiber) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStarted === "function" ) { injectedProfilingHooks.markComponentLayoutEffectMountStarted(fiber); } } } function markComponentLayoutEffectMountStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectMountStopped === "function" ) { injectedProfilingHooks.markComponentLayoutEffectMountStopped(); } } } function markComponentLayoutEffectUnmountStarted(fiber) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStarted === "function" ) { injectedProfilingHooks.markComponentLayoutEffectUnmountStarted(fiber); } } } function markComponentLayoutEffectUnmountStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentLayoutEffectUnmountStopped === "function" ) { injectedProfilingHooks.markComponentLayoutEffectUnmountStopped(); } } } function markComponentErrored(fiber, thrownValue, lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentErrored === "function" ) { injectedProfilingHooks.markComponentErrored( fiber, thrownValue, lanes ); } } } function markComponentSuspended(fiber, wakeable, lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markComponentSuspended === "function" ) { injectedProfilingHooks.markComponentSuspended(fiber, wakeable, lanes); } } } function markLayoutEffectsStarted(lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStarted === "function" ) { injectedProfilingHooks.markLayoutEffectsStarted(lanes); } } } function markLayoutEffectsStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markLayoutEffectsStopped === "function" ) { injectedProfilingHooks.markLayoutEffectsStopped(); } } } function markPassiveEffectsStarted(lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStarted === "function" ) { injectedProfilingHooks.markPassiveEffectsStarted(lanes); } } } function markPassiveEffectsStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markPassiveEffectsStopped === "function" ) { injectedProfilingHooks.markPassiveEffectsStopped(); } } } function markRenderStarted(lanes) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStarted === "function" ) { injectedProfilingHooks.markRenderStarted(lanes); } } } function markRenderYielded() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderYielded === "function" ) { injectedProfilingHooks.markRenderYielded(); } } } function markRenderStopped() { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderStopped === "function" ) { injectedProfilingHooks.markRenderStopped(); } } } function markRenderScheduled(lane) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markRenderScheduled === "function" ) { injectedProfilingHooks.markRenderScheduled(lane); } } } function markForceUpdateScheduled(fiber, lane) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markForceUpdateScheduled === "function" ) { injectedProfilingHooks.markForceUpdateScheduled(fiber, lane); } } } function markStateUpdateScheduled(fiber, lane) { if (enableSchedulingProfiler) { if ( injectedProfilingHooks !== null && typeof injectedProfilingHooks.markStateUpdateScheduled === "function" ) { injectedProfilingHooks.markStateUpdateScheduled(fiber, lane); } } } var NoMode = /* */ 0; // TODO: Remove ConcurrentMode by reading from the root tag instead var ConcurrentMode = /* */ 1; var ProfileMode = /* */ 2; var DebugTracingMode = /* */ 4; var StrictLegacyMode = /* */ 8; var StrictEffectsMode = /* */ 16; var ConcurrentUpdatesByDefaultMode = /* */ 32; var NoStrictPassiveEffectsMode = /* */ 64; // TODO: This is pretty well supported by browsers. Maybe we can drop it. var clz32 = Math.clz32 ? Math.clz32 : clz32Fallback; // Count leading zeros. // Based on: // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/clz32 var log$1 = Math.log; var LN2 = Math.LN2; function clz32Fallback(x) { var asUint = x >>> 0; if (asUint === 0) { return 32; } return (31 - ((log$1(asUint) / LN2) | 0)) | 0; } // If those values are changed that package should be rebuilt and redeployed. var TotalLanes = 31; var NoLanes = /* */ 0; var NoLane = /* */ 0; var SyncHydrationLane = /* */ 1; var SyncLane = /* */ 2; var SyncLaneIndex = 1; var InputContinuousHydrationLane = /* */ 4; var InputContinuousLane = /* */ 8; var DefaultHydrationLane = /* */ 16; var DefaultLane = /* */ 32; var SyncUpdateLanes = enableUnifiedSyncLane ? SyncLane | InputContinuousLane | DefaultLane : SyncLane; var TransitionHydrationLane = /* */ 64; var TransitionLanes = /* */ 4194176; var TransitionLane1 = /* */ 128; var TransitionLane2 = /* */ 256; var TransitionLane3 = /* */ 512; var TransitionLane4 = /* */ 1024; var TransitionLane5 = /* */ 2048; var TransitionLane6 = /* */ 4096; var TransitionLane7 = /* */ 8192; var TransitionLane8 = /* */ 16384; var TransitionLane9 = /* */ 32768; var TransitionLane10 = /* */ 65536; var TransitionLane11 = /* */ 131072; var TransitionLane12 = /* */ 262144; var TransitionLane13 = /* */ 524288; var TransitionLane14 = /* */ 1048576; var TransitionLane15 = /* */ 2097152; var RetryLanes = /* */ 62914560; var RetryLane1 = /* */ 4194304; var RetryLane2 = /* */ 8388608; var RetryLane3 = /* */ 16777216; var RetryLane4 = /* */ 33554432; var SomeRetryLane = RetryLane1; var SelectiveHydrationLane = /* */ 67108864; var NonIdleLanes = /* */ 134217727; var IdleHydrationLane = /* */ 134217728; var IdleLane = /* */ 268435456; var OffscreenLane = /* */ 536870912; var DeferredLane = /* */ 1073741824; // Any lane that might schedule an update. This is used to detect infinite // update loops, so it doesn't include hydration lanes or retries. var UpdateLanes = SyncLane | InputContinuousLane | DefaultLane | TransitionLanes; // This function is used for the experimental timeline (react-devtools-timeline) // It should be kept in sync with the Lanes values above. function getLabelForLane(lane) { if (enableSchedulingProfiler) { if (lane & SyncHydrationLane) { return "SyncHydrationLane"; } if (lane & SyncLane) { return "Sync"; } if (lane & InputContinuousHydrationLane) { return "InputContinuousHydration"; } if (lane & InputContinuousLane) { return "InputContinuous"; } if (lane & DefaultHydrationLane) { return "DefaultHydration"; } if (lane & DefaultLane) { return "Default"; } if (lane & TransitionHydrationLane) { return "TransitionHydration"; } if (lane & TransitionLanes) { return "Transition"; } if (lane & RetryLanes) { return "Retry"; } if (lane & SelectiveHydrationLane) { return "SelectiveHydration"; } if (lane & IdleHydrationLane) { return "IdleHydration"; } if (lane & IdleLane) { return "Idle"; } if (lane & OffscreenLane) { return "Offscreen"; } if (lane & DeferredLane) { return "Deferred"; } } } var NoTimestamp = -1; var nextTransitionLane = TransitionLane1; var nextRetryLane = RetryLane1; function getHighestPriorityLanes(lanes) { if (enableUnifiedSyncLane) { var pendingSyncLanes = lanes & SyncUpdateLanes; if (pendingSyncLanes !== 0) { return pendingSyncLanes; } } switch (getHighestPriorityLane(lanes)) { case SyncHydrationLane: return SyncHydrationLane; case SyncLane: return SyncLane; case InputContinuousHydrationLane: return InputContinuousHydrationLane; case InputContinuousLane: return InputContinuousLane; case DefaultHydrationLane: return DefaultHydrationLane; case DefaultLane: return DefaultLane; case TransitionHydrationLane: return TransitionHydrationLane; case TransitionLane1: case TransitionLane2: case TransitionLane3: case TransitionLane4: case TransitionLane5: case TransitionLane6: case TransitionLane7: case TransitionLane8: case TransitionLane9: case TransitionLane10: case TransitionLane11: case TransitionLane12: case TransitionLane13: case TransitionLane14: case TransitionLane15: return lanes & TransitionLanes; case RetryLane1: case RetryLane2: case RetryLane3: case RetryLane4: return lanes & RetryLanes; case SelectiveHydrationLane: return SelectiveHydrationLane; case IdleHydrationLane: return IdleHydrationLane; case IdleLane: return IdleLane; case OffscreenLane: return OffscreenLane; case DeferredLane: // This shouldn't be reachable because deferred work is always entangled // with something else. return NoLanes; default: { error("Should have found matching lanes. This is a bug in React."); } // This shouldn't be reachable, but as a fallback, return the entire bitmask. return lanes; } } function getNextLanes(root, wipLanes) { // Early bailout if there's no pending work left. var pendingLanes = root.pendingLanes; if (pendingLanes === NoLanes) { return NoLanes; } var nextLanes = NoLanes; var suspendedLanes = root.suspendedLanes; var pingedLanes = root.pingedLanes; // Do not work on any idle work until all the non-idle work has finished, // even if the work is suspended. var nonIdlePendingLanes = pendingLanes & NonIdleLanes; if (nonIdlePendingLanes !== NoLanes) { var nonIdleUnblockedLanes = nonIdlePendingLanes & ~suspendedLanes; if (nonIdleUnblockedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(nonIdleUnblockedLanes); } else { var nonIdlePingedLanes = nonIdlePendingLanes & pingedLanes; if (nonIdlePingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(nonIdlePingedLanes); } } } else { // The only remaining work is Idle. var unblockedLanes = pendingLanes & ~suspendedLanes; if (unblockedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(unblockedLanes); } else { if (pingedLanes !== NoLanes) { nextLanes = getHighestPriorityLanes(pingedLanes); } } } if (nextLanes === NoLanes) { // This should only be reachable if we're suspended // TODO: Consider warning in this path if a fallback timer is not scheduled. return NoLanes; } // If we're already in the middle of a render, switching lanes will interrupt // it and we'll lose our progress. We should only do this if the new lanes are // higher priority. if ( wipLanes !== NoLanes && wipLanes !== nextLanes && // If we already suspended with a delay, then interrupting is fine. Don't // bother waiting until the root is complete. (wipLanes & suspendedLanes) === NoLanes ) { var nextLane = getHighestPriorityLane(nextLanes); var wipLane = getHighestPriorityLane(wipLanes); if ( // Tests whether the next lane is equal or lower priority than the wip // one. This works because the bits decrease in priority as you go left. nextLane >= wipLane || // Default priority updates should not interrupt transition updates. The // only difference between default updates and transition updates is that // default updates do not support refresh transitions. (nextLane === DefaultLane && (wipLane & TransitionLanes) !== NoLanes) ) { // Keep working on the existing in-progress tree. Do not interrupt. return wipLanes; } } return nextLanes; } function getEntangledLanes(root, renderLanes) { var entangledLanes = renderLanes; if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode); else if ((entangledLanes & InputContinuousLane) !== NoLanes) { // When updates are sync by default, we entangle continuous priority updates // and default updates, so they render in the same batch. The only reason // they use separate lanes is because continuous updates should interrupt // transitions, but default updates should not. entangledLanes |= entangledLanes & DefaultLane; } // Check for entangled lanes and add them to the batch. // // A lane is said to be entangled with another when it's not allowed to render // in a batch that does not also include the other lane. Typically we do this // when multiple updates have the same source, and we only want to respond to // the most recent event from that source. // // Note that we apply entanglements *after* checking for partial work above. // This means that if a lane is entangled during an interleaved event while // it's already rendering, we won't interrupt it. This is intentional, since // entanglement is usually "best effort": we'll try our best to render the // lanes in the same batch, but it's not worth throwing out partially // completed work in order to do it. // TODO: Reconsider this. The counter-argument is that the partial work // represents an intermediate state, which we don't want to show to the user. // And by spending extra time finishing it, we're increasing the amount of // time it takes to show the final state, which is what they are actually // waiting for. // // For those exceptions where entanglement is semantically important, // we should ensure that there is no partial work at the // time we apply the entanglement. var allEntangledLanes = root.entangledLanes; if (allEntangledLanes !== NoLanes) { var entanglements = root.entanglements; var lanes = entangledLanes & allEntangledLanes; while (lanes > 0) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; entangledLanes |= entanglements[index]; lanes &= ~lane; } } return entangledLanes; } function computeExpirationTime(lane, currentTime) { switch (lane) { case SyncHydrationLane: case SyncLane: case InputContinuousHydrationLane: case InputContinuousLane: // User interactions should expire slightly more quickly. // // NOTE: This is set to the corresponding constant as in Scheduler.js. // When we made it larger, a product metric in www regressed, suggesting // there's a user interaction that's being starved by a series of // synchronous updates. If that theory is correct, the proper solution is // to fix the starvation. However, this scenario supports the idea that // expiration times are an important safeguard when starvation // does happen. return currentTime + syncLaneExpirationMs; case DefaultHydrationLane: case DefaultLane: case TransitionHydrationLane: case TransitionLane1: case TransitionLane2: case TransitionLane3: case TransitionLane4: case TransitionLane5: case TransitionLane6: case TransitionLane7: case TransitionLane8: case TransitionLane9: case TransitionLane10: case TransitionLane11: case TransitionLane12: case TransitionLane13: case TransitionLane14: case TransitionLane15: return currentTime + transitionLaneExpirationMs; case RetryLane1: case RetryLane2: case RetryLane3: case RetryLane4: // TODO: Retries should be allowed to expire if they are CPU bound for // too long, but when I made this change it caused a spike in browser // crashes. There must be some other underlying bug; not super urgent but // ideally should figure out why and fix it. Unfortunately we don't have // a repro for the crashes, only detected via production metrics. return enableRetryLaneExpiration ? currentTime + retryLaneExpirationMs : NoTimestamp; case SelectiveHydrationLane: case IdleHydrationLane: case IdleLane: case OffscreenLane: case DeferredLane: // Anything idle priority or lower should never expire. return NoTimestamp; default: { error("Should have found matching lanes. This is a bug in React."); } return NoTimestamp; } } function markStarvedLanesAsExpired(root, currentTime) { // TODO: This gets called every time we yield. We can optimize by storing // the earliest expiration time on the root. Then use that to quickly bail out // of this function. var pendingLanes = root.pendingLanes; var suspendedLanes = root.suspendedLanes; var pingedLanes = root.pingedLanes; var expirationTimes = root.expirationTimes; // Iterate through the pending lanes and check if we've reached their // expiration time. If so, we'll assume the update is being starved and mark // it as expired to force it to finish. // TODO: We should be able to replace this with upgradePendingLanesToSync // // We exclude retry lanes because those must always be time sliced, in order // to unwrap uncached promises. // TODO: Write a test for this var lanes = enableRetryLaneExpiration ? pendingLanes : pendingLanes & ~RetryLanes; while (lanes > 0) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; var expirationTime = expirationTimes[index]; if (expirationTime === NoTimestamp) { // Found a pending lane with no expiration time. If it's not suspended, or // if it's pinged, assume it's CPU-bound. Compute a new expiration time // using the current time. if ( (lane & suspendedLanes) === NoLanes || (lane & pingedLanes) !== NoLanes ) { // Assumes timestamps are monotonically increasing. expirationTimes[index] = computeExpirationTime(lane, currentTime); } } else if (expirationTime <= currentTime) { // This lane expired root.expiredLanes |= lane; } lanes &= ~lane; } } // This returns the highest priority pending lanes regardless of whether they // are suspended. function getHighestPriorityPendingLanes(root) { return getHighestPriorityLanes(root.pendingLanes); } function getLanesToRetrySynchronouslyOnError( root, originallyAttemptedLanes ) { if (root.errorRecoveryDisabledLanes & originallyAttemptedLanes) { // The error recovery mechanism is disabled until these lanes are cleared. return NoLanes; } var everythingButOffscreen = root.pendingLanes & ~OffscreenLane; if (everythingButOffscreen !== NoLanes) { return everythingButOffscreen; } if (everythingButOffscreen & OffscreenLane) { return OffscreenLane; } return NoLanes; } function includesSyncLane(lanes) { return (lanes & (SyncLane | SyncHydrationLane)) !== NoLanes; } function includesNonIdleWork(lanes) { return (lanes & NonIdleLanes) !== NoLanes; } function includesOnlyRetries(lanes) { return (lanes & RetryLanes) === lanes; } function includesOnlyNonUrgentLanes(lanes) { // TODO: Should hydration lanes be included here? This function is only // used in `updateDeferredValueImpl`. var UrgentLanes = SyncLane | InputContinuousLane | DefaultLane; return (lanes & UrgentLanes) === NoLanes; } function includesOnlyTransitions(lanes) { return (lanes & TransitionLanes) === lanes; } function includesBlockingLane(root, lanes) { if ((root.current.mode & ConcurrentUpdatesByDefaultMode) !== NoMode) { // Concurrent updates by default always use time slicing. return false; } var SyncDefaultLanes = InputContinuousHydrationLane | InputContinuousLane | DefaultHydrationLane | DefaultLane; return (lanes & SyncDefaultLanes) !== NoLanes; } function includesExpiredLane(root, lanes) { // This is a separate check from includesBlockingLane because a lane can // expire after a render has already started. return (lanes & root.expiredLanes) !== NoLanes; } function isTransitionLane(lane) { return (lane & TransitionLanes) !== NoLanes; } function claimNextTransitionLane() { // Cycle through the lanes, assigning each new transition to the next lane. // In most cases, this means every transition gets its own lane, until we // run out of lanes and cycle back to the beginning. var lane = nextTransitionLane; nextTransitionLane <<= 1; if ((nextTransitionLane & TransitionLanes) === NoLanes) { nextTransitionLane = TransitionLane1; } return lane; } function claimNextRetryLane() { var lane = nextRetryLane; nextRetryLane <<= 1; if ((nextRetryLane & RetryLanes) === NoLanes) { nextRetryLane = RetryLane1; } return lane; } function getHighestPriorityLane(lanes) { return lanes & -lanes; } function pickArbitraryLane(lanes) { // This wrapper function gets inlined. Only exists so to communicate that it // doesn't matter which bit is selected; you can pick any bit without // affecting the algorithms where its used. Here I'm using // getHighestPriorityLane because it requires the fewest operations. return getHighestPriorityLane(lanes); } function pickArbitraryLaneIndex(lanes) { return 31 - clz32(lanes); } function laneToIndex(lane) { return pickArbitraryLaneIndex(lane); } function includesSomeLane(a, b) { return (a & b) !== NoLanes; } function isSubsetOfLanes(set, subset) { return (set & subset) === subset; } function mergeLanes(a, b) { return a | b; } function removeLanes(set, subset) { return set & ~subset; } function intersectLanes(a, b) { return a & b; } // Seems redundant, but it changes the type from a single lane (used for // updates) to a group of lanes (used for flushing work). function laneToLanes(lane) { return lane; } function higherPriorityLane(a, b) { // This works because the bit ranges decrease in priority as you go left. return a !== NoLane && a < b ? a : b; } function createLaneMap(initial) { // Intentionally pushing one by one. // https://v8.dev/blog/elements-kinds#avoid-creating-holes var laneMap = []; for (var i = 0; i < TotalLanes; i++) { laneMap.push(initial); } return laneMap; } function markRootUpdated$1(root, updateLane) { root.pendingLanes |= updateLane; // If there are any suspended transitions, it's possible this new update // could unblock them. Clear the suspended lanes so that we can try rendering // them again. // // TODO: We really only need to unsuspend only lanes that are in the // `subtreeLanes` of the updated fiber, or the update lanes of the return // path. This would exclude suspended updates in an unrelated sibling tree, // since there's no way for this update to unblock it. // // We don't do this if the incoming update is idle, because we never process // idle updates until after all the regular updates have finished; there's no // way it could unblock a transition. if (updateLane !== IdleLane) { root.suspendedLanes = NoLanes; root.pingedLanes = NoLanes; } } function markRootSuspended$1(root, suspendedLanes, spawnedLane) { root.suspendedLanes |= suspendedLanes; root.pingedLanes &= ~suspendedLanes; // The suspended lanes are no longer CPU-bound. Clear their expiration times. var expirationTimes = root.expirationTimes; var lanes = suspendedLanes; while (lanes > 0) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; expirationTimes[index] = NoTimestamp; lanes &= ~lane; } if (spawnedLane !== NoLane) { markSpawnedDeferredLane(root, spawnedLane, suspendedLanes); } } function markRootPinged$1(root, pingedLanes) { root.pingedLanes |= root.suspendedLanes & pingedLanes; } function markRootFinished(root, remainingLanes, spawnedLane) { var noLongerPendingLanes = root.pendingLanes & ~remainingLanes; root.pendingLanes = remainingLanes; // Let's try everything again root.suspendedLanes = NoLanes; root.pingedLanes = NoLanes; root.expiredLanes &= remainingLanes; root.entangledLanes &= remainingLanes; root.errorRecoveryDisabledLanes &= remainingLanes; root.shellSuspendCounter = 0; var entanglements = root.entanglements; var expirationTimes = root.expirationTimes; var hiddenUpdates = root.hiddenUpdates; // Clear the lanes that no longer have pending work var lanes = noLongerPendingLanes; while (lanes > 0) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; entanglements[index] = NoLanes; expirationTimes[index] = NoTimestamp; var hiddenUpdatesForLane = hiddenUpdates[index]; if (hiddenUpdatesForLane !== null) { hiddenUpdates[index] = null; // "Hidden" updates are updates that were made to a hidden component. They // have special logic associated with them because they may be entangled // with updates that occur outside that tree. But once the outer tree // commits, they behave like regular updates. for (var i = 0; i < hiddenUpdatesForLane.length; i++) { var update = hiddenUpdatesForLane[i]; if (update !== null) { update.lane &= ~OffscreenLane; } } } lanes &= ~lane; } if (spawnedLane !== NoLane) { markSpawnedDeferredLane( root, spawnedLane, // This render finished successfully without suspending, so we don't need // to entangle the spawned task with the parent task. NoLanes ); } } function markSpawnedDeferredLane(root, spawnedLane, entangledLanes) { // This render spawned a deferred task. Mark it as pending. root.pendingLanes |= spawnedLane; root.suspendedLanes &= ~spawnedLane; // Entangle the spawned lane with the DeferredLane bit so that we know it // was the result of another render. This lets us avoid a useDeferredValue // waterfall — only the first level will defer. var spawnedLaneIndex = laneToIndex(spawnedLane); root.entangledLanes |= spawnedLane; root.entanglements[spawnedLaneIndex] |= DeferredLane | // If the parent render task suspended, we must also entangle those lanes // with the spawned task, so that the deferred task includes all the same // updates that the parent task did. We can exclude any lane that is not // used for updates (e.g. Offscreen). (entangledLanes & UpdateLanes); } function markRootEntangled(root, entangledLanes) { // In addition to entangling each of the given lanes with each other, we also // have to consider _transitive_ entanglements. For each lane that is already // entangled with *any* of the given lanes, that lane is now transitively // entangled with *all* the given lanes. // // Translated: If C is entangled with A, then entangling A with B also // entangles C with B. // // If this is hard to grasp, it might help to intentionally break this // function and look at the tests that fail in ReactTransition-test.js. Try // commenting out one of the conditions below. var rootEntangledLanes = (root.entangledLanes |= entangledLanes); var entanglements = root.entanglements; var lanes = rootEntangledLanes; while (lanes) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; if ( // Is this one of the newly entangled lanes? (lane & entangledLanes) | // Is this lane transitively entangled with the newly entangled lanes? (entanglements[index] & entangledLanes) ) { entanglements[index] |= entangledLanes; } lanes &= ~lane; } } function upgradePendingLaneToSync(root, lane) { // Since we're upgrading the priority of the given lane, there is now pending // sync work. root.pendingLanes |= SyncLane; // Entangle the sync lane with the lane we're upgrading. This means SyncLane // will not be allowed to finish without also finishing the given lane. root.entangledLanes |= SyncLane; root.entanglements[SyncLaneIndex] |= lane; } function upgradePendingLanesToSync(root, lanesToUpgrade) { // Same as upgradePendingLaneToSync but accepts multiple lanes, so it's a // bit slower. root.pendingLanes |= SyncLane; root.entangledLanes |= SyncLane; var lanes = lanesToUpgrade; while (lanes) { var index = pickArbitraryLaneIndex(lanes); var lane = 1 << index; root.entanglements[SyncLaneIndex] |= lane; lanes &= ~lane; } } function markHiddenUpdate(root, update, lane) { var index = laneToIndex(lane); var hiddenUpdates = root.hiddenUpdates; var hiddenUpdatesForLane = hiddenUpdates[index]; if (hiddenUpdatesForLane === null) { hiddenUpdates[index] = [update]; } else { hiddenUpdatesForLane.push(update); } update.lane = lane | OffscreenLane; } function getBumpedLaneForHydration(root, renderLanes) { var renderLane = getHighestPriorityLane(renderLanes); var lane; if (enableUnifiedSyncLane && (renderLane & SyncUpdateLanes) !== NoLane) { lane = SyncHydrationLane; } else { switch (renderLane) { case SyncLane: lane = SyncHydrationLane; break; case InputContinuousLane: lane = InputContinuousHydrationLane; break; case DefaultLane: lane = DefaultHydrationLane; break; case TransitionLane1: case TransitionLane2: case TransitionLane3: case TransitionLane4: case TransitionLane5: case TransitionLane6: case TransitionLane7: case TransitionLane8: case TransitionLane9: case TransitionLane10: case TransitionLane11: case TransitionLane12: case TransitionLane13: case TransitionLane14: case TransitionLane15: case RetryLane1: case RetryLane2: case RetryLane3: case RetryLane4: lane = TransitionHydrationLane; break; case IdleLane: lane = IdleHydrationLane; break; default: // Everything else is already either a hydration lane, or shouldn't // be retried at a hydration lane. lane = NoLane; break; } } // Check if the lane we chose is suspended. If so, that indicates that we // already attempted and failed to hydrate at that level. Also check if we're // already rendering that lane, which is rare but could happen. if ((lane & (root.suspendedLanes | renderLanes)) !== NoLane) { // Give up trying to hydrate and fall back to client render. return NoLane; } return lane; } function addFiberToLanesMap(root, fiber, lanes) { if (!isDevToolsPresent) { return; } var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; while (lanes > 0) { var index = laneToIndex(lanes); var lane = 1 << index; var updaters = pendingUpdatersLaneMap[index]; updaters.add(fiber); lanes &= ~lane; } } function movePendingFibersToMemoized(root, lanes) { if (!isDevToolsPresent) { return; } var pendingUpdatersLaneMap = root.pendingUpdatersLaneMap; var memoizedUpdaters = root.memoizedUpdaters; while (lanes > 0) { var index = laneToIndex(lanes); var lane = 1 << index; var updaters = pendingUpdatersLaneMap[index]; if (updaters.size > 0) { updaters.forEach(function (fiber) { var alternate = fiber.alternate; if (alternate === null || !memoizedUpdaters.has(alternate)) { memoizedUpdaters.add(fiber); } }); updaters.clear(); } lanes &= ~lane; } } function addTransitionToLanesMap(root, transition, lane) { if (enableTransitionTracing) { var transitionLanesMap = root.transitionLanes; var index = laneToIndex(lane); var transitions = transitionLanesMap[index]; if (transitions === null) { transitions = new Set(); } transitions.add(transition); transitionLanesMap[index] = transitions; } } function getTransitionsForLanes(root, lanes) { if (!enableTransitionTracing) { return null; } var transitionsForLanes = []; while (lanes > 0) { var index = laneToIndex(lanes); var lane = 1 << index; var transitions = root.transitionLanes[index]; if (transitions !== null) { transitions.forEach(function (transition) { transitionsForLanes.push(transition); }); } lanes &= ~lane; } if (transitionsForLanes.length === 0) { return null; } return transitionsForLanes; } function clearTransitionsForLanes(root, lanes) { if (!enableTransitionTracing) { return; } while (lanes > 0) { var index = laneToIndex(lanes); var lane = 1 << index; var transitions = root.transitionLanes[index]; if (transitions !== null) { root.transitionLanes[index] = null; } lanes &= ~lane; } } var DiscreteEventPriority = SyncLane; var ContinuousEventPriority = InputContinuousLane; var DefaultEventPriority = DefaultLane; var IdleEventPriority = IdleLane; var currentUpdatePriority = NoLane; function getCurrentUpdatePriority() { return currentUpdatePriority; } function setCurrentUpdatePriority(newPriority) { currentUpdatePriority = newPriority; } function runWithPriority(priority, fn) { var previousPriority = currentUpdatePriority; try { currentUpdatePriority = priority; return fn(); } finally { currentUpdatePriority = previousPriority; } } function higherEventPriority(a, b) { return a !== 0 && a < b ? a : b; } function lowerEventPriority(a, b) { return a === 0 || a > b ? a : b; } function isHigherEventPriority(a, b) { return a !== 0 && a < b; } function lanesToEventPriority(lanes) { var lane = getHighestPriorityLane(lanes); if (!isHigherEventPriority(DiscreteEventPriority, lane)) { return DiscreteEventPriority; } if (!isHigherEventPriority(ContinuousEventPriority, lane)) { return ContinuousEventPriority; } if (includesNonIdleWork(lane)) { return DefaultEventPriority; } return IdleEventPriority; } // $FlowFixMe[method-unbinding] var hasOwnProperty = Object.prototype.hasOwnProperty; /* * The `'' + value` pattern (used in perf-sensitive code) throws for Symbol * and Temporal.* types. See https://github.com/facebook/react/pull/22064. * * The functions in this module will throw an easier-to-understand, * easier-to-debug exception with a clear errors message message explaining the * problem. (Instead of a confusing exception thrown inside the implementation * of the `value` object). */ // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. function typeName(value) { { // toStringTag is needed for namespaced types like Temporal.Instant var hasToStringTag = typeof Symbol === "function" && Symbol.toStringTag; var type = (hasToStringTag && value[Symbol.toStringTag]) || value.constructor.name || "Object"; // $FlowFixMe[incompatible-return] return type; } } // $FlowFixMe[incompatible-return] only called in DEV, so void return is not possible. function willCoercionThrow(value) { { try { testStringCoercion(value); return false; } catch (e) { return true; } } } function testStringCoercion(value) { // If you ended up here by following an exception call stack, here's what's // happened: you supplied an object or symbol value to React (as a prop, key, // DOM attribute, CSS property, string ref, etc.) and when React tried to // coerce it to a string using `'' + value`, an exception was thrown. // // The most common types that will cause this exception are `Symbol` instances // and Temporal objects like `Temporal.Instant`. But any object that has a // `valueOf` or `[Symbol.toPrimitive]` method that throws will also cause this // exception. (Library authors do this to prevent users from using built-in // numeric operators like `+` or comparison operators like `>=` because custom // methods are needed to perform accurate arithmetic or comparison.) // // To fix the problem, coerce this object or symbol value to a string before // passing it to React. The most reliable way is usually `String(value)`. // // To find which value is throwing, check the browser or debugger console. // Before this exception was thrown, there should be `console.error` output // that shows the type (Symbol, Temporal.PlainDate, etc.) that caused the // problem and how that type was used: key, atrribute, input value prop, etc. // In most cases, this console output also shows the component and its // ancestor components where the exception happened. // // eslint-disable-next-line react-internal/safe-string-coercion return "" + value; } function checkAttributeStringCoercion(value, attributeName) { { if (willCoercionThrow(value)) { error( "The provided `%s` attribute is an unsupported type %s." + " This value must be coerced to a string before using it here.", attributeName, typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } function checkKeyStringCoercion(value) { { if (willCoercionThrow(value)) { error( "The provided key is an unsupported type %s." + " This value must be coerced to a string before using it here.", typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } function checkPropStringCoercion(value, propName) { { if (willCoercionThrow(value)) { error( "The provided `%s` prop is an unsupported type %s." + " This value must be coerced to a string before using it here.", propName, typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } function checkCSSPropertyStringCoercion(value, propName) { { if (willCoercionThrow(value)) { error( "The provided `%s` CSS property is an unsupported type %s." + " This value must be coerced to a string before using it here.", propName, typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } function checkHtmlStringCoercion(value) { { if (willCoercionThrow(value)) { error( "The provided HTML markup uses a value of unsupported type %s." + " This value must be coerced to a string before using it here.", typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } function checkFormFieldValueStringCoercion(value) { { if (willCoercionThrow(value)) { error( "Form field values (value, checked, defaultValue, or defaultChecked props)" + " must be strings, not %s." + " This value must be coerced to a string before using it here.", typeName(value) ); return testStringCoercion(value); // throw (to help callers find troubleshooting comments) } } } // Below code forked from dom-accessibility-api var tagToRoleMappings = { ARTICLE: "article", ASIDE: "complementary", BODY: "document", BUTTON: "button", DATALIST: "listbox", DD: "definition", DETAILS: "group", DIALOG: "dialog", DT: "term", FIELDSET: "group", FIGURE: "figure", // WARNING: Only with an accessible name FORM: "form", FOOTER: "contentinfo", H1: "heading", H2: "heading", H3: "heading", H4: "heading", H5: "heading", H6: "heading", HEADER: "banner", HR: "separator", LEGEND: "legend", LI: "listitem", MATH: "math", MAIN: "main", MENU: "list", NAV: "navigation", OL: "list", OPTGROUP: "group", // WARNING: Only in certain context OPTION: "option", OUTPUT: "status", PROGRESS: "progressbar", // WARNING: Only with an accessible name SECTION: "region", SUMMARY: "button", TABLE: "table", TBODY: "rowgroup", TEXTAREA: "textbox", TFOOT: "rowgroup", // WARNING: Only in certain context TD: "cell", TH: "columnheader", THEAD: "rowgroup", TR: "row", UL: "list" }; function getImplicitRole(element) { var mappedByTag = tagToRoleMappings[element.tagName]; if (mappedByTag !== undefined) { return mappedByTag; } switch (element.tagName) { case "A": case "AREA": case "LINK": if (element.hasAttribute("href")) { return "link"; } break; case "IMG": if ((element.getAttribute("alt") || "").length > 0) { return "img"; } break; case "INPUT": { var type = element.type; switch (type) { case "button": case "image": case "reset": case "submit": return "button"; case "checkbox": case "radio": return type; case "range": return "slider"; case "email": case "tel": case "text": case "url": if (element.hasAttribute("list")) { return "combobox"; } return "textbox"; case "search": if (element.hasAttribute("list")) { return "combobox"; } return "searchbox"; default: return null; } } case "SELECT": if (element.hasAttribute("multiple") || element.size > 1) { return "listbox"; } return "combobox"; } return null; } function getExplicitRoles(element) { var role = element.getAttribute("role"); if (role) { return role.trim().split(" "); } return null; } // https://w3c.github.io/html-aria/#document-conformance-requirements-for-use-of-aria-attributes-in-html function hasRole(element, role) { var explicitRoles = getExplicitRoles(element); if (explicitRoles !== null && explicitRoles.indexOf(role) >= 0) { return true; } return role === getImplicitRole(element); } var allNativeEvents = new Set(); { allNativeEvents.add("beforeblur"); allNativeEvents.add("afterblur"); } /** * Mapping from registration name to event name */ var registrationNameDependencies = {}; /** * Mapping from lowercase registration names to the properly cased version, * used to warn in the case of missing event handlers. Available * only in __DEV__. * @type {Object} */ var possibleRegistrationNames = {}; // Trust the developer to only use possibleRegistrationNames in true function registerTwoPhaseEvent(registrationName, dependencies) { registerDirectEvent(registrationName, dependencies); registerDirectEvent(registrationName + "Capture", dependencies); } function registerDirectEvent(registrationName, dependencies) { { if (registrationNameDependencies[registrationName]) { error( "EventRegistry: More than one plugin attempted to publish the same " + "registration name, `%s`.", registrationName ); } } registrationNameDependencies[registrationName] = dependencies; { var lowerCasedName = registrationName.toLowerCase(); possibleRegistrationNames[lowerCasedName] = registrationName; if (registrationName === "onDoubleClick") { possibleRegistrationNames.ondblclick = registrationName; } } for (var i = 0; i < dependencies.length; i++) { allNativeEvents.add(dependencies[i]); } } var canUseDOM = !!( typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined" ); var hasReadOnlyValue = { button: true, checkbox: true, image: true, hidden: true, radio: true, reset: true, submit: true }; function checkControlledValueProps(tagName, props) { { if ( !( hasReadOnlyValue[props.type] || props.onChange || props.onInput || props.readOnly || props.disabled || props.value == null ) ) { if (tagName === "select") { error( "You provided a `value` prop to a form field without an " + "`onChange` handler. This will render a read-only field. If " + "the field should be mutable use `defaultValue`. Otherwise, set `onChange`." ); } else { error( "You provided a `value` prop to a form field without an " + "`onChange` handler. This will render a read-only field. If " + "the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`." ); } } if ( !( props.onChange || props.readOnly || props.disabled || props.checked == null ) ) { error( "You provided a `checked` prop to a form field without an " + "`onChange` handler. This will render a read-only field. If " + "the field should be mutable use `defaultChecked`. Otherwise, " + "set either `onChange` or `readOnly`." ); } } } /* eslint-disable max-len */ var ATTRIBUTE_NAME_START_CHAR = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD"; /* eslint-enable max-len */ var ATTRIBUTE_NAME_CHAR = ATTRIBUTE_NAME_START_CHAR + "\\-.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040"; var VALID_ATTRIBUTE_NAME_REGEX = new RegExp( "^[" + ATTRIBUTE_NAME_START_CHAR + "][" + ATTRIBUTE_NAME_CHAR + "]*$" ); var illegalAttributeNameCache = {}; var validatedAttributeNameCache = {}; function isAttributeNameSafe(attributeName) { if (hasOwnProperty.call(validatedAttributeNameCache, attributeName)) { return true; } if (hasOwnProperty.call(illegalAttributeNameCache, attributeName)) { return false; } if (VALID_ATTRIBUTE_NAME_REGEX.test(attributeName)) { validatedAttributeNameCache[attributeName] = true; return true; } illegalAttributeNameCache[attributeName] = true; { error("Invalid attribute name: `%s`", attributeName); } return false; } /** * Get the value for a attribute on a node. Only used in DEV for SSR validation. * The third argument is used as a hint of what the expected value is. Some * attributes have multiple equivalent values. */ function getValueForAttribute(node, name, expected) { { if (!isAttributeNameSafe(name)) { return; } if (!node.hasAttribute(name)) { // shouldRemoveAttribute switch (typeof expected) { case "function": case "symbol": // eslint-disable-line return expected; case "boolean": { var prefix = name.toLowerCase().slice(0, 5); if (prefix !== "data-" && prefix !== "aria-") { return expected; } } } return expected === undefined ? undefined : null; } var value = node.getAttribute(name); { checkAttributeStringCoercion(expected, name); } if (value === "" + expected) { return expected; } return value; } } function getValueForAttributeOnCustomComponent(node, name, expected) { { if (!isAttributeNameSafe(name)) { return; } if (!node.hasAttribute(name)) { // shouldRemoveAttribute switch (typeof expected) { case "symbol": case "object": // Symbols and objects are ignored when they're emitted so // it would be expected that they end up not having an attribute. return expected; case "function": { return expected; } case "boolean": { if (expected === false) { return expected; } } } return expected === undefined ? undefined : null; } var value = node.getAttribute(name); { if (value === "" && expected === true) { return true; } } { checkAttributeStringCoercion(expected, name); } if (value === "" + expected) { return expected; } return value; } } function setValueForAttribute(node, name, value) { if (isAttributeNameSafe(name)) { // If the prop isn't in the special list, treat it as a simple attribute. // shouldRemoveAttribute if (value === null) { node.removeAttribute(name); return; } switch (typeof value) { case "undefined": case "function": case "symbol": // eslint-disable-line node.removeAttribute(name); return; case "boolean": { var prefix = name.toLowerCase().slice(0, 5); if (prefix !== "data-" && prefix !== "aria-") { node.removeAttribute(name); return; } } } { checkAttributeStringCoercion(value, name); } node.setAttribute( name, enableTrustedTypesIntegration ? value : "" + value ); } } function setValueForKnownAttribute(node, name, value) { if (value === null) { node.removeAttribute(name); return; } switch (typeof value) { case "undefined": case "function": case "symbol": case "boolean": { node.removeAttribute(name); return; } } { checkAttributeStringCoercion(value, name); } node.setAttribute( name, enableTrustedTypesIntegration ? value : "" + value ); } function setValueForNamespacedAttribute(node, namespace, name, value) { if (value === null) { node.removeAttribute(name); return; } switch (typeof value) { case "undefined": case "function": case "symbol": case "boolean": { node.removeAttribute(name); return; } } { checkAttributeStringCoercion(value, name); } node.setAttributeNS( namespace, name, enableTrustedTypesIntegration ? value : "" + value ); } function setValueForPropertyOnCustomComponent(node, name, value) { if (name[0] === "o" && name[1] === "n") { var useCapture = name.endsWith("Capture"); var eventName = name.slice(2, useCapture ? name.length - 7 : undefined); var prevProps = getFiberCurrentPropsFromNode(node); var prevValue = prevProps != null ? prevProps[name] : null; if (typeof prevValue === "function") { node.removeEventListener(eventName, prevValue, useCapture); } if (typeof value === "function") { if (typeof prevValue !== "function" && prevValue !== null) { // If we previously assigned a non-function type into this node, then // remove it when switching to event listener mode. if (name in node) { node[name] = null; } else if (node.hasAttribute(name)) { node.removeAttribute(name); } } // $FlowFixMe[incompatible-cast] value can't be casted to EventListener. node.addEventListener(eventName, value, useCapture); return; } } if (name in node) { node[name] = value; return; } if (value === true) { node.setAttribute(name, ""); return; } // From here, it's the same as any attribute setValueForAttribute(node, name, value); } var ReactCurrentDispatcher$2 = ReactSharedInternals.ReactCurrentDispatcher; var prefix; function describeBuiltInComponentFrame(name, ownerFn) { { if (prefix === undefined) { // Extract the VM specific prefix used by each line. try { throw Error(); } catch (x) { var match = x.stack.trim().match(/\n( *(at )?)/); prefix = (match && match[1]) || ""; } } // We use the prefix to ensure our stacks line up with native stack frames. return "\n" + prefix + name; } } var reentry = false; var componentFrameCache; { var PossiblyWeakMap$2 = typeof WeakMap === "function" ? WeakMap : Map; componentFrameCache = new PossiblyWeakMap$2(); } /** * Leverages native browser/VM stack frames to get proper details (e.g. * filename, line + col number) for a single component in a component stack. We * do this by: * (1) throwing and catching an error in the function - this will be our * control error. * (2) calling the component which will eventually throw an error that we'll * catch - this will be our sample error. * (3) diffing the control and sample error stacks to find the stack frame * which represents our component. */ function describeNativeComponentFrame(fn, construct) { // If something asked for a stack inside a fake render, it should get ignored. if (!fn || reentry) { return ""; } { var frame = componentFrameCache.get(fn); if (frame !== undefined) { return frame; } } reentry = true; var previousPrepareStackTrace = Error.prepareStackTrace; // $FlowFixMe[incompatible-type] It does accept undefined. Error.prepareStackTrace = undefined; var previousDispatcher; { previousDispatcher = ReactCurrentDispatcher$2.current; // Set the dispatcher in DEV because this might be call in the render function // for warnings. ReactCurrentDispatcher$2.current = null; disableLogs(); } /** * Finding a common stack frame between sample and control errors can be * tricky given the different types and levels of stack trace truncation from * different JS VMs. So instead we'll attempt to control what that common * frame should be through this object method: * Having both the sample and control errors be in the function under the * `DescribeNativeComponentFrameRoot` property, + setting the `name` and * `displayName` properties of the function ensures that a stack * frame exists that has the method name `DescribeNativeComponentFrameRoot` in * it for both control and sample stacks. */ var RunInRootFrame = { DetermineComponentFrameRoot: function () { var control; try { // This should throw. if (construct) { // Something should be setting the props in the constructor. var Fake = function () { throw Error(); }; // $FlowFixMe[prop-missing] Object.defineProperty(Fake.prototype, "props", { set: function () { // We use a throwing setter instead of frozen or non-writable props // because that won't throw in a non-strict mode function. throw Error(); } }); if (typeof Reflect === "object" && Reflect.construct) { // We construct a different control for this case to include any extra // frames added by the construct call. try { Reflect.construct(Fake, []); } catch (x) { control = x; } Reflect.construct(fn, [], Fake); } else { try { Fake.call(); } catch (x) { control = x; } // $FlowFixMe[prop-missing] found when upgrading Flow fn.call(Fake.prototype); } } else { try { throw Error(); } catch (x) { control = x; } // TODO(luna): This will currently only throw if the function component // tries to access React/ReactDOM/props. We should probably make this throw // in simple components too var maybePromise = fn(); // If the function component returns a promise, it's likely an async // component, which we don't yet support. Attach a noop catch handler to // silence the error. // TODO: Implement component stacks for async client components? if (maybePromise && typeof maybePromise.catch === "function") { maybePromise.catch(function () {}); } } } catch (sample) { // This is inlined manually because closure doesn't do it for us. if (sample && control && typeof sample.stack === "string") { return [sample.stack, control.stack]; } } return [null, null]; } }; // $FlowFixMe[prop-missing] RunInRootFrame.DetermineComponentFrameRoot.displayName = "DetermineComponentFrameRoot"; var namePropDescriptor = Object.getOwnPropertyDescriptor( RunInRootFrame.DetermineComponentFrameRoot, "name" ); // Before ES6, the `name` property was not configurable. if (namePropDescriptor && namePropDescriptor.configurable) { // V8 utilizes a function's `name` property when generating a stack trace. Object.defineProperty( RunInRootFrame.DetermineComponentFrameRoot, // Configurable properties can be updated even if its writable descriptor // is set to `false`. // $FlowFixMe[cannot-write] "name", { value: "DetermineComponentFrameRoot" } ); } try { var _RunInRootFrame$Deter = RunInRootFrame.DetermineComponentFrameRoot(), sampleStack = _RunInRootFrame$Deter[0], controlStack = _RunInRootFrame$Deter[1]; if (sampleStack && controlStack) { // This extracts the first frame from the sample that isn't also in the control. // Skipping one frame that we assume is the frame that calls the two. var sampleLines = sampleStack.split("\n"); var controlLines = controlStack.split("\n"); var s = 0; var c = 0; while ( s < sampleLines.length && !sampleLines[s].includes("DetermineComponentFrameRoot") ) { s++; } while ( c < controlLines.length && !controlLines[c].includes("DetermineComponentFrameRoot") ) { c++; } // We couldn't find our intentionally injected common root frame, attempt // to find another common root frame by search from the bottom of the // control stack... if (s === sampleLines.length || c === controlLines.length) { s = sampleLines.length - 1; c = controlLines.length - 1; while (s >= 1 && c >= 0 && sampleLines[s] !== controlLines[c]) { // We expect at least one stack frame to be shared. // Typically this will be the root most one. However, stack frames may be // cut off due to maximum stack limits. In this case, one maybe cut off // earlier than the other. We assume that the sample is longer or the same // and there for cut off earlier. So we should find the root most frame in // the sample somewhere in the control. c--; } } for (; s >= 1 && c >= 0; s--, c--) { // Next we find the first one that isn't the same which should be the // frame that called our sample function and the control. if (sampleLines[s] !== controlLines[c]) { // In V8, the first line is describing the message but other VMs don't. // If we're about to return the first line, and the control is also on the same // line, that's a pretty good indicator that our sample threw at same line as // the control. I.e. before we entered the sample frame. So we ignore this result. // This can happen if you passed a class to function component, or non-function. if (s !== 1 || c !== 1) { do { s--; c--; // We may still have similar intermediate frames from the construct call. // The next one that isn't the same should be our match though. if (c < 0 || sampleLines[s] !== controlLines[c]) { // V8 adds a "new" prefix for native classes. Let's remove it to make it prettier. var _frame = "\n" + sampleLines[s].replace(" at new ", " at "); // If our component frame is labeled "" // but we have a user-provided "displayName" // splice it in to make the stack more readable. if (fn.displayName && _frame.includes("")) { _frame = _frame.replace("", fn.displayName); } if (true) { if (typeof fn === "function") { componentFrameCache.set(fn, _frame); } } // Return the line we found. return _frame; } } while (s >= 1 && c >= 0); } break; } } } } finally { reentry = false; { ReactCurrentDispatcher$2.current = previousDispatcher; reenableLogs(); } Error.prepareStackTrace = previousPrepareStackTrace; } // Fallback to just using the name if we couldn't make it throw. var name = fn ? fn.displayName || fn.name : ""; var syntheticFrame = name ? describeBuiltInComponentFrame(name) : ""; { if (typeof fn === "function") { componentFrameCache.set(fn, syntheticFrame); } } return syntheticFrame; } function describeClassComponentFrame(ctor, ownerFn) { { return describeNativeComponentFrame(ctor, true); } } function describeFunctionComponentFrame(fn, ownerFn) { { return describeNativeComponentFrame(fn, false); } } function describeFiber(fiber) { switch (fiber.tag) { case HostHoistable: case HostSingleton: case HostComponent: return describeBuiltInComponentFrame(fiber.type); case LazyComponent: return describeBuiltInComponentFrame("Lazy"); case SuspenseComponent: return describeBuiltInComponentFrame("Suspense"); case SuspenseListComponent: return describeBuiltInComponentFrame("SuspenseList"); case FunctionComponent: case IndeterminateComponent: case SimpleMemoComponent: return describeFunctionComponentFrame(fiber.type); case ForwardRef: return describeFunctionComponentFrame(fiber.type.render); case ClassComponent: return describeClassComponentFrame(fiber.type); default: return ""; } } function getStackByFiberInDevAndProd(workInProgress) { try { var info = ""; var node = workInProgress; do { info += describeFiber(node); // $FlowFixMe[incompatible-type] we bail out when we get a null node = node.return; } while (node); return info; } catch (x) { return "\nError generating stack: " + x.message + "\n" + x.stack; } } var ReactDebugCurrentFrame = ReactSharedInternals.ReactDebugCurrentFrame; var current = null; var isRendering = false; function getCurrentFiberOwnerNameInDevOrNull() { { if (current === null) { return null; } var owner = current._debugOwner; if (owner !== null && typeof owner !== "undefined") { return getComponentNameFromFiber(owner); } } return null; } function getCurrentFiberStackInDev() { { if (current === null) { return ""; } // Safe because if current fiber exists, we are reconciling, // and it is guaranteed to be the work-in-progress version. return getStackByFiberInDevAndProd(current); } } function resetCurrentFiber() { { ReactDebugCurrentFrame.getCurrentStack = null; current = null; isRendering = false; } } function setCurrentFiber(fiber) { { ReactDebugCurrentFrame.getCurrentStack = fiber === null ? null : getCurrentFiberStackInDev; current = fiber; isRendering = false; } } function getCurrentFiber() { { return current; } } function setIsRendering(rendering) { { isRendering = rendering; } } // around this limitation, we use an opaque type that can only be obtained by // passing the value through getToStringValue first. function toString(value) { // The coercion safety check is performed in getToStringValue(). // eslint-disable-next-line react-internal/safe-string-coercion return "" + value; } function getToStringValue(value) { switch (typeof value) { case "boolean": case "number": case "string": case "undefined": return value; case "object": { checkFormFieldValueStringCoercion(value); } return value; default: // function, symbol are assigned as empty strings return ""; } } function isCheckable(elem) { var type = elem.type; var nodeName = elem.nodeName; return ( nodeName && nodeName.toLowerCase() === "input" && (type === "checkbox" || type === "radio") ); } function getTracker(node) { return node._valueTracker; } function detachTracker(node) { node._valueTracker = null; } function getValueFromNode(node) { var value = ""; if (!node) { return value; } if (isCheckable(node)) { value = node.checked ? "true" : "false"; } else { value = node.value; } return value; } function trackValueOnNode(node) { var valueField = isCheckable(node) ? "checked" : "value"; var descriptor = Object.getOwnPropertyDescriptor( node.constructor.prototype, valueField ); { checkFormFieldValueStringCoercion(node[valueField]); } var currentValue = "" + node[valueField]; // if someone has already defined a value or Safari, then bail // and don't track value will cause over reporting of changes, // but it's better then a hard failure // (needed for certain tests that spyOn input values and Safari) if ( node.hasOwnProperty(valueField) || typeof descriptor === "undefined" || typeof descriptor.get !== "function" || typeof descriptor.set !== "function" ) { return; } var get = descriptor.get, set = descriptor.set; Object.defineProperty(node, valueField, { configurable: true, // $FlowFixMe[missing-this-annot] get: function () { return get.call(this); }, // $FlowFixMe[missing-local-annot] // $FlowFixMe[missing-this-annot] set: function (value) { { checkFormFieldValueStringCoercion(value); } currentValue = "" + value; set.call(this, value); } }); // We could've passed this the first time // but it triggers a bug in IE11 and Edge 14/15. // Calling defineProperty() again should be equivalent. // https://github.com/facebook/react/issues/11768 Object.defineProperty(node, valueField, { enumerable: descriptor.enumerable }); var tracker = { getValue: function () { return currentValue; }, setValue: function (value) { { checkFormFieldValueStringCoercion(value); } currentValue = "" + value; }, stopTracking: function () { detachTracker(node); delete node[valueField]; } }; return tracker; } function track(node) { if (getTracker(node)) { return; } node._valueTracker = trackValueOnNode(node); } function updateValueIfChanged(node) { if (!node) { return false; } var tracker = getTracker(node); // if there is no tracker at this point it's unlikely // that trying again will succeed if (!tracker) { return true; } var lastValue = tracker.getValue(); var nextValue = getValueFromNode(node); if (nextValue !== lastValue) { tracker.setValue(nextValue); return true; } return false; } function getActiveElement(doc) { doc = doc || (typeof document !== "undefined" ? document : undefined); if (typeof doc === "undefined") { return null; } try { return doc.activeElement || doc.body; } catch (e) { return doc.body; } } // When passing user input into querySelector(All) the embedded string must not alter // the semantics of the query. This escape function is safe to use when we know the // provided value is going to be wrapped in double quotes as part of an attribute selector // Do not use it anywhere else // we escape double quotes and backslashes var escapeSelectorAttributeValueInsideDoubleQuotesRegex = /[\n\"\\]/g; function escapeSelectorAttributeValueInsideDoubleQuotes(value) { return value.replace( escapeSelectorAttributeValueInsideDoubleQuotesRegex, function (ch) { return "\\" + ch.charCodeAt(0).toString(16) + " "; } ); } var didWarnValueDefaultValue$1 = false; var didWarnCheckedDefaultChecked = false; /** * Implements an host component that allows setting these optional * props: `checked`, `value`, `defaultChecked`, and `defaultValue`. * * If `checked` or `value` are not supplied (or null/undefined), user actions * that affect the checked state or value will trigger updates to the element. * * If they are supplied (and not null/undefined), the rendered element will not * trigger updates to the element. Instead, the props must change in order for * the rendered element to be updated. * * The rendered element will be initialized as unchecked (or `defaultChecked`) * with an empty value (or `defaultValue`). * * See http://www.w3.org/TR/2012/WD-html5-20121025/the-input-element.html */ function validateInputProps(element, props) { { // Normally we check for undefined and null the same, but explicitly specifying both // properties, at all is probably worth warning for. We could move this either direction // and just make it ok to pass null or just check hasOwnProperty. if ( props.checked !== undefined && props.defaultChecked !== undefined && !didWarnCheckedDefaultChecked ) { error( "%s contains an input of type %s with both checked and defaultChecked props. " + "Input elements must be either controlled or uncontrolled " + "(specify either the checked prop, or the defaultChecked prop, but not " + "both). Decide between using a controlled or uncontrolled input " + "element and remove one of these props. More info: " + "https://reactjs.org/link/controlled-components", getCurrentFiberOwnerNameInDevOrNull() || "A component", props.type ); didWarnCheckedDefaultChecked = true; } if ( props.value !== undefined && props.defaultValue !== undefined && !didWarnValueDefaultValue$1 ) { error( "%s contains an input of type %s with both value and defaultValue props. " + "Input elements must be either controlled or uncontrolled " + "(specify either the value prop, or the defaultValue prop, but not " + "both). Decide between using a controlled or uncontrolled input " + "element and remove one of these props. More info: " + "https://reactjs.org/link/controlled-components", getCurrentFiberOwnerNameInDevOrNull() || "A component", props.type ); didWarnValueDefaultValue$1 = true; } } } function updateInput( element, value, defaultValue, lastDefaultValue, checked, defaultChecked, type, name ) { var node = element; // Temporarily disconnect the input from any radio buttons. // Changing the type or name as the same time as changing the checked value // needs to be atomically applied. We can only ensure that by disconnecting // the name while do the mutations and then reapply the name after that's done. node.name = ""; if ( type != null && typeof type !== "function" && typeof type !== "symbol" && typeof type !== "boolean" ) { { checkAttributeStringCoercion(type, "type"); } node.type = type; } else { node.removeAttribute("type"); } if (value != null) { if (type === "number") { if ( // $FlowFixMe[incompatible-type] (value === 0 && node.value === "") || // We explicitly want to coerce to number here if possible. // eslint-disable-next-line node.value != value ) { node.value = toString(getToStringValue(value)); } } else if (node.value !== toString(getToStringValue(value))) { node.value = toString(getToStringValue(value)); } } else if (type === "submit" || type === "reset") { // Submit/reset inputs need the attribute removed completely to avoid // blank-text buttons. node.removeAttribute("value"); } if (disableInputAttributeSyncing) { // When not syncing the value attribute, React only assigns a new value // whenever the defaultValue React prop has changed. When not present, // React does nothing if (defaultValue != null) { setDefaultValue(node, type, getToStringValue(defaultValue)); } else if (lastDefaultValue != null) { node.removeAttribute("value"); } } else { // When syncing the value attribute, the value comes from a cascade of // properties: // 1. The value React property // 2. The defaultValue React property // 3. Otherwise there should be no change if (value != null) { setDefaultValue(node, type, getToStringValue(value)); } else if (defaultValue != null) { setDefaultValue(node, type, getToStringValue(defaultValue)); } else if (lastDefaultValue != null) { node.removeAttribute("value"); } } if (disableInputAttributeSyncing) { // When not syncing the checked attribute, the attribute is directly // controllable from the defaultValue React property. It needs to be // updated as new props come in. if (defaultChecked == null) { node.removeAttribute("checked"); } else { node.defaultChecked = !!defaultChecked; } } else { // When syncing the checked attribute, it only changes when it needs // to be removed, such as transitioning from a checkbox into a text input if (checked == null && defaultChecked != null) { node.defaultChecked = !!defaultChecked; } } if (checked != null) { // Important to set this even if it's not a change in order to update input // value tracking with radio buttons // TODO: Should really update input value tracking for the whole radio // button group in an effect or something (similar to #27024) node.checked = checked && typeof checked !== "function" && typeof checked !== "symbol"; } if ( name != null && typeof name !== "function" && typeof name !== "symbol" && typeof name !== "boolean" ) { { checkAttributeStringCoercion(name, "name"); } node.name = toString(getToStringValue(name)); } else { node.removeAttribute("name"); } } function initInput( element, value, defaultValue, checked, defaultChecked, type, name, isHydrating ) { var node = element; if ( type != null && typeof type !== "function" && typeof type !== "symbol" && typeof type !== "boolean" ) { { checkAttributeStringCoercion(type, "type"); } node.type = type; } if (value != null || defaultValue != null) { var isButton = type === "submit" || type === "reset"; // Avoid setting value attribute on submit/reset inputs as it overrides the // default value provided by the browser. See: #12872 if (isButton && (value === undefined || value === null)) { return; } var defaultValueStr = defaultValue != null ? toString(getToStringValue(defaultValue)) : ""; var initialValue = value != null ? toString(getToStringValue(value)) : defaultValueStr; // Do not assign value if it is already set. This prevents user text input // from being lost during SSR hydration. if (!isHydrating) { if (disableInputAttributeSyncing) { // When not syncing the value attribute, the value property points // directly to the React prop. Only assign it if it exists. if (value != null) { // Always assign on buttons so that it is possible to assign an // empty string to clear button text. // // Otherwise, do not re-assign the value property if is empty. This // potentially avoids a DOM write and prevents Firefox (~60.0.1) from // prematurely marking required inputs as invalid. Equality is compared // to the current value in case the browser provided value is not an // empty string. if ( isButton || toString(getToStringValue(value)) !== node.value ) { node.value = toString(getToStringValue(value)); } } } else { // When syncing the value attribute, the value property should use // the wrapperState._initialValue property. This uses: // // 1. The value React property when present // 2. The defaultValue React property when present // 3. An empty string if (initialValue !== node.value) { node.value = initialValue; } } } if (disableInputAttributeSyncing) { // When not syncing the value attribute, assign the value attribute // directly from the defaultValue React property (when present) if (defaultValue != null) { node.defaultValue = defaultValueStr; } } else { // Otherwise, the value attribute is synchronized to the property, // so we assign defaultValue to the same thing as the value property // assignment step above. node.defaultValue = initialValue; } } // Normally, we'd just do `node.checked = node.checked` upon initial mount, less this bug // this is needed to work around a chrome bug where setting defaultChecked // will sometimes influence the value of checked (even after detachment). // Reference: https://bugs.chromium.org/p/chromium/issues/detail?id=608416 // We need to temporarily unset name to avoid disrupting radio button groups. var checkedOrDefault = checked != null ? checked : defaultChecked; // TODO: This 'function' or 'symbol' check isn't replicated in other places // so this semantic is inconsistent. var initialChecked = typeof checkedOrDefault !== "function" && typeof checkedOrDefault !== "symbol" && !!checkedOrDefault; if (isHydrating) { // Detach .checked from .defaultChecked but leave user input alone node.checked = node.checked; } else { node.checked = !!initialChecked; } if (disableInputAttributeSyncing) { // Only assign the checked attribute if it is defined. This saves // a DOM write when controlling the checked attribute isn't needed // (text inputs, submit/reset) if (defaultChecked != null) { node.defaultChecked = !node.defaultChecked; node.defaultChecked = !!defaultChecked; } } else { // When syncing the checked attribute, both the checked property and // attribute are assigned at the same time using defaultChecked. This uses: // // 1. The checked React property when present // 2. The defaultChecked React property when present // 3. Otherwise, false node.defaultChecked = !node.defaultChecked; node.defaultChecked = !!initialChecked; } // Name needs to be set at the end so that it applies atomically to connected radio buttons. if ( name != null && typeof name !== "function" && typeof name !== "symbol" && typeof name !== "boolean" ) { { checkAttributeStringCoercion(name, "name"); } node.name = name; } } function restoreControlledInputState(element, props) { var rootNode = element; updateInput( rootNode, props.value, props.defaultValue, props.defaultValue, props.checked, props.defaultChecked, props.type, props.name ); var name = props.name; if (props.type === "radio" && name != null) { var queryRoot = rootNode; while (queryRoot.parentNode) { queryRoot = queryRoot.parentNode; } // If `rootNode.form` was non-null, then we could try `form.elements`, // but that sometimes behaves strangely in IE8. We could also try using // `form.getElementsByName`, but that will only return direct children // and won't include inputs that use the HTML5 `form=` attribute. Since // the input might not even be in a form. It might not even be in the // document. Let's just use the local `querySelectorAll` to ensure we don't // miss anything. { checkAttributeStringCoercion(name, "name"); } var group = queryRoot.querySelectorAll( 'input[name="' + escapeSelectorAttributeValueInsideDoubleQuotes("" + name) + '"][type="radio"]' ); for (var i = 0; i < group.length; i++) { var otherNode = group[i]; if (otherNode === rootNode || otherNode.form !== rootNode.form) { continue; } // This will throw if radio buttons rendered by different copies of React // and the same name are rendered into the same form (same as #1939). // That's probably okay; we don't support it just as we don't support // mixing React radio buttons with non-React ones. var otherProps = getFiberCurrentPropsFromNode(otherNode); if (!otherProps) { throw new Error( "ReactDOMInput: Mixing React and non-React radio inputs with the " + "same `name` is not supported." ); } // If this is a controlled radio button group, forcing the input that // was previously checked to update will cause it to be come re-checked // as appropriate. updateInput( otherNode, otherProps.value, otherProps.defaultValue, otherProps.defaultValue, otherProps.checked, otherProps.defaultChecked, otherProps.type, otherProps.name ); } // If any updateInput() call set .checked to true, an input in this group // (often, `rootNode` itself) may have become unchecked for (var _i = 0; _i < group.length; _i++) { var _otherNode = group[_i]; if (_otherNode.form !== rootNode.form) { continue; } updateValueIfChanged(_otherNode); } } } // In Chrome, assigning defaultValue to certain input types triggers input validation. // For number inputs, the display value loses trailing decimal points. For email inputs, // Chrome raises "The specified value is not a valid email address". // // Here we check to see if the defaultValue has actually changed, avoiding these problems // when the user is inputting text // // https://github.com/facebook/react/issues/7253 function setDefaultValue(node, type, value) { if ( // Focused number inputs synchronize on blur. See ChangeEventPlugin.js type !== "number" || getActiveElement(node.ownerDocument) !== node ) { if (node.defaultValue !== toString(value)) { node.defaultValue = toString(value); } } } var didWarnSelectedSetOnOption = false; var didWarnInvalidChild = false; var didWarnInvalidInnerHTML = false; /** * Implements an