From 179a492290a530fa947e8262c197c3013c1bf82b Mon Sep 17 00:00:00 2001 From: Nicola Corti Date: Fri, 15 May 2026 07:19:12 -0700 Subject: [PATCH] Remove `!!` from `YogaNodeJNIBase` (#56841) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: X-link: https://github.com/facebook/yoga/pull/1961 Follow-up to D104666335 (Yoga Java→Kotlin migration of `YogaNodeJNIBase`). The original migration kept several `!!` (not-null assertion) operators. Per reviewer feedback, replace them with safer Kotlin idioms: - `addChildAt`: replace the `if (children == null) { children = ArrayList(4) } children!!.add(...)` pattern with a single `val list = children ?: ArrayList(4).also { children = it }` so the local `val` is statically non-null and lazy-initializes the backing field in one expression. - `swapChildAt`: capture `children` into a local `val` via `checkNotNull(children) { "YogaNode does not have children" }` instead of `children!!.removeAt(...)` / `children!!.add(...)`. Surfaces a clearer `IllegalStateException` instead of a bare `KotlinNullPointerException`. - `cloneWithChildren`: collapse `if (clonedYogaNode.children != null) { clonedYogaNode.children = ArrayList(clonedYogaNode.children!!) }` into `clonedYogaNode.children?.let { clonedYogaNode.children = ArrayList(it) }`. - `measure`: fold the existing `if (!isMeasureDefined) throw RuntimeException(...)` guard into `val mf = checkNotNull(measureFunction) { "Measure function isn't defined!" }`. Same behavior, no double-read of the mutable property. - `baseline`: convert the expression body using `baselineFunction!!.baseline(...)` to a block body that uses `checkNotNull(baselineFunction) { "Baseline function isn't defined!" }`. Yields a clearer error than a bare NPE if `baseline()` is ever invoked when no `YogaBaselineFunction` was set. Both mirrored copies (`xplat/yoga/...` and `xplat/js/react-native-github/...`) are kept in sync. Changelog: [Internal] - Differential Revision: D105300348 --- .../java/com/facebook/yoga/YogaNodeJNIBase.kt | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt index 994ba0729de0..3312896c1c3e 100644 --- a/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt +++ b/packages/react-native/ReactAndroid/src/main/java/com/facebook/yoga/YogaNodeJNIBase.kt @@ -70,10 +70,8 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { throw IllegalStateException("Child already has a parent, it must be removed first.") } - if (children == null) { - children = ArrayList(4) - } - children!!.add(i, child) + val list = children ?: ArrayList(4).also { children = it } + list.add(i, child) child.owner = this YogaNative.jni_YGNodeInsertChildJNI(nativePointer, child.nativePointer, i) } @@ -89,8 +87,9 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { if (newChild !is YogaNodeJNIBase) { return } - children!!.removeAt(position) - children!!.add(position, newChild) + val list = checkNotNull(children) { "YogaNode does not have children" } + list.removeAt(position) + list.add(position, newChild) newChild.owner = this YogaNative.jni_YGNodeSwapChildJNI(nativePointer, newChild.nativePointer, position) } @@ -98,9 +97,7 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { override fun cloneWithChildren(): YogaNodeJNIBase { try { val clonedYogaNode = super.clone() as YogaNodeJNIBase - if (clonedYogaNode.children != null) { - clonedYogaNode.children = ArrayList(clonedYogaNode.children!!) - } + clonedYogaNode.children?.let { clonedYogaNode.children = ArrayList(it) } val clonedNativePointer = YogaNative.jni_YGNodeCloneJNI(nativePointer) clonedYogaNode.owner = null clonedYogaNode.nativePointer = clonedNativePointer @@ -540,11 +537,8 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { // methods are final by default, which enforces this constraint. @DoNotStrip public fun measure(width: Float, widthMode: Int, height: Float, heightMode: Int): Long { - if (!isMeasureDefined) { - throw RuntimeException("Measure function isn't defined!") - } - - return measureFunction!!.measure( + val mf = checkNotNull(measureFunction) { "Measure function isn't defined!" } + return mf.measure( this, width, YogaMeasureMode.fromInt(widthMode), @@ -560,8 +554,10 @@ public abstract class YogaNodeJNIBase : YogaNode, Cloneable { // Same JNI jmethodid caching concern as measure() — must not be overridden. @DoNotStrip - public fun baseline(width: Float, height: Float): Float = - baselineFunction!!.baseline(this, width, height) + public fun baseline(width: Float, height: Float): Float { + val bf = checkNotNull(baselineFunction) { "Baseline function isn't defined!" } + return bf.baseline(this, width, height) + } override val isMeasureDefined: Boolean get() = measureFunction != null