@cloudcare/browser-core 1.2.11 → 2.0.0

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 (61) hide show
  1. package/cjs/browser/fetchObservable.js +3 -4
  2. package/cjs/browser/htmlDomUtils.js +45 -0
  3. package/cjs/browser/pageExitObservable.js +72 -0
  4. package/cjs/configuration/configuration.js +8 -0
  5. package/cjs/configuration/transportConfiguration.js +7 -0
  6. package/cjs/dataMap.js +12 -4
  7. package/cjs/helper/deviceInfo.js +44 -2
  8. package/cjs/helper/enums.js +3 -0
  9. package/cjs/helper/getZoneJsOriginalValue.js +34 -0
  10. package/cjs/helper/instrumentMethod.js +7 -1
  11. package/cjs/helper/lifeCycle.js +2 -6
  12. package/cjs/helper/readBytesFromStream.js +74 -0
  13. package/cjs/helper/tools.js +123 -46
  14. package/cjs/index.js +52 -0
  15. package/cjs/session/sessionStore.js +1 -1
  16. package/cjs/transport/batch.js +7 -44
  17. package/cjs/transport/httpRequest.js +4 -2
  18. package/cjs/transport/sendWithRetryStrategy.js +8 -8
  19. package/cjs/transport/startBatchWithReplica.js +2 -2
  20. package/esm/browser/fetchObservable.js +3 -4
  21. package/esm/browser/htmlDomUtils.js +26 -0
  22. package/esm/browser/pageExitObservable.js +57 -0
  23. package/esm/configuration/configuration.js +5 -0
  24. package/esm/configuration/transportConfiguration.js +7 -0
  25. package/esm/dataMap.js +9 -2
  26. package/esm/helper/contextHistory.js +1 -1
  27. package/esm/helper/deviceInfo.js +44 -2
  28. package/esm/helper/enums.js +3 -0
  29. package/esm/helper/getZoneJsOriginalValue.js +27 -0
  30. package/esm/helper/instrumentMethod.js +6 -1
  31. package/esm/helper/lifeCycle.js +2 -6
  32. package/esm/helper/readBytesFromStream.js +67 -0
  33. package/esm/helper/tools.js +99 -44
  34. package/esm/index.js +4 -0
  35. package/esm/session/sessionStore.js +1 -1
  36. package/esm/transport/batch.js +8 -45
  37. package/esm/transport/httpRequest.js +4 -2
  38. package/esm/transport/sendWithRetryStrategy.js +8 -8
  39. package/esm/transport/startBatchWithReplica.js +2 -2
  40. package/package.json +2 -2
  41. package/src/browser/fetchObservable.js +21 -17
  42. package/src/browser/htmlDomUtils.js +35 -0
  43. package/src/browser/pageExitObservable.js +70 -0
  44. package/src/configuration/configuration.js +6 -0
  45. package/src/configuration/transportConfiguration.js +30 -6
  46. package/src/dataMap.js +9 -2
  47. package/src/helper/contextHistory.js +1 -1
  48. package/src/helper/deviceInfo.js +39 -3
  49. package/src/helper/enums.js +40 -37
  50. package/src/helper/getZoneJsOriginalValue.js +27 -0
  51. package/src/helper/instrumentMethod.js +40 -50
  52. package/src/helper/lifeCycle.js +2 -7
  53. package/src/helper/readBytesFromStream.js +69 -0
  54. package/src/helper/tools.js +112 -43
  55. package/src/index.js +4 -1
  56. package/src/session/sessionStore.js +27 -24
  57. package/src/synthetics/syntheticsWorkerValues.js +11 -7
  58. package/src/transport/batch.js +70 -81
  59. package/src/transport/httpRequest.js +25 -25
  60. package/src/transport/sendWithRetryStrategy.js +14 -9
  61. package/src/transport/startBatchWithReplica.js +11 -5
