@openreplay/tracker 4.0.0 → 4.0.2

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 (64) hide show
  1. package/cjs/app/guards.d.ts +1 -0
  2. package/cjs/app/guards.js +6 -1
  3. package/cjs/app/index.d.ts +1 -1
  4. package/cjs/app/index.js +16 -10
  5. package/cjs/app/messages.gen.d.ts +1 -0
  6. package/cjs/app/messages.gen.js +10 -1
  7. package/cjs/app/nodes.d.ts +1 -1
  8. package/cjs/app/nodes.js +3 -5
  9. package/cjs/app/observer/iframe_observer.js +1 -0
  10. package/cjs/app/observer/iframe_offsets.d.ts +8 -0
  11. package/cjs/app/observer/iframe_offsets.js +59 -0
  12. package/cjs/app/observer/observer.js +4 -4
  13. package/cjs/app/observer/top_observer.d.ts +2 -4
  14. package/cjs/app/observer/top_observer.js +11 -21
  15. package/cjs/app/sanitizer.d.ts +10 -4
  16. package/cjs/app/sanitizer.js +33 -15
  17. package/cjs/app/session.js +1 -1
  18. package/cjs/common/messages.gen.d.ts +8 -2
  19. package/cjs/common/messages.gen.js +1 -0
  20. package/cjs/index.d.ts +1 -0
  21. package/cjs/index.js +7 -7
  22. package/cjs/modules/constructedStyleSheets.d.ts +4 -0
  23. package/cjs/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +21 -20
  24. package/cjs/modules/cssrules.js +65 -18
  25. package/cjs/modules/img.js +27 -19
  26. package/cjs/modules/input.js +2 -2
  27. package/cjs/modules/mouse.js +11 -7
  28. package/cjs/modules/scroll.js +32 -12
  29. package/cjs/utils.d.ts +5 -3
  30. package/cjs/utils.js +18 -13
  31. package/lib/app/guards.d.ts +1 -0
  32. package/lib/app/guards.js +4 -0
  33. package/lib/app/index.d.ts +1 -1
  34. package/lib/app/index.js +16 -10
  35. package/lib/app/messages.gen.d.ts +1 -0
  36. package/lib/app/messages.gen.js +8 -0
  37. package/lib/app/nodes.d.ts +1 -1
  38. package/lib/app/nodes.js +3 -5
  39. package/lib/app/observer/iframe_observer.js +1 -0
  40. package/lib/app/observer/iframe_offsets.d.ts +8 -0
  41. package/lib/app/observer/iframe_offsets.js +56 -0
  42. package/lib/app/observer/observer.js +4 -4
  43. package/lib/app/observer/top_observer.d.ts +2 -4
  44. package/lib/app/observer/top_observer.js +11 -21
  45. package/lib/app/sanitizer.d.ts +10 -4
  46. package/lib/app/sanitizer.js +32 -15
  47. package/lib/app/session.js +1 -1
  48. package/lib/common/messages.gen.d.ts +8 -2
  49. package/lib/common/messages.gen.js +1 -0
  50. package/lib/common/tsconfig.tsbuildinfo +1 -1
  51. package/lib/index.d.ts +1 -0
  52. package/lib/index.js +5 -6
  53. package/lib/modules/constructedStyleSheets.d.ts +4 -0
  54. package/lib/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +20 -21
  55. package/lib/modules/cssrules.js +67 -19
  56. package/lib/modules/img.js +28 -20
  57. package/lib/modules/input.js +3 -3
  58. package/lib/modules/mouse.js +11 -7
  59. package/lib/modules/scroll.js +33 -13
  60. package/lib/utils.d.ts +5 -3
  61. package/lib/utils.js +17 -11
  62. package/package.json +1 -1
  63. package/cjs/modules/adoptedStyleSheets.d.ts +0 -2
  64. package/lib/modules/adoptedStyleSheets.d.ts +0 -2
@@ -1,3 +1,4 @@
1
+ export declare function isNode(sth: any): sth is Node;
1
2
  export declare function isSVGElement(node: Element): node is SVGElement;
