@cloudcare/browser-core 1.0.16 → 1.0.19
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/cjs/configuration.js +20 -1
- package/cjs/dataMap.js +1 -0
- package/cjs/errorCollection.js +9 -5
- package/cjs/helper/errorTools.js +39 -1
- package/cjs/helper/tools.js +116 -3
- package/esm/configuration.js +18 -1
- package/esm/dataMap.js +1 -0
- package/esm/errorCollection.js +11 -7
- package/esm/helper/errorTools.js +37 -2
- package/esm/helper/tools.js +113 -3
- package/package.json +2 -2
- package/src/configuration.js +14 -1
- package/src/dataMap.js +1 -0
- package/src/errorCollection.js +12 -7
- package/src/helper/errorTools.js +39 -2
- package/src/helper/tools.js +108 -4
package/cjs/configuration.js
CHANGED
|
@@ -91,6 +91,7 @@ function commonInit(userConfiguration, buildEnv) {
|
|
|
91
91
|
applicationId: userConfiguration.applicationId,
|
|
92
92
|
env: userConfiguration.env || '',
|
|
93
93
|
version: userConfiguration.version || '',
|
|
94
|
+
service: userConfiguration.service || 'browser',
|
|
94
95
|
sdkVersion: buildEnv.sdkVersion,
|
|
95
96
|
sdkName: buildEnv.sdkName,
|
|
96
97
|
datakitUrl: getDatakitUrl(userConfiguration.datakitUrl || userConfiguration.datakitOrigin),
|
|
@@ -150,5 +151,23 @@ function mustUseSecureCookie(userConfiguration) {
|
|
|
150
151
|
}
|
|
151
152
|
|
|
152
153
|
function isIntakeRequest(url, configuration) {
|
|
153
|
-
return
|
|
154
|
+
// return haveSameOrigin(url, configuration.datakitUrl)
|
|
155
|
+
var notTakeRequest = [configuration.datakitUrl];
|
|
156
|
+
|
|
157
|
+
if (configuration.logsEndpoint) {
|
|
158
|
+
notTakeRequest.push(configuration.logsEndpoint);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
var isIntake = false;
|
|
162
|
+
|
|
163
|
+
for (var _i = 0, _notTakeRequest = notTakeRequest; _i < _notTakeRequest.length; _i++) {
|
|
164
|
+
var _url = _notTakeRequest[_i];
|
|
165
|
+
|
|
166
|
+
if (url.indexOf(_url) === 0) {
|
|
167
|
+
isIntake = true;
|
|
168
|
+
break;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
return isIntake;
|
|
154
173
|
}
|
package/cjs/dataMap.js
CHANGED
|
@@ -102,6 +102,7 @@ var dataMap = {
|
|
|
102
102
|
tags: {
|
|
103
103
|
error_source: 'error.source',
|
|
104
104
|
error_type: 'error.type',
|
|
105
|
+
error_handling: 'error.handling',
|
|
105
106
|
resource_url: 'error.resource.url',
|
|
106
107
|
resource_url_host: 'error.resource.url_host',
|
|
107
108
|
resource_url_path: 'error.resource.url_path',
|
package/cjs/errorCollection.js
CHANGED
|
@@ -46,14 +46,16 @@ function startConsoleTracking(errorObservable) {
|
|
|
46
46
|
|
|
47
47
|
console.error = function () {
|
|
48
48
|
originalConsoleError.apply(console, arguments);
|
|
49
|
-
|
|
49
|
+
var handlingStack = (0, _errorTools.createHandlingStack)();
|
|
50
|
+
errorObservable.notify((0, _tools.extend)({}, buildErrorFromParams((0, _tools.toArray)(arguments), handlingStack), {
|
|
50
51
|
source: _errorTools.ErrorSource.CONSOLE,
|
|
51
|
-
startClocks: (0, _tools.clocksNow)()
|
|
52
|
+
startClocks: (0, _tools.clocksNow)(),
|
|
53
|
+
handling: _enums.ErrorHandling.HANDLED
|
|
52
54
|
}));
|
|
53
55
|
};
|
|
54
56
|
}
|
|
55
57
|
|
|
56
|
-
function buildErrorFromParams(params) {
|
|
58
|
+
function buildErrorFromParams(params, handlingStack) {
|
|
57
59
|
var firstErrorParam = (0, _tools.find)(params, function (param) {
|
|
58
60
|
return param instanceof Error;
|
|
59
61
|
});
|
|
@@ -63,7 +65,8 @@ function buildErrorFromParams(params) {
|
|
|
63
65
|
}).join(' ');
|
|
64
66
|
return {
|
|
65
67
|
message: message,
|
|
66
|
-
stack: firstErrorParam ? (0, _errorTools.toStackTraceString)((0, _tracekit.computeStackTrace)(firstErrorParam)) : undefined
|
|
68
|
+
stack: firstErrorParam ? (0, _errorTools.toStackTraceString)((0, _tracekit.computeStackTrace)(firstErrorParam)) : undefined,
|
|
69
|
+
handlingStack: handlingStack
|
|
67
70
|
};
|
|
68
71
|
}
|
|
69
72
|
|
|
@@ -93,7 +96,8 @@ function startRuntimeErrorTracking(errorObservable) {
|
|
|
93
96
|
stack: error.stack,
|
|
94
97
|
type: error.type,
|
|
95
98
|
source: _errorTools.ErrorSource.SOURCE,
|
|
96
|
-
startClocks: (0, _tools.clocksNow)()
|
|
99
|
+
startClocks: (0, _tools.clocksNow)(),
|
|
100
|
+
handling: _enums.ErrorHandling.UNHANDLED
|
|
97
101
|
});
|
|
98
102
|
};
|
|
99
103
|
|
package/cjs/helper/errorTools.js
CHANGED
|
@@ -4,12 +4,15 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.formatUnknownError = formatUnknownError;
|
|
7
|
+
exports.createHandlingStack = createHandlingStack;
|
|
7
8
|
exports.toStackTraceString = toStackTraceString;
|
|
8
9
|
exports.formatErrorMessage = formatErrorMessage;
|
|
9
10
|
exports.ErrorSource = void 0;
|
|
10
11
|
|
|
11
12
|
var _tools = require("./tools");
|
|
12
13
|
|
|
14
|
+
var _tracekit = require("../tracekit");
|
|
15
|
+
|
|
13
16
|
var ErrorSource = {
|
|
14
17
|
AGENT: 'agent',
|
|
15
18
|
CONSOLE: 'console',
|
|
@@ -20,11 +23,12 @@ var ErrorSource = {
|
|
|
20
23
|
};
|
|
21
24
|
exports.ErrorSource = ErrorSource;
|
|
22
25
|
|
|
23
|
-
function formatUnknownError(stackTrace, errorObject, nonErrorPrefix) {
|
|
26
|
+
function formatUnknownError(stackTrace, errorObject, nonErrorPrefix, handlingStack) {
|
|
24
27
|
if (!stackTrace || stackTrace.message === undefined && !(errorObject instanceof Error)) {
|
|
25
28
|
return {
|
|
26
29
|
message: nonErrorPrefix + '' + JSON.stringify(errorObject),
|
|
27
30
|
stack: 'No stack, consider using an instance of Error',
|
|
31
|
+
handlingStack: handlingStack,
|
|
28
32
|
type: stackTrace && stackTrace.name
|
|
29
33
|
};
|
|
30
34
|
}
|
|
@@ -32,9 +36,43 @@ function formatUnknownError(stackTrace, errorObject, nonErrorPrefix) {
|
|
|
32
36
|
return {
|
|
33
37
|
message: stackTrace.message || 'Empty message',
|
|
34
38
|
stack: toStackTraceString(stackTrace),
|
|
39
|
+
handlingStack: handlingStack,
|
|
35
40
|
type: stackTrace.name
|
|
36
41
|
};
|
|
37
42
|
}
|
|
43
|
+
/**
|
|
44
|
+
Creates a stacktrace without SDK internal frames.
|
|
45
|
+
|
|
46
|
+
Constraints:
|
|
47
|
+
- Has to be called at the utmost position of the call stack.
|
|
48
|
+
- No internal monitoring should encapsulate the function, that is why we need to use callMonitored inside of it.
|
|
49
|
+
*/
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
function createHandlingStack() {
|
|
53
|
+
/**
|
|
54
|
+
* Skip the two internal frames:
|
|
55
|
+
* - SDK API (console.error, ...)
|
|
56
|
+
* - this function
|
|
57
|
+
* in order to keep only the user calls
|
|
58
|
+
*/
|
|
59
|
+
var internalFramesToSkip = 2;
|
|
60
|
+
var error = new Error();
|
|
61
|
+
var formattedStack; // IE needs to throw the error to fill in the stack trace
|
|
62
|
+
|
|
63
|
+
if (!error.stack) {
|
|
64
|
+
try {
|
|
65
|
+
throw error;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
(0, _tools.noop)();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
var stackTrace = (0, _tracekit.computeStackTrace)(error);
|
|
72
|
+
stackTrace.stack = stackTrace.stack.slice(internalFramesToSkip);
|
|
73
|
+
formattedStack = toStackTraceString(stackTrace);
|
|
74
|
+
return formattedStack;
|
|
75
|
+
}
|
|
38
76
|
|
|
39
77
|
function toStackTraceString(stack) {
|
|
40
78
|
var result = stack.name || 'Error' + ': ' + stack.message;
|
package/cjs/helper/tools.js
CHANGED
|
@@ -5,6 +5,9 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.UUID = UUID;
|
|
7
7
|
exports.replaceNumberCharByPath = replaceNumberCharByPath;
|
|
8
|
+
exports.getType = getType;
|
|
9
|
+
exports.mergeInto = mergeInto;
|
|
10
|
+
exports.deepClone = deepClone;
|
|
8
11
|
exports.getStatusGroup = getStatusGroup;
|
|
9
12
|
exports.jsonStringify = jsonStringify;
|
|
10
13
|
exports.noop = noop;
|
|
@@ -803,8 +806,8 @@ var urlParse = function urlParse(para) {
|
|
|
803
806
|
|
|
804
807
|
URLParser.prototype.getUrl = function () {
|
|
805
808
|
var url = '';
|
|
806
|
-
url += this._values.Origin;
|
|
807
|
-
|
|
809
|
+
url += this._values.Origin; // url += this._values.Port ? ':' + this._values.Port : ''
|
|
810
|
+
|
|
808
811
|
url += this._values.Path;
|
|
809
812
|
url += this._values.QueryString ? '?' + this._values.QueryString : '';
|
|
810
813
|
return url;
|
|
@@ -825,8 +828,11 @@ var urlParse = function urlParse(para) {
|
|
|
825
828
|
}
|
|
826
829
|
}
|
|
827
830
|
|
|
831
|
+
this._values['Path'] = this._values['Path'] || '/';
|
|
828
832
|
this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '');
|
|
829
|
-
this._values['Origin'] = this._values['Protocol'] + '://' + this._values['Hostname'];
|
|
833
|
+
this._values['Origin'] = this._values['Protocol'] + '://' + this._values['Hostname'] + (this._values.Port ? ':' + this._values.Port : ''); // this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '')
|
|
834
|
+
// this._values['Origin'] =
|
|
835
|
+
// this._values['Protocol'] + '://' + this._values['Hostname']
|
|
830
836
|
};
|
|
831
837
|
|
|
832
838
|
return new URLParser(para);
|
|
@@ -1309,6 +1315,113 @@ var getURLSearchParams = function getURLSearchParams(queryString) {
|
|
|
1309
1315
|
|
|
1310
1316
|
exports.getURLSearchParams = getURLSearchParams;
|
|
1311
1317
|
|
|
1318
|
+
function createCircularReferenceChecker() {
|
|
1319
|
+
if (typeof WeakSet !== 'undefined') {
|
|
1320
|
+
var set = new WeakSet();
|
|
1321
|
+
return {
|
|
1322
|
+
hasAlreadyBeenSeen: function hasAlreadyBeenSeen(value) {
|
|
1323
|
+
var has = set.has(value);
|
|
1324
|
+
|
|
1325
|
+
if (!has) {
|
|
1326
|
+
set.add(value);
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
return has;
|
|
1330
|
+
}
|
|
1331
|
+
};
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
var array = [];
|
|
1335
|
+
return {
|
|
1336
|
+
hasAlreadyBeenSeen: function hasAlreadyBeenSeen(value) {
|
|
1337
|
+
var has = array.indexOf(value) >= 0;
|
|
1338
|
+
|
|
1339
|
+
if (!has) {
|
|
1340
|
+
array.push(value);
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
return has;
|
|
1344
|
+
}
|
|
1345
|
+
};
|
|
1346
|
+
}
|
|
1347
|
+
/**
|
|
1348
|
+
* Similar to `typeof`, but distinguish plain objects from `null` and arrays
|
|
1349
|
+
*/
|
|
1350
|
+
|
|
1351
|
+
|
|
1352
|
+
function getType(value) {
|
|
1353
|
+
if (value === null) {
|
|
1354
|
+
return 'null';
|
|
1355
|
+
}
|
|
1356
|
+
|
|
1357
|
+
if (Array.isArray(value)) {
|
|
1358
|
+
return 'array';
|
|
1359
|
+
}
|
|
1360
|
+
|
|
1361
|
+
return _typeof(value);
|
|
1362
|
+
}
|
|
1363
|
+
/**
|
|
1364
|
+
* Iterate over source and affect its sub values into destination, recursively.
|
|
1365
|
+
* If the source and destination can't be merged, return source.
|
|
1366
|
+
*/
|
|
1367
|
+
|
|
1368
|
+
|
|
1369
|
+
function mergeInto(destination, source, circularReferenceChecker) {
|
|
1370
|
+
// ignore the source if it is undefined
|
|
1371
|
+
if (typeof circularReferenceChecker === 'undefined') {
|
|
1372
|
+
circularReferenceChecker = createCircularReferenceChecker();
|
|
1373
|
+
}
|
|
1374
|
+
|
|
1375
|
+
if (source === undefined) {
|
|
1376
|
+
return destination;
|
|
1377
|
+
}
|
|
1378
|
+
|
|
1379
|
+
if (_typeof(source) !== 'object' || source === null) {
|
|
1380
|
+
// primitive values - just return source
|
|
1381
|
+
return source;
|
|
1382
|
+
} else if (source instanceof Date) {
|
|
1383
|
+
return new Date(source.getTime());
|
|
1384
|
+
} else if (source instanceof RegExp) {
|
|
1385
|
+
var flags = source.flags || // old browsers compatibility
|
|
1386
|
+
[source.global ? 'g' : '', source.ignoreCase ? 'i' : '', source.multiline ? 'm' : '', source.sticky ? 'y' : '', source.unicode ? 'u' : ''].join('');
|
|
1387
|
+
return new RegExp(source.source, flags);
|
|
1388
|
+
}
|
|
1389
|
+
|
|
1390
|
+
if (circularReferenceChecker.hasAlreadyBeenSeen(source)) {
|
|
1391
|
+
// remove circular references
|
|
1392
|
+
return undefined;
|
|
1393
|
+
} else if (Array.isArray(source)) {
|
|
1394
|
+
var merged = Array.isArray(destination) ? destination : [];
|
|
1395
|
+
|
|
1396
|
+
for (var i = 0; i < source.length; ++i) {
|
|
1397
|
+
merged[i] = mergeInto(merged[i], source[i], circularReferenceChecker);
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
return merged;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
var merged = getType(destination) === 'object' ? destination : {};
|
|
1404
|
+
|
|
1405
|
+
for (var key in source) {
|
|
1406
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1407
|
+
merged[key] = mergeInto(merged[key], source[key], circularReferenceChecker);
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
return merged;
|
|
1412
|
+
}
|
|
1413
|
+
/**
|
|
1414
|
+
* A simplistic implementation of a deep clone algorithm.
|
|
1415
|
+
* Caveats:
|
|
1416
|
+
* - It doesn't maintain prototype chains - don't use with instances of custom classes.
|
|
1417
|
+
* - It doesn't handle Map and Set
|
|
1418
|
+
*/
|
|
1419
|
+
|
|
1420
|
+
|
|
1421
|
+
function deepClone(value) {
|
|
1422
|
+
return mergeInto(undefined, value);
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1312
1425
|
var _URL = function _URL(url) {
|
|
1313
1426
|
var result = {};
|
|
1314
1427
|
var basicProps = ['hash', 'host', 'hostname', 'href', 'origin', 'password', 'pathname', 'port', 'protocol', 'search', 'username'];
|
package/esm/configuration.js
CHANGED
|
@@ -76,6 +76,7 @@ export function commonInit(userConfiguration, buildEnv) {
|
|
|
76
76
|
applicationId: userConfiguration.applicationId,
|
|
77
77
|
env: userConfiguration.env || '',
|
|
78
78
|
version: userConfiguration.version || '',
|
|
79
|
+
service: userConfiguration.service || 'browser',
|
|
79
80
|
sdkVersion: buildEnv.sdkVersion,
|
|
80
81
|
sdkName: buildEnv.sdkName,
|
|
81
82
|
datakitUrl: getDatakitUrl(userConfiguration.datakitUrl || userConfiguration.datakitOrigin),
|
|
@@ -135,5 +136,21 @@ function mustUseSecureCookie(userConfiguration) {
|
|
|
135
136
|
}
|
|
136
137
|
|
|
137
138
|
export function isIntakeRequest(url, configuration) {
|
|
138
|
-
return haveSameOrigin(url, configuration.datakitUrl)
|
|
139
|
+
// return haveSameOrigin(url, configuration.datakitUrl)
|
|
140
|
+
var notTakeRequest = [configuration.datakitUrl];
|
|
141
|
+
|
|
142
|
+
if (configuration.logsEndpoint) {
|
|
143
|
+
notTakeRequest.push(configuration.logsEndpoint);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
var isIntake = false;
|
|
147
|
+
|
|
148
|
+
for (var _url of notTakeRequest) {
|
|
149
|
+
if (url.indexOf(_url) === 0) {
|
|
150
|
+
isIntake = true;
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return isIntake;
|
|
139
156
|
}
|
package/esm/dataMap.js
CHANGED
|
@@ -93,6 +93,7 @@ export var dataMap = {
|
|
|
93
93
|
tags: {
|
|
94
94
|
error_source: 'error.source',
|
|
95
95
|
error_type: 'error.type',
|
|
96
|
+
error_handling: 'error.handling',
|
|
96
97
|
resource_url: 'error.resource.url',
|
|
97
98
|
resource_url_host: 'error.resource.url_host',
|
|
98
99
|
resource_url_path: 'error.resource.url_path',
|
package/esm/errorCollection.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { toArray, jsonStringify, find, clocksNow, map, extend } from './helper/tools';
|
|
2
|
-
import { ErrorSource, formatUnknownError, toStackTraceString, formatErrorMessage } from './helper/errorTools';
|
|
2
|
+
import { ErrorSource, formatUnknownError, toStackTraceString, formatErrorMessage, createHandlingStack } from './helper/errorTools';
|
|
3
3
|
import { computeStackTrace, subscribe, unsubscribe } from './tracekit';
|
|
4
4
|
import { Observable } from './helper/observable';
|
|
5
5
|
import { isIntakeRequest } from './configuration';
|
|
6
|
-
import { RequestType } from './helper/enums';
|
|
6
|
+
import { RequestType, ErrorHandling } from './helper/enums';
|
|
7
7
|
import { resetXhrProxy, startXhrProxy } from './xhrProxy';
|
|
8
8
|
import { resetFetchProxy, startFetchProxy } from './fetchProxy';
|
|
9
9
|
var errorObservable;
|
|
@@ -23,14 +23,16 @@ export function startConsoleTracking(errorObservable) {
|
|
|
23
23
|
|
|
24
24
|
console.error = function () {
|
|
25
25
|
originalConsoleError.apply(console, arguments);
|
|
26
|
-
|
|
26
|
+
var handlingStack = createHandlingStack();
|
|
27
|
+
errorObservable.notify(extend({}, buildErrorFromParams(toArray(arguments), handlingStack), {
|
|
27
28
|
source: ErrorSource.CONSOLE,
|
|
28
|
-
startClocks: clocksNow()
|
|
29
|
+
startClocks: clocksNow(),
|
|
30
|
+
handling: ErrorHandling.HANDLED
|
|
29
31
|
}));
|
|
30
32
|
};
|
|
31
33
|
}
|
|
32
34
|
|
|
33
|
-
function buildErrorFromParams(params) {
|
|
35
|
+
function buildErrorFromParams(params, handlingStack) {
|
|
34
36
|
var firstErrorParam = find(params, function (param) {
|
|
35
37
|
return param instanceof Error;
|
|
36
38
|
});
|
|
@@ -40,7 +42,8 @@ function buildErrorFromParams(params) {
|
|
|
40
42
|
}).join(' ');
|
|
41
43
|
return {
|
|
42
44
|
message: message,
|
|
43
|
-
stack: firstErrorParam ? toStackTraceString(computeStackTrace(firstErrorParam)) : undefined
|
|
45
|
+
stack: firstErrorParam ? toStackTraceString(computeStackTrace(firstErrorParam)) : undefined,
|
|
46
|
+
handlingStack: handlingStack
|
|
44
47
|
};
|
|
45
48
|
}
|
|
46
49
|
|
|
@@ -69,7 +72,8 @@ export function startRuntimeErrorTracking(errorObservable) {
|
|
|
69
72
|
stack: error.stack,
|
|
70
73
|
type: error.type,
|
|
71
74
|
source: ErrorSource.SOURCE,
|
|
72
|
-
startClocks: clocksNow()
|
|
75
|
+
startClocks: clocksNow(),
|
|
76
|
+
handling: ErrorHandling.UNHANDLED
|
|
73
77
|
});
|
|
74
78
|
};
|
|
75
79
|
|
package/esm/helper/errorTools.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { each } from './tools';
|
|
1
|
+
import { each, noop } from './tools';
|
|
2
|
+
import { computeStackTrace } from '../tracekit';
|
|
2
3
|
export var ErrorSource = {
|
|
3
4
|
AGENT: 'agent',
|
|
4
5
|
CONSOLE: 'console',
|
|
@@ -7,11 +8,12 @@ export var ErrorSource = {
|
|
|
7
8
|
LOGGER: 'logger',
|
|
8
9
|
CUSTOM: 'custom'
|
|
9
10
|
};
|
|
10
|
-
export function formatUnknownError(stackTrace, errorObject, nonErrorPrefix) {
|
|
11
|
+
export function formatUnknownError(stackTrace, errorObject, nonErrorPrefix, handlingStack) {
|
|
11
12
|
if (!stackTrace || stackTrace.message === undefined && !(errorObject instanceof Error)) {
|
|
12
13
|
return {
|
|
13
14
|
message: nonErrorPrefix + '' + JSON.stringify(errorObject),
|
|
14
15
|
stack: 'No stack, consider using an instance of Error',
|
|
16
|
+
handlingStack: handlingStack,
|
|
15
17
|
type: stackTrace && stackTrace.name
|
|
16
18
|
};
|
|
17
19
|
}
|
|
@@ -19,9 +21,42 @@ export function formatUnknownError(stackTrace, errorObject, nonErrorPrefix) {
|
|
|
19
21
|
return {
|
|
20
22
|
message: stackTrace.message || 'Empty message',
|
|
21
23
|
stack: toStackTraceString(stackTrace),
|
|
24
|
+
handlingStack: handlingStack,
|
|
22
25
|
type: stackTrace.name
|
|
23
26
|
};
|
|
24
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
Creates a stacktrace without SDK internal frames.
|
|
30
|
+
|
|
31
|
+
Constraints:
|
|
32
|
+
- Has to be called at the utmost position of the call stack.
|
|
33
|
+
- No internal monitoring should encapsulate the function, that is why we need to use callMonitored inside of it.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
export function createHandlingStack() {
|
|
37
|
+
/**
|
|
38
|
+
* Skip the two internal frames:
|
|
39
|
+
* - SDK API (console.error, ...)
|
|
40
|
+
* - this function
|
|
41
|
+
* in order to keep only the user calls
|
|
42
|
+
*/
|
|
43
|
+
var internalFramesToSkip = 2;
|
|
44
|
+
var error = new Error();
|
|
45
|
+
var formattedStack; // IE needs to throw the error to fill in the stack trace
|
|
46
|
+
|
|
47
|
+
if (!error.stack) {
|
|
48
|
+
try {
|
|
49
|
+
throw error;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
noop();
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
var stackTrace = computeStackTrace(error);
|
|
56
|
+
stackTrace.stack = stackTrace.stack.slice(internalFramesToSkip);
|
|
57
|
+
formattedStack = toStackTraceString(stackTrace);
|
|
58
|
+
return formattedStack;
|
|
59
|
+
}
|
|
25
60
|
export function toStackTraceString(stack) {
|
|
26
61
|
var result = stack.name || 'Error' + ': ' + stack.message;
|
|
27
62
|
each(stack.stack, function (frame) {
|
package/esm/helper/tools.js
CHANGED
|
@@ -625,8 +625,8 @@ export var urlParse = function urlParse(para) {
|
|
|
625
625
|
|
|
626
626
|
URLParser.prototype.getUrl = function () {
|
|
627
627
|
var url = '';
|
|
628
|
-
url += this._values.Origin;
|
|
629
|
-
|
|
628
|
+
url += this._values.Origin; // url += this._values.Port ? ':' + this._values.Port : ''
|
|
629
|
+
|
|
630
630
|
url += this._values.Path;
|
|
631
631
|
url += this._values.QueryString ? '?' + this._values.QueryString : '';
|
|
632
632
|
return url;
|
|
@@ -647,8 +647,11 @@ export var urlParse = function urlParse(para) {
|
|
|
647
647
|
}
|
|
648
648
|
}
|
|
649
649
|
|
|
650
|
+
this._values['Path'] = this._values['Path'] || '/';
|
|
650
651
|
this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '');
|
|
651
|
-
this._values['Origin'] = this._values['Protocol'] + '://' + this._values['Hostname'];
|
|
652
|
+
this._values['Origin'] = this._values['Protocol'] + '://' + this._values['Hostname'] + (this._values.Port ? ':' + this._values.Port : ''); // this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '')
|
|
653
|
+
// this._values['Origin'] =
|
|
654
|
+
// this._values['Protocol'] + '://' + this._values['Hostname']
|
|
652
655
|
};
|
|
653
656
|
|
|
654
657
|
return new URLParser(para);
|
|
@@ -1095,6 +1098,113 @@ export var getURLSearchParams = function getURLSearchParams(queryString) {
|
|
|
1095
1098
|
|
|
1096
1099
|
return args;
|
|
1097
1100
|
};
|
|
1101
|
+
|
|
1102
|
+
function createCircularReferenceChecker() {
|
|
1103
|
+
if (typeof WeakSet !== 'undefined') {
|
|
1104
|
+
var set = new WeakSet();
|
|
1105
|
+
return {
|
|
1106
|
+
hasAlreadyBeenSeen(value) {
|
|
1107
|
+
var has = set.has(value);
|
|
1108
|
+
|
|
1109
|
+
if (!has) {
|
|
1110
|
+
set.add(value);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
return has;
|
|
1114
|
+
}
|
|
1115
|
+
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
var array = [];
|
|
1120
|
+
return {
|
|
1121
|
+
hasAlreadyBeenSeen(value) {
|
|
1122
|
+
var has = array.indexOf(value) >= 0;
|
|
1123
|
+
|
|
1124
|
+
if (!has) {
|
|
1125
|
+
array.push(value);
|
|
1126
|
+
}
|
|
1127
|
+
|
|
1128
|
+
return has;
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
};
|
|
1132
|
+
}
|
|
1133
|
+
/**
|
|
1134
|
+
* Similar to `typeof`, but distinguish plain objects from `null` and arrays
|
|
1135
|
+
*/
|
|
1136
|
+
|
|
1137
|
+
|
|
1138
|
+
export function getType(value) {
|
|
1139
|
+
if (value === null) {
|
|
1140
|
+
return 'null';
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
if (Array.isArray(value)) {
|
|
1144
|
+
return 'array';
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
return typeof value;
|
|
1148
|
+
}
|
|
1149
|
+
/**
|
|
1150
|
+
* Iterate over source and affect its sub values into destination, recursively.
|
|
1151
|
+
* If the source and destination can't be merged, return source.
|
|
1152
|
+
*/
|
|
1153
|
+
|
|
1154
|
+
export function mergeInto(destination, source, circularReferenceChecker) {
|
|
1155
|
+
// ignore the source if it is undefined
|
|
1156
|
+
if (typeof circularReferenceChecker === 'undefined') {
|
|
1157
|
+
circularReferenceChecker = createCircularReferenceChecker();
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
if (source === undefined) {
|
|
1161
|
+
return destination;
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
if (typeof source !== 'object' || source === null) {
|
|
1165
|
+
// primitive values - just return source
|
|
1166
|
+
return source;
|
|
1167
|
+
} else if (source instanceof Date) {
|
|
1168
|
+
return new Date(source.getTime());
|
|
1169
|
+
} else if (source instanceof RegExp) {
|
|
1170
|
+
var flags = source.flags || // old browsers compatibility
|
|
1171
|
+
[source.global ? 'g' : '', source.ignoreCase ? 'i' : '', source.multiline ? 'm' : '', source.sticky ? 'y' : '', source.unicode ? 'u' : ''].join('');
|
|
1172
|
+
return new RegExp(source.source, flags);
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
if (circularReferenceChecker.hasAlreadyBeenSeen(source)) {
|
|
1176
|
+
// remove circular references
|
|
1177
|
+
return undefined;
|
|
1178
|
+
} else if (Array.isArray(source)) {
|
|
1179
|
+
var merged = Array.isArray(destination) ? destination : [];
|
|
1180
|
+
|
|
1181
|
+
for (var i = 0; i < source.length; ++i) {
|
|
1182
|
+
merged[i] = mergeInto(merged[i], source[i], circularReferenceChecker);
|
|
1183
|
+
}
|
|
1184
|
+
|
|
1185
|
+
return merged;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
var merged = getType(destination) === 'object' ? destination : {};
|
|
1189
|
+
|
|
1190
|
+
for (var key in source) {
|
|
1191
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1192
|
+
merged[key] = mergeInto(merged[key], source[key], circularReferenceChecker);
|
|
1193
|
+
}
|
|
1194
|
+
}
|
|
1195
|
+
|
|
1196
|
+
return merged;
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* A simplistic implementation of a deep clone algorithm.
|
|
1200
|
+
* Caveats:
|
|
1201
|
+
* - It doesn't maintain prototype chains - don't use with instances of custom classes.
|
|
1202
|
+
* - It doesn't handle Map and Set
|
|
1203
|
+
*/
|
|
1204
|
+
|
|
1205
|
+
export function deepClone(value) {
|
|
1206
|
+
return mergeInto(undefined, value);
|
|
1207
|
+
}
|
|
1098
1208
|
export var _URL = function _URL(url) {
|
|
1099
1209
|
var result = {};
|
|
1100
1210
|
var basicProps = ['hash', 'host', 'hostname', 'href', 'origin', 'password', 'pathname', 'port', 'protocol', 'search', 'username'];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloudcare/browser-core",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.19",
|
|
4
4
|
"main": "cjs/index.js",
|
|
5
5
|
"module": "esm/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
"author": "dataflux",
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"description": "DataFlux RUM Web 端数据指标监控",
|
|
23
|
-
"gitHead": "
|
|
23
|
+
"gitHead": "642b7a18f128ce5297dcb9b73df3136418c8c53e"
|
|
24
24
|
}
|
package/src/configuration.js
CHANGED
|
@@ -77,6 +77,7 @@ export function commonInit(userConfiguration, buildEnv) {
|
|
|
77
77
|
applicationId: userConfiguration.applicationId,
|
|
78
78
|
env: userConfiguration.env || '',
|
|
79
79
|
version: userConfiguration.version || '',
|
|
80
|
+
service: userConfiguration.service || 'browser',
|
|
80
81
|
sdkVersion: buildEnv.sdkVersion,
|
|
81
82
|
sdkName: buildEnv.sdkName,
|
|
82
83
|
datakitUrl: getDatakitUrl(
|
|
@@ -131,5 +132,17 @@ function mustUseSecureCookie(userConfiguration) {
|
|
|
131
132
|
}
|
|
132
133
|
|
|
133
134
|
export function isIntakeRequest(url, configuration) {
|
|
134
|
-
return haveSameOrigin(url, configuration.datakitUrl)
|
|
135
|
+
// return haveSameOrigin(url, configuration.datakitUrl)
|
|
136
|
+
var notTakeRequest = [configuration.datakitUrl]
|
|
137
|
+
if (configuration.logsEndpoint) {
|
|
138
|
+
notTakeRequest.push(configuration.logsEndpoint)
|
|
139
|
+
}
|
|
140
|
+
var isIntake = false
|
|
141
|
+
for(var _url of notTakeRequest) {
|
|
142
|
+
if (url.indexOf(_url) === 0) {
|
|
143
|
+
isIntake = true
|
|
144
|
+
break;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
return isIntake
|
|
135
148
|
}
|
package/src/dataMap.js
CHANGED
|
@@ -93,6 +93,7 @@ export var dataMap = {
|
|
|
93
93
|
tags: {
|
|
94
94
|
error_source: 'error.source',
|
|
95
95
|
error_type: 'error.type',
|
|
96
|
+
error_handling: 'error.handling',
|
|
96
97
|
resource_url: 'error.resource.url',
|
|
97
98
|
resource_url_host: 'error.resource.url_host',
|
|
98
99
|
resource_url_path: 'error.resource.url_path',
|
package/src/errorCollection.js
CHANGED
|
@@ -10,12 +10,13 @@ import {
|
|
|
10
10
|
ErrorSource,
|
|
11
11
|
formatUnknownError,
|
|
12
12
|
toStackTraceString,
|
|
13
|
-
formatErrorMessage
|
|
13
|
+
formatErrorMessage,
|
|
14
|
+
createHandlingStack
|
|
14
15
|
} from './helper/errorTools'
|
|
15
16
|
import { computeStackTrace, subscribe, unsubscribe } from './tracekit'
|
|
16
17
|
import { Observable } from './helper/observable'
|
|
17
18
|
import { isIntakeRequest } from './configuration'
|
|
18
|
-
import { RequestType } from './helper/enums'
|
|
19
|
+
import { RequestType, ErrorHandling } from './helper/enums'
|
|
19
20
|
import { resetXhrProxy, startXhrProxy } from './xhrProxy'
|
|
20
21
|
import { resetFetchProxy, startFetchProxy } from './fetchProxy'
|
|
21
22
|
|
|
@@ -37,16 +38,18 @@ export function startConsoleTracking(errorObservable) {
|
|
|
37
38
|
originalConsoleError = console.error
|
|
38
39
|
console.error = function () {
|
|
39
40
|
originalConsoleError.apply(console, arguments)
|
|
41
|
+
const handlingStack = createHandlingStack()
|
|
40
42
|
errorObservable.notify(
|
|
41
|
-
extend({}, buildErrorFromParams(toArray(arguments)), {
|
|
43
|
+
extend({}, buildErrorFromParams(toArray(arguments), handlingStack), {
|
|
42
44
|
source: ErrorSource.CONSOLE,
|
|
43
|
-
startClocks: clocksNow()
|
|
45
|
+
startClocks: clocksNow(),
|
|
46
|
+
handling: ErrorHandling.HANDLED
|
|
44
47
|
})
|
|
45
48
|
)
|
|
46
49
|
}
|
|
47
50
|
}
|
|
48
51
|
|
|
49
|
-
function buildErrorFromParams(params) {
|
|
52
|
+
function buildErrorFromParams(params, handlingStack) {
|
|
50
53
|
var firstErrorParam = find(params, function (param) {
|
|
51
54
|
return param instanceof Error
|
|
52
55
|
})
|
|
@@ -58,7 +61,8 @@ function buildErrorFromParams(params) {
|
|
|
58
61
|
message: message,
|
|
59
62
|
stack: firstErrorParam
|
|
60
63
|
? toStackTraceString(computeStackTrace(firstErrorParam))
|
|
61
|
-
: undefined
|
|
64
|
+
: undefined,
|
|
65
|
+
handlingStack: handlingStack
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
68
|
|
|
@@ -86,7 +90,8 @@ export function startRuntimeErrorTracking(errorObservable) {
|
|
|
86
90
|
stack: error.stack,
|
|
87
91
|
type: error.type,
|
|
88
92
|
source: ErrorSource.SOURCE,
|
|
89
|
-
startClocks: clocksNow()
|
|
93
|
+
startClocks: clocksNow(),
|
|
94
|
+
handling: ErrorHandling.UNHANDLED
|
|
90
95
|
})
|
|
91
96
|
}
|
|
92
97
|
|
package/src/helper/errorTools.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { each } from './tools'
|
|
1
|
+
import { each , noop} from './tools'
|
|
2
|
+
import { computeStackTrace} from '../tracekit'
|
|
3
|
+
|
|
2
4
|
export var ErrorSource = {
|
|
3
5
|
AGENT: 'agent',
|
|
4
6
|
CONSOLE: 'console',
|
|
@@ -7,7 +9,8 @@ export var ErrorSource = {
|
|
|
7
9
|
LOGGER: 'logger',
|
|
8
10
|
CUSTOM: 'custom'
|
|
9
11
|
}
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
export function formatUnknownError(stackTrace, errorObject, nonErrorPrefix,handlingStack) {
|
|
11
14
|
if (
|
|
12
15
|
!stackTrace ||
|
|
13
16
|
(stackTrace.message === undefined && !(errorObject instanceof Error))
|
|
@@ -15,16 +18,50 @@ export function formatUnknownError(stackTrace, errorObject, nonErrorPrefix) {
|
|
|
15
18
|
return {
|
|
16
19
|
message: nonErrorPrefix + '' + JSON.stringify(errorObject),
|
|
17
20
|
stack: 'No stack, consider using an instance of Error',
|
|
21
|
+
handlingStack:handlingStack,
|
|
18
22
|
type: stackTrace && stackTrace.name
|
|
19
23
|
}
|
|
20
24
|
}
|
|
21
25
|
return {
|
|
22
26
|
message: stackTrace.message || 'Empty message',
|
|
23
27
|
stack: toStackTraceString(stackTrace),
|
|
28
|
+
handlingStack:handlingStack,
|
|
24
29
|
type: stackTrace.name
|
|
25
30
|
}
|
|
26
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
Creates a stacktrace without SDK internal frames.
|
|
34
|
+
|
|
35
|
+
Constraints:
|
|
36
|
+
- Has to be called at the utmost position of the call stack.
|
|
37
|
+
- No internal monitoring should encapsulate the function, that is why we need to use callMonitored inside of it.
|
|
38
|
+
*/
|
|
39
|
+
export function createHandlingStack() {
|
|
40
|
+
/**
|
|
41
|
+
* Skip the two internal frames:
|
|
42
|
+
* - SDK API (console.error, ...)
|
|
43
|
+
* - this function
|
|
44
|
+
* in order to keep only the user calls
|
|
45
|
+
*/
|
|
46
|
+
const internalFramesToSkip = 2
|
|
47
|
+
const error = new Error()
|
|
48
|
+
let formattedStack
|
|
27
49
|
|
|
50
|
+
// IE needs to throw the error to fill in the stack trace
|
|
51
|
+
if (!error.stack) {
|
|
52
|
+
try {
|
|
53
|
+
throw error
|
|
54
|
+
} catch (e) {
|
|
55
|
+
noop()
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const stackTrace = computeStackTrace(error)
|
|
60
|
+
stackTrace.stack = stackTrace.stack.slice(internalFramesToSkip)
|
|
61
|
+
formattedStack = toStackTraceString(stackTrace)
|
|
62
|
+
|
|
63
|
+
return formattedStack
|
|
64
|
+
}
|
|
28
65
|
export function toStackTraceString(stack) {
|
|
29
66
|
var result = stack.name || 'Error' + ': ' + stack.message
|
|
30
67
|
each(stack.stack, function (frame) {
|
package/src/helper/tools.js
CHANGED
|
@@ -613,7 +613,7 @@ export var urlParse = function (para) {
|
|
|
613
613
|
URLParser.prototype.getUrl = function () {
|
|
614
614
|
var url = ''
|
|
615
615
|
url += this._values.Origin
|
|
616
|
-
url += this._values.Port ? ':' + this._values.Port : ''
|
|
616
|
+
// url += this._values.Port ? ':' + this._values.Port : ''
|
|
617
617
|
url += this._values.Path
|
|
618
618
|
url += this._values.QueryString ? '?' + this._values.QueryString : ''
|
|
619
619
|
return url
|
|
@@ -629,9 +629,13 @@ export var urlParse = function (para) {
|
|
|
629
629
|
this._values[c] = b[this._fields[c]]
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
|
-
this._values['
|
|
633
|
-
|
|
634
|
-
|
|
632
|
+
this._values['Path'] = this._values['Path'] || '/'
|
|
633
|
+
this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '')
|
|
634
|
+
this._values['Origin'] =
|
|
635
|
+
this._values['Protocol'] + '://' + this._values['Hostname'] + (this._values.Port ? ':' + this._values.Port : '')
|
|
636
|
+
// this._values['Hostname'] = this._values['Host'].replace(/:\d+$/, '')
|
|
637
|
+
// this._values['Origin'] =
|
|
638
|
+
// this._values['Protocol'] + '://' + this._values['Hostname']
|
|
635
639
|
}
|
|
636
640
|
return new URLParser(para)
|
|
637
641
|
}
|
|
@@ -1060,7 +1064,107 @@ export var getURLSearchParams = function (queryString) {
|
|
|
1060
1064
|
}
|
|
1061
1065
|
return args
|
|
1062
1066
|
}
|
|
1067
|
+
function createCircularReferenceChecker() {
|
|
1068
|
+
if (typeof WeakSet !== 'undefined') {
|
|
1069
|
+
var set = new WeakSet()
|
|
1070
|
+
return {
|
|
1071
|
+
hasAlreadyBeenSeen(value) {
|
|
1072
|
+
var has = set.has(value)
|
|
1073
|
+
if (!has) {
|
|
1074
|
+
set.add(value)
|
|
1075
|
+
}
|
|
1076
|
+
return has
|
|
1077
|
+
},
|
|
1078
|
+
}
|
|
1079
|
+
}
|
|
1080
|
+
var array = []
|
|
1081
|
+
return {
|
|
1082
|
+
hasAlreadyBeenSeen(value) {
|
|
1083
|
+
var has = array.indexOf(value) >= 0
|
|
1084
|
+
if (!has) {
|
|
1085
|
+
array.push(value)
|
|
1086
|
+
}
|
|
1087
|
+
return has
|
|
1088
|
+
},
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
/**
|
|
1092
|
+
* Similar to `typeof`, but distinguish plain objects from `null` and arrays
|
|
1093
|
+
*/
|
|
1094
|
+
export function getType(value) {
|
|
1095
|
+
if (value === null) {
|
|
1096
|
+
return 'null'
|
|
1097
|
+
}
|
|
1098
|
+
if (Array.isArray(value)) {
|
|
1099
|
+
return 'array'
|
|
1100
|
+
}
|
|
1101
|
+
return typeof value
|
|
1102
|
+
}
|
|
1103
|
+
/**
|
|
1104
|
+
* Iterate over source and affect its sub values into destination, recursively.
|
|
1105
|
+
* If the source and destination can't be merged, return source.
|
|
1106
|
+
*/
|
|
1107
|
+
export function mergeInto(
|
|
1108
|
+
destination,
|
|
1109
|
+
source,
|
|
1110
|
+
circularReferenceChecker
|
|
1111
|
+
) {
|
|
1112
|
+
// ignore the source if it is undefined
|
|
1113
|
+
if (typeof circularReferenceChecker === 'undefined') {
|
|
1114
|
+
circularReferenceChecker = createCircularReferenceChecker()
|
|
1115
|
+
}
|
|
1116
|
+
if (source === undefined) {
|
|
1117
|
+
return destination
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
if (typeof source !== 'object' || source === null) {
|
|
1121
|
+
// primitive values - just return source
|
|
1122
|
+
return source
|
|
1123
|
+
} else if (source instanceof Date) {
|
|
1124
|
+
return new Date(source.getTime())
|
|
1125
|
+
} else if (source instanceof RegExp) {
|
|
1126
|
+
var flags =
|
|
1127
|
+
source.flags ||
|
|
1128
|
+
// old browsers compatibility
|
|
1129
|
+
[
|
|
1130
|
+
source.global ? 'g' : '',
|
|
1131
|
+
source.ignoreCase ? 'i' : '',
|
|
1132
|
+
source.multiline ? 'm' : '',
|
|
1133
|
+
source.sticky ? 'y' : '',
|
|
1134
|
+
source.unicode ? 'u' : '',
|
|
1135
|
+
].join('')
|
|
1136
|
+
return new RegExp(source.source, flags)
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
if (circularReferenceChecker.hasAlreadyBeenSeen(source)) {
|
|
1140
|
+
// remove circular references
|
|
1141
|
+
return undefined
|
|
1142
|
+
} else if (Array.isArray(source)) {
|
|
1143
|
+
var merged= Array.isArray(destination) ? destination : []
|
|
1144
|
+
for (var i = 0; i < source.length; ++i) {
|
|
1145
|
+
merged[i] = mergeInto(merged[i], source[i], circularReferenceChecker)
|
|
1146
|
+
}
|
|
1147
|
+
return merged
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1150
|
+
var merged = getType(destination) === 'object' ? destination : {}
|
|
1151
|
+
for (var key in source) {
|
|
1152
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1153
|
+
merged[key] = mergeInto(merged[key], source[key], circularReferenceChecker)
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
return merged
|
|
1157
|
+
}
|
|
1063
1158
|
|
|
1159
|
+
/**
|
|
1160
|
+
* A simplistic implementation of a deep clone algorithm.
|
|
1161
|
+
* Caveats:
|
|
1162
|
+
* - It doesn't maintain prototype chains - don't use with instances of custom classes.
|
|
1163
|
+
* - It doesn't handle Map and Set
|
|
1164
|
+
*/
|
|
1165
|
+
export function deepClone(value){
|
|
1166
|
+
return mergeInto(undefined, value)
|
|
1167
|
+
}
|
|
1064
1168
|
export var _URL = function (url) {
|
|
1065
1169
|
var result = {}
|
|
1066
1170
|
var basicProps = [
|