@@ -0,0 +1,69 @@
1
+ import { noop, each } from './tools'
2
+
3
+ /**
4
+ * Read bytes from a ReadableStream until at least `limit` bytes have been read (or until the end of
5
+ * the stream). The callback is invoked with the at most `limit` bytes, and indicates that the limit
6
+ * has been exceeded if more bytes were available.
7
+ */
8
+ export function readBytesFromStream(stream, callback, options) {
9
+ var reader = stream.getReader()
10
+ var chunks = []
11
+ var readBytesCount = 0
12
+
13
+ readMore()
14
+
15
+ function readMore() {
16
+ reader.read().then(
17
+ function (result) {
18
+ if (result.done) {
19
+ onDone()
20
+ return
21
+ }
22
+
23
+ if (options.collectStreamBody) {
24
+ chunks.push(result.value)
25
+ }
26
+ readBytesCount += result.value.length
27
+
28
+ if (readBytesCount > options.bytesLimit) {
29
+ onDone()
30
+ } else {
31
+ readMore()
32
+ }
33
+ },
34
+ function (error) {
35
+ callback(error)
36
+ }
37
+ )
38
+ }
39
+
40
+ function onDone() {
41
+ reader.cancel().catch(
42
+ // we don't care if cancel fails, but we still need to catch the error to avoid reporting it
43
+ // as an unhandled rejection
44
+ noop
45
+ )
46
+
47
+ var bytes
48
+ var limitExceeded
49
+ if (options.collectStreamBody) {
50
+ var completeBuffer
51
+ if (chunks.length === 1) {
52
+ // optimization: if the response is small enough to fit in a single buffer (provided by the browser), just
53
+ // use it directly.
54
+ completeBuffer = chunks[0]
55
+ } else {
56
+ // else, we need to copy buffers into a larger buffer to concatenate them.
57
+ completeBuffer = new Uint8Array(readBytesCount)
58
+ var offset = 0
59
+ each(chunks, function (chunk) {
60
+ completeBuffer.set(chunk, offset)
61
+ offset += chunk.length
62
+ })
63
+ }
64
+ bytes = completeBuffer.slice(0, options.bytesLimit)
65
+ limitExceeded = completeBuffer.length > options.bytesLimit
66
+ }
67
+ callback(undefined, bytes, limitExceeded)
68
+ }
69
+ }
@@ -1,3 +1,6 @@
1
+ import { DOM_EVENT } from './enums'
2
+ import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'
3
+
1
4
  var ArrayProto = Array.prototype
2
5
  var FuncProto = Function.prototype
3
6
  var ObjProto = Object.prototype
@@ -260,6 +263,7 @@ export var isObject = function (obj) {
260
263
  if (obj === null) return false
261
264
  return toString.call(obj) === '[object Object]'
262
265
  }
