@cloudcare/browser-core 2.0.3 → 2.0.5

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.
Files changed (97) hide show
  1. package/cjs/browser/addEventListener.js +57 -0
  2. package/cjs/browser/pageExitObservable.js +4 -2
  3. package/cjs/browser/runOnReadyState.js +21 -0
  4. package/cjs/browser/xhrObservable.js +7 -5
  5. package/cjs/configuration/configuration.js +5 -3
  6. package/cjs/console/consoleObservable.js +3 -1
  7. package/cjs/dataMap.js +1 -0
  8. package/cjs/helper/byteUtils.js +26 -0
  9. package/cjs/helper/contextHistory.js +4 -2
  10. package/cjs/helper/createEventRateLimiter.js +3 -1
  11. package/cjs/helper/errorTools.js +4 -2
  12. package/cjs/helper/instrumentMethod.js +2 -4
  13. package/cjs/helper/serialisation/contextManager.js +84 -0
  14. package/cjs/helper/serialisation/heavyCustomerDataWarning.js +34 -0
  15. package/cjs/helper/serialisation/jsonStringify.js +57 -0
  16. package/cjs/helper/serialisation/rowData.js +50 -0
  17. package/cjs/helper/timer.js +29 -0
  18. package/cjs/helper/tools.js +10 -331
  19. package/cjs/index.js +117 -0
  20. package/cjs/init.js +6 -6
  21. package/cjs/report/reportObservable.js +4 -2
  22. package/cjs/session/sessionCookieStore.js +3 -1
  23. package/cjs/session/sessionManagement.js +10 -5
  24. package/cjs/session/sessionStore.js +10 -4
  25. package/cjs/transport/batch.js +40 -91
  26. package/cjs/transport/flushController.js +121 -0
  27. package/cjs/transport/httpRequest.js +6 -2
  28. package/cjs/transport/index.js +9 -1
  29. package/cjs/transport/sendWithRetryStrategy.js +8 -4
  30. package/cjs/transport/startBatchWithReplica.js +10 -2
  31. package/cjs/user/index.js +18 -0
  32. package/cjs/user/user.js +42 -0
  33. package/esm/browser/addEventListener.js +46 -0
  34. package/esm/browser/pageExitObservable.js +2 -1
  35. package/esm/browser/runOnReadyState.js +12 -0
  36. package/esm/browser/xhrObservable.js +6 -5
  37. package/esm/configuration/configuration.js +2 -1
  38. package/esm/console/consoleObservable.js +2 -1
  39. package/esm/dataMap.js +1 -0
  40. package/esm/helper/byteUtils.js +16 -0
  41. package/esm/helper/contextHistory.js +1 -0
  42. package/esm/helper/createEventRateLimiter.js +1 -0
  43. package/esm/helper/errorTools.js +2 -1
  44. package/esm/helper/instrumentMethod.js +1 -3
  45. package/esm/helper/serialisation/contextManager.js +70 -0
  46. package/esm/helper/serialisation/heavyCustomerDataWarning.js +20 -0
  47. package/esm/helper/serialisation/jsonStringify.js +46 -0
  48. package/esm/helper/serialisation/rowData.js +33 -0
  49. package/esm/helper/timer.js +14 -0
  50. package/esm/helper/tools.js +1 -292
  51. package/esm/index.js +10 -1
  52. package/esm/init.js +6 -6
  53. package/esm/report/reportObservable.js +3 -2
  54. package/esm/session/sessionCookieStore.js +1 -0
  55. package/esm/session/sessionManagement.js +5 -2
  56. package/esm/session/sessionStore.js +7 -2
  57. package/esm/transport/batch.js +31 -85
  58. package/esm/transport/flushController.js +114 -0
  59. package/esm/transport/httpRequest.js +5 -2
  60. package/esm/transport/index.js +2 -1
  61. package/esm/transport/sendWithRetryStrategy.js +3 -1
  62. package/esm/transport/startBatchWithReplica.js +9 -2
  63. package/esm/user/index.js +1 -0
  64. package/esm/user/user.js +32 -0
  65. package/package.json +22 -22
  66. package/src/browser/addEventListener.js +50 -0
  67. package/src/browser/pageExitObservable.js +4 -5
  68. package/src/browser/runOnReadyState.js +16 -0
  69. package/src/browser/xhrObservable.js +57 -32
  70. package/src/configuration/configuration.js +1 -1
  71. package/src/console/consoleObservable.js +22 -12
  72. package/src/dataMap.js +1 -0
  73. package/src/helper/byteUtils.js +17 -0
  74. package/src/helper/contextHistory.js +1 -1
  75. package/src/helper/createEventRateLimiter.js +7 -9
  76. package/src/helper/errorTools.js +2 -1
  77. package/src/helper/instrumentMethod.js +1 -2
  78. package/src/helper/serialisation/contextManager.js +79 -0
  79. package/src/helper/serialisation/heavyCustomerDataWarning.js +28 -0
  80. package/src/helper/serialisation/jsonStringify.js +47 -0
  81. package/src/helper/serialisation/rowData.js +41 -0
  82. package/src/helper/timer.js +21 -0
  83. package/src/helper/tools.js +2 -301
  84. package/src/index.js +11 -0
  85. package/src/init.js +6 -6
  86. package/src/report/reportObservable.js +40 -25
  87. package/src/session/sessionCookieStore.js +24 -14
  88. package/src/session/sessionManagement.js +34 -17
  89. package/src/session/sessionStore.js +7 -2
  90. package/src/transport/batch.js +39 -91
  91. package/src/transport/flushController.js +115 -0
  92. package/src/transport/httpRequest.js +13 -6
  93. package/src/transport/index.js +1 -0
  94. package/src/transport/sendWithRetryStrategy.js +3 -7
  95. package/src/transport/startBatchWithReplica.js +11 -7
  96. package/src/user/index.js +1 -0
  97. package/src/user/user.js +31 -0
