Skip to content

refactor: clean up composeSignals early-return structure#10844

Merged
jasonsaayman merged 3 commits into
axios:v1.xfrom
mixelburg:refactor/composeSignals-cleanup
May 6, 2026
Merged

refactor: clean up composeSignals early-return structure#10844
jasonsaayman merged 3 commits into
axios:v1.xfrom
mixelburg:refactor/composeSignals-cleanup

Conversation

@mixelburg
Copy link
Copy Markdown
Contributor

@mixelburg mixelburg commented May 4, 2026

What

Restructures lib/helpers/composeSignals.js from a nested if-block to an early-return pattern, reducing indentation and making the flow clearer.

Changes

  • Flips the outer if (timeout || length) to if (!timeout && !signals.length) return;
  • Uses const for the AbortController (not reassigned)
  • Explicitly initializes aborted = false instead of relying on implicit undefined
  • Adds a guard clause if (!signals) return at the top of unsubscribe for cleaner double-call protection
  • Preserves the existing manual event-listener approach

Why not AbortSignal.any()

I explored using AbortSignal.any(signals) instead of manual addEventListener calls. While it works for basic abort scenarios, it introduces subtle event-loop timing differences that cause the fetch adapter's stream-abort tests to fail (10 of 42 fetch tests hang). The composed signal's abort event fires in a different microtask queue compared to the direct listener approach, which changes the order of operations during stream abort handling. Until that's resolved upstream, the manual approach is more reliable.

Tests

All 45 relevant tests pass (3 composeSignals + 42 fetch adapter).


Summary by cubic

Refactors composeSignals to use an early-return pattern with small safety guards while keeping manual listener composition to preserve abort timing. No API or behavior changes.

Description

  • Summary of changes
    • Early return: if (!timeout && !signals.length) return
    • Use const for AbortController
    • Initialize aborted = false
    • Guard unsubscribe to ignore double calls
    • Keep manual listeners instead of AbortSignal.any()
  • Reasoning
    • Early returns simplify flow and reduce nesting
    • AbortSignal.any() changes event-loop timing and breaks stream-abort tests; manual listeners keep current behavior
  • Additional context
    • Only lib/helpers/composeSignals.js is changed
    • Merged latest v1.x into this branch; no functional changes

Docs

  • No API change; no docs required
  • Optional note in /docs/ that composeSignals uses manual signal composition and an early-return guard for empty input

Testing

  • No new tests
  • All existing tests pass (3 composeSignals, 42 fetch adapter)
  • No new tests needed; abort and timeout paths are covered

Semantic version impact

  • Patch: internal refactor with no API or behavior changes

Written for commit e7b6bd5. Summary will update on new commits.

Flips the main if-block to an early-return pattern to reduce nesting.
Explicitly initializes aborted to false. Adds a guard clause in
unsubscribe to avoid duplicate cleanup.

Preserves the existing manual event-listener approach because
AbortSignal.any() introduces event-loop timing differences that
break fetch adapter stream-abort tests.

Closes axios#10815.
@mixelburg mixelburg requested a review from jasonsaayman as a code owner May 4, 2026 22:50
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

@jasonsaayman jasonsaayman added priority::medium A medium priority commit::refactor The PR is related to refactoring labels May 6, 2026
@jasonsaayman jasonsaayman merged commit 5ad5fe0 into axios:v1.x May 6, 2026
23 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commit::refactor The PR is related to refactoring priority::medium A medium priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants