fix(zone.js): support passthrough of Promise.try API

When Zone patches Promise, it uses ZoneAwarePromise. The new Promise.try API was undefined on ZoneAwarePromise, making it unavailable when zone was present. This change gracefully passes through Promise.try to the native Promise implementation, if available, without patching it to execute in the right zone (our stance is not to add new patches but avoid destructively making new APIs unavailable).

Fixes #67057
This commit is contained in:
Andrew Scott
2026-02-13 09:23:43 -08:00
committed by Matthew Beck (Berry)
parent 95b3f37d4a
commit fc557f0276
3 changed files with 51 additions and 0 deletions
+5
View File
@@ -627,6 +627,11 @@ export function patchPromise(Zone: ZoneType): void {
if (NativePromise) {
patchThen(NativePromise);
// TODO(atscott): Investigate generic to propagate any unknown properties
const nativeTry = (NativePromise as any)['try'];
if (nativeTry && typeof nativeTry === 'function') {
(ZoneAwarePromise as any)['try'] = nativeTry;
}
patchMethod(global, 'fetch', (delegate) => zoneify(delegate));
}
@@ -969,5 +969,38 @@ describe(
reject(error);
});
});
describe('Promise.try', () => {
it('should resolve', (done: DoneFn) => {
(Promise as any)
.try(() => 1)
.then((v: any) => {
expect(v).toBe(1);
done();
});
});
it('should reject on throw', (done: DoneFn) => {
const error = new Error('test');
(Promise as any)
.try(() => {
throw error;
})
.catch((e: any) => {
expect(e).toBe(error);
done();
});
});
it('should execute in the correct zone', (done: DoneFn) => {
const zone = Zone.current.fork({name: 'promise-try'});
zone.run(() => {
(Promise as any)
.try(() => 1)
.then(() => {
expect(Zone.current.name).toEqual(zone.name);
done();
});
});
});
});
}),
);
@@ -17,6 +17,19 @@ export function setupFakePolyfill(): void {
NativeError.customProperty = 'customProperty';
NativeError.customFunction = function () {};
// Polyfill Promise.try for testing pass-through
if (global.Promise && typeof global.Promise.try !== 'function') {
global.Promise.try = function (callback: any) {
return new global.Promise((resolve: any, reject: any) => {
try {
resolve(callback());
} catch (e) {
reject(e);
}
});
};
}
// add fake cordova polyfill for test
const fakeCordova = function () {};