Skip to content

[Bug] Fix IPromise.finally() to await returned promises per ES2018 spec#508

Merged
nev21 merged 3 commits into
nevware21:mainfrom
MSNev:MSNev/Resilience
May 20, 2026
Merged

[Bug] Fix IPromise.finally() to await returned promises per ES2018 spec#508
nev21 merged 3 commits into
nevware21:mainfrom
MSNev:MSNev/Resilience

Conversation

@MSNev
Copy link
Copy Markdown
Contributor

@MSNev MSNev commented May 18, 2026

Promise.finally() was ignoring the return value of the onFinally callback. Per the ES2018 specification (ECMA-262 §27.2.5.3), if onFinally returns a promise/thenable, the resulting promise must wait for it to settle before propagating the original value or reason. If the returned promise rejects, that rejection must propagate.

Fixed in:

  • lib/src/promise/base.ts (_finally implementation)
  • lib/src/promise/await.ts (doFinally fallback when .finally is unavailable)
  • lib/src/interfaces/types.ts (FinallyPromiseHandler type updated to allow PromiseLike)
  • lib/src/interfaces/IPromise.ts (updated @param typedoc)

@MSNev MSNev added this to the 0.6.0 milestone May 18, 2026
@MSNev MSNev requested review from a team as code owners May 18, 2026 22:50
@MSNev MSNev requested a review from Copilot May 18, 2026 22:50
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes IPromise.finally() (and the doFinally fallback when native .finally is unavailable) to comply with ES2018 §27.2.5.3: when the onFinally callback returns a thenable, the resulting promise now waits for that thenable to settle before propagating the original value/reason, and if the returned thenable rejects, that rejection replaces the original outcome.

Changes:

  • Updated _finally in lib/src/promise/base.ts to await a thenable returned from onFinally in both fulfilled and rejected paths.
  • Updated the simulated-finally branch of doFinally in lib/src/promise/await.ts to do the same.
  • Broadened FinallyPromiseHandler to allow () => PromiseLike<void> and refreshed the related TypeDoc on IPromise.finally.
  • Refreshed transitive dependency versions in common/config/rush/npm-shrinkwrap.json (notably @nevware21/ts-preproc 0.1.4 → 0.1.5 with newer globby/ignore).

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
lib/src/promise/base.ts Await thenable returned by onFinally in both then/catch branches to comply with the spec.
lib/src/promise/await.ts Mirror the same spec-compliant behavior in the doFinally simulated-finally fallback.
lib/src/interfaces/types.ts Extend FinallyPromiseHandler to allow returning PromiseLike<void> and update the doc comment.
lib/src/interfaces/IPromise.ts Update @param onfinally TypeDoc to describe the new async/awaiting semantics.
common/config/rush/npm-shrinkwrap.json Lockfile refresh including @nevware21/ts-preproc 0.1.4→0.1.5 and related transitive bumps.
Files not reviewed (1)
  • common/config/rush/npm-shrinkwrap.json: Language not supported

Comment thread lib/src/promise/base.ts Outdated
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

❌ Patch coverage is 69.23077% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 96.96%. Comparing base (1e7a8f4) to head (60e3c77).

Files with missing lines Patch % Lines
lib/src/promise/await.ts 50.00% 4 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #508      +/-   ##
==========================================
- Coverage   97.49%   96.96%   -0.54%     
==========================================
  Files          27       27              
  Lines        1439     1450      +11     
  Branches      338      341       +3     
==========================================
+ Hits         1403     1406       +3     
- Misses         36       44       +8     
Files with missing lines Coverage Δ
lib/src/interfaces/IPromise.ts 50.00% <ø> (ø)
lib/src/interfaces/types.ts 50.00% <ø> (ø)
lib/src/promise/base.ts 98.98% <100.00%> (-0.01%) ⬇️
lib/src/promise/await.ts 91.83% <50.00%> (-8.17%) ⬇️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 9 out of 10 changed files in this pull request and generated 4 comments.

Files not reviewed (1)
  • common/config/rush/npm-shrinkwrap.json: Language not supported

Comment thread lib/src/interfaces/types.ts Outdated
Comment thread common/config/rush/npm-shrinkwrap.json
Comment thread common/config/rush/npm-shrinkwrap.json
Comment thread lib/test/src/promise/use.await.test.ts Outdated
@MSNev MSNev force-pushed the MSNev/Resilience branch 6 times, most recently from 14193df to 94b3773 Compare May 19, 2026 23:31
Promise.finally() was ignoring the return value of the onFinally callback.
Per the ES2018 specification (ECMA-262 §27.2.5.3), if onFinally returns a
promise/thenable, the resulting promise must wait for it to settle before
propagating the original value or reason. If the returned promise rejects,
that rejection must propagate.

Fixed in:
- lib/src/promise/base.ts (_finally implementation)
- lib/src/promise/await.ts (doFinally fallback when .finally is unavailable)
- lib/src/interfaces/types.ts (FinallyPromiseHandler type updated to allow PromiseLike<void>)
- lib/src/interfaces/IPromise.ts (updated @param typedoc)
@MSNev MSNev force-pushed the MSNev/Resilience branch from 94b3773 to 0217915 Compare May 20, 2026 04:53
nev21
nev21 previously approved these changes May 20, 2026
@nev21 nev21 enabled auto-merge (squash) May 20, 2026 05:14
@nev21 nev21 merged commit 2552bac into nevware21:main May 20, 2026
9 of 10 checks passed
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.

4 participants