@@ -177,11 +177,11 @@ Zone.patchProperty = function (obj, prop) {
177177 Object . defineProperty ( obj , prop , desc ) ;
178178} ;
179179
180- Zone . patchProperties = function ( obj ) {
181- Object . keys ( obj ) .
180+ Zone . patchProperties = function ( obj , properties ) {
181+ ( properties || Object . keys ( obj ) .
182182 filter ( function ( propertyName ) {
183183 return propertyName . substr ( 0 , 2 ) === 'on' ;
184- } ) .
184+ } ) ) .
185185 forEach ( function ( eventName ) {
186186 Zone . patchProperty ( obj , eventName ) ;
187187 } ) ;
@@ -211,36 +211,46 @@ Zone.patch = function patch () {
211211 Zone . patchableFn ( window , [ 'alert' , 'prompt' ] ) ;
212212
213213 // patched properties depend on addEventListener, so this needs to come first
214- if ( EventTarget ) {
215- Zone . patchEventTargetMethods ( EventTarget . prototype ) ;
214+ if ( window . EventTarget ) {
215+ Zone . patchEventTargetMethods ( window . EventTarget . prototype ) ;
216216
217217 // Note: EventTarget is not available in all browsers,
218218 // if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget
219219 } else {
220- [ ApplicationCache . prototype ,
221- EventSource . prototype ,
222- FileReader . prototype ,
223- InputMethodContext . prototype ,
224- MediaController . prototype ,
225- MessagePort . prototype ,
226- Node . prototype ,
227- Performance . prototype ,
228- SVGElementInstance . prototype ,
229- SharedWorker . prototype ,
230- TextTrack . prototype ,
231- TextTrackCue . prototype ,
232- TextTrackList . prototype ,
233- WebKitNamedFlow . prototype ,
234- Window . prototype ,
235- Worker . prototype ,
236- WorkerGlobalScope . prototype ,
237- XMLHttpRequestEventTarget . prototype ,
238- XMLHttpRequestUpload . prototype
239- ] . forEach ( patchEventTargetMethods ) ;
220+ [ 'ApplicationCache' ,
221+ 'EventSource' ,
222+ 'FileReader' ,
223+ 'InputMethodContext' ,
224+ 'MediaController' ,
225+ 'MessagePort' ,
226+ 'Node' ,
227+ 'Performance' ,
228+ 'SVGElementInstance' ,
229+ 'SharedWorker' ,
230+ 'TextTrack' ,
231+ 'TextTrackCue' ,
232+ 'TextTrackList' ,
233+ 'WebKitNamedFlow' ,
234+ 'Window' ,
235+ 'Worker' ,
236+ 'WorkerGlobalScope' ,
237+ 'XMLHttpRequestEventTarget' ,
238+ 'XMLHttpRequestUpload'
239+ ] .
240+ filter ( function ( thing ) {
241+ return window [ thing ] ;
242+ } ) .
243+ map ( function ( thing ) {
244+ return window [ thing ] . prototype ;
245+ } ) .
246+ forEach ( Zone . patchEventTargetMethods ) ;
240247 }
241248
242- Zone . patchProperties ( HTMLElement . prototype ) ;
243- Zone . patchProperties ( XMLHttpRequest . prototype ) ;
249+ if ( Zone . canPatchViaPropertyDescriptor ( ) ) {
250+ Zone . patchViaPropertyDescriptor ( ) ;
251+ } else {
252+ Zone . patchViaCapturingAllTheEvents ( ) ;
253+ }
244254
245255 // patch promises
246256 if ( window . Promise ) {
@@ -251,6 +261,51 @@ Zone.patch = function patch () {
251261 }
252262} ;
253263
264+ //
265+ Zone . canPatchViaPropertyDescriptor = function ( ) {
266+ Object . defineProperty ( HTMLElement . prototype , 'onclick' , {
267+ get : function ( ) {
268+ return true ;
269+ }
270+ } ) ;
271+ var elt = document . createElement ( 'div' ) ;
272+ var result = ! ! elt . onclick ;
273+ Object . defineProperty ( HTMLElement . prototype , 'onclick' , { } ) ;
274+ return result ;
275+ } ;
276+
277+ // for browsers that we can patch the descriptor:
278+ // - eventually Chrome once this bug gets resolved
279+ // - Firefox
280+ Zone . patchViaPropertyDescriptor = function ( ) {
281+ Zone . patchProperties ( HTMLElement . prototype , Zone . eventNames . map ( function ( property ) {
282+ return 'on' + property ;
283+ } ) ) ;
284+ Zone . patchProperties ( XMLHttpRequest . prototype ) ;
285+ } ;
286+
287+ // Whenever any event fires, we check the event target and all parents
288+ // for `onwhatever` properties and replace them with zone-bound functions
289+ // - Chrome (for now)
290+ Zone . patchViaCapturingAllTheEvents = function ( ) {
291+ Zone . eventNames . forEach ( function ( property ) {
292+ var onproperty = 'on' + property ;
293+ document . addEventListener ( property , function ( event ) {
294+ var elt = event . target , bound ;
295+ while ( elt ) {
296+ if ( elt [ onproperty ] && ! elt [ onproperty ] . _unbound ) {
297+ bound = zone . bind ( elt [ onproperty ] ) ;
298+ bound . _unbound = elt [ onproperty ] ;
299+ elt [ onproperty ] = bound ;
300+ }
301+ elt = elt . parentElement ;
302+ }
303+ } , true ) ;
304+ } ) ;
305+ } ;
306+
307+ Zone . eventNames = 'copy cut paste abort blur focus canplay canplaythrough change click contextmenu dblclick drag dragend dragenter dragleave dragover dragstart drop durationchange emptied ended input invalid keydown keypress keyup load loadeddata loadedmetadata loadstart mousedown mouseenter mouseleave mousemove mouseout mouseover mouseup pause play playing progress ratechange reset scroll seeked seeking select show stalled submit suspend timeupdate volumechange waiting mozfullscreenchange mozfullscreenerror mozpointerlockchange mozpointerlockerror error' . split ( ' ' ) ;
308+
254309Zone . init = function init ( ) {
255310 window . zone = new Zone ( ) ;
256311 Zone . patch ( ) ;
0 commit comments