266
+
263
267
  export var isEmptyObject = function (obj) {
264
268
  if (isObject(obj)) {
265
269
  for (var key in obj) {
@@ -364,45 +368,42 @@ export var now =
364
368
  return new Date().getTime()
365
369
  }
366
370
 
367
- export var throttle = function (func, wait, options) {
368
- var timeout, context, args, result
369
- var previous = 0
370
- if (!options) options = {}
371
-
372
- var later = function () {
373
- previous = options.leading === false ? 0 : new Date().getTime()
374
- timeout = null
375
- result = func.apply(context, args)
376
- if (!timeout) context = args = null
377
- }
378
-
379
- var throttled = function () {
380
- args = arguments
381
- var now = new Date().getTime()
382
- if (!previous && options.leading === false) previous = now
383
- //下次触发 func 剩余的时间
384
- var remaining = wait - (now - previous)
385
- context = this
386
- // 如果没有剩余的时间了或者你改了系统时间
387
- if (remaining <= 0 || remaining > wait) {
388
- if (timeout) {
389
- clearTimeout(timeout)
390
- timeout = null
371
+ export var throttle = function (fn, wait, options) {
372
+ var needLeadingExecution =
373
+ options && options.leading !== undefined ? options.leading : true
374
+ var needTrailingExecution =
375
+ options && options.trailing !== undefined ? options.trailing : true
376
+ let inWaitPeriod = false
377
+ let pendingExecutionWithParameters
378
+ let pendingTimeoutId
379
+ var context = this
380
+ return {
381
+ throttled: function () {
382
+ if (inWaitPeriod) {
383
+ pendingExecutionWithParameters = arguments
384
+ return
391
385
  }
392
- previous = now
393
- result = func.apply(context, args)
394
- if (!timeout) context = args = null
395
- } else if (!timeout && options.trailing !== false) {
396
- timeout = setTimeout(later, remaining)
386
+
387
+ if (needLeadingExecution) {
388
+ fn.apply(context, arguments)
389
+ } else {
390
+ pendingExecutionWithParameters = arguments
391
+ }
392
+ inWaitPeriod = true
393
+ pendingTimeoutId = setTimeout(function () {
394
+ if (needTrailingExecution && pendingExecutionWithParameters) {
395
+ fn.apply(context, pendingExecutionWithParameters)
396
+ }
397
+ inWaitPeriod = false
398
+ pendingExecutionWithParameters = undefined
399
+ }, wait)
400
+ },
401
+ cancel: function () {
402
+ clearTimeout(pendingTimeoutId)
403
+ inWaitPeriod = false
404
+ pendingExecutionWithParameters = undefined
397
405
  }
398
- return result
399
- }
400
- throttled.cancel = function () {
401
- clearTimeout(timeout)
402
- previous = 0
403
- timeout = null
404
406
  }
405
- return throttled
406
407
  }
407
408
  export var hashCode = function (str) {
408
409
  if (typeof str !== 'string') {
@@ -1632,7 +1633,9 @@ export function currentDrift() {
1632
1633
  // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
1633
1634
  return Math.round(dateNow() - (getNavigationStart() + performance.now()))
1634
1635
  }
1635
-
1636
+ export function addDuration(a, b) {
1637
+ return a + b
1638
+ }
1636
1639
  function getCorrectedTimeStamp(relativeTime) {
1637
1640
  var correctedOrigin = dateNow() - performance.now()
1638
1641
  // apply correction only for positive drift
@@ -1676,8 +1679,8 @@ export function safeTruncate(candidate, length) {
1676
1679
  return candidate.slice(0, length)
1677
1680
  }
1678
1681
 
1679
- export function addEventListener(emitter, event, listener, options) {
1680
- return addEventListeners(emitter, [event], listener, options)
1682
+ export function addEventListener(eventTarget, event, listener, options) {
1683
+ return addEventListeners(eventTarget, [event], listener, options)
1681
1684
  }
1682
1685
 
1683
1686
  /**
@@ -1695,8 +1698,9 @@ export function addEventListener(emitter, event, listener, options) {
1695
1698
  * * with `once: true`, the listener will be called at most once, even if different events are
1696
1699
  * listened
1697
1700
  */
1698
- export function addEventListeners(emitter, events, listener, options) {
1699
- var wrapedListener =
1701
+
1702
+ export function addEventListeners(eventTarget, events, listener, options) {
1703
+ var wrappedListener =
1700
1704
  options && options.once
1701
1705
  ? function (event) {
1702
1706
  stop()
@@ -1708,12 +1712,15 @@ export function addEventListeners(emitter, events, listener, options) {
1708
1712
  options && options.passive
1709
1713
  ? { capture: options.capture, passive: options.passive }
1710
1714
  : options && options.capture
1715
+ var add = getZoneJsOriginalValue(eventTarget, 'addEventListener')
1716
+
1711
1717
  each(events, function (event) {
1712
- emitter.addEventListener(event, wrapedListener, options)
1718
+ add.call(eventTarget, event, wrappedListener, options)
1713
1719
  })
1714
1720
  var stop = function () {
1721
+ var remove = getZoneJsOriginalValue(eventTarget, 'removeEventListener')
1715
1722
  each(events, function (event) {
1716
- emitter.removeEventListener(event, wrapedListener, options)
1723
+ remove.call(eventTarget, event, wrappedListener, options)
1717
1724
  })
1718
1725
  }
1719
1726
  return {
@@ -1909,3 +1916,65 @@ export function isNullUndefinedDefaultValue(data, defaultValue) {
1909
1916
  return defaultValue
1910
1917
  }
1911
1918
  }
1919
+
1920
+ export function runOnReadyState(expectedReadyState, callback) {
1921
+ if (
1922
+ document.readyState === expectedReadyState ||
1923
+ document.readyState === 'complete'
1924
+ ) {
1925
+ callback()
1926
+ } else {
1927
+ var eventName =
1928
+ expectedReadyState === 'complete'
1929
+ ? DOM_EVENT.LOAD
1930
+ : DOM_EVENT.DOM_CONTENT_LOADED
1931
+ addEventListener(window, eventName, callback, { once: true })
1932
+ }
1933
+ }
1934
+
1935
+ export function requestIdleCallback(callback, opts) {
1936
+ // Use 'requestIdleCallback' when available: it will throttle the mutation processing if the
1937
+ // browser is busy rendering frames (ex: when frames are below 60fps). When not available, the
1938
+ // fallback on 'requestAnimationFrame' will still ensure the mutations are processed after any
1939
+ // browser rendering process (Layout, Recalculate Style, etc.), so we can serialize DOM nodes
1940
+ // efficiently.
1941
+ if (window.requestIdleCallback) {
1942
+ var id = window.requestIdleCallback(callback, opts)
1943
+ return function () {
1944
+ return window.cancelIdleCallback(id)
1945
+ }
1946
+ }
1947
+ var id = window.requestAnimationFrame(callback)
1948
+ return function () {
1949
+ return window.cancelAnimationFrame(id)
1950
+ }
1951
+ }
1952
+ export function objectHasValue(object, value) {
1953
+ return some(keys(object), function (key) {
1954
+ return object[key] === value
1955
+ })
1956
+ }
1957
+ export function startsWith(candidate, search) {
1958
+ return candidate.slice(0, search.length) === search
1959
+ }
1960
+
1961
+ export function endsWith(candidate, search) {
1962
+ return candidate.slice(-search.length) === search
1963
+ }
1964
+
1965
+ export function tryToClone(response) {
1966
+ try {
1967
+ return response.clone()
1968
+ } catch (e) {
1969
+ // clone can throw if the response has already been used by another instrumentation or is disturbed
1970
+ return
1971
+ }
1972
+ }
1973
+ export function isHashAnAnchor(hash) {
1974
+ var correspondingId = hash.substr(1)
1975
+ return !!document.getElementById(correspondingId)
1976
+ }
1977
+ export function getPathFromHash(hash) {
1978
+ var index = hash.indexOf('?')
1979
+ return index < 0 ? hash : hash.slice(0, index)
1980
+ }
package/src/index.js CHANGED
@@ -16,12 +16,16 @@ export * from './helper/observable'
16
16
  export * from './helper/tools'
17
17
  export * from './helper/urlPolyfill'
18
18
  export * from './helper/mobileUtil'
19
+ export * from './helper/getZoneJsOriginalValue'
20
+ export * from './helper/readBytesFromStream'
19
21
  export * from './tracekit'
20
22
  export * from './configuration/configuration'
21
23
  export * from './configuration/transportConfiguration'
22
24
  export * from './browser/cookie'
23
25
  export * from './browser/fetchObservable'
24
26
  export * from './browser/xhrObservable'
27
+ export * from './browser/pageExitObservable'
28
+ export * from './browser/htmlDomUtils'
25
29
  export * from './dataMap'
26
30
  export * from './init'
27
31
  export * from './session/sessionManagement'
@@ -30,4 +34,3 @@ export * from './session/sessionCookieStore'
30
34
  export * from './session/sessionStore'
31
35
  export * from './transport'
32
36
  export * from './synthetics/syntheticsWorkerValues'
33
-
@@ -10,11 +10,7 @@ import { retrieveSession, withCookieLockAccess } from './sessionCookieStore'
10
10
  * - not tracked, the session does not have an id but it is updated along the user navigation
11
11
  * - inactive, no session in store or session expired, waiting for a renew session
12
12
  */
13
- export function startSessionStore(
14
- options,
15
- productKey,
16
- computeSessionState
17
- ) {
13
+ export function startSessionStore(options, productKey, computeSessionState) {
18
14
  var renewObservable = new Observable()
19
15
  var expireObservable = new Observable()
20
16
 
@@ -25,26 +21,28 @@ export function startSessionStore(
25
21
  var isTracked
26
22
  withCookieLockAccess({
27
23
  options: options,
28
- process: function(cookieSession){
24
+ process: function (cookieSession) {
29
25
  var synchronizedSession = synchronizeSession(cookieSession)
30
26
  isTracked = expandOrRenewCookie(synchronizedSession)
31
27
  return synchronizedSession
32
28
  },
33
- after: function(cookieSession) {
29
+ after: function (cookieSession) {
34
30
  if (isTracked && !hasSessionInCache()) {
35
31
  renewSession(cookieSession)
36
32
  }
37
33
  sessionCache = cookieSession
38
- },
34
+ }
39
35
  })
40
36
  }
41
37
 
42
38
  function expandSession() {
43
39
  withCookieLockAccess({
44
40
  options: options,
45
- process: function(cookieSession) {
46
- return (hasSessionInCache() ? synchronizeSession(cookieSession) : undefined)
47
- },
41
+ process: function (cookieSession) {
42
+ return hasSessionInCache()
43
+ ? synchronizeSession(cookieSession)
44
+ : undefined
45
+ }
48
46
  })
49
47
  }
50
48
 
@@ -55,11 +53,11 @@ export function startSessionStore(
55
53
  */
56
54
  function watchSession() {
57
55
  withCookieLockAccess({
58
- options:options,
59
- process: function(cookieSession) {
60
- return (!isActiveSession(cookieSession) ? {} : undefined)
56
+ options: options,
57
+ process: function (cookieSession) {
58
+ return !isActiveSession(cookieSession) ? {} : undefined
61
59
  },
62
- after: synchronizeSession,
60
+ after: synchronizeSession
63
61
  })
64
62
  }
65
63
 
@@ -78,7 +76,7 @@ export function startSessionStore(
78
76
  }
79
77
 
80
78
  function expandOrRenewCookie(cookieSession) {
81
- var sessionState= computeSessionState(cookieSession[productKey])
79
+ var sessionState = computeSessionState(cookieSession[productKey])
82
80
  var trackingType = sessionState.trackingType
83
81
  var isTracked = sessionState.isTracked
84
82
  cookieSession[productKey] = trackingType
@@ -94,7 +92,10 @@ export function startSessionStore(
94
92
  }
95
93
 
96
94
  function isSessionInCacheOutdated(cookieSession) {
97
- return sessionCache.id !== cookieSession.id || sessionCache[productKey] !== cookieSession[productKey]
95
+ return (
96
+ sessionCache.id !== cookieSession.id ||
97
+ sessionCache[productKey] !== cookieSession[productKey]
98
+ )
98
99
  }
99
100
 
100
101
  function expireSession() {
@@ -119,21 +120,23 @@ export function startSessionStore(
119
120
  // created and expire can be undefined for versions which was not storing them
120
121
  // these checks could be removed when older versions will not be available/live anymore
121
122
  return (
122
- (session.created === undefined || dateNow() - Number(session.created) < SESSION_TIME_OUT_DELAY) &&
123
+ (session.created === undefined ||
124
+ dateNow() - Number(session.created) < SESSION_TIME_OUT_DELAY) &&
123
125
  (session.expire === undefined || dateNow() < Number(session.expire))
124
126
  )
125
127
  }
126
128
 
127
129
  return {
128
- expandOrRenewSession: throttle(expandOrRenewSession, COOKIE_ACCESS_DELAY),
130
+ expandOrRenewSession: throttle(expandOrRenewSession, COOKIE_ACCESS_DELAY)
131
+ .throttled,
129
132
  expandSession: expandSession,
130
- getSession: function() {
133
+ getSession: function () {
131
134
  return sessionCache
132
135
  },
133
- renewObservable:renewObservable,
134
- expireObservable:expireObservable,
135
- stop: function() {
136
+ renewObservable: renewObservable,
137
+ expireObservable: expireObservable,
138
+ stop: function () {
136
139
  clearInterval(watchSessionTimeoutId)
137
- },
140
+ }
138
141
  }
139
142
  }
@@ -1,22 +1,26 @@
1
1
  import { getCookie } from '../browser/cookie'
2
2
 
3
- export const SYNTHETICS_TEST_ID_COOKIE_NAME = 'guance-synthetics-public-id'
4
- export const SYNTHETICS_RESULT_ID_COOKIE_NAME = 'guance-synthetics-result-id'
5
- export const SYNTHETICS_INJECTS_RUM_COOKIE_NAME = 'guance-synthetics-injects-rum'
6
-
3
+ export var SYNTHETICS_TEST_ID_COOKIE_NAME = 'guance-synthetics-public-id'
4
+ export var SYNTHETICS_RESULT_ID_COOKIE_NAME = 'guance-synthetics-result-id'
5
+ export var SYNTHETICS_INJECTS_RUM_COOKIE_NAME = 'guance-synthetics-injects-rum'
7
6
 
8
7
  export function willSyntheticsInjectRum() {
9
8
  return Boolean(
10
- window._GUANCE_SYNTHETICS_INJECTS_RUM || getCookie(SYNTHETICS_INJECTS_RUM_COOKIE_NAME)
9
+ window._GUANCE_SYNTHETICS_INJECTS_RUM ||
10
+ getCookie(SYNTHETICS_INJECTS_RUM_COOKIE_NAME)
11
11
  )
12
12
  }
13
13
 
14
14
  export function getSyntheticsTestId() {
15
- var value = window._GUANCE_SYNTHETICS_PUBLIC_ID || getCookie(SYNTHETICS_TEST_ID_COOKIE_NAME)
15
+ var value =
16
+ window._GUANCE_SYNTHETICS_PUBLIC_ID ||
17
+ getCookie(SYNTHETICS_TEST_ID_COOKIE_NAME)
16
18
  return typeof value === 'string' ? value : undefined
17
19
  }
18
20
 
19
21
  export function getSyntheticsResultId() {
20
- const value = window._GUANCE_SYNTHETICS_RESULT_ID || getCookie(SYNTHETICS_RESULT_ID_COOKIE_NAME)
22
+ var value =
23
+ window._GUANCE_SYNTHETICS_RESULT_ID ||
24
+ getCookie(SYNTHETICS_RESULT_ID_COOKIE_NAME)
21
25
  return typeof value === 'string' ? value : undefined
22
26
  }