@@ -0,0 +1,16 @@
1
+ import { addEventListener } from './addEventListener'
2
+ import { DOM_EVENT } from '../helper/enums'
3
+ export function runOnReadyState(expectedReadyState, callback) {
4
+ if (
5
+ document.readyState === expectedReadyState ||
6
+ document.readyState === 'complete'
7
+ ) {
8
+ callback()
9
+ } else {
10
+ var eventName =
11
+ expectedReadyState === 'complete'
12
+ ? DOM_EVENT.LOAD
13
+ : DOM_EVENT.DOM_CONTENT_LOADED
14
+ addEventListener(window, eventName, callback, { once: true })
15
+ }
16
+ }
@@ -1,8 +1,15 @@
1
1
  import { instrumentMethodAndCallOriginal } from '../helper/instrumentMethod'
2
2
  import { Observable } from '../helper/observable'
3
3
  import { normalizeUrl } from '../helper/urlPolyfill'
4
- import { shallowClone, elapsed, relativeNow, clocksNow, timeStampNow, UUID } from '../helper/tools'
5
-
4
+ import {
5
+ shallowClone,
6
+ elapsed,
7
+ relativeNow,
8
+ clocksNow,
9
+ timeStampNow,
10
+ UUID
11
+ } from '../helper/tools'
12
+ import { addEventListener } from '../browser/addEventListener'
6
13
  var xhrObservable
7
14
  var xhrContexts = {}
8
15
  var DATA_FLUX_REQUEST_ID_KEY = '_DATAFLUX_REQUEST_UUID'
@@ -14,22 +21,34 @@ export function initXhrObservable() {
14
21
  }
15
22
 