2
3
  export declare function isElementNode(node: Node): node is Element;
3
4
  export declare function isTextNode(node: Node): node is Text;
package/cjs/app/guards.js CHANGED
@@ -1,6 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.hasTag = exports.isRootNode = exports.isDocument = exports.isTextNode = exports.isElementNode = exports.isSVGElement = void 0;
3
+ exports.hasTag = exports.isRootNode = exports.isDocument = exports.isTextNode = exports.isElementNode = exports.isSVGElement = exports.isNode = void 0;
4
+ //@ts-ignore
5
+ function isNode(sth) {
6
+ return !!sth && sth.nodeType != null;
7
+ }
8
+ exports.isNode = isNode;
4
9
  function isSVGElement(node) {
5
10
  return node.namespaceURI === 'http://www.w3.org/2000/svg';
6
11
  }
@@ -77,7 +77,7 @@ export default class App {
77
77
  private _debug;
78
78
  send(message: Message, urgent?: boolean): void;
79
79
  private commit;
80
- safe<T extends (...args: any[]) => void>(fn: T): T;
80
+ safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
81
81
  attachCommitCallback(cb: CommitCallback): void;
82
82
  attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
83
83
  attachStopCallback(cb: () => any, useSafe?: boolean): void;
package/cjs/app/index.js CHANGED
@@ -32,7 +32,7 @@ class App {
32
32
  this.stopCallbacks = [];
33
33
  this.commitCallbacks = [];
34
34
  this.activityState = ActivityState.NotActive;
35
- this.version = '4.0.0'; // TODO: version compatability check inside each plugin.
35
+ this.version = '4.0.2'; // TODO: version compatability check inside each plugin.
36
36
  this.projectKey = projectKey;
37
37
  this.options = Object.assign({
38
38
  revID: '',
@@ -74,17 +74,17 @@ class App {
74
74
  this.session.applySessionHash(sessionToken);
75
75
  }
76
76
  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])}}}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!==c&&(clearInterval(c),c=null),h&&(h.clean(),h=null),n.NotActive}n.NotActive;let o,c=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]?o=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(o)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{self.postMessage("restart")},()=>{r&&(r.clean(),r=null),a(),self.postMessage("failed")},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===c&&(c=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' })));
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' })));
78
78
  this.worker.onerror = (e) => {
79
79
  this._debug('webworker_error', e);
80
80
  };
81
81
  this.worker.onmessage = ({ data }) => {
82
82
  if (data === 'failed') {
83
- this.stop();
83
+ this.stop(false);
84
84
  this._debug('worker_failed', {}); // add context (from worker)
85
85
  }
86
86
  else if (data === 'restart') {
87
- this.stop();
87
+ this.stop(false);
88
88
  this.start({ forceNew: true });
89
89
  }
90
90
  };
@@ -153,8 +153,6 @@ class App {
153
153
  }; // TODO: correct typing
154
154
  }
155
155
  attachCommitCallback(cb) {
156
- // TODO!: what if start callback added when activityState === Active ?
157
- // For example - attachEventListener() called during dynamic <iframe> appearance
158
156
  this.commitCallbacks.push(cb);
159
157
  }
160
158
  attachStartCallback(cb, useSafe = false) {
@@ -169,6 +167,7 @@ class App {
169
167
  }
170
168
  this.stopCallbacks.push(cb);
171
169
  }
170
+ // Use app.nodes.attachNodeListener for registered nodes instead
172
171
  attachEventListener(target, type, listener, useSafe = true, useCapture = true) {
173
172
  if (useSafe) {
174
173
  listener = this.safe(listener);
@@ -220,7 +219,7 @@ class App {
220
219
  return this.options.ingestPoint.replace(/ingest$/, `${projectID}/session/${sessionID}`);
221
220
  }
222
221
  getHost() {
223
- return new URL(this.options.ingestPoint).hostname;
222
+ return new URL(this.options.ingestPoint).host;
224
223
  }
225
224
  getProjectKey() {
226
225
  return this.projectKey;
@@ -291,14 +290,15 @@ class App {
291
290
  });
292
291
  const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
293
292
  this.sessionStorage.removeItem(this.options.session_reset_key);
293
+ const shouldReset = startOpts.forceNew || sReset !== null;
294
294
  return window
295
295
  .fetch(this.options.ingestPoint + '/v1/web/start', {
296
296
  method: 'POST',
297
297
  headers: {
298
298
  'Content-Type': 'application/json',
299
299
  },
300
- body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: this.session.getSessionToken(), deviceMemory: performance_js_1.deviceMemory,
301
- jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
300
+ body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: shouldReset ? undefined : this.session.getSessionToken(), deviceMemory: performance_js_1.deviceMemory,
301
+ jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit })),
302
302
  })
