UNPKG

d2-ui

Version:
171 lines (151 loc) 6.66 kB
/** * Copyright 2013-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. * * @providesModule ReactReconciler */ 'use strict'; var ReactRef = require('./ReactRef'); var ReactInstrumentation = require('./ReactInstrumentation'); var invariant = require('fbjs/lib/invariant'); /** * Helper to call ReactRef.attachRefs with this composite component, split out * to avoid allocations in the transaction mount-ready queue. */ function attachRefs() { ReactRef.attachRefs(this, this._currentElement); } var ReactReconciler = { /** * Initializes the component, renders markup, and registers event listeners. * * @param {ReactComponent} internalInstance * @param {ReactReconcileTransaction|ReactServerRenderingTransaction} transaction * @param {?object} the containing native component instance * @param {?object} info about the native container * @return {?string} Rendered markup to be inserted into the DOM. * @final * @internal */ mountComponent: function (internalInstance, transaction, nativeParent, nativeContainerInfo, context) { if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'mountComponent'); } } var markup = internalInstance.mountComponent(transaction, nativeParent, nativeContainerInfo, context); if (internalInstance._currentElement && internalInstance._currentElement.ref != null) { transaction.getReactMountReady().enqueue(attachRefs, internalInstance); } if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'mountComponent'); ReactInstrumentation.debugTool.onMountComponent(internalInstance._debugID); } } return markup; }, /** * Returns a value that can be passed to * ReactComponentEnvironment.replaceNodeWithMarkup. */ getNativeNode: function (internalInstance) { return internalInstance.getNativeNode(); }, /** * Releases any resources allocated by `mountComponent`. * * @final * @internal */ unmountComponent: function (internalInstance, safely) { if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'unmountComponent'); } } ReactRef.detachRefs(internalInstance, internalInstance._currentElement); internalInstance.unmountComponent(safely); if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'unmountComponent'); ReactInstrumentation.debugTool.onUnmountComponent(internalInstance._debugID); } } }, /** * Update a component using a new element. * * @param {ReactComponent} internalInstance * @param {ReactElement} nextElement * @param {ReactReconcileTransaction} transaction * @param {object} context * @internal */ receiveComponent: function (internalInstance, nextElement, transaction, context) { var prevElement = internalInstance._currentElement; if (nextElement === prevElement && context === internalInstance._context) { // Since elements are immutable after the owner is rendered, // we can do a cheap identity compare here to determine if this is a // superfluous reconcile. It's possible for state to be mutable but such // change should trigger an update of the owner which would recreate // the element. We explicitly check for the existence of an owner since // it's possible for an element created outside a composite to be // deeply mutated and reused. // TODO: Bailing out early is just a perf optimization right? // TODO: Removing the return statement should affect correctness? return; } if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'receiveComponent'); } } var refsChanged = ReactRef.shouldUpdateRefs(prevElement, nextElement); if (refsChanged) { ReactRef.detachRefs(internalInstance, prevElement); } internalInstance.receiveComponent(nextElement, transaction, context); if (refsChanged && internalInstance._currentElement && internalInstance._currentElement.ref != null) { transaction.getReactMountReady().enqueue(attachRefs, internalInstance); } if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'receiveComponent'); ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID); } } }, /** * Flush any dirty changes in a component. * * @param {ReactComponent} internalInstance * @param {ReactReconcileTransaction} transaction * @internal */ performUpdateIfNecessary: function (internalInstance, transaction, updateBatchNumber) { if (internalInstance._updateBatchNumber !== updateBatchNumber) { // The component's enqueued batch number should always be the current // batch or the following one. !(internalInstance._updateBatchNumber == null || internalInstance._updateBatchNumber === updateBatchNumber + 1) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'performUpdateIfNecessary: Unexpected batch number (current %s, ' + 'pending %s)', updateBatchNumber, internalInstance._updateBatchNumber) : invariant(false) : void 0; return; } if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onBeginReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary'); } } internalInstance.performUpdateIfNecessary(transaction); if (process.env.NODE_ENV !== 'production') { if (internalInstance._debugID !== 0) { ReactInstrumentation.debugTool.onEndReconcilerTimer(internalInstance._debugID, 'performUpdateIfNecessary'); ReactInstrumentation.debugTool.onUpdateComponent(internalInstance._debugID); } } } }; module.exports = ReactReconciler;