From bec8a377f8be8f35680e48093d5ca50854baafed Mon Sep 17 00:00:00 2001 From: rory Date: Mon, 23 Feb 2026 14:39:41 -0800 Subject: [PATCH 1/3] Strip Hermes debug info from production iOS bytecode (standalone) Add a patch for react-native's react-native-xcode.sh to always pass -output-source-map to hermesc for production builds. This strips ~13.4MB of debug metadata from the bytecode by writing it to the source map file instead. When source maps aren't being composed, the generated .map file is cleaned up to prevent it from shipping. This is the standalone App counterpart to the same fix applied in Mobile-Expensify for HybridApp builds. Co-authored-by: Cursor --- ...e+0.81.4+028+strip-hermes-debug-info.patch | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch diff --git a/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch b/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch new file mode 100644 index 0000000000000..9c59b9c4c7cf8 --- /dev/null +++ b/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch @@ -0,0 +1,24 @@ +diff --git a/node_modules/react-native/scripts/react-native-xcode.sh b/node_modules/react-native/scripts/react-native-xcode.sh +--- a/node_modules/react-native/scripts/react-native-xcode.sh ++++ b/node_modules/react-native/scripts/react-native-xcode.sh +@@ -171,17 +171,16 @@ + if [[ $DEV == true ]]; then + EXTRA_COMPILER_ARGS=-Og + else +- EXTRA_COMPILER_ARGS=-O ++ EXTRA_COMPILER_ARGS="-O -output-source-map" + fi +- if [[ $EMIT_SOURCEMAP == true ]]; then +- EXTRA_COMPILER_ARGS="$EXTRA_COMPILER_ARGS -output-source-map" +- fi + "$HERMES_CLI_PATH" -emit-binary -max-diagnostic-width=80 $EXTRA_COMPILER_ARGS -out "$DEST/$BUNDLE_NAME.jsbundle" "$BUNDLE_FILE" + if [[ $EMIT_SOURCEMAP == true ]]; then + HBC_SOURCEMAP_FILE="$DEST/$BUNDLE_NAME.jsbundle.map" + "$NODE_BINARY" "$COMPOSE_SOURCEMAP_PATH" "$PACKAGER_SOURCEMAP_FILE" "$HBC_SOURCEMAP_FILE" -o "$SOURCEMAP_FILE" + rm "$HBC_SOURCEMAP_FILE" + rm "$PACKAGER_SOURCEMAP_FILE" ++ elif [[ $DEV != true ]]; then ++ rm -f "$DEST/$BUNDLE_NAME.jsbundle.map" + fi + BUNDLE_FILE="$DEST/$BUNDLE_NAME.jsbundle" + fi From cd5037778e6c1fe10c5ae050bac2002949903d62 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 26 Feb 2026 15:41:38 -0800 Subject: [PATCH 2/3] Add patch documentation to details.md Made-with: Cursor --- patches/react-native/details.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/patches/react-native/details.md b/patches/react-native/details.md index be59cade91d99..f7b4c34790d15 100644 --- a/patches/react-native/details.md +++ b/patches/react-native/details.md @@ -210,3 +210,10 @@ - Upstream PR/issue: This is not intended to be upstreamed, since this is a low-level fix very specific to the Expensify app's requirements. - E/App issue: [#76859](https://github.com/Expensify/App/issues/76859) - PR introducing patch: [#76154](https://github.com/Expensify/App/pull/76154) + +### [react-native+0.81.4+028+strip-hermes-debug-info.patch](react-native+0.81.4+028+strip-hermes-debug-info.patch) + +- Reason: Always pass `-output-source-map` to `hermesc` for production iOS builds, stripping ~13.4MB of debug metadata from the Hermes bytecode. Previously this flag was only passed when `SOURCEMAP_FILE` was set; if the build environment didn't propagate that variable, debug info remained in the shipped bundle. +- Upstream PR/issue: This should ideally be the default behavior upstream, but no PR has been filed yet. +- E/App issue: [#83000](https://github.com/Expensify/App/issues/83000) +- PR introducing patch: [#83256](https://github.com/Expensify/App/pull/83256) From e29d9332889894f0e4fb35f2cce47256f931b290 Mon Sep 17 00:00:00 2001 From: rory Date: Thu, 26 Feb 2026 17:00:34 -0800 Subject: [PATCH 3/3] Fix: preserve -output-source-map for debug builds with source maps The previous patch broke debug builds on physical devices where EMIT_SOURCEMAP=true. The compose step expects main.jsbundle.map from hermesc, which wasn't being generated for dev builds. Now pass -output-source-map when EITHER source maps are requested (EMIT_SOURCEMAP=true) OR it's a production build (DEV!=true). Made-with: Cursor --- ...ative+0.81.4+028+strip-hermes-debug-info.patch | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch b/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch index 9c59b9c4c7cf8..199e0d9080b67 100644 --- a/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch +++ b/patches/react-native/react-native+0.81.4+028+strip-hermes-debug-info.patch @@ -1,19 +1,16 @@ diff --git a/node_modules/react-native/scripts/react-native-xcode.sh b/node_modules/react-native/scripts/react-native-xcode.sh --- a/node_modules/react-native/scripts/react-native-xcode.sh +++ b/node_modules/react-native/scripts/react-native-xcode.sh -@@ -171,17 +171,16 @@ - if [[ $DEV == true ]]; then - EXTRA_COMPILER_ARGS=-Og +@@ -173,7 +173,7 @@ else -- EXTRA_COMPILER_ARGS=-O -+ EXTRA_COMPILER_ARGS="-O -output-source-map" + EXTRA_COMPILER_ARGS=-O fi - if [[ $EMIT_SOURCEMAP == true ]]; then -- EXTRA_COMPILER_ARGS="$EXTRA_COMPILER_ARGS -output-source-map" -- fi ++ if [[ $EMIT_SOURCEMAP == true || $DEV != true ]]; then + EXTRA_COMPILER_ARGS="$EXTRA_COMPILER_ARGS -output-source-map" + fi "$HERMES_CLI_PATH" -emit-binary -max-diagnostic-width=80 $EXTRA_COMPILER_ARGS -out "$DEST/$BUNDLE_NAME.jsbundle" "$BUNDLE_FILE" - if [[ $EMIT_SOURCEMAP == true ]]; then - HBC_SOURCEMAP_FILE="$DEST/$BUNDLE_NAME.jsbundle.map" +@@ -183,6 +183,8 @@ "$NODE_BINARY" "$COMPOSE_SOURCEMAP_PATH" "$PACKAGER_SOURCEMAP_FILE" "$HBC_SOURCEMAP_FILE" -o "$SOURCEMAP_FILE" rm "$HBC_SOURCEMAP_FILE" rm "$PACKAGER_SOURCEMAP_FILE"