Skip to content

[0.88] Revert EventEmitter ArrayBuffer payload rejection (breaking for C++ TurboModules) #1418

Closed

Description

@fabriziocucci

Target Branch

0.88

Link to commit or PR to be picked

Revert of react/react-native#58063 (ab2ea649e65) on 0.88-stable.

Description

0.88 is a non-breaking release. #58063 is a confirmed breaking change for C++ TurboModules and must not ship in it.

What it does

It adds a codegen parse-time guard, throwIfEventEmitterPayloadTypeIsUnsupported, that rejects ArrayBuffer as a TurboModule EventEmitter payload on all platforms:

export interface Spec extends TurboModule {
  +onBuffer: EventEmitter<ArrayBuffer>;
}

Why this is breaking, demonstrated

The same spec was run through both branches' codegen. It worked on 0.87 and is rejected on 0.88:

0.87.1 0.88-stable
Parse accepted rejected
GenerateModuleH (modulesCxx) succeeded never runs
GenerateModuleObjCpp threw, "Unsupported eventType" never runs

The C++ output on 0.87 is functional, not placeholder:

eventEmitterMap_["onBuffer"] = std::make_shared<AsyncEventEmitter<jsi::Value>>();
static_assert(bridging::supportsFromJs<OnBufferType, jsi::ArrayBuffer>, ...);
static_cast<AsyncEventEmitter<jsi::Value>&>(*eventEmitterMap_["onBuffer"]).emit(...)

and the static_assert passes on 0.87, because struct Bridging<jsi::ArrayBuffer> with fromJs and toJs exists at react/bridging/ArrayBuffer.h:46 and is exported through the Bridging.h umbrella. modulesCxx is a consumer-facing codegen target.

So a C++ TurboModule with an ArrayBuffer event payload parsed, generated, compiled and had working bridging on 0.87, and its build fails on 0.88 with no code change by the consumer.

The iOS path already rejected it on 0.87, which is why this needed checking per generator target rather than once.

Scope

Surface: the codegen parser and generator files that implement the guard (error-utils.js, errors.js, parsers-commons.js, generators/modules/Utils.js, GenerateModuleH.js, GenerateModuleJavaSpec.js, GenerateModuleObjCpp/serializeEventEmitter.js).

0.88-only commits touching that surface, baseline v0.87.1:

  • ab2ea649e65 #58063 — revert
  • 5bb96395949 #57897, 4bf55754905, 5fb3ebce1ac — all predate it and add zero EventEmitter payload validation

Nothing lands after ab2ea649e65 on those files, so no later work conflicts. Both symbols it introduced (throwIfEventEmitterPayloadTypeIsUnsupported, UnsupportedModuleEventEmitterPayloadTypeParserError) are referenced only by files that commit itself created or modified, so the revert is self-contained.

Single commit. 23 files, all JavaScript under react-native-codegen, no native code.

Not reverted

