@@ -15,168 +15,184 @@ import {eventTargetPatch} from './event-target';
1515import { propertyDescriptorPatch } from './property-descriptor' ;
1616import { registerElementPatch } from './register-element' ;
1717
18- const set = 'set' ;
19- const clear = 'clear' ;
20- const blockingMethods = [ 'alert' , 'prompt' , 'confirm' ] ;
21- const _global : any =
22- typeof window !== 'undefined' && window || typeof self !== 'undefined' && self || global ;
23-
24- patchTimer ( _global , set , clear , 'Timeout' ) ;
25- patchTimer ( _global , set , clear , 'Interval' ) ;
26- patchTimer ( _global , set , clear , 'Immediate' ) ;
27- patchTimer ( _global , 'request' , 'cancel' , 'AnimationFrame' ) ;
28- patchTimer ( _global , 'mozRequest' , 'mozCancel' , 'AnimationFrame' ) ;
29- patchTimer ( _global , 'webkitRequest' , 'webkitCancel' , 'AnimationFrame' ) ;
30-
31- for ( let i = 0 ; i < blockingMethods . length ; i ++ ) {
32- const name = blockingMethods [ i ] ;
33- patchMethod ( _global , name , ( delegate , symbol , name ) => {
34- return function ( s : any , args : any [ ] ) {
35- return Zone . current . run ( delegate , _global , args , name ) ;
36- } ;
37- } ) ;
38- }
39-
40- eventTargetPatch ( _global ) ;
41- // patch XMLHttpRequestEventTarget's addEventListener/removeEventListener
42- const XMLHttpRequestEventTarget = ( _global as any ) [ 'XMLHttpRequestEventTarget' ] ;
43- if ( XMLHttpRequestEventTarget && XMLHttpRequestEventTarget . prototype ) {
44- patchEventTargetMethods ( XMLHttpRequestEventTarget . prototype ) ;
45- }
46- propertyDescriptorPatch ( _global ) ;
47- patchClass ( 'MutationObserver' ) ;
48- patchClass ( 'WebKitMutationObserver' ) ;
49- patchClass ( 'FileReader' ) ;
50- propertyPatch ( ) ;
51- registerElementPatch ( _global ) ;
52-
53- // Treat XMLHTTPRequest as a macrotask.
54- patchXHR ( _global ) ;
55-
56- const XHR_TASK = zoneSymbol ( 'xhrTask' ) ;
57- const XHR_SYNC = zoneSymbol ( 'xhrSync' ) ;
58- const XHR_LISTENER = zoneSymbol ( 'xhrListener' ) ;
59- const XHR_SCHEDULED = zoneSymbol ( 'xhrScheduled' ) ;
60-
61- interface XHROptions extends TaskData {
62- target : any ;
63- args : any [ ] ;
64- aborted : boolean ;
65- }
66-
67- function patchXHR ( window : any ) {
68- function findPendingTask ( target : any ) {
69- const pendingTask : Task = target [ XHR_TASK ] ;
70- return pendingTask ;
18+ Zone . __load_patch ( 'timers' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
19+ const set = 'set' ;
20+ const clear = 'clear' ;
21+ patchTimer ( global , set , clear , 'Timeout' ) ;
22+ patchTimer ( global , set , clear , 'Interval' ) ;
23+ patchTimer ( global , set , clear , 'Immediate' ) ;
24+ patchTimer ( global , 'request' , 'cancel' , 'AnimationFrame' ) ;
25+ patchTimer ( global , 'mozRequest' , 'mozCancel' , 'AnimationFrame' ) ;
26+ patchTimer ( global , 'webkitRequest' , 'webkitCancel' , 'AnimationFrame' ) ;
27+ } ) ;
28+
29+ Zone . __load_patch ( 'blocking' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
30+ const blockingMethods = [ 'alert' , 'prompt' , 'confirm' ] ;
31+ for ( let i = 0 ; i < blockingMethods . length ; i ++ ) {
32+ const name = blockingMethods [ i ] ;
33+ patchMethod ( global , name , ( delegate , symbol , name ) => {
34+ return function ( s : any , args : any [ ] ) {
35+ return Zone . current . run ( delegate , global , args , name ) ;
36+ } ;
37+ } ) ;
38+ }
39+ } ) ;
40+
41+ Zone . __load_patch ( 'EventTarget' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
42+ eventTargetPatch ( global ) ;
43+ // patch XMLHttpRequestEventTarget's addEventListener/removeEventListener
44+ const XMLHttpRequestEventTarget = ( global as any ) [ 'XMLHttpRequestEventTarget' ] ;
45+ if ( XMLHttpRequestEventTarget && XMLHttpRequestEventTarget . prototype ) {
46+ patchEventTargetMethods ( XMLHttpRequestEventTarget . prototype ) ;
47+ }
48+ patchClass ( 'MutationObserver' ) ;
49+ patchClass ( 'WebKitMutationObserver' ) ;
50+ patchClass ( 'FileReader' ) ;
51+ } ) ;
52+
53+ Zone . __load_patch ( 'on_property' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
54+ propertyDescriptorPatch ( global ) ;
55+ propertyPatch ( ) ;
56+ registerElementPatch ( global ) ;
57+ } ) ;
58+
59+ Zone . __load_patch ( 'XHR' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
60+ // Treat XMLHTTPRequest as a macrotask.
61+ patchXHR ( global ) ;
62+
63+ const XHR_TASK = zoneSymbol ( 'xhrTask' ) ;
64+ const XHR_SYNC = zoneSymbol ( 'xhrSync' ) ;
65+ const XHR_LISTENER = zoneSymbol ( 'xhrListener' ) ;
66+ const XHR_SCHEDULED = zoneSymbol ( 'xhrScheduled' ) ;
67+
68+ interface XHROptions extends TaskData {
69+ target : any ;
70+ args : any [ ] ;
71+ aborted : boolean ;
7172 }
7273
73- function scheduleTask ( task : Task ) {
74- ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] = false ;
75- const data = < XHROptions > task . data ;
76- // remove existing event listener
77- const listener = data . target [ XHR_LISTENER ] ;
78- if ( listener ) {
79- data . target . removeEventListener ( 'readystatechange' , listener ) ;
74+ function patchXHR ( window : any ) {
75+ function findPendingTask ( target : any ) {
76+ const pendingTask : Task = target [ XHR_TASK ] ;
77+ return pendingTask ;
8078 }
81- const newListener = data . target [ XHR_LISTENER ] = ( ) => {
82- if ( data . target . readyState === data . target . DONE ) {
83- // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
84- // readyState=4 multiple times, so we need to check task state here
85- if ( ! data . aborted && ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] && task . state === 'scheduled' ) {
86- task . invoke ( ) ;
87- }
79+
80+ function scheduleTask ( task : Task ) {
81+ ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] = false ;
82+ const data = < XHROptions > task . data ;
83+ // remove existing event listener
84+ const listener = data . target [ XHR_LISTENER ] ;
85+ if ( listener ) {
86+ data . target . removeEventListener ( 'readystatechange' , listener ) ;
8887 }
89- } ;
90- data . target . addEventListener ( 'readystatechange' , newListener ) ;
88+ const newListener = data . target [ XHR_LISTENER ] = ( ) => {
89+ if ( data . target . readyState === data . target . DONE ) {
90+ // sometimes on some browsers XMLHttpRequest will fire onreadystatechange with
91+ // readyState=4 multiple times, so we need to check task state here
92+ if ( ! data . aborted && ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] &&
93+ task . state === 'scheduled' ) {
94+ task . invoke ( ) ;
95+ }
96+ }
97+ } ;
98+ data . target . addEventListener ( 'readystatechange' , newListener ) ;
9199
92- const storedTask : Task = data . target [ XHR_TASK ] ;
93- if ( ! storedTask ) {
94- data . target [ XHR_TASK ] = task ;
100+ const storedTask : Task = data . target [ XHR_TASK ] ;
101+ if ( ! storedTask ) {
102+ data . target [ XHR_TASK ] = task ;
103+ }
104+ sendNative . apply ( data . target , data . args ) ;
105+ ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] = true ;
106+ return task ;
95107 }
96- sendNative . apply ( data . target , data . args ) ;
97- ( XMLHttpRequest as any ) [ XHR_SCHEDULED ] = true ;
98- return task ;
99- }
100108
101- function placeholderCallback ( ) { }
109+ function placeholderCallback ( ) { }
102110
103- function clearTask ( task : Task ) {
104- const data = < XHROptions > task . data ;
105- // Note - ideally, we would call data.target.removeEventListener here, but it's too late
106- // to prevent it from firing. So instead, we store info for the event listener.
107- data . aborted = true ;
108- return abortNative . apply ( data . target , data . args ) ;
109- }
110-
111- const openNative : Function =
112- patchMethod ( window . XMLHttpRequest . prototype , 'open' , ( ) => function ( self : any , args : any [ ] ) {
113- self [ XHR_SYNC ] = args [ 2 ] == false ;
114- return openNative . apply ( self , args ) ;
115- } ) ;
116-
117- const sendNative : Function =
118- patchMethod ( window . XMLHttpRequest . prototype , 'send' , ( ) => function ( self : any , args : any [ ] ) {
119- const zone = Zone . current ;
120- if ( self [ XHR_SYNC ] ) {
121- // if the XHR is sync there is no task to schedule, just execute the code.
122- return sendNative . apply ( self , args ) ;
123- } else {
124- const options : XHROptions =
125- { target : self , isPeriodic : false , delay : null , args : args , aborted : false } ;
126- return zone . scheduleMacroTask (
127- 'XMLHttpRequest.send' , placeholderCallback , options , scheduleTask , clearTask ) ;
128- }
129- } ) ;
111+ function clearTask ( task : Task ) {
112+ const data = < XHROptions > task . data ;
113+ // Note - ideally, we would call data.target.removeEventListener here, but it's too late
114+ // to prevent it from firing. So instead, we store info for the event listener.
115+ data . aborted = true ;
116+ return abortNative . apply ( data . target , data . args ) ;
117+ }
130118
131- const abortNative = patchMethod (
132- window . XMLHttpRequest . prototype , 'abort' ,
133- ( delegate : Function ) => function ( self : any , args : any [ ] ) {
134- const task : Task = findPendingTask ( self ) ;
135- if ( task && typeof task . type == 'string' ) {
136- // If the XHR has already completed, do nothing.
137- // If the XHR has already been aborted, do nothing.
138- // Fix #569, call abort multiple times before done will cause
139- // macroTask task count be negative number
140- if ( task . cancelFn == null || ( task . data && ( < XHROptions > task . data ) . aborted ) ) {
141- return ;
119+ const openNative : Function = patchMethod (
120+ window . XMLHttpRequest . prototype , 'open' , ( ) => function ( self : any , args : any [ ] ) {
121+ self [ XHR_SYNC ] = args [ 2 ] == false ;
122+ return openNative . apply ( self , args ) ;
123+ } ) ;
124+
125+ const sendNative : Function = patchMethod (
126+ window . XMLHttpRequest . prototype , 'send' , ( ) => function ( self : any , args : any [ ] ) {
127+ const zone = Zone . current ;
128+ if ( self [ XHR_SYNC ] ) {
129+ // if the XHR is sync there is no task to schedule, just execute the code.
130+ return sendNative . apply ( self , args ) ;
131+ } else {
132+ const options : XHROptions =
133+ { target : self , isPeriodic : false , delay : null , args : args , aborted : false } ;
134+ return zone . scheduleMacroTask (
135+ 'XMLHttpRequest.send' , placeholderCallback , options , scheduleTask , clearTask ) ;
142136 }
143- task . zone . cancelTask ( task ) ;
137+ } ) ;
138+
139+ const abortNative = patchMethod (
140+ window . XMLHttpRequest . prototype , 'abort' ,
141+ ( delegate : Function ) => function ( self : any , args : any [ ] ) {
142+ const task : Task = findPendingTask ( self ) ;
143+ if ( task && typeof task . type == 'string' ) {
144+ // If the XHR has already completed, do nothing.
145+ // If the XHR has already been aborted, do nothing.
146+ // Fix #569, call abort multiple times before done will cause
147+ // macroTask task count be negative number
148+ if ( task . cancelFn == null || ( task . data && ( < XHROptions > task . data ) . aborted ) ) {
149+ return ;
150+ }
151+ task . zone . cancelTask ( task ) ;
152+ }
153+ // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no
154+ // task
155+ // to cancel. Do nothing.
156+ } ) ;
157+ }
158+ } ) ;
159+
160+ Zone . __load_patch ( 'geo' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
161+ /// GEO_LOCATION
162+ if ( global [ 'navigator' ] && global [ 'navigator' ] . geolocation ) {
163+ patchPrototype ( global [ 'navigator' ] . geolocation , [ 'getCurrentPosition' , 'watchPosition' ] ) ;
164+ }
165+ } ) ;
166+
167+ Zone . __load_patch ( 'toString' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
168+ // patch Func.prototype.toString to let them look like native
169+ patchFuncToString ( ) ;
170+ // patch Object.prototype.toString to let them look like native
171+ patchObjectToString ( ) ;
172+ } ) ;
173+
174+ Zone . __load_patch ( 'promiseRejectionHandler' , ( global : any , Zone : ZoneType , api : _ZonePrivate ) => {
175+ // handle unhandled promise rejection
176+ function findPromiseRejectionHandler ( evtName : string ) {
177+ return function ( e : any ) {
178+ const eventTasks = findEventTask ( global , evtName ) ;
179+ eventTasks . forEach ( eventTask => {
180+ // windows has added unhandledrejection event listener
181+ // trigger the event listener
182+ const PromiseRejectionEvent = global [ 'PromiseRejectionEvent' ] ;
183+ if ( PromiseRejectionEvent ) {
184+ const evt = new PromiseRejectionEvent ( evtName , { promise : e . promise , reason : e . rejection } ) ;
185+ eventTask . invoke ( evt ) ;
144186 }
145- // Otherwise, we are trying to abort an XHR which has not yet been sent, so there is no task
146- // to cancel. Do nothing.
147187 } ) ;
148- }
149-
150- /// GEO_LOCATION
151- if ( _global [ 'navigator' ] && _global [ 'navigator' ] . geolocation ) {
152- patchPrototype ( _global [ 'navigator' ] . geolocation , [ 'getCurrentPosition' , 'watchPosition' ] ) ;
153- }
154-
155- // patch Func.prototype.toString to let them look like native
156- patchFuncToString ( ) ;
157- // patch Object.prototype.toString to let them look like native
158- patchObjectToString ( ) ;
159-
160- // handle unhandled promise rejection
161- function findPromiseRejectionHandler ( evtName : string ) {
162- return function ( e : any ) {
163- const eventTasks = findEventTask ( _global , evtName ) ;
164- eventTasks . forEach ( eventTask => {
165- // windows has added unhandledrejection event listener
166- // trigger the event listener
167- const PromiseRejectionEvent = _global [ 'PromiseRejectionEvent' ] ;
168- if ( PromiseRejectionEvent ) {
169- const evt = new PromiseRejectionEvent ( evtName , { promise : e . promise , reason : e . rejection } ) ;
170- eventTask . invoke ( evt ) ;
171- }
172- } ) ;
173- } ;
174- }
188+ } ;
189+ }
175190
176- if ( _global [ 'PromiseRejectionEvent' ] ) {
177- ( Zone as any ) [ zoneSymbol ( 'unhandledPromiseRejectionHandler' ) ] =
178- findPromiseRejectionHandler ( 'unhandledrejection' ) ;
191+ if ( global [ 'PromiseRejectionEvent' ] ) {
192+ ( Zone as any ) [ zoneSymbol ( 'unhandledPromiseRejectionHandler' ) ] =
193+ findPromiseRejectionHandler ( 'unhandledrejection' ) ;
179194
180- ( Zone as any ) [ zoneSymbol ( 'rejectionHandledHandler' ) ] =
181- findPromiseRejectionHandler ( 'rejectionhandled' ) ;
182- }
195+ ( Zone as any ) [ zoneSymbol ( 'rejectionHandledHandler' ) ] =
196+ findPromiseRejectionHandler ( 'rejectionhandled' ) ;
197+ }
198+ } ) ;
0 commit comments