@openreplay/tracker 3.4.15 → 3.4.17

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.
@@ -1,19 +1,25 @@
1
1
  import Message from "../messages/message.js";
2
2
  import Nodes from "./nodes.js";
3
- import Observer from "./observer/top_observer.js";
3
+ import Sanitizer from "./sanitizer.js";
4
4
  import Ticker from "./ticker.js";
5
5
  import type { Options as ObserverOptions } from "./observer/top_observer.js";
6
+ import type { Options as SanitizerOptions } from "./sanitizer.js";
6
7
  import type { Options as WebworkerOptions } from "../messages/webworker.js";
7
8
  export interface OnStartInfo {
8
9
  sessionID: string;
9
10
  sessionToken: string;
10
11
  userUUID: string;
11
12
  }
12
- export declare type Options = {
13
+ export interface StartOptions {
14
+ userID?: string;
15
+ forceNew: boolean;
16
+ }
17
+ declare type AppOptions = {
13
18
  revID: string;
14
19
  node_id: string;
15
20
  session_token_key: string;
16
21
  session_pageno_key: string;
22
+ session_reset_key: string;
17
23
  local_uuid_key: string;
18
24
  ingestPoint: string;
19
25
  resourceBaseHref: string | null;
@@ -21,7 +27,8 @@ export declare type Options = {
21
27
  __debug_report_edp: string | null;
22
28
  __debug_log: boolean;
23
29
  onStart?: (info: OnStartInfo) => void;
24
- } & ObserverOptions & WebworkerOptions;
30
+ } & WebworkerOptions;
31
+ export declare type Options = AppOptions & ObserverOptions & SanitizerOptions;
25
32
  declare type Callback = () => void;
26
33
  declare type CommitCallback = (messages: Array<Message>) => void;
27
34
  export declare const DEFAULT_INGEST_POINT = "https://api.openreplay.com/ingest";
@@ -29,18 +36,20 @@ export default class App {
29
36
  readonly nodes: Nodes;
30
37
  readonly ticker: Ticker;
31
38
  readonly projectKey: string;
39
+ readonly sanitizer: Sanitizer;
32
40
  private readonly messages;
33
- readonly observer: Observer;
41
+ private readonly observer;
34
42
  private readonly startCallbacks;
35
43
  private readonly stopCallbacks;
36
44
  private readonly commitCallbacks;
37
45
  private readonly options;
38
46
  private readonly revID;
39
47
  private _sessionID;
48
+ private _userID;
40
49
  private isActive;
41
50
  private version;
42
51
  private readonly worker?;
43
- constructor(projectKey: string, sessionToken: string | null | undefined, opts: Partial<Options>);
52
+ constructor(projectKey: string, sessionToken: string | null | undefined, options: Partial<Options>);
44
53
  private _debug;
45
54
  send(message: Message, urgent?: boolean): void;
46
55
  private commit;
@@ -58,8 +67,9 @@ export default class App {
58
67
  resolveResourceURL(resourceURL: string): string;
59
68
  isServiceURL(url: string): boolean;
60
69
  active(): boolean;
70
+ resetNextPageSession(flag: boolean): void;
61
71
  private _start;
62
- start(reset?: boolean): Promise<OnStartInfo>;
72
+ start(options?: StartOptions): Promise<OnStartInfo>;
63
73
  stop(): void;
64
74
  }
65
75
  export {};
package/lib/app/index.js CHANGED
@@ -2,45 +2,45 @@ import { timestamp, log, warn } from "../utils.js";
2
2
  import { Timestamp } from "../messages/index.js";
3
3
  import Nodes from "./nodes.js";
4
4
  import Observer from "./observer/top_observer.js";
5
+ import Sanitizer from "./sanitizer.js";
5
6
  import Ticker from "./ticker.js";
6
7
  import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
7
8
  // TODO: use backendHost only
8
9
  export const DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
9
10
  export default class App {
10
- constructor(projectKey, sessionToken, opts) {
11
+ constructor(projectKey, sessionToken, options) {
11
12
  this.messages = [];
12
13
  this.startCallbacks = [];
13
14
  this.stopCallbacks = [];
14
15
  this.commitCallbacks = [];
15
16
  this._sessionID = null;
16
17
  this.isActive = false;
17
- this.version = '3.4.15';
18
+ this.version = '3.4.17';
18
19
  this.projectKey = projectKey;
19
20
  this.options = Object.assign({
20
21
  revID: '',
21
22
  node_id: '__openreplay_id',
22
23
  session_token_key: '__openreplay_token',
23
24
  session_pageno_key: '__openreplay_pageno',
25
+ session_reset_key: '__openreplay_reset',
24
26
  local_uuid_key: '__openreplay_uuid',
25
27
  ingestPoint: DEFAULT_INGEST_POINT,
26
28
  resourceBaseHref: null,
27
29
  __is_snippet: false,
28
30
  __debug_report_edp: null,
29
31
  __debug_log: false,
30
- obscureTextEmails: true,
31
- obscureTextNumbers: false,
32
- captureIFrames: false,
33
- }, opts);
32
+ }, options);
34
33
  if (sessionToken != null) {
35
34
  sessionStorage.setItem(this.options.session_token_key, sessionToken);
36
35
  }
37
36
  this.revID = this.options.revID;
37
+ this.sanitizer = new Sanitizer(this, options);
38
38
  this.nodes = new Nodes(this.options.node_id);
39
- this.observer = new Observer(this, this.options);
39
+ this.observer = new Observer(this, options);
40
40
  this.ticker = new Ticker(this);
41
41
  this.ticker.attach(() => this.commit());
42
42
  try {
43
- this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}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=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st=1e6,it=2e5,nt=new tt(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}let lt=null;const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(at||""===rt||""===et)return;const t=nt.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),at=!0,dt()}function St(){et="",rt="",null!==lt&&(clearInterval(lt),lt=null),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ft)),nt.checkpoint(),!i.encode(nt)&&(vt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new tt(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null===lt&&(lt=setInterval(vt,1e4))));vt()};
43
+ this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}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=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st=1e6,it=2e5,nt=new tt(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}let lt=null;const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(at||""===rt||""===et)return;const t=nt.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return pt=!1,St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),at=!0,dt()}function St(){et="",rt="",null!==lt&&(clearInterval(lt),lt=null),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ft)),nt.checkpoint(),!i.encode(nt)&&(vt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new tt(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null===lt&&(lt=setInterval(vt,1e4))));vt()};
44
44
  `], { type: 'text/javascript' })));
45
45
  this.worker.onerror = e => {
46
46
  this._debug("webworker_error", e);
@@ -53,7 +53,10 @@ export default class App {
53
53
  }
54
54
  else if (data === "restart") {
55
55
  this.stop();
56
- this.start(true);
56
+ this.start({
57
+ forceNew: true,
58
+ userID: this._userID,
59
+ });
57
60
  }
58
61
  };
59
62
  const alertWorker = () => {
@@ -178,114 +181,126 @@ export default class App {
178
181
  active() {
179
182
  return this.isActive;
180
183
  }
181
- _start(reset) {
182
- if (!this.isActive) {
183
- if (!this.worker) {
184
- return Promise.reject("No worker found: perhaps, CSP is not set.");
184
+ resetNextPageSession(flag) {
185
+ if (flag) {
186
+ sessionStorage.setItem(this.options.session_reset_key, 't');
187
+ }
188
+ else {
189
+ sessionStorage.removeItem(this.options.session_reset_key);
190
+ }
191
+ }
192
+ _start(startOpts) {
193
+ if (!this.worker) {
194
+ return Promise.reject("No worker found: perhaps, CSP is not set.");
195
+ }
196
+ if (this.isActive) {
197
+ return Promise.reject("OpenReplay: trying to call `start()` on the instance that has been started already.");
198
+ }
199
+ this.isActive = true;
200
+ let pageNo = 0;
201
+ const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
202
+ if (pageNoStr != null) {
203
+ pageNo = parseInt(pageNoStr);
204
+ pageNo++;
205
+ }
206
+ sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
207
+ const startTimestamp = timestamp();
208
+ const messageData = {
209
+ ingestPoint: this.options.ingestPoint,
210
+ pageNo,
211
+ startTimestamp,
212
+ connAttemptCount: this.options.connAttemptCount,
213
+ connAttemptGap: this.options.connAttemptGap,
214
+ };
215
+ this.worker.postMessage(messageData); // brings delay of 10th ms?
216
+ // let token = sessionStorage.getItem(this.options.session_token_key)
217
+ // const tokenIsActive = localStorage.getItem("__or_at_" + token)
218
+ // if (tokenIsActive) {
219
+ // token = null
220
+ // }
221
+ const sReset = sessionStorage.getItem(this.options.session_reset_key);
222
+ sessionStorage.removeItem(this.options.session_reset_key);
223
+ this._userID = startOpts.userID || undefined;
224
+ return window.fetch(this.options.ingestPoint + '/v1/web/start', {
225
+ method: 'POST',
226
+ headers: {
227
+ 'Content-Type': 'application/json',
228
+ },
229
+ body: JSON.stringify({
230
+ token: sessionStorage.getItem(this.options.session_token_key),
231
+ userUUID: localStorage.getItem(this.options.local_uuid_key),
232
+ projectKey: this.projectKey,
233
+ revID: this.revID,
234
+ timestamp: startTimestamp,
235
+ trackerVersion: this.version,
236
+ isSnippet: this.options.__is_snippet,
237
+ deviceMemory,
238
+ jsHeapSizeLimit,
239
+ reset: startOpts.forceNew || sReset !== null,
240
+ userID: this._userID,
241
+ }),
242
+ })
243
+ .then(r => {
244
+ if (r.status === 200) {
245
+ return r.json();
185
246
  }
186
- this.isActive = true;
187
- let pageNo = 0;
188
- const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
189
- if (pageNoStr != null) {
190
- pageNo = parseInt(pageNoStr);
191
- pageNo++;
247
+ else { // TODO: handle canceling && 403
248
+ return r.text().then(text => {
249
+ throw new Error(`Server error: ${r.status}. ${text}`);
250
+ });
192
251
  }
193
- sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
194
- const startTimestamp = timestamp();
195
- const messageData = {
196
- ingestPoint: this.options.ingestPoint,
197
- pageNo,
198
- startTimestamp,
199
- connAttemptCount: this.options.connAttemptCount,
200
- connAttemptGap: this.options.connAttemptGap,
201
- };
202
- this.worker.postMessage(messageData); // brings delay of 10th ms?
203
- let token = sessionStorage.getItem(this.options.session_token_key);
204
- const tokenIsActive = localStorage.getItem("__or_at_" + token);
205
- if (tokenIsActive) {
206
- token = null;
252
+ })
253
+ .then(r => {
254
+ const { token, userUUID, sessionID, beaconSizeLimit } = r;
255
+ if (typeof token !== 'string' ||
256
+ typeof userUUID !== 'string' ||
257
+ (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
258
+ throw new Error(`Incorrect server response: ${JSON.stringify(r)}`);
207
259
  }
208
- return window.fetch(this.options.ingestPoint + '/v1/web/start', {
209
- method: 'POST',
210
- headers: {
211
- 'Content-Type': 'application/json',
212
- },
213
- body: JSON.stringify({
214
- token,
215
- userUUID: localStorage.getItem(this.options.local_uuid_key),
216
- projectKey: this.projectKey,
217
- revID: this.revID,
218
- timestamp: startTimestamp,
219
- trackerVersion: this.version,
220
- isSnippet: this.options.__is_snippet,
221
- deviceMemory,
222
- jsHeapSizeLimit,
223
- reset,
224
- }),
225
- })
226
- .then(r => {
227
- if (r.status === 200) {
228
- return r.json();
229
- }
230
- else { // TODO: handle canceling && 403
231
- return r.text().then(text => {
232
- throw new Error(`Server error: ${r.status}. ${text}`);
233
- });
234
- }
235
- })
236
- .then(r => {
237
- const { token, userUUID, sessionID, beaconSizeLimit } = r;
238
- if (typeof token !== 'string' ||
239
- typeof userUUID !== 'string' ||
240
- (typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
241
- throw new Error(`Incorrect server response: ${JSON.stringify(r)}`);
242
- }
243
- sessionStorage.setItem(this.options.session_token_key, token);
244
- localStorage.setItem(this.options.local_uuid_key, userUUID);
245
- localStorage.setItem("__or_at_" + token, "true");
246
- this.attachEventListener(window, 'beforeunload', () => {
247
- localStorage.removeItem("__or_at_" + token);
248
- }, false);
249
- this.attachEventListener(window, 'pagehide', () => {
250
- localStorage.removeItem("__or_at_" + token);
251
- }, false);
252
- if (typeof sessionID === 'string') {
253
- this._sessionID = sessionID;
254
- }
255
- if (!this.worker) {
256
- throw new Error("no worker found after start request (this might not happen)");
257
- }
258
- this.worker.postMessage({ token, beaconSizeLimit });
259
- this.startCallbacks.forEach((cb) => cb());
260
- this.observer.observe();
261
- this.ticker.start();
262
- log("OpenReplay tracking started.");
263
- const onStartInfo = { sessionToken: token, userUUID, sessionID };
264
- if (typeof this.options.onStart === 'function') {
265
- this.options.onStart(onStartInfo);
266
- }
267
- return onStartInfo;
268
- })
269
- .catch(e => {
270
- sessionStorage.removeItem(this.options.session_token_key);
271
- this.stop();
272
- warn("OpenReplay was unable to start. ", e);
273
- this._debug("session_start", e);
274
- throw e;
275
- });
276
- }
277
- return Promise.reject("Player is already active");
260
+ sessionStorage.setItem(this.options.session_token_key, token);
261
+ localStorage.setItem(this.options.local_uuid_key, userUUID);
262
+ // localStorage.setItem("__or_at_" + token, "true")
263
+ // this.attachEventListener(window, 'beforeunload', ()=>{
264
+ // localStorage.removeItem("__or_at_" + token)
265
+ // }, false);
266
+ // this.attachEventListener(window, 'pagehide', ()=>{
267
+ // localStorage.removeItem("__or_at_" + token)
268
+ // }, false);
269
+ if (typeof sessionID === 'string') {
270
+ this._sessionID = sessionID;
271
+ }
272
+ if (!this.worker) {
273
+ throw new Error("no worker found after start request (this might not happen)");
274
+ }
275
+ this.worker.postMessage({ token, beaconSizeLimit });
276
+ this.startCallbacks.forEach((cb) => cb());
277
+ this.observer.observe();
278
+ this.ticker.start();
279
+ log("OpenReplay tracking started.");
280
+ const onStartInfo = { sessionToken: token, userUUID, sessionID };
281
+ if (typeof this.options.onStart === 'function') {
282
+ this.options.onStart(onStartInfo);
283
+ }
284
+ return onStartInfo;
285
+ })
286
+ .catch(e => {
287
+ sessionStorage.removeItem(this.options.session_token_key);
288
+ this.stop();
289
+ warn("OpenReplay was unable to start. ", e);
290
+ this._debug("session_start", e);
291
+ throw e;
292
+ });
278
293
  }
279
- start(reset = false) {
294
+ start(options = { forceNew: false }) {
280
295
  if (!document.hidden) {
281
- return this._start(reset);
296
+ return this._start(options);
282
297
  }
283
298
  else {
284
299
  return new Promise((resolve) => {
285
300
  const onVisibilityChange = () => {
286
301
  if (!document.hidden) {
287
302
  document.removeEventListener("visibilitychange", onVisibilityChange);
288
- resolve(this._start(reset));
303
+ resolve(this._start(options));
289
304
  }
290
305
  };
291
306
  document.addEventListener("visibilitychange", onVisibilityChange);
@@ -298,6 +313,7 @@ export default class App {
298
313
  if (this.worker) {
299
314
  this.worker.postMessage("stop");
300
315
  }
316
+ this.sanitizer.clear();
301
317
  this.observer.disconnect();
302
318
  this.nodes.clear();
303
319
  this.ticker.stop();
@@ -1,25 +1,5 @@
1
1
  import App from "../index.js";
2
- export interface Window extends globalThis.Window {
3
- HTMLInputElement: typeof HTMLInputElement;
4
- HTMLLinkElement: typeof HTMLLinkElement;
5
- HTMLStyleElement: typeof HTMLStyleElement;
6
- SVGStyleElement: typeof SVGStyleElement;
7
- HTMLIFrameElement: typeof HTMLIFrameElement;
8
- Text: typeof Text;
9
- Element: typeof Element;
10
- ShadowRoot: typeof ShadowRoot;
11
- }
12
- declare type WindowConstructor = Document | Element | Text | ShadowRoot | HTMLInputElement | HTMLLinkElement | HTMLStyleElement | HTMLIFrameElement;
13
- declare type Constructor<T> = {
14
- new (...args: any[]): T;
15
- name: string;
16
- };
17
- export declare function isInstance<T extends WindowConstructor>(node: Node, constr: Constructor<T>): node is T;
18
- export interface Options {
19
- obscureTextEmails: boolean;
20
- obscureTextNumbers: boolean;
21
- }
22
- export default abstract class Observer<AdditionalOptions = {}> {
2
+ export default abstract class Observer {
23
3
  protected readonly app: App;
24
4
  protected readonly context: Window;
25
5
  private readonly observer;
@@ -29,14 +9,10 @@ export default abstract class Observer<AdditionalOptions = {}> {
29
9
  private readonly indexes;
30
10
  private readonly attributesList;
31
11
  private readonly textSet;
32
- private readonly textMasked;
33
- protected readonly options: Options & AdditionalOptions;
34
12
  private readonly inUpperContext;
35
- constructor(app: App, options: Partial<Options> & AdditionalOptions, context?: Window);
13
+ constructor(app: App, context?: Window);
36
14
  private clear;
37
15
  private sendNodeAttribute;
38
- getInnerTextSecure(el: HTMLElement): string;
39
- private checkObscure;
40
16
  private sendNodeData;
41
17
  private bindNode;
42
18
  private bindTree;
@@ -47,4 +23,3 @@ export default abstract class Observer<AdditionalOptions = {}> {
47
23
  protected observeRoot(node: Node, beforeCommit: (id?: number) => unknown, nodeToBind?: Node): void;
48
24
  disconnect(): void;
49
25
  }
50
- export {};
@@ -1,30 +1,8 @@
1
- import { stars, hasOpenreplayAttribute } from "../../utils.js";
2
1
  import { RemoveNodeAttribute, SetNodeAttribute, SetNodeAttributeURLBased, SetCSSDataURLBased, SetNodeData, CreateTextNode, CreateElementNode, MoveNode, RemoveNode, } from "../../messages/index.js";
2
+ import { isInstance, inDocument } from "../context.js";
3
3
  function isSVGElement(node) {
4
4
  return node.namespaceURI === 'http://www.w3.org/2000/svg';
5
5
  }
6
- // TODO: we need a type expert here so we won't have to ignore the lines
7
- // TODO: use it everywhere (static function; export from which file? <-- global Window typing required)
8
- export function isInstance(node, constr) {
9
- const doc = node.ownerDocument;
10
- if (!doc) { // null if Document
11
- return constr.name === 'Document';
12
- }
13
- let context =
14
- // @ts-ignore (for EI, Safary)
15
- doc.parentWindow ||
16
- doc.defaultView; // TODO: smart global typing for Window object
17
- while (context.parent && context.parent !== context) {
18
- // @ts-ignore
19
- if (node instanceof context[constr.name]) {
20
- return true;
21
- }
22
- // @ts-ignore
23
- context = context.parent;
24
- }
25
- // @ts-ignore
26
- return node instanceof context[constr.name];
27
- }
28
6
  function isIgnored(node) {
29
7
  if (isInstance(node, Text)) {
30
8
  return false;
@@ -54,7 +32,7 @@ function isObservable(node) {
54
32
  return !isIgnored(node);
55
33
  }
56
34
  export default class Observer {
57
- constructor(app, options, context = window) {
35
+ constructor(app, context = window) {
58
36
  this.app = app;
59
37
  this.context = context;
60
38
  this.commited = [];
@@ -63,34 +41,12 @@ export default class Observer {
63
41
  this.indexes = [];
64
42
  this.attributesList = [];
65
43
  this.textSet = new Set();
66
- this.textMasked = new Set();
67
- this.options = Object.assign({
68
- obscureTextEmails: true,
69
- obscureTextNumbers: false,
70
- }, options);
71
- this.inUpperContext = context.parent === context;
44
+ this.inUpperContext = context.parent === context; //TODO: get rid of context here
72
45
  this.observer = new MutationObserver(this.app.safe((mutations) => {
73
46
  for (const mutation of mutations) {
74
47
  const target = mutation.target;
75
48
  const type = mutation.type;
76
- // TODO TODO TODO: move to iframe_observer/remove??? (check if )
77
- // Special case
78
- // 'childList' on Document might happen in case of iframe.
79
- // TODO: generalize as much as possible
80
- // if (isInstance(target, Document) // Also ShadowRoot can be here
81
- // && type === 'childList'
82
- // //&& new Array(mutation.addedNodes).some(node => isInstance(node, HTMLHtmlElement))
83
- // ) {
84
- // const parentFrame = target.defaultView?.frameElement
85
- // if (!parentFrame) { continue }
86
- // this.bindTree(target.documentElement)
87
- // const frameID = this.app.nodes.getID(parentFrame)
88
- // const docID = this.app.nodes.getID(target.documentElement)
89
- // if (frameID === undefined || docID === undefined) { continue }
90
- // this.app.send(CreateIFrameDocument(frameID, docID));
91
- // continue;
92
- // }
93
- if (!isObservable(target) || !context.document.contains(target)) {
49
+ if (!isObservable(target) || !inDocument(target)) {
94
50
  continue;
95
51
  }
96
52
  if (type === 'childList') {
@@ -135,7 +91,6 @@ export default class Observer {
135
91
  this.indexes.length = 1;
136
92
  this.attributesList.length = 0;
137
93
  this.textSet.clear();
138
- //this.textMasked.clear();
139
94
  }
140
95
  sendNodeAttribute(id, node, name, value) {
141
96
  if (isSVGElement(node)) {
@@ -184,35 +139,14 @@ export default class Observer {
184
139
  }
185
140
  this.app.send(new SetNodeAttribute(id, name, value));
186
141
  }
187
- /* TODO: abstract sanitation */
188
- getInnerTextSecure(el) {
189
- const id = this.app.nodes.getID(el);
190
- if (!id) {
191
- return '';
192
- }
193
- return this.checkObscure(id, el.innerText);
194
- }
195
- checkObscure(id, data) {
196
- if (this.textMasked.has(id)) {
197
- return data.replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
198
- }
199
- if (this.options.obscureTextNumbers) {
200
- data = data.replace(/\d/g, '0');
201
- }
202
- if (this.options.obscureTextEmails) {
203
- data = data.replace(/([^\s]+)@([^\s]+)\.([^\s]+)/g, (...f) => stars(f[1]) + '@' + stars(f[2]) + '.' + stars(f[3]));
204
- }
205
- return data;
206
- }
207
142
  sendNodeData(id, parentElement, data) {
208
143
  if (isInstance(parentElement, HTMLStyleElement) || isInstance(parentElement, SVGStyleElement)) {
209
144
  this.app.send(new SetCSSDataURLBased(id, data, this.app.getBaseHref()));
210
145
  return;
211
146
  }
212
- data = this.checkObscure(id, data);
147
+ data = this.app.sanitizer.sanitize(id, data);
213
148
  this.app.send(new SetNodeData(id, data));
214
149
  }
215
- /* end TODO: abstract sanitation */
216
150
  bindNode(node) {
217
151
  const r = this.app.nodes.registerNode(node);
218
152
  const id = r[0];
@@ -264,10 +198,7 @@ export default class Observer {
264
198
  this.unbindNode(node);
265
199
  return false;
266
200
  }
267
- if (this.textMasked.has(parentID) ||
268
- (isInstance(node, Element) && hasOpenreplayAttribute(node, 'masked'))) {
269
- this.textMasked.add(id);
270
- }
201
+ this.app.sanitizer.handleNode(id, parentID, node);
271
202
  }
272
203
  let sibling = node.previousSibling;
273
204
  while (sibling !== null) {
@@ -340,8 +271,7 @@ export default class Observer {
340
271
  let node;
341
272
  for (let id = 0; id < this.recents.length; id++) {
342
273
  // TODO: make things/logic nice here.
343
- // commit required in any case if recents[id] true or false (in case of unbinding).
344
- // ???!?!?R@TW:$HKJ$WLKn
274
+ // commit required in any case if recents[id] true or false (in case of unbinding) or undefined (in case of attr change).
345
275
  if (!this.myNodes[id]) {
346
276
  continue;
347
277
  }
@@ -369,8 +299,6 @@ export default class Observer {
369
299
  disconnect() {
370
300
  this.observer.disconnect();
371
301
  this.clear();
372
- // to sanitizer
373
- this.textMasked.clear();
374
302
  this.myNodes.length = 0;
375
303
  }
376
304
  }
@@ -1,10 +1,10 @@
1
1
  import Observer from "./observer.js";
2
- import type { Options as BaseOptions } from "./observer.js";
3
2
  import App from "../index.js";
4
- export interface Options extends Partial<BaseOptions> {
3
+ export interface Options {
5
4
  captureIFrames: boolean;
6
5
  }
7
- export default class TopObserver extends Observer<Options> {
6
+ export default class TopObserver extends Observer {
7
+ private readonly options;
8
8
  constructor(app: App, options: Partial<Options>);
9
9
  private iframeObservers;
10
10
  private handleIframe;