d84c13d5111 (#57982, Java ArrayBuffer borrow contract) is annotated [Android][Breaking] but is not breaking for this release. All three Java ArrayBuffer TurboModule commits are 0.88-only, and 0.87's Android API snapshot contains no Java-facing ArrayBuffer type, only the C++ facebook::jsi::ArrayBuffer and facebook::react::AsyncArrayBuffer. No 0.87 consumer could have adopted it, so constraining it in 0.88 breaks nobody. The label is correct against main's history, not against the released line.

Verification

  • Revert applies cleanly, no conflicts.
  • After reverting, the same spec behaves identically to 0.87: parse accepted, GenerateModuleH succeeds, GenerateModuleObjCpp throws "Unsupported eventType".
  • Both introduced symbols are gone from the tree.
  • yarn jest packages/react-native-codegen passes: 64 suites, 3122 tests, 1277 snapshots.

Activity

  1. github-actions commented on Sep 21, 2026

    @github-actions

    Thank you for opening a new React Native Pick Request.

    These are the criteria we follow when accepting or rejecting a code change into a React Native release branch (source).

    If your Pick Request does not satisfy the criteria below, please close it as it will not be considered.

    ✅ Which Pick Requests we accept
    1. ✅ Fixes for regressions to core APIs. Examples:
      • A core component is behaving differently between versions 0.X and 0.X-1
      • The TurboModule.getEnforcing function is throwing an unexpected assertion error.
    2. ✅ Fixes to bugs in core React Native. Examples:
      • Breakpoints in React Native DevTools not working correctly in the debugger
      • Fast Refresh not working as expected
      • Metro bundler not starting properly or ignoring the configuration file
      • Buttons that are not clickable
    3. ✅ Fixes to APIs used by third-party libraries and out-of-tree platforms. Examples:
      • An API used by react-native-macos is not behaving as expected or is regressing
    4. ✅ Bump of patch version of dependencies. Example:
      • Bump Gradle from 8.11.0 to 8.11.1
    5. ✅ Fixes for low/high severity security vulnerabilities. Example:
      • Bump Gradle from 8.11.0 to 8.12.0 if there is a security vulnerability in 8.11 and no 8.11.x version contains the same fix.
    6. ✅ Fixes and reverts of accidental breaking changes. Example:
      • Reverting or fix-forwarding a Kotlin migration of a file (e.g. ReactRootView.java) if it is causing a breaking change for the React Native ecosystem.
    7. ✅ Performance improvements. Examples:
      • Fixing unnecessary re-renders in FlatList.
    8. ✅ Any Pick Request if the release is still in RC0 (after RC1, the previously listed criteria apply)
    ❌ Which Pick Requests we don't accept
    1. ❌ Any Pick Request that introduces a breaking change after RC1. Example:
      • A bugfix that contains a refactoring, resulting in changes to the public API of a class
    2. ❌ Any Pick Request that introduces a new feature after RC1. Example:
      • A commit that introduces a new API or a specific feature for a component.
    3. ❌ Bump of major or minor version of dependencies. Examples:
      • Bump Gradle from 8.11.0 to 8.12.0
      • Bump Gradle from 8.11.0 to 9.0.0
    4. ❌ Bump of a dependency to a pre-release version. Example:
      • Bump Gradle from 8.11.0 to 8.11.1-beta.1
    5. ❌ Any Pick Request that introduces changes to the React Native testing infrastructure after RC1. Examples:
      • Changes to GitHub Actions workflows to optimize them, even if they are on main.
      • Changes to the logic used to publish packages to NPM or Maven Central
    6. ❌ Pick Request composed of multiple commits that have several merge conflicts.
      • If your Pick Request is too complex to apply to the release branch, it will be rejected.
    7. ❌ Any non-critical improvement that landed on main.
      • These will generally ship in the following version unless they fit one of the criteria above.
    8. ❌ Any Pick Request considered a "nice to have".
      • Even one-line changes carry a risk of destabilizing and further delaying the release.
    ℹ️ What makes for a good Pick Request

    In order for your Pick Request to be considered, please do the following:

    • ℹ️ Limit your Pick Request to one commit from main, or one PR against the release branch.
    • ℹ️ Include a clear explanation of why your Pick Request should be considered, ideally referencing one of the criteria above.
    • ℹ️ Target only one minor version of React Native (e.g. [0.76]). To have your Pick Request applied to more versions, please open separate Pick Requests.
  2. fabriziocucci commented on Sep 21, 2026

    @fabriziocucci
    CollaboratorAuthor

    Merged manually into 0.88-stable as 070af03ab3b.

    Clean revert, no conflicts. Verified on the remote: both introduced symbols are gone, and EventEmitter<ArrayBuffer> now behaves identically to 0.87 (parse accepted, GenerateModuleH succeeds, GenerateModuleObjCpp throws "Unsupported eventType"). yarn jest packages/react-native-codegen passes with 64 suites and 3122 tests.

    #57982 was assessed alongside this and deliberately left in place, see the scope section above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type Pick RequestPick requests to include commits inside a React Native release

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions