Skip to content

fetch(..., { signal: AbortSignal.timeout(...) }) throws AbortError instead of TimeoutError when timeout happens #1718

Open
@Frederick888

Description

Describe the bug
When fetch() is aborted due to a timeout signal, the DOMException's name is AbortError instead of TimeoutError.

To Reproduce
I'm using happy-dom in Jest to test some code similar to the MDN example https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static#using_abortsignal.any.

  • Node.js v22.12.0
  • happy-dom v16.8.1
  • Jest v29.7.0
  • happy-com/jest-environment v16.8.1
  • ts-jest v29.1.1
/**
 * @jest-environment @happy-dom/jest-environment
 * @jest-environment-options {"settings": {"fetch": {"disableSameOriginPolicy": true} } }
 */

import { setTimeout } from 'timers/promises'

it('happy-dom', async () => {
  try {
    const signal = AbortSignal.timeout(20)
    signal.addEventListener('abort', (ev) => {
      const currentTarget = ev.currentTarget as typeof ev.currentTarget & {
        reason: DOMException
      }
      console.debug({ reason: currentTarget.reason.name })
    })
    await setTimeout(100)
    await fetch('https://example.com', { signal })
  } catch (e) {
    console.debug(e)
    expect((e as Error).name).toStrictEqual('TimeoutError')
  }
})

Output:

  console.debug  <-- log in signal.AddEventListener()
    { reason: 'TimeoutError' }

      at AbortSignal.<anonymous> (src/shared/hooks/http/fetch.test.ts:40:15)

  console.debug  <-- log in catch
    DOMException [AbortError]: The operation was aborted.
        at Fetch.send (/path/to/project/node_modules/happy-dom/src/fetch/Fetch.ts:139:10)
        at Window.fetch (/path/to/project/node_modules/happy-dom/src/window/BrowserWindow.ts:1540:10)

      at src/shared/hooks/http/fetch.test.ts:45:13
          at Generator.throw (<anonymous>)

 FAIL  src/shared/hooks/http/fetch.test.ts (7.052 s)
  ✕ whatwg-fetch (133 ms)

  ● whatwg-fetch

    expect(received).toStrictEqual(expected) // deep equality

    Expected: "TimeoutError"
    Received: "AbortError"

      44 |   } catch (e) {
      45 |     console.debug(e)
    > 46 |     expect((e as Error).name).toStrictEqual('TimeoutError')
         |                               ^
      47 |   }
      48 | })
      49 |

      at src/shared/hooks/http/fetch.test.ts:46:31
          at Generator.throw (<anonymous>)
      at rejected (src/shared/hooks/http/fetch.test.ts:10:65)

Expected behavior
It throws a DOMException whose name is TimeoutError and message is The operation timed out. (like Firefox) or signal timed out (like Chrome).

Screenshots
N/A

Device:

  • OS: macOS
  • Browser: N/A
  • Version: 15.2

Additional context
Add any other context about the problem here.

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions