Skip to content
This repository was archived by the owner on Feb 26, 2024. It is now read-only.

Commit 4ea5a02

Browse files
committed
feat(async): support native async/await
1 parent 31fc127 commit 4ea5a02

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

lib/common/promise.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
207207
api.scheduleMicroTask(); // to make sure that it is running
208208
}
209209
}
210+
if ((promise as any)['__zone_symbol__isAsync'] === true) {
211+
Zone.setAsyncFrame();
212+
}
210213
}
211214
}
212215
// Resolving an already resolved promise is a noop.
@@ -450,9 +453,16 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr
450453
proto[symbolThen] = originalThen;
451454

452455
Ctor.prototype.then = function(onResolve: any, onReject: any) {
456+
let isNativePromise = false;
457+
if (this && !(this instanceof ZoneAwarePromise)) {
458+
isNativePromise = true;
459+
}
453460
const wrapped = new ZoneAwarePromise((resolve, reject) => {
454461
originalThen.call(this, resolve, reject);
455462
});
463+
if (isNativePromise) {
464+
(wrapped as any)['__zone_symbol__isAsync'] = true;
465+
}
456466
return wrapped.then(onResolve, onReject);
457467
};
458468
(Ctor as any)[symbolThenPatched] = true;

lib/zone.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ interface ZoneType {
307307

308308
/** @internal */
309309
__symbol__(name: string): string;
310+
311+
/** @internal */
312+
setAsyncFrame(): void;
310313
}
311314

312315
/** @internal */
@@ -661,6 +664,9 @@ const Zone: ZoneType = (function(global: any) {
661664
}
662665
}
663666

667+
const detectAsyncFunction = async function() {};
668+
const AsyncFunction = detectAsyncFunction.constructor;
669+
664670
class Zone implements AmbientZone {
665671
static __symbol__: (name: string) => string = __symbol__;
666672

@@ -691,6 +697,10 @@ const Zone: ZoneType = (function(global: any) {
691697
return _currentTask;
692698
}
693699

700+
static setAsyncFrame() {
701+
_currentZoneFrame = _asyncZoneFrame!;
702+
}
703+
694704
static __load_patch(name: string, fn: _PatchFn): void {
695705
if (patches.hasOwnProperty(name)) {
696706
throw Error('Already loaded patch: ' + name);
@@ -761,9 +771,26 @@ const Zone: ZoneType = (function(global: any) {
761771
callback: (...args: any[]) => T, applyThis?: any, applyArgs?: any[], source?: string): T {
762772
_currentZoneFrame = {parent: _currentZoneFrame, zone: this};
763773
try {
774+
if (callback && callback.constructor === AsyncFunction) {
775+
const r = this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);
776+
if (r && typeof r.then === 'function') {
777+
_asyncZoneFrame = _currentZoneFrame;
778+
return r.then((result: any) => {
779+
_currentZoneFrame = _asyncZoneFrame!.parent!;
780+
_isAsyncSet = true;
781+
_asyncZoneFrame = null;
782+
return result;
783+
});
784+
}
785+
return r;
786+
}
764787
return this._zoneDelegate.invoke(this, callback, applyThis, applyArgs, source);
765788
} finally {
766-
_currentZoneFrame = _currentZoneFrame.parent!;
789+
if (!_isAsyncSet) {
790+
_currentZoneFrame = _currentZoneFrame.parent!;
791+
} else {
792+
_isAsyncSet = false;
793+
}
767794
}
768795
}
769796

@@ -1353,6 +1380,8 @@ const Zone: ZoneType = (function(global: any) {
13531380
},
13541381
};
13551382
let _currentZoneFrame: _ZoneFrame = {parent: null, zone: new Zone(null, null)};
1383+
let _asyncZoneFrame: _ZoneFrame|null = null;
1384+
let _isAsyncSet = false;
13561385
let _currentTask: Task|null = null;
13571386
let _numberOfNestedTaskFrames = 0;
13581387

0 commit comments

Comments
 (0)