diff --git a/Libraries/Renderer/REVISION b/Libraries/Renderer/REVISION index 617cce49d16..06ec4e875f8 100644 --- a/Libraries/Renderer/REVISION +++ b/Libraries/Renderer/REVISION @@ -1 +1 @@ -de84d5c1079b12455058ee177fb3ff97cc0fb8d0 \ No newline at end of file +c0fe8d6f6942f5cbc93c09825e803ba8cf950522 \ No newline at end of file diff --git a/Libraries/Renderer/oss/ReactFabric-dev.js b/Libraries/Renderer/oss/ReactFabric-dev.js index eb3f3e078b3..3597c91b11f 100644 --- a/Libraries/Renderer/oss/ReactFabric-dev.js +++ b/Libraries/Renderer/oss/ReactFabric-dev.js @@ -545,9 +545,53 @@ var validateEventDispatches = void 0; }; } +/** + * Dispatch the event to the listener. + * @param {SyntheticEvent} event SyntheticEvent to handle + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @param {function} listener Application-level callback + * @param {*} inst Internal component instance + */ +function executeDispatch(event, simulated, listener, inst) { + var type = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError( + type, + listener, + undefined, + event + ); + event.currentTarget = null; +} + /** * Standard/simple iteration through an event's collected dispatches. */ +function executeDispatchesInOrder(event, simulated) { + var dispatchListeners = event._dispatchListeners; + var dispatchInstances = event._dispatchInstances; + { + validateEventDispatches(event); + } + if (Array.isArray(dispatchListeners)) { + for (var i = 0; i < dispatchListeners.length; i++) { + if (event.isPropagationStopped()) { + break; + } + // Listeners and Instances are two parallel arrays that are always in sync. + executeDispatch( + event, + simulated, + dispatchListeners[i], + dispatchInstances[i] + ); + } + } else if (dispatchListeners) { + executeDispatch(event, simulated, dispatchListeners, dispatchInstances); + } + event._dispatchListeners = null; + event._dispatchInstances = null; +} /** * Standard/simple iteration through an event's collected dispatches, but stops @@ -686,6 +730,35 @@ function forEachAccumulated(arr, cb, scope) { } } +/** + * Internal queue of events that have accumulated their dispatches and are + * waiting to have their dispatches executed. + */ +var eventQueue = null; + +/** + * Dispatches an event and releases it back into the pool, unless persistent. + * + * @param {?object} event Synthetic event to be dispatched. + * @param {boolean} simulated If the event is simulated (changes exn behavior) + * @private + */ +var executeDispatchesAndRelease = function(event, simulated) { + if (event) { + executeDispatchesInOrder(event, simulated); + + if (!event.isPersistent()) { + event.constructor.release(event); + } + } +}; +var executeDispatchesAndReleaseSimulated = function(e) { + return executeDispatchesAndRelease(e, true); +}; +var executeDispatchesAndReleaseTopLevel = function(e) { + return executeDispatchesAndRelease(e, false); +}; + function isInteractive(tag) { return ( tag === "button" || @@ -785,6 +858,87 @@ function getListener(inst, registrationName) { return listener; } +/** + * Allows registered plugins an opportunity to extract events from top-level + * native browser events. + * + * @return {*} An accumulation of synthetic events. + * @internal + */ +function extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events = null; + for (var i = 0; i < plugins.length; i++) { + // Not every plugin in the ordering may be loaded at runtime. + var possiblePlugin = plugins[i]; + if (possiblePlugin) { + var extractedEvents = possiblePlugin.extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + if (extractedEvents) { + events = accumulateInto(events, extractedEvents); + } + } + } + return events; +} + +function runEventsInBatch(events, simulated) { + if (events !== null) { + eventQueue = accumulateInto(eventQueue, events); + } + + // Set `eventQueue` to null before processing it so that we can tell if more + // events get enqueued while processing. + var processingEventQueue = eventQueue; + eventQueue = null; + + if (!processingEventQueue) { + return; + } + + if (simulated) { + forEachAccumulated( + processingEventQueue, + executeDispatchesAndReleaseSimulated + ); + } else { + forEachAccumulated( + processingEventQueue, + executeDispatchesAndReleaseTopLevel + ); + } + invariant( + !eventQueue, + "processEventQueue(): Additional events were enqueued while processing " + + "an event queue. Support for this has not yet been implemented." + ); + // This would be a good time to rethrow if any of the event handlers threw. + ReactErrorUtils.rethrowCaughtError(); +} + +function runExtractedEventsInBatch( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget +) { + var events = extractEvents( + topLevelType, + targetInst, + nativeEvent, + nativeEventTarget + ); + runEventsInBatch(events, false); +} + var IndeterminateComponent = 0; // Before we know whether it is functional or class var FunctionalComponent = 1; var ClassComponent = 2; @@ -2331,7 +2485,7 @@ var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 0xeacb; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 0xeacc; -var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profile_root") : 0xeacc; +var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 0xead2; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 0xeacd; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 0xeace; var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 0xeacf; @@ -2375,6 +2529,56 @@ function createPortal( }; } +// Use to restore controlled state after a change event has fired. + +var fiberHostComponent = null; + +var restoreTarget = null; +var restoreQueue = null; + +function restoreStateOfTarget(target) { + // We perform this translation at the end of the event loop so that we + // always receive the correct fiber here + var internalInstance = getInstanceFromNode(target); + if (!internalInstance) { + // Unmounted + return; + } + invariant( + fiberHostComponent && + typeof fiberHostComponent.restoreControlledState === "function", + "Fiber needs to be injected to handle a fiber target for controlled " + + "events. This error is likely caused by a bug in React. Please file an issue." + ); + var props = getFiberCurrentPropsFromNode(internalInstance.stateNode); + fiberHostComponent.restoreControlledState( + internalInstance.stateNode, + internalInstance.type, + props + ); +} + +function needsStateRestore() { + return restoreTarget !== null || restoreQueue !== null; +} + +function restoreStateIfNeeded() { + if (!restoreTarget) { + return; + } + var target = restoreTarget; + var queuedTargets = restoreQueue; + restoreTarget = null; + restoreQueue = null; + + restoreStateOfTarget(target); + if (queuedTargets) { + for (var i = 0; i < queuedTargets.length; i++) { + restoreStateOfTarget(queuedTargets[i]); + } + } +} + // Used as a way to call batchedUpdates when we don't have a reference to // the renderer. Such as when we're dispatching events or if third party // libraries need to call batchedUpdates. Eventually, this API will go away when @@ -2390,6 +2594,33 @@ var _interactiveUpdates = function(fn, a, b) { }; var _flushInteractiveUpdates = function() {}; +var isBatching = false; +function batchedUpdates(fn, bookkeeping) { + if (isBatching) { + // If we are currently inside another batch, we need to wait until it + // fully completes before restoring state. + return fn(bookkeeping); + } + isBatching = true; + try { + return _batchedUpdates(fn, bookkeeping); + } finally { + // Here we wait until all updates have propagated, which is important + // when using controlled components within layers: + // https://github.com/facebook/react/issues/1698 + // Then we restore state of any controlled component. + isBatching = false; + var controlledComponentsHavePendingUpdates = needsStateRestore(); + if (controlledComponentsHavePendingUpdates) { + // If a controlled event was fired, we may need to restore the state of + // the DOM node back to the controlled value. This is necessary when React + // bails out of the update without touching the DOM. + _flushInteractiveUpdates(); + restoreStateIfNeeded(); + } + } +} + var injection$2 = { injectRenderer: function(renderer) { _batchedUpdates = renderer.batchedUpdates; @@ -3914,42 +4145,9 @@ function createFiberFromElement(element, mode, expirationTime) { // mode compatible. mode |= StrictMode; break; - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break; - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; - break; - default: - if (typeof type.tag === "number") { - // Currently assumed to be a continuation and therefore is a - // fiber already. - // TODO: The yield system is currently broken for updates in - // some cases. The reified yield stores a fiber, but we don't - // know which fiber that is; the current or a workInProgress? - // When the continuation gets rendered here we don't know if we - // can reuse that fiber or if we need to clone it. There is - // probably a clever way to restructure this. - fiber = type; - fiber.pendingProps = pendingProps; - fiber.expirationTime = expirationTime; - return fiber; - } else { - throwOnInvalidElementType(type, owner); - } - break; - } - } else { - throwOnInvalidElementType(type, owner); - } - } + default: + fiberTag = getFiberTagFromObjectType(type, owner); + break; } } @@ -3965,33 +4163,47 @@ function createFiberFromElement(element, mode, expirationTime) { return fiber; } -function throwOnInvalidElementType(type, owner) { - var info = ""; - { - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - info += - " You likely forgot to export your component from the file " + - "it's defined in, or you might have mixed up default and " + - "named imports."; - } - var ownerName = owner ? getComponentName(owner) : null; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; +function getFiberTagFromObjectType(type, owner) { + var $$typeof = + typeof type === "object" && type !== null ? type.$$typeof : null; + + switch ($$typeof) { + case REACT_PROVIDER_TYPE: + return ContextProvider; + case REACT_CONTEXT_TYPE: + // This is a consumer + return ContextConsumer; + case REACT_FORWARD_REF_TYPE: + return ForwardRef; + default: { + var info = ""; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and " + + "named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } + invariant( + false, + "Element type is invalid: expected a string (for built-in " + + "components) or a class/function (for composite components) " + + "but got: %s.%s", + type == null ? type : typeof type, + info + ); } } - invariant( - false, - "Element type is invalid: expected a string (for built-in " + - "components) or a class/function (for composite components) " + - "but got: %s.%s", - type == null ? type : typeof type, - info - ); } function createFiberFromFragment(elements, mode, expirationTime, key) { @@ -4399,15 +4611,15 @@ var ReactStrictModeWarnings = { pendingUnsafeLifecycleWarnings = new Map(); }; - var getStrictRoot = function(fiber) { + var findStrictRoot = function(fiber) { var maybeStrictRoot = null; - while (fiber !== null) { - if (fiber.mode & StrictMode) { - maybeStrictRoot = fiber; + var node = fiber; + while (node !== null) { + if (node.mode & StrictMode) { + maybeStrictRoot = node; } - - fiber = fiber.return; + node = node.return; } return maybeStrictRoot; @@ -4517,7 +4729,15 @@ var ReactStrictModeWarnings = { fiber, instance ) { - var strictRoot = getStrictRoot(fiber); + var strictRoot = findStrictRoot(fiber); + if (strictRoot === null) { + warning( + false, + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + return; + } // Dedup strategy: Warn once per component. // This is difficult to track any other way since component names @@ -9832,7 +10052,7 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; function logError(boundary, errorInfo) { var source = errorInfo.source; var stack = errorInfo.stack; - if (stack === null) { + if (stack === null && source !== null) { stack = getStackAddendumByWorkInProgressFiber(source); } @@ -11892,6 +12112,7 @@ var ReactFiberNewContext = function(stack, isPrimaryRenderer) { context._changedBits = providerFiber.stateNode; { !( + context._currentRenderer === undefined || context._currentRenderer === null || context._currentRenderer === rendererSigil ) @@ -11912,6 +12133,7 @@ var ReactFiberNewContext = function(stack, isPrimaryRenderer) { context._changedBits2 = providerFiber.stateNode; { !( + context._currentRenderer2 === undefined || context._currentRenderer2 === null || context._currentRenderer2 === rendererSigil ) @@ -12260,10 +12482,20 @@ var ReactFiberScheduler = function(config) { } // Restore the original state of the work-in-progress + if (stashedWorkInProgressProperties === null) { + // This should never happen. Don't throw because this code is DEV-only. + warning( + false, + "Could not replay rendering after an error. This is likely a bug in React. " + + "Please file an issue." + ); + return; + } assignFiberPropertiesInDEV( failedUnitOfWork, stashedWorkInProgressProperties ); + switch (failedUnitOfWork.tag) { case HostRoot: popHostContainer(failedUnitOfWork); @@ -12988,43 +13220,52 @@ var ReactFiberScheduler = function(config) { // This is a fatal error. didFatal = true; onUncaughtError(thrownValue); - break; - } + } else { + { + // Reset global debug state + // We assume this is defined in DEV + resetCurrentlyProcessingQueue(); + } - { - // Reset global debug state - // We assume this is defined in DEV - resetCurrentlyProcessingQueue(); - } - - if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { var failedUnitOfWork = nextUnitOfWork; - replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); - } + if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { + replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); + } - var sourceFiber = nextUnitOfWork; - var returnFiber = sourceFiber.return; - if (returnFiber === null) { - // This is the root. The root could capture its own errors. However, - // we don't know if it errors before or after we pushed the host - // context. This information is needed to avoid a stack mismatch. - // Because we're not sure, treat this as a fatal error. We could track - // which phase it fails in, but doesn't seem worth it. At least - // for now. - didFatal = true; - onUncaughtError(thrownValue); - break; + // TODO: we already know this isn't true in some cases. + // At least this shows a nicer error message until we figure out the cause. + // https://github.com/facebook/react/issues/12449#issuecomment-386727431 + invariant( + nextUnitOfWork !== null, + "Failed to replay rendering after an error. This " + + "is likely caused by a bug in React. Please file an issue " + + "with a reproducing case to help us find it." + ); + + var sourceFiber = nextUnitOfWork; + var returnFiber = sourceFiber.return; + if (returnFiber === null) { + // This is the root. The root could capture its own errors. However, + // we don't know if it errors before or after we pushed the host + // context. This information is needed to avoid a stack mismatch. + // Because we're not sure, treat this as a fatal error. We could track + // which phase it fails in, but doesn't seem worth it. At least + // for now. + didFatal = true; + onUncaughtError(thrownValue); + break; + } + throwException( + root, + returnFiber, + sourceFiber, + thrownValue, + nextRenderIsExpired, + nextRenderExpirationTime, + mostRecentCurrentTimeMs + ); + nextUnitOfWork = completeUnitOfWork(sourceFiber); } - throwException( - root, - returnFiber, - sourceFiber, - thrownValue, - nextRenderIsExpired, - nextRenderExpirationTime, - mostRecentCurrentTimeMs - ); - nextUnitOfWork = completeUnitOfWork(sourceFiber); } break; } while (true); @@ -14210,6 +14451,20 @@ function cancelDeferredCallback(callbackID) { clearTimeout(callbackID); } +function dispatchEvent(target, topLevelType, nativeEvent) { + var targetFiber = target; + batchedUpdates(function() { + runExtractedEventsInBatch( + topLevelType, + targetFiber, + nativeEvent, + nativeEvent.target + ); + }); + // React Native doesn't use ReactControlledComponent but if it did, here's + // where it would do it. +} + function _classCallCheck$1(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); @@ -14223,9 +14478,18 @@ function _classCallCheck$1(instance, Constructor) { // This means that they never overlap. var nextReactTag = 2; +// TODO: Remove this conditional once all changes have propagated. +if (FabricUIManager.registerEventHandler) { + /** + * Register the event emitter with the native bridge + */ + FabricUIManager.registerEventHandler(dispatchEvent); +} + /** * This is used for refs on host components. */ + var ReactFabricHostComponent = (function() { function ReactFabricHostComponent(tag, viewConfig, props) { _classCallCheck$1(this, ReactFabricHostComponent); diff --git a/Libraries/Renderer/oss/ReactFabric-prod.js b/Libraries/Renderer/oss/ReactFabric-prod.js index c4ca5aba4be..6f17e0bfb3a 100644 --- a/Libraries/Renderer/oss/ReactFabric-prod.js +++ b/Libraries/Renderer/oss/ReactFabric-prod.js @@ -23,8 +23,72 @@ var invariant = require("fbjs/lib/invariant"), emptyObject = require("fbjs/lib/emptyObject"), shallowEqual = require("fbjs/lib/shallowEqual"), ExceptionsManager = require("ExceptionsManager"), - FabricUIManager = require("FabricUIManager"), - eventPluginOrder = null, + FabricUIManager = require("FabricUIManager"); +function invokeGuardedCallback(name, func, context, a, b, c, d, e, f) { + this._hasCaughtError = !1; + this._caughtError = null; + var funcArgs = Array.prototype.slice.call(arguments, 3); + try { + func.apply(context, funcArgs); + } catch (error) { + (this._caughtError = error), (this._hasCaughtError = !0); + } +} +var ReactErrorUtils = { + _caughtError: null, + _hasCaughtError: !1, + _rethrowError: null, + _hasRethrowError: !1, + invokeGuardedCallback: function(name, func, context, a, b, c, d, e, f) { + invokeGuardedCallback.apply(ReactErrorUtils, arguments); + }, + invokeGuardedCallbackAndCatchFirstError: function( + name, + func, + context, + a, + b, + c, + d, + e, + f + ) { + ReactErrorUtils.invokeGuardedCallback.apply(this, arguments); + if (ReactErrorUtils.hasCaughtError()) { + var error = ReactErrorUtils.clearCaughtError(); + ReactErrorUtils._hasRethrowError || + ((ReactErrorUtils._hasRethrowError = !0), + (ReactErrorUtils._rethrowError = error)); + } + }, + rethrowCaughtError: function() { + return rethrowCaughtError.apply(ReactErrorUtils, arguments); + }, + hasCaughtError: function() { + return ReactErrorUtils._hasCaughtError; + }, + clearCaughtError: function() { + if (ReactErrorUtils._hasCaughtError) { + var error = ReactErrorUtils._caughtError; + ReactErrorUtils._caughtError = null; + ReactErrorUtils._hasCaughtError = !1; + return error; + } + invariant( + !1, + "clearCaughtError was called but no error was captured. This error is likely caused by a bug in React. Please file an issue." + ); + } +}; +function rethrowCaughtError() { + if (ReactErrorUtils._hasRethrowError) { + var error = ReactErrorUtils._rethrowError; + ReactErrorUtils._rethrowError = null; + ReactErrorUtils._hasRethrowError = !1; + throw error; + } +} +var eventPluginOrder = null, namesToPlugins = {}; function recomputePluginOrdering() { if (eventPluginOrder) @@ -100,6 +164,17 @@ var plugins = [], getFiberCurrentPropsFromNode = null, getInstanceFromNode = null, getNodeFromInstance = null; +function executeDispatch(event, simulated, listener, inst) { + simulated = event.type || "unknown-event"; + event.currentTarget = getNodeFromInstance(inst); + ReactErrorUtils.invokeGuardedCallbackAndCatchFirstError( + simulated, + listener, + void 0, + event + ); + event.currentTarget = null; +} function executeDirectDispatch(event) { var dispatchListener = event._dispatchListeners, dispatchInstance = event._dispatchInstances; @@ -132,6 +207,26 @@ function accumulateInto(current, next) { function forEachAccumulated(arr, cb, scope) { Array.isArray(arr) ? arr.forEach(cb, scope) : arr && cb.call(scope, arr); } +var eventQueue = null; +function executeDispatchesAndReleaseTopLevel(e) { + if (e) { + var dispatchListeners = e._dispatchListeners, + dispatchInstances = e._dispatchInstances; + if (Array.isArray(dispatchListeners)) + for ( + var i = 0; + i < dispatchListeners.length && !e.isPropagationStopped(); + i++ + ) + executeDispatch(e, !1, dispatchListeners[i], dispatchInstances[i]); + else + dispatchListeners && + executeDispatch(e, !1, dispatchListeners, dispatchInstances); + e._dispatchListeners = null; + e._dispatchInstances = null; + e.isPersistent() || e.constructor.release(e); + } +} var injection = { injectEventPluginOrder: function(injectedEventPluginOrder) { invariant( @@ -942,7 +1037,7 @@ var hasSymbol = "function" === typeof Symbol && Symbol.for, REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profile_root") : 60108, + REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 60111, @@ -968,6 +1063,43 @@ function createPortal(children, containerInfo, implementation) { implementation: implementation }; } +var restoreTarget = null, + restoreQueue = null; +function restoreStateOfTarget(target) { + if ((target = getInstanceFromNode(target))) { + invariant( + null, + "Fiber needs to be injected to handle a fiber target for controlled events. This error is likely caused by a bug in React. Please file an issue." + ); + var props = getFiberCurrentPropsFromNode(target.stateNode); + null.restoreControlledState(target.stateNode, target.type, props); + } +} +function _batchedUpdates(fn, bookkeeping) { + return fn(bookkeeping); +} +function _flushInteractiveUpdates() {} +var isBatching = !1; +function batchedUpdates(fn, bookkeeping) { + if (isBatching) return fn(bookkeeping); + isBatching = !0; + try { + return _batchedUpdates(fn, bookkeeping); + } finally { + if (((isBatching = !1), null !== restoreTarget || null !== restoreQueue)) + if ( + (_flushInteractiveUpdates(), + restoreTarget && + ((bookkeeping = restoreTarget), + (fn = restoreQueue), + (restoreQueue = restoreTarget = null), + restoreStateOfTarget(bookkeeping), + fn)) + ) + for (bookkeeping = 0; bookkeeping < fn.length; bookkeeping++) + restoreStateOfTarget(fn[bookkeeping]); + } +} var emptyObject$1 = {}, removedKeys = null, removedKeyCount = 0; @@ -1426,9 +1558,8 @@ function createFiberFromElement(element, mode, expirationTime) { var type = element.type, key = element.key; element = element.props; - var fiberTag = void 0; if ("function" === typeof type) - fiberTag = type.prototype && type.prototype.isReactComponent ? 2 : 0; + var fiberTag = type.prototype && type.prototype.isReactComponent ? 2 : 0; else if ("string" === typeof type) fiberTag = 5; else switch (type) { @@ -1460,42 +1591,35 @@ function createFiberFromElement(element, mode, expirationTime) { mode |= 2; break; default: - if ("object" === typeof type && null !== type) - switch (type.$$typeof) { + a: { + switch ("object" === typeof type && null !== type + ? type.$$typeof + : null) { case REACT_PROVIDER_TYPE: fiberTag = 13; - break; + break a; case REACT_CONTEXT_TYPE: fiberTag = 12; - break; + break a; case REACT_FORWARD_REF_TYPE: fiberTag = 14; - break; + break a; default: - if ("number" === typeof type.tag) - return ( - (mode = type), - (mode.pendingProps = element), - (mode.expirationTime = expirationTime), - mode - ); - throwOnInvalidElementType(type, null); + invariant( + !1, + "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", + null == type ? type : typeof type, + "" + ); } - else throwOnInvalidElementType(type, null); + fiberTag = void 0; + } } mode = new FiberNode(fiberTag, element, key, mode); mode.type = type; mode.expirationTime = expirationTime; return mode; } -function throwOnInvalidElementType(type) { - invariant( - !1, - "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", - null == type ? type : typeof type, - "" - ); -} function createFiberFromFragment(elements, mode, expirationTime, key) { elements = new FiberNode(10, elements, key, mode); elements.expirationTime = expirationTime; @@ -3819,7 +3943,9 @@ function createCapturedValue(value, source) { function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; - null === stack && (stack = getStackAddendumByWorkInProgressFiber(source)); + null === stack && + null !== source && + (stack = getStackAddendumByWorkInProgressFiber(source)); null !== source && getComponentName(source); source = null !== stack ? stack : ""; errorInfo = errorInfo.value; @@ -4774,28 +4900,31 @@ function ReactFiberScheduler(config) { for (; null !== nextUnitOfWork; ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); } catch (thrownValue) { - if (null === nextUnitOfWork) { - didFatal = !0; - onUncaughtError(thrownValue); - break; + if (null === nextUnitOfWork) + (didFatal = !0), onUncaughtError(thrownValue); + else { + invariant( + null !== nextUnitOfWork, + "Failed to replay rendering after an error. This is likely caused by a bug in React. Please file an issue with a reproducing case to help us find it." + ); + isAsync = nextUnitOfWork; + var returnFiber = isAsync.return; + if (null === returnFiber) { + didFatal = !0; + onUncaughtError(thrownValue); + break; + } + throwException( + root, + returnFiber, + isAsync, + thrownValue, + nextRenderIsExpired, + nextRenderExpirationTime, + mostRecentCurrentTimeMs + ); + nextUnitOfWork = completeUnitOfWork(isAsync); } - isAsync = nextUnitOfWork; - var returnFiber = isAsync.return; - if (null === returnFiber) { - didFatal = !0; - onUncaughtError(thrownValue); - break; - } - throwException( - root, - returnFiber, - isAsync, - thrownValue, - nextRenderIsExpired, - nextRenderExpirationTime, - mostRecentCurrentTimeMs - ); - nextUnitOfWork = completeUnitOfWork(isAsync); } break; } while (1); @@ -5665,8 +5794,37 @@ function setTimeoutCallback() { scheduledCallback = null; null !== callback && callback(frameDeadlineObject); } -var nextReactTag = 2, - ReactFabricHostComponent = (function() { +function dispatchEvent(target, topLevelType, nativeEvent) { + batchedUpdates(function() { + var events = nativeEvent.target; + for (var events$jscomp$0 = null, i = 0; i < plugins.length; i++) { + var possiblePlugin = plugins[i]; + possiblePlugin && + (possiblePlugin = possiblePlugin.extractEvents( + topLevelType, + target, + nativeEvent, + events + )) && + (events$jscomp$0 = accumulateInto(events$jscomp$0, possiblePlugin)); + } + events = events$jscomp$0; + null !== events && (eventQueue = accumulateInto(eventQueue, events)); + events = eventQueue; + eventQueue = null; + events && + (forEachAccumulated(events, executeDispatchesAndReleaseTopLevel), + invariant( + !eventQueue, + "processEventQueue(): Additional events were enqueued while processing an event queue. Support for this has not yet been implemented." + ), + ReactErrorUtils.rethrowCaughtError()); + }); +} +var nextReactTag = 2; +FabricUIManager.registerEventHandler && + FabricUIManager.registerEventHandler(dispatchEvent); +var ReactFabricHostComponent = (function() { function ReactFabricHostComponent(tag, viewConfig, props) { if (!(this instanceof ReactFabricHostComponent)) throw new TypeError("Cannot call a class as a function"); @@ -5882,6 +6040,8 @@ function findNodeHandle(componentOrHandle) { ? componentOrHandle.canonical._nativeTag : componentOrHandle._nativeTag; } +_batchedUpdates = ReactFabricRenderer.batchedUpdates; +_flushInteractiveUpdates = ReactFabricRenderer.flushInteractiveUpdates; var roots = new Map(), ReactFabric = { NativeComponent: (function(findNodeHandle, findHostInstance) { diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-dev.js b/Libraries/Renderer/oss/ReactNativeRenderer-dev.js index 9b2b430c146..f1a8809d897 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-dev.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-dev.js @@ -2763,7 +2763,7 @@ var REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 0xeacb; var REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 0xeacc; -var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profile_root") : 0xeacc; +var REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 0xead2; var REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 0xeacd; var REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 0xeace; var REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 0xeacf; @@ -3373,42 +3373,9 @@ function createFiberFromElement(element, mode, expirationTime) { // mode compatible. mode |= StrictMode; break; - default: { - if (typeof type === "object" && type !== null) { - switch (type.$$typeof) { - case REACT_PROVIDER_TYPE: - fiberTag = ContextProvider; - break; - case REACT_CONTEXT_TYPE: - // This is a consumer - fiberTag = ContextConsumer; - break; - case REACT_FORWARD_REF_TYPE: - fiberTag = ForwardRef; - break; - default: - if (typeof type.tag === "number") { - // Currently assumed to be a continuation and therefore is a - // fiber already. - // TODO: The yield system is currently broken for updates in - // some cases. The reified yield stores a fiber, but we don't - // know which fiber that is; the current or a workInProgress? - // When the continuation gets rendered here we don't know if we - // can reuse that fiber or if we need to clone it. There is - // probably a clever way to restructure this. - fiber = type; - fiber.pendingProps = pendingProps; - fiber.expirationTime = expirationTime; - return fiber; - } else { - throwOnInvalidElementType(type, owner); - } - break; - } - } else { - throwOnInvalidElementType(type, owner); - } - } + default: + fiberTag = getFiberTagFromObjectType(type, owner); + break; } } @@ -3424,33 +3391,47 @@ function createFiberFromElement(element, mode, expirationTime) { return fiber; } -function throwOnInvalidElementType(type, owner) { - var info = ""; - { - if ( - type === undefined || - (typeof type === "object" && - type !== null && - Object.keys(type).length === 0) - ) { - info += - " You likely forgot to export your component from the file " + - "it's defined in, or you might have mixed up default and " + - "named imports."; - } - var ownerName = owner ? getComponentName(owner) : null; - if (ownerName) { - info += "\n\nCheck the render method of `" + ownerName + "`."; +function getFiberTagFromObjectType(type, owner) { + var $$typeof = + typeof type === "object" && type !== null ? type.$$typeof : null; + + switch ($$typeof) { + case REACT_PROVIDER_TYPE: + return ContextProvider; + case REACT_CONTEXT_TYPE: + // This is a consumer + return ContextConsumer; + case REACT_FORWARD_REF_TYPE: + return ForwardRef; + default: { + var info = ""; + { + if ( + type === undefined || + (typeof type === "object" && + type !== null && + Object.keys(type).length === 0) + ) { + info += + " You likely forgot to export your component from the file " + + "it's defined in, or you might have mixed up default and " + + "named imports."; + } + var ownerName = owner ? getComponentName(owner) : null; + if (ownerName) { + info += "\n\nCheck the render method of `" + ownerName + "`."; + } + } + invariant( + false, + "Element type is invalid: expected a string (for built-in " + + "components) or a class/function (for composite components) " + + "but got: %s.%s", + type == null ? type : typeof type, + info + ); } } - invariant( - false, - "Element type is invalid: expected a string (for built-in " + - "components) or a class/function (for composite components) " + - "but got: %s.%s", - type == null ? type : typeof type, - info - ); } function createFiberFromFragment(elements, mode, expirationTime, key) { @@ -3858,15 +3839,15 @@ var ReactStrictModeWarnings = { pendingUnsafeLifecycleWarnings = new Map(); }; - var getStrictRoot = function(fiber) { + var findStrictRoot = function(fiber) { var maybeStrictRoot = null; - while (fiber !== null) { - if (fiber.mode & StrictMode) { - maybeStrictRoot = fiber; + var node = fiber; + while (node !== null) { + if (node.mode & StrictMode) { + maybeStrictRoot = node; } - - fiber = fiber.return; + node = node.return; } return maybeStrictRoot; @@ -3976,7 +3957,15 @@ var ReactStrictModeWarnings = { fiber, instance ) { - var strictRoot = getStrictRoot(fiber); + var strictRoot = findStrictRoot(fiber); + if (strictRoot === null) { + warning( + false, + "Expected to find a StrictMode component in a strict mode tree. " + + "This error is likely caused by a bug in React. Please file an issue." + ); + return; + } // Dedup strategy: Warn once per component. // This is difficult to track any other way since component names @@ -9291,7 +9280,7 @@ var didWarnAboutUndefinedSnapshotBeforeUpdate = null; function logError(boundary, errorInfo) { var source = errorInfo.source; var stack = errorInfo.stack; - if (stack === null) { + if (stack === null && source !== null) { stack = getStackAddendumByWorkInProgressFiber(source); } @@ -11351,6 +11340,7 @@ var ReactFiberNewContext = function(stack, isPrimaryRenderer) { context._changedBits = providerFiber.stateNode; { !( + context._currentRenderer === undefined || context._currentRenderer === null || context._currentRenderer === rendererSigil ) @@ -11371,6 +11361,7 @@ var ReactFiberNewContext = function(stack, isPrimaryRenderer) { context._changedBits2 = providerFiber.stateNode; { !( + context._currentRenderer2 === undefined || context._currentRenderer2 === null || context._currentRenderer2 === rendererSigil ) @@ -11719,10 +11710,20 @@ var ReactFiberScheduler = function(config) { } // Restore the original state of the work-in-progress + if (stashedWorkInProgressProperties === null) { + // This should never happen. Don't throw because this code is DEV-only. + warning( + false, + "Could not replay rendering after an error. This is likely a bug in React. " + + "Please file an issue." + ); + return; + } assignFiberPropertiesInDEV( failedUnitOfWork, stashedWorkInProgressProperties ); + switch (failedUnitOfWork.tag) { case HostRoot: popHostContainer(failedUnitOfWork); @@ -12447,43 +12448,52 @@ var ReactFiberScheduler = function(config) { // This is a fatal error. didFatal = true; onUncaughtError(thrownValue); - break; - } + } else { + { + // Reset global debug state + // We assume this is defined in DEV + resetCurrentlyProcessingQueue(); + } - { - // Reset global debug state - // We assume this is defined in DEV - resetCurrentlyProcessingQueue(); - } - - if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { var failedUnitOfWork = nextUnitOfWork; - replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); - } + if (true && replayFailedUnitOfWorkWithInvokeGuardedCallback) { + replayUnitOfWork(failedUnitOfWork, thrownValue, isAsync); + } - var sourceFiber = nextUnitOfWork; - var returnFiber = sourceFiber.return; - if (returnFiber === null) { - // This is the root. The root could capture its own errors. However, - // we don't know if it errors before or after we pushed the host - // context. This information is needed to avoid a stack mismatch. - // Because we're not sure, treat this as a fatal error. We could track - // which phase it fails in, but doesn't seem worth it. At least - // for now. - didFatal = true; - onUncaughtError(thrownValue); - break; + // TODO: we already know this isn't true in some cases. + // At least this shows a nicer error message until we figure out the cause. + // https://github.com/facebook/react/issues/12449#issuecomment-386727431 + invariant( + nextUnitOfWork !== null, + "Failed to replay rendering after an error. This " + + "is likely caused by a bug in React. Please file an issue " + + "with a reproducing case to help us find it." + ); + + var sourceFiber = nextUnitOfWork; + var returnFiber = sourceFiber.return; + if (returnFiber === null) { + // This is the root. The root could capture its own errors. However, + // we don't know if it errors before or after we pushed the host + // context. This information is needed to avoid a stack mismatch. + // Because we're not sure, treat this as a fatal error. We could track + // which phase it fails in, but doesn't seem worth it. At least + // for now. + didFatal = true; + onUncaughtError(thrownValue); + break; + } + throwException( + root, + returnFiber, + sourceFiber, + thrownValue, + nextRenderIsExpired, + nextRenderExpirationTime, + mostRecentCurrentTimeMs + ); + nextUnitOfWork = completeUnitOfWork(sourceFiber); } - throwException( - root, - returnFiber, - sourceFiber, - thrownValue, - nextRenderIsExpired, - nextRenderExpirationTime, - mostRecentCurrentTimeMs - ); - nextUnitOfWork = completeUnitOfWork(sourceFiber); } break; } while (true); diff --git a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js index 471d0418167..52c14c46bfc 100644 --- a/Libraries/Renderer/oss/ReactNativeRenderer-prod.js +++ b/Libraries/Renderer/oss/ReactNativeRenderer-prod.js @@ -1148,7 +1148,7 @@ var ReactCurrentOwner = REACT_PORTAL_TYPE = hasSymbol ? Symbol.for("react.portal") : 60106, REACT_FRAGMENT_TYPE = hasSymbol ? Symbol.for("react.fragment") : 60107, REACT_STRICT_MODE_TYPE = hasSymbol ? Symbol.for("react.strict_mode") : 60108, - REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profile_root") : 60108, + REACT_PROFILER_TYPE = hasSymbol ? Symbol.for("react.profiler") : 60114, REACT_PROVIDER_TYPE = hasSymbol ? Symbol.for("react.provider") : 60109, REACT_CONTEXT_TYPE = hasSymbol ? Symbol.for("react.context") : 60110, REACT_ASYNC_MODE_TYPE = hasSymbol ? Symbol.for("react.async_mode") : 60111, @@ -1368,9 +1368,8 @@ function createFiberFromElement(element, mode, expirationTime) { var type = element.type, key = element.key; element = element.props; - var fiberTag = void 0; if ("function" === typeof type) - fiberTag = type.prototype && type.prototype.isReactComponent ? 2 : 0; + var fiberTag = type.prototype && type.prototype.isReactComponent ? 2 : 0; else if ("string" === typeof type) fiberTag = 5; else switch (type) { @@ -1402,42 +1401,35 @@ function createFiberFromElement(element, mode, expirationTime) { mode |= 2; break; default: - if ("object" === typeof type && null !== type) - switch (type.$$typeof) { + a: { + switch ("object" === typeof type && null !== type + ? type.$$typeof + : null) { case REACT_PROVIDER_TYPE: fiberTag = 13; - break; + break a; case REACT_CONTEXT_TYPE: fiberTag = 12; - break; + break a; case REACT_FORWARD_REF_TYPE: fiberTag = 14; - break; + break a; default: - if ("number" === typeof type.tag) - return ( - (mode = type), - (mode.pendingProps = element), - (mode.expirationTime = expirationTime), - mode - ); - throwOnInvalidElementType(type, null); + invariant( + !1, + "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", + null == type ? type : typeof type, + "" + ); } - else throwOnInvalidElementType(type, null); + fiberTag = void 0; + } } mode = new FiberNode(fiberTag, element, key, mode); mode.type = type; mode.expirationTime = expirationTime; return mode; } -function throwOnInvalidElementType(type) { - invariant( - !1, - "Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: %s.%s", - null == type ? type : typeof type, - "" - ); -} function createFiberFromFragment(elements, mode, expirationTime, key) { elements = new FiberNode(10, elements, key, mode); elements.expirationTime = expirationTime; @@ -3704,7 +3696,9 @@ function createCapturedValue(value, source) { function logError(boundary, errorInfo) { var source = errorInfo.source, stack = errorInfo.stack; - null === stack && (stack = getStackAddendumByWorkInProgressFiber(source)); + null === stack && + null !== source && + (stack = getStackAddendumByWorkInProgressFiber(source)); null !== source && getComponentName(source); source = null !== stack ? stack : ""; errorInfo = errorInfo.value; @@ -4837,28 +4831,31 @@ function ReactFiberScheduler(config) { for (; null !== nextUnitOfWork; ) nextUnitOfWork = performUnitOfWork(nextUnitOfWork); } catch (thrownValue) { - if (null === nextUnitOfWork) { - didFatal = !0; - onUncaughtError(thrownValue); - break; + if (null === nextUnitOfWork) + (didFatal = !0), onUncaughtError(thrownValue); + else { + invariant( + null !== nextUnitOfWork, + "Failed to replay rendering after an error. This is likely caused by a bug in React. Please file an issue with a reproducing case to help us find it." + ); + isAsync = nextUnitOfWork; + var returnFiber = isAsync.return; + if (null === returnFiber) { + didFatal = !0; + onUncaughtError(thrownValue); + break; + } + throwException( + root, + returnFiber, + isAsync, + thrownValue, + nextRenderIsExpired, + nextRenderExpirationTime, + mostRecentCurrentTimeMs + ); + nextUnitOfWork = completeUnitOfWork(isAsync); } - isAsync = nextUnitOfWork; - var returnFiber = isAsync.return; - if (null === returnFiber) { - didFatal = !0; - onUncaughtError(thrownValue); - break; - } - throwException( - root, - returnFiber, - isAsync, - thrownValue, - nextRenderIsExpired, - nextRenderExpirationTime, - mostRecentCurrentTimeMs - ); - nextUnitOfWork = completeUnitOfWork(isAsync); } break; } while (1);