511 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			511 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| /**
 | |
|  * @license
 | |
|  * Copyright Google Inc. All Rights Reserved.
 | |
|  *
 | |
|  * Use of this source code is governed by an MIT-style license that can be
 | |
|  * found in the LICENSE file at https://angular.io/license
 | |
|  */
 | |
| Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePrivate) => {
 | |
|   const ObjectGetOwnPropertyDescriptor = Object.getOwnPropertyDescriptor;
 | |
|   const ObjectDefineProperty = Object.defineProperty;
 | |
| 
 | |
|   function readableObjectToString(obj: any) {
 | |
|     if (obj && obj.toString === Object.prototype.toString) {
 | |
|       const className = obj.constructor && obj.constructor.name;
 | |
|       return (className ? className : '') + ': ' + JSON.stringify(obj);
 | |
|     }
 | |
| 
 | |
|     return obj ? obj.toString() : Object.prototype.toString.call(obj);
 | |
|   }
 | |
| 
 | |
|   const __symbol__ = api.symbol;
 | |
|   const _uncaughtPromiseErrors: UncaughtPromiseError[] = [];
 | |
|   const symbolPromise = __symbol__('Promise');
 | |
|   const symbolThen = __symbol__('then');
 | |
|   const creationTrace = '__creationTrace__';
 | |
| 
 | |
|   api.onUnhandledError = (e: any) => {
 | |
|     if (api.showUncaughtError()) {
 | |
|       const rejection = e && e.rejection;
 | |
|       if (rejection) {
 | |
|         console.error(
 | |
|             'Unhandled Promise rejection:',
 | |
|             rejection instanceof Error ? rejection.message : rejection, '; Zone:',
 | |
|             (<Zone>e.zone).name, '; Task:', e.task && (<Task>e.task).source, '; Value:', rejection,
 | |
|             rejection instanceof Error ? rejection.stack : undefined);
 | |
|       } else {
 | |
|         console.error(e);
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   api.microtaskDrainDone = () => {
 | |
|     while (_uncaughtPromiseErrors.length) {
 | |
|       while (_uncaughtPromiseErrors.length) {
 | |
|         const uncaughtPromiseError: UncaughtPromiseError = _uncaughtPromiseErrors.shift() !;
 | |
|         try {
 | |
|           uncaughtPromiseError.zone.runGuarded(() => { throw uncaughtPromiseError; });
 | |
|         } catch (error) {
 | |
|           handleUnhandledRejection(error);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   const UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL = __symbol__('unhandledPromiseRejectionHandler');
 | |
| 
 | |
|   function handleUnhandledRejection(this: unknown, e: any) {
 | |
|     api.onUnhandledError(e);
 | |
|     try {
 | |
|       const handler = (Zone as any)[UNHANDLED_PROMISE_REJECTION_HANDLER_SYMBOL];
 | |
|       if (handler && typeof handler === 'function') {
 | |
|         handler.call(this, e);
 | |
|       }
 | |
|     } catch (err) {
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function isThenable(value: any): boolean { return value && value.then; }
 | |
| 
 | |
|   function forwardResolution(value: any): any { return value; }
 | |
| 
 | |
|   function forwardRejection(rejection: any): any { return ZoneAwarePromise.reject(rejection); }
 | |
| 
 | |
|   const symbolState: string = __symbol__('state');
 | |
|   const symbolValue: string = __symbol__('value');
 | |
|   const symbolFinally: string = __symbol__('finally');
 | |
|   const symbolParentPromiseValue: string = __symbol__('parentPromiseValue');
 | |
|   const symbolParentPromiseState: string = __symbol__('parentPromiseState');
 | |
|   const source: string = 'Promise.then';
 | |
|   const UNRESOLVED: null = null;
 | |
|   const RESOLVED = true;
 | |
|   const REJECTED = false;
 | |
|   const REJECTED_NO_CATCH = 0;
 | |
| 
 | |
|   function makeResolver(promise: ZoneAwarePromise<any>, state: boolean): (value: any) => void {
 | |
|     return (v) => {
 | |
|       try {
 | |
|         resolvePromise(promise, state, v);
 | |
|       } catch (err) {
 | |
|         resolvePromise(promise, false, err);
 | |
|       }
 | |
|       // Do not return value or you will break the Promise spec.
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   const once = function() {
 | |
|     let wasCalled = false;
 | |
| 
 | |
|     return function wrapper(wrappedFunction: Function) {
 | |
|       return function() {
 | |
|         if (wasCalled) {
 | |
|           return;
 | |
|         }
 | |
|         wasCalled = true;
 | |
|         wrappedFunction.apply(null, arguments);
 | |
|       };
 | |
|     };
 | |
|   };
 | |
| 
 | |
|   const TYPE_ERROR = 'Promise resolved with itself';
 | |
|   const CURRENT_TASK_TRACE_SYMBOL = __symbol__('currentTaskTrace');
 | |
| 
 | |
|   // Promise Resolution
 | |
|   function resolvePromise(
 | |
|       promise: ZoneAwarePromise<any>, state: boolean, value: any): ZoneAwarePromise<any> {
 | |
|     const onceWrapper = once();
 | |
|     if (promise === value) {
 | |
|       throw new TypeError(TYPE_ERROR);
 | |
|     }
 | |
|     if ((promise as any)[symbolState] === UNRESOLVED) {
 | |
|       // should only get value.then once based on promise spec.
 | |
|       let then: any = null;
 | |
|       try {
 | |
|         if (typeof value === 'object' || typeof value === 'function') {
 | |
|           then = value && value.then;
 | |
|         }
 | |
|       } catch (err) {
 | |
|         onceWrapper(() => { resolvePromise(promise, false, err); })();
 | |
|         return promise;
 | |
|       }
 | |
|       // if (value instanceof ZoneAwarePromise) {
 | |
|       if (state !== REJECTED && value instanceof ZoneAwarePromise &&
 | |
|           value.hasOwnProperty(symbolState) && value.hasOwnProperty(symbolValue) &&
 | |
|           (value as any)[symbolState] !== UNRESOLVED) {
 | |
|         clearRejectedNoCatch(value);
 | |
|         resolvePromise(promise, (value as any)[symbolState], (value as any)[symbolValue]);
 | |
|       } else if (state !== REJECTED && typeof then === 'function') {
 | |
|         try {
 | |
|           then.call(
 | |
|               value, onceWrapper(makeResolver(promise, state)),
 | |
|               onceWrapper(makeResolver(promise, false)));
 | |
|         } catch (err) {
 | |
|           onceWrapper(() => { resolvePromise(promise, false, err); })();
 | |
|         }
 | |
|       } else {
 | |
|         (promise as any)[symbolState] = state;
 | |
|         const queue = (promise as any)[symbolValue];
 | |
|         (promise as any)[symbolValue] = value;
 | |
| 
 | |
|         if ((promise as any)[symbolFinally] === symbolFinally) {
 | |
|           // the promise is generated by Promise.prototype.finally
 | |
|           if (state === RESOLVED) {
 | |
|             // the state is resolved, should ignore the value
 | |
|             // and use parent promise value
 | |
|             (promise as any)[symbolState] = (promise as any)[symbolParentPromiseState];
 | |
|             (promise as any)[symbolValue] = (promise as any)[symbolParentPromiseValue];
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         // record task information in value when error occurs, so we can
 | |
|         // do some additional work such as render longStackTrace
 | |
|         if (state === REJECTED && value instanceof Error) {
 | |
|           // check if longStackTraceZone is here
 | |
|           const trace = Zone.currentTask && Zone.currentTask.data &&
 | |
|               (Zone.currentTask.data as any)[creationTrace];
 | |
|           if (trace) {
 | |
|             // only keep the long stack trace into error when in longStackTraceZone
 | |
|             ObjectDefineProperty(
 | |
|                 value, CURRENT_TASK_TRACE_SYMBOL,
 | |
|                 {configurable: true, enumerable: false, writable: true, value: trace});
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         for (let i = 0; i < queue.length;) {
 | |
|           scheduleResolveOrReject(promise, queue[i++], queue[i++], queue[i++], queue[i++]);
 | |
|         }
 | |
|         if (queue.length == 0 && state == REJECTED) {
 | |
|           (promise as any)[symbolState] = REJECTED_NO_CATCH;
 | |
|           try {
 | |
|             // try to print more readable error log
 | |
|             throw new Error(
 | |
|                 'Uncaught (in promise): ' + readableObjectToString(value) +
 | |
|                 (value && value.stack ? '\n' + value.stack : ''));
 | |
|           } catch (err) {
 | |
|             const error: UncaughtPromiseError = err;
 | |
|             error.rejection = value;
 | |
|             error.promise = promise;
 | |
|             error.zone = Zone.current;
 | |
|             error.task = Zone.currentTask !;
 | |
|             _uncaughtPromiseErrors.push(error);
 | |
|             api.scheduleMicroTask();  // to make sure that it is running
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|     // Resolving an already resolved promise is a noop.
 | |
|     return promise;
 | |
|   }
 | |
| 
 | |
|   const REJECTION_HANDLED_HANDLER = __symbol__('rejectionHandledHandler');
 | |
|   function clearRejectedNoCatch(this: unknown, promise: ZoneAwarePromise<any>): void {
 | |
|     if ((promise as any)[symbolState] === REJECTED_NO_CATCH) {
 | |
|       // if the promise is rejected no catch status
 | |
|       // and queue.length > 0, means there is a error handler
 | |
|       // here to handle the rejected promise, we should trigger
 | |
|       // windows.rejectionhandled eventHandler or nodejs rejectionHandled
 | |
|       // eventHandler
 | |
|       try {
 | |
|         const handler = (Zone as any)[REJECTION_HANDLED_HANDLER];
 | |
|         if (handler && typeof handler === 'function') {
 | |
|           handler.call(this, {rejection: (promise as any)[symbolValue], promise: promise});
 | |
|         }
 | |
|       } catch (err) {
 | |
|       }
 | |
|       (promise as any)[symbolState] = REJECTED;
 | |
|       for (let i = 0; i < _uncaughtPromiseErrors.length; i++) {
 | |
|         if (promise === _uncaughtPromiseErrors[i].promise) {
 | |
|           _uncaughtPromiseErrors.splice(i, 1);
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   function scheduleResolveOrReject<R, U1, U2>(
 | |
|       promise: ZoneAwarePromise<any>, zone: Zone, chainPromise: ZoneAwarePromise<any>,
 | |
|       onFulfilled?: ((value: R) => U1) | null | undefined,
 | |
|       onRejected?: ((error: any) => U2) | null | undefined): void {
 | |
|     clearRejectedNoCatch(promise);
 | |
|     const promiseState = (promise as any)[symbolState];
 | |
|     const delegate = promiseState ?
 | |
|         (typeof onFulfilled === 'function') ? onFulfilled : forwardResolution :
 | |
|         (typeof onRejected === 'function') ? onRejected : forwardRejection;
 | |
|     zone.scheduleMicroTask(source, () => {
 | |
|       try {
 | |
|         const parentPromiseValue = (promise as any)[symbolValue];
 | |
|         const isFinallyPromise =
 | |
|             !!chainPromise && symbolFinally === (chainPromise as any)[symbolFinally];
 | |
|         if (isFinallyPromise) {
 | |
|           // if the promise is generated from finally call, keep parent promise's state and value
 | |
|           (chainPromise as any)[symbolParentPromiseValue] = parentPromiseValue;
 | |
|           (chainPromise as any)[symbolParentPromiseState] = promiseState;
 | |
|         }
 | |
|         // should not pass value to finally callback
 | |
|         const value = zone.run(
 | |
|             delegate, undefined,
 | |
|             isFinallyPromise && delegate !== forwardRejection && delegate !== forwardResolution ?
 | |
|                 [] :
 | |
|                 [parentPromiseValue]);
 | |
|         resolvePromise(chainPromise, true, value);
 | |
|       } catch (error) {
 | |
|         // if error occurs, should always return this error
 | |
|         resolvePromise(chainPromise, false, error);
 | |
|       }
 | |
|     }, chainPromise as TaskData);
 | |
|   }
 | |
| 
 | |
|   const ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }';
 | |
| 
 | |
|   class ZoneAwarePromise<R> implements Promise<R> {
 | |
|     static toString() { return ZONE_AWARE_PROMISE_TO_STRING; }
 | |
| 
 | |
|     static resolve<R>(value: R): Promise<R> {
 | |
|       return resolvePromise(<ZoneAwarePromise<R>>new this(null as any), RESOLVED, value);
 | |
|     }
 | |
| 
 | |
|     static reject<U>(error: U): Promise<U> {
 | |
|       return resolvePromise(<ZoneAwarePromise<U>>new this(null as any), REJECTED, error);
 | |
|     }
 | |
| 
 | |
|     static race<R>(values: PromiseLike<any>[]): Promise<R> {
 | |
|       let resolve: (v: any) => void;
 | |
|       let reject: (v: any) => void;
 | |
|       let promise: any = new this((res, rej) => {
 | |
|         resolve = res;
 | |
|         reject = rej;
 | |
|       });
 | |
|       function onResolve(value: any) { resolve(value); }
 | |
|       function onReject(error: any) { reject(error); }
 | |
| 
 | |
|       for (let value of values) {
 | |
|         if (!isThenable(value)) {
 | |
|           value = this.resolve(value);
 | |
|         }
 | |
|         value.then(onResolve, onReject);
 | |
|       }
 | |
|       return promise;
 | |
|     }
 | |
| 
 | |
|     static all<R>(values: any): Promise<R> { return ZoneAwarePromise.allWithCallback(values); }
 | |
| 
 | |
|     static allSettled<R>(values: any): Promise<R> {
 | |
|       const P = this && this.prototype instanceof ZoneAwarePromise ? this : ZoneAwarePromise;
 | |
|       return P.allWithCallback(values, {
 | |
|         thenCallback: (value: any) => ({status: 'fulfilled', value}),
 | |
|         errorCallback: (err: any) => ({status: 'rejected', reason: err})
 | |
|       });
 | |
|     }
 | |
| 
 | |
|     static allWithCallback<R>(values: any, callback?: {
 | |
|       thenCallback: (value: any) => any,
 | |
|       errorCallback: (err: any) => any
 | |
|     }): Promise<R> {
 | |
|       let resolve: (v: any) => void;
 | |
|       let reject: (v: any) => void;
 | |
|       let promise = new this<R>((res, rej) => {
 | |
|         resolve = res;
 | |
|         reject = rej;
 | |
|       });
 | |
| 
 | |
|       // Start at 2 to prevent prematurely resolving if .then is called immediately.
 | |
|       let unresolvedCount = 2;
 | |
|       let valueIndex = 0;
 | |
| 
 | |
|       const resolvedValues: any[] = [];
 | |
|       for (let value of values) {
 | |
|         if (!isThenable(value)) {
 | |
|           value = this.resolve(value);
 | |
|         }
 | |
| 
 | |
|         const curValueIndex = valueIndex;
 | |
|         try {
 | |
|           value.then(
 | |
|               (value: any) => {
 | |
|                 resolvedValues[curValueIndex] = callback ? callback.thenCallback(value) : value;
 | |
|                 unresolvedCount--;
 | |
|                 if (unresolvedCount === 0) {
 | |
|                   resolve !(resolvedValues);
 | |
|                 }
 | |
|               },
 | |
|               (err: any) => {
 | |
|                 if (!callback) {
 | |
|                   reject !(err);
 | |
|                 } else {
 | |
|                   resolvedValues[curValueIndex] = callback.errorCallback(err);
 | |
|                   unresolvedCount--;
 | |
|                   if (unresolvedCount === 0) {
 | |
|                     resolve !(resolvedValues);
 | |
|                   }
 | |
|                 }
 | |
|               });
 | |
|         } catch (thenErr) {
 | |
|           reject !(thenErr);
 | |
|         }
 | |
| 
 | |
|         unresolvedCount++;
 | |
|         valueIndex++;
 | |
|       }
 | |
| 
 | |
|       // Make the unresolvedCount zero-based again.
 | |
|       unresolvedCount -= 2;
 | |
| 
 | |
|       if (unresolvedCount === 0) {
 | |
|         resolve !(resolvedValues);
 | |
|       }
 | |
| 
 | |
|       return promise;
 | |
|     }
 | |
| 
 | |
|     constructor(
 | |
|         executor:
 | |
|             (resolve: (value?: R|PromiseLike<R>) => void, reject: (error?: any) => void) => void) {
 | |
|       const promise: ZoneAwarePromise<R> = this;
 | |
|       if (!(promise instanceof ZoneAwarePromise)) {
 | |
|         throw new Error('Must be an instanceof Promise.');
 | |
|       }
 | |
|       (promise as any)[symbolState] = UNRESOLVED;
 | |
|       (promise as any)[symbolValue] = [];  // queue;
 | |
|       try {
 | |
|         executor && executor(makeResolver(promise, RESOLVED), makeResolver(promise, REJECTED));
 | |
|       } catch (error) {
 | |
|         resolvePromise(promise, false, error);
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     get[Symbol.toStringTag]() { return 'Promise' as any; }
 | |
| 
 | |
|     then<TResult1 = R, TResult2 = never>(
 | |
|         onFulfilled?: ((value: R) => TResult1 | PromiseLike<TResult1>)|undefined|null,
 | |
|         onRejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>)|undefined|
 | |
|         null): Promise<TResult1|TResult2> {
 | |
|       const chainPromise: Promise<TResult1|TResult2> =
 | |
|           new (this.constructor as typeof ZoneAwarePromise)(null as any);
 | |
|       const zone = Zone.current;
 | |
|       if ((this as any)[symbolState] == UNRESOLVED) {
 | |
|         (<any[]>(this as any)[symbolValue]).push(zone, chainPromise, onFulfilled, onRejected);
 | |
|       } else {
 | |
|         scheduleResolveOrReject(this, zone, chainPromise as any, onFulfilled, onRejected);
 | |
|       }
 | |
|       return chainPromise;
 | |
|     }
 | |
| 
 | |
|     catch<TResult = never>(onRejected?: ((reason: any) => TResult | PromiseLike<TResult>)|undefined|
 | |
|                            null): Promise<R|TResult> {
 | |
|       return this.then(null, onRejected);
 | |
|     }
 | |
| 
 | |
|     finally<U>(onFinally?: () => U | PromiseLike<U>): Promise<R> {
 | |
|       const chainPromise: Promise<R|never> =
 | |
|           new (this.constructor as typeof ZoneAwarePromise)(null as any);
 | |
|       (chainPromise as any)[symbolFinally] = symbolFinally;
 | |
|       const zone = Zone.current;
 | |
|       if ((this as any)[symbolState] == UNRESOLVED) {
 | |
|         (<any[]>(this as any)[symbolValue]).push(zone, chainPromise, onFinally, onFinally);
 | |
|       } else {
 | |
|         scheduleResolveOrReject(this, zone, chainPromise as any, onFinally, onFinally);
 | |
|       }
 | |
|       return chainPromise;
 | |
|     }
 | |
|   }
 | |
|   // Protect against aggressive optimizers dropping seemingly unused properties.
 | |
|   // E.g. Closure Compiler in advanced mode.
 | |
|   ZoneAwarePromise['resolve'] = ZoneAwarePromise.resolve;
 | |
|   ZoneAwarePromise['reject'] = ZoneAwarePromise.reject;
 | |
|   ZoneAwarePromise['race'] = ZoneAwarePromise.race;
 | |
|   ZoneAwarePromise['all'] = ZoneAwarePromise.all;
 | |
| 
 | |
|   const NativePromise = global[symbolPromise] = global['Promise'];
 | |
|   const ZONE_AWARE_PROMISE = Zone.__symbol__('ZoneAwarePromise');
 | |
| 
 | |
|   let desc = ObjectGetOwnPropertyDescriptor(global, 'Promise');
 | |
|   if (!desc || desc.configurable) {
 | |
|     desc && delete desc.writable;
 | |
|     desc && delete desc.value;
 | |
|     if (!desc) {
 | |
|       desc = {configurable: true, enumerable: true};
 | |
|     }
 | |
|     desc.get = function() {
 | |
|       // if we already set ZoneAwarePromise, use patched one
 | |
|       // otherwise return native one.
 | |
|       return global[ZONE_AWARE_PROMISE] ? global[ZONE_AWARE_PROMISE] : global[symbolPromise];
 | |
|     };
 | |
|     desc.set = function(NewNativePromise) {
 | |
|       if (NewNativePromise === ZoneAwarePromise) {
 | |
|         // if the NewNativePromise is ZoneAwarePromise
 | |
|         // save to global
 | |
|         global[ZONE_AWARE_PROMISE] = NewNativePromise;
 | |
|       } else {
 | |
|         // if the NewNativePromise is not ZoneAwarePromise
 | |
|         // for example: after load zone.js, some library just
 | |
|         // set es6-promise to global, if we set it to global
 | |
|         // directly, assertZonePatched will fail and angular
 | |
|         // will not loaded, so we just set the NewNativePromise
 | |
|         // to global[symbolPromise], so the result is just like
 | |
|         // we load ES6 Promise before zone.js
 | |
|         global[symbolPromise] = NewNativePromise;
 | |
|         if (!NewNativePromise.prototype[symbolThen]) {
 | |
|           patchThen(NewNativePromise);
 | |
|         }
 | |
|         api.setNativePromise(NewNativePromise);
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     ObjectDefineProperty(global, 'Promise', desc);
 | |
|   }
 | |
| 
 | |
|   global['Promise'] = ZoneAwarePromise;
 | |
| 
 | |
|   const symbolThenPatched = __symbol__('thenPatched');
 | |
| 
 | |
|   function patchThen(Ctor: Function) {
 | |
|     const proto = Ctor.prototype;
 | |
| 
 | |
|     const prop = ObjectGetOwnPropertyDescriptor(proto, 'then');
 | |
|     if (prop && (prop.writable === false || !prop.configurable)) {
 | |
|       // check Ctor.prototype.then propertyDescriptor is writable or not
 | |
|       // in meteor env, writable is false, we should ignore such case
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     const originalThen = proto.then;
 | |
|     // Keep a reference to the original method.
 | |
|     proto[symbolThen] = originalThen;
 | |
| 
 | |
|     Ctor.prototype.then = function(onResolve: any, onReject: any) {
 | |
|       const wrapped =
 | |
|           new ZoneAwarePromise((resolve, reject) => { originalThen.call(this, resolve, reject); });
 | |
|       return wrapped.then(onResolve, onReject);
 | |
|     };
 | |
|     (Ctor as any)[symbolThenPatched] = true;
 | |
|   }
 | |
| 
 | |
|   api.patchThen = patchThen;
 | |
| 
 | |
|   function zoneify(fn: Function) {
 | |
|     return function(this: unknown) {
 | |
|       let resultPromise = fn.apply(this, arguments);
 | |
|       if (resultPromise instanceof ZoneAwarePromise) {
 | |
|         return resultPromise;
 | |
|       }
 | |
|       let ctor = resultPromise.constructor;
 | |
|       if (!ctor[symbolThenPatched]) {
 | |
|         patchThen(ctor);
 | |
|       }
 | |
|       return resultPromise;
 | |
|     };
 | |
|   }
 | |
| 
 | |
|   if (NativePromise) {
 | |
|     patchThen(NativePromise);
 | |
|     const fetch = global['fetch'];
 | |
|     if (typeof fetch == 'function') {
 | |
|       global[api.symbol('fetch')] = fetch;
 | |
|       global['fetch'] = zoneify(fetch);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   // This is not part of public API, but it is useful for tests, so we expose it.
 | |
|   (Promise as any)[Zone.__symbol__('uncaughtPromiseErrors')] = _uncaughtPromiseErrors;
 | |
|   return ZoneAwarePromise;
 | |
| });
 |