~stephen-stewart/online-services-common-js/update-global-nav

« back to all changes in this revision

Viewing changes to build/util-oops/util-oops-debug.js

  • Committer: Stephen Stewart
  • Date: 2014-02-22 15:05:16 UTC
  • Revision ID: stephen.stewart@canonical.com-20140222150516-rkzti2c43ggwr2ta
import latest js, convert

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
YUI.add('util-oops', function (Y, NAME) {
 
2
 
 
3
"use strict";
 
4
Y.namespace('U1.util');
 
5
 
 
6
var Oops = Y.Base.create('oneUtilOops', Y.Base, [], {
 
7
 
 
8
    initializer: function (config) {
 
9
 
 
10
        config = config || {};
 
11
 
 
12
        var globalContext = config.globalContext || this.get('globalContext'),
 
13
            globalHandler = config.globalErrorHandler || this._globalErrorHandler;
 
14
 
 
15
        // save older onerror
 
16
        // replace with our handler
 
17
        this._oldOnError = globalContext.onerror;
 
18
        globalContext.onerror = Y.bind(globalHandler, this);
 
19
 
 
20
    },
 
21
 
 
22
    destructor: function () {
 
23
 
 
24
        // revert global error handler
 
25
        this.get('globalContext').onerror = this._oldOnError;
 
26
 
 
27
    },
 
28
 
 
29
    // overloaded to handle directly calling window.onerror(new Error("Foo"))
 
30
    _globalErrorHandler: function (message, url, line) {
 
31
        var error;
 
32
 
 
33
        if(Y.Lang.isObject(message)) {
 
34
            error = message;
 
35
        } else {
 
36
            error = {
 
37
                message: message,
 
38
                url: url,
 
39
                line: line
 
40
            };
 
41
        }
 
42
 
 
43
        // send returns supress
 
44
        return this.send(error);
 
45
    },
 
46
 
 
47
    _createOopsReport: function (error) {
 
48
 
 
49
        return new Y.U1.util.OopsReport(error, {
 
50
            ioConfig:       this.get('ioConfig'),
 
51
            endPoint:       this.get('endPoint'),
 
52
            reporter:       this.get('reporter'),
 
53
            sessionData:    this.get('sessionData')
 
54
        });
 
55
 
 
56
    },
 
57
 
 
58
    // creates OOPS report and sends it
 
59
    send: function (error) {
 
60
 
 
61
        var report = this._createOopsReport(error);
 
62
 
 
63
        if(report) {
 
64
 
 
65
            this.fire('registered');
 
66
 
 
67
            report.send();
 
68
 
 
69
        }
 
70
 
 
71
        return this.get('suppress');
 
72
    }
 
73
 
 
74
}, {
 
75
    ATTRS: {
 
76
        globalErrorHandler: { value: null },
 
77
        globalContext: { value: Y.config.win },
 
78
        ioConfig: {
 
79
            value: {
 
80
                method: 'POST',
 
81
                xdr: {
 
82
                    use: 'native'
 
83
                }
 
84
            }
 
85
        },
 
86
        reporter: { value: 'u1.' + Y.config.win.location.hostname },
 
87
        sessionData: { value: null },
 
88
        suppress: { value: false },
 
89
        endPoint: {
 
90
            value: '',
 
91
            writeOnce: true
 
92
        }
 
93
    }
 
94
}),
 
95
 
 
96
OopsReport = function (error, config) {
 
97
 
 
98
    if(!error) {
 
99
        return null;
 
100
    }
 
101
 
 
102
    this.error = error;
 
103
    this.config = config;
 
104
 
 
105
    this.initializer();
 
106
    return this;
 
107
};
 
108
 
 
109
OopsReport.prototype = {
 
110
 
 
111
    _io: null,
 
112
 
 
113
    initializer: function () {
 
114
 
 
115
        this._io = new Y.IO();
 
116
 
 
117
    },
 
118
 
 
119
    send: function () {
 
120
 
 
121
        return this._io.send(this.config.endPoint, Y.merge(this.config.ioConfig, {
 
122
            data: this._createReport()
 
123
        }));
 
124
 
 
125
    },
 
126
 
 
127
    _createReport: function () {
 
128
 
 
129
        var reportElements = [
 
130
            { reporter: this.config.reporter },
 
131
            this.uaToJSON(),
 
132
            this.config.sessionData,
 
133
            this._normalizeError(this.error)
 
134
        ],
 
135
            ret,
 
136
            i = 0,
 
137
            j = reportElements.length;
 
138
 
 
139
        // Will try to report all reportElements
 
140
        // If it fails, drop one element at a time
 
141
        // This will end up with just the basic error
 
142
 
 
143
        // e.g. if reporter, ua and sessiondata are all borked,
 
144
        // the report will still include the error
 
145
        for(; i < j; i++) {
 
146
 
 
147
            try {
 
148
                ret = Y.JSON.stringify(Y.merge.apply(this, reportElements.splice(i)));
 
149
            } catch (e) {
 
150
 
 
151
                // report the stringification failure
 
152
                // but drop everything but the error
 
153
                new Y.U1.util.OopsReport(e, {
 
154
                    endPoint: this.config.endPoint,
 
155
                    ioConfig: this.config.ioConfig
 
156
                }).send();
 
157
 
 
158
            } finally {
 
159
                if(Y.Lang.isString(ret)) {
 
160
                    break;
 
161
                }
 
162
            }
 
163
 
 
164
        }
 
165
 
 
166
        return ret;
 
167
 
 
168
    },
 
169
 
 
170
    _normalizeError: function (error) {
 
171
 
 
172
        var e       = {},
 
173
            props   = [
 
174
                { accepts: ['message', 'description'], output: 'message' },
 
175
                { accepts: ['url', 'fileName'], output: 'url' },
 
176
                { accepts: ['line', 'lineNumber'], output: 'line' },
 
177
                { accepts: ['column', 'columnNumber'], output: 'column' },
 
178
                { accepts: ['name'], output: 'name' },
 
179
                { accepts: ['number'], output: 'errorCode' },
 
180
                { accepts: ['stack', 'stacktrace'], output: 'stacktrace' }
 
181
            ];
 
182
 
 
183
        // take accepted inputs and add as output on e
 
184
        Y.each(props, function (prop) {
 
185
            Y.each(prop.accepts, function (accept) {
 
186
                if(error[accept]) {
 
187
                    e[prop.output] = error[accept];
 
188
                }
 
189
            });
 
190
        });
 
191
 
 
192
        return e;
 
193
    },
 
194
 
 
195
    uaToJSON: function () {
 
196
        var queryObj = {};
 
197
 
 
198
        Y.each(Y.UA, function(v, k) {
 
199
            if (!Y.Lang.isFunction(v)) {
 
200
                if (v) {
 
201
                    try {
 
202
                        queryObj[k] = v;
 
203
                        if(Y.Lang.isNumber(v)) {
 
204
                            queryObj.browser = k;
 
205
                            queryObj.browserVersion = v;
 
206
                        }
 
207
                    } catch (e) {
 
208
                        void(0);
 
209
                    }
 
210
                }
 
211
            }
 
212
        });
 
213
 
 
214
        return queryObj;
 
215
    }
 
216
};
 
217
 
 
218
Y.U1.util.Oops = Oops;
 
219
Y.U1.util.OopsReport = OopsReport;
 
220
 
 
221
 
 
222
}, '@VERSION@', {"requires": ["base", "io-base", "json-stringify"]});