diff --git a/README.md b/README.md index 5b07fc43..211cde67 100644 --- a/README.md +++ b/README.md @@ -211,10 +211,11 @@ Currently, `react-native-live-markdown` supports only [ExpensiMark](https://gith ### `react-native-worklets` compatibility -| | 0.6.x | 0.7.x | 0.8.x | 0.9.x | -|:-----------------:|:-----:|:-----:|:-----:|:-----:| -| 0.1.321+ | ❌ | ✅ | ✅ | ✅ | -| 0.1.308 – 0.1.320 | ✅ | ❌ | ❌ | ❌ | +| | 0.6.x | 0.7.x | 0.8.x | 0.9.x | 0.10.x | +|:-----------------:|:-----:|:-----:|:-----:|:-----:|:------:| +| 0.1.333+ | ❌ | ✅ | ✅ | ✅ | ✅ | +| 0.1.321 – 0.1.332 | ❌ | ✅ | ✅ | ✅ | ❌ | +| 0.1.308 – 0.1.320 | ✅ | ❌ | ❌ | ❌ | ❌ | ## License diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 04a3e5c6..201f7b89 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -1810,7 +1810,7 @@ PODS: - ReactNativeDependencies - RNWorklets - Yoga - - RNWorklets (0.9.1): + - RNWorklets (0.10.1): - hermes-engine - RCTRequired - RCTTypeSafety @@ -1832,10 +1832,10 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - ReactNativeDependencies - - RNWorklets/apple (= 0.9.1) - - RNWorklets/common (= 0.9.1) + - RNWorklets/apple (= 0.10.1) + - RNWorklets/common (= 0.10.1) - Yoga - - RNWorklets/apple (0.9.1): + - RNWorklets/apple (0.10.1): - hermes-engine - RCTRequired - RCTTypeSafety @@ -1858,7 +1858,7 @@ PODS: - ReactCommon/turbomodule/core - ReactNativeDependencies - Yoga - - RNWorklets/common (0.9.1): + - RNWorklets/common (0.10.1): - hermes-engine - RCTRequired - RCTTypeSafety @@ -2192,7 +2192,7 @@ SPEC CHECKSUMS: ReactCommon: 7dfc3250793bf36cf221096ff59e1179e13eef7f ReactNativeDependencies: d31ce49efcbdece34c3541b1307e2d9074626c92 RNLiveMarkdown: 325f2f9421d5e9f9214ae5980b50ebe4b2fb6d02 - RNWorklets: c9d31be8d2b0f73d73c573489c885a8534a9f53e + RNWorklets: bb6f040dd3a46ef34d7e9ca51d4c7d1b804c190c Yoga: 77dfa8673de2874e1855002ae59c68b8be9b007b PODFILE CHECKSUM: 3f53660915b3f926239de7f89ab29581306a2614 diff --git a/example/package.json b/example/package.json index e52c0a32..8c60bcce 100644 --- a/example/package.json +++ b/example/package.json @@ -12,7 +12,7 @@ "expensify-common": "2.0.148", "react": "19.2.3", "react-native": "0.85.3", - "react-native-worklets": "0.9.1" + "react-native-worklets": "0.10.1" }, "devDependencies": { "@babel/core": "^7.25.2", diff --git a/package-lock.json b/package-lock.json index 243de05f..e8b49b69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -57,7 +57,7 @@ "react-native": "0.85.3", "react-native-builder-bob": "^0.30.2", "react-native-web": "^0.20.0", - "react-native-worklets": "0.9.1", + "react-native-worklets": "0.10.1", "release-it": "^15.0.0", "turbo": "^1.10.7", "typescript": "^5.8.3" @@ -79,7 +79,7 @@ "expensify-common": "2.0.148", "react": "19.2.3", "react-native": "0.85.3", - "react-native-worklets": "0.9.1" + "react-native-worklets": "0.10.1" }, "devDependencies": { "@babel/core": "^7.25.2", @@ -19551,9 +19551,9 @@ "license": "MIT" }, "node_modules/react-native-worklets": { - "version": "0.9.1", - "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.9.1.tgz", - "integrity": "sha512-kb6lGtBI5Ap41tvBPM09Np472r2GXuJ+jRApIFy1eXBk699eChG3U+lyqRC2/wz/VDpaJAy6i5XPcceNOoH3mA==", + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/react-native-worklets/-/react-native-worklets-0.10.1.tgz", + "integrity": "sha512-62mRM19bDpfpdI8HLkEErcdOsrAPDtE9lA/sw+5lLRpzBHNhxaoj9QyY2KjXqUmirelxkX4zuPGTC3VdA0feJA==", "license": "MIT", "dependencies": { "@babel/plugin-transform-arrow-functions": "^7.27.1", @@ -19565,6 +19565,7 @@ "@babel/plugin-transform-template-literals": "^7.27.1", "@babel/plugin-transform-unicode-regex": "^7.27.1", "@babel/preset-typescript": "^7.28.5", + "@babel/types": "^7.27.1", "convert-source-map": "^2.0.0", "semver": "^7.7.4" }, diff --git a/package.json b/package.json index 595798e4..7a3e29eb 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,7 @@ "react-native": "0.85.3", "react-native-builder-bob": "^0.30.2", "react-native-web": "^0.20.0", - "react-native-worklets": "0.9.1", + "react-native-worklets": "0.10.1", "release-it": "^15.0.0", "turbo": "^1.10.7", "typescript": "^5.8.3" diff --git a/src/MarkdownTextInput.tsx b/src/MarkdownTextInput.tsx index 935b0554..9fca64cd 100644 --- a/src/MarkdownTextInput.tsx +++ b/src/MarkdownTextInput.tsx @@ -1,7 +1,7 @@ import {StyleSheet, TextInput, processColor} from 'react-native'; import React from 'react'; import type {TextInputProps} from 'react-native'; -import {createSerializable, createWorkletRuntime} from 'react-native-worklets'; +import {createSerializable, createWorkletRuntime, registerCustomSerializable} from 'react-native-worklets'; import type {SerializableRef, WorkletFunction, WorkletRuntime} from 'react-native-worklets'; import MarkdownTextInputDecoratorViewNativeComponent from './MarkdownTextInputDecoratorViewNativeComponent'; import type {MarkdownStyle} from './MarkdownTextInputDecoratorViewNativeComponent'; @@ -22,6 +22,34 @@ declare global { let initialized = false; let workletRuntime: WorkletRuntime | undefined; +// The worklet closure of the built-in `parseExpensiMark` parser captures the `Log` singleton from +// `expensify-common`, and serializing the parser worklet fails because `react-native-worklets` 0.10 +// can't copy `Logger` class instances. The logger is unused on the worklet runtime, so serialize it as a no-op. +// `registerCustomSerializable` has been available since react-native-worklets 0.7.0, so this stays +// compatible with every supported version (on 0.9.x and older it's a harmless no-op — they don't throw). +function registerLoggerSerializableOnceIfNeeded() { + type NoopLogger = Record void>; + registerCustomSerializable>({ + name: 'react-native-live-markdown/Logger', + determine: (value): value is NoopLogger => { + 'worklet'; + + return value !== null && typeof value === 'object' && (value as {constructor?: {name?: string}}).constructor?.name === 'Logger'; + }, + pack: () => { + 'worklet'; + + return {}; + }, + unpack: () => { + 'worklet'; + + const noop = () => undefined; + return {logToServer: noop, add: noop, info: noop, alert: noop, warn: noop, hmmm: noop, client: noop}; + }, + }); +} + function getWorkletRuntime(): WorkletRuntime { if (workletRuntime === undefined) { throw new Error( @@ -41,6 +69,7 @@ function initializeLiveMarkdownIfNeeded() { if (!global.jsi_setMarkdownRuntime) { throw new Error('[react-native-live-markdown] global.jsi_setMarkdownRuntime is not available'); } + registerLoggerSerializableOnceIfNeeded(); workletRuntime = createWorkletRuntime({name: 'LiveMarkdownRuntime'}); global.jsi_setMarkdownRuntime(workletRuntime); initialized = true;