303
303
  .then((r) => {
304
304
  if (r.status === 200) {
@@ -316,6 +316,9 @@ class App {
316
316
  if (!this.worker) {
317
317
  return Promise.reject('no worker found after start request (this might not happen)');
318
318
  }
319
+ if (this.activityState === ActivityState.NotActive) {
320
+ return Promise.reject('Tracker stopped during authorisation');
321
+ }
319
322
  const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
320
323
  } = r;
321
324
  if (typeof token !== 'string' ||
@@ -325,9 +328,12 @@ class App {
325
328
  (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
326
329
  return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
327
330
  }
331
+ if (sessionID !== this.session.getInfo().sessionID) {
332
+ this.session.reset();
333
+ }
328
334
  this.session.setSessionToken(token);
329
- this.localStorage.setItem(this.options.local_uuid_key, userUUID);
330
335
  this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
336
+ this.localStorage.setItem(this.options.local_uuid_key, userUUID);
331
337
  const startWorkerMsg = {
332
338
  type: 'auth',
333
339
  token,
@@ -55,3 +55,4 @@ export declare function AdoptedSSInsertRuleURLBased(sheetID: number, rule: strin
55
55
  export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Messages.AdoptedSSDeleteRule;
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
+ export declare function Zustand(mutation: string, state: string): Messages.Zustand;
@@ -1,8 +1,9 @@
1
1
  "use strict";
2
2
  // Auto-generated, do not edit
3
+ /* eslint-disable */
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
4
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;
5
- exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
6
+ exports.Zustand = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
6
7
  function BatchMetadata(version, pageNo, firstIndex, timestamp, location) {
7
8
  return [
8
9
  81 /* BatchMetadata */,
@@ -491,3 +492,11 @@ function AdoptedSSRemoveOwner(sheetID, id) {
491
492
  ];
492
493
  }
493
494
  exports.AdoptedSSRemoveOwner = AdoptedSSRemoveOwner;
495
+ function Zustand(mutation, state) {
496
+ return [
497
+ 79 /* Zustand */,
498
+ mutation,
499
+ state,
500
+ ];
501
+ }
502
+ exports.Zustand = Zustand;
@@ -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
- attachElementListener(type: string, node: Element, elementListener: EventListener): void;
9
+ attachNodeListener(node: Node, type: string, listener: EventListener): 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,20 +11,18 @@ class Nodes {
11
11
  attachNodeCallback(nodeCallback) {
12
12
  this.nodeCallbacks.push(nodeCallback);
13
13
  }
14
- // TODO: what is the difference with app.attachEventListener. can we use only one of those?
15
- attachElementListener(type, node, elementListener) {
14
+ attachNodeListener(node, type, listener) {
16
15
  const id = this.getID(node);
17
16
  if (id === undefined) {
18
17
  return;
19
18
  }
20
- node.addEventListener(type, elementListener);
19
+ node.addEventListener(type, listener);
21
20
  let listeners = this.elementListeners.get(id);
22
21
  if (listeners === undefined) {
23
22
  listeners = [];
24
23
  this.elementListeners.set(id, listeners);
25
- return;
26
24
  }
27
- listeners.push([type, elementListener]);
25
+ listeners.push([type, listener]);
28
26
  }
29
27
  registerNode(node) {
30
28
  let id = node[this.node_id];
@@ -11,6 +11,7 @@ class IFrameObserver extends observer_js_1.default {
11
11
  } //log TODO common app.logger
12
12
  // Have to observe document, because the inner <html> might be changed
13
13
  this.observeRoot(doc, (docID) => {
14
+ //MBTODO: do not send if empty (send on load? it might be in-place iframe, like our replayer, which does not get loaded)
14
15
  if (docID === undefined) {
15
16
  console.log('OpenReplay: Iframe document not bound');
16
17
  return;
@@ -0,0 +1,8 @@
1
+ export declare type Offset = [/*left:*/ number, /*top: */ number];
2
+ export default class IFrameOffsets {
3
+ private readonly states;
4
+ private calcOffset;
5
+ getDocumentOffset(doc: Document): Offset;
6
+ observe(iFrame: HTMLIFrameElement): void;
7
+ clear(): void;
8
+ }
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ // Le truc - for defining an absolute offset for (nested) iframe documents. (To track mouse movments)
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ class IFrameOffsets {
5
+ constructor() {
6
+ this.states = new Map();
7
+ }
8
+ calcOffset(state) {
9
+ let parLeft = 0, parTop = 0;
10
+ if (state.parent) {
11
+ ;
12
+ [parLeft, parTop] = this.calcOffset(state.parent);
13
+ }
14
+ if (!state.offset) {
15
+ const { left, top } = state.iFrame.getBoundingClientRect();
16
+ state.offset = [left, top];
17
+ }
18
+ const [left, top] = state.offset;
19
+ return [parLeft + left, parTop + top]; // TODO: store absolute sum, invalidate whole subtree. Otherwise it is summated on each mousemove
20
+ }
21
+ getDocumentOffset(doc) {
22
+ const state = this.states.get(doc);
23
+ if (!state) {
24
+ return [0, 0];
25
+ } // topmost doc
26
+ return this.calcOffset(state);
27
+ }
28
+ observe(iFrame) {
29
+ var _a;
30
+ const doc = iFrame.contentDocument;
31
+ if (!doc) {
32
+ return;
33
+ }
34
+ const parentDoc = iFrame.ownerDocument;
35
+ const parentState = this.states.get(parentDoc);
36
+ const state = {
37
+ offset: null,
38
+ iFrame,
39
+ parent: parentState || null,
40
+ clear: () => {
41
+ var _a;
42
+ parentDoc.removeEventListener('scroll', invalidateOffset);
43
+ (_a = parentDoc.defaultView) === null || _a === void 0 ? void 0 : _a.removeEventListener('resize', invalidateOffset);
44
+ },
45
+ };
46
+ const invalidateOffset = () => {
47
+ state.offset = null;
48
+ };
49
+ // anything more reliable? This does not cover all cases (layout changes are ignored, for ex.)
50
+ parentDoc.addEventListener('scroll', invalidateOffset);
51
+ (_a = parentDoc.defaultView) === null || _a === void 0 ? void 0 : _a.addEventListener('resize', invalidateOffset);
52
+ this.states.set(doc, state);
53
+ }
54
+ clear() {
55
+ this.states.forEach((s) => s.clear());
56
+ this.states.clear();
57
+ }
58
+ }
59
+ exports.default = IFrameOffsets;
@@ -223,7 +223,7 @@ class Observer {
223
223
  return false;
224
224
  }
225
225
  this.app.sanitizer.handleNode(id, parentID, node);
226
- if (this.app.sanitizer.isMaskedContainer(parentID)) {
226
+ if (this.app.sanitizer.isHidden(parentID)) {
227
227
  return false;
228
228
  }
229
229
  }
@@ -251,12 +251,12 @@ class Observer {
251
251
  if ((0, guards_js_1.isElementNode)(node)) {
252
252
  let el = node;
253
253
  if (parentID !== undefined) {
254
- if (this.app.sanitizer.isMaskedContainer(id)) {
254
+ if (this.app.sanitizer.isHidden(id)) {
255
255
  const width = el.clientWidth;
256
256
  const height = el.clientHeight;
257
257
  el = node.cloneNode();
258
- el.style.width = width + 'px';
259
- el.style.height = height + 'px';
258
+ el.style.width = `${width}px`;
259
+ el.style.height = `${height}px`;
260
260
  }
261
261
  this.app.send((0, messages_gen_js_1.CreateElementNode)(id, parentID, index, el.tagName, (0, guards_js_1.isSVGElement)(node)));
262
262
  }
@@ -1,16 +1,14 @@
1
1
  import Observer from './observer.js';
2
+ import { Offset } from './iframe_offsets.js';
2
3
  import App from '../index.js';
3
4
  export interface Options {
4
5
  captureIFrames: boolean;
5
6
  }
6
7
  declare type Context = Window & typeof globalThis;
7
8
  declare type ContextCallback = (context: Context) => void;
8
- declare type Offset = {
9
- top: number;
10
- left: number;
11
- };
12
9
  export default class TopObserver extends Observer {
13
10
  private readonly options;
11
+ private readonly iframeOffsets;
14
12
  constructor(app: App, options: Partial<Options>);
15
13
  private readonly contextCallbacks;
16
14
  private readonly contextsSet;
@@ -4,16 +4,14 @@ const observer_js_1 = require("./observer.js");
4
4
  const guards_js_1 = require("../guards.js");
5
5
  const iframe_observer_js_1 = require("./iframe_observer.js");
6
6
  const shadow_root_observer_js_1 = require("./shadow_root_observer.js");
7
+ const iframe_offsets_js_1 = require("./iframe_offsets.js");
7
8
  const messages_gen_js_1 = require("../messages.gen.js");
8
9
  const utils_js_1 = require("../../utils.js");
9
- function isPatchedDocument(doc) {
10
- // @ts-ignore
11
- return typeof doc.__openreplay__getOffset === 'function';
12
- }
13
10
  const attachShadowNativeFn = utils_js_1.IN_BROWSER ? Element.prototype.attachShadow : () => new ShadowRoot();
14
11
  class TopObserver extends observer_js_1.default {
15
12
  constructor(app, options) {
16
13
  super(app, true);
14
+ this.iframeOffsets = new iframe_offsets_js_1.default();
17
15
  this.contextCallbacks = [];
18
16
  // Attached once per Tracker instance
19
17
  this.contextsSet = new Set();
@@ -40,17 +38,14 @@ class TopObserver extends observer_js_1.default {
40
38
  attachContextCallback(cb) {
41
39
  this.contextCallbacks.push(cb);
42
40
  }
43
- // Le truc
44
41
  getDocumentOffset(doc) {
45
- if (isPatchedDocument(doc)) {
46
- return doc.__openreplay__getOffset();
47
- }
48
- return { top: 0, left: 0 };
42
+ return this.iframeOffsets.getDocumentOffset(doc);
49
43
  }
50
44
  handleIframe(iframe) {
51
45
  let doc = null;
52
- let win = null;
53
- const handle = this.app.safe(() => {
46
+ // setTimeout is required. Otherwise some event listeners (scroll, mousemove) applied in modules
47
+ // do not work on the iframe document when it 've been loaded dynamically ((why?))
48
+ const handle = this.app.safe(() => setTimeout(() => {
54
49
  const id = this.app.nodes.getID(iframe);
55
50
  if (id === undefined) {
56
51
  //log
@@ -61,27 +56,21 @@ class TopObserver extends observer_js_1.default {
61
56
  if (currentDoc && currentDoc !== doc) {
62
57
  const observer = new iframe_observer_js_1.default(this.app);
63
58
  this.iframeObservers.push(observer);
64
- observer.observe(iframe);
59
+ observer.observe(iframe); // TODO: call unregisterNode for the previous doc if present (incapsulate: one iframe - one observer)
65
60
  doc = currentDoc;
66
- doc.__openreplay__getOffset = () => {
67
- const { top, left } = this.getDocumentOffset(iframe.ownerDocument);
68
- return {
69
- top: iframe.offsetTop + top,
70
- left: iframe.offsetLeft + left,
71
- };
72
- };
61
+ this.iframeOffsets.observe(iframe);
73
62
  }
74
63
  if (currentWin &&
75
64
  // Sometimes currentWin.window is null (not in specification). Such window object is not functional
76
65
  currentWin === currentWin.window &&
77
66
  !this.contextsSet.has(currentWin) // for each context callbacks called once per Tracker (TopObserver) instance
67
+ //TODO: more explicit logic
78
68
  ) {
79
69
  this.contextsSet.add(currentWin);
80
70
  //@ts-ignore https://github.com/microsoft/TypeScript/issues/41684
81
71
  this.contextCallbacks.forEach((cb) => cb(currentWin));
82
- win = currentWin;
83
72
  }
84
- });
73
+ }, 0));
85
74
  iframe.addEventListener('load', handle); // why app.attachEventListener not working?
86
75
  handle();
87
76
  }
@@ -110,6 +99,7 @@ class TopObserver extends observer_js_1.default {
110
99
  }, window.document.documentElement);
111
100
  }
112
101
  disconnect() {
102
+ this.iframeOffsets.clear();
113
103
  Element.prototype.attachShadow = attachShadowNativeFn;
114
104
  this.iframeObservers.forEach((o) => o.disconnect());
115
105
  this.iframeObservers = [];
@@ -1,18 +1,24 @@
1
1
  import type App from './index.js';
2
+ export declare enum SanitizeLevel {
3
+ Plain = 0,
4
+ Obscured = 1,
5
+ Hidden = 2
6
+ }
2
7
  export interface Options {
3
8
  obscureTextEmails: boolean;
4
9
  obscureTextNumbers: boolean;
10
+ domSanitizer?: (node: Element) => SanitizeLevel;
5
11
  }
6
12
  export default class Sanitizer {
7
13
  private readonly app;
8
- private readonly masked;
9
- private readonly maskedContainers;
14
+ private readonly obscured;
15
+ private readonly hidden;
10
16
  private readonly options;
11
17
  constructor(app: App, options: Partial<Options>);
12
18
  handleNode(id: number, parentID: number, node: Node): void;
13
19
  sanitize(id: number, data: string): string;
14
- isMasked(id: number): boolean;
15
- isMaskedContainer(id: number): boolean;
20
+ isObscured(id: number): boolean;
21
+ isHidden(id: number): boolean;
16
22
  getInnerTextSecure(el: HTMLElement): string;
17
23
  clear(): void;
18
24
  }
@@ -1,29 +1,47 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SanitizeLevel = void 0;
3
4
  const utils_js_1 = require("../utils.js");
4
5
  const guards_js_1 = require("./guards.js");
6
+ var SanitizeLevel;
7
+ (function (SanitizeLevel) {
8
+ SanitizeLevel[SanitizeLevel["Plain"] = 0] = "Plain";
9
+ SanitizeLevel[SanitizeLevel["Obscured"] = 1] = "Obscured";
10
+ SanitizeLevel[SanitizeLevel["Hidden"] = 2] = "Hidden";
11
+ })(SanitizeLevel = exports.SanitizeLevel || (exports.SanitizeLevel = {}));
5
12
  class Sanitizer {
6
13
  constructor(app, options) {
7
14
  this.app = app;
8
- this.masked = new Set();
9
- this.maskedContainers = new Set();
15
+ this.obscured = new Set();
16
+ this.hidden = new Set();
10
17
  this.options = Object.assign({
11
18
  obscureTextEmails: true,
12
19
  obscureTextNumbers: false,
13
20
  }, options);
14
21
  }
15
22
  handleNode(id, parentID, node) {
16
- if (this.masked.has(parentID) ||
17
- ((0, guards_js_1.isElementNode)(node) && (0, utils_js_1.hasOpenreplayAttribute)(node, 'masked'))) {
18
- this.masked.add(id);
23
+ if (this.obscured.has(parentID) ||
24
+ ((0, guards_js_1.isElementNode)(node) &&
25
+ ((0, utils_js_1.hasOpenreplayAttribute)(node, 'masked') || (0, utils_js_1.hasOpenreplayAttribute)(node, 'obscured')))) {
26
+ this.obscured.add(id);
19
27
  }
20
- if (this.maskedContainers.has(parentID) ||
21
- ((0, guards_js_1.isElementNode)(node) && (0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked'))) {
22
- this.maskedContainers.add(id);
28
+ if (this.hidden.has(parentID) ||
29
+ ((0, guards_js_1.isElementNode)(node) &&
30
+ ((0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked') || (0, utils_js_1.hasOpenreplayAttribute)(node, 'hidden')))) {
31
+ this.hidden.add(id);
32
+ }
33
+ if (this.options.domSanitizer !== undefined && (0, guards_js_1.isElementNode)(node)) {
34
+ const sanitizeLevel = this.options.domSanitizer(node);
35
+ if (sanitizeLevel === SanitizeLevel.Obscured) {
36
+ this.obscured.add(id);
37
+ }
38
+ if (sanitizeLevel === SanitizeLevel.Hidden) {
39
+ this.hidden.add(id);
40
+ }
23
41
  }
24
42
  }
25
43
  sanitize(id, data) {
26
- if (this.masked.has(id)) {
44
+ if (this.obscured.has(id)) {
27
45
  // TODO: is it the best place to put trim() ? Might trimmed spaces be considered in layout in certain cases?
28
46
  return data
29
47
  .trim()
@@ -37,11 +55,11 @@ class Sanitizer {
37
55
  }
38
56
  return data;
39
57
  }
40
- isMasked(id) {
41
- return this.masked.has(id);
58
+ isObscured(id) {
59
+ return this.obscured.has(id);
42
60
  }
43
- isMaskedContainer(id) {
44
- return this.maskedContainers.has(id);
61
+ isHidden(id) {
62
+ return this.hidden.has(id);
45
63
  }
46
64
  getInnerTextSecure(el) {
47
65
  const id = this.app.nodes.getID(el);
@@ -51,8 +69,8 @@ class Sanitizer {
51
69
  return this.sanitize(id, el.innerText);
52
70
  }
53
71
  clear() {
54
- this.masked.clear();
55
- this.maskedContainers.clear();
72
+ this.obscured.clear();
73
+ this.hidden.clear();
56
74
  }
57
75
  }
58
76
  exports.default = Sanitizer;
@@ -78,7 +78,7 @@ class Session {
78
78
  let pageNoStr = '100500'; // back-compat for sessionToken
79
79
  if (hashParts.length == 2) {
80
80
  ;
81
- [token, pageNoStr] = hashParts;
81
+ [pageNoStr, token] = hashParts;
82
82
  }
83
83
  if (!pageNoStr || !token) {
84
84
  return;
@@ -53,7 +53,8 @@ export declare const enum Type {
53
53
  AdoptedSSInsertRuleURLBased = 73,
54
54
  AdoptedSSDeleteRule = 75,
55
55
  AdoptedSSAddOwner = 76,
56
- AdoptedSSRemoveOwner = 77
56
+ AdoptedSSRemoveOwner = 77,
57
+ Zustand = 79
57
58
  }
58
59
  export declare type BatchMetadata = [
59
60
  Type.BatchMetadata,
@@ -378,5 +379,10 @@ export declare type AdoptedSSRemoveOwner = [
378
379
  number,
379
380
  number
380
381
  ];
381
- 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;
382
+ export declare type Zustand = [
383
+ Type.Zustand,
384
+ string,
385
+ string
386
+ ];
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;
382
388
  export default Message;
@@ -1,3 +1,4 @@
1
1
  "use strict";
2
2
  // Auto-generated, do not edit
3
+ /* eslint-disable */
3
4
  Object.defineProperty(exports, "__esModule", { value: true });
package/cjs/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import App from './app/index.js';
2
2
  export { default as App } from './app/index.js';
3
3
  import * as _Messages from './app/messages.gen.js';
4
4
  export declare const Messages: typeof _Messages;
5
+ export { SanitizeLevel } from './app/sanitizer.js';
5
6
  import type { Options as AppOptions } from './app/index.js';
6
7
  import type { Options as ConsoleOptions } from './modules/console.js';
7
8
  import type { Options as ExceptionOptions } from './modules/exception.js';