function moveCoroutineToHandlerPhase(current : ?Fiber, workInProgress : Fiber) {
    var coroutine = (workInProgress.pendingProps : ?ReactCoroutine);
    if (!coroutine) {
      throw new Error('Should be resolved by now');
    }

    // First step of the coroutine has completed. Now we need to do the second.
    // TODO: It would be nice to have a multi stage coroutine represented by a
    // single component, or at least tail call optimize nested ones. Currently
    // that requires additional fields that we don't want to add to the fiber.
    // So this requires nested handlers.
    // Note: This doesn't mutate the alternate node. I don't think it needs to
    // since this stage is reset for every pass.
    workInProgress.tag = CoroutineHandlerPhase;

    // Build up the yields.
    // TODO: Compare this to a generator or opaque helpers like Children.
    var yields : Array<ReifiedYield> = [];
    appendAllYields(yields, workInProgress);
    var fn = coroutine.handler;
    var props = coroutine.props;
    var nextChildren = fn(props, yields);

    var currentFirstChild = current ? current.stateNode : null;
    // Inherit the priority of the returnFiber.
    const priority = workInProgress.pendingWorkPriority;
    workInProgress.stateNode = reconcileChildFibers(
      workInProgress,
      currentFirstChild,
      nextChildren,
      priority
    );
    return workInProgress.stateNode;
  }
 function reconcileChildrenAtPriority(current, workInProgress, nextChildren, priorityLevel) {
   // At this point any memoization is no longer valid since we'll have changed
   // the children.
   workInProgress.memoizedProps = null;
   if (current && current.child === workInProgress.child) {
     // If the current child is the same as the work in progress, it means that
     // we haven't yet started any work on these children. Therefore, we use
     // the clone algorithm to create a copy of all the current children.
     workInProgress.child = reconcileChildFibers(
       workInProgress,
       workInProgress.child,
       nextChildren,
       priorityLevel
     );
   } else {
     // If, on the other hand, we don't have a current fiber or if it is
     // already using a clone, that means we've already begun some work on this
     // tree and we can continue where we left off by reconciling against the
     // existing children.
     workInProgress.child = reconcileChildFibersInPlace(
       workInProgress,
       workInProgress.child,
       nextChildren,
       priorityLevel
     );
   }
   markChildAsProgressed(current, workInProgress, priorityLevel);
 }
