refactor(core): remove usages of Promise.withResolvers (#63856)

Promise.withResolvers is Baseline 2024. Our policy is to support browsers in the scope of Basline widely available.

Fixes #63855

PR Close #63856
This commit is contained in:
Matthieu Riegler 2025-09-17 09:47:43 +02:00 committed by Jessica Janiuk
parent 423cc17a76
commit dcdca98f5d
4 changed files with 29 additions and 8 deletions

View file

@ -70,7 +70,7 @@ import {
getTDeferBlockDetails,
} from './utils';
import {ApplicationRef} from '../application/application_ref';
import type {PromiseConstructor} from '../util/promise_with_resolvers';
import {promiseWithResolvers} from '../util/promise_with_resolvers';
/**
* Schedules triggering of a defer block for `on idle` and `on timer` conditions.
@ -549,7 +549,7 @@ function cleanupRemainingHydrationQueue(
*/
function populateHydratingStateForQueue(registry: DehydratedBlockRegistry, queue: string[]) {
for (let blockId of queue) {
registry.hydrating.set(blockId, (Promise as unknown as PromiseConstructor).withResolvers());
registry.hydrating.set(blockId, promiseWithResolvers<void>());
}
}

View file

@ -19,7 +19,7 @@ import {Renderer} from '../interfaces/renderer';
import {NgZone} from '../../zone';
import {determineLongestAnimation, allLeavingAnimations} from '../../animation/longest_animation';
import {TNode} from '../interfaces/node';
import type {PromiseConstructor} from '../../util/promise_with_resolvers';
import {promiseWithResolvers} from '../../util/promise_with_resolvers';
import {
areAnimationsDisabled,
@ -230,7 +230,7 @@ function runLeaveAnimations(
value: string | Function,
animationsDisabled: boolean,
): Promise<void> {
const {promise, resolve} = (Promise as unknown as PromiseConstructor).withResolvers<void>();
const {promise, resolve} = promiseWithResolvers<void>();
const nativeElement = getNativeByTNode(tNode, lView) as Element;
ngDevMode && assertElementNodes(nativeElement, 'animate.leave');
@ -363,7 +363,7 @@ function runLeaveAnimationFunction(
tNode: TNode,
value: AnimationFunction,
): Promise<void> {
const {promise, resolve} = (Promise as unknown as PromiseConstructor).withResolvers<void>();
const {promise, resolve} = promiseWithResolvers<void>();
const nativeElement = getNativeByTNode(tNode, lView) as Element;
ngDevMode && assertElementNodes(nativeElement, 'animate.leave');

View file

@ -27,3 +27,25 @@ export interface PromiseConstructor {
*/
withResolvers<T>(): PromiseWithResolvers<T>;
}
/**
* Replace with `Promise.withResolvers()` once it's available.
* NET September 2026
*
* See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers.
*/
export function promiseWithResolvers<T>(): {
promise: Promise<T>;
resolve: (value: T | PromiseLike<T>) => void;
reject: (reason?: any) => void;
} {
let resolve!: (value: T | PromiseLike<T>) => void;
let reject!: (reason?: any) => void;
const promise = new Promise<T>((res, rej) => {
resolve = res;
reject = rej;
});
return {promise, resolve, reject};
}

View file

@ -18,8 +18,7 @@ import {
signal,
} from '../../src/core';
import {TestBed} from '../../testing';
import type {PromiseConstructor} from '../../src/util/promise_with_resolvers';
import {promiseWithResolvers} from '../../src/util/promise_with_resolvers';
abstract class MockBackend<T, R> {
protected pending = new Map<
@ -337,7 +336,7 @@ describe('resource', () => {
const res = resource({
params: request,
loader: async ({params}) => {
const p = (Promise as unknown as PromiseConstructor).withResolvers<number>();
const p = promiseWithResolvers<number>();
resolve.push(() => p.resolve(params));
return p.promise;
},