@openreplay/tracker 4.1.4 → 4.1.7-beta.1

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.
@@ -77,6 +77,8 @@ export default class App {
77
77
  private _debug;
78
78
  send(message: Message, urgent?: boolean): void;
79
79
  private commit;
80
+ private delay;
81
+ timestamp(): number;
80
82
  safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
81
83
  attachCommitCallback(cb: CommitCallback): void;
82
84
  attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
package/cjs/app/index.js CHANGED
@@ -27,12 +27,14 @@ class App {
27
27
  // if (options.onStart !== undefined) {
28
28
  // deprecationWarn("'onStart' option", "tracker.start().then(/* handle session info */)")
29
29
  // } ?? maybe onStart is good
30
+ var _a, _b;
30
31
  this.messages = [];
31
32
  this.startCallbacks = [];
32
33
  this.stopCallbacks = [];
33
34
  this.commitCallbacks = [];
34
35
  this.activityState = ActivityState.NotActive;
35
- this.version = '4.1.4'; // TODO: version compatability check inside each plugin.
36
+ this.version = '4.1.6'; // TODO: version compatability check inside each plugin.
37
+ this.delay = 0;
36
38
  this.projectKey = projectKey;
37
39
  this.options = Object.assign({
38
40
  revID: '',
@@ -46,10 +48,12 @@ class App {
46
48
  verbose: false,
47
49
  __is_snippet: false,
48
50
  __debug_report_edp: null,
49
- localStorage: window === null || window === void 0 ? void 0 : window.localStorage,
50
- sessionStorage: window === null || window === void 0 ? void 0 : window.sessionStorage,
51
+ localStorage: null,
52
+ sessionStorage: null,
51
53
  }, options);
52
54
  this.revID = this.options.revID;
55
+ this.localStorage = (_a = this.options.localStorage) !== null && _a !== void 0 ? _a : window.localStorage;
56
+ this.sessionStorage = (_b = this.options.sessionStorage) !== null && _b !== void 0 ? _b : window.sessionStorage;
53
57
  this.sanitizer = new sanitizer_js_1.default(this, options);
54
58
  this.nodes = new nodes_js_1.default(this.options.node_id);
55
59
  this.observer = new top_observer_js_1.default(this, options);
@@ -57,8 +61,6 @@ class App {
57
61
  this.ticker.attach(() => this.commit());
58
62
  this.debug = new logger_js_1.default(this.options.__debug__);
59
63
  this.notify = new logger_js_1.default(this.options.verbose ? logger_js_1.LogLevel.Warnings : logger_js_1.LogLevel.Silent);
60
- this.localStorage = this.options.localStorage || window.localStorage;
61
- this.sessionStorage = this.options.sessionStorage || window.sessionStorage;
62
64
  this.session = new session_js_1.default(this, this.options);
63
65
  this.session.attachUpdateCallback(({ userID, metadata }) => {
64
66
  if (userID != null) {
@@ -74,18 +76,18 @@ class App {
74
76
  this.session.applySessionHash(sessionToken);
75
77
  }
76
78
  try {
77
- this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==f&&(clearInterval(f),f=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){self.postMessage("restart"),a()}n.NotActive;let c,f=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return u(),void a();if(Array.isArray(i)){if(!h)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const t=h;i.forEach(i=>{55===i[0]&&(i[1]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},()=>{self.postMessage("failed"),a()},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===f&&(f=setInterval(u,1e4)),n.Active;if("auth"===i.type){if(!r)throw new Error("WebWorker: sender not initialised. Received auth.");if(!h)throw new Error("WebWorker: writer not initialised. Received auth.");return r.authorise(i.token),void(i.beaconSizeLimit&&h.setBeaconSizeLimit(i.beaconSizeLimit))}}}else u()};'], { type: 'text/javascript' })));
79
+ this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure(`Failed to send batch after ${this.attemptsCount} attempts.`):(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2]);case 78:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==g&&(clearInterval(g),g=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){postMessage("restart"),a()}n.NotActive;let c,g=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return u(),void a();if(Array.isArray(i)){if(!h)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const t=h;i.forEach(i=>{55===i[0]&&(i[1]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},t=>{!function(t){postMessage({type:"failure",reason:t}),a()}(t)},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===g&&(g=setInterval(u,1e4)),n.Active;if("auth"===i.type){if(!r)throw new Error("WebWorker: sender not initialised. Received auth.");if(!h)throw new Error("WebWorker: writer not initialised. Received auth.");return r.authorise(i.token),void(i.beaconSizeLimit&&h.setBeaconSizeLimit(i.beaconSizeLimit))}}}else u()};'], { type: 'text/javascript' })));
78
80
  this.worker.onerror = (e) => {
79
81
  this._debug('webworker_error', e);
80
82
  };
81
83
  this.worker.onmessage = ({ data }) => {
82
- if (data === 'failed') {
84
+ if (data === 'restart') {
83
85
  this.stop(false);
84
- this._debug('worker_failed', {}); // add context (from worker)
86
+ this.start({ forceNew: true }); // TODO: keep userID & metadata (draw scenarios)
85
87
  }
86
- else if (data === 'restart') {
88
+ else if (data.type === 'failure') {
87
89
  this.stop(false);
88
- this.start({ forceNew: true }); // TODO: keep userID & metadata (draw scenarios)
90
+ this._debug('worker_failed', data.reason);
89
91
  }
90
92
  };
91
93
  const alertWorker = () => {
@@ -122,21 +124,25 @@ class App {
122
124
  }
123
125
  this.messages.push(message);
124
126
  // TODO: commit on start if there were `urgent` sends;
125
- // Clearify where urgent can be used for;
126
- // Clearify workflow for each type of message in case it was sent before start
127
+ // Clarify where urgent can be used for;
128
+ // Clarify workflow for each type of message in case it was sent before start
127
129
  // (like Fetch before start; maybe add an option "preCapture: boolean" or sth alike)
130
+ // Careful: `this.delay` is equal to zero before start hense all Timestamp-s will have to be updated on start
128
131
  if (this.activityState === ActivityState.Active && urgent) {
129
132
  this.commit();
130
133
  }
131
134
  }
132
135
  commit() {
133
136
  if (this.worker && this.messages.length) {
134
- this.messages.unshift((0, messages_gen_js_1.Timestamp)((0, utils_js_1.timestamp)()));
137
+ this.messages.unshift((0, messages_gen_js_1.Timestamp)(this.timestamp()));
135
138
  this.worker.postMessage(this.messages);
136
139
  this.commitCallbacks.forEach((cb) => cb(this.messages));
137
140
  this.messages.length = 0;
138
141
  }
139
142
  }
143
+ timestamp() {
144
+ return (0, utils_js_1.now)() + this.delay;
145
+ }
140
146
  safe(fn) {
141
147
  const app = this;
142
148
  return function (...args) {
@@ -145,7 +151,7 @@ class App {
145
151
  }
146
152
  catch (e) {
147
153
  app._debug('safe_fn_call', e);
148
- // time: now(),
154
+ // time: this.timestamp(),
149
155
  // name: e.name,
150
156
  // message: e.message,
151
157
  // stack: e.stack
@@ -273,8 +279,8 @@ class App {
273
279
  if (startOpts.sessionHash) {
274
280
  this.session.applySessionHash(startOpts.sessionHash);
275
281
  }
276
- const timestamp = (0, utils_js_1.timestamp)();
277
- const startWorkerMsg = {
282
+ const timestamp = (0, utils_js_1.now)();
283
+ this.worker.postMessage({
278
284
  type: 'start',
279
285
  pageNo: this.session.incPageNo(),
280
286
  ingestPoint: this.options.ingestPoint,
@@ -282,8 +288,7 @@ class App {
282
288
  url: document.URL,
283
289
  connAttemptCount: this.options.connAttemptCount,
284
290
  connAttemptGap: this.options.connAttemptGap,
285
- };
286
- this.worker.postMessage(startWorkerMsg);
291
+ });
287
292
  this.session.update({
288
293
  // TODO: transparent "session" module logic AND explicit internal api for plugins.
289
294
  // "updating" with old metadata in order to trigger session's UpdateCallbacks.
@@ -323,14 +328,16 @@ class App {
323
328
  return Promise.reject('Tracker stopped during authorisation');
324
329
  }
325
330
  const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
326
- } = r;
331
+ delay, } = r;
327
332
  if (typeof token !== 'string' ||
328
333
  typeof userUUID !== 'string' ||
329
334
  //typeof startTimestamp !== 'number' ||
330
335
  //typeof sessionID !== 'string' ||
336
+ typeof delay !== 'number' ||
331
337
  (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
332
338
  return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
333
339
  }
340
+ this.delay = delay;
334
341
  const prevSessionID = this.session.getInfo().sessionID;
335
342
  if (prevSessionID && prevSessionID !== sessionID) {
336
343
  this.session.reset();
@@ -338,12 +345,11 @@ class App {
338
345
  this.session.setSessionToken(token);
339
346
  this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
340
347
  this.localStorage.setItem(this.options.local_uuid_key, userUUID);
341
- const startWorkerMsg = {
348
+ this.worker.postMessage({
342
349
  type: 'auth',
343
350
  token,
344
351
  beaconSizeLimit,
345
- };
346
- this.worker.postMessage(startWorkerMsg);
352
+ });
347
353
  const onStartInfo = { sessionToken: token, userUUID, sessionID };
348
354
  this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
349
355
  this.observer.observe();
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
22
  export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
23
  export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
24
24
  export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
25
- export declare function JSException(name: string, message: string, payload: string): Messages.JSException;
25
+ export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
26
26
  export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
27
  export declare function UserID(id: string): Messages.UserID;
28
28
  export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
@@ -22,7 +22,7 @@ export declare function MouseMove(x: number, y: number): Messages.MouseMove;
22
22
  export declare function ConsoleLog(level: string, value: string): Messages.ConsoleLog;
23
23
  export declare function PageLoadTiming(requestStart: number, responseStart: number, responseEnd: number, domContentLoadedEventStart: number, domContentLoadedEventEnd: number, loadEventStart: number, loadEventEnd: number, firstPaint: number, firstContentfulPaint: number): Messages.PageLoadTiming;
24
24
  export declare function PageRenderTiming(speedIndex: number, visuallyComplete: number, timeToInteractive: number): Messages.PageRenderTiming;
25
- export declare function JSException(name: string, message: string, payload: string): Messages.JSException;
25
+ export declare function JSExceptionDeprecated(name: string, message: string, payload: string): Messages.JSExceptionDeprecated;
26
26
  export declare function RawCustomEvent(name: string, payload: string): Messages.RawCustomEvent;
27
27
  export declare function UserID(id: string): Messages.UserID;
28
28
  export declare function UserAnonymousID(id: string): Messages.UserAnonymousID;
@@ -56,3 +56,4 @@ export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Mes
56
56
  export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
57
57
  export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
58
58
  export declare function Zustand(mutation: string, state: string): Messages.Zustand;
59
+ export declare function JSException(name: string, message: string, payload: string, metadata: string): Messages.JSException;
@@ -2,8 +2,8 @@
2
2
  // Auto-generated, do not edit
3
3
  /* eslint-disable */
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.CreateIFrameDocument = exports.MouseClick = exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetPageVisibility = exports.ConnectionInformation = exports.ResourceTiming = exports.PerformanceTrack = exports.GraphQL = exports.NgRx = exports.MobX = exports.Vuex = exports.Redux = exports.StateAction = exports.OTable = exports.Profiler = exports.Fetch = exports.CSSDeleteRule = exports.CSSInsertRule = exports.Metadata = exports.UserAnonymousID = exports.UserID = exports.RawCustomEvent = exports.JSException = exports.PageRenderTiming = exports.PageLoadTiming = exports.ConsoleLog = exports.MouseMove = exports.SetInputChecked = exports.SetInputValue = exports.SetInputTarget = exports.SetNodeScroll = exports.SetNodeData = exports.RemoveNodeAttribute = exports.SetNodeAttribute = exports.RemoveNode = exports.MoveNode = exports.CreateTextNode = exports.CreateElementNode = exports.CreateDocument = exports.SetViewportScroll = exports.SetViewportSize = exports.SetPageLocation = exports.Timestamp = exports.PartitionedMessage = exports.BatchMetadata = void 0;
6
- exports.Zustand = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
5
+ exports.CreateIFrameDocument = exports.MouseClick = exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetPageVisibility = exports.ConnectionInformation = exports.ResourceTiming = exports.PerformanceTrack = exports.GraphQL = exports.NgRx = exports.MobX = exports.Vuex = exports.Redux = exports.StateAction = exports.OTable = exports.Profiler = exports.Fetch = exports.CSSDeleteRule = exports.CSSInsertRule = exports.Metadata = exports.UserAnonymousID = exports.UserID = exports.RawCustomEvent = exports.JSExceptionDeprecated = exports.PageRenderTiming = exports.PageLoadTiming = exports.ConsoleLog = exports.MouseMove = exports.SetInputChecked = exports.SetInputValue = exports.SetInputTarget = exports.SetNodeScroll = exports.SetNodeData = exports.RemoveNodeAttribute = exports.SetNodeAttribute = exports.RemoveNode = exports.MoveNode = exports.CreateTextNode = exports.CreateElementNode = exports.CreateDocument = exports.SetViewportScroll = exports.SetViewportSize = exports.SetPageLocation = exports.Timestamp = exports.PartitionedMessage = exports.BatchMetadata = void 0;
6
+ exports.JSException = exports.Zustand = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
7
7
  function BatchMetadata(version, pageNo, firstIndex, timestamp, location) {
8
8
  return [
9
9
  81 /* BatchMetadata */,
@@ -196,15 +196,15 @@ function PageRenderTiming(speedIndex, visuallyComplete, timeToInteractive) {
196
196
  ];
197
197
  }
198
198
  exports.PageRenderTiming = PageRenderTiming;
199
- function JSException(name, message, payload) {
199
+ function JSExceptionDeprecated(name, message, payload) {
200
200
  return [
201
- 25 /* JSException */,
201
+ 25 /* JSExceptionDeprecated */,
202
202
  name,
203
203
  message,
204
204
  payload,
205
205
  ];
206
206
  }
207
- exports.JSException = JSException;
207
+ exports.JSExceptionDeprecated = JSExceptionDeprecated;
208
208
  function RawCustomEvent(name, payload) {
209
209
  return [
210
210
  27 /* RawCustomEvent */,
@@ -500,3 +500,13 @@ function Zustand(mutation, state) {
500
500
  ];
501
501
  }
502
502
  exports.Zustand = Zustand;
503
+ function JSException(name, message, payload, metadata) {
504
+ return [
505
+ 78 /* JSException */,
506
+ name,
507
+ message,
508
+ payload,
509
+ metadata,
510
+ ];
511
+ }
512
+ exports.JSException = JSException;
@@ -101,8 +101,8 @@ function PageRenderTiming(speedIndex, visuallyComplete, timeToInteractive) {
101
101
  return [24 /* PageRenderTiming */, speedIndex, visuallyComplete, timeToInteractive];
102
102
  }
103
103
  exports.PageRenderTiming = PageRenderTiming;
104
- function JSException(name, message, payload) {
105
- return [25 /* JSException */, name, message, payload];
104
+ function JSException(name, message, payload, metadata) {
105
+ return [78 /* JSException */, name, message, payload, metadata];
106
106
  }
107
107
  exports.JSException = JSException;
108
108
  function RawCustomEvent(name, payload) {
@@ -6,7 +6,7 @@ export default class Nodes {
6
6
  private readonly elementListeners;
7
7
  constructor(node_id: string);
8
8
  attachNodeCallback(nodeCallback: NodeCallback): void;
9
- attachNodeListener(node: Node, type: string, listener: EventListener): void;
9
+ attachNodeListener(node: Node, type: string, listener: EventListener, useCapture?: boolean): void;
10
10
  registerNode(node: Node): [/*id:*/ number, /*isNew:*/ boolean];
11
11
  unregisterNode(node: Node): number | undefined;
12
12
  cleanTree(): void;
package/cjs/app/nodes.js CHANGED
@@ -11,18 +11,18 @@ class Nodes {
11
11
  attachNodeCallback(nodeCallback) {
12
12
  this.nodeCallbacks.push(nodeCallback);
13
13
  }
14
- attachNodeListener(node, type, listener) {
14
+ attachNodeListener(node, type, listener, useCapture = true) {
15
15
  const id = this.getID(node);
16
16
  if (id === undefined) {
17
17
  return;
18
18
  }
19
- node.addEventListener(type, listener);
19
+ node.addEventListener(type, listener, useCapture);
20
20
  let listeners = this.elementListeners.get(id);
21
21
  if (listeners === undefined) {
22
22
  listeners = [];
23
23
  this.elementListeners.set(id, listeners);
24
24
  }
25
- listeners.push([type, listener]);
25
+ listeners.push([type, listener, useCapture]);
26
26
  }
27
27
  registerNode(node) {
28
28
  let id = node[this.node_id];
@@ -42,7 +42,7 @@ class Nodes {
42
42
  const listeners = this.elementListeners.get(id);
43
43
  if (listeners !== undefined) {
44
44
  this.elementListeners.delete(id);
45
- listeners.forEach((listener) => node.removeEventListener(listener[0], listener[1]));
45
+ listeners.forEach((listener) => node.removeEventListener(listener[0], listener[1], listener[2]));
46
46
  }
47
47
  }
48
48
  return id;
@@ -15,5 +15,10 @@ declare type Auth = {
15
15
  token: string;
16
16
  beaconSizeLimit?: number;
17
17
  };
18
- export declare type WorkerMessageData = null | 'stop' | Start | Auth | Array<Message>;
18
+ export declare type ToWorkerData = null | 'stop' | Start | Auth | Array<Message>;
19
+ declare type Failure = {
20
+ type: 'failure';
21
+ reason: string;
22
+ };
23
+ export declare type FromWorkerData = 'restart' | Failure;
19
24
  export {};
@@ -21,7 +21,7 @@ export declare const enum Type {
21
21
  ConsoleLog = 22,
22
22
  PageLoadTiming = 23,
23
23
  PageRenderTiming = 24,
24
- JSException = 25,
24
+ JSExceptionDeprecated = 25,
25
25
  RawCustomEvent = 27,
26
26
  UserID = 28,
27
27
  UserAnonymousID = 29,
@@ -54,7 +54,8 @@ export declare const enum Type {
54
54
  AdoptedSSDeleteRule = 75,
55
55
  AdoptedSSAddOwner = 76,
56
56
  AdoptedSSRemoveOwner = 77,
57
- Zustand = 79
57
+ Zustand = 79,
58
+ JSException = 78
58
59
  }
59
60
  export declare type BatchMetadata = [
60
61
  Type.BatchMetadata,
@@ -182,8 +183,8 @@ export declare type PageRenderTiming = [
182
183
  number,
183
184
  number
184
185
  ];
185
- export declare type JSException = [
186
- Type.JSException,
186
+ export declare type JSExceptionDeprecated = [
187
+ Type.JSExceptionDeprecated,
187
188
  string,
188
189
  string,
189
190
  string
@@ -384,5 +385,12 @@ export declare type Zustand = [
384
385
  string,
385
386
  string
386
387
  ];
387
- declare type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSException | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand;
388
+ export declare type JSException = [
389
+ Type.JSException,
390
+ string,
391
+ string,
392
+ string,
393
+ string
394
+ ];
395
+ declare type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSExceptionDeprecated | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand | JSException;
388
396
  export default Message;
package/cjs/index.d.ts CHANGED
@@ -37,7 +37,7 @@ export default class API {
37
37
  userAnonymousID(id: string): void;
38
38
  setMetadata(key: string, value: string): void;
39
39
  metadata(key: string, value: string): void;
40
- event(key: string, payload: any, issue?: boolean): void;
41
- issue(key: string, payload: any): void;
42
- handleError: (e: Error | ErrorEvent | PromiseRejectionEvent) => void;
40
+ event(key: string, payload?: any, issue?: boolean): void;
41
+ issue(key: string, payload?: any): void;
42
+ handleError: (e: Error | ErrorEvent | PromiseRejectionEvent, metadata?: Record<string, any>) => void;
43
43
  }
package/cjs/index.js CHANGED
@@ -54,16 +54,17 @@ class API {
54
54
  constructor(options) {
55
55
  this.options = options;
56
56
  this.app = null;
57
- this.handleError = (e) => {
57
+ this.handleError = (e, metadata = {}) => {
58
58
  if (this.app === null) {
59
59
  return;
60
60
  }
61
61
  if (e instanceof Error) {
62
- this.app.send((0, exception_js_1.getExceptionMessage)(e, []));
62
+ const msg = (0, exception_js_1.getExceptionMessage)(e, [], metadata);
63
+ this.app.send(msg);
63
64
  }
64
65
  else if (e instanceof ErrorEvent ||
65
66
  ('PromiseRejectionEvent' in window && e instanceof PromiseRejectionEvent)) {
66
- const msg = (0, exception_js_1.getExceptionMessageFromEvent)(e);
67
+ const msg = (0, exception_js_1.getExceptionMessageFromEvent)(e, undefined, metadata);
67
68
  if (msg != null) {
68
69
  this.app.send(msg);
69
70
  }
@@ -133,7 +134,7 @@ class API {
133
134
  // no-cors issue only with text/plain or not-set Content-Type
134
135
  // req.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
135
136
  req.send(JSON.stringify({
136
- trackerVersion: '4.1.4',
137
+ trackerVersion: '4.1.6',
137
138
  projectKey: options.projectKey,
138
139
  doNotTrack,
139
140
  // TODO: add precise reason (an exact API missing)
@@ -216,7 +217,7 @@ class API {
216
217
  (0, utils_js_1.deprecationWarn)("'metadata' method", "'setMetadata' method", '/');
217
218
  this.setMetadata(key, value);
218
219
  }
219
- event(key, payload, issue = false) {
220
+ event(key, payload = null, issue = false) {
220
221
  if (typeof key === 'string' && this.app !== null) {
221
222
  if (issue) {
222
223
  return this.issue(key, payload);
@@ -232,7 +233,7 @@ class API {
232
233
  }
233
234
  }
234
235
  }
235
- issue(key, payload) {
236
+ issue(key, payload = null) {
236
237
  if (typeof key === 'string' && this.app !== null) {
237
238
  try {
238
239
  payload = JSON.stringify(payload);
@@ -28,12 +28,12 @@ function default_1(app) {
28
28
  }
29
29
  const styleSheetIDMap = new Map();
30
30
  const adoptedStyleSheetsOwnings = new Map();
31
- const sendAdoptedStyleSheetsUpdate = (root) => {
31
+ const sendAdoptedStyleSheetsUpdate = (root) => setTimeout(() => {
32
32
  let nodeID = app.nodes.getID(root);
33
33
  if (root === document) {
34
34
  nodeID = 0; // main document doesn't have nodeID. ID count starts from the documentElement
35
35
  }
36
- if (!nodeID) {
36
+ if (nodeID === undefined) {
37
37
  return;
38
38
  }
39
39
  let pastOwning = adoptedStyleSheetsOwnings.get(nodeID);
@@ -47,8 +47,8 @@ function default_1(app) {
47
47
  const init = !sheetID;
48
48
  if (!sheetID) {
49
49
  sheetID = nextID();
50
+ styleSheetIDMap.set(s, sheetID);
50
51
  }
51
- nowOwning.push(sheetID);
52
52
  if (!pastOwning.includes(sheetID)) {
53
53
  app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
54
54
  }
@@ -58,6 +58,7 @@ function default_1(app) {
58
58
  app.send((0, messages_gen_js_1.AdoptedSSInsertRuleURLBased)(sheetID, rules[i].cssText, i, app.getBaseHref()));
59
59
  }
60
60
  }
61
+ nowOwning.push(sheetID);
61
62
  }
62
63
  for (const sheetID of pastOwning) {
63
64
  if (!nowOwning.includes(sheetID)) {
@@ -65,7 +66,13 @@ function default_1(app) {
65
66
  }
66
67
  }
67
68
  adoptedStyleSheetsOwnings.set(nodeID, nowOwning);
68
- };
69
+ }, 20); // Misterious bug:
70
+ /* On the page https://explore.fast.design/components/fast-accordion
71
+ the only rule inside the only adoptedStyleSheet of the iframe-s document
72
+ gets changed during first milliseconds after the load.
73
+ Howerer, none of the documented methods (replace, insertRule) is triggered.
74
+ The rule is not substituted (remains the same object), however the text gets changed.
75
+ */
69
76
  function patchAdoptedStyleSheets(prototype) {
70
77
  const nativeAdoptedStyleSheetsDescriptor = Object.getOwnPropertyDescriptor(prototype, 'adoptedStyleSheets');
71
78
  if (nativeAdoptedStyleSheetsDescriptor) {
@@ -88,8 +95,8 @@ function default_1(app) {
88
95
  }
89
96
  patchAdoptedStyleSheets(context.Document.prototype);
90
97
  patchAdoptedStyleSheets(context.ShadowRoot.prototype);
91
- //@ts-ignore TODO: configure ts (use necessary lib)
92
- const { insertRule, deleteRule, replace, replaceSync } = context.CSSStyleSheet.prototype;
98
+ //@ts-ignore TODO: upgrade ts to 4.8+
99
+ const { replace, replaceSync } = context.CSSStyleSheet.prototype;
93
100
  //@ts-ignore
94
101
  context.CSSStyleSheet.prototype.replace = function (text) {
95
102
  return replace.call(this, text).then((sheet) => {
@@ -110,7 +117,7 @@ function default_1(app) {
110
117
  };
111
118
  };
112
119
  patchContext(window);
113
- app.observer.attachContextCallback(patchContext);
120
+ app.observer.attachContextCallback(app.safe(patchContext));
114
121
  app.attachStopCallback(() => {
115
122
  styleSheetIDMap.clear();
116
123
  adoptedStyleSheetsOwnings.clear();
@@ -11,7 +11,7 @@ function default_1(app) {
11
11
  app.send((0, messages_gen_js_1.TechnicalInfo)('no_stylesheet_prototype_in_window', ''));
12
12
  return;
13
13
  }
14
- const sendInserDeleteRule = app.safe((sheet, index, rule) => {
14
+ const sendInsertDeleteRule = app.safe((sheet, index, rule) => {
15
15
  const sheetID = constructedStyleSheets_js_1.styleSheetIDMap.get(sheet);
16
16
  if (!sheetID) {
17
17
  // OK-case. Sheet haven't been registered yet. Rules will be sent on registration.
@@ -51,15 +51,15 @@ function default_1(app) {
51
51
  app.debug.warn('Rule index not found in', sheet, topmostRule);
52
52
  }
53
53
  });
54
- const patchContext = (context) => {
54
+ const patchContext = app.safe((context) => {
55
55
  const { insertRule, deleteRule } = context.CSSStyleSheet.prototype;
56
56
  const { insertRule: groupInsertRule, deleteRule: groupDeleteRule } = context.CSSGroupingRule.prototype;
57
57
  context.CSSStyleSheet.prototype.insertRule = function (rule, index = 0) {
58
- sendInserDeleteRule(this, index, rule);
58
+ sendInsertDeleteRule(this, index, rule);
59
59
  return insertRule.call(this, rule, index);
60
60
  };
61
61
  context.CSSStyleSheet.prototype.deleteRule = function (index) {
62
- sendInserDeleteRule(this, index);
62
+ sendInsertDeleteRule(this, index);
63
63
  return deleteRule.call(this, index);
64
64
  };
65
65
  context.CSSGroupingRule.prototype.insertRule = function (rule, index = 0) {
@@ -72,7 +72,7 @@ function default_1(app) {
72
72
  sendReplaceGroupingRule(this);
73
73
  return result;
74
74
  };
75
- };
75
+ });
76
76
  patchContext(window);
77
77
  app.observer.attachContextCallback(patchContext);
78
78
  app.nodes.attachNodeCallback((node) => {
@@ -92,7 +92,7 @@ function default_1(app) {
92
92
  app.send((0, messages_gen_js_1.AdoptedSSAddOwner)(sheetID, nodeID));
93
93
  const rules = sheet.cssRules;
94
94
  for (let i = 0; i < rules.length; i++) {
95
- sendInserDeleteRule(sheet, i, rules[i].cssText);
95
+ sendInsertDeleteRule(sheet, i, rules[i].cssText);
96
96
  }
97
97
  });
98
98
  }
@@ -10,7 +10,7 @@ interface StackFrame {
10
10
  functionName?: string;
11
11
  source?: string;
12
12
  }
13
- export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>): Message;
14
- export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis): Message | null;
13
+ export declare function getExceptionMessage(error: Error, fallbackStack: Array<StackFrame>, metadata?: Record<string, any>): Message;
14
+ export declare function getExceptionMessageFromEvent(e: ErrorEvent | PromiseRejectionEvent, context?: typeof globalThis, metadata?: Record<string, any>): Message | null;
15
15
  export default function (app: App, opts: Partial<Options>): void;
16
16
  export {};
@@ -14,19 +14,19 @@ function getDefaultStack(e) {
14
14
  },
15
15
  ];
16
16
  }
17
- function getExceptionMessage(error, fallbackStack) {
17
+ function getExceptionMessage(error, fallbackStack, metadata = {}) {
18
18
  let stack = fallbackStack;
19
19
  try {
20
20
  stack = error_stack_parser_1.default.parse(error);
21
21
  }
22
22
  catch (e) { }
23
- return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack));
23
+ return (0, messages_gen_js_1.JSException)(error.name, error.message, JSON.stringify(stack), JSON.stringify(metadata));
24
24
  }
25
25
  exports.getExceptionMessage = getExceptionMessage;
26
- function getExceptionMessageFromEvent(e, context = window) {
26
+ function getExceptionMessageFromEvent(e, context = window, metadata = {}) {
27
27
  if (e instanceof ErrorEvent) {
28
28
  if (e.error instanceof Error) {
29
- return getExceptionMessage(e.error, getDefaultStack(e));
29
+ return getExceptionMessage(e.error, getDefaultStack(e), metadata);
30
30
  }
31
31
  else {
32
32
  let [name, message] = e.message.split(':');
@@ -34,12 +34,12 @@ function getExceptionMessageFromEvent(e, context = window) {
34
34
  name = 'Error';
35
35
  message = e.message;
36
36
  }
37
- return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)));
37
+ return (0, messages_gen_js_1.JSException)(name, message, JSON.stringify(getDefaultStack(e)), JSON.stringify(metadata));
38
38
  }
39
39
  }
40
40
  else if ('PromiseRejectionEvent' in context && e instanceof context.PromiseRejectionEvent) {
41
41
  if (e.reason instanceof Error) {
42
- return getExceptionMessage(e.reason, []);
42
+ return getExceptionMessage(e.reason, [], metadata);
43
43
  }
44
44
  else {
45
45
  let message;
@@ -49,7 +49,7 @@ function getExceptionMessageFromEvent(e, context = window) {
49
49
  catch (_) {
50
50
  message = String(e.reason);
51
51
  }
52
- return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]');
52
+ return (0, messages_gen_js_1.JSException)('Unhandled Promise Rejection', message, '[]', JSON.stringify(metadata));
53
53
  }
54
54
  }
55
55
  return null;
@@ -70,7 +70,7 @@ function default_1(app, opts) {
70
70
  app.attachEventListener(context, 'error', handler);
71
71
  }
72
72
  if (options.captureExceptions) {
73
- app.observer.attachContextCallback(patchContext);
73
+ app.observer.attachContextCallback(patchContext); // TODO: attach once-per-iframe (?)
74
74
  patchContext(window);
75
75
  }
76
76
  }
@@ -54,7 +54,7 @@ function default_1(app) {
54
54
  const sendImgError = app.safe(function (img) {
55
55
  const resolvedSrc = resolveURL(img.src || ''); // Src type is null sometimes. - is it true?
56
56
  if ((0, utils_js_1.isURL)(resolvedSrc)) {
57
- app.send((0, messages_gen_js_1.ResourceTiming)((0, utils_js_1.timestamp)(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
57
+ app.send((0, messages_gen_js_1.ResourceTiming)(app.timestamp(), 0, 0, 0, 0, 0, resolvedSrc, 'img'));
58
58
  }
59
59
  });
60
60
  const sendImgAttrs = app.safe(function (img) {