aboutsummaryrefslogtreecommitdiff
path: root/node_modules/react-dom/lib/ReactChildFiber.js
diff options
context:
space:
mode:
Diffstat (limited to 'node_modules/react-dom/lib/ReactChildFiber.js')
-rw-r--r--node_modules/react-dom/lib/ReactChildFiber.js243
1 files changed, 243 insertions, 0 deletions
diff --git a/node_modules/react-dom/lib/ReactChildFiber.js b/node_modules/react-dom/lib/ReactChildFiber.js
new file mode 100644
index 000000000..c78c63809
--- /dev/null
+++ b/node_modules/react-dom/lib/ReactChildFiber.js
@@ -0,0 +1,243 @@
+/**
+ * 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.
+ *
+ *
+ */
+
+'use strict';
+
+var REACT_ELEMENT_TYPE = require('./ReactElementSymbol');
+
+var _require = require('./ReactCoroutine'),
+ REACT_COROUTINE_TYPE = _require.REACT_COROUTINE_TYPE,
+ REACT_YIELD_TYPE = _require.REACT_YIELD_TYPE;
+
+var ReactFiber = require('./ReactFiber');
+var ReactReifiedYield = require('./ReactReifiedYield');
+
+var cloneFiber = ReactFiber.cloneFiber,
+ createFiberFromElement = ReactFiber.createFiberFromElement,
+ createFiberFromCoroutine = ReactFiber.createFiberFromCoroutine,
+ createFiberFromYield = ReactFiber.createFiberFromYield;
+var createReifiedYield = ReactReifiedYield.createReifiedYield;
+
+
+var isArray = Array.isArray;
+
+function ChildReconciler(shouldClone) {
+
+ function createSubsequentChild(returnFiber, existingChild, previousSibling, newChildren, priority) {
+ if (typeof newChildren !== 'object' || newChildren === null) {
+ return previousSibling;
+ }
+
+ switch (newChildren.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ {
+ var element = newChildren;
+ if (existingChild && element.type === existingChild.type && element.key === existingChild.key) {
+ // TODO: This is not sufficient since previous siblings could be new.
+ // Will fix reconciliation properly later.
+ var clone = shouldClone ? cloneFiber(existingChild, priority) : existingChild;
+ if (!shouldClone) {
+ // TODO: This might be lowering the priority of nested unfinished work.
+ clone.pendingWorkPriority = priority;
+ }
+ clone.pendingProps = element.props;
+ clone.sibling = null;
+ clone['return'] = returnFiber;
+ previousSibling.sibling = clone;
+ return clone;
+ }
+ var child = createFiberFromElement(element, priority);
+ previousSibling.sibling = child;
+ child['return'] = returnFiber;
+ return child;
+ }
+
+ case REACT_COROUTINE_TYPE:
+ {
+ var coroutine = newChildren;
+ var _child = createFiberFromCoroutine(coroutine, priority);
+ previousSibling.sibling = _child;
+ _child['return'] = returnFiber;
+ return _child;
+ }
+
+ case REACT_YIELD_TYPE:
+ {
+ var yieldNode = newChildren;
+ var reifiedYield = createReifiedYield(yieldNode);
+ var _child2 = createFiberFromYield(yieldNode, priority);
+ _child2.output = reifiedYield;
+ previousSibling.sibling = _child2;
+ _child2['return'] = returnFiber;
+ return _child2;
+ }
+ }
+
+ if (isArray(newChildren)) {
+ var prev = previousSibling;
+ var existing = existingChild;
+ for (var i = 0; i < newChildren.length; i++) {
+ var nextExisting = existing && existing.sibling;
+ prev = createSubsequentChild(returnFiber, existing, prev, newChildren[i], priority);
+ if (prev && existing) {
+ // TODO: This is not correct because there could've been more
+ // than one sibling consumed but I don't want to return a tuple.
+ existing = nextExisting;
+ }
+ }
+ return prev;
+ } else {
+ // TODO: Throw for unknown children.
+ return previousSibling;
+ }
+ }
+
+ function createFirstChild(returnFiber, existingChild, newChildren, priority) {
+ if (typeof newChildren !== 'object' || newChildren === null) {
+ return null;
+ }
+
+ switch (newChildren.$$typeof) {
+ case REACT_ELEMENT_TYPE:
+ {
+ /* $FlowFixMe(>=0.31.0): This is an unsafe cast. Consider adding a type
+ * annotation to the `newChildren` param of this
+ * function.
+ */
+ var element = newChildren;
+ if (existingChild && element.type === existingChild.type && element.key === existingChild.key) {
+ // Get the clone of the existing fiber.
+ var clone = shouldClone ? cloneFiber(existingChild, priority) : existingChild;
+ if (!shouldClone) {
+ // TODO: This might be lowering the priority of nested unfinished work.
+ clone.pendingWorkPriority = priority;
+ }
+ clone.pendingProps = element.props;
+ clone.sibling = null;
+ clone['return'] = returnFiber;
+ return clone;
+ }
+ var child = createFiberFromElement(element, priority);
+ child['return'] = returnFiber;
+ return child;
+ }
+
+ case REACT_COROUTINE_TYPE:
+ {
+ /* $FlowFixMe(>=0.31.0): No 'handler' property found in object type
+ */
+ var coroutine = newChildren;
+ var _child3 = createFiberFromCoroutine(coroutine, priority);
+ _child3['return'] = returnFiber;
+ return _child3;
+ }
+
+ case REACT_YIELD_TYPE:
+ {
+ // A yield results in a fragment fiber whose output is the continuation.
+ // TODO: When there is only a single child, we can optimize this to avoid
+ // the fragment.
+ /* $FlowFixMe(>=0.31.0): No 'continuation' property found in object
+ * type
+ */
+ var yieldNode = newChildren;
+ var reifiedYield = createReifiedYield(yieldNode);
+ var _child4 = createFiberFromYield(yieldNode, priority);
+ _child4.output = reifiedYield;
+ _child4['return'] = returnFiber;
+ return _child4;
+ }
+ }
+
+ if (isArray(newChildren)) {
+ var first = null;
+ var prev = null;
+ var existing = existingChild;
+ /* $FlowIssue(>=0.31.0) #12747709
+ *
+ * `Array.isArray` is matched syntactically for now until predicate
+ * support is complete.
+ */
+ for (var i = 0; i < newChildren.length; i++) {
+ var nextExisting = existing && existing.sibling;
+ if (prev == null) {
+ prev = createFirstChild(returnFiber, existing, newChildren[i], priority);
+ first = prev;
+ } else {
+ prev = createSubsequentChild(returnFiber, existing, prev, newChildren[i], priority);
+ }
+ if (prev && existing) {
+ // TODO: This is not correct because there could've been more
+ // than one sibling consumed but I don't want to return a tuple.
+ existing = nextExisting;
+ }
+ }
+ return first;
+ } else {
+ // TODO: Throw for unknown children.
+ return null;
+ }
+ }
+
+ // TODO: This API won't work because we'll need to transfer the side-effects of
+ // unmounting children to the returnFiber.
+ function reconcileChildFibers(returnFiber, currentFirstChild, newChildren, priority) {
+ return createFirstChild(returnFiber, currentFirstChild, newChildren, priority);
+ }
+
+ return reconcileChildFibers;
+}
+
+exports.reconcileChildFibers = ChildReconciler(true);
+
+exports.reconcileChildFibersInPlace = ChildReconciler(false);
+
+function cloneSiblings(current, workInProgress, returnFiber) {
+ workInProgress['return'] = returnFiber;
+ while (current.sibling) {
+ current = current.sibling;
+ workInProgress = workInProgress.sibling = cloneFiber(current, current.pendingWorkPriority);
+ workInProgress['return'] = returnFiber;
+ }
+ workInProgress.sibling = null;
+}
+
+exports.cloneChildFibers = function (current, workInProgress) {
+ if (!workInProgress.child) {
+ return;
+ }
+ if (current && workInProgress.child === current.child) {
+ // We use workInProgress.child since that lets Flow know that it can't be
+ // null since we validated that already. However, as the line above suggests
+ // they're actually the same thing.
+ var currentChild = workInProgress.child;
+ // TODO: This used to reset the pending priority. Not sure if that is needed.
+ // workInProgress.pendingWorkPriority = current.pendingWorkPriority;
+ // TODO: The below priority used to be set to NoWork which would've
+ // dropped work. This is currently unobservable but will become
+ // observable when the first sibling has lower priority work remaining
+ // than the next sibling. At that point we should add tests that catches
+ // this.
+ var newChild = cloneFiber(currentChild, currentChild.pendingWorkPriority);
+ workInProgress.child = newChild;
+ cloneSiblings(currentChild, newChild, workInProgress);
+ }
+
+ // If there is no alternate, then we don't need to clone the children.
+ // If the children of the alternate fiber is a different set, then we don't
+ // need to clone. We need to reset the return fiber though since we'll
+ // traverse down into them.
+ var child = workInProgress.child;
+ while (child) {
+ child['return'] = workInProgress;
+ child = child.sibling;
+ }
+}; \ No newline at end of file