diff options
Diffstat (limited to 'node_modules/react-dom/lib/ReactFiber.js')
-rw-r--r-- | node_modules/react-dom/lib/ReactFiber.js | 190 |
1 files changed, 190 insertions, 0 deletions
diff --git a/node_modules/react-dom/lib/ReactFiber.js b/node_modules/react-dom/lib/ReactFiber.js new file mode 100644 index 000000000..07737ecc4 --- /dev/null +++ b/node_modules/react-dom/lib/ReactFiber.js @@ -0,0 +1,190 @@ +/** + * 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 ReactTypeOfWork = require('./ReactTypeOfWork'); +var IndeterminateComponent = ReactTypeOfWork.IndeterminateComponent, + ClassComponent = ReactTypeOfWork.ClassComponent, + HostContainer = ReactTypeOfWork.HostContainer, + HostComponent = ReactTypeOfWork.HostComponent, + CoroutineComponent = ReactTypeOfWork.CoroutineComponent, + YieldComponent = ReactTypeOfWork.YieldComponent; + +var _require = require('./ReactPriorityLevel'), + NoWork = _require.NoWork; + +// An Instance is shared between all versions of a component. We can easily +// break this out into a separate object to avoid copying so much to the +// alternate versions of the tree. We put this on a single object for now to +// minimize the number of objects created during the initial render. + + +// A Fiber is work on a Component that needs to be done or was done. There can +// be more than one per component. + + +// This is a constructor of a POJO instead of a constructor function for a few +// reasons: +// 1) Nobody should add any instance methods on this. Instance methods can be +// more difficult to predict when they get optimized and they are almost +// never inlined properly in static compilers. +// 2) Nobody should rely on `instanceof Fiber` for type testing. We should +// always know when it is a fiber. +// 3) We can easily go from a createFiber call to calling a constructor if that +// is faster. The opposite is not true. +// 4) We might want to experiment with using numeric keys since they are easier +// to optimize in a non-JIT environment. +// 5) It should be easy to port this to a C struct and keep a C implementation +// compatible. +var createFiber = function (tag, key) { + return { + + // Instance + + tag: tag, + + key: key, + + type: null, + + stateNode: null, + + // Fiber + + 'return': null, + + child: null, + sibling: null, + + ref: null, + + pendingProps: null, + memoizedProps: null, + updateQueue: null, + memoizedState: null, + callbackList: null, + output: null, + + nextEffect: null, + firstEffect: null, + lastEffect: null, + + pendingWorkPriority: NoWork, + progressedPriority: NoWork, + progressedChild: null, + + alternate: null + + }; +}; + +function shouldConstruct(Component) { + return !!(Component.prototype && Component.prototype.isReactComponent); +} + +// This is used to create an alternate fiber to do work on. +// TODO: Rename to createWorkInProgressFiber or something like that. +exports.cloneFiber = function (fiber, priorityLevel) { + // We clone to get a work in progress. That means that this fiber is the + // current. To make it safe to reuse that fiber later on as work in progress + // we need to reset its work in progress flag now. We don't have an + // opportunity to do this earlier since we don't traverse the tree when + // the work in progress tree becomes the current tree. + // fiber.progressedPriority = NoWork; + // fiber.progressedChild = null; + + // We use a double buffering pooling technique because we know that we'll only + // ever need at most two versions of a tree. We pool the "other" unused node + // that we're free to reuse. This is lazily created to avoid allocating extra + // objects for things that are never updated. It also allow us to reclaim the + // extra memory if needed. + var alt = fiber.alternate; + if (alt) { + // Whenever we clone, we do so to get a new work in progress. + // This ensures that we've reset these in the new tree. + alt.nextEffect = null; + alt.firstEffect = null; + alt.lastEffect = null; + } else { + // This should not have an alternate already + alt = createFiber(fiber.tag, fiber.key); + alt.type = fiber.type; + + alt.progressedChild = fiber.progressedChild; + alt.progressedPriority = fiber.progressedPriority; + + alt.alternate = fiber; + fiber.alternate = alt; + } + + alt.stateNode = fiber.stateNode; + alt.child = fiber.child; + alt.sibling = fiber.sibling; // This should always be overridden. TODO: null + alt.ref = fiber.ref; + // pendingProps is here for symmetry but is unnecessary in practice for now. + // TODO: Pass in the new pendingProps as an argument maybe? + alt.pendingProps = fiber.pendingProps; + alt.updateQueue = fiber.updateQueue; + alt.callbackList = fiber.callbackList; + alt.pendingWorkPriority = priorityLevel; + + alt.memoizedProps = fiber.memoizedProps; + alt.output = fiber.output; + + return alt; +}; + +exports.createHostContainerFiber = function () { + var fiber = createFiber(HostContainer, null); + return fiber; +}; + +exports.createFiberFromElement = function (element, priorityLevel) { + // $FlowFixMe: ReactElement.key is currently defined as ?string but should be defined as null | string in Flow. + var fiber = createFiberFromElementType(element.type, element.key); + fiber.pendingProps = element.props; + fiber.pendingWorkPriority = priorityLevel; + return fiber; +}; + +function createFiberFromElementType(type, key) { + var fiber = void 0; + if (typeof type === 'function') { + fiber = shouldConstruct(type) ? createFiber(ClassComponent, key) : createFiber(IndeterminateComponent, key); + fiber.type = type; + } else if (typeof type === 'string') { + fiber = createFiber(HostComponent, key); + fiber.type = type; + } else if (typeof type === 'object' && type !== null) { + // Currently assumed to be a continuation and therefore is a fiber already. + fiber = type; + } else { + throw new Error('Unknown component type: ' + typeof type); + } + return fiber; +} + +exports.createFiberFromElementType = createFiberFromElementType; + +exports.createFiberFromCoroutine = function (coroutine, priorityLevel) { + var fiber = createFiber(CoroutineComponent, coroutine.key); + fiber.type = coroutine.handler; + fiber.pendingProps = coroutine; + fiber.pendingWorkPriority = priorityLevel; + return fiber; +}; + +exports.createFiberFromYield = function (yieldNode, priorityLevel) { + var fiber = createFiber(YieldComponent, yieldNode.key); + fiber.pendingProps = {}; + return fiber; +};
\ No newline at end of file |