Skip to content

[pull] main from expo:main - #1192

Merged
pull[bot] merged 6 commits into
code:mainfrom
expo:main
Aug 28, 2026
Merged

[pull] main from expo:main#1192
pull[bot] merged 6 commits into
code:mainfrom
expo:main

Conversation

@pull

@pull pull Bot commented Aug 28, 2026

Copy link
Copy Markdown

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 : )

alanjhughes and others added 6 commits August 27, 2026 22:58
…allowing them (#49456)

# Why
addNewAssets is declared throws but never threw. All three failure paths
rolled the transaction back and returned silently. A single SQLite error
while registering a downloaded update meant the asset rows, and the
launch_asset_id write were rolled back, while the caller saw success and
still marked the update ready. The result is an update row that is
selected as launchable on every cold start but can never launch.

# How
Rethrow after each rollback. The caller in AppLoader.finish() already
has correct handling for a thrown error, so the update row stays pending
and the next update check retries it cleanly. This is deliberately the
smallest possible change so it can be cherry-picked to SDK 55.

# Test Plan
Added UpdatesDatabaseTests that forces a mid-batch statement failure by
dropping the updates_assets table, then asserts addNewAssets throws and
the whole batch rolled back
…et (#49457)

# Why
The previous PR stops inserting bad row, but devices that already have a
ready update row with no launch asset stay broken forever. The row is
selected on every launch, the launch fails, and nothing ever fixes it

# How
launchableUpdates already reads every candidate row on launch, so the
repair lives there at no extra cost to healthy devices. A ready row with
no launch asset is demoted to pending and excluded from the candidates
in the same pass. The launcher then falls back to the embedded update
cleanly on that boot, and the existing loader path re-registers the
demoted row in the background.

# Test Plan
Two tests: selection demotes a broken ready row to pending and excludes
it, and a healthy ready row passes through untouched.
… in a single transaction (#49458)

# Why
Registration used to be three separate commits: one per existing asset
link, one batch for new assets, and one for the ready status. Any
interruption between them left partial state behind. Worse, a failed
existing-asset link was logged and swallowed, and an unreadable asset
file was dropped by a release-mode no-op assert, so an update could
still be marked ready without its launch asset. This mirrors what #49130
fixed for embedded registration on Android.

# How
A new finishUpdateRegistration runs the existing links, the new asset
batch, and the finished status in one transaction. The transaction
helper checks the result codes of BEGIN and COMMIT, which the old inline
code ignored, so a failed commit can no longer report success. Before
committing, a guard verifies the update actually has a launch asset and
refuses to mark it ready otherwise.

# Test Plan
Three tests on the new method
…lently or hanging (#49459)

# Why
iOS had no equivalent of Android's "Launch asset not found" error. A
launchable update with no linked launch asset completed with a nil error
and a false success flag, and an update with zero linked assets never
invoked its completion at all, leaving the app on the splash screen
forever. In production this surfaced as a generic message that pointed
at nothing.

# How
Both paths now produce appLauncherLaunchAssetNotFound carrying the
update id: the empty asset list completes immediately with the error,
and a completed pass with no launch asset URL substitutes it for the nil
error. The new checks sit after the embedded and development early
returns, so no-copy embedded launches are unaffected, per the iOS caveat
raised on #48733. With the repair in the previous PR filtering broken
rows at selection, this guard is the backstop for states that arise
after selection.

# Test Plan
Two launcher tests run the real ensureAllAssetsExist against a seeded
database, one for the hang and one for the silent failure
…reason (#49460)

# Why
On a cold start where the cached update fails to launch and the remote
check finds nothing new, AppLoaderTask logged the real failure and then
reported the generic "unexpected error" to the delegate. Crash reporting
therefore showed one indistinguishable message for completely different
failure modes

# How
A fallbackLaunchError property defaults to the generic error and is
upgraded to the wrapped launcher failure when the task defers to the
remote check. finish reports the explicit error when there is one, then
the fallback. The delegate, and therefore the emergency launch reason in
crash reporting, now carries the real cause.

# Test Plan
A new AppLoaderTaskTests suite simulates the full cold-start
@pull pull Bot locked and limited conversation to collaborators Aug 28, 2026
@pull pull Bot added the ⤵️ pull label Aug 28, 2026
@pull
pull Bot merged commit f423e2a into code:main Aug 28, 2026
13 checks passed
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants