react-native-windows 0.78.2 → 0.78.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/Directory.Build.props +2 -2
  2. package/Folly/TEMP_UntilFollyUpdate/json.cpp +4 -0
  3. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.cpp +23 -15
  4. package/Folly/TEMP_UntilFollyUpdate/lang/ToAscii.h +5 -5
  5. package/Folly/cgmanifest.json +1 -1
  6. package/Libraries/Modal/Modal.windows.js +4 -1
  7. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.cpp +97 -0
  8. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.h +53 -0
  9. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.h +160 -17
  10. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +182 -14
  11. package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp +12 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +2 -1
  13. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +0 -1
  14. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +16 -14
  15. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +10 -1
  16. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  17. package/PropertySheets/WebView2.props +2 -1
  18. package/PropertySheets/WinUI.props +5 -2
  19. package/Shared/Networking/WinRTWebSocketResource.cpp +5 -0
  20. package/Shared/Shared.vcxitems +3 -3
  21. package/Shared/Shared.vcxitems.filters +1 -1
  22. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +1 -1
  23. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +1 -1
  24. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +1 -1
  25. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +1 -1
  26. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +1 -1
  27. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +1 -1
  28. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +1 -1
  29. package/codegen/react/components/rnwcore/InputAccessory.g.h +1 -1
  30. package/codegen/react/components/rnwcore/ModalHostView.g.h +1 -1
  31. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +1 -1
  32. package/codegen/react/components/rnwcore/SafeAreaView.g.h +1 -1
  33. package/codegen/react/components/rnwcore/Switch.g.h +1 -1
  34. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +1 -1
  35. package/package.json +6 -6
  36. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +0 -191
@@ -20,8 +20,8 @@
20
20
  <EnableSourceLink Condition="'$(EnableSourceLink)' == '' AND '$(BuildingInRnwRepo)' == 'true'">true</EnableSourceLink>
21
21
  <EnableSourceLink Condition="'$(EnableSourceLink)' == ''">false</EnableSourceLink>
22
22
  <!-- When bumping the Folly version, be sure to bump the git hash of that version's commit and build Folly.vcxproj (to update its cgmanifest.json) too. -->
23
- <FollyVersion>2023.11.06.00</FollyVersion>
24
- <FollyCommitHash>d62707bf4dc8c58bcc317260611b8cbe25c7f444</FollyCommitHash>
23
+ <FollyVersion>2024.01.01.00</FollyVersion>
24
+ <FollyCommitHash>234d39a36a43106747d10cc19efada72fd810dd3</FollyCommitHash>
25
25
  <!-- When bumping the fmt version, be sure to bump the git hash of that version's commit and build fmt.vcxproj (to update its cgmanifest.json) too. -->
26
26
  <FmtVersion>10.1.0</FmtVersion>
27
27
  <FmtCommitHash>ca2e3685b160617d3d95fcd9e789c4e06ca88</FmtCommitHash>
@@ -849,6 +849,10 @@ void escapeStringImpl(
849
849
  }
850
850
  auto prefix = firstEscapableInWord<EnableExtraAsciiEscapes>(word, opts);
851
851
  DCHECK_LE(prefix, avail);
852
+ // [Windows Sometimes prefix is completely wrong (corrupt?), only in Release, causing a later AV (see issue #14394).
853
+ // Prefix should always be <= avail, capping it here as a workaround, hoping the assert above eventually catches this in Debug.
854
+ prefix = std::min(prefix, (size_t)avail);
855
+ // Windows]
852
856
  firstEsc += prefix;
853
857
  if (prefix < 8) {
854
858
  break;
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -38,7 +38,6 @@ struct to_ascii_array {
38
38
  return data.data[index];
39
39
  }
40
40
  };
41
-
42
41
  template <uint64_t Base, typename Alphabet>
43
42
  alignas(kIsMobile ? sizeof(size_t) : hardware_constructive_interference_size)
44
43
  typename to_ascii_array<Base, Alphabet>::data_type_ const
