Example #1
0
void Scheduler::uiManagerDidCreateShadowNode(
    const SharedShadowNode &shadowNode) {
  if (delegate_) {
    delegate_->schedulerDidRequestPreliminaryViewAllocation(
        shadowNode->getRootTag(), shadowNode->getComponentName());
  }
}
Example #2
0
void UIManager::appendChild(
    const SharedShadowNode &parentShadowNode,
    const SharedShadowNode &childShadowNode) const {
  SystraceSection s("UIManager::appendChild");

  auto &componentDescriptor = parentShadowNode->getComponentDescriptor();
  componentDescriptor.appendChild(parentShadowNode, childShadowNode);
}
Example #3
0
void UIManager::setNativeProps(
    const SharedShadowNode &shadowNode,
    const RawProps &rawProps) const {
  SystraceSection s("UIManager::setNativeProps");

  auto &componentDescriptor = shadowNode->getComponentDescriptor();
  auto props = componentDescriptor.cloneProps(shadowNode->getProps(), rawProps);
  auto newShadowNode = shadowNode->clone({
      /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
      /* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
      /* .props = */ props,
  });

  shadowTreeRegistry_->visit(
      shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
        shadowTree.tryCommit(
            [&](const SharedRootShadowNode &oldRootShadowNode) {
              return oldRootShadowNode->clone(shadowNode, newShadowNode);
            });
      });
}
Example #4
0
SharedShadowNode UIManager::cloneNode(
    const SharedShadowNode &shadowNode,
    const SharedShadowNodeSharedList &children,
    const RawProps *rawProps) const {
  SystraceSection s("UIManager::cloneNode");

  auto &componentDescriptor = shadowNode->getComponentDescriptor();
  auto clonedShadowNode = componentDescriptor.cloneShadowNode(
      *shadowNode,
      {
          /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
          /* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
          /* .props = */
          rawProps ? componentDescriptor.cloneProps(
                         shadowNode->getProps(), *rawProps)
                   : ShadowNodeFragment::propsPlaceholder(),
          /* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
          /* .children = */ children,
      });

  return clonedShadowNode;
}
Example #5
0
void UIManager::updateState(
    const SharedShadowNode &shadowNode,
    const StateData::Shared &rawStateData) const {
  auto &componentDescriptor = shadowNode->getComponentDescriptor();
  auto state =
      componentDescriptor.createState(shadowNode->getState(), rawStateData);
  auto newShadowNode = shadowNode->clone({
      /* .tag = */ ShadowNodeFragment::tagPlaceholder(),
      /* .surfaceId = */ ShadowNodeFragment::surfaceIdPlaceholder(),
      /* .props = */ ShadowNodeFragment::propsPlaceholder(),
      /* .eventEmitter = */ ShadowNodeFragment::eventEmitterPlaceholder(),
      /* .children = */ ShadowNodeFragment::childrenPlaceholder(),
      /* .localData = */ ShadowNodeFragment::localDataPlaceholder(),
      /* .state = */ state,
  });

  shadowTreeRegistry_->visit(
      shadowNode->getSurfaceId(), [&](const ShadowTree &shadowTree) {
        shadowTree.tryCommit(
            [&](const SharedRootShadowNode &oldRootShadowNode) {
              return oldRootShadowNode->clone(shadowNode, newShadowNode);
            });
      });
}
AttributedString BaseTextShadowNode::getAttributedString(
    const TextAttributes &textAttributes,
    const SharedShadowNode &parentNode) const {
  auto attributedString = AttributedString{};

  for (const auto &childNode : parentNode->getChildren()) {
    // RawShadowNode
    auto rawTextShadowNode =
        std::dynamic_pointer_cast<const RawTextShadowNode>(childNode);
    if (rawTextShadowNode) {
      auto fragment = AttributedString::Fragment{};
      fragment.string = rawTextShadowNode->getProps()->text;
      fragment.textAttributes = textAttributes;
      fragment.parentShadowNode = parentNode;
      attributedString.appendFragment(fragment);
      continue;
    }

    // TextShadowNode
    auto textShadowNode =
        std::dynamic_pointer_cast<const TextShadowNode>(childNode);
    if (textShadowNode) {
      auto localTextAttributes = textAttributes;
      localTextAttributes.apply(textShadowNode->getProps()->textAttributes);
      attributedString.appendAttributedString(
          textShadowNode->getAttributedString(
              localTextAttributes, textShadowNode));
      continue;
    }

    // Any other kind of ShadowNode
    auto fragment = AttributedString::Fragment{};
    fragment.shadowNode = childNode;
    fragment.textAttributes = textAttributes;
    attributedString.appendFragment(fragment);
  }

  return attributedString;
}
const SharedComponentDescriptor ComponentDescriptorRegistry::operator[](const SharedShadowNode &shadowNode) const {
  ComponentHandle componentHandle = shadowNode->getComponentHandle();
  return _registryByHandle.at(componentHandle);
}
void calculateMutationInstructions(
  TreeMutationInstructionList &instructions,
  SharedShadowNode parentNode,
  SharedShadowNodeSharedList oldChildNodes,
  SharedShadowNodeSharedList newChildNodes
) {
  // The current version of the algorithm is otimized for simplicity,
  // not for performance of optimal result.

  // TODO(shergin): Consider to use Minimal Edit Distance algorithm to produce
  // optimal set of instructions and improve mounting performance.
  // https://en.wikipedia.org/wiki/Edit_distance
  // https://www.geeksforgeeks.org/dynamic-programming-set-5-edit-distance/

  if (oldChildNodes == newChildNodes) {
    return;
  }

  if (oldChildNodes->size() == 0 && newChildNodes->size() == 0) {
    return;
  }

  std::unordered_set<Tag> insertedTags = {};
  int index = 0;

  TreeMutationInstructionList createInstructions = {};
  TreeMutationInstructionList deleteInstructions = {};
  TreeMutationInstructionList insertInstructions = {};
  TreeMutationInstructionList removeInstructions = {};
  TreeMutationInstructionList replaceInstructions = {};
  TreeMutationInstructionList downwardInstructions = {};

  // Stage 1: Collectings Updates
  for (index = 0; index < oldChildNodes->size() && index < newChildNodes->size(); index++) {
    SharedShadowNode oldChildNode = oldChildNodes->at(index);
    SharedShadowNode newChildNode = newChildNodes->at(index);

    if (oldChildNode->getTag() != newChildNode->getTag()) {
      // Totally different nodes, updating is impossible.
      break;
    }

    if (*oldChildNode != *newChildNode) {
      replaceInstructions.push_back(
        TreeMutationInstruction::Replace(
          parentNode,
          oldChildNode,
          newChildNode,
          index
        )
      );
    }

    calculateMutationInstructions(
      downwardInstructions,
      oldChildNode,
      oldChildNode->getChildren(),
      newChildNode->getChildren()
    );
  }

  int lastIndexAfterFirstStage = index;

  // Stage 2: Collectings Insertions
  for (; index < newChildNodes->size(); index++) {
    SharedShadowNode newChildNode = newChildNodes->at(index);

    insertInstructions.push_back(
      TreeMutationInstruction::Insert(
        parentNode,
        newChildNode,
        index
      )
    );

    insertedTags.insert(newChildNode->getTag());

    SharedShadowNode newChildSourceNode = newChildNode->getSourceNode();
    SharedShadowNodeSharedList newChildSourceChildNodes =
      newChildSourceNode ? newChildSourceNode->getChildren() : ShadowNode::emptySharedShadowNodeSharedList();

    calculateMutationInstructions(
      downwardInstructions,
      newChildNode,
      newChildSourceChildNodes,
      newChildNode->getChildren()
    );
  }

  // Stage 3: Collectings Deletions and Removals
  for (index = lastIndexAfterFirstStage; index < oldChildNodes->size(); index++) {
    SharedShadowNode oldChildNode = oldChildNodes->at(index);

    // Even if the old node was (re)inserted, we have to generate `remove`
    // instruction.
    removeInstructions.push_back(
      TreeMutationInstruction::Remove(
        parentNode,
        oldChildNode,
        index
      )
    );

    auto numberOfRemovedTags = insertedTags.erase(oldChildNode->getTag());
    assert(numberOfRemovedTags == 0 || numberOfRemovedTags == 1);

    if (numberOfRemovedTags == 0) {
      // The old node was *not* (re)inserted,
      // so we have to generate `delete` instruction and apply the algorithm
      // recursively.
      deleteInstructions.push_back(
        TreeMutationInstruction::Delete(
          oldChildNode
        )
      );

      calculateMutationInstructions(
        downwardInstructions,
        oldChildNode,
        oldChildNode->getChildren(),
        ShadowNode::emptySharedShadowNodeSharedList()
      );
    }
  }

  // Stage 4: Collectings Creations
  for (index = lastIndexAfterFirstStage; index < newChildNodes->size(); index++) {
    SharedShadowNode newChildNode = newChildNodes->at(index);
    if (insertedTags.find(newChildNode->getTag()) == insertedTags.end()) {
      // The new node was (re)inserted, so there is no need to create it.
      continue;
    }

    createInstructions.push_back(
      TreeMutationInstruction::Create(
        newChildNode
      )
    );
  }

  // All instructions in an optimal order:
  instructions.insert(instructions.end(), replaceInstructions.begin(), replaceInstructions.end());
  instructions.insert(instructions.end(), removeInstructions.begin(), removeInstructions.end());
  instructions.insert(instructions.end(), deleteInstructions.begin(), deleteInstructions.end());
  instructions.insert(instructions.end(), createInstructions.begin(), createInstructions.end());
  instructions.insert(instructions.end(), insertInstructions.begin(), insertInstructions.end());
  instructions.insert(instructions.end(), downwardInstructions.begin(), downwardInstructions.end());
}