Conversation
# Why Expo modules already require iOS 16.4, but SPM configurations declare iOS 16. It makes easy to miss the code that pass compile tests but fails during precompilation. Related discussion: https://github.com/expo/expo/pull/44876/changes#r3101755826 # How - Added support for `iOS("16.4")` to the SPM configuration type and schema. - Updated all configs to `16.4`. - Refactored product-platform mapping to use platform prefixes instead of enumerating individual versions. - Removed `iOS(.v15_1)` and `tvOS(.v15_1)` as it's invalid value and wouldn't work anyway. # Test Plan `et prebuild-packages` and tests succeeds.
# Why
Adds TypeScript ESLint configuration file support (`eslint.config.ts`,
`.mts`, `.cts`), following native TypeScript configuration support in
ESLint v9.18.0 (January 2025), fixing "No ESLint config found" output
from `npx expo lint` with `eslint.config.ts`.
# How
Extended configuration file resolution to check for `.ts`, `.mts`, and
`.cts` extensions.
# Test Plan
```
npx create-expo-app@latest test --yes && cd test
npx expo lint # Creates eslint.config.js
mv eslint.config.{js,ts}
npx expo lint # Runs ESLint
```
# Checklist
- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
---------
Co-authored-by: Phil Pluckthun <phil@kitten.sh>
…les [step 0] (#49150) # Why The task ENG-25370 describes how to move all iOS precompiled metadata generation from the ruby/cocoapods pipeline and into `expo-modules-autolinking`. The plan is to setup CI tests that verifies that the generated data from the ruby pipeline is consistent with the data we generate in the auto-linking code in `expo-modules-autolinking`. When this is verified (over time), we can move the whole ruby code over to use the output from `expo-modules-autolinking` instead of reading its own data - and then finally remove the data generation within the Ruby code. This PR is the first step in this process - adding support for generating a metadata file with data from the ruby pipeline. This is for now checked against a fixture and will fail loud if there are deviations - making sure we catch any issues with ongoing changes before moving on to step 1 in the linear task. # How - Added ruby methods for generating the metadata json file - Committed fixture with metadata - Added e2e test to catch any changes that would cause the fixture to need to be updated. # Test Plan - Guard test green: `pnpm exec jest e2e/__tests__/precompiled-derivations-test.ts` passes (334 ms). - Guard test red: adding a fake `externalDependencies` entry to `packages/expo-image/spm.config.json` without regenerating fails the test with the regen command and a structured diff naming the `ExpoImage` pod. - Determinism: two consecutive runner invocations produce byte-identical output. - `ruby -c` passes on both Ruby files. The `EXPO_PRECOMPILED_DUMP` hook is a one-line call to the same method exercised by the runner; not verified via a full `pod install`. # Checklist - [x] Documentation is up to date to reflect these changes. - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) - [x] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
# Why
`npx expo lint` installs ESLint when it is missing and then immediately
loads it within the same process. `await import()` cannot resolve a
module installed mid-process, causing "Cannot find module 'eslint'" on
the first run.
# How
Replace `await import('eslint')` with `require('eslint')`, which can
resolve a module installed mid-process.
Edit by `@kitten`: Replace resolution and loading with
`@expo/require-utils`
# Test Plan
1. Create a new Expo project.
2. Run `npx expo lint` for the first time, without adding ESLint or a
configuration file beforehand.
3. Verify that lint ran successfully on the first run of `npx expo
lint`.
# Checklist
- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
---------
Co-authored-by: Phil Pluckthun <phil@kitten.sh>
# Summary Related to #48670 Upgrades to `metro@0.84.5` via `@expo/metro@~56.0.2` **Note:** - `56.0.2` isn't yet marked `latest`, but should be once we're about to publish or shortly after or before merging. - `sdk-55` and `sdk-54` need separate releases for different metro versions and PRs. We may only update 55 and backport it to 54 - `56.0.1` was "burned" and replaced with `56.0.2` to update `metro-transform-worker` which missed the `0.84.5` bump before (lockfile flagged this) # Test Plan - CI is expected to pass # Checklist <!-- Please check the appropriate items below if they apply to your diff. --> - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
…le (#49196) # Why On web, `Crypto.AES` reads the wrong bytes whenever a caller passes a `Uint8Array` that is a window onto a larger buffer. Two places reach past a view to its backing buffer and drop `byteOffset` / `byteLength`: ```ts // SealedData.fromCombined const buffer = binaryInputBytes(combined).buffer as ArrayBuffer; // binaryInputBytes if (ArrayBuffer.isView(input)) { return new Uint8Array(input.buffer); } ``` `BinaryInput` is `string | Uint8Array | ArrayBuffer`, and a `Uint8Array` is very often a window onto something bigger — `subarray()` of a read buffer, a slice of a pooled allocation, a record framed inside a larger payload. Reading `.buffer` off one of those yields the whole allocation, not the 48 bytes the caller meant. The result is a `SealedData` describing the wrong region entirely. With a 42-byte sealed blob sitting at offset 100 of a 512-byte buffer: ``` combinedSize=512 (expected 42) decrypt FAILED -> DOMException: The operation failed for an operation-specific reason ``` `combinedSize` reports the backing length, so `iv()` reads offset 0 of the backing buffer instead of the blob's IV, and `tag()` — which is positioned as `combinedSize - tagSize` — lands at the end of the backing buffer. Decryption fails with `OperationError`. This is silent and input-dependent: the same sealed bytes work when they happen to own their buffer and fail when they are a view, which makes it look like data corruption rather than a library bug. # How Keep the view rather than its buffer. `SealedData` now holds the `Uint8Array` and slices it with `subarray`, so every offset is relative to the sealed data instead of to whatever allocation happens to be underneath. `binaryInputBytes` passes `byteOffset` and `byteLength` through when it wraps a view. Storing the view rather than normalizing with a copy in `fromCombined` keeps the existing zero-copy behaviour and fixes the getters as a class, instead of patching the one call site that happened to reach `.buffer`. Data built by `fromParts` and `encryptAsync` is unaffected — both allocate exact-size arrays, where the view and its buffer coincide — so the only behaviour that changes is the cases that were reading the wrong bytes. `subarray` clamps where `new Uint8Array(buffer, offset, length)` threw, so on its own this change would have made truncated input fail later and less clearly — `decryptAsync` would report a generic AES-GCM `OperationError`, and `tag()` would hand back a short slice instead of raising. `fromCombined` therefore now rejects data that cannot hold its own IV and tag. That check is not new behaviour for the API, it is the behaviour the other platforms already have. Android throws `InvalidSealedDataConfigException` from [`SealedData`'s `init`](https://github.com/expo/expo/blob/main/packages/expo-crypto/android/src/main/java/expo/modules/crypto/aes/objects/SealedData.kt), and iOS throws out of `AES.GCM.SealedBox(combined:)`. Web was the only platform that accepted a too-short blob, and it failed later with a raw `RangeError: Invalid typed array length: -18`. It now fails at the same point as the other two, with the code Android uses: ``` CodedError [ERR_INVALID_SEALED_DATA_CONFIG]: Sealed data is 10 bytes, which is too short to hold a 12-byte IV and a 16-byte authentication tag. Pass the whole combined output of encryptAsync, or set ivLength and tagLength in the config to match how the data was sealed. ``` The `ArrayBuffer.isView` branch is only reachable for views outside the declared `BinaryInput` union (`DataView`, `Int8Array`, …), since `Uint8Array` returns earlier. It is fixed for the same reason: the branch exists precisely to accept those, and it was mishandling every one of them. # Test Plan Added `src/aes/__tests__/`, which had no coverage before. Every test below fails on `main` and passes with this change. `web-utils-test.web.ts` covers `binaryInputBytes` (6 tests), `SealedData-test.web.ts` covers `fromCombined` (4 tests). Before — 5 distinct assertions fail, reported as 10 because each `.web.ts` file is picked up by both the Node and the Web jest project: ``` ● binaryInputBytes › keeps the region of a DataView Expected: 3 Received: 64 ● binaryInputBytes › keeps the region of a non-Uint8Array typed view Expected: 3 Received: 64 ● SealedData.fromCombined › reads a Uint8Array that views part of a larger buffer Expected: 48 Received: 200 ● SealedData.fromCombined › rejects data too short to hold an IV and a tag ● SealedData.fromCombined › rejects data too short for a custom config Test Suites: 4 failed, 4 total Tests: 10 failed, 10 passed, 20 total ``` After, with the pre-existing 28 tests still green: ``` Test Suites: 10 passed, 10 total Tests: 48 passed, 48 total ``` The unit tests stop at the `SealedData` boundary because `crypto.subtle` is present in the Node jest project but not in the jsdom one, so a round trip cannot run in both. To confirm the user-visible effect I ran one directly against Node's WebCrypto, encrypting, framing the sealed bytes at offset 100 of a 512-byte buffer, and decrypting through `fromCombined(view)`: ``` ──────── BEFORE the fix ──────── MODE=old combinedSize=512 (expected 42) decrypt FAILED -> DOMException: The operation failed for an operation-specific reason ──────── AFTER the fix ──────── MODE=fixed combinedSize=42 (expected 42) decrypt OK -> "attack at dawn" ``` `et check-packages expo-crypto`: ``` Tasks: 2 successful, 2 total 🏁 All checks passed. ``` `tsc -p tsconfig.json --noEmit` exits 0. # Checklist - [x] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why `NavigationIndependentTree` was never recommended solution in expo-router - https://docs.expo.dev/router/migrate/from-react-navigation/#independent For a very rare cases when someone needs a mini-app or different navigation within our system, they can just use `@react-navigation/native` and construct the whole nested navigation themselves. # How Remove `NavigationIndependentTree` # Test Plan CI # Checklist <!-- Please check the appropriate items below if they apply to your diff. --> - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --------- Co-authored-by: expo-tuft[bot] <288127324+expo-tuft[bot]@users.noreply.github.com> Co-authored-by: Expo Bot <34669131+expo-bot@users.noreply.github.com>
# Why <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> Fix ENG-25941 # How <!-- How did you build this feature or fix this bug and why? --> Fix four incomplete SDK examples. # Test Plan <!-- Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction. --> Proofread. # Checklist <!-- Please check the appropriate items below if they apply to your diff. --> - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [x] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
…49183) # Why <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> Fix ENG-26079 # How <!-- How did you build this feature or fix this bug and why? --> - Add example screenshots to Expo UI universal component pages - Add available components screenshots in the Universal and Expo UI overview pages in card form # Test Plan <!-- Please describe how you tested this change and how a reviewer could reproduce your test, especially if this PR does not include automated tests! If possible, please also provide terminal output and/or screenshots demonstrating your test/reproduction. --> See preview: https://pr-49183.expo-docs.pages.dev/versions/unversioned/sdk/ui/#universal & https://pr-49183.expo-docs.pages.dev/versions/unversioned/sdk/ui/universal/ <img width="2370" height="2060" alt="CleanShot 2026-08-21 at 00 47 17@2x" src="https://github.com/user-attachments/assets/9cadbcf7-3a2f-46b8-91c2-72fad5a1f46e" /> <img width="2446" height="2046" alt="CleanShot 2026-08-21 at 00 47 13@2x" src="https://github.com/user-attachments/assets/d1b46d7b-20c7-4581-b340-f50d2005aab6" /> # Checklist <!-- Please check the appropriate items below if they apply to your diff. --> - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --------- Co-authored-by: Kadi Kraman <hellokadi@gmail.com>
# Why Since Vaul is a heavy library and not-maintained anymore, we want to remove it and the whole web modal stack from expo-router. # How 1. Remove web modal stack 2. Export `NativeStackView`, so that people can create their own modal stacks 3. Add guide for how to create custom modal stack - docs/pages/router/advanced/web-modals.mdx # Test Plan CI # Checklist <!-- Please check the appropriate items below if they apply to your diff. --> - [ ] I added a `changelog.md` entry and rebuilt the package sources according to [this short guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting) - [ ] This diff will work correctly for `npx expo prebuild` & EAS Build (eg: updated a module plugin). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md) --------- Co-authored-by: expo-tuft[bot] <288127324+expo-tuft[bot]@users.noreply.github.com> Co-authored-by: Aman Mittal <amandeepmittal@live.com>
…-announce Reverses yesterday's opt-in default: the "started - watch the run" comment posts on every comment-path command unless --no-announce is given. Dispatch runs remain quiet always.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )