Repository navigation
Commit aa811de
Scope the TextInput spannable cache to the React instance
Summary:
WARNING: Generated by Autopilot (alpha) — review carefully, verify the underlying claim before accepting.
Agent: React Native Agent (Bugs) | Trajectory: https://www.internalfb.com/intern/devai/devmate/inspector/4f3686f6-6eac-416a-8116-4fd4ee5a627f/ | SC job: https://www.internalfb.com/intern/sandcastle/instance/54043196239422512/
---
On Fabric, `ReactEditText` caches its spannable in `TextLayoutManager` keyed by react tag, and the shadow node's state keeps that tag as `cachedAttributedStringId` to re-measure against. The cache was a single process-global map keyed only by tag. React tags restart for every new React instance, so after a reload the old and new instances can use the same tags in the same map: the new instance can read the old instance's spannable, and when an old `ReactEditText` is finalized it removes the new view's entry. The next cached measure then fails `checkNotNull` in `getOrCreateSpannableForText` with "Required value was null".
This change gives each React instance its own spannable cache:
- `TextLayoutManager` keeps one map per `ReactApplicationContext`. `FabricUIManager` creates it in its constructor and removes it in `invalidate()`.
- `FabricUIManager.measureText` passes its own context, so a cached measure only looks in that instance's map.
- `ReactEditText` writes to and evicts from the map of the context it was created with (`ThemedReactContext.reactApplicationContext`). Create, destroy, read and write all resolve the key through one helper, so a view's `ThemedReactContext` and `FabricUIManager`'s `ReactApplicationContext` always hit the same map. After teardown, an old view's set or evict does nothing because its map is gone.
- A layout that started before `invalidate()` can still reach `measureText` after the map is removed. In that case the cached measure uses an empty spannable instead of throwing, because the cache-id `MapBuffer` carries only the id and there is nothing to rebuild from. The result belongs to an instance that is going away. A missing entry in a live map still fails `checkNotNull`.
This replaces the previous version of this diff, where `finalize()` only evicted the spannable the instance itself had cached. Per-tag eviction still happens in `finalize()`, but now only within the view's own instance, where tags are never reused. I did not move eviction to `onDropViewInstance`: a commit whose layout is still running on a background thread can measure a TextInput after the UI thread has already processed that view's delete, so evicting right away would add a new way to hit the same `checkNotNull`.
Changelog:
[Android][Fixed] - Fix TextInput measurement crash ("Required value was null") after a React instance reload, by scoping the cached TextInput spannables to the React instance
Reviewed By: zeyap
Differential Revision: D1228703001 parent 4e6bf24 commit aa811de
4 files changed
Lines changed: 178 additions & 9 deletions
File tree
- packages/react-native/ReactAndroid/src
- main/java/com/facebook/react
- fabric
- views
- textinput
- text
- test/java/com/facebook/react/views/textinput
Lines changed: 4 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
259 | 259 | | |
260 | 260 | | |
261 | 261 | | |
| 262 | + | |
262 | 263 | | |
263 | 264 | | |
264 | 265 | | |
| |||
496 | 497 | | |
497 | 498 | | |
498 | 499 | | |
| 500 | + | |
499 | 501 | | |
500 | 502 | | |
501 | 503 | | |
| |||
658 | 660 | | |
659 | 661 | | |
660 | 662 | | |
661 | | - | |
| 663 | + | |
| 664 | + | |
662 | 665 | | |
663 | 666 | | |
664 | 667 | | |
| |||
Lines changed: 40 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
30 | 30 | | |
31 | 31 | | |
32 | 32 | | |
| 33 | + | |
33 | 34 | | |
34 | 35 | | |
35 | 36 | | |
| |||
42 | 43 | | |
43 | 44 | | |
44 | 45 | | |
| 46 | + | |
45 | 47 | | |
46 | 48 | | |
47 | 49 | | |
| |||
115 | 117 | | |
116 | 118 | | |
117 | 119 | | |
118 | | - | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
119 | 125 | | |
120 | 126 | | |
121 | 127 | | |
| |||
180 | 186 | | |
181 | 187 | | |
182 | 188 | | |
183 | | - | |
184 | | - | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
185 | 209 | | |
186 | 210 | | |
187 | | - | |
188 | | - | |
| 211 | + | |
| 212 | + | |
189 | 213 | | |
190 | 214 | | |
191 | 215 | | |
| |||
765 | 789 | | |
766 | 790 | | |
767 | 791 | | |
| 792 | + | |
768 | 793 | | |
769 | 794 | | |
770 | 795 | | |
771 | 796 | | |
772 | | - | |
| 797 | + | |
| 798 | + | |
| 799 | + | |
| 800 | + | |
773 | 801 | | |
774 | 802 | | |
775 | 803 | | |
| |||
1091 | 1119 | | |
1092 | 1120 | | |
1093 | 1121 | | |
| 1122 | + | |
1094 | 1123 | | |
1095 | 1124 | | |
1096 | 1125 | | |
| |||
1099 | 1128 | | |
1100 | 1129 | | |
1101 | 1130 | | |
| 1131 | + | |
1102 | 1132 | | |
1103 | 1133 | | |
1104 | 1134 | | |
| |||
1463 | 1493 | | |
1464 | 1494 | | |
1465 | 1495 | | |
| 1496 | + | |
1466 | 1497 | | |
1467 | 1498 | | |
1468 | 1499 | | |
| |||
1476 | 1507 | | |
1477 | 1508 | | |
1478 | 1509 | | |
| 1510 | + | |
1479 | 1511 | | |
1480 | 1512 | | |
1481 | 1513 | | |
| |||
1492 | 1524 | | |
1493 | 1525 | | |
1494 | 1526 | | |
| 1527 | + | |
1495 | 1528 | | |
1496 | 1529 | | |
1497 | 1530 | | |
| |||
1506 | 1539 | | |
1507 | 1540 | | |
1508 | 1541 | | |
| 1542 | + | |
1509 | 1543 | | |
1510 | 1544 | | |
1511 | 1545 | | |
| |||
Lines changed: 2 additions & 2 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
292 | 292 | | |
293 | 293 | | |
294 | 294 | | |
295 | | - | |
| 295 | + | |
296 | 296 | | |
297 | 297 | | |
298 | 298 | | |
| |||
1220 | 1220 | | |
1221 | 1221 | | |
1222 | 1222 | | |
1223 | | - | |
| 1223 | + | |
1224 | 1224 | | |
1225 | 1225 | | |
1226 | 1226 | | |
| |||
Lines changed: 132 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
0 commit comments