• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3 * Copyright (C) 2006 David Smith (catfish.man@gmail.com)
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1.  Redistributions of source code must retain the above copyright
10 *     notice, this list of conditions and the following disclaimer.
11 * 2.  Redistributions in binary form must reproduce the above copyright
12 *     notice, this list of conditions and the following disclaimer in the
13 *     documentation and/or other materials provided with the distribution.
14 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
15 *     its contributors may be used to endorse or promote products derived
16 *     from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30#import "WebDelegateImplementationCaching.h"
31
32#import "WebKitLogging.h"
33#import "WebView.h"
34#import "WebViewData.h"
35#import <objc/objc-runtime.h>
36
37@implementation WebView (WebDelegateImplementationCaching)
38
39WebResourceDelegateImplementationCache* WebViewGetResourceLoadDelegateImplementations(WebView *webView)
40{
41    static WebResourceDelegateImplementationCache empty;
42    if (!webView)
43        return &empty;
44    return &webView->_private->resourceLoadDelegateImplementations;
45}
46
47WebFrameLoadDelegateImplementationCache* WebViewGetFrameLoadDelegateImplementations(WebView *webView)
48{
49    static WebFrameLoadDelegateImplementationCache empty;
50    if (!webView)
51        return &empty;
52    return &webView->_private->frameLoadDelegateImplementations;
53}
54
55WebScriptDebugDelegateImplementationCache* WebViewGetScriptDebugDelegateImplementations(WebView *webView)
56{
57    static WebScriptDebugDelegateImplementationCache empty;
58    if (!webView)
59        return &empty;
60    return &webView->_private->scriptDebugDelegateImplementations;
61}
62
63// We use these functions to call the delegates and block exceptions. These functions are
64// declared inside a WebView category to get direct access to the delegate data memebers,
65// preventing more ObjC message dispatch and compensating for the expense of the @try/@catch.
66
67typedef float (*ObjCMsgSendFPRet)(id, SEL, ...);
68#if defined(__i386__)
69static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend_fpret);
70#else
71static const ObjCMsgSendFPRet objc_msgSend_float_return = reinterpret_cast<ObjCMsgSendFPRet>(objc_msgSend);
72#endif
73
74static inline id CallDelegate(WebView *self, id delegate, SEL selector)
75{
76    if (!delegate || ![delegate respondsToSelector:selector])
77        return nil;
78    if (!self->_private->catchesDelegateExceptions)
79        return objc_msgSend(delegate, selector, self);
80    @try {
81        return objc_msgSend(delegate, selector, self);
82    } @catch(id exception) {
83        ReportDiscardedDelegateException(selector, exception);
84    }
85    return nil;
86}
87
88static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object)
89{
90    if (!delegate || ![delegate respondsToSelector:selector])
91        return nil;
92    if (!self->_private->catchesDelegateExceptions)
93        return objc_msgSend(delegate, selector, self, object);
94    @try {
95        return objc_msgSend(delegate, selector, self, object);
96    } @catch(id exception) {
97        ReportDiscardedDelegateException(selector, exception);
98    }
99    return nil;
100}
101
102static inline id CallDelegate(WebView *self, id delegate, SEL selector, NSRect rect)
103{
104    if (!delegate || ![delegate respondsToSelector:selector])
105        return nil;
106    if (!self->_private->catchesDelegateExceptions)
107        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
108    @try {
109        return reinterpret_cast<id (*)(id, SEL, WebView *, NSRect)>(objc_msgSend)(delegate, selector, self, rect);
110    } @catch(id exception) {
111        ReportDiscardedDelegateException(selector, exception);
112    }
113    return nil;
114}
115
116static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2)
117{
118    if (!delegate || ![delegate respondsToSelector:selector])
119        return nil;
120    if (!self->_private->catchesDelegateExceptions)
121        return objc_msgSend(delegate, selector, self, object1, object2);
122    @try {
123        return objc_msgSend(delegate, selector, self, object1, object2);
124    } @catch(id exception) {
125        ReportDiscardedDelegateException(selector, exception);
126    }
127    return nil;
128}
129
130static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, BOOL boolean)
131{
132    if (!delegate || ![delegate respondsToSelector:selector])
133        return nil;
134    if (!self->_private->catchesDelegateExceptions)
135        return objc_msgSend(delegate, selector, self, object, boolean);
136    @try {
137        return objc_msgSend(delegate, selector, self, object, boolean);
138    } @catch(id exception) {
139        ReportDiscardedDelegateException(selector, exception);
140    }
141    return nil;
142}
143
144static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
145{
146    if (!delegate || ![delegate respondsToSelector:selector])
147        return nil;
148    if (!self->_private->catchesDelegateExceptions)
149        return objc_msgSend(delegate, selector, self, object1, object2, object3);
150    @try {
151        return objc_msgSend(delegate, selector, self, object1, object2, object3);
152    } @catch(id exception) {
153        ReportDiscardedDelegateException(selector, exception);
154    }
155    return nil;
156}
157
158static inline id CallDelegate(WebView *self, id delegate, SEL selector, id object, NSUInteger integer)
159{
160    if (!delegate || ![delegate respondsToSelector:selector])
161        return nil;
162    if (!self->_private->catchesDelegateExceptions)
163        return objc_msgSend(delegate, selector, self, object, integer);
164    @try {
165        return objc_msgSend(delegate, selector, self, object, integer);
166    } @catch(id exception) {
167        ReportDiscardedDelegateException(selector, exception);
168    }
169    return nil;
170}
171
172static inline float CallDelegateReturningFloat(WebView *self, id delegate, SEL selector)
173{
174    if (!delegate || ![delegate respondsToSelector:selector])
175        return 0.0f;
176    if (!self->_private->catchesDelegateExceptions)
177        return objc_msgSend_float_return(delegate, selector, self);
178    @try {
179        return objc_msgSend_float_return(delegate, selector, self);
180    } @catch(id exception) {
181        ReportDiscardedDelegateException(selector, exception);
182    }
183    return 0.0f;
184}
185
186static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector)
187{
188    if (!delegate || ![delegate respondsToSelector:selector])
189        return result;
190    if (!self->_private->catchesDelegateExceptions)
191        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
192    @try {
193        return reinterpret_cast<BOOL (*)(id, SEL, WebView *)>(objc_msgSend)(delegate, selector, self);
194    } @catch(id exception) {
195        ReportDiscardedDelegateException(selector, exception);
196    }
197    return result;
198}
199
200static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object)
201{
202    if (!delegate || ![delegate respondsToSelector:selector])
203        return result;
204    if (!self->_private->catchesDelegateExceptions)
205        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
206    @try {
207        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id)>(objc_msgSend)(delegate, selector, self, object);
208    } @catch(id exception) {
209        ReportDiscardedDelegateException(selector, exception);
210    }
211    return result;
212}
213
214static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object, BOOL boolean)
215{
216    if (!delegate || ![delegate respondsToSelector:selector])
217        return result;
218    if (!self->_private->catchesDelegateExceptions)
219        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
220    @try {
221        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, BOOL)>(objc_msgSend)(delegate, selector, self, object, boolean);
222    } @catch(id exception) {
223        ReportDiscardedDelegateException(selector, exception);
224    }
225    return result;
226}
227
228static inline BOOL CallDelegateReturningBoolean(BOOL result, WebView *self, id delegate, SEL selector, id object1, id object2)
229{
230    if (!delegate || ![delegate respondsToSelector:selector])
231        return result;
232    if (!self->_private->catchesDelegateExceptions)
233        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
234    @try {
235        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(delegate, selector, self, object1, object2);
236    } @catch(id exception) {
237        ReportDiscardedDelegateException(selector, exception);
238    }
239    return result;
240}
241
242static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector)
243{
244    if (!delegate)
245        return nil;
246    if (!self->_private->catchesDelegateExceptions)
247        return implementation(delegate, selector, self);
248    @try {
249        return implementation(delegate, selector, self);
250    } @catch(id exception) {
251        ReportDiscardedDelegateException(selector, exception);
252    }
253    return nil;
254}
255
256static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object)
257{
258    if (!delegate)
259        return nil;
260    if (!self->_private->catchesDelegateExceptions)
261        return implementation(delegate, selector, self, object);
262    @try {
263        return implementation(delegate, selector, self, object);
264    } @catch(id exception) {
265        ReportDiscardedDelegateException(selector, exception);
266    }
267    return nil;
268}
269
270static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2)
271{
272    if (!delegate)
273        return nil;
274    if (!self->_private->catchesDelegateExceptions)
275        return implementation(delegate, selector, self, object1, object2);
276    @try {
277        return implementation(delegate, selector, self, object1, object2);
278    } @catch(id exception) {
279        ReportDiscardedDelegateException(selector, exception);
280    }
281    return nil;
282}
283
284static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3)
285{
286    if (!delegate)
287        return nil;
288    if (!self->_private->catchesDelegateExceptions)
289        return implementation(delegate, selector, self, object1, object2, object3);
290    @try {
291        return implementation(delegate, selector, self, object1, object2, object3);
292    } @catch(id exception) {
293        ReportDiscardedDelegateException(selector, exception);
294    }
295    return nil;
296}
297
298static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, id object3, id object4)
299{
300    if (!delegate)
301        return nil;
302    if (!self->_private->catchesDelegateExceptions)
303        return implementation(delegate, selector, self, object1, object2, object3, object4);
304    @try {
305        return implementation(delegate, selector, self, object1, object2, object3, object4);
306    } @catch(id exception) {
307        ReportDiscardedDelegateException(selector, exception);
308    }
309    return nil;
310}
311
312static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2)
313{
314    if (!delegate)
315        return nil;
316    if (!self->_private->catchesDelegateExceptions)
317        return implementation(delegate, selector, self, object1, integer, object2);
318    @try {
319        return implementation(delegate, selector, self, object1, integer, object2);
320    } @catch(id exception) {
321        ReportDiscardedDelegateException(selector, exception);
322    }
323    return nil;
324}
325
326static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2)
327{
328    if (!delegate)
329        return nil;
330    if (!self->_private->catchesDelegateExceptions)
331        return implementation(delegate, selector, self, object1, integer1, integer2, object2);
332    @try {
333        return implementation(delegate, selector, self, object1, integer1, integer2, object2);
334    } @catch(id exception) {
335        ReportDiscardedDelegateException(selector, exception);
336    }
337    return nil;
338}
339
340static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, id object2, NSInteger integer, id object3)
341{
342    if (!delegate)
343        return nil;
344    if (!self->_private->catchesDelegateExceptions)
345        return implementation(delegate, selector, self, object1, object2, integer, object3);
346    @try {
347        return implementation(delegate, selector, self, object1, object2, integer, object3);
348    } @catch(id exception) {
349        ReportDiscardedDelegateException(selector, exception);
350    }
351    return nil;
352}
353
354static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
355{
356    if (!delegate)
357        return nil;
358    if (!self->_private->catchesDelegateExceptions)
359        return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
360    @try {
361        return implementation(delegate, selector, self, object1, integer1, object2, integer2, object3);
362    } @catch(id exception) {
363        ReportDiscardedDelegateException(selector, exception);
364    }
365    return nil;
366}
367
368static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
369{
370    if (!delegate)
371        return nil;
372    if (!self->_private->catchesDelegateExceptions)
373        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
374    @try {
375        return implementation(delegate, selector, self, object1, integer, object2, object3, object4);
376    } @catch(id exception) {
377        ReportDiscardedDelegateException(selector, exception);
378    }
379    return nil;
380}
381
382static inline id CallDelegate(IMP implementation, WebView *self, id delegate, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
383{
384    if (!delegate)
385        return nil;
386    if (!self->_private->catchesDelegateExceptions)
387        return implementation(delegate, selector, self, object1, interval, object2, object3);
388    @try {
389        return implementation(delegate, selector, self, object1, interval, object2, object3);
390    } @catch(id exception) {
391        ReportDiscardedDelegateException(selector, exception);
392    }
393    return nil;
394}
395
396id CallUIDelegate(WebView *self, SEL selector)
397{
398    return CallDelegate(self, self->_private->UIDelegate, selector);
399}
400
401id CallUIDelegate(WebView *self, SEL selector, id object)
402{
403    return CallDelegate(self, self->_private->UIDelegate, selector, object);
404}
405
406id CallUIDelegate(WebView *self, SEL selector, id object, BOOL boolean)
407{
408    return CallDelegate(self, self->_private->UIDelegate, selector, object, boolean);
409}
410
411id CallUIDelegate(WebView *self, SEL selector, NSRect rect)
412{
413    return CallDelegate(self, self->_private->UIDelegate, selector, rect);
414}
415
416id CallUIDelegate(WebView *self, SEL selector, id object1, id object2)
417{
418    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2);
419}
420
421id CallUIDelegate(WebView *self, SEL selector, id object1, id object2, id object3)
422{
423    return CallDelegate(self, self->_private->UIDelegate, selector, object1, object2, object3);
424}
425
426id CallUIDelegate(WebView *self, SEL selector, id object, NSUInteger integer)
427{
428    return CallDelegate(self, self->_private->UIDelegate, selector, object, integer);
429}
430
431float CallUIDelegateReturningFloat(WebView *self, SEL selector)
432{
433    return CallDelegateReturningFloat(self, self->_private->UIDelegate, selector);
434}
435
436BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector)
437{
438    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector);
439}
440
441BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object)
442{
443    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object);
444}
445
446BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object, BOOL boolean)
447{
448    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object, boolean);
449}
450
451BOOL CallUIDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, id object2)
452{
453    return CallDelegateReturningBoolean(result, self, self->_private->UIDelegate, selector, object1, object2);
454}
455
456id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector)
457{
458    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector);
459}
460
461id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object)
462{
463    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object);
464}
465
466id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
467{
468    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2);
469}
470
471id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
472{
473    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3);
474}
475
476id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
477{
478    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, object2, object3, object4);
479}
480
481id CallFrameLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSTimeInterval interval, id object2, id object3)
482{
483    return CallDelegate(implementation, self, self->_private->frameLoadDelegate, selector, object1, interval, object2, object3);
484}
485
486id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2)
487{
488    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2);
489}
490
491id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3)
492{
493    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3);
494}
495
496id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, id object3, id object4)
497{
498    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, object3, object4);
499}
500
501id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2)
502{
503    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, integer, object2);
504}
505
506id CallResourceLoadDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
507{
508    return CallDelegate(implementation, self, self->_private->resourceProgressDelegate, selector, object1, object2, integer, object3);
509}
510
511BOOL CallResourceLoadDelegateReturningBoolean(BOOL result, IMP implementation, WebView *self, SEL selector, id object1, id object2)
512{
513    if (!self->_private->catchesDelegateExceptions)
514        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
515    @try {
516        return reinterpret_cast<BOOL (*)(id, SEL, WebView *, id, id)>(objc_msgSend)(self->_private->resourceProgressDelegate, selector, self, object1, object2);
517    } @catch(id exception) {
518        ReportDiscardedDelegateException(selector, exception);
519    }
520    return result;
521}
522
523id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, id object2, NSInteger integer, id object3)
524{
525    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, object2, integer, object3);
526}
527
528id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, id object2, NSInteger integer2, id object3)
529{
530    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, object2, integer2, object3);
531}
532
533id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer, id object2, id object3, id object4)
534{
535    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer, object2, object3, object4);
536}
537
538id CallScriptDebugDelegate(IMP implementation, WebView *self, SEL selector, id object1, NSInteger integer1, NSInteger integer2, id object2)
539{
540    return CallDelegate(implementation, self, self->_private->scriptDebugDelegate, selector, object1, integer1, integer2, object2);
541}
542
543// The form delegate needs to have it's own implementation, because the first argument is never the WebView
544
545id CallFormDelegate(WebView *self, SEL selector, id object1, id object2)
546{
547    id delegate = self->_private->formDelegate;
548    if (!delegate || ![delegate respondsToSelector:selector])
549        return nil;
550    if (!self->_private->catchesDelegateExceptions)
551        return objc_msgSend(delegate, selector, object1, object2);
552    @try {
553        return objc_msgSend(delegate, selector, object1, object2);
554    } @catch(id exception) {
555        ReportDiscardedDelegateException(selector, exception);
556    }
557    return nil;
558}
559
560id CallFormDelegate(WebView *self, SEL selector, id object1, id object2, id object3, id object4, id object5)
561{
562    id delegate = self->_private->formDelegate;
563    if (!delegate || ![delegate respondsToSelector:selector])
564        return nil;
565    if (!self->_private->catchesDelegateExceptions)
566        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
567    @try {
568        return objc_msgSend(delegate, selector, object1, object2, object3, object4, object5);
569    } @catch(id exception) {
570        ReportDiscardedDelegateException(selector, exception);
571    }
572    return nil;
573}
574
575BOOL CallFormDelegateReturningBoolean(BOOL result, WebView *self, SEL selector, id object1, SEL selectorArg, id object2)
576{
577    id delegate = self->_private->formDelegate;
578    if (!delegate || ![delegate respondsToSelector:selector])
579        return result;
580    if (!self->_private->catchesDelegateExceptions)
581        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
582    @try {
583        return reinterpret_cast<BOOL (*)(id, SEL, id, SEL, id)>(objc_msgSend)(delegate, selector, object1, selectorArg, object2);
584    } @catch(id exception) {
585        ReportDiscardedDelegateException(selector, exception);
586    }
587    return result;
588}
589
590@end
591