Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from facebook:master #654

Merged
merged 8 commits into from
Mar 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions Libraries/Animated/createAnimatedComponent.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,8 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
);

class AnimatedComponent extends React.Component<Object> {
constructor(props) {
super(props);
this._waitForUpdate();
this._attachProps(this.props);
this._lastProps = this.props;
}

_component: any; // TODO T53738161: flow type this, and the whole file
_invokeAnimatedPropsCallbackOnMount: boolean = false;
_lastProps: Object;
_prevComponent: any;
_propsAnimated: AnimatedProps;
_eventDetachers: Array<Function> = [];
Expand Down Expand Up @@ -182,6 +174,10 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
_attachProps(nextProps) {
const oldPropsAnimated = this._propsAnimated;

if (nextProps === oldPropsAnimated) {
return;
}

this._propsAnimated = new AnimatedProps(
nextProps,
this._animatedPropsCallback,
Expand Down Expand Up @@ -223,11 +219,6 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
});

render() {
if (this._lastProps !== this.props) {
this._waitForUpdate();
this._attachProps(this.props);
this._lastProps = this.props;
}
const {style = {}, ...props} = this._propsAnimated.__getValue() || {};
const {style: passthruStyle = {}, ...passthruProps} =
this.props.passthroughAnimatedPropExplicitValues || {};
Expand Down Expand Up @@ -272,6 +263,11 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
);
}

UNSAFE_componentWillMount() {
this._waitForUpdate();
this._attachProps(this.props);
}

