Skip to content
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix issue with prop cloning with custom native props",
"packageName": "@react-native-windows/codegen",
"email": "53619745+rnbot@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Fix issue with prop cloning with custom native props",
"packageName": "react-native-windows",
"email": "53619745+rnbot@users.noreply.github.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,14 @@ const headerTemplate = `/*

const propsTemplate = `REACT_STRUCT(::_PROPS_NAME_::)
struct ::_PROPS_NAME_:: : winrt::implements<::_PROPS_NAME_::, winrt::Microsoft::ReactNative::IComponentProps> {
::_PROPS_NAME_::(winrt::Microsoft::ReactNative::ViewProps props) : ViewProps(props) {}
::_PROPS_NAME_::(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
: ViewProps(props)
{
if (cloneFrom) {
auto cloneFromProps = cloneFrom.as<::_PROPS_NAME_::>();
::_PROP_INITIALIZERS_::
}
}

void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
Expand Down Expand Up @@ -144,8 +151,10 @@ void Register::_COMPONENT_NAME_::NativeComponent(
L"::_COMPONENT_NAME_::", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
auto compBuilder = builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();

builder.SetCreateProps(
[](winrt::Microsoft::ReactNative::ViewProps props) noexcept { return winrt::make<::_COMPONENT_NAME_::Props>(props); });
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
return winrt::make<::_COMPONENT_NAME_::Props>(props, cloneFrom);
});

builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
const winrt::Microsoft::ReactNative::IComponentProps &newProps,
Expand Down Expand Up @@ -296,6 +305,12 @@ export function createComponentGenerator({
})
.join('\n');

const propInitializers = componentShape.props
.map(prop => {
return ` ${prop.name} = cloneFromProps->${prop.name};`;
})
.join('\n');

const propObjectTypes = propObjectAliases.jobs
.map(propObjectTypeName => {
const propObjectType = propObjectAliases.types[propObjectTypeName]!;
Expand Down Expand Up @@ -510,6 +525,7 @@ ${
.replace(/::_EVENT_EMITTER_NAME_::/g, eventEmitterName)
.replace(/::_PROPS_NAME_::/g, propsName)
.replace(/::_COMPONENT_NAME_::/g, componentName)
.replace(/::_PROP_INITIALIZERS_::/g, propInitializers)
.replace(/::_PROPS_FIELDS_::/g, propsFields)
.replace(/::_NAMESPACE_::/g, namespace)
.replace(/\n\n\n+/g, '\n\n');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ namespace winrt::PlaygroundApp::implementation {
REACT_STRUCT(CustomXamlComponentProps)
struct CustomXamlComponentProps
: winrt::implements<CustomXamlComponentProps, winrt::Microsoft::ReactNative::IComponentProps> {
CustomXamlComponentProps(winrt::Microsoft::ReactNative::ViewProps props) : m_props(props) {}
CustomXamlComponentProps(
winrt::Microsoft::ReactNative::ViewProps props,
const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom)
: m_props(props) {
if (cloneFrom) {
auto cloneFromProps = cloneFrom.as<CustomXamlComponentProps>();
label = cloneFromProps->label;
}
}

void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
Expand Down Expand Up @@ -139,8 +147,9 @@ struct CustomComponentUserData : winrt::implements<CustomComponentUserData, winr
static void ConfigureBuilderForCustomComponent(
winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder,
bool nativeLayout) {
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props) noexcept {
return winrt::make<CustomXamlComponentProps>(props);
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
const winrt::Microsoft::ReactNative::IComponentProps &cloneFrom) noexcept {
return winrt::make<CustomXamlComponentProps>(props, cloneFrom);
});

builder.SetFinalizeUpdateHandler([](const winrt::Microsoft::ReactNative::ComponentView &source,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,14 @@ namespace winrt::SampleCustomComponent::Codegen {

REACT_STRUCT(DrawingIslandProps)
struct DrawingIslandProps : winrt::implements<DrawingIslandProps, winrt::Microsoft::ReactNative::IComponentProps> {
DrawingIslandProps(winrt::Microsoft::ReactNative::ViewProps props) : ViewProps(props) {}
DrawingIslandProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
: ViewProps(props)
{
if (cloneFrom) {
auto cloneFromProps = cloneFrom.as<DrawingIslandProps>();

}
}

void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
Expand Down Expand Up @@ -92,8 +99,10 @@ void RegisterDrawingIslandNativeComponent(
L"DrawingIsland", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
auto compBuilder = builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();

builder.SetCreateProps(
[](winrt::Microsoft::ReactNative::ViewProps props) noexcept { return winrt::make<DrawingIslandProps>(props); });
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
return winrt::make<DrawingIslandProps>(props, cloneFrom);
});

builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
const winrt::Microsoft::ReactNative::IComponentProps &newProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,17 @@ struct MovingLightSpec_MovingLightProps_objectProp {

REACT_STRUCT(MovingLightProps)
struct MovingLightProps : winrt::implements<MovingLightProps, winrt::Microsoft::ReactNative::IComponentProps> {
MovingLightProps(winrt::Microsoft::ReactNative::ViewProps props) : ViewProps(props) {}
MovingLightProps(winrt::Microsoft::ReactNative::ViewProps props, const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom)
: ViewProps(props)
{
if (cloneFrom) {
auto cloneFromProps = cloneFrom.as<MovingLightProps>();
size = cloneFromProps->size;
color = cloneFromProps->color;
eventParam = cloneFromProps->eventParam;
objectProp = cloneFromProps->objectProp;
}
}

void SetProp(uint32_t hash, winrt::hstring propName, winrt::Microsoft::ReactNative::IJSValueReader value) noexcept {
winrt::Microsoft::ReactNative::ReadProp(hash, propName, value, *this);
Expand Down Expand Up @@ -142,8 +152,10 @@ void RegisterMovingLightNativeComponent(
L"MovingLight", [builderCallback](winrt::Microsoft::ReactNative::IReactViewComponentBuilder const &builder) noexcept {
auto compBuilder = builder.as<winrt::Microsoft::ReactNative::Composition::IReactCompositionViewComponentBuilder>();

builder.SetCreateProps(
[](winrt::Microsoft::ReactNative::ViewProps props) noexcept { return winrt::make<MovingLightProps>(props); });
builder.SetCreateProps([](winrt::Microsoft::ReactNative::ViewProps props,
const winrt::Microsoft::ReactNative::IComponentProps& cloneFrom) noexcept {
return winrt::make<MovingLightProps>(props, cloneFrom);
});

builder.SetUpdatePropsHandler([](const winrt::Microsoft::ReactNative::ComponentView &view,
const winrt::Microsoft::ReactNative::IComponentProps &newProps,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ struct MovingLight : public winrt::implements<MovingLight, winrt::IInspectable>,
auto view = sender.as<winrt::Microsoft::ReactNative::Composition::ViewComponentView>();
if (!oldProps || oldProps->color != newProps->color) {
m_spotlight.InnerConeColor(newProps->color.AsWindowsColor(view.Theme()));
} else {
m_spotlight.InnerConeColor(winrt::Windows::UI::Colors::FloralWhite());
}

if (!oldProps || oldProps->size != newProps->size) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ facebook::react::Props::Shared AbiComponentDescriptor::cloneProps(
rawProps);
auto userProps =
winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
->CreateProps(nullptr);
->CreateProps(
nullptr,
props ? static_cast<winrt::Microsoft::ReactNative::implementation::AbiProps const &>(*props).UserProps()
: nullptr);
shadowNodeProps->SetUserProps(userProps);

const auto &dynamic = static_cast<folly::dynamic>(rawProps);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ facebook::react::Props::Shared AbiViewComponentDescriptor::cloneProps(
winrt::make<winrt::Microsoft::ReactNative::implementation::ViewProps>(shadowNodeProps, false /*holdRef*/);
auto userProps =
winrt::get_self<winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder>(m_builder)
->CreateProps(viewProps);
->CreateProps(viewProps, props ? static_cast<AbiViewProps const &>(*props).UserProps() : nullptr);
shadowNodeProps->SetUserProps(userProps, viewProps);

const auto &dynamic = static_cast<folly::dynamic>(rawProps);
Expand Down
7 changes: 7 additions & 0 deletions vnext/Microsoft.ReactNative/Fabric/AbiViewProps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IBrush Color::AsIntern
return winrt::get_self<winrt::Microsoft::ReactNative::Composition::implementation::Theme>(theme)->Brush(*m_color);
}

bool Color::Equals(const winrt::Microsoft::ReactNative::Color &color) const noexcept {
if (!color) {
return false;
}
return m_color == winrt::get_self<Color>(color)->m_color;
}

winrt::Microsoft::ReactNative::Color Color::ReadValue(
const winrt::Microsoft::ReactNative::IJSValueReader &reader) noexcept {
switch (reader.ValueType()) {
Expand Down
2 changes: 2 additions & 0 deletions vnext/Microsoft.ReactNative/Fabric/AbiViewProps.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ struct Color : ColorT<Color, Composition::Experimental::IInternalColor> {
winrt::Microsoft::ReactNative::Composition::Experimental::IBrush AsInternalBrush(
const winrt::Microsoft::ReactNative::Composition::Theme theme) noexcept;

bool Equals(const winrt::Microsoft::ReactNative::Color &color) const noexcept;

static winrt::Microsoft::ReactNative::Color ReadValue(
const winrt::Microsoft::ReactNative::IJSValueReader &reader) noexcept;
static void WriteValue(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,10 @@ void ComponentView::ReleasePointerCapture(
->ReleasePointerCapture(pointer, static_cast<facebook::react::Tag>(Tag()));
}

void ComponentView::SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept {
m_flags = viewFeatures;
}

RECT ComponentView::getClientRect() const noexcept {
RECT rc{0};
facebook::react::Point parentOffset{0};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ struct ComponentView : public ComponentViewT<
void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
bool CapturePointer(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
void ReleasePointerCapture(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept;

std::vector<facebook::react::ComponentDescriptorProvider> supplementalComponentDescriptorProviders() noexcept
override;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ void ReactCompositionViewComponentBuilder::SetCreateProps(ViewPropsFactory impl)
m_propsFactory = impl;
}

IComponentProps ReactCompositionViewComponentBuilder::CreateProps(ViewProps props) noexcept {
return m_propsFactory(props);
IComponentProps ReactCompositionViewComponentBuilder::CreateProps(
ViewProps props,
const IComponentProps &cloneFrom) noexcept {
return m_propsFactory(props, cloneFrom);
}

void ReactCompositionViewComponentBuilder::CreateShadowNode(ShadowNode shadowNode) noexcept {
Expand Down Expand Up @@ -72,27 +74,32 @@ void ReactCompositionViewComponentBuilder::InitializeComponentView(

void ReactCompositionViewComponentBuilder::SetComponentViewInitializer(
const ComponentViewInitializer &initializer) noexcept {
m_fnCreateView =
[initializer](const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context) {
auto view = winrt::make<winrt::Microsoft::ReactNative::implementation::ComponentView>(tag, reactContext);
initializer(view);
return view;
};
m_fnCreateView = [initializer](
const IReactContext &reactContext,
int32_t tag,
const Experimental::ICompositionContext &context,
ComponentViewFeatures) {
auto view = winrt::make<winrt::Microsoft::ReactNative::implementation::ComponentView>(tag, reactContext);
initializer(view);
return view;
};
m_descriptorConstructorFactory = []() {
return &facebook::react::concreteComponentDescriptorConstructor<::Microsoft::ReactNative::AbiComponentDescriptor>;
};
}

void ReactCompositionViewComponentBuilder::SetViewComponentViewInitializer(
const ViewComponentViewInitializer &initializer) noexcept {
m_fnCreateView =
[initializer](const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context) {
auto view = winrt::Microsoft::ReactNative::Composition::implementation::ViewComponentView::Create(
context, tag, reactContext)
.as<winrt::Microsoft::ReactNative::Composition::ViewComponentView>();
initializer(view);
return view;
};
m_fnCreateView = [initializer](
const IReactContext &reactContext,
int32_t tag,
const Experimental::ICompositionContext &context,
ComponentViewFeatures features) {
auto view = winrt::make<implementation::ViewComponentView>(
implementation::ViewComponentView::defaultProps(), context, tag, reactContext, features);
initializer(view);
return view;
};
m_descriptorConstructorFactory = []() {
return &facebook::react::concreteComponentDescriptorConstructor<
::Microsoft::ReactNative::AbiViewComponentDescriptor>;
Expand All @@ -101,9 +108,12 @@ void ReactCompositionViewComponentBuilder::SetViewComponentViewInitializer(

void ReactCompositionViewComponentBuilder::SetContentIslandComponentViewInitializer(
const ComponentIslandComponentViewInitializer &initializer) noexcept {
m_fnCreateView = [initializer](
const IReactContext &reactContext, int32_t tag, const Experimental::ICompositionContext &context)
-> winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView {
m_fnCreateView =
[initializer](
const IReactContext &reactContext,
int32_t tag,
const Experimental::ICompositionContext &context,
ComponentViewFeatures) -> winrt::Microsoft::ReactNative::Composition::ContentIslandComponentView {
auto view = winrt::make<winrt::Microsoft::ReactNative::Composition::implementation::ContentIslandComponentView>(
context, tag, reactContext);
initializer(view);
Expand Down Expand Up @@ -186,12 +196,16 @@ void ReactCompositionViewComponentBuilder::SetCreateVisualHandler(CreateVisualDe
m_createVisualHandler = impl;
}

void ReactCompositionViewComponentBuilder::SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept {
m_features = viewFeatures;
}

winrt::Microsoft::ReactNative::ComponentView ReactCompositionViewComponentBuilder::CreateView(
const IReactContext &reactContext,
int32_t tag,
const Experimental::ICompositionContext &context) noexcept {
assert(m_fnCreateView);
auto view = m_fnCreateView(reactContext, tag, context);
auto view = m_fnCreateView(reactContext, tag, context, m_features);
InitializeComponentView(view);
return view;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,11 @@ struct ReactCompositionViewComponentBuilder : winrt::implements<
public: // Composition::IReactCompositionViewComponentBuilder
void SetViewComponentViewInitializer(const ViewComponentViewInitializer &initializer) noexcept;
void SetContentIslandComponentViewInitializer(const ComponentIslandComponentViewInitializer &initializer) noexcept;

void SetCreateVisualHandler(CreateVisualDelegate impl) noexcept;
void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept;

public:
IComponentProps CreateProps(ViewProps props) noexcept;
IComponentProps CreateProps(ViewProps props, const IComponentProps &cloneFrom) noexcept;
void CreateShadowNode(ShadowNode shadowNode) noexcept;
void CloneShadowNode(ShadowNode shadowNode, ShadowNode sourceShadowNode) noexcept;
winrt::Windows::Foundation::IInspectable InitialStateData(
Expand All @@ -69,10 +69,12 @@ struct ReactCompositionViewComponentBuilder : winrt::implements<
InitialStateDataFactory m_initialStateDataFactory;
winrt::Microsoft::ReactNative::MeasureContentHandler m_measureContent;
winrt::Microsoft::ReactNative::LayoutHandler m_layoutHandler;
ComponentViewFeatures m_features{ComponentViewFeatures::Default};
std::function<winrt::Microsoft::ReactNative::ComponentView(
const IReactContext &reactContext,
int32_t tag,
const Experimental::ICompositionContext &context)>
const Experimental::ICompositionContext &context,
ComponentViewFeatures features)>
m_fnCreateView;
std::function<facebook::react::ComponentDescriptorConstructor *()> m_descriptorConstructorFactory;
winrt::Microsoft::ReactNative::HandleCommandDelegate m_customCommandHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ namespace Microsoft.ReactNative.Composition
void SetViewComponentViewInitializer(ViewComponentViewInitializer initializer);
void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer);
void SetCreateVisualHandler(CreateVisualDelegate impl);
void SetViewFeatures(ComponentViewFeatures viewFeatures);
};

} // namespace Microsoft.ReactNative
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ namespace Microsoft.ReactNative

[experimental]
DOC_STRING("A delegate that creates a @IComponentProps object for an instance of @ViewProps. See @IReactViewComponentBuilder.SetCreateProps")
delegate IComponentProps ViewPropsFactory(ViewProps props);
delegate IComponentProps ViewPropsFactory(ViewProps props, IComponentProps cloneFrom);

[experimental]
delegate Windows.Foundation.Size MeasureContentHandler(ShadowNode shadowNode, LayoutContext layoutContext, LayoutConstraints layoutConstraints);
Expand Down
2 changes: 2 additions & 0 deletions vnext/Microsoft.ReactNative/ViewProps.idl
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ namespace Microsoft.ReactNative {
Microsoft.UI.Composition.CompositionBrush AsBrush(Microsoft.ReactNative.Composition.Theme theme);
#endif

Boolean Equals(Color color);

static Color Black();
static Color Transparent();
static Color ReadValue(IJSValueReader reader);
Expand Down