Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: lean core JSC #836

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions proposals/0836-lean-core-jsc.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
title: Extract JSC (JavaScriptCore) from React Native Core
author:
- Kudo Chien <[email protected]>
date: 2024-11-28
---

# RFC0836: Extract JSC (JavaScriptCore) from React Native Core

## Summary

This RFC proposes a Lean Core effort to extract JSC (JavaScriptCore) from React Native's core.

## Proposed Changes and Timeline

- Version 0.78: Remove the [`jsc-android` npm dependency](https://github.com/facebook/react-native/blob/2d337efc23c662143b3f39a6c994d80fec047054/packages/react-native/package.json#L132) from React Native and instead download the artifact from Maven Central. When using Hermes, downloading the unused npm dependency is unnecessary and removing it saves about 32 MB of uncompressed build time size.
- Version 0.80: Introduce a new `react-native-javascriptcore` npm package with a newer version of JavaScriptCore for Android. In this version, we will only provide the [Intl variant](https://github.com/react-native-community/jsc-android-buildscripts/blob/9c61fece4753902a2cd6d29dfa46b7b521f0c821/README.md#international-variant), as newer JavaScriptCore versions do not support disabling Intl. The existing JSCRuntime from the core should still function with this version but will display a deprecation warning during build time. A challenge will be managing the core JSCRuntime alongside the third-party JSCRuntime from `react-native-javascriptcore`; details will be mentioned in the [Mixing `JSCRuntime` from core and third-party](#mixing-jscruntime-from-core-and-third-party) section.
- Could we support `react-native-javascriptcore` only on New Architecture mode?
- Version 0.82: Completely remove JavaScriptCore from the core:
- Eliminate `JSCRuntime` code and drop `useThirdPartyJSC` support.
- Update documentation at https://reactnative.dev/docs/hermes.
- At this point, React Native will stop JSCRuntime testing from core. All the integration testing effort should move into the `react-native-javascriptcore` repository.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a paragraph mentioning that we'll stop testing JSC in the release testing matrix (you can link this page: https://github.com/reactwg/react-native-releases/blob/main/docs/guide-release-testing.md)

## Motivation

Since Hermes has become the dominant JavaScript engine in the React Native ecosystem, it is inefficient to include unused JavaScriptCore code and binaries in the core. By extracting JavaScriptCore to a separate, third-party maintained library, we can streamline the core and reduce unnecessary bloat.

## Adoption strategy
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: How will this work? Is it going to work through Community CLI autolinking? If so, we'll have to extend it so that when react-native-javascriptcore is added, the hermes dependency is excluded.

Could you add a paragraph about it?


We will offer a drop-in replacement with the `react-native-javascriptcore` npm package while maintaining JSC support in the core for two additional React Native releases to ensure a smooth transition.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the boundary is jsi::Runtime, then I think that means there could be frequent updates needed against RN package.

The current structure has a nice benefit of keeping it up to date automatically, since it must build in line with JSI changes. But I think it means the project would need a long term maintainer to continue working. See microsoft/v8-jsi@4438466

Depending on whether there is a natural maintainer, the other option would look like a harder deprecation, which would still allow externally maintained runtimes to develop.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is also the same problem for https://github.com/Kudo/react-native-v8. i can try to maintain the in my spare time (also love to have other maintainers from community)

maybe we need to include nightly testing from v8 and react-native-javascriptcore, so that we can catch jsi interface breaking changes and take action earlier.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd be happy to help with maintenance of that RN <-> JSC integration at Callstack

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

awesome! love the collaboration with someone from Callstack then.


### Mixing `JSCRuntime` from core and third-party

Originally, the `hermesEnabled` in Android's **gradle.properties** and `hermes_enabled` in iOS's **Podfile** take two responsibilities. One is to create the Hermes bytecode bundle. The other is to choose JSCRuntime over HermesRuntime. During the transition period, we will introduce a `useThirdPartyJSC` flag for **gradle.properties** and `ENV['useThirdPartyJSC']` for CocoaPods. When `useThirdPartyJSC` is enabled, React Native will not link the `JSCRuntime` from core.

### Setup guide for `react-native-javascriptcore`

A rough idea to set up `react-native-javascriptcore`:

1. `yarn add react-native-javascriptcore`
2. Set `hermesEnabled=false`
3. Add `useThirdPartyJSC=true` on React Native 0.80~0.82
4. On Android, update MainApplication to support custom JSRuntimeFactory for JSC
5. TODO: On iOS, there are some challenges since `createJSRuntimeFactory()` requires C++ integration and we now have AppDelegate.swift. We could try to abstract the `createJSRuntimeFactory()` to an Objective-C interface first, so that people can pass their own JSRuntimeFactory through Swift. I will study some approaches and update this part later.

## How we teach this

We will announce the upcoming changes in the version 0.80 release notes and provide guidance for developers on migrating to the new `react-native-javascriptcore` package. After version 0.82, the core will no longer support JSCRuntime and no more integration testing will be done in the core. All the integration testing effort should move into the `react-native-javascriptcore` repository.