Skip to content

Commit 606fafa

Browse files
hryhoriiK97claude
andcommitted
Look up Android image resources without throwing an exception
ResourceDrawableIdHelper.getResourceDrawableId first tried to parse the resource name as a number with toInt() and caught the NumberFormatException. Bundled images in Release builds are drawable resources whose names are not numbers, so every such image source threw an exception and filled in its stack trace. Use toIntOrNull() instead, which parses the same way without throwing. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 7fc911a commit 606fafa

2 files changed

Lines changed: 79 additions & 5 deletions

File tree

‎packages/react-native/ReactAndroid/src/main/java/com/facebook/react/views/imagehelper/ResourceDrawableIdHelper.kt‎

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,10 @@ public object ResourceDrawableIdHelper {
3131
}
3232
val normalizedName = name.lowercase().replace("-", "_")
3333

34-
// name could be a resource id.
35-
try {
36-
return normalizedName.toInt()
37-
} catch (e: NumberFormatException) {
38-
// Do nothing.
34+
// name could be a resource id. Most names are not numbers, so this must not throw: an
35+
// exception would build a stack trace for every image source.
36+
normalizedName.toIntOrNull()?.let {
37+
return it
3938
}
4039

4140
synchronized(this) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
package com.facebook.react.views.imagehelper
9+
10+
import android.content.Context
11+
import org.assertj.core.api.Assertions.assertThat
12+
import org.junit.After
13+
import org.junit.Before
14+
import org.junit.Test
15+
import org.junit.runner.RunWith
16+
import org.robolectric.RobolectricTestRunner
17+
import org.robolectric.RuntimeEnvironment
18+
19+
@RunWith(RobolectricTestRunner::class)
20+
class ResourceDrawableIdHelperTest {
21+
22+
private lateinit var context: Context
23+
24+
@Before
25+
fun setUp() {
26+
context = RuntimeEnvironment.getApplication()
27+
ResourceDrawableIdHelper.clear()
28+
}
29+
30+
@After
31+
fun tearDown() {
32+
ResourceDrawableIdHelper.clear()
33+
}
34+
35+
@Test
36+
fun returnsZeroForMissingName() {
37+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, null)).isEqualTo(0)
38+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, "")).isEqualTo(0)
39+
}
40+
41+
@Test
42+
fun returnsNumericNameAsId() {
43+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, "123")).isEqualTo(123)
44+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, "+42")).isEqualTo(42)
45+
}
46+
47+
@Test
48+
fun looksUpNonNumericNameAsDrawable() {
49+
val expected =
50+
context.resources.getIdentifier(
51+
"redbox_top_border_background",
52+
"drawable",
53+
context.packageName,
54+
)
55+
assertThat(expected).isGreaterThan(0)
56+
assertThat(
57+
ResourceDrawableIdHelper.getResourceDrawableId(
58+
context,
59+
"Redbox-Top-Border-Background",
60+
)
61+
)
62+
.isEqualTo(expected)
63+
}
64+
65+
@Test
66+
fun looksUpNumberThatDoesNotFitInAnIntAsDrawable() {
67+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, "99999999999")).isEqualTo(0)
68+
}
69+
70+
@Test
71+
fun returnsZeroForUnknownDrawable() {
72+
assertThat(ResourceDrawableIdHelper.getResourceDrawableId(context, "unknown_image"))
73+
.isEqualTo(0)
74+
}
75+
}

0 commit comments

Comments
 (0)