componentDidMount() {
if (this._invokeAnimatedPropsCallbackOnMount) {
this._invokeAnimatedPropsCallbackOnMount = false;
Expand All @@ -283,6 +279,11 @@ function createAnimatedComponent<Props: {+[string]: mixed, ...}, Instance>(
this._markUpdateComplete();
}

UNSAFE_componentWillReceiveProps(newProps) {
this._waitForUpdate();
this._attachProps(newProps);
}

componentDidUpdate(prevProps) {
if (this._component !== this._prevComponent) {
this._propsAnimated.setNativeView(this._component);
Expand Down
3 changes: 2 additions & 1 deletion React/Fabric/RCTScheduler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ void schedulerDidDispatchCommand(
[scheduler.delegate schedulerDidDispatchCommand:shadowView commandName:commandName args:args];
}

void schedulerDidSetIsJSResponder(ShadowView const &shadowView, bool isJSResponder) override
void schedulerDidSetIsJSResponder(ShadowView const &shadowView, bool isJSResponder, bool blockNativeResponder)
override
{
RCTScheduler *scheduler = (__bridge RCTScheduler *)scheduler_;
[scheduler.delegate schedulerDidSetIsJSResponder:isJSResponder forShadowView:shadowView];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -618,8 +618,7 @@ void Binding::schedulerDidFinishTransaction(
auto &mutationType = mutation.type;
auto &index = mutation.index;

bool isVirtual = newChildShadowView.layoutMetrics == EmptyLayoutMetrics &&
oldChildShadowView.layoutMetrics == EmptyLayoutMetrics;
bool isVirtual = mutation.mutatedViewIsVirtual();

switch (mutationType) {
case ShadowViewMutation::Create: {
Expand Down Expand Up @@ -1190,7 +1189,8 @@ void Binding::schedulerDidSendAccessibilityEvent(

void Binding::schedulerDidSetIsJSResponder(
ShadowView const &shadowView,
bool isJSResponder) {
bool isJSResponder,
bool blockNativeResponder) {
jni::global_ref<jobject> localJavaUIManager = getJavaUIManager();
if (!localJavaUIManager) {
LOG(ERROR) << "Binding::schedulerSetJSResponder: JavaUIManager disappeared";
Expand All @@ -1215,7 +1215,7 @@ void Binding::schedulerDidSetIsJSResponder(
// be flattened because the only component that uses this feature -
// ScrollView - cannot be flattened.
shadowView.tag,
(jboolean) true);
(jboolean)blockNativeResponder);
} else {
clearJSResponder(localJavaUIManager);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,8 @@ class Binding : public jni::HybridClass<Binding>,

void schedulerDidSetIsJSResponder(
ShadowView const &shadowView,
bool isJSResponder) override;
bool isJSResponder,
bool blockNativeResponder) override;

void setPixelDensity(float pointScaleFactor);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,7 @@ void LayoutAnimationKeyFrameManager::
isRemoveMutation || mutation.type == ShadowViewMutation::Type::Insert);

// TODO: turn all of this into a lambda and share code?
if (mutatedViewIsVirtual(mutation)) {
if (mutation.mutatedViewIsVirtual()) {
PrintMutationInstruction(
"[IndexAdjustment] Not calling adjustImmediateMutationIndicesForDelayedMutations, is virtual, for:",
mutation);
Expand Down Expand Up @@ -457,7 +457,7 @@ void LayoutAnimationKeyFrameManager::
if (delayedMutation.type != ShadowViewMutation::Type::Remove) {
continue;
}
if (mutatedViewIsVirtual(delayedMutation)) {
if (delayedMutation.mutatedViewIsVirtual()) {
continue;
}
if (delayedMutation.oldChildShadowView.tag ==
Expand Down Expand Up @@ -519,7 +519,7 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
bool isInsertMutation = mutation.type == ShadowViewMutation::Type::Insert;
react_native_assert(isRemoveMutation || isInsertMutation);

if (mutatedViewIsVirtual(mutation)) {
if (mutation.mutatedViewIsVirtual()) {
PrintMutationInstruction(
"[IndexAdjustment] Not calling adjustDelayedMutationIndicesForMutation, is virtual, for:",
mutation);
Expand Down Expand Up @@ -573,7 +573,7 @@ void LayoutAnimationKeyFrameManager::adjustDelayedMutationIndicesForMutation(
if (finalAnimationMutation.type != ShadowViewMutation::Type::Remove) {
continue;
}
if (mutatedViewIsVirtual(*animatedKeyFrame.finalMutationForKeyFrame)) {
if (animatedKeyFrame.finalMutationForKeyFrame->mutatedViewIsVirtual()) {
continue;
}

Expand Down Expand Up @@ -674,8 +674,8 @@ LayoutAnimationKeyFrameManager::getAndEraseConflictingAnimations(
// for example, "insert" mutations where the final update needs to set
// opacity to "1", even if there's no final ShadowNode update.
if (!(animatedKeyFrame.finalMutationForKeyFrame.has_value() &&
mutatedViewIsVirtual(
*animatedKeyFrame.finalMutationForKeyFrame))) {
animatedKeyFrame.finalMutationForKeyFrame
->mutatedViewIsVirtual())) {
conflictingAnimations.push_back(animatedKeyFrame);
}

Expand Down Expand Up @@ -777,7 +777,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
continue;
}
if (keyframe.finalMutationForKeyFrame &&
!mutatedViewIsVirtual(*keyframe.finalMutationForKeyFrame)) {
!keyframe.finalMutationForKeyFrame->mutatedViewIsVirtual()) {
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
std::to_string(j) + ": Final Animation";
PrintMutationInstruction(msg, *keyframe.finalMutationForKeyFrame);
Expand Down Expand Up @@ -1594,7 +1594,7 @@ LayoutAnimationKeyFrameManager::pullTransaction(
continue;
}
if (keyframe.finalMutationForKeyFrame &&
!mutatedViewIsVirtual(*keyframe.finalMutationForKeyFrame)) {
!keyframe.finalMutationForKeyFrame->mutatedViewIsVirtual()) {
std::string msg = "Animation " + std::to_string(i) + " keyframe " +
std::to_string(j) + ": Final Animation";
PrintMutationInstruction(msg, *keyframe.finalMutationForKeyFrame);
Expand Down Expand Up @@ -1626,21 +1626,6 @@ LayoutAnimationKeyFrameManager::pullTransaction(
surfaceId, transactionNumber, std::move(mutations), telemetry};
}

bool LayoutAnimationKeyFrameManager::mutatedViewIsVirtual(
ShadowViewMutation const &mutation) const {
bool viewIsVirtual = false;

// TODO: extract this into an Android platform-specific class?
// Explanation: for "Insert" mutations, oldChildShadowView is always empty.
// for "Remove" mutations, newChildShadowView is always empty.
#ifdef ANDROID
viewIsVirtual =
mutation.newChildShadowView.layoutMetrics == EmptyLayoutMetrics &&
mutation.oldChildShadowView.layoutMetrics == EmptyLayoutMetrics;
#endif
return viewIsVirtual;
}

bool LayoutAnimationKeyFrameManager::hasComponentDescriptorForShadowView(
ShadowView const &shadowView) const {
return componentDescriptorRegistry_->hasComponentDescriptorAt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,8 +226,6 @@ class LayoutAnimationKeyFrameManager : public UIManagerAnimationDelegate,
mutable std::vector<SurfaceId> surfaceIdsToStop_{};

protected:
bool mutatedViewIsVirtual(ShadowViewMutation const &mutation) const;

bool hasComponentDescriptorForShadowView(ShadowView const &shadowView) const;
ComponentDescriptor const &getComponentDescriptorForShadowView(
ShadowView const &shadowView) const;
Expand Down
16 changes: 16 additions & 0 deletions ReactCommon/react/renderer/mounting/ShadowViewMutation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,22 @@ ShadowViewMutation ShadowViewMutation::UpdateMutation(
};
}

bool ShadowViewMutation::mutatedViewIsVirtual() const {
bool viewIsVirtual = false;

#ifdef ANDROID
// Explanation: Even for non-virtual views,
// for "Insert" mutations, oldChildShadowView is always empty.
// for "Remove" mutations, newChildShadowView is always empty.
// Thus, to see if a view is virtual, we need to always check both the old and
// new View.
viewIsVirtual = newChildShadowView.layoutMetrics == EmptyLayoutMetrics &&
oldChildShadowView.layoutMetrics == EmptyLayoutMetrics;
#endif

return viewIsVirtual;
}

#if RN_DEBUG_STRING_CONVERTIBLE

std::string getDebugName(ShadowViewMutation const &mutation) {
Expand Down
8 changes: 8 additions & 0 deletions ReactCommon/react/renderer/mounting/ShadowViewMutation.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ struct ShadowViewMutation final {
ShadowView oldChildShadowView = {};
ShadowView newChildShadowView = {};
int index = -1;

public:
// Some platforms can have the notion of virtual views - views that are in the
// ShadowTree hierarchy but never are on the platform. Generally this is used
// so notify the platform that a view exists so that we can keep EventEmitters
// around, to notify JS of something. This mechanism is DEPRECATED and it is
// highly recommended that you NOT make use of this in your platform!
bool mutatedViewIsVirtual() const;
};

using ShadowViewMutationList = std::vector<ShadowViewMutation>;
Expand Down
109 changes: 57 additions & 52 deletions ReactCommon/react/renderer/mounting/StubViewTree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,62 +73,67 @@ void StubViewTree::mutate(ShadowViewMutationList const &mutations) {
}

case ShadowViewMutation::Insert: {
react_native_assert(mutation.oldChildShadowView == ShadowView{});
auto parentTag = mutation.parentShadowView.tag;
react_native_assert(registry.find(parentTag) != registry.end());
auto parentStubView = registry[parentTag];
auto childTag = mutation.newChildShadowView.tag;
react_native_assert(registry.find(childTag) != registry.end());
auto childStubView = registry[childTag];
react_native_assert(childStubView->parentTag == NO_VIEW_TAG);
childStubView->update(mutation.newChildShadowView);
STUB_VIEW_LOG({
LOG(ERROR) << "StubView: Insert [" << childTag << "] into ["
<< parentTag << "] @" << mutation.index << "("
<< parentStubView->children.size() << " children)";
});
react_native_assert(parentStubView->children.size() >= mutation.index);
childStubView->parentTag = parentTag;
parentStubView->children.insert(
parentStubView->children.begin() + mutation.index, childStubView);
if (!mutation.mutatedViewIsVirtual()) {
react_native_assert(mutation.oldChildShadowView == ShadowView{});
auto parentTag = mutation.parentShadowView.tag;
react_native_assert(registry.find(parentTag) != registry.end());
auto parentStubView = registry[parentTag];
auto childTag = mutation.newChildShadowView.tag;
react_native_assert(registry.find(childTag) != registry.end());
auto childStubView = registry[childTag];
react_native_assert(childStubView->parentTag == NO_VIEW_TAG);
childStubView->update(mutation.newChildShadowView);
STUB_VIEW_LOG({
LOG(ERROR) << "StubView: Insert [" << childTag << "] into ["
<< parentTag << "] @" << mutation.index << "("
<< parentStubView->children.size() << " children)";
});
react_native_assert(
parentStubView->children.size() >= mutation.index);
childStubView->parentTag = parentTag;
parentStubView->children.insert(
parentStubView->children.begin() + mutation.index, childStubView);
}
break;
}

case ShadowViewMutation::Remove: {
react_native_assert(mutation.newChildShadowView == ShadowView{});
auto parentTag = mutation.parentShadowView.tag;
react_native_assert(registry.find(parentTag) != registry.end());
auto parentStubView = registry[parentTag];
auto childTag = mutation.oldChildShadowView.tag;
STUB_VIEW_LOG({
LOG(ERROR) << "StubView: Remove [" << childTag << "] from ["
<< parentTag << "] @" << mutation.index << " with "
<< parentStubView->children.size() << " children";
});
react_native_assert(parentStubView->children.size() > mutation.index);
react_native_assert(registry.find(childTag) != registry.end());
auto childStubView = registry[childTag];
react_native_assert(childStubView->parentTag == parentTag);
STUB_VIEW_LOG({
std::string strChildList = "";
int i = 0;
for (auto const &child : parentStubView->children) {
strChildList.append(std::to_string(i));
strChildList.append(":");
strChildList.append(std::to_string(child->tag));
strChildList.append(", ");
i++;
}
LOG(ERROR) << "StubView: BEFORE REMOVE: Children of " << parentTag
<< ": " << strChildList;
});
react_native_assert(
parentStubView->children.size() > mutation.index &&
parentStubView->children[mutation.index]->tag ==
childStubView->tag);
childStubView->parentTag = NO_VIEW_TAG;
parentStubView->children.erase(
parentStubView->children.begin() + mutation.index);
if (!mutation.mutatedViewIsVirtual()) {
react_native_assert(mutation.newChildShadowView == ShadowView{});
auto parentTag = mutation.parentShadowView.tag;
react_native_assert(registry.find(parentTag) != registry.end());
auto parentStubView = registry[parentTag];
auto childTag = mutation.oldChildShadowView.tag;
STUB_VIEW_LOG({
LOG(ERROR) << "StubView: Remove [" << childTag << "] from ["
<< parentTag << "] @" << mutation.index << " with "
<< parentStubView->children.size() << " children";
});
react_native_assert(parentStubView->children.size() > mutation.index);
react_native_assert(registry.find(childTag) != registry.end());
auto childStubView = registry[childTag];
react_native_assert(childStubView->parentTag == parentTag);
STUB_VIEW_LOG({
std::string strChildList = "";
int i = 0;
for (auto const &child : parentStubView->children) {
strChildList.append(std::to_string(i));
strChildList.append(":");
strChildList.append(std::to_string(child->tag));
strChildList.append(", ");
i++;
}
LOG(ERROR) << "StubView: BEFORE REMOVE: Children of " << parentTag
<< ": " << strChildList;
});
react_native_assert(
parentStubView->children.size() > mutation.index &&
parentStubView->children[mutation.index]->tag ==
childStubView->tag);
childStubView->parentTag = NO_VIEW_TAG;
parentStubView->children.erase(
parentStubView->children.begin() + mutation.index);
}
break;
}

Expand Down
5 changes: 3 additions & 2 deletions ReactCommon/react/renderer/scheduler/Scheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,11 @@ void Scheduler::uiManagerDidSendAccessibilityEvent(
*/
void Scheduler::uiManagerDidSetIsJSResponder(
ShadowNode::Shared const &shadowNode,
bool isJSResponder) {
bool isJSResponder,
bool blockNativeResponder) {
if (delegate_) {
delegate_->schedulerDidSetIsJSResponder(
ShadowView(*shadowNode), isJSResponder);
ShadowView(*shadowNode), isJSResponder, blockNativeResponder);
}
}

Expand Down
3 changes: 2 additions & 1 deletion ReactCommon/react/renderer/scheduler/Scheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@ class Scheduler final : public UIManagerDelegate {
std::string const &eventType) override;
void uiManagerDidSetIsJSResponder(
ShadowNode::Shared const &shadowView,
bool isJSResponder) override;
bool isJSResponder,
bool blockNativeResponder) override;

private:
friend class SurfaceHandler;
Expand Down
Loading