fix: implement Symbol.specics of Promise (#34162)
Close #34105, #33989 PR Close #34162
This commit is contained in:
		
							parent
							
								
									6b1a47183d
								
							
						
					
					
						commit
						539d8f09e0
					
				| @ -256,6 +256,8 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr | ||||
| 
 | ||||
|   const ZONE_AWARE_PROMISE_TO_STRING = 'function ZoneAwarePromise() { [native code] }'; | ||||
| 
 | ||||
|   const noop = function() {}; | ||||
| 
 | ||||
|   class ZoneAwarePromise<R> implements Promise<R> { | ||||
|     static toString() { return ZONE_AWARE_PROMISE_TO_STRING; } | ||||
| 
 | ||||
| @ -374,12 +376,17 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr | ||||
| 
 | ||||
|     get[Symbol.toStringTag]() { return 'Promise' as any; } | ||||
| 
 | ||||
|     get[Symbol.species]() { return ZoneAwarePromise; } | ||||
| 
 | ||||
|     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); | ||||
|       let C = (this.constructor as any)[Symbol.species]; | ||||
|       if (!C || typeof C !== 'function') { | ||||
|         C = ZoneAwarePromise; | ||||
|       } | ||||
|       const chainPromise: Promise<TResult1|TResult2> = new (C as typeof ZoneAwarePromise)(noop); | ||||
|       const zone = Zone.current; | ||||
|       if ((this as any)[symbolState] == UNRESOLVED) { | ||||
|         (<any[]>(this as any)[symbolValue]).push(zone, chainPromise, onFulfilled, onRejected); | ||||
| @ -395,8 +402,11 @@ Zone.__load_patch('ZoneAwarePromise', (global: any, Zone: ZoneType, api: _ZonePr | ||||
|     } | ||||
| 
 | ||||
|     finally<U>(onFinally?: () => U | PromiseLike<U>): Promise<R> { | ||||
|       const chainPromise: Promise<R|never> = | ||||
|           new (this.constructor as typeof ZoneAwarePromise)(null as any); | ||||
|       let C = (this.constructor as any)[Symbol.species]; | ||||
|       if (!C || typeof C !== 'function') { | ||||
|         C = ZoneAwarePromise; | ||||
|       } | ||||
|       const chainPromise: Promise<R|never> = new (C as typeof ZoneAwarePromise)(noop); | ||||
|       (chainPromise as any)[symbolFinally] = symbolFinally; | ||||
|       const zone = Zone.current; | ||||
|       if ((this as any)[symbolState] == UNRESOLVED) { | ||||
|  | ||||
| @ -103,11 +103,21 @@ describe( | ||||
|         }).toThrowError('Must be an instanceof Promise.'); | ||||
|       }); | ||||
| 
 | ||||
|       xit('should allow subclassing', () => { | ||||
|       it('should allow subclassing with Promise.specices', () => { | ||||
|         class MyPromise extends Promise<any> { | ||||
|           constructor(fn: any) { super(fn); } | ||||
| 
 | ||||
|           static get[Symbol.species]() { return MyPromise; } | ||||
|         } | ||||
|         expect(new MyPromise(null).then(() => null) instanceof MyPromise).toBe(true); | ||||
|         expect(new MyPromise(() => {}).then(() => null) instanceof MyPromise).toBe(true); | ||||
|       }); | ||||
| 
 | ||||
|       it('Promise.specices should return ZoneAwarePromise', () => { | ||||
|         const empty = function() {}; | ||||
|         const promise = Promise.resolve(1); | ||||
|         const FakePromise = ((promise.constructor = {} as any) as any)[Symbol.species] = function( | ||||
|             exec: any) { exec(empty, empty); }; | ||||
|         expect(promise.then(empty) instanceof FakePromise).toBe(true); | ||||
|       }); | ||||
| 
 | ||||
|       it('should intercept scheduling of resolution and then', (done) => { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user