Skip to content

Commit 0b59724

Browse files
authored
ref: Move utils from raven.js to utils.js file (#1084)
1 parent 955187a commit 0b59724

File tree

4 files changed

+361
-350
lines changed

4 files changed

+361
-350
lines changed

src/raven.js

Lines changed: 23 additions & 345 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,31 @@
1-
/*global XDomainRequest:false, __DEV__:false*/
1+
/*global XDomainRequest:false */
22

33
var TraceKit = require('../vendor/TraceKit/tracekit');
44
var stringify = require('../vendor/json-stringify-safe/stringify');
55
var RavenConfigError = require('./configError');
6-
var utils = require('./utils');
76

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;
1029

1130
var wrapConsoleMethod = require('./console').wrapMethod;
1231

@@ -1891,347 +1910,6 @@ Raven.prototype = {
18911910
}
18921911
};
18931912

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-
22351913
// Deprecations
22361914
Raven.prototype.setUser = Raven.prototype.setUserContext;
22371915
Raven.prototype.setReleaseContext = Raven.prototype.setRelease;

0 commit comments

Comments
 (0)