diff --git a/packages/common/http/test/fetch_spec.ts b/packages/common/http/test/fetch_spec.ts index 32e4484959f..8d1da8de8f0 100644 --- a/packages/common/http/test/fetch_spec.ts +++ b/packages/common/http/test/fetch_spec.ts @@ -767,15 +767,12 @@ describe('FetchBackend', () => { export class MockFetchFactory extends FetchFactory { public readonly response = new MockFetchResponse(); public readonly request = new MockFetchRequest(); - private resolve!: Function; - private reject!: Function; + private resolve!: (value: Response | PromiseLike) => void; + private reject!: (reason?: any) => void; private clearWarningTimeout?: VoidFunction; - private promise = new Promise((resolve, reject) => { - this.resolve = resolve; - this.reject = reject; - }); + private promise = this.createFetchPromise(); override fetch = (input: RequestInfo | URL, init?: RequestInit): Promise => { this.request.method = init?.method; @@ -849,10 +846,14 @@ export class MockFetchFactory extends FetchFactory { } resetFetchPromise() { - this.promise = new Promise((resolve, reject) => { - this.resolve = resolve; - this.reject = reject; - }); + this.promise = this.createFetchPromise(); + } + + private createFetchPromise(): Promise { + const {promise, resolve, reject} = Promise.withResolvers(); + this.resolve = resolve; + this.reject = reject; + return promise; } } diff --git a/packages/common/test/pipes/async_pipe_spec.ts b/packages/common/test/pipes/async_pipe_spec.ts index f3ec2e4a251..88f4870157a 100644 --- a/packages/common/test/pipes/async_pipe_spec.ts +++ b/packages/common/test/pipes/async_pipe_spec.ts @@ -178,10 +178,7 @@ describe('AsyncPipe', () => { let promise: Promise; beforeEach(() => { - promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); + ({promise, resolve, reject} = Promise.withResolvers()); }); describe('transform', () => { diff --git a/packages/core/test/acceptance/change_detection_spec.ts b/packages/core/test/acceptance/change_detection_spec.ts index 0bd8dffb5e1..b4b07189eb3 100644 --- a/packages/core/test/acceptance/change_detection_spec.ts +++ b/packages/core/test/acceptance/change_detection_spec.ts @@ -1523,9 +1523,7 @@ describe('change detection', () => { private resolve?: Function; changeDetectorRef = inject(ChangeDetectorRef); createReadPromise() { - this.promise = new Promise((resolve) => { - this.resolve = resolve; - }); + ({promise: this.promise, resolve: this.resolve} = Promise.withResolvers()); } resolveReadPromise() { this.resolve?.(); diff --git a/packages/core/test/acceptance/pending_tasks_spec.ts b/packages/core/test/acceptance/pending_tasks_spec.ts index 93f58308c44..65bee39ade9 100644 --- a/packages/core/test/acceptance/pending_tasks_spec.ts +++ b/packages/core/test/acceptance/pending_tasks_spec.ts @@ -88,14 +88,10 @@ describe('public PendingTasks', () => { const appRef = TestBed.inject(ApplicationRef); const pendingTasks = TestBed.inject(PendingTasks); - let resolveFn: () => void; - pendingTasks.run(() => { - return new Promise((r) => { - resolveFn = r; - }); - }); + const {promise, resolve} = Promise.withResolvers(); + pendingTasks.run(() => promise); await expectAsync(applicationRefIsStable(appRef)).toBeResolvedTo(false); - resolveFn!(); + resolve(); await expectAsync(TestBed.inject(ApplicationRef).whenStable()).toBeResolved(); }); @@ -105,14 +101,10 @@ describe('public PendingTasks', () => { const errorHandler = TestBed.inject(ErrorHandler); const spy = spyOn(errorHandler, 'handleError'); - let rejectFn: () => void; - pendingTasks.run(() => { - return new Promise((_, reject) => { - rejectFn = reject; - }); - }); + const {promise, reject} = Promise.withResolvers(); + pendingTasks.run(() => promise); await expectAsync(applicationRefIsStable(appRef)).toBeResolvedTo(false); - rejectFn!(); + reject(); await expectAsync(appRef.whenStable()).toBeResolved(); expect(spy).toHaveBeenCalled(); }); diff --git a/packages/core/test/application_init_spec.ts b/packages/core/test/application_init_spec.ts index 12969afe903..d9c8dfda50b 100644 --- a/packages/core/test/application_init_spec.ts +++ b/packages/core/test/application_init_spec.ts @@ -50,10 +50,7 @@ describe('ApplicationInitStatus', () => { let initFnInvoked = false; beforeEach(() => { - promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); + ({promise, resolve, reject} = Promise.withResolvers()); TestBed.configureTestingModule({ providers: [{provide: APP_INITIALIZER, useValue: [() => promise]}], }); diff --git a/packages/core/test/application_ref_spec.ts b/packages/core/test/application_ref_spec.ts index 96d12974ac7..d9ca7037910 100644 --- a/packages/core/test/application_ref_spec.ts +++ b/packages/core/test/application_ref_spec.ts @@ -466,10 +466,7 @@ describe('bootstrap', () => { })); it('should wait for asynchronous app initializers', waitForAsync(async () => { - let resolve: (result: any) => void; - const promise: Promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); let initializerDone = false; setTimeout(() => { resolve(true); @@ -643,10 +640,7 @@ describe('bootstrap', () => { defaultPlatform = _platform; })); it('should wait for asynchronous app initializers', waitForAsync(async () => { - let resolve: (result: any) => void; - const promise: Promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); let initializerDone = false; setTimeout(() => { resolve(true); diff --git a/packages/core/test/change_detection_scheduler_spec.ts b/packages/core/test/change_detection_scheduler_spec.ts index 0fd45bb2189..813701d602b 100644 --- a/packages/core/test/change_detection_scheduler_spec.ts +++ b/packages/core/test/change_detection_scheduler_spec.ts @@ -469,10 +469,7 @@ describe('Angular with zoneless enabled', () => { }); it('executes render hooks when a new one is registered', async () => { - let resolveFn: Function; - let calledPromise = new Promise((resolve) => { - resolveFn = resolve; - }); + const {promise: calledPromise, resolve: resolveFn} = Promise.withResolvers(); TestBed.runInInjectionContext(() => { afterNextRender(() => { resolveFn(); @@ -496,10 +493,7 @@ describe('Angular with zoneless enabled', () => { await fixture.whenStable(); expect(checks).toBe(1); - let resolveFn: Function; - let calledPromise = new Promise((resolve) => { - resolveFn = resolve; - }); + const {promise: calledPromise, resolve: resolveFn} = Promise.withResolvers(); TestBed.runInInjectionContext(() => { afterNextRender(() => { resolveFn(); diff --git a/packages/core/test/di/inject_async/inject_async_spec.ts b/packages/core/test/di/inject_async/inject_async_spec.ts index 9d21a43779e..701f698b049 100644 --- a/packages/core/test/di/inject_async/inject_async_spec.ts +++ b/packages/core/test/di/inject_async/inject_async_spec.ts @@ -62,10 +62,7 @@ describe('injectAsync', () => { }); await TestBed.runInInjectionContext(async () => { - let prefetchResolve!: () => void; - const prefetchPromise = new Promise((resolve) => { - prefetchResolve = resolve; - }); + const {promise: prefetchPromise, resolve: prefetchResolve} = Promise.withResolvers(); let prefetchCalled = false; const loader = () => { diff --git a/packages/core/test/linker/integration_spec.ts b/packages/core/test/linker/integration_spec.ts index 96323229908..3df850cf240 100644 --- a/packages/core/test/linker/integration_spec.ts +++ b/packages/core/test/linker/integration_spec.ts @@ -2422,13 +2422,11 @@ class PushCmpWithHostEvent { }) class PushCmpWithAsyncPipe { numberOfChecks: number = 0; - resolve!: (result: any) => void; + resolve: (result: any) => void; promise: Promise; constructor() { - this.promise = new Promise((resolve) => { - this.resolve = resolve; - }); + ({promise: this.promise, resolve: this.resolve} = Promise.withResolvers()); } get field() { diff --git a/packages/core/test/linker/resource_loader_mock.ts b/packages/core/test/linker/resource_loader_mock.ts index a00e040fb40..26f71818e9e 100644 --- a/packages/core/test/linker/resource_loader_mock.ts +++ b/packages/core/test/linker/resource_loader_mock.ts @@ -103,17 +103,16 @@ export class MockResourceLoader extends ResourceLoader { } class _PendingRequest { - // Using non null assertion, these fields are defined below - // within the `new Promise` callback (synchronously). - resolve!: (result: string) => void; - reject!: (error: any) => void; + resolve: (result: string) => void; + reject: (error: any) => void; promise: Promise; constructor(public url: string) { - this.promise = new Promise((res, rej) => { - this.resolve = res; - this.reject = rej; - }); + ({ + promise: this.promise, + resolve: this.resolve, + reject: this.reject, + } = Promise.withResolvers()); } complete(response: string | null) { diff --git a/packages/core/test/resource/debounce_spec.ts b/packages/core/test/resource/debounce_spec.ts index e105a556f72..5735acd338c 100644 --- a/packages/core/test/resource/debounce_spec.ts +++ b/packages/core/test/resource/debounce_spec.ts @@ -142,11 +142,12 @@ describe('debounced', () => { const res = debounced( source, - () => - new Promise((resolve) => { - calls++; - release = resolve; - }), + () => { + calls++; + const {promise, resolve} = Promise.withResolvers(); + release = resolve; + return promise; + }, {injector}, ); @@ -198,12 +199,13 @@ describe('debounced', () => { const res = debounced( source, - (val: string) => - new Promise((resolve) => { - if (val === 'initial') releaseInitial = resolve; - if (val === 'update1') release1 = resolve; - if (val === 'update2') release2 = resolve; - }), + (val: string) => { + const {promise, resolve} = Promise.withResolvers(); + if (val === 'initial') releaseInitial = resolve; + if (val === 'update1') release1 = resolve; + if (val === 'update2') release2 = resolve; + return promise; + }, {injector}, ); diff --git a/packages/core/test/resource/resource_spec.ts b/packages/core/test/resource/resource_spec.ts index 494b6ac58a7..b676f0bd291 100644 --- a/packages/core/test/resource/resource_spec.ts +++ b/packages/core/test/resource/resource_spec.ts @@ -25,7 +25,6 @@ import { signal, TransferState, } from '../../src/core'; -import {promiseWithResolvers} from '../../src/util/promise_with_resolvers'; import {TestBed} from '../../testing'; abstract class MockBackend { @@ -344,7 +343,7 @@ describe('resource', () => { const res = resource({ params: request, loader: async ({params}) => { - const p = promiseWithResolvers(); + const p = Promise.withResolvers(); resolve.push(() => p.resolve(params)); return p.promise; }, diff --git a/packages/core/test/zone/ng_zone_spec.ts b/packages/core/test/zone/ng_zone_spec.ts index 4b12f8adb59..af988377c83 100644 --- a/packages/core/test/zone/ng_zone_spec.ts +++ b/packages/core/test/zone/ng_zone_spec.ts @@ -90,10 +90,7 @@ describe('NgZone', () => { it('should produce long stack traces', (done) => { macroTask(() => { - let resolve: (result: any) => void; - const promise: Promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); _zone.run(() => { setTimeout(() => { @@ -114,10 +111,7 @@ describe('NgZone', () => { it('should produce long stack traces (when using microtasks)', (done) => { macroTask(() => { - let resolve: (result: any) => void; - const promise: Promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); _zone.run(() => { queueMicrotask(() => { @@ -150,10 +144,7 @@ describe('NgZone', () => { it('should disable long stack traces', (done) => { macroTask(() => { - let resolve: (result: any) => void; - const promise: Promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); _zone.run(() => { setTimeout(() => { @@ -524,12 +515,8 @@ function commonTests() { runNgZoneNoLog(() => { macroTask(() => { - aPromise = new Promise((res) => { - aResolve = res; - }); - bPromise = new Promise((res) => { - bResolve = res; - }); + ({promise: aPromise, resolve: aResolve} = Promise.withResolvers()); + ({promise: bPromise, resolve: bResolve} = Promise.withResolvers()); _log.add('run start'); aPromise.then(_log.fn('a then')); @@ -569,9 +556,7 @@ function commonTests() { macroTask(() => { NgZone.assertNotInAngularZone(); - promise = new Promise((res) => { - resolve = res; - }); + ({promise, resolve} = Promise.withResolvers()); }); runNgZoneNoLog(() => { @@ -748,12 +733,8 @@ function commonTests() { runNgZoneNoLog(() => { macroTask(() => { - aPromise = new Promise((res) => { - aResolve = res; - }); - bPromise = new Promise((res) => { - bResolve = res; - }); + ({promise: aPromise, resolve: aResolve} = Promise.withResolvers()); + ({promise: bPromise, resolve: bResolve} = Promise.withResolvers()); aPromise.then(_log.fn('a then')); bPromise.then(_log.fn('b then')); _log.add('run start'); diff --git a/packages/forms/signals/test/node/field_node.spec.ts b/packages/forms/signals/test/node/field_node.spec.ts index 69148e1f123..449f3b1ee51 100644 --- a/packages/forms/signals/test/node/field_node.spec.ts +++ b/packages/forms/signals/test/node/field_node.spec.ts @@ -1570,10 +1570,7 @@ describe('FieldNode', () => { }); it('should immediately update value on reset even if a debounce is pending', async () => { - let resolveDebounce: (value: void | PromiseLike) => void; - const debouncePromise = new Promise((resolve) => { - resolveDebounce = resolve; - }); + const {promise: debouncePromise, resolve: resolveDebounce} = Promise.withResolvers(); const model = signal('initial'); const f = form( @@ -1598,7 +1595,7 @@ describe('FieldNode', () => { expect(f().controlValue()).toBe('reset value'); // 3. Resolve the debounce - resolveDebounce!(); + resolveDebounce(); await Promise.resolve(); // Wait for promise microtasks // Value should STILL be 'reset value', not 'user input' @@ -1635,10 +1632,7 @@ describe('FieldNode', () => { }); it('should abort pending debounce on reset without value and not trigger further sync', async () => { - let resolveDebounce: (value: void | PromiseLike) => void; - const debouncePromise = new Promise((resolve) => { - resolveDebounce = resolve; - }); + const {promise: debouncePromise, resolve: resolveDebounce} = Promise.withResolvers(); const model = signal('initial'); const f = form( @@ -1664,7 +1658,7 @@ describe('FieldNode', () => { expect(f().controlValue()).toBe('initial'); // 3. Resolve the debounce - resolveDebounce!(); + resolveDebounce(); await Promise.resolve(); // Wait for promise microtasks // value.set should NEVER have been called during or after reset @@ -1673,10 +1667,7 @@ describe('FieldNode', () => { }); it('should abort pending debounce on reset with new value and only call value.set once immediately', async () => { - let resolveDebounce: (value: void | PromiseLike) => void; - const debouncePromise = new Promise((resolve) => { - resolveDebounce = resolve; - }); + const {promise: debouncePromise, resolve: resolveDebounce} = Promise.withResolvers(); const model = signal('initial'); const f = form( @@ -1704,7 +1695,7 @@ describe('FieldNode', () => { expect(f().value.set).toHaveBeenCalledWith('reset value'); // 3. Resolve the debounce - resolveDebounce!(); + resolveDebounce(); await Promise.resolve(); // Wait for promise microtasks // value.set should STILL have only been called once (the immediate one) diff --git a/packages/forms/signals/test/web/orphan_repro.spec.ts b/packages/forms/signals/test/web/orphan_repro.spec.ts index 5689d6eff65..d68bb11818b 100644 --- a/packages/forms/signals/test/web/orphan_repro.spec.ts +++ b/packages/forms/signals/test/web/orphan_repro.spec.ts @@ -69,10 +69,7 @@ describe('Signal Forms array removal orphan repro', () => { } }); it('should handle debounceSync resolving after the field is orphaned', async () => { - let resolveDebounce!: () => void; - const debouncePromise = new Promise((r) => { - resolveDebounce = r; - }); + const {promise: debouncePromise, resolve: resolveDebounce} = Promise.withResolvers(); @Component({ imports: [FormField], diff --git a/packages/forms/test/reactive_integration_spec.ts b/packages/forms/test/reactive_integration_spec.ts index 8d55910ae59..0253dfc0c5e 100644 --- a/packages/forms/test/reactive_integration_spec.ts +++ b/packages/forms/test/reactive_integration_spec.ts @@ -6300,10 +6300,7 @@ function asyncValidator( }, ) { return (c: AbstractControl) => { - let resolve: (result: any) => void; - const promise = new Promise((res) => { - resolve = res; - }); + const {promise, resolve} = Promise.withResolvers(); const res = checker(c) ? null : error; setTimeout(() => resolve(res), timeout); return promise; diff --git a/packages/platform-browser/test/testing_public_spec.ts b/packages/platform-browser/test/testing_public_spec.ts index d1fbc2d2635..120abbf6fa1 100644 --- a/packages/platform-browser/test/testing_public_spec.ts +++ b/packages/platform-browser/test/testing_public_spec.ts @@ -924,12 +924,7 @@ describe('public testing API', () => { let originalJasmineIt: (description: string, func: () => void) => jasmine.Spec; const patchJasmineIt = () => { - let resolve: (result: any) => void; - let reject: (error: any) => void; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); + const {promise, resolve, reject} = Promise.withResolvers(); const jasmineEnv = jasmine.getEnv() as any; originalJasmineIt = jasmineEnv.it; jasmineEnv.it = (description: string, fn: (done: DoneFn) => void): any => { diff --git a/packages/router/test/bootstrap.spec.ts b/packages/router/test/bootstrap.spec.ts index c05e85e2124..fae02051692 100644 --- a/packages/router/test/bootstrap.spec.ts +++ b/packages/router/test/bootstrap.spec.ts @@ -90,7 +90,7 @@ describe('bootstrap', () => { doc.body.appendChild(el1); doc.body.appendChild(el2); - const {promise, resolveFn} = createPromise(); + const {promise, resolve: resolveFn} = Promise.withResolvers(); navigationEndPromise = promise; log = []; testProviders = [ @@ -455,7 +455,7 @@ describe('bootstrap', () => { spyOn(router as any, 'resetRootComponentType').and.callThrough(); const appRef: ApplicationRef = res.injector.get(ApplicationRef); - const {promise, resolveFn} = createPromise(); + const {promise, resolve: resolveFn} = Promise.withResolvers(); appRef.components[0].onDestroy(() => { appRef.bootstrap(SecondRootCmp); expect((router as any).resetRootComponentType).toHaveBeenCalled(); @@ -629,11 +629,3 @@ function provideNavigationEndAction(fn: Function) { }, }; } - -function createPromise() { - let resolveFn: () => void; - const promise = new Promise((r) => { - resolveFn = r; - }); - return {resolveFn: () => resolveFn(), promise}; -} diff --git a/packages/router/test/router_resource_behavior_spec.ts b/packages/router/test/router_resource_behavior_spec.ts index 71fc938fe6b..a4852c8e929 100644 --- a/packages/router/test/router_resource_behavior_spec.ts +++ b/packages/router/test/router_resource_behavior_spec.ts @@ -94,9 +94,9 @@ describe('routerResource behavior tests', () => { resolveImmediately = false; return Promise.resolve('initial'); } - return new Promise((resolve) => { - resolveLoader = resolve; - }); + const {promise, resolve} = Promise.withResolvers(); + resolveLoader = resolve; + return promise; }, }); }