|
1 | | -/*global XDomainRequest:false, __DEV__:false*/ |
| 1 | +/*global XDomainRequest:false */ |
2 | 2 |
|
3 | 3 | var TraceKit = require('../vendor/TraceKit/tracekit'); |
4 | 4 | var stringify = require('../vendor/json-stringify-safe/stringify'); |
5 | 5 | var RavenConfigError = require('./configError'); |
6 | | -var utils = require('./utils'); |
7 | 6 |
|
8 | | -var isError = utils.isError, |
9 | | - isObject = utils.isObject; |
| 7 | +var utils = require('./utils'); |
| 8 | +var isError = utils.isError; |
| 9 | +var isObject = utils.isObject; |
| 10 | +var isObject = utils.isObject; |
| 11 | +var isError = utils.isError; |
| 12 | +var isUndefined = utils.isUndefined; |
| 13 | +var isFunction = utils.isFunction; |
| 14 | +var isString = utils.isString; |
| 15 | +var isEmptyObject = utils.isEmptyObject; |
| 16 | +var each = utils.each; |
| 17 | +var objectMerge = utils.objectMerge; |
| 18 | +var truncate = utils.truncate; |
| 19 | +var objectFrozen = utils.objectFrozen; |
| 20 | +var hasKey = utils.hasKey; |
| 21 | +var joinRegExp = utils.joinRegExp; |
| 22 | +var urlencode = utils.urlencode; |
| 23 | +var uuid4 = utils.uuid4; |
| 24 | +var htmlTreeAsString = utils.htmlTreeAsString; |
| 25 | +var isSameException = utils.isSameException; |
| 26 | +var isSameStacktrace = utils.isSameStacktrace; |
| 27 | +var parseUrl = utils.parseUrl; |
| 28 | +var fill = utils.fill; |
10 | 29 |
|
11 | 30 | var wrapConsoleMethod = require('./console').wrapMethod; |
12 | 31 |
|
@@ -1891,347 +1910,6 @@ Raven.prototype = { |
1891 | 1910 | } |
1892 | 1911 | }; |
1893 | 1912 |
|
1894 | | -/*------------------------------------------------ |
1895 | | - * utils |
1896 | | - * |
1897 | | - * conditionally exported for test via Raven.utils |
1898 | | - ================================================= |
1899 | | - */ |
1900 | | -var objectPrototype = Object.prototype; |
1901 | | - |
1902 | | -function isUndefined(what) { |
1903 | | - return what === void 0; |
1904 | | -} |
1905 | | - |
1906 | | -function isFunction(what) { |
1907 | | - return typeof what === 'function'; |
1908 | | -} |
1909 | | - |
1910 | | -function isString(what) { |
1911 | | - return objectPrototype.toString.call(what) === '[object String]'; |
1912 | | -} |
1913 | | - |
1914 | | -function isEmptyObject(what) { |
1915 | | - for (var _ in what) return false; // eslint-disable-line guard-for-in, no-unused-vars |
1916 | | - return true; |
1917 | | -} |
1918 | | - |
1919 | | -function each(obj, callback) { |
1920 | | - var i, j; |
1921 | | - |
1922 | | - if (isUndefined(obj.length)) { |
1923 | | - for (i in obj) { |
1924 | | - if (hasKey(obj, i)) { |
1925 | | - callback.call(null, i, obj[i]); |
1926 | | - } |
1927 | | - } |
1928 | | - } else { |
1929 | | - j = obj.length; |
1930 | | - if (j) { |
1931 | | - for (i = 0; i < j; i++) { |
1932 | | - callback.call(null, i, obj[i]); |
1933 | | - } |
1934 | | - } |
1935 | | - } |
1936 | | -} |
1937 | | - |
1938 | | -function objectMerge(obj1, obj2) { |
1939 | | - if (!obj2) { |
1940 | | - return obj1; |
1941 | | - } |
1942 | | - each(obj2, function(key, value) { |
1943 | | - obj1[key] = value; |
1944 | | - }); |
1945 | | - return obj1; |
1946 | | -} |
1947 | | - |
1948 | | -/** |
1949 | | - * This function is only used for react-native. |
1950 | | - * react-native freezes object that have already been sent over the |
1951 | | - * js bridge. We need this function in order to check if the object is frozen. |
1952 | | - * So it's ok that objectFrozen returns false if Object.isFrozen is not |
1953 | | - * supported because it's not relevant for other "platforms". See related issue: |
1954 | | - * https://github.com/getsentry/react-native-sentry/issues/57 |
1955 | | - */ |
1956 | | -function objectFrozen(obj) { |
1957 | | - if (!Object.isFrozen) { |
1958 | | - return false; |
1959 | | - } |
1960 | | - return Object.isFrozen(obj); |
1961 | | -} |
1962 | | - |
1963 | | -function truncate(str, max) { |
1964 | | - return !max || str.length <= max ? str : str.substr(0, max) + '\u2026'; |
1965 | | -} |
1966 | | - |
1967 | | -/** |
1968 | | - * hasKey, a better form of hasOwnProperty |
1969 | | - * Example: hasKey(MainHostObject, property) === true/false |
1970 | | - * |
1971 | | - * @param {Object} host object to check property |
1972 | | - * @param {string} key to check |
1973 | | - */ |
1974 | | -function hasKey(object, key) { |
1975 | | - return objectPrototype.hasOwnProperty.call(object, key); |
1976 | | -} |
1977 | | - |
1978 | | -function joinRegExp(patterns) { |
1979 | | - // Combine an array of regular expressions and strings into one large regexp |
1980 | | - // Be mad. |
1981 | | - var sources = [], |
1982 | | - i = 0, |
1983 | | - len = patterns.length, |
1984 | | - pattern; |
1985 | | - |
1986 | | - for (; i < len; i++) { |
1987 | | - pattern = patterns[i]; |
1988 | | - if (isString(pattern)) { |
1989 | | - // If it's a string, we need to escape it |
1990 | | - // Taken from: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions |
1991 | | - sources.push(pattern.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, '\\$1')); |
1992 | | - } else if (pattern && pattern.source) { |
1993 | | - // If it's a regexp already, we want to extract the source |
1994 | | - sources.push(pattern.source); |
1995 | | - } |
1996 | | - // Intentionally skip other cases |
1997 | | - } |
1998 | | - return new RegExp(sources.join('|'), 'i'); |
1999 | | -} |
2000 | | - |
2001 | | -function urlencode(o) { |
2002 | | - var pairs = []; |
2003 | | - each(o, function(key, value) { |
2004 | | - pairs.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); |
2005 | | - }); |
2006 | | - return pairs.join('&'); |
2007 | | -} |
2008 | | - |
2009 | | -// borrowed from https://tools.ietf.org/html/rfc3986#appendix-B |
2010 | | -// intentionally using regex and not <a/> href parsing trick because React Native and other |
2011 | | -// environments where DOM might not be available |
2012 | | -function parseUrl(url) { |
2013 | | - var match = url.match(/^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?$/); |
2014 | | - if (!match) return {}; |
2015 | | - |
2016 | | - // coerce to undefined values to empty string so we don't get 'undefined' |
2017 | | - var query = match[6] || ''; |
2018 | | - var fragment = match[8] || ''; |
2019 | | - return { |
2020 | | - protocol: match[2], |
2021 | | - host: match[4], |
2022 | | - path: match[5], |
2023 | | - relative: match[5] + query + fragment // everything minus origin |
2024 | | - }; |
2025 | | -} |
2026 | | -function uuid4() { |
2027 | | - var crypto = _window.crypto || _window.msCrypto; |
2028 | | - |
2029 | | - if (!isUndefined(crypto) && crypto.getRandomValues) { |
2030 | | - // Use window.crypto API if available |
2031 | | - // eslint-disable-next-line no-undef |
2032 | | - var arr = new Uint16Array(8); |
2033 | | - crypto.getRandomValues(arr); |
2034 | | - |
2035 | | - // set 4 in byte 7 |
2036 | | - arr[3] = (arr[3] & 0xfff) | 0x4000; |
2037 | | - // set 2 most significant bits of byte 9 to '10' |
2038 | | - arr[4] = (arr[4] & 0x3fff) | 0x8000; |
2039 | | - |
2040 | | - var pad = function(num) { |
2041 | | - var v = num.toString(16); |
2042 | | - while (v.length < 4) { |
2043 | | - v = '0' + v; |
2044 | | - } |
2045 | | - return v; |
2046 | | - }; |
2047 | | - |
2048 | | - return ( |
2049 | | - pad(arr[0]) + |
2050 | | - pad(arr[1]) + |
2051 | | - pad(arr[2]) + |
2052 | | - pad(arr[3]) + |
2053 | | - pad(arr[4]) + |
2054 | | - pad(arr[5]) + |
2055 | | - pad(arr[6]) + |
2056 | | - pad(arr[7]) |
2057 | | - ); |
2058 | | - } else { |
2059 | | - // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523 |
2060 | | - return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) { |
2061 | | - var r = (Math.random() * 16) | 0, |
2062 | | - v = c === 'x' ? r : (r & 0x3) | 0x8; |
2063 | | - return v.toString(16); |
2064 | | - }); |
2065 | | - } |
2066 | | -} |
2067 | | - |
2068 | | -/** |
2069 | | - * Given a child DOM element, returns a query-selector statement describing that |
2070 | | - * and its ancestors |
2071 | | - * e.g. [HTMLElement] => body > div > input#foo.btn[name=baz] |
2072 | | - * @param elem |
2073 | | - * @returns {string} |
2074 | | - */ |
2075 | | -function htmlTreeAsString(elem) { |
2076 | | - /* eslint no-extra-parens:0*/ |
2077 | | - var MAX_TRAVERSE_HEIGHT = 5, |
2078 | | - MAX_OUTPUT_LEN = 80, |
2079 | | - out = [], |
2080 | | - height = 0, |
2081 | | - len = 0, |
2082 | | - separator = ' > ', |
2083 | | - sepLength = separator.length, |
2084 | | - nextStr; |
2085 | | - |
2086 | | - while (elem && height++ < MAX_TRAVERSE_HEIGHT) { |
2087 | | - nextStr = htmlElementAsString(elem); |
2088 | | - // bail out if |
2089 | | - // - nextStr is the 'html' element |
2090 | | - // - the length of the string that would be created exceeds MAX_OUTPUT_LEN |
2091 | | - // (ignore this limit if we are on the first iteration) |
2092 | | - if ( |
2093 | | - nextStr === 'html' || |
2094 | | - (height > 1 && len + out.length * sepLength + nextStr.length >= MAX_OUTPUT_LEN) |
2095 | | - ) { |
2096 | | - break; |
2097 | | - } |
2098 | | - |
2099 | | - out.push(nextStr); |
2100 | | - |
2101 | | - len += nextStr.length; |
2102 | | - elem = elem.parentNode; |
2103 | | - } |
2104 | | - |
2105 | | - return out.reverse().join(separator); |
2106 | | -} |
2107 | | - |
2108 | | -/** |
2109 | | - * Returns a simple, query-selector representation of a DOM element |
2110 | | - * e.g. [HTMLElement] => input#foo.btn[name=baz] |
2111 | | - * @param HTMLElement |
2112 | | - * @returns {string} |
2113 | | - */ |
2114 | | -function htmlElementAsString(elem) { |
2115 | | - var out = [], |
2116 | | - className, |
2117 | | - classes, |
2118 | | - key, |
2119 | | - attr, |
2120 | | - i; |
2121 | | - |
2122 | | - if (!elem || !elem.tagName) { |
2123 | | - return ''; |
2124 | | - } |
2125 | | - |
2126 | | - out.push(elem.tagName.toLowerCase()); |
2127 | | - if (elem.id) { |
2128 | | - out.push('#' + elem.id); |
2129 | | - } |
2130 | | - |
2131 | | - className = elem.className; |
2132 | | - if (className && isString(className)) { |
2133 | | - classes = className.split(/\s+/); |
2134 | | - for (i = 0; i < classes.length; i++) { |
2135 | | - out.push('.' + classes[i]); |
2136 | | - } |
2137 | | - } |
2138 | | - var attrWhitelist = ['type', 'name', 'title', 'alt']; |
2139 | | - for (i = 0; i < attrWhitelist.length; i++) { |
2140 | | - key = attrWhitelist[i]; |
2141 | | - attr = elem.getAttribute(key); |
2142 | | - if (attr) { |
2143 | | - out.push('[' + key + '="' + attr + '"]'); |
2144 | | - } |
2145 | | - } |
2146 | | - return out.join(''); |
2147 | | -} |
2148 | | - |
2149 | | -/** |
2150 | | - * Returns true if either a OR b is truthy, but not both |
2151 | | - */ |
2152 | | -function isOnlyOneTruthy(a, b) { |
2153 | | - return !!(!!a ^ !!b); |
2154 | | -} |
2155 | | - |
2156 | | -/** |
2157 | | - * Returns true if the two input exception interfaces have the same content |
2158 | | - */ |
2159 | | -function isSameException(ex1, ex2) { |
2160 | | - if (isOnlyOneTruthy(ex1, ex2)) return false; |
2161 | | - |
2162 | | - ex1 = ex1.values[0]; |
2163 | | - ex2 = ex2.values[0]; |
2164 | | - |
2165 | | - if (ex1.type !== ex2.type || ex1.value !== ex2.value) return false; |
2166 | | - |
2167 | | - return isSameStacktrace(ex1.stacktrace, ex2.stacktrace); |
2168 | | -} |
2169 | | - |
2170 | | -/** |
2171 | | - * Returns true if the two input stack trace interfaces have the same content |
2172 | | - */ |
2173 | | -function isSameStacktrace(stack1, stack2) { |
2174 | | - if (isOnlyOneTruthy(stack1, stack2)) return false; |
2175 | | - |
2176 | | - var frames1 = stack1.frames; |
2177 | | - var frames2 = stack2.frames; |
2178 | | - |
2179 | | - // Exit early if frame count differs |
2180 | | - if (frames1.length !== frames2.length) return false; |
2181 | | - |
2182 | | - // Iterate through every frame; bail out if anything differs |
2183 | | - var a, b; |
2184 | | - for (var i = 0; i < frames1.length; i++) { |
2185 | | - a = frames1[i]; |
2186 | | - b = frames2[i]; |
2187 | | - if ( |
2188 | | - a.filename !== b.filename || |
2189 | | - a.lineno !== b.lineno || |
2190 | | - a.colno !== b.colno || |
2191 | | - a['function'] !== b['function'] |
2192 | | - ) |
2193 | | - return false; |
2194 | | - } |
2195 | | - return true; |
2196 | | -} |
2197 | | - |
2198 | | -/** |
2199 | | - * Polyfill a method |
2200 | | - * @param obj object e.g. `document` |
2201 | | - * @param name method name present on object e.g. `addEventListener` |
2202 | | - * @param replacement replacement function |
2203 | | - * @param track {optional} record instrumentation to an array |
2204 | | - */ |
2205 | | -function fill(obj, name, replacement, track) { |
2206 | | - var orig = obj[name]; |
2207 | | - obj[name] = replacement(orig); |
2208 | | - if (track) { |
2209 | | - track.push([obj, name, orig]); |
2210 | | - } |
2211 | | -} |
2212 | | - |
2213 | | -if (typeof __DEV__ !== 'undefined' && __DEV__) { |
2214 | | - Raven.utils = { |
2215 | | - isUndefined: isUndefined, |
2216 | | - isFunction: isFunction, |
2217 | | - isString: isString, |
2218 | | - isObject: isObject, |
2219 | | - isEmptyObject: isEmptyObject, |
2220 | | - isError: isError, |
2221 | | - each: each, |
2222 | | - objectMerge: objectMerge, |
2223 | | - truncate: truncate, |
2224 | | - hasKey: hasKey, |
2225 | | - joinRegExp: joinRegExp, |
2226 | | - urlencode: urlencode, |
2227 | | - uuid4: uuid4, |
2228 | | - htmlTreeAsString: htmlTreeAsString, |
2229 | | - htmlElementAsString: htmlElementAsString, |
2230 | | - parseUrl: parseUrl, |
2231 | | - fill: fill |
2232 | | - }; |
2233 | | -} |
2234 | | - |
2235 | 1913 | // Deprecations |
2236 | 1914 | Raven.prototype.setUser = Raven.prototype.setUserContext; |
2237 | 1915 | Raven.prototype.setReleaseContext = Raven.prototype.setRelease; |
|
0 commit comments