示例#3
0
function moveCoroutineToHandlerPhase(workInProgress : Fiber) {
  var coroutine = (workInProgress.input : ?ReactCoroutine);
  if (!coroutine) {
    throw new Error('Should be resolved by now');
  }

  // First step of the coroutine has completed. Now we need to do the second.
  // TODO: It would be nice to have a multi stage coroutine represented by a
  // single component, or at least tail call optimize nested ones. Currently
  // that requires additional fields that we don't want to add to the fiber.
  // So this requires nested handlers.
  // Note: This doesn't mutate the alternate node. I don't think it needs to
  // since this stage is reset for every pass.
  workInProgress.tag = CoroutineHandlerPhase;

  // Build up the yields.
  // TODO: Compare this to a generator or opaque helpers like Children.
  var yields : Array<ReifiedYield> = [];
  var child = workInProgress.child;
  while (child) {
    recursivelyFillYields(yields, child.output);
    child = child.sibling;
  }
  var fn = coroutine.handler;
  var props = coroutine.props;
  var nextChildren = fn(props, yields);

  workInProgress.stateNode = ReactChildFiber.reconcileChildFibers(
    workInProgress,
    workInProgress.stateNode,
    nextChildren
  );
  return workInProgress.stateNode;
}
示例#4
0
  function updateCoroutineComponent(
    current,
    workInProgress,
    renderExpirationTime,
  ) {
    var nextCoroutine = (workInProgress.pendingProps: null | ReactCoroutine);
    if (hasContextChanged()) {
      // Normally we can bail out on props equality but if context has changed
      // we don't do the bailout and we have to reuse existing props instead.
      if (nextCoroutine === null) {
        nextCoroutine = current && current.memoizedProps;
        invariant(
          nextCoroutine !== null,
          'We should always have pending or current props. This error is ' +
            'likely caused by a bug in React. Please file an issue.',
        );
      }
    } else if (
      nextCoroutine === null ||
      workInProgress.memoizedProps === nextCoroutine
    ) {
      nextCoroutine = workInProgress.memoizedProps;
      // TODO: When bailing out, we might need to return the stateNode instead
      // of the child. To check it for work.
      // return bailoutOnAlreadyFinishedWork(current, workInProgress);
    }

    const nextChildren = nextCoroutine.children;

    // The following is a fork of reconcileChildrenAtExpirationTime but using
    // stateNode to store the child.
    if (current === null) {
      workInProgress.stateNode = mountChildFibersInPlace(
        workInProgress,
        workInProgress.stateNode,
        nextChildren,
        renderExpirationTime,
      );
    } else if (current.child === workInProgress.child) {
      workInProgress.stateNode = reconcileChildFibers(
        workInProgress,
        workInProgress.stateNode,
        nextChildren,
        renderExpirationTime,
      );
    } else {
      workInProgress.stateNode = reconcileChildFibersInPlace(
        workInProgress,
        workInProgress.stateNode,
        nextChildren,
        renderExpirationTime,
      );
    }

    memoizeProps(workInProgress, nextCoroutine);
    // This doesn't take arbitrary time so we could synchronously just begin
    // eagerly do the work of workInProgress.child as an optimization.
    return workInProgress.stateNode;
  }
  function reconcileChildrenAtPriority(
    current,
    workInProgress,
    nextChildren,
    priorityLevel,
  ) {
    // At this point any memoization is no longer valid since we'll have changed
    // the children.
    workInProgress.memoizedProps = null;
    if (current === null) {
      // If this is a fresh new component that hasn't been rendered yet, we
      // won't update its child set by applying minimal side-effects. Instead,
      // we will add them all to the child before it gets rendered. That means
      // we can optimize this reconciliation pass by not tracking side-effects.
      workInProgress.child = mountChildFibersInPlace(
        workInProgress,
        workInProgress.child,
        nextChildren,
        priorityLevel,
      );
    } else if (current.child === workInProgress.child) {
      // If the current child is the same as the work in progress, it means that
      // we haven't yet started any work on these children. Therefore, we use
      // the clone algorithm to create a copy of all the current children.

      // If we had any progressed work already, that is invalid at this point so
      // let's throw it out.
      clearDeletions(workInProgress);

      workInProgress.child = reconcileChildFibers(
        workInProgress,
        workInProgress.child,
        nextChildren,
        priorityLevel,
      );

      transferDeletions(workInProgress);
    } else {
      // If, on the other hand, it is already using a clone, that means we've
      // already begun some work on this tree and we can continue where we left
      // off by reconciling against the existing children.
      workInProgress.child = reconcileChildFibersInPlace(
        workInProgress,
        workInProgress.child,
        nextChildren,
        priorityLevel,
      );

      transferDeletions(workInProgress);
    }
    markChildAsProgressed(current, workInProgress, priorityLevel);
  }
示例#6
0
  function moveCoroutineToHandlerPhase(
    current: Fiber | null,
    workInProgress: Fiber,
  ) {
    var coroutine = (workInProgress.memoizedProps: ?ReactCoroutine);
    invariant(
      coroutine,
      'Should be resolved by now. This error is likely caused by a bug in ' +
        'React. Please file an issue.',
    );

    // First step of the coroutine has completed. Now we need to do the second.
    // TODO: It would be nice to have a multi stage coroutine represented by a
    // single component, or at least tail call optimize nested ones. Currently
    // that requires additional fields that we don't want to add to the fiber.
    // So this requires nested handlers.
    // Note: This doesn't mutate the alternate node. I don't think it needs to
    // since this stage is reset for every pass.
    workInProgress.tag = CoroutineHandlerPhase;

    // Build up the yields.
    // TODO: Compare this to a generator or opaque helpers like Children.
    var yields: Array<mixed> = [];
    appendAllYields(yields, workInProgress);
    var fn = coroutine.handler;
    var props = coroutine.props;
    var nextChildren = fn(props, yields);

    var currentFirstChild = current !== null ? current.child : null;
    // Inherit the priority of the returnFiber.
    const priority = workInProgress.pendingWorkPriority;
    workInProgress.child = reconcileChildFibers(
      workInProgress,
      currentFirstChild,
      nextChildren,
      priority,
    );
    markChildAsProgressed(current, workInProgress, priority);
    return workInProgress.child;
  }