@@ -94,13 +93,13 @@ extern template to_ascii_table<10, to_ascii_alphabet_upper>::data_type_ const
94
93
  extern template to_ascii_table<16, to_ascii_alphabet_upper>::data_type_ const
95
94
  to_ascii_table<16, to_ascii_alphabet_upper>::data;
96
95
 
97
- template <uint64_t Base, typename I>
96
+ template <uint64_t Base, typename Int>
98
97
  struct to_ascii_powers {
99
- static constexpr size_t size_(I v) {
98
+ static constexpr size_t size_(Int v) {
100
99
  return 1 + (v < Base ? 0 : size_(v / Base));
101
100
  }
102
- static constexpr size_t const size = size_(~I(0));
103
- using data_type_ = c_array<I, size>;
101
+ static constexpr size_t const size = size_(~Int(0));
102
+ using data_type_ = c_array<Int, size>;
104
103
  static constexpr data_type_ data_() {
105
104
  data_type_ result{};
106
105
  for (size_t i = 0; i < size; ++i) {
@@ -111,12 +110,14 @@ struct to_ascii_powers {
111
110
  // @lint-ignore CLANGTIDY
112
111
  static data_type_ const data;
113
112
  };
114
- template <uint64_t Base, typename I>
115
- constexpr size_t const to_ascii_powers<Base, I>::size;
116
- template <uint64_t Base, typename I>
113
+ #if FOLLY_CPLUSPLUS < 201703L
114
+ template <uint64_t Base, typename Int>
115
+ constexpr size_t const to_ascii_powers<Base, Int>::size;
116
+ #endif
117
+ template <uint64_t Base, typename Int>
117
118
  alignas(hardware_constructive_interference_size)
118
- typename to_ascii_powers<Base, I>::data_type_ const
119
- to_ascii_powers<Base, I>::data = to_ascii_powers<Base, I>::data_();
119
+ typename to_ascii_powers<Base, Int>::data_type_ const
120
+ to_ascii_powers<Base, Int>::data = to_ascii_powers<Base, Int>::data_();
120
121
 
121
122
  extern template to_ascii_powers<8, uint64_t>::data_type_ const
122
123
  to_ascii_powers<8, uint64_t>::data;
@@ -151,7 +152,7 @@ template <uint64_t Base>
151
152
  FOLLY_ALWAYS_INLINE size_t to_ascii_size_array(uint64_t v) {
152
153
  using powers = to_ascii_powers<Base, uint64_t>;
153
154
  for (size_t i = 0u; i < powers::size; ++i) {
154
- if (FOLLY_LIKELY(v < powers::data.data[i])) {
155
+ if (FOLLY_UNLIKELY(v < powers::data.data[i])) {
155
156
  return i + size_t(i == 0);
156
157
  }
157
158
  }
@@ -272,6 +273,15 @@ FOLLY_ALWAYS_INLINE size_t to_ascii_with_table(char* out, uint64_t v) {
272
273
  return size;
273
274
  }
274
275
 
276
+ // Assumes that size >= number of digits in v. If >, the result is left-padded
277
+ // with 0s.
278
+ template <uint64_t Base, typename Alphabet>
279
+ FOLLY_ALWAYS_INLINE void to_ascii_with_route(
280
+ char* outb, size_t size, uint64_t v) {
281
+ kIsMobile //
282
+ ? to_ascii_with_array<Base, Alphabet>(outb, size, v)
283
+ : to_ascii_with_table<Base, Alphabet>(outb, size, v);
284
+ }
275
285
  template <uint64_t Base, typename Alphabet>
276
286
  FOLLY_ALWAYS_INLINE size_t
277
287
  to_ascii_with_route(char* outb, char const* oute, uint64_t v) {
@@ -279,9 +289,7 @@ to_ascii_with_route(char* outb, char const* oute, uint64_t v) {
279
289
  if (FOLLY_UNLIKELY(oute < outb || size_t(oute - outb) < size)) {
280
290
  return 0;
281
291
  }
282
- kIsMobile //
283
- ? to_ascii_with_array<Base, Alphabet>(outb, size, v)
284
- : to_ascii_with_table<Base, Alphabet>(outb, size, v);
292
+ to_ascii_with_route<Base, Alphabet>(outb, size, v);
285
293
  return size;
286
294
  }
287
295
  template <uint64_t Base, typename Alphabet, size_t N>
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) Facebook, Inc. and its affiliates.
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
3
  *
4
4
  * Licensed under the Apache License, Version 2.0 (the "License");
5
5
  * you may not use this file except in compliance with the License.
@@ -61,14 +61,14 @@ using to_ascii_alphabet_upper = to_ascii_alphabet<true>;
61
61
  // In base 10, u64 requires at most 20 bytes, u32 at most 10, u16 at most 5,
62
62
  // and u8 at most 3.
63
63
  /*
64
- template <uint64_t Base, typename I>
64
+ template <uint64_t Base, typename Int>
65
65
  FOLLY_INLINE_VARIABLE constexpr size_t to_ascii_size_max =
66
- detail::to_ascii_powers<Base, I>::size;
66
+ detail::to_ascii_powers<Base, Int>::size;
67
67
  */
68
68
  // to_ascii_size_max_decimal
69
69
  //
70
70
  // An alias to to_ascii_size_max<10>.
71
- template <typename I>
71
+ template <typename Int>
72
72
  FOLLY_INLINE_VARIABLE constexpr size_t to_ascii_size_max_decimal;
73
73
 
74
74
  template <>
@@ -170,7 +170,7 @@ size_t to_ascii_upper(char (&out)[N], uint64_t v) {
170
170
  //
171
171
  // An alias to to_ascii<10, false>.
172
172
  //
173
- // async-signals-afe
173
+ // async-signal-safe
174
174
  inline size_t to_ascii_decimal(char* outb, char const* oute, uint64_t v) {
175
175
  return to_ascii_lower<10>(outb, oute, v);
176
176
  }
@@ -6,7 +6,7 @@
6
6
  "Type": "git",
7
7
  "Git": {
8
8
  "RepositoryUrl": "https://github.com/facebook/folly",
9
- "CommitHash": "d62707bf4dc8c58bcc317260611b8cbe25c7f444"
9
+ "CommitHash": "234d39a36a43106747d10cc19efada72fd810dd3"
10
10
  }
11
11
  },
12
12
  "DevelopmentDependency": false
@@ -290,8 +290,11 @@ class Modal extends React.Component<Props, State> {
290
290
  }
291
291
  }
292
292
 
293
+ // [Windows] - apply empty rootViewStyle to AppContainer to prevent modal from always expanding to fill available space
293
294
  const innerChildren = __DEV__ ? (
294
- <AppContainer rootTag={this.context}>{this.props.children}</AppContainer>
295
+ <AppContainer rootTag={this.context} rootViewStyle={{}}>
296
+ {this.props.children}
297
+ </AppContainer>
295
298
  ) : (
296
299
  this.props.children
297
300
  );
@@ -0,0 +1,97 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #include "AbiPortalShadowNode.h"
5
+
6
+ #include <Fabric/Composition/ReactCompositionViewComponentBuilder.h>
7
+ #include <react/debug/react_native_assert.h>
8
+ #include <react/renderer/core/LayoutConstraints.h>
9
+ #include <react/renderer/core/LayoutContext.h>
10
+ #include <react/renderer/core/conversions.h>
11
+
12
+ #include <utility>
13
+
14
+ namespace Microsoft::ReactNative {
15
+
16
+ extern const char AbiPortalComponentName[] = "AbiPortal";
17
+
18
+ facebook::react::Size AbiPortalShadowNode::measureContent(
19
+ const facebook::react::LayoutContext &layoutContext,
20
+ const facebook::react::LayoutConstraints &layoutConstraints) const {
21
+ return {0, 0}; // The portal placeholder node shouldn't take up any space
22
+ }
23
+
24
+ void AbiPortalShadowNode::layout(facebook::react::LayoutContext layoutContext) {
25
+ ensureUnsealed();
26
+ auto layoutMetrics = getLayoutMetrics();
27
+
28
+ auto portalOwningShadowNode = ShadowNode::Unshared{};
29
+
30
+ if (getChildren().empty()) {
31
+ return;
32
+ }
33
+
34
+ // A Portal should only have a single child
35
+ react_native_assert(getChildren().size() == 1);
36
+
37
+ const auto &childNode = getChildren()[0];
38
+
39
+ auto clonedShadowNode = ShadowNode::Unshared{};
40
+
41
+ portalOwningShadowNode = cloneTree(childNode->getFamily(), [&](const ShadowNode &oldShadowNode) {
42
+ clonedShadowNode = oldShadowNode.clone({});
43
+ return clonedShadowNode;
44
+ });
45
+ auto portalShadowNode = static_cast<AbiPortalShadowNode *>(portalOwningShadowNode.get());
46
+
47
+ auto &layoutableShadowNode = dynamic_cast<LayoutableShadowNode &>(*clonedShadowNode);
48
+
49
+ auto &state = getStateData();
50
+
51
+ facebook::react::LayoutConstraints layoutConstraints;
52
+ layoutConstraints.layoutDirection = layoutMetrics.layoutDirection;
53
+
54
+ if (state.userdata) {
55
+ // If the portal component set a state of type IPortalStateData,
56
+ // extract constraint information from it, and use that for layout
57
+ if (auto portalState = state.userdata.try_as<winrt::Microsoft::ReactNative::Composition::IPortalStateData>()) {
58
+ auto stateConstraints = portalState.LayoutConstraints();
59
+
60
+ layoutConstraints.minimumSize = {stateConstraints.MinimumSize.Width, stateConstraints.MinimumSize.Height};
61
+ layoutConstraints.maximumSize = {stateConstraints.MaximumSize.Width, stateConstraints.MaximumSize.Height};
62
+ if (stateConstraints.LayoutDirection == winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight) {
63
+ layoutConstraints.layoutDirection = facebook::react::LayoutDirection::LeftToRight;
64
+ } else if (stateConstraints.LayoutDirection == winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft) {
65
+ layoutConstraints.layoutDirection = facebook::react::LayoutDirection::RightToLeft;
66
+ }
67
+ }
68
+ }
69
+
70
+ // Laying out the `ShadowNode` and the subtree starting from it.
71
+ layoutableShadowNode.layoutTree(layoutContext, layoutConstraints);
72
+
73
+ auto childLayoutMetrics = layoutableShadowNode.getLayoutMetrics();
74
+ childLayoutMetrics.frame.origin = {0, 0};
75
+ layoutableShadowNode.setLayoutMetrics(childLayoutMetrics);
76
+
77
+ // Update the list of children to reflect the changes that we made.
78
+ this->children_ = static_cast<AbiPortalShadowNode *>(portalOwningShadowNode.get())->children_;
79
+ }
80
+
81
+ void AbiPortalShadowNode::Builder(winrt::Microsoft::ReactNative::IReactViewComponentBuilder builder) noexcept {
82
+ m_builder = builder;
83
+ }
84
+
85
+ winrt::Microsoft::ReactNative::IReactViewComponentBuilder AbiPortalShadowNode::Builder() const noexcept {
86
+ return m_builder;
87
+ }
88
+
89
+ void AbiPortalShadowNode::Proxy(winrt::Microsoft::ReactNative::ShadowNode proxy) noexcept {
90
+ m_proxy = proxy;
91
+ }
92
+
93
+ winrt::Microsoft::ReactNative::ShadowNode AbiPortalShadowNode::Proxy() const noexcept {
94
+ return m_proxy;
95
+ }
96
+
97
+ } // namespace Microsoft::ReactNative
@@ -0,0 +1,53 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
4
+ #pragma once
5
+
6
+ #include <react/components/rnwcore/EventEmitters.h>
7
+ #include <unordered_map>
8
+ #include "AbiShadowNode.h"
9
+ #include "AbiState.h"
10
+ #include "AbiViewProps.h"
11
+
12
+ #include <react/renderer/components/view/ConcreteViewShadowNode.h>
13
+ #include <react/renderer/core/LayoutContext.h>
14
+
15
+ namespace Microsoft::ReactNative {
16
+
17
+ extern const char AbiPortalComponentName[];
18
+
19
+ class AbiPortalShadowNode final : public facebook::react::ConcreteViewShadowNode<
20
+ AbiPortalComponentName,
21
+ AbiViewProps,
22
+ facebook::react::ViewEventEmitter,
23
+ Microsoft::ReactNative::AbiStateData> {
24
+ public:
25
+ using ConcreteViewShadowNode::ConcreteViewShadowNode;
26
+
27
+ static facebook::react::ShadowNodeTraits BaseTraits() {
28
+ auto traits = facebook::react::ShadowNode::BaseTraits();
29
+ traits.set(facebook::react::ShadowNodeTraits::Trait::FormsStackingContext);
30
+ traits.set(facebook::react::ShadowNodeTraits::Trait::FormsView);
31
+ traits.set(facebook::react::ShadowNodeTraits::Trait::RootNodeKind);
32
+ traits.set(facebook::react::ShadowNodeTraits::Trait::LeafYogaNode);
33
+ traits.set(facebook::react::ShadowNodeTraits::Trait::MeasurableYogaNode);
34
+ return traits;
35
+ }
36
+
37
+ facebook::react::Size measureContent(
38
+ const facebook::react::LayoutContext &layoutContext,
39
+ const facebook::react::LayoutConstraints &layoutConstraints) const override;
40
+ void layout(facebook::react::LayoutContext layoutContext) override;
41
+
42
+ void OnClone(const facebook::react::ShadowNode &sourceShadowNode) noexcept;
43
+ void Builder(winrt::Microsoft::ReactNative::IReactViewComponentBuilder builder) noexcept;
44
+ winrt::Microsoft::ReactNative::IReactViewComponentBuilder Builder() const noexcept;
45
+ void Proxy(winrt::Microsoft::ReactNative::ShadowNode handle) noexcept;
46
+ winrt::Microsoft::ReactNative::ShadowNode Proxy() const noexcept;
47
+
48
+ private:
49
+ winrt::Microsoft::ReactNative::ShadowNode m_proxy{nullptr};
50
+ winrt::Microsoft::ReactNative::IReactViewComponentBuilder m_builder{nullptr};
51
+ };
52
+
53
+ } // namespace Microsoft::ReactNative
@@ -3,16 +3,22 @@
3
3
 
4
4
  #pragma once
5
5
 
6
+ #include <Fabric/Composition/ReactCompositionViewComponentBuilder.h>
7
+ #include <Fabric/WindowsComponentDescriptorRegistry.h>
8
+ #include <ReactContext.h>
6
9
  #include <react/renderer/components/view/ConcreteViewShadowNode.h>
7
10
  #include <react/renderer/core/ComponentDescriptor.h>
11
+ #include "AbiPortalShadowNode.h"
8
12
  #include "AbiViewProps.h"
9
13
  #include "AbiViewShadowNode.h"
14
+ #include "DynamicReader.h"
10
15
  #include "winrt/Microsoft.ReactNative.h"
11
16
 
12
17
  namespace Microsoft::ReactNative {
13
18
 
14
- class AbiViewComponentDescriptor : public facebook::react::ComponentDescriptor {
15
- using ShadowNodeT = AbiViewShadowNode;
19
+ template <typename ShadowNodeT>
20
+ class ConcreteAbiViewComponentDescriptor : public facebook::react::ComponentDescriptor {
21
+ protected:
16
22
  using SharedShadowNodeT = std::shared_ptr<const ShadowNodeT>;
17
23
 
18
24
  public:
@@ -24,34 +30,142 @@ class AbiViewComponentDescriptor : public facebook::react::ComponentDescriptor {
24
30
  using ConcreteState = typename ShadowNodeT::ConcreteState;
25
31
  using ConcreteStateData = typename ShadowNodeT::ConcreteState::Data;
26
32
 
27
- AbiViewComponentDescriptor(facebook::react::ComponentDescriptorParameters const &parameters);
33
+ ConcreteAbiViewComponentDescriptor(facebook::react::ComponentDescriptorParameters const &parameters)
34
+ : ComponentDescriptor(parameters) {
35
+ auto flavor = std::static_pointer_cast<std::string const>(this->flavor_);
36
+ m_builder = WindowsComponentDescriptorRegistry::FromProperties(
37
+ parameters.contextContainer->at<winrt::Microsoft::ReactNative::ReactContext>("MSRN.ReactContext")
38
+ .Properties())
39
+ ->GetDescriptor(flavor);
40
+
41
+ rawPropsParser_.prepare<ConcreteProps>();
42
+ }
43
+ facebook::react::ComponentHandle getComponentHandle() const override {
44
+ return reinterpret_cast<facebook::react::ComponentHandle>(getComponentName());
45
+ }
46
+
47
+ facebook::react::ComponentName getComponentName() const override {
48
+ return std::static_pointer_cast<std::string const>(this->flavor_)->c_str();
49
+ }
50
+
51
+ facebook::react::ShadowNodeTraits getTraits() const override {
52
+ auto traits = ShadowNodeT::BaseTraits();
53
+ if (winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
54
+ ->MeasureContentHandler()) {
55
+ traits.set(facebook::react::ShadowNodeTraits::LeafYogaNode);
56
+ traits.set(facebook::react::ShadowNodeTraits::MeasurableYogaNode);
57
+ }
58
+ return traits;
59
+ }
28
60
 
29
- facebook::react::ComponentHandle getComponentHandle() const override;
30
- facebook::react::ComponentName getComponentName() const override;
31
- facebook::react::ShadowNodeTraits getTraits() const override;
32
61
  std::shared_ptr<facebook::react::ShadowNode> createShadowNode(
33
62
  const facebook::react::ShadowNodeFragment &fragment,
34
- facebook::react::ShadowNodeFamily::Shared const &family) const override;
63
+ facebook::react::ShadowNodeFamily::Shared const &family) const override {
64
+ auto shadowNode = std::make_shared<ShadowNodeT>(fragment, family, getTraits());
65
+ shadowNode->Proxy(winrt::make<winrt::Microsoft::ReactNative::implementation::YogaLayoutableShadowNode>(shadowNode));
66
+ winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
67
+ ->CreateShadowNode(shadowNode->Proxy());
68
+
69
+ adopt(*shadowNode);
70
+ return shadowNode;
71
+ }
72
+
35
73
  facebook::react::ShadowNode::Unshared cloneShadowNode(
36
74
  const facebook::react::ShadowNode &sourceShadowNode,
37
- const facebook::react::ShadowNodeFragment &fragment) const override;
75
+ const facebook::react::ShadowNodeFragment &fragment) const override {
76
+ auto shadowNode = std::make_shared<ShadowNodeT>(sourceShadowNode, fragment);
77
+ shadowNode->Proxy(winrt::make<winrt::Microsoft::ReactNative::implementation::YogaLayoutableShadowNode>(shadowNode));
78
+ winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
79
+ ->CloneShadowNode(shadowNode->Proxy(), static_cast<const ShadowNodeT &>(sourceShadowNode).Proxy());
80
+
81
+ adopt(*shadowNode);
82
+ return shadowNode;
83
+ }
38
84
 
39
85
  void appendChild(
40
86
  const facebook::react::ShadowNode::Shared &parentShadowNode,
41
- const facebook::react::ShadowNode::Shared &childShadowNode) const override;
87
+ const facebook::react::ShadowNode::Shared &childShadowNode) const override {
88
+ auto concreteParentShadowNode = std::static_pointer_cast<const ShadowNodeT>(parentShadowNode);
89
+ auto concreteNonConstParentShadowNode = std::const_pointer_cast<ShadowNodeT>(concreteParentShadowNode);
90
+ concreteNonConstParentShadowNode->appendChild(childShadowNode);
91
+ }
92
+
42
93
  virtual facebook::react::Props::Shared cloneProps(
43
94
  const facebook::react::PropsParserContext &context,
44
95
  const facebook::react::Props::Shared &props,
45
- facebook::react::RawProps rawProps) const override;
96
+ facebook::react::RawProps rawProps) const override {
97
+ // Optimization:
98
+ // Quite often nodes are constructed with default/empty props: the base
99
+ // `props` object is `null` (there no base because it's not cloning) and the
100
+ // `rawProps` is empty. In this case, we can return the default props object
101
+ // of a concrete type entirely bypassing parsing.
102
+ if (!props && rawProps.isEmpty()) {
103
+ return ShadowNodeT::defaultSharedProps();
104
+ }
105
+
106
+ if constexpr (facebook::react::RawPropsFilterable<ShadowNodeT>) {
107
+ ShadowNodeT::filterRawProps(rawProps);
108
+ }
109
+
110
+ rawProps.parse(rawPropsParser_);
111
+
112
+ // Call old-style constructor
113
+ // auto shadowNodeProps = std::make_shared<ShadowNodeT::Props>(context, rawProps, props);
114
+ auto shadowNodeProps = std::make_shared<AbiViewProps>(
115
+ context, props ? static_cast<AbiViewProps const &>(*props) : *ShadowNodeT::defaultSharedProps(), rawProps);
116
+ auto viewProps =
117
+ winrt::make<winrt::Microsoft::ReactNative::implementation::ViewProps>(shadowNodeProps, false /*holdRef*/);
118
+ auto userProps =
119
+ winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
120
+ ->CreateProps(viewProps, props ? static_cast<AbiViewProps const &>(*props).UserProps() : nullptr);
121
+ shadowNodeProps->SetUserProps(userProps, viewProps);
122
+
123
+ const auto &dynamic = static_cast<folly::dynamic>(rawProps);
124
+ for (const auto &pair : dynamic.items()) {
125
+ const auto &propName = pair.first.getString();
126
+ auto hash = RAW_PROPS_KEY_HASH(propName);
127
+ shadowNodeProps.get()->setProp(context, hash, propName.c_str(), facebook::react::RawValue(pair.second));
128
+ userProps.SetProp(
129
+ hash, winrt::to_hstring(propName), winrt::make<winrt::Microsoft::ReactNative::DynamicReader>(pair.second));
130
+ }
131
+ return shadowNodeProps;
132
+ }
133
+
46
134
  virtual facebook::react::State::Shared createInitialState(
47
135
  facebook::react::Props::Shared const &props,
48
- facebook::react::ShadowNodeFamily::Shared const &family) const override;
136
+ facebook::react::ShadowNodeFamily::Shared const &family) const override {
137
+ if (std::is_same<ConcreteStateData, facebook::react::StateData>::value) {
138
+ // Default case: Returning `null` for nodes that don't use `State`.
139
+ return nullptr;
140
+ }
141
+
142
+ return std::make_shared<ConcreteState>(
143
+ std::make_shared<ConcreteStateData const>(
144
+ ConcreteAbiViewComponentDescriptor<ShadowNodeT>::initialStateData(props, family, *this)),
145
+ family);
146
+ }
147
+
49
148
  virtual facebook::react::State::Shared createState(
50
149
  facebook::react::ShadowNodeFamily const &family,
51
- facebook::react::StateData::Shared const &data) const override;
150
+ facebook::react::StateData::Shared const &data) const override {
151
+ if (std::is_same<ConcreteStateData, facebook::react::StateData>::value) {
152
+ // Default case: Returning `null` for nodes that don't use `State`.
153
+ return nullptr;
154
+ }
155
+
156
+ react_native_assert(data && "Provided `data` is nullptr.");
157
+
158
+ return std::make_shared<ConcreteState const>(
159
+ std::static_pointer_cast<ConcreteStateData const>(data), *family.getMostRecentState());
160
+ }
52
161
 
53
162
  facebook::react::ShadowNodeFamily::Shared createFamily(
54
- facebook::react::ShadowNodeFamilyFragment const &fragment) const override;
163
+ facebook::react::ShadowNodeFamilyFragment const &fragment) const override {
164
+ auto eventEmitter = std::make_shared<const ConcreteEventEmitter>(
165
+ std::make_shared<facebook::react::EventTarget>(fragment.instanceHandle, fragment.surfaceId), eventDispatcher_);
166
+ return std::make_shared<facebook::react::ShadowNodeFamily>(
167
+ fragment, std::move(eventEmitter), eventDispatcher_, *this);
168
+ }
55
169
 
56
170
  protected:
57
171
  /*
@@ -66,15 +180,44 @@ class AbiViewComponentDescriptor : public facebook::react::ComponentDescriptor {
66
180
  * - Set `ShadowNode`'s size from state in
67
181
  * `ModalHostViewComponentDescriptor`.
68
182
  */
69
- virtual void adopt(facebook::react::ShadowNode &shadowNode) const;
183
+ virtual void adopt(facebook::react::ShadowNode &shadowNode) const {
184
+ react_native_assert(shadowNode.getComponentHandle() == getComponentHandle());
185
+
186
+ auto &abiViewShadowNode = static_cast<AbiViewShadowNode &>(shadowNode);
187
+
188
+ abiViewShadowNode.Builder(m_builder);
189
+
190
+ if (winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
191
+ ->MeasureContentHandler()) {
192
+ abiViewShadowNode.dirtyLayout();
193
+ abiViewShadowNode.enableMeasurement();
194
+ }
195
+ }
70
196
 
71
197
  private:
72
198
  static ConcreteStateData initialStateData(
73
- const facebook::react::Props::Shared & /*props*/,
199
+ const facebook::react::Props::Shared &props,
74
200
  const facebook::react::ShadowNodeFamily::Shared & /*family*/,
75
- const facebook::react::ComponentDescriptor & /*componentDescriptor*/) noexcept;
201
+ const facebook::react::ComponentDescriptor &componentDescriptor) noexcept {
202
+ return {winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(
203
+ static_cast<const ConcreteAbiViewComponentDescriptor<ShadowNodeT> &>(componentDescriptor).m_builder)
204
+ ->InitialStateData(std::static_pointer_cast<AbiViewProps const>(props)->UserProps())};
205
+ return {};
206
+ }
76
207
 
77
- winrt::Microsoft::ReactNative::IReactViewComponentBuilder m_builder;
208
+ winrt::Microsoft::ReactNative::IReactViewComponentBuilder m_builder{nullptr};
209
+ };
210
+
211
+ class AbiViewComponentDescriptor : public ConcreteAbiViewComponentDescriptor<AbiViewShadowNode> {
212
+ public:
213
+ AbiViewComponentDescriptor(facebook::react::ComponentDescriptorParameters const &parameters)
214
+ : ConcreteAbiViewComponentDescriptor<AbiViewShadowNode>(parameters) {}
215
+ };
216
+
217
+ class AbiPortalComponentDescriptor : public ConcreteAbiViewComponentDescriptor<AbiPortalShadowNode> {
218
+ public:
219
+ AbiPortalComponentDescriptor(facebook::react::ComponentDescriptorParameters const &parameters)
220
+ : ConcreteAbiViewComponentDescriptor<AbiPortalShadowNode>(parameters) {}
78
221
  };
79
222
 
80
223
  } // namespace Microsoft::ReactNative