noibu-react-native 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -7
- package/dist/api/clientConfig.js +50 -48
- package/dist/api/helpCode.js +3 -3
- package/dist/api/inputManager.js +5 -5
- package/dist/api/metroplexSocket.js +31 -43
- package/dist/api/storedMetrics.js +18 -22
- package/dist/api/storedPageVisit.js +27 -29
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +7 -48
- package/dist/entry/index.d.ts +8 -1
- package/dist/entry/index.js +8 -2
- package/dist/entry/init.js +6 -5
- package/dist/monitors/clickMonitor.js +1 -2
- package/dist/monitors/elementMonitor.js +4 -1
- package/dist/monitors/errorMonitor.d.ts +25 -0
- package/dist/monitors/errorMonitor.js +109 -262
- package/dist/monitors/httpDataBundler.js +11 -12
- package/dist/monitors/inputMonitor.js +4 -1
- package/dist/monitors/locationChangeMonitor.js +4 -16
- package/dist/monitors/pageMonitor.js +4 -1
- package/dist/monitors/requestMonitor.js +5 -19
- package/dist/pageVisit/pageVisit.js +3 -1
- package/dist/pageVisit/pageVisitEventError/blacklistedDomains.js +9 -0
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +9 -14
- package/dist/pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js +3 -14
- package/dist/storage/rnStorageProvider.d.ts +23 -0
- package/dist/storage/rnStorageProvider.js +23 -52
- package/dist/storage/storage.d.ts +38 -0
- package/dist/storage/storage.js +69 -104
- package/dist/storage/storageProvider.d.ts +25 -0
- package/dist/storage/storageProvider.js +38 -71
- package/dist/utils/function.js +80 -53
- package/dist/utils/performance.js +0 -7
- package/dist/utils/stacktrace-parser.d.ts +9 -0
- package/dist/utils/stacktrace-parser.js +156 -0
- package/package.json +4 -4
- package/dist/storage/localStorageProvider.js +0 -23
- package/dist/storage/sessionStorageProvider.js +0 -23
package/dist/utils/function.js
CHANGED
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import * as stackTraceParser from 'stacktrace-parser';
|
|
2
1
|
import DeviceInfo from 'react-native-device-info';
|
|
3
|
-
import {
|
|
2
|
+
import { getLocales } from 'react-native-localize';
|
|
3
|
+
import { parseStack } from './stacktrace-parser.js';
|
|
4
|
+
import { MAX_BEACON_PAYLOAD_SIZE, MAX_STRING_LENGTH, REQUIRED_DATA_PROCESSING_URLS, HTTP_DATA_COLLECTION_FLAG_NAME, HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME, WIN_BLOCKED_SELECTOR_ATT_NAME, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, JS_STACK_FRAMES_ATT_NAME, JS_STACK_MESSAGE_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_LINE_ATT_NAME, JS_STACK_COL_ATT_NAME, MAX_FRAMES_IN_ARRAY, NOIBUJS_CONFIG, JS_STACK_METHOD_ATT_NAME, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
|
|
5
|
+
import ClientConfig from '../api/clientConfig.js';
|
|
4
6
|
|
|
5
7
|
/** @module Functions */
|
|
6
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Returns a stack trace frame with default filed values
|
|
11
|
+
*/
|
|
12
|
+
const getDefaultFrame = () => ({
|
|
13
|
+
[JS_STACK_LINE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
14
|
+
[JS_STACK_METHOD_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
15
|
+
[JS_STACK_FILE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
16
|
+
});
|
|
17
|
+
|
|
7
18
|
/**
|
|
8
19
|
*
|
|
9
20
|
* returns a string that satisfies a max length
|
|
@@ -25,61 +36,54 @@ function getMaxSubstringAllowed(
|
|
|
25
36
|
|
|
26
37
|
/**
|
|
27
38
|
*
|
|
39
|
+
* todo implement navigation
|
|
28
40
|
* getProperGlobalUrl gets the proper global url from the window
|
|
41
|
+
* @returns {string}
|
|
29
42
|
*/
|
|
30
43
|
function getProperGlobalUrl() {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
// if it does not follow the http protocol,
|
|
35
|
-
// then we check the parent frame and if that
|
|
36
|
-
// fails then we return what we have without
|
|
37
|
-
// trying anything else
|
|
38
|
-
if (
|
|
39
|
-
(
|
|
40
|
-
(window.location && window.location.href) ||
|
|
41
|
-
'http://localhost'
|
|
42
|
-
).startsWith('http')
|
|
43
|
-
) {
|
|
44
|
-
globalUrl = (window.location && window.location.href) || 'http://localhost';
|
|
45
|
-
} else if (
|
|
46
|
-
window.parent &&
|
|
47
|
-
window.parent.location &&
|
|
48
|
-
window.parent.location.href.startsWith('http')
|
|
49
|
-
) {
|
|
50
|
-
globalUrl = window.parent.location.href;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
return getMaxSubstringAllowed(globalUrl);
|
|
44
|
+
const globalUrl = new URL('https://localhost');
|
|
45
|
+
globalUrl.hostname = ClientConfig.getInstance().customerDomain;
|
|
46
|
+
return getMaxSubstringAllowed(globalUrl.toString());
|
|
54
47
|
}
|
|
55
48
|
|
|
56
49
|
/**
|
|
57
50
|
* Processes the raw stack frames and creates a readable stack in a safe manner
|
|
58
|
-
* @param rawFrames
|
|
51
|
+
* @param {StackFrame[]} rawFrames
|
|
59
52
|
*/
|
|
60
53
|
function processFrames(rawFrames) {
|
|
61
54
|
return rawFrames.map(frame => {
|
|
62
|
-
const processedFrame =
|
|
63
|
-
[JS_STACK_LINE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
64
|
-
[JS_STACK_METHOD_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
65
|
-
[JS_STACK_FILE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
66
|
-
};
|
|
55
|
+
const processedFrame = getDefaultFrame();
|
|
67
56
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
57
|
+
if (frame[JS_STACK_LINE_ATT_NAME]) {
|
|
58
|
+
if (Number.isInteger(frame[JS_STACK_LINE_ATT_NAME])) {
|
|
59
|
+
processedFrame[JS_STACK_LINE_ATT_NAME] = String(
|
|
60
|
+
frame[JS_STACK_LINE_ATT_NAME],
|
|
61
|
+
);
|
|
62
|
+
}
|
|
71
63
|
}
|
|
72
64
|
|
|
73
|
-
if (
|
|
74
|
-
|
|
65
|
+
if (
|
|
66
|
+
frame[JS_STACK_METHOD_ATT_NAME] &&
|
|
67
|
+
frame[JS_STACK_METHOD_ATT_NAME] !== '<unknown>'
|
|
68
|
+
) {
|
|
69
|
+
processedFrame[JS_STACK_METHOD_ATT_NAME] = String(
|
|
70
|
+
frame[JS_STACK_METHOD_ATT_NAME],
|
|
71
|
+
);
|
|
75
72
|
}
|
|
76
73
|
|
|
77
|
-
if (
|
|
78
|
-
|
|
74
|
+
if (
|
|
75
|
+
frame[JS_STACK_FILE_ATT_NAME] &&
|
|
76
|
+
frame[JS_STACK_FILE_ATT_NAME] !== '<unknown>'
|
|
77
|
+
) {
|
|
78
|
+
processedFrame[JS_STACK_FILE_ATT_NAME] = String(
|
|
79
|
+
frame[JS_STACK_FILE_ATT_NAME],
|
|
80
|
+
);
|
|
79
81
|
}
|
|
80
82
|
|
|
81
|
-
if (frame
|
|
82
|
-
|
|
83
|
+
if (frame[JS_STACK_COL_ATT_NAME]) {
|
|
84
|
+
if (Number.isInteger(frame[JS_STACK_COL_ATT_NAME])) {
|
|
85
|
+
processedFrame[JS_STACK_COL_ATT_NAME] = frame[JS_STACK_COL_ATT_NAME];
|
|
86
|
+
}
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
return processedFrame;
|
|
@@ -120,7 +124,7 @@ function getJSStack(errObj) {
|
|
|
120
124
|
frames[0][JS_STACK_COL_ATT_NAME] = errObj.columnNumber;
|
|
121
125
|
}
|
|
122
126
|
} else {
|
|
123
|
-
frames = processFrames(
|
|
127
|
+
frames = processFrames(parseStack(errObj.stack));
|
|
124
128
|
}
|
|
125
129
|
|
|
126
130
|
if (frames.length >= MAX_FRAMES_IN_ARRAY) {
|
|
@@ -134,6 +138,18 @@ function getJSStack(errObj) {
|
|
|
134
138
|
};
|
|
135
139
|
}
|
|
136
140
|
|
|
141
|
+
/**
|
|
142
|
+
* @param {string} possiblyStacktrace
|
|
143
|
+
* @returns {boolean}
|
|
144
|
+
*/
|
|
145
|
+
function isStackTrace(possiblyStacktrace) {
|
|
146
|
+
try {
|
|
147
|
+
return parseStack(possiblyStacktrace).length > 0;
|
|
148
|
+
} catch (e) {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
137
153
|
/**
|
|
138
154
|
* safely stringifies an object
|
|
139
155
|
* @param jsonObject
|
|
@@ -166,7 +182,7 @@ function stringifyJSON(jsonObject) {
|
|
|
166
182
|
* @param timeout
|
|
167
183
|
* @param sendAndForget
|
|
168
184
|
*/
|
|
169
|
-
function makeRequest(
|
|
185
|
+
async function makeRequest(
|
|
170
186
|
method,
|
|
171
187
|
url,
|
|
172
188
|
data,
|
|
@@ -174,12 +190,20 @@ function makeRequest(
|
|
|
174
190
|
timeout,
|
|
175
191
|
sendAndForget,
|
|
176
192
|
) {
|
|
177
|
-
|
|
193
|
+
const ua = Object.keys(headers).findLast(
|
|
194
|
+
k => k.toLowerCase() === 'user-agent',
|
|
195
|
+
);
|
|
196
|
+
const headersWithUa = { ...headers };
|
|
197
|
+
if (!headers[ua]) {
|
|
198
|
+
headersWithUa['User-Agent'] = await getUserAgent();
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// a send-and-forget request is made by using the beacon API (fetch + keepalive)
|
|
178
202
|
if (sendAndForget) {
|
|
179
203
|
const stringData = stringifyJSON(data);
|
|
180
204
|
const currentPayloadSize = new Blob([stringData]).size;
|
|
181
205
|
// if we have a large object or fetch is not available, we skip sending the message
|
|
182
|
-
if (!
|
|
206
|
+
if (!global.fetch || currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
|
|
183
207
|
return new Promise(resolve => {
|
|
184
208
|
resolve();
|
|
185
209
|
});
|
|
@@ -187,7 +211,7 @@ function makeRequest(
|
|
|
187
211
|
|
|
188
212
|
return fetch(url, {
|
|
189
213
|
method: 'POST',
|
|
190
|
-
headers,
|
|
214
|
+
headers: headersWithUa,
|
|
191
215
|
body: stringifyJSON(data),
|
|
192
216
|
// keep alive outlives the current page, its the same as beacon
|
|
193
217
|
keepalive: true,
|
|
@@ -195,10 +219,10 @@ function makeRequest(
|
|
|
195
219
|
}
|
|
196
220
|
|
|
197
221
|
return new Promise((resolve, reject) => {
|
|
198
|
-
const xhr = new XMLHttpRequest();
|
|
222
|
+
const xhr = new global.XMLHttpRequest();
|
|
199
223
|
xhr.open(method, url);
|
|
200
224
|
xhr.timeout = timeout;
|
|
201
|
-
Object.keys(
|
|
225
|
+
Object.keys(headersWithUa).forEach(header => {
|
|
202
226
|
xhr.setRequestHeader(header, headers[header]);
|
|
203
227
|
});
|
|
204
228
|
|
|
@@ -302,7 +326,7 @@ async function getUserAgent() {
|
|
|
302
326
|
/**
|
|
303
327
|
* isInvalidURLConfig will verify that Collect is being initializes with
|
|
304
328
|
* the correct env vars.
|
|
305
|
-
* @param {} urlConfig
|
|
329
|
+
* @param {Noibu.UrlConfig} urlConfig
|
|
306
330
|
*/
|
|
307
331
|
function isInvalidURLConfig(urlConfig) {
|
|
308
332
|
for (let i = 0; i < REQUIRED_DATA_PROCESSING_URLS.length; i += 1) {
|
|
@@ -359,9 +383,8 @@ function maskTextInput(text) {
|
|
|
359
383
|
* @param {} realOnURL
|
|
360
384
|
*/
|
|
361
385
|
function getOnURL(realOnURL) {
|
|
362
|
-
let onURL =
|
|
363
|
-
|
|
364
|
-
);
|
|
386
|
+
let onURL = getProperGlobalUrl();
|
|
387
|
+
|
|
365
388
|
if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
|
|
366
389
|
onURL = asString(getMaxSubstringAllowed(realOnURL));
|
|
367
390
|
}
|
|
@@ -371,7 +394,11 @@ function getOnURL(realOnURL) {
|
|
|
371
394
|
|
|
372
395
|
/** gets the user language from the browser */
|
|
373
396
|
function getUserLanguage() {
|
|
374
|
-
const
|
|
397
|
+
const locales = getLocales();
|
|
398
|
+
if (!locales.length) {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
const lang = locales[0].languageCode;
|
|
375
402
|
|
|
376
403
|
if (lang === '' || !lang) {
|
|
377
404
|
return null;
|
|
@@ -395,4 +422,4 @@ function isInstanceOf(instance, type) {
|
|
|
395
422
|
}
|
|
396
423
|
}
|
|
397
424
|
|
|
398
|
-
export { asString, checkHttpDataCollectionEnabled, getBlockedCSSForCurrentDomain, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getProperGlobalUrl, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
|
|
425
|
+
export { asString, checkHttpDataCollectionEnabled, getBlockedCSSForCurrentDomain, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getProperGlobalUrl, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
|
|
@@ -8,13 +8,6 @@ import { timestampWrapper } from './date.js';
|
|
|
8
8
|
* we return Date.now() instead.
|
|
9
9
|
*/
|
|
10
10
|
function safePerformanceNow() {
|
|
11
|
-
if (window.performance && window.performance.now) {
|
|
12
|
-
// There is a 70% hit with using this
|
|
13
|
-
// https://jsperf.com/perf-vs-date/1
|
|
14
|
-
// performance.now is for relative time measurement
|
|
15
|
-
// cannot be used instead of Date.getTime() on it's own
|
|
16
|
-
return window.performance.now();
|
|
17
|
-
}
|
|
18
11
|
return timestampWrapper(Date.now());
|
|
19
12
|
}
|
|
20
13
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { JS_STACK_COL_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_LINE_ATT_NAME, JS_STACK_METHOD_ATT_NAME } from '../constants';
|
|
2
|
+
declare interface StackFrame {
|
|
3
|
+
[JS_STACK_FILE_ATT_NAME]: string;
|
|
4
|
+
[JS_STACK_LINE_ATT_NAME]?: number;
|
|
5
|
+
[JS_STACK_COL_ATT_NAME]?: number;
|
|
6
|
+
[JS_STACK_METHOD_ATT_NAME]: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function parseStack(stackString: string): StackFrame[];
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { MAX_FRAMES_IN_ARRAY, MAX_STRING_LENGTH, JS_STACK_LINE_ATT_NAME, JS_STACK_COL_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_METHOD_ATT_NAME } from '../constants.js';
|
|
2
|
+
|
|
3
|
+
/* eslint-disable require-jsdoc,prefer-destructuring,camelcase */
|
|
4
|
+
// This is a loose copy of ravenjs code
|
|
5
|
+
// Copyright (c) 2013 Onur Can Cakmak onur.cakmak@gmail.com and all TraceKit contributors.
|
|
6
|
+
//
|
|
7
|
+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
8
|
+
// software and associated documentation files(the 'Software'), to deal in the Software
|
|
9
|
+
// without restriction, including without limitation the rights to use, copy, modify,
|
|
10
|
+
// merge, publish, distribute, sublicense, and / or sell copies of the Software, and to
|
|
11
|
+
// permit persons to whom the Software is furnished to do so, subject to the following
|
|
12
|
+
// conditions:
|
|
13
|
+
//
|
|
14
|
+
// The above copyright notice and this permission notice shall be included in all copies
|
|
15
|
+
// or substantial portions of the Software.
|
|
16
|
+
//
|
|
17
|
+
// THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
18
|
+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
|
19
|
+
// PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
20
|
+
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
|
21
|
+
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
|
|
22
|
+
// OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
23
|
+
// global reference to slice
|
|
24
|
+
const UNKNOWN_FUNCTION = '<unknown>';
|
|
25
|
+
/**
|
|
26
|
+
* Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
|
|
27
|
+
* What it means, is that instead of format like:
|
|
28
|
+
*
|
|
29
|
+
* Error: wat
|
|
30
|
+
* at function@url:row:col
|
|
31
|
+
* at function@url:row:col
|
|
32
|
+
* at function@url:row:col
|
|
33
|
+
*
|
|
34
|
+
* it produces something like:
|
|
35
|
+
*
|
|
36
|
+
* function@url:row:col
|
|
37
|
+
* function@url:row:col
|
|
38
|
+
* function@url:row:col
|
|
39
|
+
*
|
|
40
|
+
* Because of that, it won't be captured by `chrome` RegExp and will fall into `Gecko` branch.
|
|
41
|
+
* This function is extracted so that we can use it in both places without duplicating the logic.
|
|
42
|
+
* Unfortunately "just" changing RegExp is too complicated now and making it pass all tests
|
|
43
|
+
* and fix this case seems like an impossible, or at least way too time-consuming task.
|
|
44
|
+
*/
|
|
45
|
+
const extractSafariExtensionDetails = (func, filename) => {
|
|
46
|
+
const isSafariExtension = func.indexOf('safari-extension') !== -1;
|
|
47
|
+
const isSafariWebExtension = func.indexOf('safari-web-extension') !== -1;
|
|
48
|
+
return isSafariExtension || isSafariWebExtension
|
|
49
|
+
? [
|
|
50
|
+
func.indexOf('@') !== -1 ? func.split('@')[0] : UNKNOWN_FUNCTION,
|
|
51
|
+
isSafariExtension
|
|
52
|
+
? `safari-extension:${filename}`
|
|
53
|
+
: `safari-web-extension:${filename}`,
|
|
54
|
+
]
|
|
55
|
+
: [func, filename];
|
|
56
|
+
};
|
|
57
|
+
function createFrame(filename, func, lineno, colno) {
|
|
58
|
+
const frame = {
|
|
59
|
+
[JS_STACK_FILE_ATT_NAME]: filename,
|
|
60
|
+
[JS_STACK_METHOD_ATT_NAME]: func,
|
|
61
|
+
};
|
|
62
|
+
if (lineno !== undefined) {
|
|
63
|
+
frame[JS_STACK_LINE_ATT_NAME] = lineno;
|
|
64
|
+
}
|
|
65
|
+
if (colno !== undefined) {
|
|
66
|
+
frame[JS_STACK_COL_ATT_NAME] = colno;
|
|
67
|
+
}
|
|
68
|
+
return frame;
|
|
69
|
+
}
|
|
70
|
+
// Chromium based browsers: Chrome, Brave, new Opera, new Edge
|
|
71
|
+
const chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
|
|
72
|
+
const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
|
|
73
|
+
const chrome = (line) => {
|
|
74
|
+
const parts = chromeRegex.exec(line);
|
|
75
|
+
if (parts) {
|
|
76
|
+
const isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
|
|
77
|
+
if (isEval) {
|
|
78
|
+
const subMatch = chromeEvalRegex.exec(parts[2]);
|
|
79
|
+
if (subMatch) {
|
|
80
|
+
// throw out eval line/column and use top-most line/column number
|
|
81
|
+
parts[2] = subMatch[1]; // url
|
|
82
|
+
parts[3] = subMatch[2]; // line
|
|
83
|
+
parts[4] = subMatch[3]; // column
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
|
|
87
|
+
return createFrame(filename, func, parts[3] ? +parts[3] : undefined, parts[4] ? +parts[4] : undefined);
|
|
88
|
+
}
|
|
89
|
+
return undefined;
|
|
90
|
+
};
|
|
91
|
+
const geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
92
|
+
const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
93
|
+
const gecko = (line) => {
|
|
94
|
+
const parts = geckoREgex.exec(line);
|
|
95
|
+
if (parts) {
|
|
96
|
+
const isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
|
|
97
|
+
if (isEval) {
|
|
98
|
+
const subMatch = geckoEvalRegex.exec(parts[3]);
|
|
99
|
+
if (subMatch) {
|
|
100
|
+
// throw out eval line/column and use top-most line number
|
|
101
|
+
parts[1] = parts[1] || 'eval';
|
|
102
|
+
parts[3] = subMatch[1];
|
|
103
|
+
parts[4] = subMatch[2];
|
|
104
|
+
parts[5] = ''; // no column when eval
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
let filename = parts[3];
|
|
108
|
+
let func = parts[1] || UNKNOWN_FUNCTION;
|
|
109
|
+
[func, filename] = extractSafariExtensionDetails(func, filename);
|
|
110
|
+
return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined);
|
|
111
|
+
}
|
|
112
|
+
return undefined;
|
|
113
|
+
};
|
|
114
|
+
const winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
115
|
+
const winjs = (line) => {
|
|
116
|
+
const parts = winjsRegex.exec(line);
|
|
117
|
+
return parts
|
|
118
|
+
? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined)
|
|
119
|
+
: undefined;
|
|
120
|
+
};
|
|
121
|
+
const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
|
|
122
|
+
const opera10 = (line) => {
|
|
123
|
+
const parts = opera10Regex.exec(line);
|
|
124
|
+
return parts
|
|
125
|
+
? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1])
|
|
126
|
+
: undefined;
|
|
127
|
+
};
|
|
128
|
+
const opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
|
|
129
|
+
const opera11 = (line) => {
|
|
130
|
+
const parts = opera11Regex.exec(line);
|
|
131
|
+
return parts
|
|
132
|
+
? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2])
|
|
133
|
+
: undefined;
|
|
134
|
+
};
|
|
135
|
+
function parseStack(stackString) {
|
|
136
|
+
const lines = stackString.split('\n');
|
|
137
|
+
if (lines.length > MAX_FRAMES_IN_ARRAY) {
|
|
138
|
+
return [];
|
|
139
|
+
}
|
|
140
|
+
return lines.reduce((stack, line) => {
|
|
141
|
+
if (line.length > MAX_STRING_LENGTH) {
|
|
142
|
+
return stack;
|
|
143
|
+
}
|
|
144
|
+
const parseResult = gecko(line) ||
|
|
145
|
+
chrome(line) ||
|
|
146
|
+
winjs(line) ||
|
|
147
|
+
opera11(line) ||
|
|
148
|
+
opera10(line);
|
|
149
|
+
if (parseResult) {
|
|
150
|
+
stack.push(parseResult);
|
|
151
|
+
}
|
|
152
|
+
return stack;
|
|
153
|
+
}, []);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export { parseStack };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noibu-react-native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "React-Native SDK for NoibuJS to collect errors in React-Native applications",
|
|
5
5
|
"main": "dist/entry/index.js",
|
|
6
6
|
"types": "dist/entry/index.d.ts",
|
|
@@ -10,7 +10,6 @@
|
|
|
10
10
|
],
|
|
11
11
|
"author": "Noibu Inc",
|
|
12
12
|
"license": "ISC",
|
|
13
|
-
|
|
14
13
|
"scripts": {
|
|
15
14
|
"clean": "rimraf ./dist/*",
|
|
16
15
|
"build": "node ./build.js",
|
|
@@ -21,13 +20,14 @@
|
|
|
21
20
|
"lint_output": "eslint src -c .eslintrc.json --ext js,ts,jsx,tsx -f json > eslint_report.json",
|
|
22
21
|
"codecov": "codecov"
|
|
23
22
|
},
|
|
24
|
-
"
|
|
23
|
+
"dependencies": {
|
|
25
24
|
"react": ">=16.11.0",
|
|
26
25
|
"react-native": ">=0.63.0",
|
|
26
|
+
"@react-native-async-storage/async-storage": "^1.19.0",
|
|
27
27
|
"react-native-device-info": "^10.6.0",
|
|
28
28
|
"react-native-url-polyfill": "^1.3.0",
|
|
29
29
|
"react-native-uuid": "^2.0.1",
|
|
30
|
-
"
|
|
30
|
+
"react-native-localize": "^3.0.1"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@rollup/plugin-commonjs": "^25.0.0",
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import StorageProvider from './storageProvider.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Local storage provider implementation
|
|
5
|
-
*/
|
|
6
|
-
class LocalStorageProvider extends StorageProvider {
|
|
7
|
-
/**
|
|
8
|
-
* Creates new instance
|
|
9
|
-
*/
|
|
10
|
-
constructor() {
|
|
11
|
-
super(window.localStorage);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Checks if storage is available
|
|
16
|
-
* @returns {Object}
|
|
17
|
-
*/
|
|
18
|
-
static isAvailable() {
|
|
19
|
-
return StorageProvider.isAvailable(() => window.localStorage);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export { LocalStorageProvider as default };
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import StorageProvider from './storageProvider.js';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Session storage provider implementation
|
|
5
|
-
*/
|
|
6
|
-
class SessionStorageProvider extends StorageProvider {
|
|
7
|
-
/**
|
|
8
|
-
* Creates new instance
|
|
9
|
-
*/
|
|
10
|
-
constructor() {
|
|
11
|
-
super(window.sessionStorage);
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Checks if storage is available
|
|
16
|
-
* @returns {Object}
|
|
17
|
-
*/
|
|
18
|
-
static isAvailable() {
|
|
19
|
-
return StorageProvider.isAvailable(() => window.sessionStorage);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
export { SessionStorageProvider as default };
|