Skip to content

chore: Release v0.9.3 - #1335

Open
msluszniak wants to merge 3 commits into
release/0.9from
@ms/release-0.9.3
Open

chore: Release v0.9.3#1335
msluszniak wants to merge 3 commits into
release/0.9from
@ms/release-0.9.3

Conversation

@msluszniak

@msluszniak msluszniak commented Jul 28, 2026

Copy link
Copy Markdown
Member

Description

Patch release v0.9.3. The bundleId/system telemetry change (#1311) is already merged into release/0.9. This PR cherry-picks the following bug fixes from main (chronological order, with -x) and bumps the core package version:

Bump packages/react-native-executorch/package.json to 0.9.3. Adapter packages (bare-resource-fetcher, expo-resource-fetcher) untouched by the cherry-picks — versions not bumped.

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)

Tested on

  • iOS
  • Android

Related issues

#1310 #1325

Checklist

  • I have performed a self-review of my code
  • My changes generate no new warnings

danchily2 and others added 3 commits July 28, 2026 14:52
…1310)

## Description

`ResourceFetcher.fs.readAsString` is an async arrow inside a **static
class-field initializer** and relies on `this` binding to the class.
Because the package resolves through the `"react-native": "src/index"`
entry, Metro compiles this TypeScript source with the **consuming
app's** Babel config. Under `@react-native/babel-preset` with
`unstable_transformProfile: 'hermes-stable'` (or `'hermes-canary'`), the
async transform hoists the arrow's `this` capture to module scope:

```js
var _this = this; // module scope!
class ResourceFetcher {
  static fs = { readAsString: /* ... */ _this.getAdapter().readAsString(path) /* ... */ };
}
```

`_this.getAdapter` is `undefined`, so **every model load fails** with
`TypeError: undefined is not a function` inside `LLMController.load`,
right after the download finishes — on both iOS and Android. The
`default` transform profile compiles it correctly, which is why this
only bites apps that opt into the hermes profiles.

Fix: reference the class by name instead of `this`. One line, no
behavior change.

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [x] iOS
- [x] Android

### Testing instructions

1. In a bare RN app (RN 0.86, New Architecture) set
`unstable_transformProfile: 'hermes-stable'` on
`@react-native/babel-preset` in `babel.config.js`.
2. Load any LLM, e.g. `useLLM({ model: GEMMA4_E2B })`, on a physical
device.
3. Without this patch: load fails with `TypeError: undefined is not a
function` after the download completes. With it: the model loads and
generates.

Reproducible without a device: run `@babel/core` on
`src/utils/ResourceFetcher.ts` with the preset above and inspect the
output — the `var _this = this` hoist lands at module scope.

Verified end-to-end on a physical iPhone 16 with `GEMMA4_E2B` (MLX
backend): download → load → generation all work with this patch (applied
via `yarn patch` against 0.9.2).

### Screenshots

N/A

### Related issues

N/A

### Checklist

- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [x] My changes generate no new warnings

### Additional notes

A repo-wide sweep found no other `this` usage inside static-field
initializers, so this is the only affected site.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Cuc Dan Mihai <dan-mihai.cuc@visma.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
(cherry picked from commit a0bf85b)
## Description

Fixes an Android release crash caused by R8 removing ExecuTorch classes
that are accessed during JNI initialization.

at minified release builds without the consumer rules, the app crashes
during `ETInstaller` initialization:

```text
java.lang.ClassNotFoundException: org.pytorch.executorch.Module
at java.lang.System.loadLibrary(...)
at com.swmansion.rnexecutorch.ETInstaller.<init>(...)
```
This PR ports the upstream rules and registers them through
`consumerProguardFiles`

The first two rules ared covered with RN's own consumer rules, but are
intentionally retained to keep the upstream ExecuTorch rule block
intact. The rule that fixes the observed `Module` crash is:

```proguard
-keepclasseswithmembers class org.pytorch.executorch.** {
    native <methods>;
}
```
### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [x] Bug fix (change which fixes an issue)
- [ ] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [ ] iOS
- [x] Android

### Testing instructions

1. Enable R8/ProGuard for the release build.
2. Build the minified release APK
3. Verify that JNI-accessed classes retain their names in mapping.txt

### Screenshots

<!-- Add screenshots here, if applicable -->

### Related issues

<!-- Link related issues here using #issue-number -->

### Checklist

- [x] I have performed a self-review of my code
- [x] I have commented my code, particularly in hard-to-understand areas
- [x] I have updated the documentation accordingly
- [x] My changes generate no new warnings

### Additional notes

Android-only; iOS does not use R8. tested on a android physical
device(galaxy s20 FE)

The upstream ExecuTorch rules are copied without semantic changes.

(cherry picked from commit 189c24f)
@msluszniak msluszniak self-assigned this Jul 28, 2026
@msluszniak
msluszniak requested a review from mkopcins July 28, 2026 12:58
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.

3 participants