@@ -177,11 +177,11 @@ Zone.patchProperty = function (obj, prop) {
177
177
Object . defineProperty ( obj , prop , desc ) ;
178
178
} ;
179
179
180
- Zone . patchProperties = function ( obj ) {
181
- Object . keys ( obj ) .
180
+ Zone . patchProperties = function ( obj , properties ) {
181
+ ( properties || Object . keys ( obj ) .
182
182
filter ( function ( propertyName ) {
183
183
return propertyName . substr ( 0 , 2 ) === 'on' ;
184
- } ) .
184
+ } ) ) .
185
185
forEach ( function ( eventName ) {
186
186
Zone . patchProperty ( obj , eventName ) ;
187
187
} ) ;
@@ -211,36 +211,46 @@ Zone.patch = function patch () {
211
211
Zone . patchableFn ( window , [ 'alert' , 'prompt' ] ) ;
212
212
213
213
// 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 ) ;
216
216
217
217
// Note: EventTarget is not available in all browsers,
218
218
// if it's not available, we instead patch the APIs in the IDL that inherit from EventTarget
219
219
} 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 ) ;
240
247
}
241
248
242
- Zone . patchProperties ( HTMLElement . prototype ) ;
243
- Zone . patchProperties ( XMLHttpRequest . prototype ) ;
249
+ if ( Zone . canPatchViaPropertyDescriptor ( ) ) {
250
+ Zone . patchViaPropertyDescriptor ( ) ;
251
+ } else {
252
+ Zone . patchViaCapturingAllTheEvents ( ) ;
253
+ }
244
254
245
255
// patch promises
246
256
if ( window . Promise ) {
@@ -251,6 +261,51 @@ Zone.patch = function patch () {
251
261
}
252
262
} ;
253
263
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
+
254
309
Zone . init = function init ( ) {
255
310
window . zone = new Zone ( ) ;
256
311
Zone . patch ( ) ;
0 commit comments