From 452af525f7d30c9449098c82a0c9b4035bb4f38e Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 17:18:19 +0200 Subject: [PATCH 1/4] feat: Upgrade Nitro to 0.37 for View improvements --- bun.lock | 18 ++-- example/ios/Podfile.lock | 4 +- example/package.json | 2 +- .../JHybridNitroImageViewStateUpdater.cpp | 72 +++++++++------ .../JHybridNitroImageViewStateUpdater.hpp | 7 +- .../views/HybridNitroImageViewManager.kt | 36 +++++--- .../views/HybridNitroImageViewStateUpdater.kt | 4 +- .../views/HybridNitroImageViewComponent.mm | 88 ++++++++++++------- .../views/HybridNitroImageViewComponent.cpp | 83 ++--------------- .../views/HybridNitroImageViewComponent.hpp | 78 ++++++---------- .../react-native-nitro-image/package.json | 4 +- .../react-native-nitro-web-image/package.json | 4 +- 12 files changed, 190 insertions(+), 210 deletions(-) diff --git a/bun.lock b/bun.lock index 98c5a4b1..abcc2036 100644 --- a/bun.lock +++ b/bun.lock @@ -30,7 +30,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -57,10 +57,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -74,10 +74,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -1555,7 +1555,7 @@ "new-github-release-url": ["new-github-release-url@2.0.0", "", { "dependencies": { "type-fest": "^2.5.1" } }, "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ=="], - "nitrogen": ["nitrogen@0.36.5", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.36.5", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-PvlHrBVaoKEaD6CCUCG7om8MTvLeh4ZSDxHoRx2YiEWUVXPXrRN9NwMn1gjie9Bd91jHA3dYMF7no9Eme4txMA=="], + "nitrogen": ["nitrogen@0.37.0-beta.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-pKrlM7ZYlAVdVNpho9XvGeGOw7gzH0IglQjnmkeDk3aZASLBhGEMlmfq+LsaRGcONxpO4kayTMH/fd3/IaBoTA=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -1723,7 +1723,7 @@ "react-native-nitro-image": ["react-native-nitro-image@workspace:packages/react-native-nitro-image"], - "react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-kGfWyj3IS7+B3IaukbaO84/YcdevhXWCGqBHzwQ7yvALBty56MPt18H9hCKAaua7oNEk0ZZUo3kgMr3o9CYpGA=="], "react-native-nitro-web-image": ["react-native-nitro-web-image@workspace:packages/react-native-nitro-web-image"], @@ -2543,6 +2543,10 @@ "react-native-builder-bob/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], + "react-native-nitro-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + + "react-native-nitro-web-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], + "release-it/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "release-it/url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="], diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index eca8dcba..14a741cd 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -61,7 +61,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.36.5): + - NitroModules (0.37.0-beta.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2284,7 +2284,7 @@ SPEC CHECKSUMS: hermes-engine: ef561c35b1325a953b54456ddbd27ee0faf01ba4 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 452230d9b63c6c3f59dd97eeaa27ec3449271d4a + NitroModules: 6b173a14405398cc5db9568ee4b1ac091aebc20a NitroWebImage: ca414f829cae44174179ea0e8ff28df75f40f08e RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/example/package.json b/example/package.json index f5f30da1..a397216e 100644 --- a/example/package.json +++ b/example/package.json @@ -19,7 +19,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2" diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.cpp b/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.cpp index 81eb6e4c..3a03ad18 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.cpp +++ b/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.cpp @@ -15,49 +15,69 @@ namespace margelo::nitro::image::views { using namespace facebook; using ConcreteStateData = react::ConcreteState; -void JHybridNitroImageViewStateUpdater::updateViewProps(jni::alias_ref /* class */, - jni::alias_ref javaView, - jni::alias_ref stateWrapperInterface) { - std::shared_ptr hybridView = javaView->getJHybridNitroImageViewSpec(); - +std::shared_ptr JHybridNitroImageViewStateUpdater::getPropsFromStateWrapper( + jni::alias_ref stateWrapper) { + if (stateWrapper.get() == nullptr) { + return nullptr; + } // Get concrete StateWrapperImpl from passed StateWrapper interface object - jobject rawStateWrapper = stateWrapperInterface.get(); - if (!stateWrapperInterface->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { - throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + jobject rawStateWrapper = stateWrapper.get(); + if (!stateWrapper->isInstanceOf(react::StateWrapperImpl::javaClassStatic())) [[unlikely]] { + throw std::runtime_error("StateWrapper is not a StateWrapperImpl"); + } + auto stateWrapperImpl = jni::alias_ref{ + static_cast(rawStateWrapper) + }; + std::shared_ptr state = stateWrapperImpl->cthis()->getState(); + if (state == nullptr) { + return nullptr; } - auto stateWrapper = jni::alias_ref{ - static_cast(rawStateWrapper)}; - std::shared_ptr state = stateWrapper->cthis()->getState(); auto concreteState = std::static_pointer_cast(state); const HybridNitroImageViewState& data = concreteState->getData(); - const std::shared_ptr& props = data.getProps(); + const std::shared_ptr& props = data.getProps(); if (props == nullptr) [[unlikely]] { - // Props aren't set yet! throw std::runtime_error("HybridNitroImageViewState's data doesn't contain any props!"); } + return props; +} + +void JHybridNitroImageViewStateUpdater::updateViewProps(jni::alias_ref /* class */, + jni::alias_ref javaView, + jni::alias_ref newState, + jni::alias_ref oldState) { + std::shared_ptr hybridView = javaView->getJHybridNitroImageViewSpec(); + std::shared_ptr newProps = getPropsFromStateWrapper(newState); + std::shared_ptr oldProps = getPropsFromStateWrapper(oldState); + if (newProps == nullptr) [[unlikely]] { + throw std::runtime_error("Current StateWrapper doesn't contain any props!"); + } - // Update all props if they are dirty - if (props->image.isDirty) { - hybridView->setImage(props->image.value); - props->image.isDirty = false; + // Update only props that differ from the previous State snapshot. + if (oldProps == nullptr + ? newProps->image.isProvided() + : !newProps->image.hasSameValue(oldProps->image)) { + hybridView->setImage(newProps->image.get()); } - if (props->resizeMode.isDirty) { - hybridView->setResizeMode(props->resizeMode.value); - props->resizeMode.isDirty = false; + if (oldProps == nullptr + ? newProps->resizeMode.isProvided() + : !newProps->resizeMode.hasSameValue(oldProps->resizeMode)) { + hybridView->setResizeMode(newProps->resizeMode.get()); } - if (props->recyclingKey.isDirty) { - hybridView->setRecyclingKey(props->recyclingKey.value); - props->recyclingKey.isDirty = false; + if (oldProps == nullptr + ? newProps->recyclingKey.isProvided() + : !newProps->recyclingKey.hasSameValue(oldProps->recyclingKey)) { + hybridView->setRecyclingKey(newProps->recyclingKey.get()); } // Update hybridRef if it changed - if (props->hybridRef.isDirty) { + if (oldProps == nullptr + ? newProps->hybridRef.isProvided() + : !newProps->hybridRef.hasSameValue(oldProps->hybridRef)) { // hybridRef changed - call it with new this - const auto& maybeFunc = props->hybridRef.value; + const auto& maybeFunc = newProps->hybridRef.get(); if (maybeFunc.has_value()) { maybeFunc.value()(hybridView); } - props->hybridRef.isDirty = false; } } diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.hpp b/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.hpp index b37d81e7..fb0edf54 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/android/c++/views/JHybridNitroImageViewStateUpdater.hpp @@ -31,7 +31,12 @@ class JHybridNitroImageViewStateUpdater final: public jni::JavaClass /* class */, jni::alias_ref view, - jni::alias_ref stateWrapperInterface); + jni::alias_ref newState, + jni::alias_ref oldState); + +private: + static std::shared_ptr getPropsFromStateWrapper( + jni::alias_ref stateWrapper); public: static void registerNatives() { diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewManager.kt b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewManager.kt index a0c23213..a59da19b 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewManager.kt +++ b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewManager.kt @@ -20,6 +20,14 @@ import com.margelo.nitro.image.* * Represents the React Native `ViewManager` for the "NitroImageView" Nitro HybridView. */ public class HybridNitroImageViewManager: SimpleViewManager() { + /** + * Represents the View and its last state snapshot (mutable) + */ + private class HybridViewHolder( + val hybridView: HybridImageView, + var lastState: StateWrapper? = null, + ) + init { if (RecyclableView::class.java.isAssignableFrom(HybridImageView::class.java)) { // Enable view recycling @@ -34,33 +42,41 @@ public class HybridNitroImageViewManager: SimpleViewManager() { override fun createViewInstance(reactContext: ThemedReactContext): View { val hybridView = HybridImageView(reactContext) val view = hybridView.view - view.setTag(associated_hybrid_view_tag, hybridView) + view.setTag(associated_hybrid_view_tag, HybridViewHolder(hybridView)) return view } override fun updateState(view: View, props: ReactStylesDiffMap, stateWrapper: StateWrapper): Any? { - val hybridView = getHybridView(view) + val holder = getHybridViewHolder(view) ?: throw Error("Couldn't find view $view in local views table!") + val hybridView = holder.hybridView + val oldState = holder.lastState + val newState = stateWrapper // 1. Update each prop individually hybridView.beforeUpdate() - HybridNitroImageViewStateUpdater.updateViewProps(hybridView, stateWrapper) + HybridNitroImageViewStateUpdater.updateViewProps(hybridView, newState, oldState) hybridView.afterUpdate() + holder.lastState = newState // 2. Continue in base View props - return super.updateState(view, props, stateWrapper) + return super.updateState(view, props, newState) } override fun onDropViewInstance(view: View) { - val hybridView = getHybridView(view) - hybridView?.onDropView() + val holder = getHybridViewHolder(view) + holder?.lastState = null + holder?.hybridView?.onDropView() return super.onDropViewInstance(view) } protected override fun prepareToRecycleView(reactContext: ThemedReactContext, view: View): View? { - super.prepareToRecycleView(reactContext, view) - val hybridView = getHybridView(view) + val preparedView = super.prepareToRecycleView(reactContext, view) + ?: return null + val holder = getHybridViewHolder(preparedView) ?: return null + val hybridView = holder.hybridView + holder.lastState = null @Suppress("USELESS_IS_CHECK") if (hybridView is RecyclableView) { @@ -74,7 +90,7 @@ public class HybridNitroImageViewManager: SimpleViewManager() { } } - private fun getHybridView(view: View): HybridImageView? { - return view.getTag(associated_hybrid_view_tag) as? HybridImageView + private fun getHybridViewHolder(view: View): HybridViewHolder? { + return view.getTag(associated_hybrid_view_tag) as? HybridViewHolder } } diff --git a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewStateUpdater.kt b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewStateUpdater.kt index a77cb5d9..d010544b 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewStateUpdater.kt +++ b/packages/react-native-nitro-image/nitrogen/generated/android/kotlin/com/margelo/nitro/image/views/HybridNitroImageViewStateUpdater.kt @@ -14,10 +14,10 @@ internal class HybridNitroImageViewStateUpdater { companion object { /** * Updates the props for [view] through C++. - * The [state] prop is expected to contain [view]'s props as wrapped Fabric state. + * The [newState] prop is expected to contain [view]'s props as wrapped Fabric state. */ @Suppress("KotlinJniMissingFunction") @JvmStatic - external fun updateViewProps(view: HybridNitroImageViewSpec, state: StateWrapper) + external fun updateViewProps(view: HybridNitroImageViewSpec, newState: StateWrapper, oldState: StateWrapper?) } } diff --git a/packages/react-native-nitro-image/nitrogen/generated/ios/c++/views/HybridNitroImageViewComponent.mm b/packages/react-native-nitro-image/nitrogen/generated/ios/c++/views/HybridNitroImageViewComponent.mm index 176e7b23..34ef3c1e 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/ios/c++/views/HybridNitroImageViewComponent.mm +++ b/packages/react-native-nitro-image/nitrogen/generated/ios/c++/views/HybridNitroImageViewComponent.mm @@ -37,6 +37,7 @@ + (BOOL)shouldBeRecycled; @implementation HybridNitroImageViewComponent { std::shared_ptr _hybridView; + BOOL _didDropView; } + (void) load { @@ -50,6 +51,7 @@ + (void) load { - (instancetype) init { if (self = [super init]) { + _props = HybridNitroImageViewShadowNode::defaultSharedProps(); std::shared_ptr hybridView = NitroImage::NitroImageAutolinking::createNitroImageView(); _hybridView = std::dynamic_pointer_cast(hybridView); [self updateView]; @@ -69,45 +71,67 @@ - (void) updateView { [self setContentView:view]; } +- (void) notifyOnDropView { + // A recycled component can later be invalidated. Notify only once per mount. + if (_didDropView) { + return; + } + NitroImage::HybridNitroImageViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); + swiftPart.onDropView(); + _didDropView = YES; +} + - (void) updateProps:(const std::shared_ptr&)props oldProps:(const std::shared_ptr&)oldProps { + // A props update marks a newly mounted or still-active component. + _didDropView = NO; + // 1. Downcast props - const auto& newViewPropsConst = *std::static_pointer_cast(props); - auto& newViewProps = const_cast(newViewPropsConst); + const auto& newViewProps = *std::static_pointer_cast(props); + const auto* oldViewProps = static_cast(oldProps.get()); NitroImage::HybridNitroImageViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - // 2. Update each prop individually - swiftPart.beforeUpdate(); - - // image: optional - if (newViewProps.image.isDirty) { - swiftPart.setImage(newViewProps.image.value); - newViewProps.image.isDirty = false; - } - // resizeMode: optional - if (newViewProps.resizeMode.isDirty) { - swiftPart.setResizeMode(newViewProps.resizeMode.value); - newViewProps.resizeMode.isDirty = false; - } - // recyclingKey: optional - if (newViewProps.recyclingKey.isDirty) { - swiftPart.setRecyclingKey(newViewProps.recyclingKey.value); - newViewProps.recyclingKey.isDirty = false; - } - - swiftPart.afterUpdate(); + // 2. Update only props that differ from the previous Props snapshot. + const bool hasTransactionPropChanges = oldViewProps == nullptr + ? newViewProps.hasAnyProvidedProps() + : !newViewProps.hasSameProps(*oldViewProps); + if (hasTransactionPropChanges) { + swiftPart.beforeUpdate(); + + // image: optional + if (oldViewProps == nullptr + ? newViewProps.image.isProvided() + : !newViewProps.image.hasSameValue(oldViewProps->image)) { + swiftPart.setImage(newViewProps.image.get()); + } + // resizeMode: optional + if (oldViewProps == nullptr + ? newViewProps.resizeMode.isProvided() + : !newViewProps.resizeMode.hasSameValue(oldViewProps->resizeMode)) { + swiftPart.setResizeMode(newViewProps.resizeMode.get()); + } + // recyclingKey: optional + if (oldViewProps == nullptr + ? newViewProps.recyclingKey.isProvided() + : !newViewProps.recyclingKey.hasSameValue(oldViewProps->recyclingKey)) { + swiftPart.setRecyclingKey(newViewProps.recyclingKey.get()); + } - // 3. Update hybridRef if it changed - if (newViewProps.hybridRef.isDirty) { - // hybridRef changed - call it with new this - const auto& maybeFunc = newViewProps.hybridRef.value; - if (maybeFunc.has_value()) { - maybeFunc.value()(_hybridView); + // Update hybridRef if it changed + if (oldViewProps == nullptr + ? newViewProps.hybridRef.isProvided() + : !newViewProps.hybridRef.hasSameValue(oldViewProps->hybridRef)) { + // hybridRef changed - call it with new this + const auto& maybeFunc = newViewProps.hybridRef.get(); + if (maybeFunc.has_value()) { + maybeFunc.value()(_hybridView); + } } - newViewProps.hybridRef.isDirty = false; + + swiftPart.afterUpdate(); } - // 4. Continue in base class + // 3. Continue in base class [super updateProps:props oldProps:oldProps]; } @@ -116,6 +140,7 @@ + (BOOL)shouldBeRecycled { } - (void)prepareForRecycle { + [self notifyOnDropView]; [super prepareForRecycle]; NitroImage::HybridNitroImageViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); swiftPart.maybePrepareForRecycle(); @@ -123,8 +148,7 @@ - (void)prepareForRecycle { #ifdef ENABLE_RCT_COMPONENT_VIEW_INVALIDATE - (void)invalidate { - NitroImage::HybridNitroImageViewSpec_cxx& swiftPart = _hybridView->getSwiftPart(); - swiftPart.onDropView(); + [self notifyOnDropView]; [super invalidate]; } #endif diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp index 7a77d827..c5c416cd 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp @@ -7,65 +7,23 @@ #include "HybridNitroImageViewComponent.hpp" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include namespace margelo::nitro::image::views { + using namespace facebook; + extern const char HybridNitroImageViewComponentName[] = "NitroImageView"; HybridNitroImageViewProps::HybridNitroImageViewProps(const react::PropsParserContext& context, const HybridNitroImageViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - image([&]() -> CachedProp, std::shared_ptr>>> { - try { - const react::RawValue* rawValue = rawProps.at("image", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.image; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp, std::shared_ptr>>>::fromRawValue(*runtime, value, sourceProps.image); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("NitroImageView.image: ") + exc.what()); - } - }()), - resizeMode([&]() -> CachedProp> { - try { - const react::RawValue* rawValue = rawProps.at("resizeMode", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.resizeMode; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>::fromRawValue(*runtime, value, sourceProps.resizeMode); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("NitroImageView.resizeMode: ") + exc.what()); - } - }()), - recyclingKey([&]() -> CachedProp> { - try { - const react::RawValue* rawValue = rawProps.at("recyclingKey", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.recyclingKey; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp>::fromRawValue(*runtime, value, sourceProps.recyclingKey); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("NitroImageView.recyclingKey: ") + exc.what()); - } - }()), - hybridRef([&]() -> CachedProp& /* ref */)>>> { - try { - const react::RawValue* rawValue = rawProps.at("hybridRef", nullptr, nullptr); - if (rawValue == nullptr) return sourceProps.hybridRef; - const auto& [runtime, value] = (std::pair)*rawValue; - return CachedProp& /* ref */)>>>::fromRawValue(*runtime, value.asObject(*runtime).getProperty(*runtime, PropNameIDCache::get(*runtime, "f")), sourceProps.hybridRef); - } catch (const std::exception& exc) { - throw std::runtime_error(std::string("NitroImageView.hybridRef: ") + exc.what()); - } - }()) { } + image(nitro::CachedProp, std::shared_ptr>>>::fromRawValue("NitroImageView", "image", rawProps, sourceProps.image)), + resizeMode(nitro::CachedProp>::fromRawValue("NitroImageView", "resizeMode", rawProps, sourceProps.resizeMode)), + recyclingKey(nitro::CachedProp>::fromRawValue("NitroImageView", "recyclingKey", rawProps, sourceProps.recyclingKey)), + hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("NitroImageView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridNitroImageViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { @@ -77,29 +35,4 @@ namespace margelo::nitro::image::views { } } - HybridNitroImageViewComponentDescriptor::HybridNitroImageViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters) - : ConcreteComponentDescriptor(parameters, - react::RawPropsParser()) {} - - std::shared_ptr HybridNitroImageViewComponentDescriptor::cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const { - // 1. Prepare raw props parser - rawProps.parse(rawPropsParser_); - // 2. Copy props with Nitro's cached copy constructor - return HybridNitroImageViewShadowNode::Props(context, /* & */ rawProps, props); - } - -#ifdef ANDROID - void HybridNitroImageViewComponentDescriptor::adopt(react::ShadowNode& shadowNode) const { - // This is called immediately after `ShadowNode` is created, cloned or in progress. - // On Android, we need to wrap props in our state, which gets routed through Java and later unwrapped in JNI/C++. - auto& concreteShadowNode = static_cast(shadowNode); - const std::shared_ptr& constProps = concreteShadowNode.getConcreteSharedProps(); - const std::shared_ptr& props = std::const_pointer_cast(constProps); - HybridNitroImageViewState state{props}; - concreteShadowNode.setStateData(std::move(state)); - } -#endif - } // namespace margelo::nitro::image::views diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp index 91248b9e..d4e2e1d1 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp @@ -7,14 +7,15 @@ #pragma once -#include -#include -#include #include -#include -#include +#include +#include #include #include +#include +#include + +#include #include #include "HybridImageSpec.hpp" @@ -46,10 +47,26 @@ namespace margelo::nitro::image::views { const react::RawProps& rawProps); public: - CachedProp, std::shared_ptr>>> image; - CachedProp> resizeMode; - CachedProp> recyclingKey; - CachedProp& /* ref */)>>> hybridRef; + nitro::CachedProp, std::shared_ptr>>> image; + nitro::CachedProp> resizeMode; + nitro::CachedProp> recyclingKey; + nitro::CachedProp& /* ref */)>>> hybridRef; + + [[nodiscard]] + bool hasSameProps(const HybridNitroImageViewProps& other) const noexcept { + return image.hasSameValue(other.image) && + resizeMode.hasSameValue(other.resizeMode) && + recyclingKey.hasSameValue(other.recyclingKey) && + hybridRef.hasSameValue(other.hybridRef); + } + + [[nodiscard]] + bool hasAnyProvidedProps() const noexcept { + return image.isProvided() || + resizeMode.isProvided() || + recyclingKey.isProvided() || + hybridRef.isProvided(); + } private: static bool filterObjectKeys(const std::string& propName); @@ -58,32 +75,7 @@ namespace margelo::nitro::image::views { /** * State for the "NitroImageView" View. */ - class HybridNitroImageViewState final { - public: - HybridNitroImageViewState() = default; - explicit HybridNitroImageViewState(const std::shared_ptr& props): - _props(props) {} - - public: - [[nodiscard]] - const std::shared_ptr& getProps() const { - return _props; - } - - public: -#ifdef ANDROID - HybridNitroImageViewState(const HybridNitroImageViewState& /* previousState */, folly::dynamic /* data */) {} - folly::dynamic getDynamic() const { - throw std::runtime_error("HybridNitroImageViewState does not support folly!"); - } - react::MapBuffer getMapBuffer() const { - throw std::runtime_error("HybridNitroImageViewState does not support MapBuffer!"); - }; -#endif - - private: - std::shared_ptr _props; - }; + using HybridNitroImageViewState = nitro::ViewPropsHolderState; /** * The Shadow Node for the "NitroImageView" View. @@ -96,21 +88,7 @@ namespace margelo::nitro::image::views { /** * The Component Descriptor for the "NitroImageView" View. */ - class HybridNitroImageViewComponentDescriptor final: public react::ConcreteComponentDescriptor { - public: - explicit HybridNitroImageViewComponentDescriptor(const react::ComponentDescriptorParameters& parameters); - - public: - /** - * A faster path for cloning props - reuses the caching logic from `HybridNitroImageViewProps`. - */ - std::shared_ptr cloneProps(const react::PropsParserContext& context, - const std::shared_ptr& props, - react::RawProps rawProps) const override; -#ifdef ANDROID - void adopt(react::ShadowNode& shadowNode) const override; -#endif - }; + using HybridNitroImageViewComponentDescriptor = nitro::ViewComponentDescriptor; /* The actual view for "NitroImageView" needs to be implemented in platform-specific code. */ diff --git a/packages/react-native-nitro-image/package.json b/packages/react-native-nitro-image/package.json index f6d2104e..9e4ed3ea 100644 --- a/packages/react-native-nitro-image/package.json +++ b/packages/react-native-nitro-image/package.json @@ -58,10 +58,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3" }, "peerDependencies": { diff --git a/packages/react-native-nitro-web-image/package.json b/packages/react-native-nitro-web-image/package.json index 20ddfcf9..d2278821 100644 --- a/packages/react-native-nitro-web-image/package.json +++ b/packages/react-native-nitro-web-image/package.json @@ -57,10 +57,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.36.5", + "nitrogen": "0.37.0-beta.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.36.5", + "react-native-nitro-modules": "0.37.0-beta.0", "typescript": "6.0.3" }, "peerDependencies": { From 06031d0a86e41a041fbf21901d6b679343acb45e Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 17:33:14 +0200 Subject: [PATCH 2/4] fix: Force single react-native-nitro-modules resolution via overrides peerDependencies "*" doesn't match prereleases per semver, so bun auto-installed a nested 0.36.5 copy under each workspace package. Metro bundled that 0.36.5 JS while native built against 0.37.0-beta.0, tripping Nitro's "installed twice" version guard in the harness tests. --- bun.lock | 5 +---- package.json | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/bun.lock b/bun.lock index abcc2036..ac8fe2d0 100644 --- a/bun.lock +++ b/bun.lock @@ -91,6 +91,7 @@ "overrides": { "@babel/plugin-transform-modules-systemjs": "^7.29.7", "@babel/preset-env": "^7.29.7", + "react-native-nitro-modules": "0.37.0-beta.0", }, "packages": { "@ark/schema": ["@ark/schema@0.56.0", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA=="], @@ -2543,10 +2544,6 @@ "react-native-builder-bob/yargs": ["yargs@18.0.0", "", { "dependencies": { "cliui": "^9.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "string-width": "^7.2.0", "y18n": "^5.0.5", "yargs-parser": "^22.0.0" } }, "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg=="], - "react-native-nitro-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - - "react-native-nitro-web-image/react-native-nitro-modules": ["react-native-nitro-modules@0.36.5", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-SJby84+hovD70JmQ1fq+56tw3oapJeChehUqXA4Gqjm+ktJhMAcj8LGwoAjStSOUwRaK7czbzBPB0Widj+EDoQ=="], - "release-it/semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], "release-it/url-join": ["url-join@5.0.0", "", {}, "sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA=="], diff --git a/package.json b/package.json index 6fa61801..2cac3761 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ ], "overrides": { "@babel/preset-env": "^7.29.7", - "@babel/plugin-transform-modules-systemjs": "^7.29.7" + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "react-native-nitro-modules": "0.37.0-beta.0" }, "scripts": { "build": "bun run --cwd packages/react-native-nitro-image build && bun run --cwd packages/react-native-nitro-web-image build", From 7ac9f9ebe2722aa61762540eb003e6e948deb7f2 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 18:39:43 +0200 Subject: [PATCH 3/4] feat: Update Nitro to 0.37.0-beta.1 Nitrogen 0.37.0-beta.1 renames CachedProp to ReactProp in generated view props, so specs were re-generated. CachedProp remains as a deprecated alias upstream and no hand-written code referenced it. Also drops the react-native-nitro-modules override again - now that #170 marks the peer dependency as optional, bun no longer installs a second stable copy alongside the pre-release, so the workaround is redundant. --- bun.lock | 15 +++++++-------- example/ios/Podfile.lock | 4 ++-- example/package.json | 2 +- package.json | 3 +-- .../c++/views/HybridNitroImageViewComponent.cpp | 10 +++++----- .../c++/views/HybridNitroImageViewComponent.hpp | 10 +++++----- packages/react-native-nitro-image/package.json | 4 ++-- .../react-native-nitro-web-image/package.json | 4 ++-- 8 files changed, 25 insertions(+), 27 deletions(-) diff --git a/bun.lock b/bun.lock index c216216e..04c0645a 100644 --- a/bun.lock +++ b/bun.lock @@ -30,7 +30,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -57,10 +57,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3", }, "peerDependencies": { @@ -77,10 +77,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3", }, "peerDependencies": { @@ -97,7 +97,6 @@ "overrides": { "@babel/plugin-transform-modules-systemjs": "^7.29.7", "@babel/preset-env": "^7.29.7", - "react-native-nitro-modules": "0.37.0-beta.0", }, "packages": { "@ark/schema": ["@ark/schema@0.56.0", "", { "dependencies": { "@ark/util": "0.56.0" } }, "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA=="], @@ -1562,7 +1561,7 @@ "new-github-release-url": ["new-github-release-url@2.0.0", "", { "dependencies": { "type-fest": "^2.5.1" } }, "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ=="], - "nitrogen": ["nitrogen@0.37.0-beta.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-pKrlM7ZYlAVdVNpho9XvGeGOw7gzH0IglQjnmkeDk3aZASLBhGEMlmfq+LsaRGcONxpO4kayTMH/fd3/IaBoTA=="], + "nitrogen": ["nitrogen@0.37.0-beta.1", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.1", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-DMe2KA168ZWY9pkn1BFhTPjg2yfcVF4e/Fboj9lQElK3wBMYzDECIgcgHvfeoxo+z9ZBRVV4PR4p8c57PiOccQ=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -1730,7 +1729,7 @@ "react-native-nitro-image": ["react-native-nitro-image@workspace:packages/react-native-nitro-image"], - "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-kGfWyj3IS7+B3IaukbaO84/YcdevhXWCGqBHzwQ7yvALBty56MPt18H9hCKAaua7oNEk0ZZUo3kgMr3o9CYpGA=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-PQfd8YVgK+sDrcw+m8EZ9jBD1bgmoHhofDO882EGDaRlKoCAUy1yvMP16esouk8CnMEBGdKToWW2EBOu13JUBA=="], "react-native-nitro-web-image": ["react-native-nitro-web-image@workspace:packages/react-native-nitro-web-image"], diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 14a741cd..e270c47f 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -61,7 +61,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.37.0-beta.0): + - NitroModules (0.37.0-beta.1): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2284,7 +2284,7 @@ SPEC CHECKSUMS: hermes-engine: ef561c35b1325a953b54456ddbd27ee0faf01ba4 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 6b173a14405398cc5db9568ee4b1ac091aebc20a + NitroModules: 7b1bbaed4743fc48e3dfc50d1f8aaf58a8421c31 NitroWebImage: ca414f829cae44174179ea0e8ff28df75f40f08e RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/example/package.json b/example/package.json index a397216e..476747e5 100644 --- a/example/package.json +++ b/example/package.json @@ -19,7 +19,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2" diff --git a/package.json b/package.json index 2cac3761..6fa61801 100644 --- a/package.json +++ b/package.json @@ -11,8 +11,7 @@ ], "overrides": { "@babel/preset-env": "^7.29.7", - "@babel/plugin-transform-modules-systemjs": "^7.29.7", - "react-native-nitro-modules": "0.37.0-beta.0" + "@babel/plugin-transform-modules-systemjs": "^7.29.7" }, "scripts": { "build": "bun run --cwd packages/react-native-nitro-image build && bun run --cwd packages/react-native-nitro-web-image build", diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp index c5c416cd..a65f0aaf 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.cpp @@ -8,7 +8,7 @@ #include "HybridNitroImageViewComponent.hpp" #include -#include +#include namespace margelo::nitro::image::views { @@ -20,10 +20,10 @@ namespace margelo::nitro::image::views { const HybridNitroImageViewProps& sourceProps, const react::RawProps& rawProps): react::ViewProps(context, sourceProps, rawProps, filterObjectKeys), - image(nitro::CachedProp, std::shared_ptr>>>::fromRawValue("NitroImageView", "image", rawProps, sourceProps.image)), - resizeMode(nitro::CachedProp>::fromRawValue("NitroImageView", "resizeMode", rawProps, sourceProps.resizeMode)), - recyclingKey(nitro::CachedProp>::fromRawValue("NitroImageView", "recyclingKey", rawProps, sourceProps.recyclingKey)), - hybridRef(nitro::CachedProp& /* ref */)>>>::fromRawValue("NitroImageView", "hybridRef", rawProps, sourceProps.hybridRef)) { } + image(nitro::ReactProp, std::shared_ptr>>>::fromRawValue("NitroImageView", "image", rawProps, sourceProps.image)), + resizeMode(nitro::ReactProp>::fromRawValue("NitroImageView", "resizeMode", rawProps, sourceProps.resizeMode)), + recyclingKey(nitro::ReactProp>::fromRawValue("NitroImageView", "recyclingKey", rawProps, sourceProps.recyclingKey)), + hybridRef(nitro::ReactProp& /* ref */)>>>::fromRawValue("NitroImageView", "hybridRef", rawProps, sourceProps.hybridRef)) { } bool HybridNitroImageViewProps::filterObjectKeys(const std::string& propName) { switch (hashString(propName)) { diff --git a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp index d4e2e1d1..0f0ab044 100644 --- a/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp +++ b/packages/react-native-nitro-image/nitrogen/generated/shared/c++/views/HybridNitroImageViewComponent.hpp @@ -7,7 +7,7 @@ #pragma once -#include +#include #include #include #include @@ -47,10 +47,10 @@ namespace margelo::nitro::image::views { const react::RawProps& rawProps); public: - nitro::CachedProp, std::shared_ptr>>> image; - nitro::CachedProp> resizeMode; - nitro::CachedProp> recyclingKey; - nitro::CachedProp& /* ref */)>>> hybridRef; + nitro::ReactProp, std::shared_ptr>>> image; + nitro::ReactProp> resizeMode; + nitro::ReactProp> recyclingKey; + nitro::ReactProp& /* ref */)>>> hybridRef; [[nodiscard]] bool hasSameProps(const HybridNitroImageViewProps& other) const noexcept { diff --git a/packages/react-native-nitro-image/package.json b/packages/react-native-nitro-image/package.json index 8e767ab2..53adf6d5 100644 --- a/packages/react-native-nitro-image/package.json +++ b/packages/react-native-nitro-image/package.json @@ -58,10 +58,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3" }, "peerDependencies": { diff --git a/packages/react-native-nitro-web-image/package.json b/packages/react-native-nitro-web-image/package.json index 86f65dcb..368f6367 100644 --- a/packages/react-native-nitro-web-image/package.json +++ b/packages/react-native-nitro-web-image/package.json @@ -57,10 +57,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.0", + "nitrogen": "0.37.0-beta.1", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.0", + "react-native-nitro-modules": "0.37.0-beta.1", "typescript": "6.0.3" }, "peerDependencies": { From 318d0de289ee5152b58b6141f84d80a0e48813b2 Mon Sep 17 00:00:00 2001 From: Marc Rousavy Date: Thu, 20 Aug 2026 19:48:22 +0200 Subject: [PATCH 4/4] feat: Update Nitro to 0.37.0 0.37.0 stable generates identical specs to 0.37.0-beta.1, so there is no codegen delta - only the version pins and lockfiles change. --- bun.lock | 14 +++++++------- example/ios/Podfile.lock | 4 ++-- example/package.json | 2 +- packages/react-native-nitro-image/package.json | 4 ++-- packages/react-native-nitro-web-image/package.json | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/bun.lock b/bun.lock index 04c0645a..5694ed62 100644 --- a/bun.lock +++ b/bun.lock @@ -30,7 +30,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2", @@ -57,10 +57,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -77,10 +77,10 @@ "version": "0.15.1", "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3", }, "peerDependencies": { @@ -1561,7 +1561,7 @@ "new-github-release-url": ["new-github-release-url@2.0.0", "", { "dependencies": { "type-fest": "^2.5.1" } }, "sha512-NHDDGYudnvRutt/VhKFlX26IotXe1w0cmkDm6JGquh5bz/bDTw0LufSmH/GxTjEdpHEO+bVKFTwdrcGa/9XlKQ=="], - "nitrogen": ["nitrogen@0.37.0-beta.1", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0-beta.1", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-DMe2KA168ZWY9pkn1BFhTPjg2yfcVF4e/Fboj9lQElK3wBMYzDECIgcgHvfeoxo+z9ZBRVV4PR4p8c57PiOccQ=="], + "nitrogen": ["nitrogen@0.37.0", "", { "dependencies": { "chalk": "^5.3.0", "react-native-nitro-modules": "^0.37.0", "ts-morph": "^28.0.0", "yargs": "^18.0.0", "zod": "^4.4.3" }, "bin": { "nitrogen": "lib/index.js" } }, "sha512-lrWmvctRyazMLU6y4ThUl6q129wMCOvmQfdtqCeZShgmmh3Nbplm9dSJLN2OZSBnDWA5k+T2P8aiNyjr1yiJAg=="], "nocache": ["nocache@3.0.4", "", {}, "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw=="], @@ -1729,7 +1729,7 @@ "react-native-nitro-image": ["react-native-nitro-image@workspace:packages/react-native-nitro-image"], - "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0-beta.1", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-PQfd8YVgK+sDrcw+m8EZ9jBD1bgmoHhofDO882EGDaRlKoCAUy1yvMP16esouk8CnMEBGdKToWW2EBOu13JUBA=="], + "react-native-nitro-modules": ["react-native-nitro-modules@0.37.0", "", { "peerDependencies": { "react": "*", "react-native": "*" } }, "sha512-ULS2CBZcdwGw5d4Y35EV/tbCOsNsQOnQ9LC9CehMhDNm5c90lwF/LxRamzKuFpjI547G7teTQgD0peqYSGnP9g=="], "react-native-nitro-web-image": ["react-native-nitro-web-image@workspace:packages/react-native-nitro-web-image"], diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index e270c47f..79f8f632 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -61,7 +61,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - NitroModules (0.37.0-beta.1): + - NitroModules (0.37.0): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2284,7 +2284,7 @@ SPEC CHECKSUMS: hermes-engine: ef561c35b1325a953b54456ddbd27ee0faf01ba4 libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8 NitroImage: 2f592086cbdecbbaa1c10dd97e0cdd43b1bb0817 - NitroModules: 7b1bbaed4743fc48e3dfc50d1f8aaf58a8421c31 + NitroModules: cda827b31eb05c1bfcc0e2bbd9b647a69c6c314f NitroWebImage: ca414f829cae44174179ea0e8ff28df75f40f08e RCTDeprecation: a4c521821fab57cbb125b36effe84d897d0dfa12 RCTRequired: 9f3a7e5645d4bc3f551593de7550bb66ab6e42bc diff --git a/example/package.json b/example/package.json index 476747e5..7e0add0d 100644 --- a/example/package.json +++ b/example/package.json @@ -19,7 +19,7 @@ "react-native-fast-image": "^8.6.3", "react-native-harness": "^1.3.0", "react-native-nitro-image": "workspace:*", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "react-native-nitro-web-image": "workspace:*", "react-native-safe-area-context": "^5.8.0", "react-native-screens": "^4.25.2" diff --git a/packages/react-native-nitro-image/package.json b/packages/react-native-nitro-image/package.json index 53adf6d5..5a4ee6d9 100644 --- a/packages/react-native-nitro-image/package.json +++ b/packages/react-native-nitro-image/package.json @@ -58,10 +58,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3" }, "peerDependencies": { diff --git a/packages/react-native-nitro-web-image/package.json b/packages/react-native-nitro-web-image/package.json index 368f6367..379c9eff 100644 --- a/packages/react-native-nitro-web-image/package.json +++ b/packages/react-native-nitro-web-image/package.json @@ -57,10 +57,10 @@ }, "devDependencies": { "@types/react": "^19.2.15", - "nitrogen": "0.37.0-beta.1", + "nitrogen": "0.37.0", "react": "19.2.3", "react-native": "0.85.3", - "react-native-nitro-modules": "0.37.0-beta.1", + "react-native-nitro-modules": "0.37.0", "typescript": "6.0.3" }, "peerDependencies": {