From 858d134717fc72d695bdfdfffd104b4c899204a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20K=C3=B6hler?= Date: Fri, 30 Oct 2026 23:40:44 +0100 Subject: [PATCH] Fix the native build on React Native 0.88 and AGP 9 iOS: React Native 0.88 removed RCTCxxBridge and its declaration in RCTBridge+Private.h, so JSIInstaller and WMDatabaseBridge no longer compiled. The installer now takes a plain RCTBridge and declares the -runtime selector itself; both the legacy RCTCxxBridge and the bridgeless RCTBridgeProxy respond to it, so JSI installs on either. Android: AGP 9 stops generating BuildConfig for library modules, but the Java sources read BuildConfig.DEBUG, so the module enables buildFeatures.buildConfig explicitly. The module has had no Kotlin sources since the Java rewrite, and applying kotlin-android collides with AGP 9's built-in Kotlin extension, so the plugin, its classpath and the stdlib dependency go. Fixes #1969, fixes #1974 (same root cause), related to #1769. Co-Authored-By: Claude Fable 5.1 --- CHANGELOG-Unreleased.md | 2 ++ native/android/build.gradle | 18 ++++++++---------- native/android/gradle.properties | 1 - native/ios/WatermelonDB/JSIInstaller.h | 4 ++-- native/ios/WatermelonDB/JSIInstaller.mm | 9 ++++++++- .../ios/WatermelonDB/objc/WMDatabaseBridge.m | 2 +- 6 files changed, 21 insertions(+), 15 deletions(-) diff --git a/CHANGELOG-Unreleased.md b/CHANGELOG-Unreleased.md index a641a6196..ee3d21943 100644 --- a/CHANGELOG-Unreleased.md +++ b/CHANGELOG-Unreleased.md @@ -20,6 +20,8 @@ - [Android] Added linker flag for building with 16kB page alignment - [TS] make catchError visible to typescript - [LokiJS] Fixed `unsafeResetDatabase()` failing with "another operation is already in progress" when it's called while an autosave is in progress +- [iOS] Fixed compilation on React Native 0.88, which removed `RCTCxxBridge`; JSI is installed through the bridge or the bridgeless proxy alike +- [Android] Generate `BuildConfig` explicitly (AGP 9 no longer does for libraries) and stop applying the unused Kotlin plugin, which collides with AGP 9's built-in Kotlin support ### Performance diff --git a/native/android/build.gradle b/native/android/build.gradle index a45cfe0b6..5f723c3f9 100644 --- a/native/android/build.gradle +++ b/native/android/build.gradle @@ -7,18 +7,11 @@ buildscript { ext.getExtOrIntegerDefault = {name -> return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativeWatermelonDB_' + name]).toInteger() } - - repositories { - mavenCentral() - } - - dependencies { - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${getExtOrDefault('kotlinVersion')}") - } } +// The module has no Kotlin sources anymore, so the Kotlin Gradle plugin is not applied: +// AGP 9 registers its own `kotlin` extension and fails when a plugin applies it again. apply plugin: 'com.android.library' -apply plugin: 'kotlin-android' android { compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') @@ -32,12 +25,17 @@ android { versionCode 1 versionName "1.0" } + + // AGP 9 stops generating BuildConfig for library modules by default; + // the Java sources read BuildConfig.DEBUG + buildFeatures { + buildConfig true + } } dependencies { //noinspection GradleDynamicVersion implementation 'com.facebook.react:react-native:+' - implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:${getExtOrDefault('kotlinVersion')}" } repositories { diff --git a/native/android/gradle.properties b/native/android/gradle.properties index 777558da3..c791b5661 100644 --- a/native/android/gradle.properties +++ b/native/android/gradle.properties @@ -1,4 +1,3 @@ -ReactNativeWatermelonDB_kotlinVersion=1.3.50 ReactNativeWatermelonDB_compileSdkVersion=31 ReactNativeWatermelonDB_buildToolsVersion=28.0.3 ReactNativeWatermelonDB_targetSdkVersion=28 diff --git a/native/ios/WatermelonDB/JSIInstaller.h b/native/ios/WatermelonDB/JSIInstaller.h index c1b7efb0f..858183e7a 100644 --- a/native/ios/WatermelonDB/JSIInstaller.h +++ b/native/ios/WatermelonDB/JSIInstaller.h @@ -1,13 +1,13 @@ #pragma once -#import +#import #ifdef __cplusplus extern "C" { #endif -void installWatermelonJSI(RCTCxxBridge *bridge); +void installWatermelonJSI(RCTBridge *bridge); void watermelondbProvideSyncJson(int id, NSData *json, NSError **errorPtr); #ifdef __cplusplus diff --git a/native/ios/WatermelonDB/JSIInstaller.mm b/native/ios/WatermelonDB/JSIInstaller.mm index d50824973..6694f77d9 100644 --- a/native/ios/WatermelonDB/JSIInstaller.mm +++ b/native/ios/WatermelonDB/JSIInstaller.mm @@ -1,7 +1,14 @@ #import "JSIInstaller.h" #import "Database.h" -extern "C" void installWatermelonJSI(RCTCxxBridge *bridge) { +// React Native 0.88 removed RCTCxxBridge (and its declaration in RCTBridge+Private.h). +// Both the legacy RCTCxxBridge and the bridgeless RCTBridgeProxy still respond to -runtime, +// so the installer takes a plain RCTBridge and declares the selector itself. +@interface RCTBridge (WatermelonJSIRuntime) +- (void *)runtime; +@end + +extern "C" void installWatermelonJSI(RCTBridge *bridge) { if (bridge.runtime == nullptr) { return; } diff --git a/native/ios/WatermelonDB/objc/WMDatabaseBridge.m b/native/ios/WatermelonDB/objc/WMDatabaseBridge.m index 8a3ab356b..1a7301e1c 100644 --- a/native/ios/WatermelonDB/objc/WMDatabaseBridge.m +++ b/native/ios/WatermelonDB/objc/WMDatabaseBridge.m @@ -196,7 +196,7 @@ + (BOOL) requiresMainQueueSetup RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(initializeJSI) { - __block RCTCxxBridge *bridge = (RCTCxxBridge *) _bridge; + __block RCTBridge *bridge = _bridge; dispatch_sync([self methodQueue], ^{ installWatermelonJSI(bridge); });