Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use .at() method instead of operator[] for shareable worklet lookup #604

Merged
merged 1 commit into from
Jan 31, 2025

Conversation

tomekzaw
Copy link
Collaborator

@tomekzaw tomekzaw commented Jan 30, 2025

Details

This PR partially fixes the following crash on Android:

react-native-live-markdown/cpp/MarkdownGlobal.cpp:40: std::shared_ptr<ShareableWorklet> expensify::livemarkdown::getMarkdownWorklet(const int): assertion "worklet != nullptr" failed

For some reason, getMarkdownWorklet is called for given parserId after unregisterMarkdownWorklet is called. The reason is currently unknown and will be investigated separately. In such case, globalMarkdownShareableWorklets[parserId] returns nullptr (and also stores nullptr in globalMarkdownShareableWorklets, sic!) and the assert fails.

After this change, in such case globalMarkdownShareableWorklets.at(parserId) will throw an exception. The exception will be passed through C++ code and then passed to Java side where it is already handled here:

json = nativeParse(text, parserId);
} catch (Exception e) {
// Skip formatting, runGuarded will show the error in LogBox
mPrevText = text;
mPrevParserId = parserId;
mPrevMarkdownRanges = Collections.emptyList();
return mPrevMarkdownRanges;
} finally {

Related Issues

Manual Tests

  1. Apply the following changes:
diff --git a/example/src/App.tsx b/example/src/App.tsx
index 2d48a2b..b9b21e7 100644
--- a/example/src/App.tsx
+++ b/example/src/App.tsx
@@ -54,6 +54,11 @@ export default function App() {
 
   const ref = React.useRef<MarkdownTextInput>(null);
 
+  const parser = (markdown: string) => {
+    'worklet';
+    return parseExpensiMark(markdown);
+  };
+
   return (
     <View style={styles.container}>
       <PlatformInfo />
@@ -66,7 +71,7 @@ export default function App() {
         style={[styles.input, style]}
         ref={ref}
         markdownStyle={markdownStyle}
-        parser={parseExpensiMark}
+        parser={parser}
         placeholder="Type here..."
         onSelectionChange={e => setSelection(e.nativeEvent.selection)}
         selection={selection}
diff --git a/src/MarkdownTextInput.tsx b/src/MarkdownTextInput.tsx
index bff1928..0439547 100644
--- a/src/MarkdownTextInput.tsx
+++ b/src/MarkdownTextInput.tsx
@@ -105,8 +105,7 @@ const MarkdownTextInput = React.forwardRef<MarkdownTextInput, MarkdownTextInputP
 
   const parserId = React.useMemo(() => {
     return registerParser(props.parser);
-    // eslint-disable-next-line react-hooks/exhaustive-deps
-  }, [workletHash]);
+  }, [props.parser]);
 
   React.useEffect(() => {
     return () => unregisterParser(parserId);
  1. Build and launch the app on Android emulator
  2. Place your cursor at the end of line > blockquote
  3. Press a key multiple times

Linked PRs

@tomekzaw tomekzaw merged commit c3f616b into main Jan 31, 2025
7 checks passed
@tomekzaw tomekzaw deleted the @tomekzaw/global-markdown-shareable-worklets-at branch January 31, 2025 14:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants