Native Promise Predicate S2
- Stage: Stage 2
- Status: Active
- ECMAScript edition: —
- Synchronized: Aug 28, 2026
- 中文译文 · Source repository
This proposal introduces Promise.isPromise, a new predicate that exposes the result of the internal IsPromise abstract operation, allowing side-effect-free detection of native promises. It addresses the limitations of current patterns like Promise.resolve(val) === val, which allocate unnecessary promises and may trigger thenable assimilation.
The README below comes from the upstream repository and may contain outdated stage or status metadata. Use the proposal details above as the current source of truth.
Promise.isPromise
ECMAScript proposal and spec for Promise.isPromise.
Status
Stage: 2
Champions:
- Mathieu Hofman (@mhofman) (Agoric)
Motivation
It is currently impossible to check whether an object is a native promise without side effects. The usual pattern is to test whether Promise.resolve(val) === val, but in the negative case it creates a new promise resolved from val. Besides the unnecessary allocation, it may also trigger user-code related to the thenable assimilation mechanism.
Code that wants to be defensive, for example avoid synchronous re-entrancy when handling unknown values in async logic, can currently only do so by paying the cost of a tick (Promise.resolve().then(() => val)), even when the value is a safe native promise.
Native promises have their internal state safely adopted when doing await val, and if https://github.com/tc39/ecma262/pull/3689 is accepted, for other promise resolution paths.
instanceof Promise is not appropriate because that checks whether Promise.prototype is in the prototype chain of value, not whether the value passes the the IsPromise checks the spec performs internally.
Proposal
A new Promise.isPromise predicate that exposes the result of the IsPromise abstract operation.
Precedent
Error.isError does a similar brand check for native Error objects.
Membrane transparency
Like Error, Promises are also objects which are better "passed by copy" than proxied through membranes. Furthermore, it is already possible to asynchronously detect whether an object is a native promise or not through Promise.resolve().
A Promise.isPromise predicate would actually let membranes detect promise values which should be recreated on the other side.