Files
react-native/ReactCommon/react/renderer/core/tests/traitCastTest.cpp
T
Andrew Coates 050922a17e Remove usages of RTTI in places used by react-native-windows (#31694)
Summary:
Adding runtime type information adds greatly to the binary size, so react-native-windows builds without it.  But some parts of the fabric code currently uses dynamic_cast, which means to use fabric we have to build with RTTI turned on.  This PR removes the usages of dynamic_cast that are hit in release builds, which should allow react-native-windows to turn off RTTI in release builds.

Required for:  https://github.com/microsoft/react-native-windows/issues/7981

One thing to note, the comment in ShadowNodeTraits indicates that core was reserving the first 16 bits.  I'm adding two more.  Is that ok?  Should core be reserving more for future use?

## Changelog

<!-- Help reviewers and the release process by writing your own changelog entry. For an example, see:
https://github.com/facebook/react-native/wiki/Changelog
-->

[Internal] [Fixed] - Remove uses of dynamic_cast in release builds

Pull Request resolved: https://github.com/facebook/react-native/pull/31694

Test Plan:
Verified that I can build react-native-windows with Fabric in release, without RTTI.
Boot / clicked around in RNW RNTester

Reviewed By: sammy-SC

Differential Revision: D29040383

Pulled By: JoshuaGross

fbshipit-source-id: e49286e59c4ba54faf0b4de5e244dfa1f7c3f193
2021-06-11 11:52:30 -07:00

140 lines
5.6 KiB
C++

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#include <gtest/gtest.h>
#include <react/renderer/components/scrollview/ScrollViewComponentDescriptor.h>
#include <react/renderer/components/text/ParagraphComponentDescriptor.h>
#include <react/renderer/components/text/RawTextComponentDescriptor.h>
#include <react/renderer/components/text/TextComponentDescriptor.h>
#include <react/renderer/components/view/ViewComponentDescriptor.h>
#include <react/renderer/element/Element.h>
#include <react/renderer/element/testUtils.h>
using namespace facebook::react;
TEST(traitCastTest, testOne) {
auto builder = simpleComponentBuilder();
auto viewShadowNode = std::shared_ptr<ViewShadowNode>{};
auto scrollViewShadowNode = std::shared_ptr<ScrollViewShadowNode>{};
auto paragraphShadowNode = std::shared_ptr<ParagraphShadowNode>{};
auto textShadowNode = std::shared_ptr<TextShadowNode>{};
auto rawTextShadowNode = std::shared_ptr<RawTextShadowNode>{};
// clang-format off
auto element =
Element<ScrollViewShadowNode>()
.reference(scrollViewShadowNode)
.children({
Element<ParagraphShadowNode>()
.reference(paragraphShadowNode)
.children({
Element<TextShadowNode>()
.reference(textShadowNode),
Element<RawTextShadowNode>()
.reference(rawTextShadowNode)
}),
Element<ViewShadowNode>()
.reference(viewShadowNode),
});
// clang-format on
auto rootShadowNode = builder.build(element);
std::shared_ptr<ShadowNode> shadowNodeForRawTextShadowNode{rawTextShadowNode};
std::shared_ptr<ShadowNode> shadowNodeForTextShadowNode{textShadowNode};
// Casting `nullptr` returns `nullptrs`.
EXPECT_FALSE(traitCast<LayoutableShadowNode const *>(nullptr));
EXPECT_FALSE(traitCast<YogaLayoutableShadowNode const *>(nullptr));
// `ViewShadowNode` is `LayoutableShadowNode` and `YogaLayoutableShadowNode`.
EXPECT_TRUE(traitCast<LayoutableShadowNode const *>(viewShadowNode.get()));
EXPECT_TRUE(
traitCast<YogaLayoutableShadowNode const *>(viewShadowNode.get()));
EXPECT_NO_FATAL_FAILURE(
traitCast<LayoutableShadowNode const &>(*viewShadowNode));
EXPECT_NO_FATAL_FAILURE(
traitCast<YogaLayoutableShadowNode const &>(*viewShadowNode));
// `ScrollViewShadowNode` is `LayoutableShadowNode` and
// `YogaLayoutableShadowNode`.
EXPECT_TRUE(
traitCast<LayoutableShadowNode const *>(scrollViewShadowNode.get()));
EXPECT_TRUE(
traitCast<YogaLayoutableShadowNode const *>(scrollViewShadowNode.get()));
EXPECT_NO_FATAL_FAILURE(
traitCast<LayoutableShadowNode const &>(*scrollViewShadowNode));
EXPECT_NO_FATAL_FAILURE(
traitCast<YogaLayoutableShadowNode const &>(*scrollViewShadowNode));
// `ParagraphShadowNode` is `LayoutableShadowNode` and
// `YogaLayoutableShadowNode`.
EXPECT_TRUE(
traitCast<LayoutableShadowNode const *>(paragraphShadowNode.get()));
EXPECT_TRUE(
traitCast<YogaLayoutableShadowNode const *>(paragraphShadowNode.get()));
EXPECT_NO_FATAL_FAILURE(
traitCast<LayoutableShadowNode const &>(*paragraphShadowNode));
EXPECT_NO_FATAL_FAILURE(
traitCast<YogaLayoutableShadowNode const &>(*paragraphShadowNode));
// `TextShadowNode` is *not* `LayoutableShadowNode` nor
// `YogaLayoutableShadowNode`.
EXPECT_FALSE(traitCast<LayoutableShadowNode const *>(textShadowNode.get()));
EXPECT_FALSE(
traitCast<YogaLayoutableShadowNode const *>(textShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<LayoutableShadowNode const &>(*textShadowNode), "");
EXPECT_DEATH_IF_SUPPORTED(
traitCast<YogaLayoutableShadowNode const &>(*textShadowNode), "");
// `RawTextShadowNode` is *not* `LayoutableShadowNode` nor
// `YogaLayoutableShadowNode`.
EXPECT_FALSE(
traitCast<LayoutableShadowNode const *>(rawTextShadowNode.get()));
EXPECT_FALSE(
traitCast<YogaLayoutableShadowNode const *>(rawTextShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<LayoutableShadowNode const &>(*rawTextShadowNode), "");
EXPECT_DEATH_IF_SUPPORTED(
traitCast<YogaLayoutableShadowNode const &>(*rawTextShadowNode), "");
// trait cast to `RawTextShadowNode` works on `RawTextShadowNode`
// and not on TextShadowNode or ViewShadowNode
EXPECT_TRUE(
traitCast<RawTextShadowNode const *>(shadowNodeForRawTextShadowNode.get()));
EXPECT_NO_FATAL_FAILURE(
traitCast<RawTextShadowNode const &>(*shadowNodeForRawTextShadowNode));
EXPECT_FALSE(
traitCast<RawTextShadowNode const *>(shadowNodeForTextShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<RawTextShadowNode const &>(*shadowNodeForTextShadowNode), "");
EXPECT_FALSE(
traitCast<RawTextShadowNode const *>(viewShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<RawTextShadowNode const &>(*viewShadowNode), "");
// trait cast to `TextShadowNode` works on `TextShadowNode`
// and not on RawTextShadowNode or ViewShadowNode
EXPECT_TRUE(
traitCast<TextShadowNode const *>(shadowNodeForTextShadowNode.get()));
EXPECT_NO_FATAL_FAILURE(
traitCast<TextShadowNode const &>(*shadowNodeForTextShadowNode));
EXPECT_FALSE(
traitCast<TextShadowNode const *>(shadowNodeForRawTextShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<TextShadowNode const &>(*shadowNodeForRawTextShadowNode), "");
EXPECT_FALSE(
traitCast<TextShadowNode const *>(viewShadowNode.get()));
EXPECT_DEATH_IF_SUPPORTED(
traitCast<TextShadowNode const &>(*viewShadowNode), "");
}