From 6f17e3b328f61a8c75ceb07fc95231636db4ecc7 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Sun, 25 Mar 2018 22:43:40 -0700 Subject: [PATCH] Fabric: Introducing `TreeMutationInstruction` Summary: The Great Diffing algorithm is coming. Reviewed By: fkgozali Differential Revision: D7376528 fbshipit-source-id: bdfef69551980136cfd1717a11ae376d5eef126b --- .../uimanager/TreeMutationInstruction.cpp | 150 ++++++++++++++++++ .../uimanager/TreeMutationInstruction.h | 109 +++++++++++++ 2 files changed, 259 insertions(+) create mode 100644 ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp create mode 100644 ReactCommon/fabric/uimanager/TreeMutationInstruction.h diff --git a/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp new file mode 100644 index 00000000000..da60fb83cf0 --- /dev/null +++ b/ReactCommon/fabric/uimanager/TreeMutationInstruction.cpp @@ -0,0 +1,150 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include "TreeMutationInstruction.h" + +#include + +namespace facebook { +namespace react { + +const TreeMutationInstruction TreeMutationInstruction::Insert( + SharedShadowNode parentNode, + SharedShadowNode childNode, + int index +) { + assert(parentNode); + assert(childNode); + assert(index != -1); + + return TreeMutationInstruction( + Inserting, + parentNode, + nullptr, + childNode, + index + ); +} + +const TreeMutationInstruction TreeMutationInstruction::Delete( + SharedShadowNode parentNode, + SharedShadowNode childNode, + int index +) { + assert(parentNode); + assert(childNode); + assert(index != -1); + + return TreeMutationInstruction( + Deleting, + parentNode, + childNode, + nullptr, + index + ); +} + +const TreeMutationInstruction TreeMutationInstruction::Update( + SharedShadowNode parentNode, + SharedShadowNode oldChildNode, + SharedShadowNode newChildNode, + int index +) { + assert(parentNode); + assert(oldChildNode); + assert(newChildNode); + assert(index != -1); + + return TreeMutationInstruction( + Updating, + parentNode, + oldChildNode, + newChildNode, + index + ); +} + +TreeMutationInstruction::TreeMutationInstruction( + Type type, + SharedShadowNode parentNode, + SharedShadowNode oldChildNode, + SharedShadowNode newChildNode, + int index +): + type_(type), + parentNode_(parentNode), + oldChildNode_(oldChildNode), + newChildNode_(newChildNode), + index_(index) {}; + +#pragma mark - Getters + +TreeMutationInstruction::Type TreeMutationInstruction::getType() const { + return type_; +} + +SharedShadowNode TreeMutationInstruction::getParentNode() const { + assert(parentNode_); + return parentNode_; +} + +SharedShadowNode TreeMutationInstruction::getOldChildNode() const { + assert(oldChildNode_); + return oldChildNode_; +} + +SharedShadowNode TreeMutationInstruction::getNewChildNode() const { + assert(newChildNode_); + return newChildNode_; +} + +int TreeMutationInstruction::getIndex() const { + assert(index_ != -1); + return index_; +} + +#pragma mark - DebugStringConvertible + +std::string TreeMutationInstruction::getDebugName() const { + switch (type_) { + case Inserting: + return "Insert"; + case Deleting: + return "Delete"; + case Updating: + return "Update"; + } +}; + +SharedDebugStringConvertibleList TreeMutationInstruction::getDebugProps() const { + DebugStringConvertibleOptions options = {.maximumDepth = 1, .format = false}; + + switch (type_) { + case Inserting: + return SharedDebugStringConvertibleList { + std::make_shared("parentNode", parentNode_->getDebugDescription(options)), + std::make_shared("childNode", newChildNode_->getDebugDescription(options)), + std::make_shared("index", std::to_string(index_)) + }; + case Deleting: + return SharedDebugStringConvertibleList { + std::make_shared("parentNode", parentNode_->getDebugDescription(options)), + std::make_shared("childNode", oldChildNode_->getDebugDescription(options)), + std::make_shared("index", std::to_string(index_)) + }; + case Updating: + return SharedDebugStringConvertibleList { + std::make_shared("parentNode", parentNode_->getDebugDescription(options)), + std::make_shared("oldChildNode", oldChildNode_->getDebugDescription(options)), + std::make_shared("newChildNode", newChildNode_->getDebugDescription(options)), + std::make_shared("index", std::to_string(index_)) + }; + } +} + +} // namespace react +} // namespace facebook diff --git a/ReactCommon/fabric/uimanager/TreeMutationInstruction.h b/ReactCommon/fabric/uimanager/TreeMutationInstruction.h new file mode 100644 index 00000000000..f0e09c17d35 --- /dev/null +++ b/ReactCommon/fabric/uimanager/TreeMutationInstruction.h @@ -0,0 +1,109 @@ +/** + * Copyright (c) 2015-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#pragma once + +#include + +#include +#include + +namespace facebook { +namespace react { + +class TreeMutationInstruction; + +using TreeMutationInstructionList = std::vector; + +/* + * Describes single native views tree mutation instruction which may contain + * pointers to an old shadow node, a new shadow node, a parent shadow node and + * final index of inserted or updated node. + * The relationship between native view instances and shadow node instances is + * defined by `tag` value. + */ +class TreeMutationInstruction: + public DebugStringConvertible { +public: + +#pragma mark - Designated Initializers + + /* + * Creates and returns an *Insert* instruction with following semantic: + * 1. Create a native view for the shadow node if needed; + * 2. Unmount the native view from a previous superview if needed; + * 3. Mount the native view to the new superview. + */ + static const TreeMutationInstruction Insert( + SharedShadowNode parentNode, + SharedShadowNode childNode, + int index + ); + + /* + * Creates and returns a *Delete* instruction with following semantic: + * 1. Unmount the native view from a previous superview if needed; + * 2. Destroy (or return to a recycle pool) the native view. + */ + static const TreeMutationInstruction Delete( + SharedShadowNode parentNode, + SharedShadowNode childNode, + int index + ); + + /* + * Creates and returns an *Update* instruction with following semantic: + * 1. Update the presentation of a native view based on the new shadow node; + * 2. The exact set of changes are not specified but might contain + * new props and/or new layout (or might be empty). + */ + static const TreeMutationInstruction Update( + SharedShadowNode parentNode, + SharedShadowNode oldChildNode, + SharedShadowNode newChildNode, + int index + ); + +#pragma mark - Type + + enum Type { + Inserting, + Deleting, + Updating + }; + +#pragma mark - Getters + + Type getType() const; + SharedShadowNode getParentNode() const; + SharedShadowNode getOldChildNode() const; + SharedShadowNode getNewChildNode() const; + int getIndex() const; + +#pragma mark - DebugStringConvertible + + std::string getDebugName() const override; + SharedDebugStringConvertibleList getDebugProps() const override; + +private: + TreeMutationInstruction( + Type type, + SharedShadowNode parentNode, + SharedShadowNode oldChildNode, + SharedShadowNode newChildNode, + int index + ); + + Type type_ {Inserting}; + SharedShadowNode parentNode_ {nullptr}; + SharedShadowNode oldChildNode_ {nullptr}; + SharedShadowNode newChildNode_ {nullptr}; + int index_ {-1}; +}; + +} // namespace react +} // namespace facebook