GT2/GT2-Android/node_modules/raven-js/dist/plugins/angular.js

575 lines
14 KiB
JavaScript

/*! Raven.js 3.22.2 (1b6187b) | github.com/getsentry/raven-js */
/*
* Includes TraceKit
* https://github.com/getsentry/TraceKit
*
* Copyright 2018 Matt Robenolt and other contributors
* Released under the BSD license
* https://github.com/getsentry/raven-js/blob/master/LICENSE
*
*/
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global.Raven = global.Raven || {}, global.Raven.Plugins = global.Raven.Plugins || {}, global.Raven.Plugins.Angular = factory());
}(this, (function () { 'use strict';
function _typeof(obj) {
if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") {
_typeof = function (obj) {
return typeof obj;
};
} else {
_typeof = function (obj) {
return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
};
}
return _typeof(obj);
}
var _sPO = Object.setPrototypeOf || function _sPO(o, p) {
o.__proto__ = p;
return o;
};
var _construct = typeof Reflect === "object" && Reflect.construct || function _construct(Parent, args, Class) {
var Constructor,
a = [null];
a.push.apply(a, args);
Constructor = Parent.bind.apply(Parent, a);
return _sPO(new Constructor(), Class.prototype);
};
var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
var _window = typeof window !== 'undefined' ? window : typeof commonjsGlobal !== 'undefined' ? commonjsGlobal : typeof self !== 'undefined' ? self : {};
function isObject(what) {
return _typeof(what) === 'object' && what !== null;
} // Yanked from https://git.io/vS8DV re-used under CC0
// with some tiny modifications
function isError(value) {
switch ({}.toString.call(value)) {
case '[object Error]':
return true;
case '[object Exception]':
return true;
case '[object DOMException]':
return true;
default:
return value instanceof Error;
}
}
function isErrorEvent(value) {
return supportsErrorEvent() && {}.toString.call(value) === '[object ErrorEvent]';
}
function isUndefined(what) {
return what === void 0;
}
function isFunction(what) {
return typeof what === 'function';
}
function isPlainObject(what) {
return Object.prototype.toString.call(what) === '[object Object]';
}
function isString(what) {
return Object.prototype.toString.call(what) === '[object String]';
}
function isArray(what) {
return Object.prototype.toString.call(what) === '[object Array]';
}
function isEmptyObject(what) {
if (!isPlainObject(what)) return false;
for (var _ in what) {
if (what.hasOwnProperty(_)) {
return false;
}
}
return true;
}
function supportsErrorEvent() {
try {
new ErrorEvent(''); // eslint-disable-line no-new
return true;
} catch (e) {
return false;
}
}
function supportsFetch() {
if (!('fetch' in _window)) return false;
try {
new Headers(); // eslint-disable-line no-new
new Request(''); // eslint-disable-line no-new
new Response(); // eslint-disable-line no-new
return true;
} catch (e) {
return false;
}
}
function wrappedCallback$1(callback) {
function dataCallback(data, original) {
var normalizedData = callback(data) || data;
if (original) {
return original(normalizedData) || normalizedData;
}
return normalizedData;
}
return dataCallback;
}
function each(obj, callback) {
var i, j;
if (isUndefined(obj.length)) {
for (i in obj) {
if (hasKey(obj, i)) {
callback.call(null, i, obj[i]);
}
}
} else {
j = obj.length;
if (j) {
for (i = 0; i < j; i++) {
callback.call(null, i, obj[i]);
}
}
}
}
function objectMerge(obj1, obj2) {
if (!obj2) {
return obj1;
}
each(obj2, function (key, value) {
obj1[key] = value;
});
return obj1;
}
/**
* This function is only used for react-native.
* react-native freezes object that have already been sent over the
* js bridge. We need this function in order to check if the object is frozen.
* So it's ok that objectFrozen returns false if Object.isFrozen is not
* supported because it's not relevant for other "platforms". See related issue:
* https://github.com/getsentry/react-native-sentry/issues/57
*/
function objectFrozen(obj) {
if (!Object.isFrozen) {
return false;
}
return Object.isFrozen(obj);
}
function truncate(str, max) {
return !max || str.length <= max ? str : str.substr(0, max) + "\u2026";
}
/**
* hasKey, a better form of hasOwnProperty
* Example: hasKey(MainHostObject, property) === true/false
*
* @param {Object} host object to check property
* @param {string} key to check
*/
function hasKey(object, key) {
return Object.prototype.hasOwnProperty.call(object, key);
}
function joinRegExp(patterns) {
// Combine an array of regular expressions and strings into one large regexp
// Be mad.
var sources = [],
i = 0,
len = patterns.length,
pattern;
for (; i < len; i++) {
pattern = patterns[i];
if (isString(pattern)) {
// If it's a string, we need to escape it
// Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1'));
} else if (pattern && pattern.source) {
// If it's a regexp already, we want to extract the source
sources.push(pattern.source);
} // Intentionally skip other cases
}
return new RegExp(sources.join('|'), 'i');
}
function urlencode(o) {
var pairs = [];
each(o, function (key, value) {
pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value));
});
return pairs.join('&');
} // borrowed from https://tools.ietf.org/html/rfc3986#appendix-B
// intentionally using regex and not <a/> href parsing trick because React Native and other
// environments where DOM might not be available
function parseUrl(url) {
if (typeof url !== 'string') return {};
var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/); // coerce to undefined values to empty string so we don't get 'undefined'
var query = match[6] || '';
var fragment = match[8] || '';
return {
protocol: match[2],
host: match[4],
path: match[5],
relative: match[5] + query + fragment // everything minus origin
};
}
function uuid4() {
var crypto = _window.crypto || _window.msCrypto;
if (!isUndefined(crypto) && crypto.getRandomValues) {
// Use window.crypto API if available
// eslint-disable-next-line no-undef
var arr = new Uint16Array(8);
crypto.getRandomValues(arr); // set 4 in byte 7
arr[3] = arr[3] & 0xfff | 0x4000; // set 2 most significant bits of byte 9 to '10'
arr[4] = arr[4] & 0x3fff | 0x8000;
var pad = function pad(num) {
var v = num.toString(16);
while (v.length < 4) {
v = '0' + v;
}
return v;
};
return pad(arr[0]) + pad(arr[1]) + pad(arr[2]) + pad(arr[3]) + pad(arr[4]) + pad(arr[5]) + pad(arr[6]) + pad(arr[7]);
} else {
// http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
var r = Math.random() * 16 | 0,
v = c === 'x' ? r : r & 0x3 | 0x8;
return v.toString(16);
});
}
}
/**
* Given a child DOM element, returns a query-selector statement describing that
* and its ancestors
* e.g. [HTMLElement] => body > div > input#foo.btn[name=baz]
* @param elem
* @returns {string}
*/
function htmlTreeAsString(elem) {
/* eslint no-extra-parens:0*/
var MAX_TRAVERSE_HEIGHT = 5,
MAX_OUTPUT_LEN = 80,
out = [],
height = 0,
len = 0,
separator = ' > ',
sepLength = separator.length,
nextStr;
while (elem && height++ < MAX_TRAVERSE_HEIGHT) {
nextStr = htmlElementAsString(elem); // bail out if
// - nextStr is the 'html' element
// - the length of the string that would be created exceeds MAX_OUTPUT_LEN
// (ignore this limit if we are on the first iteration)
if (nextStr === 'html' || height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) {
break;
}
out.push(nextStr);
len += nextStr.length;
elem = elem.parentNode;
}
return out.reverse().join(separator);
}
/**
* Returns a simple, query-selector representation of a DOM element
* e.g. [HTMLElement] => input#foo.btn[name=baz]
* @param HTMLElement
* @returns {string}
*/
function htmlElementAsString(elem) {
var out = [],
className,
classes,
key,
attr,
i;
if (!elem || !elem.tagName) {
return '';
}
out.push(elem.tagName.toLowerCase());
if (elem.id) {
out.push('#' + elem.id);
}
className = elem.className;
if (className && isString(className)) {
classes = className.split(/\s+/);
for (i = 0; i < classes.length; i++) {
out.push('.' + classes[i]);
}
}
var attrWhitelist = ['type', 'name', 'title', 'alt'];
for (i = 0; i < attrWhitelist.length; i++) {
key = attrWhitelist[i];
attr = elem.getAttribute(key);
if (attr) {
out.push('[' + key + '="' + attr + '"]');
}
}
return out.join('');
}
/**
* Returns true if either a OR b is truthy, but not both
*/
function isOnlyOneTruthy(a, b) {
return !!(!!a ^ !!b);
}
/**
* Returns true if both parameters are undefined
*/
function isBothUndefined(a, b) {
return isUndefined(a) && isUndefined(b);
}
/**
* Returns true if the two input exception interfaces have the same content
*/
function isSameException(ex1, ex2) {
if (isOnlyOneTruthy(ex1, ex2)) return false;
ex1 = ex1.values[0];
ex2 = ex2.values[0];
if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; // in case both stacktraces are undefined, we can't decide so default to false
if (isBothUndefined(ex1.stacktrace, ex2.stacktrace)) return false;
return isSameStacktrace(ex1.stacktrace, ex2.stacktrace);
}
/**
* Returns true if the two input stack trace interfaces have the same content
*/
function isSameStacktrace(stack1, stack2) {
if (isOnlyOneTruthy(stack1, stack2)) return false;
var frames1 = stack1.frames;
var frames2 = stack2.frames; // Exit early if frame count differs
if (frames1.length !== frames2.length) return false; // Iterate through every frame; bail out if anything differs
var a, b;
for (var i = 0; i < frames1.length; i++) {
a = frames1[i];
b = frames2[i];
if (a.filename !== b.filename || a.lineno !== b.lineno || a.colno !== b.colno || a['function'] !== b['function']) return false;
}
return true;
}
/**
* Polyfill a method
* @param obj object e.g. `document`
* @param name method name present on object e.g. `addEventListener`
* @param replacement replacement function
* @param track {optional} record instrumentation to an array
*/
function fill(obj, name, replacement, track) {
var orig = obj[name];
obj[name] = replacement(orig);
obj[name].__raven__ = true;
obj[name].__orig__ = orig;
if (track) {
track.push([obj, name, orig]);
}
}
/**
* Join values in array
* @param input array of values to be joined together
* @param delimiter string to be placed in-between values
* @returns {string}
*/
function safeJoin(input, delimiter) {
if (!isArray(input)) return '';
var output = [];
for (var i = 0; i < input.length; i++) {
try {
output.push(String(input[i]));
} catch (e) {
output.push('[value cannot be serialized]');
}
}
return output.join(delimiter);
}
var utils = {
isObject: isObject,
isError: isError,
isErrorEvent: isErrorEvent,
isUndefined: isUndefined,
isFunction: isFunction,
isPlainObject: isPlainObject,
isString: isString,
isArray: isArray,
isEmptyObject: isEmptyObject,
supportsErrorEvent: supportsErrorEvent,
supportsFetch: supportsFetch,
wrappedCallback: wrappedCallback$1,
each: each,
objectMerge: objectMerge,
truncate: truncate,
objectFrozen: objectFrozen,
hasKey: hasKey,
joinRegExp: joinRegExp,
urlencode: urlencode,
uuid4: uuid4,
htmlTreeAsString: htmlTreeAsString,
htmlElementAsString: htmlElementAsString,
isSameException: isSameException,
isSameStacktrace: isSameStacktrace,
parseUrl: parseUrl,
fill: fill,
safeJoin: safeJoin
};
/**
* Angular.js plugin
*
* Provides an $exceptionHandler for Angular.js
*/
var wrappedCallback = utils.wrappedCallback; // See https://github.com/angular/angular.js/blob/v1.4.7/src/minErr.js
var angularPattern = /^\[((?:[$a-zA-Z0-9]+:)?(?:[$a-zA-Z0-9]+))\] (.*?)\n?(\S+)$/;
var moduleName = 'ngRaven';
function angularPlugin(Raven, angular) {
angular = angular || window.angular;
if (!angular) return;
function RavenProvider() {
this.$get = ['$window', function ($window) {
return Raven;
}];
}
function ExceptionHandlerProvider($provide) {
$provide.decorator('$exceptionHandler', ['Raven', '$delegate', exceptionHandler]);
}
function exceptionHandler(R, $delegate) {
return function (ex, cause) {
R.captureException(ex, {
extra: {
cause: cause
}
});
$delegate(ex, cause);
};
}
angular.module(moduleName, []).provider('Raven', RavenProvider).config(['$provide', ExceptionHandlerProvider]);
Raven.setDataCallback(wrappedCallback(function (data) {
return angularPlugin._normalizeData(data);
}));
}
angularPlugin._normalizeData = function (data) {
// We only care about mutating an exception
var exception = data.exception;
if (exception) {
exception = exception.values[0];
var matches = angularPattern.exec(exception.value);
if (matches) {
// This type now becomes something like: $rootScope:inprog
exception.type = matches[1];
exception.value = matches[2];
data.message = exception.type + ': ' + exception.value; // auto set a new tag specifically for the angular error url
data.extra.angularDocs = matches[3].substr(0, 250);
}
}
return data;
};
angularPlugin.moduleName = moduleName;
var angular = angularPlugin;
return angular;
})));