fix(session-replay-react-native): SRMaskView pointerEvents compiles across RN 0.73-0.88 (SDKRN-41)#1874
Merged
aliaksandr-kazarez merged 3 commits intoJul 9, 2026
Conversation
…N-41) RN 0.79 converted ReactPointerEventsView to a Kotlin interface with a val pointerEvents property, so the 0.77-era override fun getPointerEvents() belt-and-braces accessor 'overrides nothing' and hard-fails compilation on RN 0.78+ (found by the RN-version matrix sweep, lane 0.79 — a publish blocker for New-Architecture consumers on newer RN). No accessor override can compile against both shapes, so drop it: keep the init-time setPointerEvents(BOX_NONE) and re-assert it in onLayout (a version-stable hook that runs before any capture/touch can observe a recycled instance whose field was reset). Instrumented suite 16/16 on RN 0.77.2; the 0.79 lane verified the identical semantics compile and behave (5-min crash-stress, 78/78 taps through masks, Switch responsive under a widened frame) with this shape. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…d ReactViewGroup (SDKRN-41) The stable/nightly matrix lane showed the previous commit is still broken on RN >= 0.81: ReactViewGroup.java became ReactViewGroup.kt in RN 0.81, so setPointerEvents(...) is an unresolved reference from Kotlin source there. Property-assignment syntax (pointerEvents = BOX_NONE) is the one shape that compiles everywhere: Kotlin synthesizes the property from the Java accessor pair on <= 0.80 and binds the real property on 0.81+. Verified equivalent by the lane's marked node_modules experiments on 0.86.0 and 0.88.0-nightly-20260709 (build + device smoke green with property syntax). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ABI shapes (SDKRN-41)
The cross-version sweep disproved both prior shapes: RN ~0.78-0.80 has a
Kotlin ReactPointerEventsView declaring val pointerEvents over a still-Java
ReactViewGroup, so property assignment fails there ('val' cannot be
reassigned) while the explicit setter call fails on 0.81+ (Kotlinized
ReactViewGroup, unresolved reference). No single Kotlin syntax compiles
against all three eras.
The bytecode always has setPointerEvents(PointerEvents) — the Java method
through 0.80, the Kotlin-var-generated setter from 0.81 (javap-verified on
the 0.86 AAR) — and Java source resolves against bytecode. Add a minimal
Java shim (SRMaskViewPointerEvents.forceBoxNone) and call it from init and
onLayout. Sweep verification: stock tarball compile on RN 0.73 old-arch,
0.77.2, 0.79, 0.86.0, and 0.88.0-nightly.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
size-limit report 📦
|
aliaksandr-kazarez
marked this pull request as ready for review
July 9, 2026 22:36
Contributor
Author
|
bugbot review |
There was a problem hiding this comment.
✅ Bugbot reviewed your changes and found no new issues!
Comment @cursor review or bugbot run to trigger another review on this PR
Reviewed by Cursor Bugbot for commit 4c14be0. Configure here.
Contributor
There was a problem hiding this comment.
Pull request overview
Fixes an Android New Architecture build break in @amplitude/session-replay-react-native by making SRMaskView’s pointerEvents = BOX_NONE enforcement compile across React Native 0.73–0.88 despite RN’s incompatible pointerEvents source-level API shapes.
Changes:
- Added a small Java shim that calls
ReactViewGroup#setPointerEvents(PointerEvents.BOX_NONE)against stable bytecode across RN versions. - Updated
SRMaskViewto use the shim (ininitand again inonLayout) and removed the Kotlin accessor override that fails to compile across RN eras.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/session-replay-react-native/android/src/newarch/java/com/amplitude/sessionreplayreactnative/fabric/SRMaskViewPointerEvents.java | Adds the Java bytecode-level shim to set pointerEvents in a cross-RN-compatible way. |
| packages/session-replay-react-native/android/src/newarch/java/com/amplitude/sessionreplayreactnative/fabric/SRMaskView.kt | Replaces Kotlin pointerEvents handling with the shim and reasserts BOX_NONE during layout to survive recycling resets. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Mercy811
approved these changes
Jul 9, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes a publish blocker for
@amplitude/session-replay-react-native(SDKRN-41): the FabricSRMaskView's touch-transparency code (pointerEvents = BOX_NONE, shipped in #1866) does not compile on React Native ≥ 0.78 — New-Architecture consumers on newer RN cannot build the package at all.Found by a cross-version compile/behavior sweep (RN 0.73 / 0.76 / 0.77.2 / 0.79.5 / 0.86.0 / 0.88-nightly, package installed via
npm packtarball into fresh apps).The problem: three incompatible ABI shapes
pointerEventschanged source-level shape twice as Meta Kotlinized the RN Android codebase, and no single Kotlin syntax compiles against all three eras:setPointerEvents(...)calloverride fun getPointerEvents()ReactViewGroupget/setReactPointerEventsViewdeclaresval pointerEvents;ReactViewGroupstill Java'val' cannot be reassignedReactViewGroupwithvar pointerEventsThe first two fix attempts on this branch each cover two of the three eras (kept as commits for the archaeology; each was disproven empirically by the sweep).
The fix: a bytecode-level Java shim
The bytecode has
setPointerEvents(PointerEvents)in every era — the Java method through 0.80, the Kotlin-var-generated setter from 0.81 (verified viajavapof the react-android 0.86 AAR). Java source resolves against bytecode, immune to Kotlin's property semantics. So:SRMaskViewPointerEvents.java— a ~10-line package-private shim:view.setPointerEvents(PointerEvents.BOX_NONE)SRMaskView.ktcalls it frominitand re-asserts inonLayout(covers recycling resets version-agnostically; replaces the unshippable accessor override)Verification
Stock tarball (no local patches), Android compile per version — with explicit verification that
compileDebugJavaWithJavacexecutes and the shim.classlands in the library output on every new-arch lane:assembleDebug(newarch sources excluded; packaging sane)assembleDebug; separately: 5-min debug crash-stress + 12/12 taps-through-mask + masking verified in captured replay (iOS 0.79 also device-verified: ~9 min, ~8,700 stress commits, zero asserts)assembleDebug(device behavior verified with semantically identical code during the sweep)assembleDebugiOS is untouched by this change (its analogue is the version-stable
hitTestoverride).Do NOT "simplify" the shim back into Kotlin — the constraint is documented in both files, and any Kotlin call/override/assignment shape breaks at least one supported RN era.
Checklist
🤖 Generated with Claude Code
Note
Low Risk
Narrow Android Fabric touch-targeting fix with unchanged intended behavior; no auth, data, or API surface changes.
Overview
Fixes a publish blocker where Fabric
SRMaskViewno longer compiled on React Native ≥ 0.78 because Kotlin cannot expresspointerEvents = BOX_NONEconsistently across RN’s three incompatible Android API shapes.SRMaskViewPointerEvents.javais added as a small Java shim that callssetPointerEvents(PointerEvents.BOX_NONE)against bytecode that exists on all supported RN versions.SRMaskView.ktdrops direct KotlinsetPointerEventsusage and thegetPointerEvents()override, and instead callsSRMaskViewPointerEvents.forceBoxNone(this)ininitand again inonLayoutso touch transparency survives view recycling without version-specific overrides.Reviewed by Cursor Bugbot for commit 4c14be0. Bugbot is set up for automated code reviews on this repo. Configure here.