Skip to content

Conversation

@odinho
Copy link

@odinho odinho commented Oct 31, 2025

Breaking Changes

Replace pre-instantiated singleton errors with error classes to enable stack traces.

You can already provide your own errors which also gets around this, but that would require remembering doing that at all call sites. And then telling every other consumer of this library to also do that. So, not working well in practice.

Before:

import { E_TIMEOUT, E_CANCELED, E_ALREADY_LOCKED } from 'async-mutex';

if (e === E_TIMEOUT) { }

After:

import { TimeoutError, CanceledError, AlreadyLockedError } from 'async-mutex';

if (e instanceof TimeoutError) { }

Motivation

Singleton errors captured stack traces at module load time, making them not-great for debugging. Error classes provide stack traces for each error occurrence.

Changes

  • Replace E_TIMEOUT, E_ALREADY_LOCKED, E_CANCELED exports with TimeoutError, AlreadyLockedError, CanceledError classes
  • Each error creates a new instance with proper stack trace
  • Add Object.setPrototypeOf() to fix instanceof behavior in ES5 targets

~50 bytes bundle size increase, because of ES5 support. Could probably remove or write it in ES5-style directly.

Migration

TypeScript users: Compile errors will guide migration.
JavaScript users (ESM): Import errors will make any upgrade fail when loading.

The non-ESM-story I guess will get a runtime error, if they upgrade to a 1.0 version (which this should be if taken in) without checking for breaking changes.

BREAKING change. Singleton errors captured stack traces at module load
time, making them useless for debugging. Error classes provide stack
traces for each error occurrence.
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.

1 participant