16
23
  function createXhrObservable() {
17
- var observable = new Observable(function(){
18
- var openInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'open', {
19
- before: openXhr,
20
- })
24
+ var observable = new Observable(function () {
25
+ var openInstrumentMethod = instrumentMethodAndCallOriginal(
26
+ XMLHttpRequest.prototype,
27
+ 'open',
28
+ {
29
+ before: openXhr
30
+ }
31
+ )
21
32
 
22
- var sendInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'send', {
23
- before: function() {
24
- sendXhr.call(this, observable)
25
- },
26
- })
33
+ var sendInstrumentMethod = instrumentMethodAndCallOriginal(
34
+ XMLHttpRequest.prototype,
35
+ 'send',
36
+ {
37
+ before: function () {
38
+ sendXhr.call(this, observable)
39
+ }
40
+ }
41
+ )
27
42
 
28
- var abortInstrumentMethod = instrumentMethodAndCallOriginal(XMLHttpRequest.prototype, 'abort', {
29
- before:abortXhr,
30
- })
43
+ var abortInstrumentMethod = instrumentMethodAndCallOriginal(
44
+ XMLHttpRequest.prototype,
45
+ 'abort',
46
+ {
47
+ before: abortXhr
48
+ }
49
+ )
31
50
 
32
- return function() {
51
+ return function () {
33
52
  openInstrumentMethod.stop()
34
53
  sendInstrumentMethod.stop()
35
54
  abortInstrumentMethod.stop()
@@ -44,7 +63,7 @@ function openXhr(method, url) {
44
63
  xhrContexts[requestUUID] = {
45
64
  state: 'open',
46
65
  method: method,
47
- url: normalizeUrl(String(url)),
66
+ url: normalizeUrl(String(url))
48
67
  }
49
68
  }
50
69
 
@@ -60,34 +79,40 @@ function sendXhr(observable) {
60
79
  startContext.isAborted = false
61
80
  startContext.xhr = this
62
81
  var hasBeenReported = false
63
- var onreadyStateChangeInstrumentMethod = instrumentMethodAndCallOriginal(this, 'onreadystatechange', {
64
- before: function() {
65
- if (this.readyState === XMLHttpRequest.DONE) {
66
- // Try to report the XHR as soon as possible, because the XHR may be mutated by the
67
- // application during a future event. For example, Angular is calling .abort() on
68
- // completed requests during a onreadystatechange event, so the status becomes '0'
69
- // before the request is collected.
70
- onEnd.call(this)
71
-
82
+ var stopInstrumentingOnReadyStateChange = instrumentMethodAndCallOriginal(
83
+ this,
84
+ 'onreadystatechange',
85
+ {
86
+ before: function () {
87
+ if (this.readyState === XMLHttpRequest.DONE) {
88
+ // Try to report the XHR as soon as possible, because the XHR may be mutated by the
89
+ // application during a future event. For example, Angular is calling .abort() on
90
+ // completed requests during a onreadystatechange event, so the status becomes '0'
91
+ // before the request is collected.
92
+ onEnd.call(this)
93
+ }
72
94
  }
73
- },
74
- })
95
+ }
96
+ ).stop
75
97
 
76
- var onEnd = function() {
77
- this.removeEventListener('loadend', onEnd)
78
- onreadyStateChangeInstrumentMethod.stop()
98
+ var onEnd = function () {
99
+ unsubscribeLoadEndListener()
100
+ stopInstrumentingOnReadyStateChange()
79
101
  if (hasBeenReported) {
80
102
  return
81
103
  }
82
104
  hasBeenReported = true
83
105
  var completeContext = context
84
106
  completeContext.state = 'complete'
85
- completeContext.duration = elapsed(startContext.startClocks.timeStamp, timeStampNow())
107
+ completeContext.duration = elapsed(
108
+ startContext.startClocks.timeStamp,
109
+ timeStampNow()
110
+ )
86
111
  completeContext.status = this.status
87
112
  observable.notify(shallowClone(completeContext))
88
113
  clearRequestId.call(this)
89
114
  }
90
- this.addEventListener('loadend', onEnd)
115
+ var unsubscribeLoadEndListener = addEventListener(this, 'loadend', onEnd).stop
91
116
  observable.notify(startContext)
92
117
  }
93
118
  function clearRequestId() {
@@ -4,10 +4,10 @@ import { display } from '../helper/display'
4
4
  import {
5
5
  assign,
6
6
  isPercentage,
7
- ONE_KIBI_BYTE,
8
7
  ONE_SECOND,
9
8
  isNullUndefinedDefaultValue
10
9
  } from '../helper/tools'
10
+ import { ONE_KIBI_BYTE } from '../helper/byteUtils'
11
11
  import { computeTransportConfiguration } from './transportConfiguration'
12
12
 
13
13
  export var DefaultPrivacyLevel = {
@@ -1,14 +1,18 @@
1
1
  import { computeStackTrace } from '../tracekit'
2
- import { createHandlingStack, formatErrorMessage, toStackTraceString } from '../helper/errorTools'
2
+ import {
3
+ createHandlingStack,
4
+ formatErrorMessage,
5
+ toStackTraceString
6
+ } from '../helper/errorTools'
3
7
  import { mergeObservables, Observable } from '../helper/observable'
4
- import { find, jsonStringify, map } from '../helper/tools'
8
+ import { find, map } from '../helper/tools'
9
+ import { jsonStringify } from '../helper/serialisation/jsonStringify'
5
10
  import { ConsoleApiName } from '../helper/display'
6
11
 
7
-
8
12
  var consoleObservablesByApi = {}
9
13
 
10
14
  export function initConsoleObservable(apis) {
11
- var consoleObservables = map(apis, function(api) {
15
+ var consoleObservables = map(apis, function (api) {
12
16
  if (!consoleObservablesByApi[api]) {
13
17
  consoleObservablesByApi[api] = createConsoleObservable(api)
14
18
  }
@@ -20,15 +24,15 @@ export function initConsoleObservable(apis) {
20
24
 
21
25
  /* eslint-disable no-console */
22
26
  function createConsoleObservable(api) {
23
- var observable = new Observable(function(){
27
+ var observable = new Observable(function () {
24
28
  var originalConsoleApi = console[api]
25
- console[api] = function() {
29
+ console[api] = function () {
26
30
  var params = [].slice.call(arguments)
27
31
  originalConsoleApi.apply(console, arguments)
28
32
  var handlingStack = createHandlingStack()
29
33
  observable.notify(buildConsoleLog(params, api, handlingStack))
30
34
  }
31
- return function() {
35
+ return function () {
32
36
  console[api] = originalConsoleApi
33
37
  }
34
38
  })
@@ -37,20 +41,26 @@ function createConsoleObservable(api) {
37
41
 
38
42
  function buildConsoleLog(params, api, handlingStack) {
39
43
  // Todo: remove console error prefix in the next major version
40
- var message = map(params, function(param) { return formatConsoleParameters(param) }).join(' ')
44
+ var message = map(params, function (param) {
45
+ return formatConsoleParameters(param)
46
+ }).join(' ')
41
47
  var stack
42
48
 
43
49
  if (api === ConsoleApiName.error) {
44
- var firstErrorParam = find(params, function(param) { return param instanceof Error })
45
- stack = firstErrorParam ? toStackTraceString(computeStackTrace(firstErrorParam)) : undefined
46
- message = 'console error: '+ message
50
+ var firstErrorParam = find(params, function (param) {
51
+ return param instanceof Error
52
+ })
53
+ stack = firstErrorParam
54
+ ? toStackTraceString(computeStackTrace(firstErrorParam))
55
+ : undefined
56
+ message = 'console error: ' + message
47
57
  }
48
58
 
49
59
  return {
50
60
  api: api,
51
61
  message: message,
52
62
  stack: stack,
53
- handlingStack: handlingStack,
63
+ handlingStack: handlingStack
54
64
  }
55
65
  }
56
66
 
package/src/dataMap.js CHANGED
@@ -47,6 +47,7 @@ export var dataMap = {
47
47
  },
48
48
  fields: {
49
49
  session_replay_stats: '_dd.replay_stats',
50
+ session_is_active: 'session.is_active',
50
51
  view_error_count: 'view.error.count',
51
52
  view_resource_count: 'view.resource.count',
52
53
  view_long_task_count: 'view.long_task.count',
@@ -0,0 +1,17 @@
1
+ export var ONE_KIBI_BYTE = 1024
2
+ export var ONE_MEBI_BYTE = 1024 * ONE_KIBI_BYTE
3
+ // eslint-disable-next-line no-control-regex
4
+ var HAS_MULTI_BYTES_CHARACTERS = /[^\u0000-\u007F]/
5
+
6
+ export function computeBytesCount(candidate) {
7
+ // Accurate bytes count computations can degrade performances when there is a lot of events to process
8
+ if (!HAS_MULTI_BYTES_CHARACTERS.test(candidate)) {
9
+ return candidate.length
10
+ }
11
+
12
+ if (window.TextEncoder !== undefined) {
13
+ return new TextEncoder().encode(candidate).length
14
+ }
15
+
16
+ return new Blob([candidate]).size
17
+ }
@@ -1,5 +1,5 @@
1
1
  import { relativeNow, ONE_MINUTE, filter, map } from './tools'
2
-
2
+ import { setInterval, clearInterval } from './timer'
3
3
  var END_OF_TIMES = Infinity
4
4
 
5
5
  export var CLEAR_OLD_CONTEXTS_INTERVAL = ONE_MINUTE
@@ -1,16 +1,13 @@
1
1
  import { ErrorSource } from './errorTools'
2
2
  import { clocksNow, ONE_MINUTE } from './tools'
3
- export function createEventRateLimiter(
4
- eventType,
5
- limit,
6
- onLimitReached
7
- ) {
3
+ import { setTimeout } from './timer'
4
+ export function createEventRateLimiter(eventType, limit, onLimitReached) {
8
5
  var eventCount = 0
9
6
  var allowNextEvent = false
10
7
  return {
11
- isLimitReached: function() {
8
+ isLimitReached: function () {
12
9
  if (eventCount === 0) {
13
- setTimeout(function(){
10
+ setTimeout(function () {
14
11
  eventCount = 0
15
12
  }, ONE_MINUTE)
16
13
  }
@@ -23,9 +20,10 @@ export function createEventRateLimiter(
23
20
  allowNextEvent = true
24
21
  try {
25
22
  onLimitReached({
26
- message: 'Reached max number of ' + eventType +'s by minute: ' + limit,
23
+ message:
24
+ 'Reached max number of ' + eventType + 's by minute: ' + limit,
27
25
  source: ErrorSource.AGENT,
28
- startClocks: clocksNow(),
26
+ startClocks: clocksNow()
29
27
  })
30
28
  } finally {
31
29
  allowNextEvent = false
@@ -1,4 +1,5 @@
1
- import { each, noop, jsonStringify } from './tools'
1
+ import { each, noop } from './tools'
2
+ import { jsonStringify } from '../helper/serialisation/jsonStringify'
2
3
  import { computeStackTrace } from '../tracekit'
3
4
 
4
5
  export var ErrorSource = {
@@ -1,5 +1,5 @@
1
1
  import { noop } from './tools'
2
- import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'
2
+ import { setTimeout } from './timer'
3
3
  export function instrumentMethod(object, method, instrumentationFactory) {
4
4
  var original = object[method]
5
5
 
@@ -54,7 +54,6 @@ export function instrumentSetter(object, property, after) {
54
54
  }
55
55
  // Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
56
56
  // component, see issue RUMF-1443
57
- var setTimeout = getZoneJsOriginalValue(window, 'setTimeout')
58
57
  var instrumentation = function (thisObject, value) {
59
58
  // put hooked setter into event loop to avoid of set latency
60
59
  setTimeout(function () {
@@ -0,0 +1,79 @@
1
+ import { computeBytesCount } from '../byteUtils'
2
+ import { deepClone, throttle } from '../tools'
3
+ import { jsonStringify } from './jsonStringify'
4
+ import { warnIfCustomerDataLimitReached } from './heavyCustomerDataWarning'
5
+
6
+ export var BYTES_COMPUTATION_THROTTLING_DELAY = 200
7
+
8
+ export function createContextManager(customerDataType, computeBytesCountImpl) {
9
+ if (typeof computeBytesCountImpl === 'undefined') {
10
+ computeBytesCountImpl = computeBytesCount
11
+ }
12
+ var context = {}
13
+ var bytesCountCache
14
+ var alreadyWarned = false
15
+
16
+ // Throttle the bytes computation to minimize the impact on performance.
17
+ // Especially useful if the user call context APIs synchronously multiple times in a row
18
+ var computeBytesCountThrottled = throttle(function (context) {
19
+ bytesCountCache = computeBytesCountImpl(jsonStringify(context))
20
+ if (!alreadyWarned) {
21
+ alreadyWarned = warnIfCustomerDataLimitReached(
22
+ bytesCountCache,
23
+ customerDataType
24
+ )
25
+ }
26
+ }, BYTES_COMPUTATION_THROTTLING_DELAY).throttled
27
+
28
+ return {
29
+ getBytesCount: function () {
30
+ return bytesCountCache
31
+ },
32
+ /** @deprecated use getContext instead */
33
+ get: function () {
34
+ return context
35
+ },
36
+
37
+ /** @deprecated use setContextProperty instead */
38
+ add: function (key, value) {
39
+ context[key] = value
40
+ computeBytesCountThrottled(context)
41
+ },
42
+
43
+ /** @deprecated renamed to removeContextProperty */
44
+ remove: function (key) {
45
+ delete context[key]
46
+ computeBytesCountThrottled(context)
47
+ },
48
+
49
+ /** @deprecated use setContext instead */
50
+ set: function (newContext) {
51
+ context = newContext
52
+ computeBytesCountThrottled(context)
53
+ },
54
+
55
+ getContext: function () {
56
+ return deepClone(context)
57
+ },
58
+
59
+ setContext: function (newContext) {
60
+ context = deepClone(newContext)
61
+ computeBytesCountThrottled(context)
62
+ },
63
+
64
+ setContextProperty: function (key, property) {
65
+ context[key] = deepClone(property)
66
+ computeBytesCountThrottled(context)
67
+ },
68
+
69
+ removeContextProperty: function (key) {
70
+ delete context[key]
71
+ computeBytesCountThrottled(context)
72
+ },
73
+
74
+ clearContext: function () {
75
+ context = {}
76
+ bytesCountCache = 0
77
+ }
78
+ }
79
+ }
@@ -0,0 +1,28 @@
1
+ import { ONE_KIBI_BYTE } from '../byteUtils'
2
+ import { display } from '../display'
3
+
4
+ // RUM and logs batch bytes limit is 16KB
5
+ // ensure that we leave room for other event attributes and maintain a decent amount of event per batch
6
+ // (3KB (customer data) + 1KB (other attributes)) * 4 (events per batch) = 16KB
7
+ export var CUSTOMER_DATA_BYTES_LIMIT = 3 * ONE_KIBI_BYTE
8
+
9
+ export var CustomerDataType = {
10
+ FeatureFlag: 'feature flag evaluation',
11
+ User: 'user',
12
+ GlobalContext: 'global context',
13
+ LoggerContext: 'logger context'
14
+ }
15
+
16
+ export function warnIfCustomerDataLimitReached(bytesCount, customerDataType) {
17
+ if (bytesCount > CUSTOMER_DATA_BYTES_LIMIT) {
18
+ display.warn(
19
+ 'The ' +
20
+ customerDataType +
21
+ 'data is over ' +
22
+ CUSTOMER_DATA_BYTES_LIMIT / ONE_KIBI_BYTE +
23
+ " KiB. On low connectivity, the SDK has the potential to exhaust the user's upload bandwidth."
24
+ )
25
+ return true
26
+ }
27
+ return false
28
+ }
@@ -0,0 +1,47 @@
1
+ import { noop } from '../tools'
2
+
3
+ /**
4
+ * Custom implementation of JSON.stringify that ignores some toJSON methods. We need to do that
5
+ * because some sites badly override toJSON on certain objects. Removing all toJSON methods from
6
+ * nested values would be too costly, so we just detach them from the root value, and native classes
7
+ * used to build JSON values (Array and Object).
8
+ *
9
+ * Note: this still assumes that JSON.stringify is correct.
10
+ */
11
+ export function jsonStringify(value, replacer, space) {
12
+ if (typeof value !== 'object' || value === null) {
13
+ return JSON.stringify(value)
14
+ }
15
+
16
+ // Note: The order matter here. We need to detach toJSON methods on parent classes before their
17
+ // subclasses.
18
+ var restoreObjectPrototypeToJson = detachToJsonMethod(Object.prototype)
19
+ var restoreArrayPrototypeToJson = detachToJsonMethod(Array.prototype)
20
+ var restoreValuePrototypeToJson = detachToJsonMethod(
21
+ Object.getPrototypeOf(value)
22
+ )
23
+ var restoreValueToJson = detachToJsonMethod(value)
24
+
25
+ try {
26
+ return JSON.stringify(value, replacer, space)
27
+ } catch {
28
+ return '<error: unable to serialize object>'
29
+ } finally {
30
+ restoreObjectPrototypeToJson()
31
+ restoreArrayPrototypeToJson()
32
+ restoreValuePrototypeToJson()
33
+ restoreValueToJson()
34
+ }
35
+ }
36
+
37
+ export function detachToJsonMethod(value) {
38
+ const object = value
39
+ const objectToJson = object.toJSON
40
+ if (objectToJson) {
41
+ delete object.toJSON
42
+ return () => {
43
+ object.toJSON = objectToJson
44
+ }
45
+ }
46
+ return noop
47
+ }
@@ -0,0 +1,41 @@
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
+ var reg = /[\s=,"]/g
10
+ return String(str).replace(reg, function (word) {
11
+ return '\\' + word
12
+ })
13
+ }
14
+
15
+ export function escapeJsonValue(value) {
16
+ if (isString(value)) {
17
+ return value
18
+ } else {
19
+ return jsonStringify(value)
20
+ }
21
+ }
22
+
23
+ export function escapeFieldValueStr(str) {
24
+ return (
25
+ '"' +
26
+ str
27
+ .replace(/\\/g, '\\\\')
28
+ .replace(/[\\]*"/g, '"')
29
+ .replace(/"/g, '\\"') +
30
+ '"'
31
+ )
32
+ }
33
+ export function escapeRowField(value) {
34
+ if (typeof value === 'object' && value) {
35
+ return escapeFieldValueStr(jsonStringify(value))
36
+ } else if (isString(value)) {
37
+ return escapeFieldValueStr(value)
38
+ } else {
39
+ return value
40
+ }
41
+ }
@@ -0,0 +1,21 @@
1
+ import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'
2
+ import { getGlobalObject } from '../init'
3
+
4
+ export function setTimeout(callback, delay) {
5
+ return getZoneJsOriginalValue(getGlobalObject(), 'setTimeout')(
6
+ callback,
7
+ delay
8
+ )
9
+ }
10
+
11
+ export function clearTimeout(timeoutId) {
12
+ getZoneJsOriginalValue(getGlobalObject(), 'clearTimeout')(timeoutId)
13
+ }
14
+
15
+ export function setInterval(callback, delay) {
16
+ return getZoneJsOriginalValue(window, 'setInterval')(callback, delay)
17
+ }
18
+
19
+ export function clearInterval(timeoutId) {
20
+ getZoneJsOriginalValue(window, 'clearInterval')(timeoutId)
21
+ }