Conversation
## Why Fixes #20291. On Android, legacy `FileSystem.readAsStringAsync` ignored `position` and `length` for UTF-8 reads and loaded the full input stream before decoding. That defeated chunked reads for large JSON/text files and could trigger OOM. iOS also read UTF-8 strings through `String(contentsOfFile:)`, so the option docs did not match behavior outside Base64 reads. ## How Route legacy reads through byte-range helpers before encoding/decoding. Android now shares the same byte-range path for UTF-8 and Base64 while preserving existing Base64 behavior, and iOS now reads a byte range into `Data` before converting to `String`. The scope is intentionally limited to legacy `readAsStringAsync` and its `ReadingOptions` docs. ## Test Plan - [x] `git diff --check upstream/main...HEAD` - [x] `npx pnpm@10.33.0 --filter expo-file-system build` - [x] `/Users/mvincentong/.npm/_npx/00d0dcf00546c229/node_modules/.bin/oxlint --config oxlint.config.mjs .` from `packages/expo-file-system` - [x] `env ANDROID_HOME=/Users/mvincentong/Library/Android/sdk ANDROID_SDK_ROOT=/Users/mvincentong/Library/Android/sdk node_modules/.bin/et native-unit-tests --packages expo-file-system -p android` Additional check: `npx pnpm@10.33.0 --filter expo-file-system test` currently fails in unchanged `src/__tests__/FileSystem-test.native.ts` because `legacy.downloadAsync()` returns `undefined` in the legacy mock test. The same targeted failure reproduces on clean `upstream/main` with `npx pnpm@10.33.0 --filter expo-file-system test -- src/__tests__/FileSystem-test.native.ts --runInBand`, so I did not change this PR for that unrelated failure. ## Risk Seven-file `expo-file-system` diff: Android source/helper + Android unit test, iOS source helper/module, TypeScript option docs, and changelog. No dependency changes, no broad file-system API rewrite, and no committed generated output on the current base. --------- Co-authored-by: Bartłomiej Klocek <bartlomiej.klocek@swmansion.com>
# Why `expo-router` now uses [subpath exports](https://nodejs.org/api/packages.html#subpath-exports) so these files are unnecessary. Additionally, we made a mistake when declaring the `split-view` subpath in `expo-router/package.json`, it should have been `unstable-split-view`; this has now been rectified. # How Removed all files in `expo-router`'s root directory that have a subpath declaration in `package.json`. # Test Plan - CI # 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) - [x] 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)
…#49004) # Why <!-- Please describe the motivation for this PR, and link to relevant GitHub issues, forums posts, or feature requests. --> Fix ENG-25994 #49002 # How <!-- How did you build this feature or fix this bug and why? --> The unversioned page banner now hides its "latest version" link when that page doesn't exist in the latest SDK. # 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. --> <img width="2468" height="844" alt="CleanShot 2026-08-17 at 11 33 55@2x" src="https://github.com/user-attachments/assets/0b629df8-d484-4049-8b74-ae9d8cefc47d" /> # 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)
# Why The local network grant was only persisted when a dev server was discovered, so users who allowed the permission with no server running were re-prompted on every launch. # How Discovery now advertises its own Bonjour service, so a granted permission always produces a browse result, and the grant is persisted only when results arrive. The startup prompt is skipped until onboarding has finished, arriving from an deep link marks onboarding as done, and a banner on the home tab offers the permission flow whenever access is missing. # Test Plan Clean install, complete onboarding, confirm the permission screen appears on the next launch. Allow with no dev server running, relaunch, and confirm no re-prompt. Deny, relaunch, and confirm the screen returns. Open a project from a QR code on a fresh install and confirm onboarding is skipped. With permission missing, tap the home banner and complete the flow.
…ncelled requests (#48963) # Why Pull-to-refresh on the Projects and Snacks screens showed an immediate "Network error: cancelled" alert. Clearing the list before fetching swapped the rows, which cancelled the refreshable task and surfaced the cancellation as an error. # How Refresh keeps the current rows until fresh data replaces them # Test Plan Pull to refresh on Projects and Snacks. Works as expected
…tes (#48964) # Why Every published update has a unique manifest link, so opening successive updates of the same project filled Recently Opened with duplicate rows that all showed the same name. # How Entries are also treated as duplicates when both URLs are update links and the display name matches. # Test Plan Publish two updates to the same branch and open each. Recently Opened shows a single row.
…47999) # Why Sometimes building a brownfield app configured with `multipleFrameworks: true` will fail with a `ARG_MAX` error due to the way we mangle Objective-C symbols and append the list of symbols to each pod's `GCC_PREPROCESSOR_DEFINITIONS` # How Instead of inlining the renames as `-D` flags, we now emit them as `#define` lines in a generated header and force-include that header (`-include "$(MANGLING_HEADER)"` on `OTHER_CFLAGS`). # Test Plan - Added unit tests for the symbol transform covering the new filtering, selector distinctiveness, setter/ivar symmetry, and the `__OBJC__`-guarded header output. - Manual: prebuild and `pod install` an app configured with `multipleFrameworks: true`, then build for the simulator. # 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 Bot <34669131+expo-bot@users.noreply.github.com>
# Why `iOS Unit Tests` has been red on `main` since #48840 merged. The whole `xcodebuild` invocation fails to compile, so every scheduled package is reported as failed, not just `expo-audio`. ``` error: value of optional type 'Int?' must be unwrapped to a value of type 'Int' #expect(permissions["status"] as? Int == EXPermissionStatusDenied.rawValue) ``` `EXPermissionStatus` is a plain C enum, not `NS_ENUM`: ```objc // packages/expo-modules-core/ios/Interfaces/Permissions/EXPermissionsInterface.h typedef enum EXPermissionStatus { ... } EXPermissionStatus; ``` Swift imports a plain C enum as a `RawRepresentable` struct whose `RawValue` is `UInt32`, so `EXPermissionStatusDenied.rawValue` is `UInt32` while `permissions["status"] as? Int` is `Int?`. The comparison never typechecks. The diagnostic blames the optional, but the real mismatch is `Int` vs `UInt32`. # How Cast to `UInt32` instead of `Int`. `Int(EXPermissionStatusDenied.rawValue)` would also compile, but the test would then always fail: the dictionary stores a real `UInt32`, and `as? Int` on it returns `nil`. # Test Plan iOS Unit tests CI should pass
# Why The EAS changes in [#4180](expo/eas-cli#4180) tell Expo to use development or production mode when loading app config, so we needed a temporary internal environment variable that Expo reads and removes before app config loads. # How I added `__EXPO_CONFIG_MODE` as an internal handoff that `@expo/env` reads and removes before Expo loads the dotenv files and app config. I blocked `.env` files from setting the handoff and updated `getOriginalEnv()` and `getOriginalEnvValue()` to exclude dotenv values inherited from a parent process. We still use `EAS_BUILD` as the production fallback for older EAS versions. # Test Plan Tests and package checks pass. # 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). - [ ] Conforms with the [Documentation Writing Style Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
Adds workflow_dispatch with pr/agents/config-from-checkout inputs so stale-base PRs (merge base predating .expo-code-review/) can still be reviewed.
The runner forbids overriding GITHUB_REF via step env; export it inside the script instead.
Co-authored-by: nishan (o^▽^o) <nishanbende@gmail.com>
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 : )