Skip to content

Commit

Permalink
feat: add react-native 0.74 support (#202)
Browse files Browse the repository at this point in the history
# Why

add react native 0.74 and expo sdk 51 support

# How

- [v8runtime] add stub `setExternalMemoryPressure()`
- [android] fix build error on 0.74
- [ios] update config-plugin to support 0.74 from RCTRootViewFactory
- [ci] update test for react-native 0.74 and expo sdk 51
  • Loading branch information
Kudo authored Jun 30, 2024
1 parent ca4e3fc commit 38bd186
Show file tree
Hide file tree
Showing 12 changed files with 289 additions and 25 deletions.
25 changes: 25 additions & 0 deletions .github/actions/cleanup-linux-disk-space/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#
# Copyright (c) 650 Industries.
#

name: 'Cleanup GitHub Linux Runner Disk Space'
description: 'Cleanup unused preinstalled packages on the GitHub Ubuntu runners'

runs:
using: 'composite'
steps:
- name: '🧹 Cleanup preinstalled packages'
shell: bash
run: |
echo 'Disk space before cleanup'
df -aH
sudo apt-get remove -y --purge '^mysql-.*' '^mongodb-.*' '^mssql-.*' '^postgresql-.*' '^aspnetcore-*' '^dotnet-.*' '^php.*-.*' 'mono-complete' '^llvm-.*' 'powershell' 'google-chrome-*' 'microsoft-edge-*' 'firefox' 'nginx' 'apache2'
sudo apt-get autoremove -y
sudo rm -rf /usr/share/dotnet
echo 'Showing Android SDKs'
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --list
${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --uninstall 'ndk;24.0.8215888' 'ndk;25.2.9519653' 'ndk;26.2.11394342'
echo 'Removing all Docker images'
docker rmi -f $(docker images -aq)
echo 'Disk space after cleanup'
df -aH
15 changes: 9 additions & 6 deletions .github/workflows/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
rn-version: ['0.73']
rn-version: ['0.74', '0.73']
v8-android-variant:
[v8-android-jit, v8-android-jit-nointl, v8-android, v8-android-nointl]
# include:
Expand All @@ -32,17 +32,20 @@ jobs:
# v8-android-variant: v8-android-jit

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1

- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space

- name: Use JDK 17
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Restore yarn caches
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-workspace-modules-${{ hashFiles('yarn.lock') }}
Expand All @@ -60,7 +63,7 @@ jobs:
- name: Run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 33
api-level: 34
arch: x86_64
target: google_apis
script: |
Expand All @@ -72,7 +75,7 @@ jobs:
- name: Upload failed artifacts
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: artifacts-${{ matrix.rn-version }}-${{ matrix.v8-android-variant }}
path: |
Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/expo-android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,20 @@ jobs:
e2e-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1

- name: 🧹 Cleanup GitHub Linux runner disk space
uses: ./.github/actions/cleanup-linux-disk-space

- name: Use JDK 17
uses: actions/setup-java@v2
uses: actions/setup-java@v4
with:
distribution: 'temurin'
java-version: '17'

- name: Restore yarn caches
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-workspace-modules-${{ hashFiles('yarn.lock') }}
Expand All @@ -41,7 +44,7 @@ jobs:

- name: Generate TestApp
run: |
yarn create expo-app -t blank@@sdk-50 TestApp
yarn create expo-app -t blank@@sdk-51 TestApp
cd TestApp
yarn add v8-android-jit
yarn add file:../react-native-v8
Expand All @@ -66,7 +69,7 @@ jobs:
- name: Run tests
uses: reactivecircus/android-emulator-runner@v2
with:
api-level: 33
api-level: 34
arch: x86_64
target: google_apis
working-directory: ../TestApp/android
Expand All @@ -85,7 +88,7 @@ jobs:
- name: Upload failed artifacts
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: artifacts
path: |
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/expo-ios.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ jobs:
runs-on: macos-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v1

- name: 🔨 Switch to Xcode 14.3.1
run: sudo xcode-select --switch /Applications/Xcode_14.3.1.app
- name: 🔨 Switch to Xcode 15.4
run: sudo xcode-select --switch /Applications/Xcode_15.4.app

- name: Restore yarn caches
uses: actions/cache@v2
uses: actions/cache@v4
with:
path: node_modules
key: ${{ runner.os }}-workspace-modules-${{ hashFiles('yarn.lock') }}
Expand All @@ -39,7 +39,7 @@ jobs:

- name: Generate TestApp
run: |
yarn create expo-app -t blank@@sdk-50 TestApp
yarn create expo-app -t blank@@sdk-51 TestApp
cd TestApp
yarn add v8-ios
yarn add file:../react-native-v8
Expand All @@ -57,7 +57,7 @@ jobs:
- name: Run TestApp
working-directory: ../TestApp/ios
run: |
SIMUDID=$(xcrun simctl list devices available -j | jq -r '.devices."com.apple.CoreSimulator.SimRuntime.iOS-16-4"[] | select(.name=="iPhone 14 Pro") | .udid')
SIMUDID=$(xcrun simctl list devices available -j | jq -r '.devices."com.apple.CoreSimulator.SimRuntime.iOS-17-5"[] | select(.name=="iPhone 15 Pro") | .udid')
echo "Using simulator udid[${SIMUDID}]"
xcrun simctl boot ${SIMUDID}
xcrun simctl install booted ./build/Build/Products/Release-iphonesimulator/TestApp.app
Expand All @@ -75,7 +75,7 @@ jobs:
- name: Upload failed artifacts
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: artifacts
path: |
Expand Down
2 changes: 2 additions & 0 deletions android/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,10 @@ add_library(
target_include_directories(
reactnative_internal_static
PRIVATE
"${REACT_NATIVE_DIR}/ReactCommon"
"${REACT_NATIVE_DIR}/ReactCommon/jsiexecutor"
"${REACT_NATIVE_DIR}/ReactCommon/reactperflogger"
"${REACT_NATIVE_DIR}/ReactCommon/runtimeexecutor"
)

target_link_libraries(
Expand Down
4 changes: 4 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
"src/"
],
"devDependencies": {
"@types/semver": "^7.5.8",
"clang-format": "^1.8.0",
"expo": "^48.0.0",
"expo-module-scripts": "^3.0.7"
Expand All @@ -51,5 +52,8 @@
"expo": {
"optional": true
}
},
"dependencies": {
"semver": "^7.6.2"
}
}
1 change: 1 addition & 0 deletions plugin/build/withV8ExpoAdapter.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export declare function updateAndroidAppGradle(contents: string): string;
* Updates **AppDelegate.mm**
*/
export declare function updateIosAppDelegate(contents: string): string;
export declare function updateIosAppDelegate50(contents: string): string;
108 changes: 105 additions & 3 deletions plugin/build/withV8ExpoAdapter.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.updateIosAppDelegate = exports.updateAndroidAppGradle = void 0;
exports.updateIosAppDelegate50 = exports.updateIosAppDelegate = exports.updateAndroidAppGradle = void 0;
const semver_1 = __importDefault(require("semver"));
const config_plugins_1 = require("expo/config-plugins");
const generateCode_1 = require("./generateCode");
const withV8ExpoAdapter = (config, opts) => {
Expand Down Expand Up @@ -43,7 +47,12 @@ const withIosAppDelegate = (config) => {
throw new Error('Must setup `expo.jsEngine` as `jsc` in app.json.');
}
if (config.modResults.language === 'objcpp') {
config.modResults.contents = updateIosAppDelegate(config.modResults.contents);
if (config.sdkVersion && semver_1.default.lt(config.sdkVersion, '51.0.0')) {
config.modResults.contents = updateIosAppDelegate50(config.modResults.contents);
}
else {
config.modResults.contents = updateIosAppDelegate(config.modResults.contents);
}
}
else {
throw new Error('Cannot update AppDelegate file for react-native-v8 because the file is not objcpp');
Expand Down Expand Up @@ -119,6 +128,99 @@ function updateIosAppDelegate(contents) {
#define FOLLY_CFG_NO_COROUTINES 1
#endif
#import <memory>
#import <objc/runtime.h>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTJSIExecutorRuntimeInstaller.h>
#import <React/RCTSurfacePresenterBridgeAdapter.h>
#import <react/renderer/runtimescheduler/RuntimeScheduler.h>
#import <react/renderer/runtimescheduler/RuntimeSchedulerBinding.h>
#import <RNV8/V8ExecutorFactory.h>
`;
let mergeResults;
mergeResults = (0, generateCode_1.mergeContents)({
tag: `${mergeTagPrefix}:imports`,
src: contents,
newSrc: imports,
anchor: /^#import "AppDelegate\.h"/m,
offset: 1,
comment: '//',
});
didMerge || (didMerge = mergeResults.didMerge);
didClear || mergeResults.didClear;
const swizzleJsExecutorFactory = `\
method_exchangeImplementations(
class_getInstanceMethod(RCTRootViewFactory.class, @selector(jsExecutorFactoryForBridge:)),
class_getInstanceMethod(self.class, @selector(jsExecutorFactoryForBridge:)));
`;
mergeResults = (0, generateCode_1.mergeContents)({
tag: `${mergeTagPrefix}:swizzleJsExecutorFactory`,
src: mergeResults.contents,
newSrc: swizzleJsExecutorFactory,
anchor: /^\s*return \[super application:application didFinishLaunchingWithOptions:launchOptions]/m,
offset: 0,
comment: '//',
});
didMerge || (didMerge = mergeResults.didMerge);
didClear || mergeResults.didClear;
const jsExecutorFactoryForBridge = `
- (std::unique_ptr<facebook::react::JSExecutorFactory>)jsExecutorFactoryForBridge:(RCTBridge *)bridge
{
RCTAssert(!RCTIsNewArchEnabled(), @"react-native-v8 does not support new architecture yet.");
auto runtimeScheduler = std::make_shared<facebook::react::RuntimeScheduler>(RCTRuntimeExecutorFromBridge(bridge));
return std::make_unique<rnv8::V8ExecutorFactory>(
facebook::react::RCTJSIExecutorRuntimeInstaller([bridge, runtimeScheduler = std::move(runtimeScheduler)](facebook::jsi::Runtime &runtime) {
if (!bridge) {
return;
}
if (runtimeScheduler) {
facebook::react::RuntimeSchedulerBinding::createAndInstallIfNeeded(runtime, runtimeScheduler);
}
}));
}
`;
mergeResults = (0, generateCode_1.mergeContents)({
tag: `${mergeTagPrefix}:jsExecutorFactoryForBridge`,
src: mergeResults.contents,
newSrc: jsExecutorFactoryForBridge,
anchor: /^@end$/gm,
findLastAnchor: true,
offset: 0,
comment: '//',
});
didMerge || (didMerge = mergeResults.didMerge);
didClear || mergeResults.didClear;
if (didMerge || didClear) {
return mergeResults.contents;
}
return contents;
}
exports.updateIosAppDelegate = updateIosAppDelegate;
function updateIosAppDelegate50(contents) {
const mergeTagPrefix = 'react-native-v8';
let didMerge = false;
let didClear = false;
const imports = `\
#ifndef FOLLY_NO_CONFIG
#define FOLLY_NO_CONFIG 1
#endif
#ifndef FOLLY_MOBILE
#define FOLLY_MOBILE 1
#endif
#ifndef FOLLY_USE_LIBCPP
#define FOLLY_USE_LIBCPP 1
#endif
#ifndef FOLLY_HAVE_PTHREAD
#define FOLLY_HAVE_PTHREAD 1
#endif
#ifndef FOLLY_CFG_NO_COROUTINES
#define FOLLY_CFG_NO_COROUTINES 1
#endif
#import <memory>
#import <React/RCTCxxBridgeDelegate.h>
#import <React/RCTJSIExecutorRuntimeInstaller.h>
Expand Down Expand Up @@ -209,4 +311,4 @@ function updateIosAppDelegate(contents) {
}
return contents;
}
exports.updateIosAppDelegate = updateIosAppDelegate;
exports.updateIosAppDelegate50 = updateIosAppDelegate50;
Loading

0 comments on commit 38bd186

Please sign in to comment.