Skip to content

fix: build under React Native 0.89's RN_STRICT_API - #1

Closed
jpudysz wants to merge 767 commits into
mainfrom
fix/rn-strict-api-umbrellas
Closed

jpudysz wants to merge 767 commits into
mainfrom
fix/rn-strict-api-umbrellas

Conversation

@jpudysz

@jpudysz jpudysz commented Nov 2, 2026

Copy link
Copy Markdown
Owner

React Native 0.89 lets apps turn on its C++ stable API guards with RN_STRICT_API=1 pod install or Gradle strictCxxApiEnabled=true, which define RN_STRICT_API for every pod and Android library.

Under it, a direct include of a private header or of a header that has a <React/...> umbrella is a hard #error, and Nitro hits both, so no app using Nitro can opt in today. This branch includes those headers through the umbrellas when they exist and keeps the current includes on older React Native.

I tested following scenarios:

  • RN <0.89 (no change)
  • build with static frameworks on IOS ✅
  • compiles correctly with RN_STRICT_API and Uniwind

mrousavy and others added 30 commits April 2, 2026 18:33
…nts (margelo#1283)

* feat: Add `.as(...)` and `.is(...)` to Swift Variants

* fix: Avoid reserved names

* whoops

* fix name

* now fix

* feat: Create `is` and `as` for Kotlin variant too

* fix: Rename to `asType` and `isType`

* now
* [nit] fix grammar in view-components documentation

update possessive pronoun from `it's` to `its` in view-components.md

* two more
…ts equatable (margelo#1288)

* chore: Test struct equality (`operator==` / `Equatable`)

* feat: Implement custom `equals` / `hashCode` for structs so it works for Arrays

* fix: Fix type ref
…#1287)

Bumps the agp group with 1 update in the /packages/react-native-nitro-modules/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test-external/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/template/android directory: com.android.tools.build:gradle.


Updates `com.android.tools.build:gradle` from 9.1.0 to 9.1.1

Updates `com.android.tools.build:gradle` from 9.1.0 to 9.1.1

Updates `com.android.tools.build:gradle` from 9.1.0 to 9.1.1

Updates `com.android.tools.build:gradle` from 9.1.0 to 9.1.1

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* docs: Add JSON+LD

* Update docusaurus.config.ts
…#1295)

Bumps the agp group with 1 update in the /packages/react-native-nitro-modules/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test-external/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/template/android directory: com.android.tools.build:gradle.


Updates `com.android.tools.build:gradle` from 9.1.1 to 9.2.0

Updates `com.android.tools.build:gradle` from 9.1.1 to 9.2.0

Updates `com.android.tools.build:gradle` from 9.1.1 to 9.2.0

Updates `com.android.tools.build:gradle` from 9.1.1 to 9.2.0

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: agp
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* docs: Add Margelo "Let's talk" widget

* make it red
* chore: Bump Xcode version in CI to 26.4.0

* Update harness-ios.yml
…lo#1307)

* chore: Add test for nested arrays

* impl test

* format

* Update Podfile.lock

* fix: Input `__input` to lambda so `__element` isn't shadowed
* fix: Fix indentation for nitrogen `invoke_cxx`

* Update JFunc_void_std__vector_Powertrain_.hpp
Bumps [satori](https://github.com/vercel/satori) from 0.25.0 to 0.26.0.
- [Release notes](https://github.com/vercel/satori/releases)
- [Commits](vercel/satori@0.25.0...0.26.0)

---
updated-dependencies:
- dependency-name: satori
  dependency-version: 0.26.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…#1315)

Bumps the agp group with 1 update in the /packages/react-native-nitro-modules/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test-external/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/react-native-nitro-test/android directory: com.android.tools.build:gradle.
Bumps the agp group with 1 update in the /packages/template/android directory: com.android.tools.build:gradle.


Updates `com.android.tools.build:gradle` from 9.2.0 to 9.2.1

Updates `com.android.tools.build:gradle` from 9.2.0 to 9.2.1

Updates `com.android.tools.build:gradle` from 9.2.0 to 9.2.1

Updates `com.android.tools.build:gradle` from 9.2.0 to 9.2.1

---
updated-dependencies:
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
- dependency-name: com.android.tools.build:gradle
  dependency-version: 9.2.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: agp
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…elo#1313)

Bumps [docusaurus-plugin-llms](https://github.com/rachfop/docusaurus-plugin-llms) from 0.3.0 to 0.4.0.
- [Release notes](https://github.com/rachfop/docusaurus-plugin-llms/releases)
- [Changelog](https://github.com/rachfop/docusaurus-plugin-llms/blob/main/CHANGELOG.md)
- [Commits](rachfop/docusaurus-plugin-llms@v0.3.0...v0.4.0)

---
updated-dependencies:
- dependency-name: docusaurus-plugin-llms
  dependency-version: 0.4.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…argelo#1322)

Bumps [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) from 24.7.2 to 25.7.0.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/node)

---
updated-dependencies:
- dependency-name: "@types/node"
  dependency-version: 25.7.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…gelo#1318)

Bumps [ts-morph](https://github.com/dsherret/ts-morph) from 27.0.2 to 28.0.0.
- [Release notes](https://github.com/dsherret/ts-morph/releases)
- [Commits](dsherret/ts-morph@27.0.2...28.0.0)

---
updated-dependencies:
- dependency-name: ts-morph
  dependency-version: 28.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…in release (margelo#1320)

* test: repro Optional<Struct> garbage tag read on Swift Cxx-interop

Adds three runtime tests on TestObject that bracket an Optional<Struct>
round-trip bug on the Swift side of nitro's Cxx-interop bridge:

  tryOptionalStruct       Reuses the existing OptionalWrapper. An
                          Optional<{ optionalArrayBuffer?, optionalString? }>
                          round-trips cleanly. Establishes the lower bound.

  tryOptionalNestedStruct Adds OptionalNestedWrapper:
                            { count?, enabled?,
                              inner?: { start?: Side, end?: Side } }
                          where Side = 'left' | 'right'. An Optional<Struct>
                          with one 2-variant string-union enum reused
                          twice in the nested inner struct still
                          round-trips cleanly. Proves the bug is not
                          "any nested optional struct".

  tryOptionalEnumStruct   Adds OptionalEnumWrapper:
                            14 primitive optionals
                            + tier?: 'free' | 'pro' | 'enterprise'
                            + region?: 'us' | 'eu' | 'apac' | 'global'
                            + inner?: {
                                stage?: 'idle' | 'warmup' | 'active' | 'cool',
                                tone?: 'cool' | 'warm' | 'neutral'
                              }

                          Surface conditions:

                            iOS Debug    : passes
                            iOS Release  : fails with
                              "Cannot convert <Tier|Region|Stage|Tone>
                               to JS - invalid value: <garbage 4-byte int>"
                            Android      : passes on both TestObjectCpp
                                           and TestObjectSwiftKotlin
                                           (no Swift Cxx-interop in play)

                          The garbage value differs per call (observed
                          83886081 and 2003789939 in separate runs).
                          The Debug-passes / Release-fails split, paired
                          with non-deterministic garbage, points at
                          uninitialized padding bytes or an
                          optimizer-revealed layout mismatch in Swift's
                          Optional<Struct> projection across the
                          Cxx-interop bridge — not a stable
                          wrong-pointer or logic bug.

Together the three tests bracket the bug: small + few enums = works;
wide + multiple distinct string-union enum types under optimization =
corrupted enum tag.

Repro-only — no fix.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* test: tighten comment hygiene on Optional<Struct> repro fixtures

Reframe the comments above the new optional-struct fixtures to describe
shape rather than motivation. The bug context (runtime error string,
"verified empirically", which call site fails) belongs in the prior
commit message and PR description, where it does not rot as the test
suite evolves.

No behavioral change.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* test: slim Optional<Struct> repro per CONTRIBUTING.md

Drop tryOptionalStruct + tryOptionalNestedStruct and their fixtures —
only tryOptionalEnumStruct exhibits the garbage tag read on Swift
Cxx-interop under -O. Inline OptionalEnumInner into the wrapper and
reuse Powertrain for the four enum fields instead of introducing
Stage/Tier/Region/Tone/Side. Net: 1 new struct, 1 new method, 0 new
enums.

Reproduces on device (Release, iOS) as a "tryOptionalEnumStruct(...) equals"
failure where number fields read 5e-324 / subnormal denorms — classic
uninitialized-memory tag read symptomatic of swiftBug84848.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
mrousavy and others added 27 commits October 18, 2026 01:09
…o#1736)

Bumps the react group with 2 updates in the / directory: [react](https://github.com/react/react/tree/HEAD/packages/react) and [react-dom](https://github.com/react/react/tree/HEAD/packages/react-dom).


Updates `react` from 19.2.3 to 19.3.0
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.3.0/packages/react)

Updates `react-dom` from 19.2.3 to 19.3.0
- [Release notes](https://github.com/react/react/releases)
- [Changelog](https://github.com/react/react/blob/main/CHANGELOG.md)
- [Commits](https://github.com/react/react/commits/v19.3.0/packages/react-dom)

---
updated-dependencies:
- dependency-name: react
  dependency-version: 19.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: react
- dependency-name: react-dom
  dependency-version: 19.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: react
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc Rousavy <[email protected]>
Bumps [com.facebook.fbjni:fbjni](https://github.com/facebookincubator/fbjni) from 0.7.0 to 0.8.1.
- [Release notes](https://github.com/facebookincubator/fbjni/releases)
- [Commits](facebookincubator/fbjni@v0.7.0...v0.8.1)

---
updated-dependencies:
- dependency-name: com.facebook.fbjni:fbjni
  dependency-version: 0.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc Rousavy <[email protected]>
…#1728)

Bumps [org.jetbrains.kotlinx:kotlinx-coroutines-android](https://github.com/Kotlin/kotlinx.coroutines) from 1.8.1 to 1.11.0.
- [Release notes](https://github.com/Kotlin/kotlinx.coroutines/releases)
- [Changelog](https://github.com/Kotlin/kotlinx.coroutines/blob/master/CHANGES.md)
- [Commits](Kotlin/kotlinx.coroutines@1.8.1...1.11.0)

---
updated-dependencies:
- dependency-name: org.jetbrains.kotlinx:kotlinx-coroutines-android
  dependency-version: 1.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc Rousavy <[email protected]>
Bumps [jest](https://github.com/jestjs/jest/tree/HEAD/packages/jest) and [@types/jest](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jest). These dependencies needed to be updated together.

Updates `jest` from 29.7.0 to 30.5.2
- [Release notes](https://github.com/jestjs/jest/releases)
- [Changelog](https://github.com/jestjs/jest/blob/main/CHANGELOG.md)
- [Commits](https://github.com/jestjs/jest/commits/v30.5.2/packages/jest)

Updates `@types/jest` from 29.5.14 to 30.0.0
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jest)

---
updated-dependencies:
- dependency-name: jest
  dependency-version: 30.5.2
  dependency-type: direct:development
  update-type: version-update:semver-major
- dependency-name: "@types/jest"
  dependency-version: 30.0.0
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Marc Rousavy <[email protected]>
* fix: avoid Swift task starvation in runtime tests (margelo#1723)

* test: move portable Harness coverage to the standalone runner (margelo#1733)

* fix: link Nitrogen CLI before standalone tests

* Wait for iOS simulator boot before running tests
* Move React Native adapters out of Nitro Core

* Generate recycling helpers only for Hybrid Views

* Format relocated Kotlin architecture specs

* Remove legacy staged Core cleanup
* Upgrade React Native to 0.88.0

* Keep docs React aligned with the workspace

* Correct NativeComponentRegistry compatibility versions

* Fix SegmentedControl declarations for React Native 0.88

* Refresh NitroModules pod checksums after adapter split

* Update packages/react-native-nitro-modules/src/views/getHostComponent.ts
Match the API entry order produced by the locked React Native Pods so release validation leaves both app manifests unchanged. Preserve captured command output in errors so failed Git checks show the unexpected changes.
…xception` to prevent missing libc++ symbols on iOS <18 (margelo#1824)

* fix: avoid iOS 18-only libc++ symbol in Swift-visible exception helpers

When `RuntimeError.hpp` is compiled through Swift's C++ interop,
`std::make_exception_ptr` resolves to libc++'s iOS 18+ implementation
(`__cxa_init_primary_exception` + `std::exception_ptr::__from_native_exception_pointer`)
even with a lower deployment target. Apps then fail to launch on iOS < 18:

  Termination: DYLD, Symbol missing
  Symbol not found: __ZNSt13exception_ptr31__from_native_exception_pointerEPv
  Expected in: /usr/lib/libc++.1.dylib

Build the exception_ptr via throw/catch + `std::current_exception()` instead,
which is what libc++ itself falls back to below iOS 18. Apply the same to the
inline `~Promise()` timeout rejection, which Swift-compiled code can instantiate.

Verified with Xcode 27.1 (iPhoneOS 27.1 SDK), deployment target 15.1:
`nm -u libNitroModules.a` no longer references `__from_native_exception_pointer`.

* Update packages/nitro-core/native/apple/utils/RuntimeError.hpp

* Update packages/nitro-core/native/cpp/core/Promise.hpp

---------

Co-authored-by: Marc Rousavy <[email protected]>
@coderabbitai

coderabbitai Bot commented Nov 2, 2026

Copy link
Copy Markdown

Walkthrough

Warning

Review details and warnings were omitted to fit the comment limit.

@jpudysz

jpudysz commented Nov 2, 2026

Copy link
Copy Markdown
Owner Author

Opened against the wrong base (fork main). Superseded by margelo#2025.

@jpudysz jpudysz closed this Nov 2, 2026
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.