@cloudcare/browser-core 2.0.4 → 2.0.6
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/browser/addEventListener.js +57 -0
- package/cjs/browser/fetchObservable.js +4 -5
- package/cjs/browser/pageExitObservable.js +4 -2
- package/cjs/browser/runOnReadyState.js +21 -0
- package/cjs/browser/xhrObservable.js +7 -5
- package/cjs/configuration/configuration.js +5 -3
- package/cjs/console/consoleObservable.js +3 -1
- package/cjs/dataMap.js +1 -0
- package/cjs/helper/byteUtils.js +26 -0
- package/cjs/helper/contextHistory.js +4 -2
- package/cjs/helper/createEventRateLimiter.js +3 -1
- package/cjs/helper/errorTools.js +4 -2
- package/cjs/helper/instrumentMethod.js +2 -4
- package/cjs/helper/serialisation/contextManager.js +84 -0
- package/cjs/helper/serialisation/heavyCustomerDataWarning.js +34 -0
- package/cjs/helper/serialisation/jsonStringify.js +57 -0
- package/cjs/helper/serialisation/rowData.js +50 -0
- package/cjs/helper/timer.js +29 -0
- package/cjs/helper/tools.js +10 -331
- package/cjs/index.js +117 -0
- package/cjs/init.js +6 -6
- package/cjs/report/reportObservable.js +4 -2
- package/cjs/session/sessionCookieStore.js +3 -1
- package/cjs/session/sessionManagement.js +10 -5
- package/cjs/session/sessionStore.js +10 -4
- package/cjs/transport/batch.js +40 -91
- package/cjs/transport/flushController.js +121 -0
- package/cjs/transport/httpRequest.js +6 -2
- package/cjs/transport/index.js +9 -1
- package/cjs/transport/sendWithRetryStrategy.js +8 -4
- package/cjs/transport/startBatchWithReplica.js +10 -2
- package/cjs/user/index.js +18 -0
- package/cjs/user/user.js +42 -0
- package/esm/browser/addEventListener.js +46 -0
- package/esm/browser/fetchObservable.js +4 -3
- package/esm/browser/pageExitObservable.js +2 -1
- package/esm/browser/runOnReadyState.js +12 -0
- package/esm/browser/xhrObservable.js +6 -5
- package/esm/configuration/configuration.js +2 -1
- package/esm/console/consoleObservable.js +2 -1
- package/esm/dataMap.js +1 -0
- package/esm/helper/byteUtils.js +16 -0
- package/esm/helper/contextHistory.js +1 -0
- package/esm/helper/createEventRateLimiter.js +1 -0
- package/esm/helper/errorTools.js +2 -1
- package/esm/helper/instrumentMethod.js +1 -3
- package/esm/helper/serialisation/contextManager.js +70 -0
- package/esm/helper/serialisation/heavyCustomerDataWarning.js +20 -0
- package/esm/helper/serialisation/jsonStringify.js +46 -0
- package/esm/helper/serialisation/rowData.js +33 -0
- package/esm/helper/timer.js +14 -0
- package/esm/helper/tools.js +1 -292
- package/esm/index.js +10 -1
- package/esm/init.js +6 -6
- package/esm/report/reportObservable.js +3 -2
- package/esm/session/sessionCookieStore.js +1 -0
- package/esm/session/sessionManagement.js +5 -2
- package/esm/session/sessionStore.js +7 -2
- package/esm/transport/batch.js +31 -85
- package/esm/transport/flushController.js +114 -0
- package/esm/transport/httpRequest.js +5 -2
- package/esm/transport/index.js +2 -1
- package/esm/transport/sendWithRetryStrategy.js +3 -1
- package/esm/transport/startBatchWithReplica.js +9 -2
- package/esm/user/index.js +1 -0
- package/esm/user/user.js +32 -0
- package/package.json +22 -22
- package/src/browser/addEventListener.js +50 -0
- package/src/browser/fetchObservable.js +5 -5
- package/src/browser/pageExitObservable.js +4 -5
- package/src/browser/runOnReadyState.js +16 -0
- package/src/browser/xhrObservable.js +57 -32
- package/src/configuration/configuration.js +1 -1
- package/src/console/consoleObservable.js +22 -12
- package/src/dataMap.js +1 -0
- package/src/helper/byteUtils.js +17 -0
- package/src/helper/contextHistory.js +1 -1
- package/src/helper/createEventRateLimiter.js +7 -9
- package/src/helper/errorTools.js +2 -1
- package/src/helper/instrumentMethod.js +1 -2
- package/src/helper/serialisation/contextManager.js +79 -0
- package/src/helper/serialisation/heavyCustomerDataWarning.js +28 -0
- package/src/helper/serialisation/jsonStringify.js +47 -0
- package/src/helper/serialisation/rowData.js +41 -0
- package/src/helper/timer.js +21 -0
- package/src/helper/tools.js +2 -301
- package/src/index.js +11 -0
- package/src/init.js +6 -6
- package/src/report/reportObservable.js +40 -25
- package/src/session/sessionCookieStore.js +24 -14
- package/src/session/sessionManagement.js +34 -17
- package/src/session/sessionStore.js +7 -2
- package/src/transport/batch.js +39 -91
- package/src/transport/flushController.js +115 -0
- package/src/transport/httpRequest.js +13 -6
- package/src/transport/index.js +1 -0
- package/src/transport/sendWithRetryStrategy.js +3 -7
- package/src/transport/startBatchWithReplica.js +11 -7
- package/src/user/index.js +1 -0
- package/src/user/user.js +31 -0
|
@@ -38,8 +38,8 @@ function createFetchObservable() {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
function beforeSend(observable, input, init) {
|
|
41
|
-
var method = init && init.method ||
|
|
42
|
-
var url =
|
|
41
|
+
var method = init && init.method || input instanceof Request && input.method || 'GET';
|
|
42
|
+
var url = input instanceof Request ? input.url : normalizeUrl(String(input));
|
|
43
43
|
var startClocks = clocksNow();
|
|
44
44
|
var context = {
|
|
45
45
|
state: 'start',
|
|
@@ -64,7 +64,8 @@ function afterSend(observable, responsePromise, startContext) {
|
|
|
64
64
|
context.error = response;
|
|
65
65
|
} else if ('status' in response) {
|
|
66
66
|
context.response = response;
|
|
67
|
-
context.responseType = response.type;
|
|
67
|
+
context.responseType = response instanceof Response && response.type || ''; // issue The Response type getter can only be used on instances of Response
|
|
68
|
+
|
|
68
69
|
context.status = response.status;
|
|
69
70
|
context.isAborted = false;
|
|
70
71
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Observable } from '../helper/observable';
|
|
2
|
-
import {
|
|
2
|
+
import { includes, values } from '../helper/tools';
|
|
3
3
|
import { DOM_EVENT } from '../helper/enums';
|
|
4
|
+
import { addEventListener, addEventListeners } from '../browser/addEventListener';
|
|
4
5
|
export var PageExitReason = {
|
|
5
6
|
HIDDEN: 'visibility_hidden',
|
|
6
7
|
UNLOADING: 'before_unload',
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { addEventListener } from './addEventListener';
|
|
2
|
+
import { DOM_EVENT } from '../helper/enums';
|
|
3
|
+
export function runOnReadyState(expectedReadyState, callback) {
|
|
4
|
+
if (document.readyState === expectedReadyState || document.readyState === 'complete') {
|
|
5
|
+
callback();
|
|
6
|
+
} else {
|
|
7
|
+
var eventName = expectedReadyState === 'complete' ? DOM_EVENT.LOAD : DOM_EVENT.DOM_CONTENT_LOADED;
|
|
8
|
+
addEventListener(window, eventName, callback, {
|
|
9
|
+
once: true
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -2,6 +2,7 @@ import { instrumentMethodAndCallOriginal } from '../helper/instrumentMethod';
|
|
|
2
2
|
import { Observable } from '../helper/observable';
|
|
3
3
|
import { normalizeUrl } from '../helper/urlPolyfill';
|
|
4
4
|
import { shallowClone, elapsed, relativeNow, clocksNow, timeStampNow, UUID } from '../helper/tools';
|
|
5
|
+
import { addEventListener } from '../browser/addEventListener';
|
|
5
6
|
var xhrObservable;
|
|
6
7
|
var xhrContexts = {};
|
|
7
8
|
var DATA_FLUX_REQUEST_ID_KEY = '_DATAFLUX_REQUEST_UUID';
|
|
@@ -59,7 +60,7 @@ function sendXhr(observable) {
|
|
|
59
60
|
startContext.isAborted = false;
|
|
60
61
|
startContext.xhr = this;
|
|
61
62
|
var hasBeenReported = false;
|
|
62
|
-
var
|
|
63
|
+
var stopInstrumentingOnReadyStateChange = instrumentMethodAndCallOriginal(this, 'onreadystatechange', {
|
|
63
64
|
before: function before() {
|
|
64
65
|
if (this.readyState === XMLHttpRequest.DONE) {
|
|
65
66
|
// Try to report the XHR as soon as possible, because the XHR may be mutated by the
|
|
@@ -69,11 +70,11 @@ function sendXhr(observable) {
|
|
|
69
70
|
onEnd.call(this);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
|
-
});
|
|
73
|
+
}).stop;
|
|
73
74
|
|
|
74
75
|
var onEnd = function onEnd() {
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
unsubscribeLoadEndListener();
|
|
77
|
+
stopInstrumentingOnReadyStateChange();
|
|
77
78
|
|
|
78
79
|
if (hasBeenReported) {
|
|
79
80
|
return;
|
|
@@ -88,7 +89,7 @@ function sendXhr(observable) {
|
|
|
88
89
|
clearRequestId.call(this);
|
|
89
90
|
};
|
|
90
91
|
|
|
91
|
-
|
|
92
|
+
var unsubscribeLoadEndListener = addEventListener(this, 'loadend', onEnd).stop;
|
|
92
93
|
observable.notify(startContext);
|
|
93
94
|
}
|
|
94
95
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { getCurrentSite } from '../browser/cookie';
|
|
2
2
|
import { catchUserErrors } from '../helper/catchUserErrors';
|
|
3
3
|
import { display } from '../helper/display';
|
|
4
|
-
import { assign, isPercentage,
|
|
4
|
+
import { assign, isPercentage, ONE_SECOND, isNullUndefinedDefaultValue } from '../helper/tools';
|
|
5
|
+
import { ONE_KIBI_BYTE } from '../helper/byteUtils';
|
|
5
6
|
import { computeTransportConfiguration } from './transportConfiguration';
|
|
6
7
|
export var DefaultPrivacyLevel = {
|
|
7
8
|
ALLOW: 'allow',
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { computeStackTrace } from '../tracekit';
|
|
2
2
|
import { createHandlingStack, formatErrorMessage, toStackTraceString } from '../helper/errorTools';
|
|
3
3
|
import { mergeObservables, Observable } from '../helper/observable';
|
|
4
|
-
import { find,
|
|
4
|
+
import { find, map } from '../helper/tools';
|
|
5
|
+
import { jsonStringify } from '../helper/serialisation/jsonStringify';
|
|
5
6
|
import { ConsoleApiName } from '../helper/display';
|
|
6
7
|
var consoleObservablesByApi = {};
|
|
7
8
|
export function initConsoleObservable(apis) {
|
package/esm/dataMap.js
CHANGED
|
@@ -48,6 +48,7 @@ export var dataMap = {
|
|
|
48
48
|
},
|
|
49
49
|
fields: {
|
|
50
50
|
session_replay_stats: '_dd.replay_stats',
|
|
51
|
+
session_is_active: 'session.is_active',
|
|
51
52
|
view_error_count: 'view.error.count',
|
|
52
53
|
view_resource_count: 'view.resource.count',
|
|
53
54
|
view_long_task_count: 'view.long_task.count',
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export var ONE_KIBI_BYTE = 1024;
|
|
2
|
+
export var ONE_MEBI_BYTE = 1024 * ONE_KIBI_BYTE; // eslint-disable-next-line no-control-regex
|
|
3
|
+
|
|
4
|
+
var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/;
|
|
5
|
+
export function computeBytesCount(candidate) {
|
|
6
|
+
// Accurate bytes count computations can degrade performances when there is a lot of events to process
|
|
7
|
+
if (!HAS_MULTI_BYTES_CHARACTERS.test(candidate)) {
|
|
8
|
+
return candidate.length;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (window.TextEncoder !== undefined) {
|
|
12
|
+
return new TextEncoder().encode(candidate).length;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return new Blob([candidate]).size;
|
|
16
|
+
}
|
package/esm/helper/errorTools.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { noop } from './tools';
|
|
2
|
-
import {
|
|
2
|
+
import { setTimeout } from './timer';
|
|
3
3
|
export function instrumentMethod(object, method, instrumentationFactory) {
|
|
4
4
|
var original = object[method];
|
|
5
5
|
var instrumentation = instrumentationFactory(original);
|
|
@@ -57,8 +57,6 @@ export function instrumentSetter(object, property, after) {
|
|
|
57
57
|
// component, see issue RUMF-1443
|
|
58
58
|
|
|
59
59
|
|
|
60
|
-
var setTimeout = getZoneJsOriginalValue(window, 'setTimeout');
|
|
61
|
-
|
|
62
60
|
var instrumentation = function instrumentation(thisObject, value) {
|
|
63
61
|
// put hooked setter into event loop to avoid of set latency
|
|
64
62
|
setTimeout(function () {
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { computeBytesCount } from '../byteUtils';
|
|
2
|
+
import { deepClone, throttle } from '../tools';
|
|
3
|
+
import { jsonStringify } from './jsonStringify';
|
|
4
|
+
import { warnIfCustomerDataLimitReached } from './heavyCustomerDataWarning';
|
|
5
|
+
export var BYTES_COMPUTATION_THROTTLING_DELAY = 200;
|
|
6
|
+
export function createContextManager(customerDataType, computeBytesCountImpl) {
|
|
7
|
+
if (typeof computeBytesCountImpl === 'undefined') {
|
|
8
|
+
computeBytesCountImpl = computeBytesCount;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
var context = {};
|
|
12
|
+
var bytesCountCache;
|
|
13
|
+
var alreadyWarned = false; // Throttle the bytes computation to minimize the impact on performance.
|
|
14
|
+
// Especially useful if the user call context APIs synchronously multiple times in a row
|
|
15
|
+
|
|
16
|
+
var computeBytesCountThrottled = throttle(function (context) {
|
|
17
|
+
bytesCountCache = computeBytesCountImpl(jsonStringify(context));
|
|
18
|
+
|
|
19
|
+
if (!alreadyWarned) {
|
|
20
|
+
alreadyWarned = warnIfCustomerDataLimitReached(bytesCountCache, customerDataType);
|
|
21
|
+
}
|
|
22
|
+
}, BYTES_COMPUTATION_THROTTLING_DELAY).throttled;
|
|
23
|
+
return {
|
|
24
|
+
getBytesCount: function getBytesCount() {
|
|
25
|
+
return bytesCountCache;
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
/** @deprecated use getContext instead */
|
|
29
|
+
get: function get() {
|
|
30
|
+
return context;
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
/** @deprecated use setContextProperty instead */
|
|
34
|
+
add: function add(key, value) {
|
|
35
|
+
context[key] = value;
|
|
36
|
+
computeBytesCountThrottled(context);
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
/** @deprecated renamed to removeContextProperty */
|
|
40
|
+
remove: function remove(key) {
|
|
41
|
+
delete context[key];
|
|
42
|
+
computeBytesCountThrottled(context);
|
|
43
|
+
},
|
|
44
|
+
|
|
45
|
+
/** @deprecated use setContext instead */
|
|
46
|
+
set: function set(newContext) {
|
|
47
|
+
context = newContext;
|
|
48
|
+
computeBytesCountThrottled(context);
|
|
49
|
+
},
|
|
50
|
+
getContext: function getContext() {
|
|
51
|
+
return deepClone(context);
|
|
52
|
+
},
|
|
53
|
+
setContext: function setContext(newContext) {
|
|
54
|
+
context = deepClone(newContext);
|
|
55
|
+
computeBytesCountThrottled(context);
|
|
56
|
+
},
|
|
57
|
+
setContextProperty: function setContextProperty(key, property) {
|
|
58
|
+
context[key] = deepClone(property);
|
|
59
|
+
computeBytesCountThrottled(context);
|
|
60
|
+
},
|
|
61
|
+
removeContextProperty: function removeContextProperty(key) {
|
|
62
|
+
delete context[key];
|
|
63
|
+
computeBytesCountThrottled(context);
|
|
64
|
+
},
|
|
65
|
+
clearContext: function clearContext() {
|
|
66
|
+
context = {};
|
|
67
|
+
bytesCountCache = 0;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ONE_KIBI_BYTE } from '../byteUtils';
|
|
2
|
+
import { display } from '../display'; // RUM and logs batch bytes limit is 16KB
|
|
3
|
+
// ensure that we leave room for other event attributes and maintain a decent amount of event per batch
|
|
4
|
+
// (3KB (customer data) + 1KB (other attributes)) * 4 (events per batch) = 16KB
|
|
5
|
+
|
|
6
|
+
export var CUSTOMER_DATA_BYTES_LIMIT = 3 * ONE_KIBI_BYTE;
|
|
7
|
+
export var CustomerDataType = {
|
|
8
|
+
FeatureFlag: 'feature flag evaluation',
|
|
9
|
+
User: 'user',
|
|
10
|
+
GlobalContext: 'global context',
|
|
11
|
+
LoggerContext: 'logger context'
|
|
12
|
+
};
|
|
13
|
+
export function warnIfCustomerDataLimitReached(bytesCount, customerDataType) {
|
|
14
|
+
if (bytesCount > CUSTOMER_DATA_BYTES_LIMIT) {
|
|
15
|
+
display.warn('The ' + customerDataType + 'data is over ' + CUSTOMER_DATA_BYTES_LIMIT / ONE_KIBI_BYTE + " KiB. On low connectivity, the SDK has the potential to exhaust the user's upload bandwidth.");
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { noop } from '../tools';
|
|
2
|
+
/**
|
|
3
|
+
* Custom implementation of JSON.stringify that ignores some toJSON methods. We need to do that
|
|
4
|
+
* because some sites badly override toJSON on certain objects. Removing all toJSON methods from
|
|
5
|
+
* nested values would be too costly, so we just detach them from the root value, and native classes
|
|
6
|
+
* used to build JSON values (Array and Object).
|
|
7
|
+
*
|
|
8
|
+
* Note: this still assumes that JSON.stringify is correct.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export function jsonStringify(value, replacer, space) {
|
|
12
|
+
if (typeof value !== 'object' || value === null) {
|
|
13
|
+
return JSON.stringify(value);
|
|
14
|
+
} // Note: The order matter here. We need to detach toJSON methods on parent classes before their
|
|
15
|
+
// subclasses.
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
var restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype);
|
|
19
|
+
var restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype);
|
|
20
|
+
var restoreValuePrototypeToJson = detachToJsonMethod(Object.getPrototypeOf(value));
|
|
21
|
+
var restoreValueToJson = detachToJsonMethod(value);
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
return JSON.stringify(value, replacer, space);
|
|
25
|
+
} catch (_unused) {
|
|
26
|
+
return '<error: unable to serialize object>';
|
|
27
|
+
} finally {
|
|
28
|
+
restoreObjectPrototypeToJson();
|
|
29
|
+
restoreArrayPrototypeToJson();
|
|
30
|
+
restoreValuePrototypeToJson();
|
|
31
|
+
restoreValueToJson();
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function detachToJsonMethod(value) {
|
|
35
|
+
var object = value;
|
|
36
|
+
var objectToJson = object.toJSON;
|
|
37
|
+
|
|
38
|
+
if (objectToJson) {
|
|
39
|
+
delete object.toJSON;
|
|
40
|
+
return () => {
|
|
41
|
+
object.toJSON = objectToJson;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return noop;
|
|
46
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsonStringify } from './jsonStringify';
|
|
2
|
+
import { isString } from '../tools';
|
|
3
|
+
export function escapeRowData(str) {
|
|
4
|
+
if (typeof str === 'object' && str) {
|
|
5
|
+
str = jsonStringify(str);
|
|
6
|
+
} else if (!isString(str)) {
|
|
7
|
+
return str;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
var reg = /[\s=,"]/g;
|
|
11
|
+
return String(str).replace(reg, function (word) {
|
|
12
|
+
return '\\' + word;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
export function escapeJsonValue(value) {
|
|
16
|
+
if (isString(value)) {
|
|
17
|
+
return value;
|
|
18
|
+
} else {
|
|
19
|
+
return jsonStringify(value);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export function escapeFieldValueStr(str) {
|
|
23
|
+
return '"' + str.replace(/\\/g, '\\\\').replace(/[\\]*"/g, '"').replace(/"/g, '\\"') + '"';
|
|
24
|
+
}
|
|
25
|
+
export function escapeRowField(value) {
|
|
26
|
+
if (typeof value === 'object' && value) {
|
|
27
|
+
return escapeFieldValueStr(jsonStringify(value));
|
|
28
|
+
} else if (isString(value)) {
|
|
29
|
+
return escapeFieldValueStr(value);
|
|
30
|
+
} else {
|
|
31
|
+
return value;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { getZoneJsOriginalValue } from './getZoneJsOriginalValue';
|
|
2
|
+
import { getGlobalObject } from '../init';
|
|
3
|
+
export function setTimeout(callback, delay) {
|
|
4
|
+
return getZoneJsOriginalValue(getGlobalObject(), 'setTimeout')(callback, delay);
|
|
5
|
+
}
|
|
6
|
+
export function clearTimeout(timeoutId) {
|
|
7
|
+
getZoneJsOriginalValue(getGlobalObject(), 'clearTimeout')(timeoutId);
|
|
8
|
+
}
|
|
9
|
+
export function setInterval(callback, delay) {
|
|
10
|
+
return getZoneJsOriginalValue(window, 'setInterval')(callback, delay);
|
|
11
|
+
}
|
|
12
|
+
export function clearInterval(timeoutId) {
|
|
13
|
+
getZoneJsOriginalValue(window, 'clearInterval')(timeoutId);
|
|
14
|
+
}
|