forked from airbrake/airbrake-js
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathairbrake-shim.coffee
107 lines (91 loc) · 3.03 KB
/
airbrake-shim.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# this == window
global = this
# Airbrake shim that stores exceptions until Airbrake notifier is loaded.
global.Airbrake = []
# Wraps passed function and returns new function that catches and
# reports unhandled exceptions.
global.Airbrake.wrap = (fn) ->
if fn.__airbrake__
return fn
airbrakeWrapper = ->
args = wrapArguments(arguments)
try
return fn.apply(this, args)
catch exc
args = Array.prototype.slice.call(arguments)
global.Airbrake.push({error: exc, params: {arguments: args}})
return null
airbrakeWrapper.__airbrake__ = true
airbrakeWrapper.__inner__ = fn
for prop of fn
if fn.hasOwnProperty(prop)
airbrakeWrapper[prop] = fn[prop]
return airbrakeWrapper
# Registers console reporter when notifier is ready.
global.Airbrake.onload = ->
global.Airbrake.addReporter(global.Airbrake.consoleReporter)
# Reports unhandled exceptions.
global.onerror = (message, file, line, column, error) ->
if message == 'Script error.'
# Ignore.
return
if error
global.Airbrake.push({error: error})
else
global.Airbrake.push({error: {
message: message,
fileName: file,
lineNumber: line,
columnNumber: column or 0,
}})
loadAirbrakeNotifier = ->
script = document.createElement('script')
sibling = document.getElementsByTagName('script')[0]
script.src = 'https://ssljscdn.airbrake.io/0.3/airbrake.min.js'
script.async = true
sibling.parentNode.insertBefore(script, sibling)
wrapArguments = (args) ->
for arg, i in args
type = typeof arg
if type == 'function'
args[i] = global.Airbrake.wrap(arg)
else if arg && arg.length && type != 'string'
# Wrap recursively.
args[i] = wrapArguments(arg)
return args
setupJQ = ->
# Reports exceptions thrown in jQuery event handlers.
jqEventAdd = jQuery.event.add
jQuery.event.add = (elem, types, handler, data, selector) ->
if handler.handler
if not handler.handler.guid
handler.handler.guid = jQuery.guid++
handler.handler = global.Airbrake.wrap(handler.handler)
else
if not handler.guid
handler.guid = jQuery.guid++
handler = global.Airbrake.wrap(handler)
return jqEventAdd(elem, types, handler, data, selector)
# Reports exceptions thrown in jQuery callbacks.
jqCallbacks = jQuery.Callbacks
jQuery.Callbacks = (options) ->
cb = jqCallbacks(options)
cbAdd = cb.add
cb.add = ->
return cbAdd.apply(this, wrapArguments(arguments))
return cb
# Reports exceptions thrown in jQuery ready callbacks.
jqReady = jQuery.fn.ready
jQuery.fn.ready = (fn) ->
return jqReady(global.Airbrake.wrap(fn))
# Asynchronously loads global.Airbrake notifier.
if global.addEventListener
global.addEventListener('load', loadAirbrakeNotifier, false)
else if global.attachEvent
global.attachEvent('onload', loadAirbrakeNotifier)
# Reports exceptions thrown in jQuery event handlers.
if global.jQuery
setupJQ()
else
if global.console
global.console.warn('airbrake-js: jQuery not found; skipping jQuery instrumentation.')