@cloudcare/browser-core 2.0.13 → 2.0.15

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.
@@ -60,7 +60,6 @@ function computeTransportConfiguration(initConfiguration) {
60
60
  }
61
61
 
62
62
  function isIntakeRequest(url, configuration) {
63
- // return haveSameOrigin(url, configuration.datakitUrl)
64
63
  var notTakeRequest = [configuration.datakitUrl];
65
64
 
66
65
  if (configuration.logsEndpoint) {
package/cjs/dataMap.js CHANGED
@@ -8,8 +8,8 @@ exports.dataMap = exports.commonTags = exports.commonFields = void 0;
8
8
  var _enums = require("./helper/enums");
9
9
 
10
10
  var commonTags = {
11
- sdk_name: '_dd.sdk_name',
12
- sdk_version: '_dd.sdk_version',
11
+ sdk_name: '_gc.sdk_name',
12
+ sdk_version: '_gc.sdk_version',
13
13
  app_id: 'application.id',
14
14
  env: 'env',
15
15
  service: 'service',
@@ -57,7 +57,7 @@ var dataMap = {
57
57
  },
58
58
  fields: {
59
59
  is_active: 'view.is_active',
60
- session_replay_stats: '_dd.replay_stats',
60
+ session_replay_stats: '_gc.replay_stats',
61
61
  session_is_active: 'session.is_active',
62
62
  view_error_count: 'view.error.count',
63
63
  view_resource_count: 'view.resource.count',
@@ -86,8 +86,8 @@ var dataMap = {
86
86
  resource: {
87
87
  type: _enums.RumEventType.RESOURCE,
88
88
  tags: {
89
- trace_id: '_dd.trace_id',
90
- span_id: '_dd.span_id',
89
+ trace_id: '_gc.trace_id',
90
+ span_id: '_gc.span_id',
91
91
  resource_url: 'resource.url',
92
92
  resource_url_host: 'resource.url_host',
93
93
  resource_url_path: 'resource.url_path',
@@ -120,8 +120,8 @@ var dataMap = {
120
120
  type: _enums.RumEventType.ERROR,
121
121
  tags: {
122
122
  error_id: 'error.id',
123
- trace_id: '_dd.trace_id',
124
- span_id: '_dd.span_id',
123
+ trace_id: '_gc.trace_id',
124
+ span_id: '_gc.span_id',
125
125
  error_source: 'error.source',
126
126
  error_type: 'error.type',
127
127
  error_handling: 'error.handling' // resource_url: 'error.resource.url',
@@ -160,8 +160,8 @@ var dataMap = {
160
160
  action_resource_count: 'action.resource.count',
161
161
  action_frustration_types: 'action.frustration.type',
162
162
  action_long_task_count: 'action.long_task.count',
163
- action_target: '_dd.action.target',
164
- action_position: '_dd.action.position'
163
+ action_target: '_gc.action.target',
164
+ action_position: '_gc.action.position'
165
165
  }
166
166
  },
167
167
  browser_log: {
@@ -7,22 +7,31 @@ exports.limitModification = limitModification;
7
7
 
8
8
  var _tools = require("./tools");
9
9
 
10
- function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
10
+ var _sanitize = require("./sanitize");
11
+
12
+ function _createForOfIteratorHelper(o, allowArrayLike) { var it; if (typeof Symbol === "undefined" || o[Symbol.iterator] == null) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = o[Symbol.iterator](); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
13
+
14
+ function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
15
+
16
+ function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
11
17
 
12
18
  /**
13
- * Current limitations:
19
+ * Current limitation:
14
20
  * - field path do not support array, 'a.b.c' only
15
- * - modifiable fields type must be string
16
21
  */
17
22
  function limitModification(object, modifiableFieldPaths, modifier) {
18
- var clone = (0, _tools.extend2Lev)({}, object);
23
+ var clone = (0, _tools.deepClone)(object);
19
24
  var result = modifier(clone);
20
- (0, _tools.each)(modifiableFieldPaths, function (path) {
21
- var originalValue = get(object, path);
22
- var newValue = get(clone, path);
25
+ (0, _tools.each)((0, _tools.objectEntries)(modifiableFieldPaths), function (filedPaths) {
26
+ var fieldPath = filedPaths[0];
27
+ var fieldType = filedPaths[1];
28
+ var newValue = get(clone, fieldPath);
29
+ var newType = (0, _tools.getType)(newValue);
23
30
 
24
- if (typeof originalValue === 'string' && typeof newValue === 'string') {
25
- set(object, path, newValue);
31
+ if (newType === fieldType) {
32
+ set(object, fieldPath, (0, _sanitize.sanitize)(newValue));
33
+ } else if (fieldType === 'object' && (newType === 'undefined' || newType === 'null')) {
34
+ set(object, fieldPath, {});
26
35
  }
27
36
  });
28
37
  return result;
@@ -30,16 +39,24 @@ function limitModification(object, modifiableFieldPaths, modifier) {
30
39
 
31
40
  function get(object, path) {
32
41
  var current = object;
33
- var fields = path.split('.');
34
42
 
35
- for (var i = 0; i < fields.length; i++) {
36
- var field = fields[i];
43
+ var _iterator = _createForOfIteratorHelper(path.split('.')),
44
+ _step;
37
45
 
38
- if (!isValidObjectContaining(current, field)) {
39
- return;
40
- }
46
+ try {
47
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
48
+ var field = _step.value;
49
+
50
+ if (!isValidObjectContaining(current, field)) {
51
+ return;
52
+ }
41
53
 
42
- current = current[field];
54
+ current = current[field];
55
+ }
56
+ } catch (err) {
57
+ _iterator.e(err);
58
+ } finally {
59
+ _iterator.f();
43
60
  }
44
61
 
45
62
  return current;
@@ -52,7 +69,7 @@ function set(object, path, value) {
52
69
  for (var i = 0; i < fields.length; i += 1) {
53
70
  var field = fields[i];
54
71
 
55
- if (!isValidObjectContaining(current, field)) {
72
+ if (!isValidObject(current)) {
56
73
  return;
57
74
  }
58
75
 
@@ -64,6 +81,10 @@ function set(object, path, value) {
64
81
  }
65
82
  }
66
83
 
84
+ function isValidObject(object) {
85
+ return (0, _tools.getType)(object) === 'object';
86
+ }
87
+
67
88
  function isValidObjectContaining(object, field) {
68
- return _typeof(object) === 'object' && object !== null && field in object;
89
+ return isValidObject(object) && Object.prototype.hasOwnProperty.call(object, field);
69
90
  }
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.sanitize = sanitize;
7
+
8
+ var _display = require("./display");
9
+
10
+ var _byteUtils = require("./byteUtils");
11
+
12
+ var _jsonStringify = require("./serialisation/jsonStringify");
13
+
14
+ function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
15
+
16
+ // The maximum size of a single event is 256KiB. By default, we ensure that user-provided data
17
+ // going through sanitize fits inside our events, while leaving room for other contexts, metadata, ...
18
+ var SANITIZE_DEFAULT_MAX_CHARACTER_COUNT = 220 * _byteUtils.ONE_KIBI_BYTE; // Symbol for the root element of the JSONPath used for visited objects
19
+
20
+ var JSON_PATH_ROOT_ELEMENT = '$'; // When serializing (using JSON.stringify) a key of an object, { key: 42 } gets wrapped in quotes as "key".
21
+ // With the separator (:), we need to add 3 characters to the count.
22
+
23
+ var KEY_DECORATION_LENGTH = 3;
24
+ /**
25
+ * Ensures user-provided data is 'safe' for the SDK
26
+ * - Deep clones data
27
+ * - Removes cyclic references
28
+ * - Transforms unserializable types to a string representation
29
+ *
30
+ * LIMITATIONS:
31
+ * - Size is in characters, not byte count (may differ according to character encoding)
32
+ * - Size does not take into account indentation that can be applied to JSON.stringify
33
+ * - Non-numerical properties of Arrays are ignored. Same behavior as JSON.stringify
34
+ *
35
+ * @param source User-provided data meant to be serialized using JSON.stringify
36
+ * @param maxCharacterCount Maximum number of characters allowed in serialized form
37
+ */
38
+
39
+ function sanitize(source, maxCharacterCount) {
40
+ if (maxCharacterCount === undefined) {
41
+ maxCharacterCount = SANITIZE_DEFAULT_MAX_CHARACTER_COUNT;
42
+ } // Unbind any toJSON function we may have on [] or {} prototypes
43
+
44
+
45
+ var restoreObjectPrototypeToJson = (0, _jsonStringify.detachToJsonMethod)(Object.prototype);
46
+ var restoreArrayPrototypeToJson = (0, _jsonStringify.detachToJsonMethod)(Array.prototype); // Initial call to sanitizeProcessor - will populate containerQueue if source is an Array or a plain Object
47
+
48
+ var containerQueue = [];
49
+ var visitedObjectsWithPath = new WeakMap();
50
+ var sanitizedData = sanitizeProcessor(source, JSON_PATH_ROOT_ELEMENT, undefined, containerQueue, visitedObjectsWithPath);
51
+ var accumulatedCharacterCount = JSON.stringify(sanitizedData) && JSON.stringify(sanitizedData).length || 0;
52
+
53
+ if (accumulatedCharacterCount > maxCharacterCount) {
54
+ warnOverCharacterLimit(maxCharacterCount, 'discarded', source);
55
+ return undefined;
56
+ }
57
+
58
+ while (containerQueue.length > 0 && accumulatedCharacterCount < maxCharacterCount) {
59
+ var containerToProcess = containerQueue.shift();
60
+ var separatorLength = 0; // 0 for the first element, 1 for subsequent elements
61
+ // Arrays and Objects have to be handled distinctly to ensure
62
+ // we do not pick up non-numerical properties from Arrays
63
+
64
+ if (Array.isArray(containerToProcess.source)) {
65
+ for (var key = 0; key < containerToProcess.source.length; key++) {
66
+ var targetData = sanitizeProcessor(containerToProcess.source[key], containerToProcess.path, key, containerQueue, visitedObjectsWithPath);
67
+
68
+ if (targetData !== undefined) {
69
+ accumulatedCharacterCount += JSON.stringify(targetData).length;
70
+ } else {
71
+ // When an element of an Array (targetData) is undefined, it is serialized as null:
72
+ // JSON.stringify([undefined]) => '[null]' - This accounts for 4 characters
73
+ accumulatedCharacterCount += 4;
74
+ }
75
+
76
+ accumulatedCharacterCount += separatorLength;
77
+ separatorLength = 1;
78
+
79
+ if (accumulatedCharacterCount > maxCharacterCount) {
80
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source);
81
+ break;
82
+ }
83
+
84
+ containerToProcess.target[key] = targetData;
85
+ }
86
+ } else {
87
+ for (var key in containerToProcess.source) {
88
+ if (Object.prototype.hasOwnProperty.call(containerToProcess.source, key)) {
89
+ var targetData = sanitizeProcessor(containerToProcess.source[key], containerToProcess.path, key, containerQueue, visitedObjectsWithPath); // When a property of an object has an undefined value, it will be dropped during serialization:
90
+ // JSON.stringify({a:undefined}) => '{}'
91
+
92
+ if (targetData !== undefined) {
93
+ accumulatedCharacterCount += JSON.stringify(targetData).length + separatorLength + key.length + KEY_DECORATION_LENGTH;
94
+ separatorLength = 1;
95
+ }
96
+
97
+ if (accumulatedCharacterCount > maxCharacterCount) {
98
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source);
99
+ break;
100
+ }
101
+
102
+ containerToProcess.target[key] = targetData;
103
+ }
104
+ }
105
+ }
106
+ } // Rebind detached toJSON functions
107
+
108
+
109
+ restoreObjectPrototypeToJson();
110
+ restoreArrayPrototypeToJson();
111
+ return sanitizedData;
112
+ }
113
+ /**
114
+ * Internal function to factorize the process common to the
115
+ * initial call to sanitize, and iterations for Arrays and Objects
116
+ *
117
+ */
118
+
119
+
120
+ function sanitizeProcessor(source, parentPath, key, queue, visitedObjectsWithPath) {
121
+ // Start by handling toJSON, as we want to sanitize its output
122
+ var sourceToSanitize = tryToApplyToJSON(source);
123
+
124
+ if (!sourceToSanitize || _typeof(sourceToSanitize) !== 'object') {
125
+ return sanitizePrimitivesAndFunctions(sourceToSanitize);
126
+ }
127
+
128
+ var sanitizedSource = sanitizeObjects(sourceToSanitize);
129
+
130
+ if (sanitizedSource !== '[Object]' && sanitizedSource !== '[Array]' && sanitizedSource !== '[Error]') {
131
+ return sanitizedSource;
132
+ } // Handle potential cyclic references
133
+ // We need to use source as sourceToSanitize could be a reference to a new object
134
+ // At this stage, we know the source is an object type
135
+
136
+
137
+ var sourceAsObject = source;
138
+
139
+ if (visitedObjectsWithPath.has(sourceAsObject)) {
140
+ return '[Reference seen at ' + visitedObjectsWithPath.get(sourceAsObject) + ']';
141
+ } // Add processed source to queue
142
+
143
+
144
+ var currentPath = key !== undefined ? parentPath + '.' + key : parentPath;
145
+ var target = Array.isArray(sourceToSanitize) ? [] : {};
146
+ visitedObjectsWithPath.set(sourceAsObject, currentPath);
147
+ queue.push({
148
+ source: sourceToSanitize,
149
+ target: target,
150
+ path: currentPath
151
+ });
152
+ return target;
153
+ }
154
+ /**
155
+ * Handles sanitization of simple, non-object types
156
+ *
157
+ */
158
+
159
+
160
+ function sanitizePrimitivesAndFunctions(value) {
161
+ // BigInt cannot be serialized by JSON.stringify(), convert it to a string representation
162
+ if (typeof value === 'bigint') {
163
+ return '[BigInt] ' + value.toString();
164
+ } // Functions cannot be serialized by JSON.stringify(). Moreover, if a faulty toJSON is present, it needs to be converted
165
+ // so it won't prevent stringify from serializing later
166
+
167
+
168
+ if (typeof value === 'function') {
169
+ return '[Function] ' + value.name || 'unknown';
170
+ } // JSON.stringify() does not serialize symbols.
171
+
172
+
173
+ if (_typeof(value) === 'symbol') {
174
+ // symbol.description is part of ES2019+
175
+ return '[Symbol] ' + value.description || value.toString();
176
+ }
177
+
178
+ return value;
179
+ }
180
+ /**
181
+ * Handles sanitization of object types
182
+ *
183
+ * LIMITATIONS
184
+ * - If a class defines a toStringTag Symbol, it will fall in the catch-all method and prevent enumeration of properties.
185
+ * To avoid this, a toJSON method can be defined.
186
+ * - IE11 does not return a distinct type for objects such as Map, WeakMap, ... These objects will pass through and their
187
+ * properties enumerated if any.
188
+ *
189
+ */
190
+
191
+
192
+ function sanitizeObjects(value) {
193
+ try {
194
+ // Handle events - Keep a simple implementation to avoid breaking changes
195
+ if (value instanceof Event) {
196
+ return {
197
+ isTrusted: value.isTrusted
198
+ };
199
+ } // Handle all remaining object types in a generic way
200
+
201
+
202
+ var result = Object.prototype.toString.call(value);
203
+ var match = result.match(/\[object (.*)\]/);
204
+
205
+ if (match && match[1]) {
206
+ return '[' + match[1] + ']';
207
+ }
208
+ } catch (_unused) {// If the previous serialization attempts failed, and we cannot convert using
209
+ // Object.prototype.toString, declare the value unserializable
210
+ }
211
+
212
+ return '[Unserializable]';
213
+ }
214
+ /**
215
+ * Checks if a toJSON function exists and tries to execute it
216
+ *
217
+ */
218
+
219
+
220
+ function tryToApplyToJSON(value) {
221
+ var object = value;
222
+
223
+ if (object && typeof object.toJSON === 'function') {
224
+ try {
225
+ return object.toJSON();
226
+ } catch (_unused2) {// If toJSON fails, we continue by trying to serialize the value manually
227
+ }
228
+ }
229
+
230
+ return value;
231
+ }
232
+ /**
233
+ * Helper function to display the warning when the accumulated character count is over the limit
234
+ */
235
+
236
+
237
+ function warnOverCharacterLimit(maxCharacterCount, changeType, source) {
238
+ _display.display.warn('The data provided has been ' + changeType + ' as it is over the limit of ' + maxCharacterCount + ' characters:', source);
239
+ }
@@ -1960,7 +1960,7 @@ function isChromium() {
1960
1960
 
1961
1961
 
1962
1962
  function getLinkElementOrigin(element) {
1963
- if (element.origin) {
1963
+ if (element.origin && element.origin !== 'null') {
1964
1964
  return element.origin;
1965
1965
  }
1966
1966
 
@@ -8,7 +8,6 @@ exports.getHash = getHash;
8
8
  exports.getOrigin = getOrigin;
9
9
  exports.getPathName = getPathName;
10
10
  exports.getSearch = getSearch;
11
- exports.haveSameOrigin = haveSameOrigin;
12
11
  exports.isValidUrl = isValidUrl;
13
12
  exports.normalizeUrl = normalizeUrl;
14
13
 
@@ -24,11 +23,10 @@ function isValidUrl(url) {
24
23
  } catch (e) {
25
24
  return false;
26
25
  }
27
- }
26
+ } // export function haveSameOrigin(url1, url2) {
27
+ // return getOrigin(url1) === getOrigin(url2)
28
+ // }
28
29
 
29
- function haveSameOrigin(url1, url2) {
30
- return getOrigin(url1) === getOrigin(url2);
31
- }
32
30
 
33
31
  function getOrigin(url) {
34
32
  return (0, _tools.getLinkElementOrigin)(buildUrl(url));
package/cjs/index.js CHANGED
@@ -147,6 +147,19 @@ Object.keys(_display).forEach(function (key) {
147
147
  });
148
148
  });
149
149
 
150
+ var _sanitize = require("./helper/sanitize");
151
+
152
+ Object.keys(_sanitize).forEach(function (key) {
153
+ if (key === "default" || key === "__esModule") return;
154
+ if (key in exports && exports[key] === _sanitize[key]) return;
155
+ Object.defineProperty(exports, key, {
156
+ enumerable: true,
157
+ get: function get() {
158
+ return _sanitize[key];
159
+ }
160
+ });
161
+ });
162
+
150
163
  var _eventEmitter = require("./helper/eventEmitter");
151
164
 
152
165
  Object.keys(_eventEmitter).forEach(function (key) {
@@ -50,7 +50,6 @@ export function computeTransportConfiguration(initConfiguration) {
50
50
  };
51
51
  }
52
52
  export function isIntakeRequest(url, configuration) {
53
- // return haveSameOrigin(url, configuration.datakitUrl)
54
53
  var notTakeRequest = [configuration.datakitUrl];
55
54
 
56
55
  if (configuration.logsEndpoint) {
package/esm/dataMap.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RumEventType } from './helper/enums';
2
2
  export var commonTags = {
3
- sdk_name: '_dd.sdk_name',
4
- sdk_version: '_dd.sdk_version',
3
+ sdk_name: '_gc.sdk_name',
4
+ sdk_version: '_gc.sdk_version',
5
5
  app_id: 'application.id',
6
6
  env: 'env',
7
7
  service: 'service',
@@ -47,7 +47,7 @@ export var dataMap = {
47
47
  },
48
48
  fields: {
49
49
  is_active: 'view.is_active',
50
- session_replay_stats: '_dd.replay_stats',
50
+ session_replay_stats: '_gc.replay_stats',
51
51
  session_is_active: 'session.is_active',
52
52
  view_error_count: 'view.error.count',
53
53
  view_resource_count: 'view.resource.count',
@@ -76,8 +76,8 @@ export var dataMap = {
76
76
  resource: {
77
77
  type: RumEventType.RESOURCE,
78
78
  tags: {
79
- trace_id: '_dd.trace_id',
80
- span_id: '_dd.span_id',
79
+ trace_id: '_gc.trace_id',
80
+ span_id: '_gc.span_id',
81
81
  resource_url: 'resource.url',
82
82
  resource_url_host: 'resource.url_host',
83
83
  resource_url_path: 'resource.url_path',
@@ -110,8 +110,8 @@ export var dataMap = {
110
110
  type: RumEventType.ERROR,
111
111
  tags: {
112
112
  error_id: 'error.id',
113
- trace_id: '_dd.trace_id',
114
- span_id: '_dd.span_id',
113
+ trace_id: '_gc.trace_id',
114
+ span_id: '_gc.span_id',
115
115
  error_source: 'error.source',
116
116
  error_type: 'error.type',
117
117
  error_handling: 'error.handling' // resource_url: 'error.resource.url',
@@ -150,8 +150,8 @@ export var dataMap = {
150
150
  action_resource_count: 'action.resource.count',
151
151
  action_frustration_types: 'action.frustration.type',
152
152
  action_long_task_count: 'action.long_task.count',
153
- action_target: '_dd.action.target',
154
- action_position: '_dd.action.position'
153
+ action_target: '_gc.action.target',
154
+ action_position: '_gc.action.position'
155
155
  }
156
156
  },
157
157
  browser_log: {
@@ -1,19 +1,23 @@
1
- import { extend2Lev, each } from './tools';
1
+ import { extend2Lev, each, objectEntries, getType, deepClone } from './tools';
2
+ import { sanitize } from './sanitize';
2
3
  /**
3
- * Current limitations:
4
+ * Current limitation:
4
5
  * - field path do not support array, 'a.b.c' only
5
- * - modifiable fields type must be string
6
6
  */
7
7
 
8
8
  export function limitModification(object, modifiableFieldPaths, modifier) {
9
- var clone = extend2Lev({}, object);
9
+ var clone = deepClone(object);
10
10
  var result = modifier(clone);
11
- each(modifiableFieldPaths, function (path) {
12
- var originalValue = get(object, path);
13
- var newValue = get(clone, path);
11
+ each(objectEntries(modifiableFieldPaths), function (filedPaths) {
12
+ var fieldPath = filedPaths[0];
13
+ var fieldType = filedPaths[1];
14
+ var newValue = get(clone, fieldPath);
15
+ var newType = getType(newValue);
14
16
 
15
- if (typeof originalValue === 'string' && typeof newValue === 'string') {
16
- set(object, path, newValue);
17
+ if (newType === fieldType) {
18
+ set(object, fieldPath, sanitize(newValue));
19
+ } else if (fieldType === 'object' && (newType === 'undefined' || newType === 'null')) {
20
+ set(object, fieldPath, {});
17
21
  }
18
22
  });
19
23
  return result;
@@ -21,11 +25,8 @@ export function limitModification(object, modifiableFieldPaths, modifier) {
21
25
 
22
26
  function get(object, path) {
23
27
  var current = object;
24
- var fields = path.split('.');
25
-
26
- for (var i = 0; i < fields.length; i++) {
27
- var field = fields[i];
28
28
 
29
+ for (var field of path.split('.')) {
29
30
  if (!isValidObjectContaining(current, field)) {
30
31
  return;
31
32
  }
@@ -43,7 +44,7 @@ function set(object, path, value) {
43
44
  for (var i = 0; i < fields.length; i += 1) {
44
45
  var field = fields[i];
45
46
 
46
- if (!isValidObjectContaining(current, field)) {
47
+ if (!isValidObject(current)) {
47
48
  return;
48
49
  }
49
50
 
@@ -55,6 +56,10 @@ function set(object, path, value) {
55
56
  }
56
57
  }
57
58
 
59
+ function isValidObject(object) {
60
+ return getType(object) === 'object';
61
+ }
62
+
58
63
  function isValidObjectContaining(object, field) {
59
- return typeof object === 'object' && object !== null && field in object;
64
+ return isValidObject(object) && Object.prototype.hasOwnProperty.call(object, field);
60
65
  }
@@ -0,0 +1,226 @@
1
+ import { display } from './display';
2
+ import { ONE_KIBI_BYTE } from './byteUtils';
3
+ import { detachToJsonMethod } from './serialisation/jsonStringify'; // The maximum size of a single event is 256KiB. By default, we ensure that user-provided data
4
+ // going through sanitize fits inside our events, while leaving room for other contexts, metadata, ...
5
+
6
+ var SANITIZE_DEFAULT_MAX_CHARACTER_COUNT = 220 * ONE_KIBI_BYTE; // Symbol for the root element of the JSONPath used for visited objects
7
+
8
+ var JSON_PATH_ROOT_ELEMENT = '$'; // When serializing (using JSON.stringify) a key of an object, { key: 42 } gets wrapped in quotes as "key".
9
+ // With the separator (:), we need to add 3 characters to the count.
10
+
11
+ var KEY_DECORATION_LENGTH = 3;
12
+ /**
13
+ * Ensures user-provided data is 'safe' for the SDK
14
+ * - Deep clones data
15
+ * - Removes cyclic references
16
+ * - Transforms unserializable types to a string representation
17
+ *
18
+ * LIMITATIONS:
19
+ * - Size is in characters, not byte count (may differ according to character encoding)
20
+ * - Size does not take into account indentation that can be applied to JSON.stringify
21
+ * - Non-numerical properties of Arrays are ignored. Same behavior as JSON.stringify
22
+ *
23
+ * @param source User-provided data meant to be serialized using JSON.stringify
24
+ * @param maxCharacterCount Maximum number of characters allowed in serialized form
25
+ */
26
+
27
+ export function sanitize(source, maxCharacterCount) {
28
+ if (maxCharacterCount === undefined) {
29
+ maxCharacterCount = SANITIZE_DEFAULT_MAX_CHARACTER_COUNT;
30
+ } // Unbind any toJSON function we may have on [] or {} prototypes
31
+
32
+
33
+ var restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype);
34
+ var restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype); // Initial call to sanitizeProcessor - will populate containerQueue if source is an Array or a plain Object
35
+
36
+ var containerQueue = [];
37
+ var visitedObjectsWithPath = new WeakMap();
38
+ var sanitizedData = sanitizeProcessor(source, JSON_PATH_ROOT_ELEMENT, undefined, containerQueue, visitedObjectsWithPath);
39
+ var accumulatedCharacterCount = JSON.stringify(sanitizedData) && JSON.stringify(sanitizedData).length || 0;
40
+
41
+ if (accumulatedCharacterCount > maxCharacterCount) {
42
+ warnOverCharacterLimit(maxCharacterCount, 'discarded', source);
43
+ return undefined;
44
+ }
45
+
46
+ while (containerQueue.length > 0 && accumulatedCharacterCount < maxCharacterCount) {
47
+ var containerToProcess = containerQueue.shift();
48
+ var separatorLength = 0; // 0 for the first element, 1 for subsequent elements
49
+ // Arrays and Objects have to be handled distinctly to ensure
50
+ // we do not pick up non-numerical properties from Arrays
51
+
52
+ if (Array.isArray(containerToProcess.source)) {
53
+ for (var key = 0; key < containerToProcess.source.length; key++) {
54
+ var targetData = sanitizeProcessor(containerToProcess.source[key], containerToProcess.path, key, containerQueue, visitedObjectsWithPath);
55
+
56
+ if (targetData !== undefined) {
57
+ accumulatedCharacterCount += JSON.stringify(targetData).length;
58
+ } else {
59
+ // When an element of an Array (targetData) is undefined, it is serialized as null:
60
+ // JSON.stringify([undefined]) => '[null]' - This accounts for 4 characters
61
+ accumulatedCharacterCount += 4;
62
+ }
63
+
64
+ accumulatedCharacterCount += separatorLength;
65
+ separatorLength = 1;
66
+
67
+ if (accumulatedCharacterCount > maxCharacterCount) {
68
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source);
69
+ break;
70
+ }
71
+
72
+ containerToProcess.target[key] = targetData;
73
+ }
74
+ } else {
75
+ for (var key in containerToProcess.source) {
76
+ if (Object.prototype.hasOwnProperty.call(containerToProcess.source, key)) {
77
+ var targetData = sanitizeProcessor(containerToProcess.source[key], containerToProcess.path, key, containerQueue, visitedObjectsWithPath); // When a property of an object has an undefined value, it will be dropped during serialization:
78
+ // JSON.stringify({a:undefined}) => '{}'
79
+
80
+ if (targetData !== undefined) {
81
+ accumulatedCharacterCount += JSON.stringify(targetData).length + separatorLength + key.length + KEY_DECORATION_LENGTH;
82
+ separatorLength = 1;
83
+ }
84
+
85
+ if (accumulatedCharacterCount > maxCharacterCount) {
86
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source);
87
+ break;
88
+ }
89
+
90
+ containerToProcess.target[key] = targetData;
91
+ }
92
+ }
93
+ }
94
+ } // Rebind detached toJSON functions
95
+
96
+
97
+ restoreObjectPrototypeToJson();
98
+ restoreArrayPrototypeToJson();
99
+ return sanitizedData;
100
+ }
101
+ /**
102
+ * Internal function to factorize the process common to the
103
+ * initial call to sanitize, and iterations for Arrays and Objects
104
+ *
105
+ */
106
+
107
+ function sanitizeProcessor(source, parentPath, key, queue, visitedObjectsWithPath) {
108
+ // Start by handling toJSON, as we want to sanitize its output
109
+ var sourceToSanitize = tryToApplyToJSON(source);
110
+
111
+ if (!sourceToSanitize || typeof sourceToSanitize !== 'object') {
112
+ return sanitizePrimitivesAndFunctions(sourceToSanitize);
113
+ }
114
+
115
+ var sanitizedSource = sanitizeObjects(sourceToSanitize);
116
+
117
+ if (sanitizedSource !== '[Object]' && sanitizedSource !== '[Array]' && sanitizedSource !== '[Error]') {
118
+ return sanitizedSource;
119
+ } // Handle potential cyclic references
120
+ // We need to use source as sourceToSanitize could be a reference to a new object
121
+ // At this stage, we know the source is an object type
122
+
123
+
124
+ var sourceAsObject = source;
125
+
126
+ if (visitedObjectsWithPath.has(sourceAsObject)) {
127
+ return '[Reference seen at ' + visitedObjectsWithPath.get(sourceAsObject) + ']';
128
+ } // Add processed source to queue
129
+
130
+
131
+ var currentPath = key !== undefined ? parentPath + '.' + key : parentPath;
132
+ var target = Array.isArray(sourceToSanitize) ? [] : {};
133
+ visitedObjectsWithPath.set(sourceAsObject, currentPath);
134
+ queue.push({
135
+ source: sourceToSanitize,
136
+ target,
137
+ path: currentPath
138
+ });
139
+ return target;
140
+ }
141
+ /**
142
+ * Handles sanitization of simple, non-object types
143
+ *
144
+ */
145
+
146
+
147
+ function sanitizePrimitivesAndFunctions(value) {
148
+ // BigInt cannot be serialized by JSON.stringify(), convert it to a string representation
149
+ if (typeof value === 'bigint') {
150
+ return '[BigInt] ' + value.toString();
151
+ } // Functions cannot be serialized by JSON.stringify(). Moreover, if a faulty toJSON is present, it needs to be converted
152
+ // so it won't prevent stringify from serializing later
153
+
154
+
155
+ if (typeof value === 'function') {
156
+ return '[Function] ' + value.name || 'unknown';
157
+ } // JSON.stringify() does not serialize symbols.
158
+
159
+
160
+ if (typeof value === 'symbol') {
161
+ // symbol.description is part of ES2019+
162
+ return '[Symbol] ' + value.description || value.toString();
163
+ }
164
+
165
+ return value;
166
+ }
167
+ /**
168
+ * Handles sanitization of object types
169
+ *
170
+ * LIMITATIONS
171
+ * - If a class defines a toStringTag Symbol, it will fall in the catch-all method and prevent enumeration of properties.
172
+ * To avoid this, a toJSON method can be defined.
173
+ * - IE11 does not return a distinct type for objects such as Map, WeakMap, ... These objects will pass through and their
174
+ * properties enumerated if any.
175
+ *
176
+ */
177
+
178
+
179
+ function sanitizeObjects(value) {
180
+ try {
181
+ // Handle events - Keep a simple implementation to avoid breaking changes
182
+ if (value instanceof Event) {
183
+ return {
184
+ isTrusted: value.isTrusted
185
+ };
186
+ } // Handle all remaining object types in a generic way
187
+
188
+
189
+ var result = Object.prototype.toString.call(value);
190
+ var match = result.match(/\[object (.*)\]/);
191
+
192
+ if (match && match[1]) {
193
+ return '[' + match[1] + ']';
194
+ }
195
+ } catch (_unused) {// If the previous serialization attempts failed, and we cannot convert using
196
+ // Object.prototype.toString, declare the value unserializable
197
+ }
198
+
199
+ return '[Unserializable]';
200
+ }
201
+ /**
202
+ * Checks if a toJSON function exists and tries to execute it
203
+ *
204
+ */
205
+
206
+
207
+ function tryToApplyToJSON(value) {
208
+ var object = value;
209
+
210
+ if (object && typeof object.toJSON === 'function') {
211
+ try {
212
+ return object.toJSON();
213
+ } catch (_unused2) {// If toJSON fails, we continue by trying to serialize the value manually
214
+ }
215
+ }
216
+
217
+ return value;
218
+ }
219
+ /**
220
+ * Helper function to display the warning when the accumulated character count is over the limit
221
+ */
222
+
223
+
224
+ function warnOverCharacterLimit(maxCharacterCount, changeType, source) {
225
+ display.warn('The data provided has been ' + changeType + ' as it is over the limit of ' + maxCharacterCount + ' characters:', source);
226
+ }
@@ -1621,7 +1621,7 @@ export function isChromium() {
1621
1621
  */
1622
1622
 
1623
1623
  export function getLinkElementOrigin(element) {
1624
- if (element.origin) {
1624
+ if (element.origin && element.origin !== 'null') {
1625
1625
  return element.origin;
1626
1626
  }
1627
1627
 
@@ -8,10 +8,10 @@ export function isValidUrl(url) {
8
8
  } catch (e) {
9
9
  return false;
10
10
  }
11
- }
12
- export function haveSameOrigin(url1, url2) {
13
- return getOrigin(url1) === getOrigin(url2);
14
- }
11
+ } // export function haveSameOrigin(url1, url2) {
12
+ // return getOrigin(url1) === getOrigin(url2)
13
+ // }
14
+
15
15
  export function getOrigin(url) {
16
16
  return getLinkElementOrigin(buildUrl(url));
17
17
  }
package/esm/index.js CHANGED
@@ -9,6 +9,7 @@ export * from './error/trackRuntimeError';
9
9
  export * from './console/consoleObservable';
10
10
  export * from './report/reportObservable';
11
11
  export * from './helper/display';
12
+ export * from './helper/sanitize';
12
13
  export * from './helper/eventEmitter';
13
14
  export * from './helper/lifeCycle';
14
15
  export * from './helper/limitModification';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudcare/browser-core",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
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": "770d3987076f77be6dee3ba6b2c11207ba593312"
23
+ "gitHead": "a62a6d650316cdd0471530a2954add77a21ebaad"
24
24
  }
@@ -58,7 +58,6 @@ export function computeTransportConfiguration(initConfiguration) {
58
58
  }
59
59
  }
60
60
  export function isIntakeRequest(url, configuration) {
61
- // return haveSameOrigin(url, configuration.datakitUrl)
62
61
  var notTakeRequest = [configuration.datakitUrl]
63
62
  if (configuration.logsEndpoint) {
64
63
  notTakeRequest.push(configuration.logsEndpoint)
package/src/dataMap.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { RumEventType } from './helper/enums'
2
2
  export var commonTags = {
3
- sdk_name: '_dd.sdk_name',
4
- sdk_version: '_dd.sdk_version',
3
+ sdk_name: '_gc.sdk_name',
4
+ sdk_version: '_gc.sdk_version',
5
5
  app_id: 'application.id',
6
6
  env: 'env',
7
7
  service: 'service',
@@ -46,7 +46,7 @@ export var dataMap = {
46
46
  },
47
47
  fields: {
48
48
  is_active: 'view.is_active',
49
- session_replay_stats: '_dd.replay_stats',
49
+ session_replay_stats: '_gc.replay_stats',
50
50
  session_is_active: 'session.is_active',
51
51
  view_error_count: 'view.error.count',
52
52
  view_resource_count: 'view.resource.count',
@@ -75,8 +75,8 @@ export var dataMap = {
75
75
  resource: {
76
76
  type: RumEventType.RESOURCE,
77
77
  tags: {
78
- trace_id: '_dd.trace_id',
79
- span_id: '_dd.span_id',
78
+ trace_id: '_gc.trace_id',
79
+ span_id: '_gc.span_id',
80
80
  resource_url: 'resource.url',
81
81
  resource_url_host: 'resource.url_host',
82
82
  resource_url_path: 'resource.url_path',
@@ -109,8 +109,8 @@ export var dataMap = {
109
109
  type: RumEventType.ERROR,
110
110
  tags: {
111
111
  error_id: 'error.id',
112
- trace_id: '_dd.trace_id',
113
- span_id: '_dd.span_id',
112
+ trace_id: '_gc.trace_id',
113
+ span_id: '_gc.span_id',
114
114
  error_source: 'error.source',
115
115
  error_type: 'error.type',
116
116
  error_handling: 'error.handling'
@@ -149,8 +149,8 @@ export var dataMap = {
149
149
  action_resource_count: 'action.resource.count',
150
150
  action_frustration_types: 'action.frustration.type',
151
151
  action_long_task_count: 'action.long_task.count',
152
- action_target: '_dd.action.target',
153
- action_position: '_dd.action.position'
152
+ action_target: '_gc.action.target',
153
+ action_position: '_gc.action.position'
154
154
  }
155
155
  },
156
156
  browser_log: {
@@ -1,18 +1,25 @@
1
- import { extend2Lev, each } from './tools'
1
+ import { extend2Lev, each, objectEntries, getType, deepClone } from './tools'
2
+ import { sanitize } from './sanitize'
2
3
 
3
4
  /**
4
- * Current limitations:
5
+ * Current limitation:
5
6
  * - field path do not support array, 'a.b.c' only
6
- * - modifiable fields type must be string
7
7
  */
8
8
  export function limitModification(object, modifiableFieldPaths, modifier) {
9
- var clone = extend2Lev({}, object)
9
+ var clone = deepClone(object)
10
10
  var result = modifier(clone)
11
- each(modifiableFieldPaths, function (path) {
12
- var originalValue = get(object, path)
13
- var newValue = get(clone, path)
14
- if (typeof originalValue === 'string' && typeof newValue === 'string') {
15
- set(object, path, newValue)
11
+ each(objectEntries(modifiableFieldPaths), function (filedPaths) {
12
+ var fieldPath = filedPaths[0]
13
+ var fieldType = filedPaths[1]
14
+ var newValue = get(clone, fieldPath)
15
+ var newType = getType(newValue)
16
+ if (newType === fieldType) {
17
+ set(object, fieldPath, sanitize(newValue))
18
+ } else if (
19
+ fieldType === 'object' &&
20
+ (newType === 'undefined' || newType === 'null')
21
+ ) {
22
+ set(object, fieldPath, {})
16
23
  }
17
24
  })
18
25
 
@@ -21,15 +28,12 @@ export function limitModification(object, modifiableFieldPaths, modifier) {
21
28
 
22
29
  function get(object, path) {
23
30
  var current = object
24
- var fields = path.split('.')
25
- for (var i = 0; i < fields.length; i++) {
26
- var field = fields[i]
31
+ for (var field of path.split('.')) {
27
32
  if (!isValidObjectContaining(current, field)) {
28
33
  return
29
34
  }
30
35
  current = current[field]
31
36
  }
32
-
33
37
  return current
34
38
  }
35
39
 
@@ -38,7 +42,7 @@ function set(object, path, value) {
38
42
  var fields = path.split('.')
39
43
  for (var i = 0; i < fields.length; i += 1) {
40
44
  var field = fields[i]
41
- if (!isValidObjectContaining(current, field)) {
45
+ if (!isValidObject(current)) {
42
46
  return
43
47
  }
44
48
  if (i !== fields.length - 1) {
@@ -49,6 +53,12 @@ function set(object, path, value) {
49
53
  }
50
54
  }
51
55
 
56
+ function isValidObject(object) {
57
+ return getType(object) === 'object'
58
+ }
59
+
52
60
  function isValidObjectContaining(object, field) {
53
- return typeof object === 'object' && object !== null && field in object
61
+ return (
62
+ isValidObject(object) && Object.prototype.hasOwnProperty.call(object, field)
63
+ )
54
64
  }
@@ -0,0 +1,260 @@
1
+ import { display } from './display'
2
+ import { ONE_KIBI_BYTE } from './byteUtils'
3
+ import { detachToJsonMethod } from './serialisation/jsonStringify'
4
+
5
+ // The maximum size of a single event is 256KiB. By default, we ensure that user-provided data
6
+ // going through sanitize fits inside our events, while leaving room for other contexts, metadata, ...
7
+ var SANITIZE_DEFAULT_MAX_CHARACTER_COUNT = 220 * ONE_KIBI_BYTE
8
+
9
+ // Symbol for the root element of the JSONPath used for visited objects
10
+ var JSON_PATH_ROOT_ELEMENT = '$'
11
+
12
+ // When serializing (using JSON.stringify) a key of an object, { key: 42 } gets wrapped in quotes as "key".
13
+ // With the separator (:), we need to add 3 characters to the count.
14
+ var KEY_DECORATION_LENGTH = 3
15
+
16
+ /**
17
+ * Ensures user-provided data is 'safe' for the SDK
18
+ * - Deep clones data
19
+ * - Removes cyclic references
20
+ * - Transforms unserializable types to a string representation
21
+ *
22
+ * LIMITATIONS:
23
+ * - Size is in characters, not byte count (may differ according to character encoding)
24
+ * - Size does not take into account indentation that can be applied to JSON.stringify
25
+ * - Non-numerical properties of Arrays are ignored. Same behavior as JSON.stringify
26
+ *
27
+ * @param source User-provided data meant to be serialized using JSON.stringify
28
+ * @param maxCharacterCount Maximum number of characters allowed in serialized form
29
+ */
30
+
31
+ export function sanitize(source, maxCharacterCount) {
32
+ if (maxCharacterCount === undefined) {
33
+ maxCharacterCount = SANITIZE_DEFAULT_MAX_CHARACTER_COUNT
34
+ }
35
+ // Unbind any toJSON function we may have on [] or {} prototypes
36
+ var restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype)
37
+ var restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype)
38
+
39
+ // Initial call to sanitizeProcessor - will populate containerQueue if source is an Array or a plain Object
40
+ var containerQueue = []
41
+ var visitedObjectsWithPath = new WeakMap()
42
+ var sanitizedData = sanitizeProcessor(
43
+ source,
44
+ JSON_PATH_ROOT_ELEMENT,
45
+ undefined,
46
+ containerQueue,
47
+ visitedObjectsWithPath
48
+ )
49
+ var accumulatedCharacterCount =
50
+ (JSON.stringify(sanitizedData) && JSON.stringify(sanitizedData).length) || 0
51
+ if (accumulatedCharacterCount > maxCharacterCount) {
52
+ warnOverCharacterLimit(maxCharacterCount, 'discarded', source)
53
+ return undefined
54
+ }
55
+
56
+ while (
57
+ containerQueue.length > 0 &&
58
+ accumulatedCharacterCount < maxCharacterCount
59
+ ) {
60
+ var containerToProcess = containerQueue.shift()
61
+ var separatorLength = 0 // 0 for the first element, 1 for subsequent elements
62
+
63
+ // Arrays and Objects have to be handled distinctly to ensure
64
+ // we do not pick up non-numerical properties from Arrays
65
+ if (Array.isArray(containerToProcess.source)) {
66
+ for (var key = 0; key < containerToProcess.source.length; key++) {
67
+ var targetData = sanitizeProcessor(
68
+ containerToProcess.source[key],
69
+ containerToProcess.path,
70
+ key,
71
+ containerQueue,
72
+ visitedObjectsWithPath
73
+ )
74
+
75
+ if (targetData !== undefined) {
76
+ accumulatedCharacterCount += JSON.stringify(targetData).length
77
+ } else {
78
+ // When an element of an Array (targetData) is undefined, it is serialized as null:
79
+ // JSON.stringify([undefined]) => '[null]' - This accounts for 4 characters
80
+ accumulatedCharacterCount += 4
81
+ }
82
+ accumulatedCharacterCount += separatorLength
83
+ separatorLength = 1
84
+ if (accumulatedCharacterCount > maxCharacterCount) {
85
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source)
86
+ break
87
+ }
88
+ containerToProcess.target[key] = targetData
89
+ }
90
+ } else {
91
+ for (var key in containerToProcess.source) {
92
+ if (
93
+ Object.prototype.hasOwnProperty.call(containerToProcess.source, key)
94
+ ) {
95
+ var targetData = sanitizeProcessor(
96
+ containerToProcess.source[key],
97
+ containerToProcess.path,
98
+ key,
99
+ containerQueue,
100
+ visitedObjectsWithPath
101
+ )
102
+ // When a property of an object has an undefined value, it will be dropped during serialization:
103
+ // JSON.stringify({a:undefined}) => '{}'
104
+ if (targetData !== undefined) {
105
+ accumulatedCharacterCount +=
106
+ JSON.stringify(targetData).length +
107
+ separatorLength +
108
+ key.length +
109
+ KEY_DECORATION_LENGTH
110
+ separatorLength = 1
111
+ }
112
+ if (accumulatedCharacterCount > maxCharacterCount) {
113
+ warnOverCharacterLimit(maxCharacterCount, 'truncated', source)
114
+ break
115
+ }
116
+ containerToProcess.target[key] = targetData
117
+ }
118
+ }
119
+ }
120
+ }
121
+
122
+ // Rebind detached toJSON functions
123
+ restoreObjectPrototypeToJson()
124
+ restoreArrayPrototypeToJson()
125
+
126
+ return sanitizedData
127
+ }
128
+
129
+ /**
130
+ * Internal function to factorize the process common to the
131
+ * initial call to sanitize, and iterations for Arrays and Objects
132
+ *
133
+ */
134
+ function sanitizeProcessor(
135
+ source,
136
+ parentPath,
137
+ key,
138
+ queue,
139
+ visitedObjectsWithPath
140
+ ) {
141
+ // Start by handling toJSON, as we want to sanitize its output
142
+ var sourceToSanitize = tryToApplyToJSON(source)
143
+
144
+ if (!sourceToSanitize || typeof sourceToSanitize !== 'object') {
145
+ return sanitizePrimitivesAndFunctions(sourceToSanitize)
146
+ }
147
+
148
+ var sanitizedSource = sanitizeObjects(sourceToSanitize)
149
+ if (
150
+ sanitizedSource !== '[Object]' &&
151
+ sanitizedSource !== '[Array]' &&
152
+ sanitizedSource !== '[Error]'
153
+ ) {
154
+ return sanitizedSource
155
+ }
156
+
157
+ // Handle potential cyclic references
158
+ // We need to use source as sourceToSanitize could be a reference to a new object
159
+ // At this stage, we know the source is an object type
160
+ var sourceAsObject = source
161
+ if (visitedObjectsWithPath.has(sourceAsObject)) {
162
+ return (
163
+ '[Reference seen at ' + visitedObjectsWithPath.get(sourceAsObject) + ']'
164
+ )
165
+ }
166
+
167
+ // Add processed source to queue
168
+ var currentPath = key !== undefined ? parentPath + '.' + key : parentPath
169
+ var target = Array.isArray(sourceToSanitize) ? [] : {}
170
+ visitedObjectsWithPath.set(sourceAsObject, currentPath)
171
+ queue.push({ source: sourceToSanitize, target, path: currentPath })
172
+
173
+ return target
174
+ }
175
+
176
+ /**
177
+ * Handles sanitization of simple, non-object types
178
+ *
179
+ */
180
+ function sanitizePrimitivesAndFunctions(value) {
181
+ // BigInt cannot be serialized by JSON.stringify(), convert it to a string representation
182
+ if (typeof value === 'bigint') {
183
+ return '[BigInt] ' + value.toString()
184
+ }
185
+ // Functions cannot be serialized by JSON.stringify(). Moreover, if a faulty toJSON is present, it needs to be converted
186
+ // so it won't prevent stringify from serializing later
187
+ if (typeof value === 'function') {
188
+ return '[Function] ' + value.name || 'unknown'
189
+ }
190
+ // JSON.stringify() does not serialize symbols.
191
+ if (typeof value === 'symbol') {
192
+ // symbol.description is part of ES2019+
193
+ return '[Symbol] ' + value.description || value.toString()
194
+ }
195
+
196
+ return value
197
+ }
198
+
199
+ /**
200
+ * Handles sanitization of object types
201
+ *
202
+ * LIMITATIONS
203
+ * - If a class defines a toStringTag Symbol, it will fall in the catch-all method and prevent enumeration of properties.
204
+ * To avoid this, a toJSON method can be defined.
205
+ * - IE11 does not return a distinct type for objects such as Map, WeakMap, ... These objects will pass through and their
206
+ * properties enumerated if any.
207
+ *
208
+ */
209
+ function sanitizeObjects(value) {
210
+ try {
211
+ // Handle events - Keep a simple implementation to avoid breaking changes
212
+ if (value instanceof Event) {
213
+ return {
214
+ isTrusted: value.isTrusted
215
+ }
216
+ }
217
+
218
+ // Handle all remaining object types in a generic way
219
+ var result = Object.prototype.toString.call(value)
220
+ var match = result.match(/\[object (.*)\]/)
221
+ if (match && match[1]) {
222
+ return '[' + match[1] + ']'
223
+ }
224
+ } catch {
225
+ // If the previous serialization attempts failed, and we cannot convert using
226
+ // Object.prototype.toString, declare the value unserializable
227
+ }
228
+ return '[Unserializable]'
229
+ }
230
+
231
+ /**
232
+ * Checks if a toJSON function exists and tries to execute it
233
+ *
234
+ */
235
+ function tryToApplyToJSON(value) {
236
+ var object = value
237
+ if (object && typeof object.toJSON === 'function') {
238
+ try {
239
+ return object.toJSON()
240
+ } catch {
241
+ // If toJSON fails, we continue by trying to serialize the value manually
242
+ }
243
+ }
244
+
245
+ return value
246
+ }
247
+
248
+ /**
249
+ * Helper function to display the warning when the accumulated character count is over the limit
250
+ */
251
+ function warnOverCharacterLimit(maxCharacterCount, changeType, source) {
252
+ display.warn(
253
+ 'The data provided has been ' +
254
+ changeType +
255
+ ' as it is over the limit of ' +
256
+ maxCharacterCount +
257
+ ' characters:',
258
+ source
259
+ )
260
+ }
@@ -1603,7 +1603,7 @@ export function isChromium() {
1603
1603
  * https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/origin
1604
1604
  */
1605
1605
  export function getLinkElementOrigin(element) {
1606
- if (element.origin) {
1606
+ if (element.origin && element.origin !== 'null') {
1607
1607
  return element.origin
1608
1608
  }
1609
1609
  var sanitizedHost = element.host.replace(/(:80|:443)$/, '')
@@ -12,9 +12,9 @@ export function isValidUrl(url) {
12
12
  }
13
13
  }
14
14
 
15
- export function haveSameOrigin(url1, url2) {
16
- return getOrigin(url1) === getOrigin(url2)
17
- }
15
+ // export function haveSameOrigin(url1, url2) {
16
+ // return getOrigin(url1) === getOrigin(url2)
17
+ // }
18
18
 
19
19
  export function getOrigin(url) {
20
20
  return getLinkElementOrigin(buildUrl(url))
package/src/index.js CHANGED
@@ -9,6 +9,7 @@ export * from './error/trackRuntimeError'
9
9
  export * from './console/consoleObservable'
10
10
  export * from './report/reportObservable'
11
11
  export * from './helper/display'
12
+ export * from './helper/sanitize'
12
13
  export * from './helper/eventEmitter'
13
14
  export * from './helper/lifeCycle'
14
15
  export * from './helper/limitModification'