Bump @expensify/react-native-live-markdown to 0.1.328 (fix APP-EF1 iOS App Hang)#94828
Conversation
Fixes APP-EF1: iOS App Hang in MarkdownTextInput Yoga layout (createStringFromUtf8). The new version persists RCTMarkdownUtils across shadow node clones so MarkdownParser's one-entry memo cache survives repeated Yoga measure callbacks instead of being discarded on every call to applyMarkdownFormattingToTextInputState. Resolves Expensify#93831
|
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cffc658f49
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppandroid.movAndroid: mWeb ChromeiOS: HybridAppios.moviOS: mWeb SafariMacOS: Chrome / Safari |
|
🚧 mountiny has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/mountiny in version: 9.4.25-0 🚀
|
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.4.25-2 🚀
Bundle Size Analysis (Sentry): |
Explanation of Change
Bumps
@expensify/react-native-live-markdownfrom 0.1.327 → 0.1.328 to fix a recurring iOS HybridApp hang (Sentry APP-EF1, 1,082 affected users).Root cause: On iOS,
MarkdownTextInputDecoratorShadowNode::measureContentcalledapplyMarkdownFormattingToTextInputStateon every Yoga measure pass. Inside that function a brand-newRCTMarkdownUtils(→ freshMarkdownParserwith empty_prevTextcache) was allocated on each call. Because Yoga invokes the measure callback many times per layout pass and the parser cache was always cold, the full JSI string creation + worklet parse ran repeatedly on the main thread. On large composer inputs this accumulated past iOS's ~2 s watchdog → App Hang (createStringFromUtf8in the stack).Fix (in 0.1.328): Persist one
RCTMarkdownUtilson the shadow node and carry it across clones (mirroring how the Android shadow node already persisted its parser state). The parser's existing one-entry memo cache (_prevText + _prevParserId) now survives repeated Yoga measure callbacks so unchanged text is parsed at most once per actual text/parserId change. Style and parserId are passed per-call via a new locked overload ofapplyMarkdownFormatting:withDefaultTextAttributes:markdownStyle:parserId:so concurrent Fabric commits don't race on the shared instance.Fix commit in live-markdown:
ecc8175— fix(ios): persist RCTMarkdownUtils across shadow node clones to prevent AppHangFixed Issues
$ #93831
PROPOSAL: #93831 (comment)
Tests
Offline tests
N/A — this is a native iOS library bump with no JS-layer network calls affected. Markdown formatting works the same regardless of connectivity.
QA Steps
**text**,@mention, URLs) still highlights correctly.PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)Avatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
before
qweqw.mov
after
fqwfw.mov
iOS: mWeb Safari
MacOS: Chrome / Safari