@openreplay/tracker 3.5.13-beta.0 → 3.5.15-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/app/guards.d.ts +2 -1
- package/cjs/app/guards.js +1 -1
- package/cjs/app/index.d.ts +1 -1
- package/cjs/app/index.js +37 -18
- package/cjs/app/nodes.d.ts +4 -3
- package/cjs/app/nodes.js +5 -2
- package/cjs/app/observer/observer.d.ts +2 -3
- package/cjs/app/observer/observer.js +65 -36
- package/cjs/app/sanitizer.d.ts +3 -1
- package/cjs/app/sanitizer.js +12 -1
- package/cjs/app/session.d.ts +2 -7
- package/cjs/app/session.js +24 -37
- package/cjs/index.js +2 -2
- package/cjs/modules/img.js +35 -9
- package/cjs/modules/input.d.ts +1 -0
- package/cjs/modules/input.js +5 -8
- package/cjs/modules/scroll.js +6 -5
- package/cjs/utils.js +1 -1
- package/lib/app/guards.d.ts +2 -1
- package/lib/app/guards.js +1 -1
- package/lib/app/index.d.ts +1 -1
- package/lib/app/index.js +38 -19
- package/lib/app/nodes.d.ts +4 -3
- package/lib/app/nodes.js +5 -2
- package/lib/app/observer/observer.d.ts +2 -3
- package/lib/app/observer/observer.js +65 -36
- package/lib/app/sanitizer.d.ts +3 -1
- package/lib/app/sanitizer.js +12 -1
- package/lib/app/session.d.ts +2 -7
- package/lib/app/session.js +24 -37
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.js +2 -2
- package/lib/modules/img.js +35 -9
- package/lib/modules/input.d.ts +1 -0
- package/lib/modules/input.js +5 -8
- package/lib/modules/scroll.js +6 -5
- package/lib/utils.js +1 -1
- package/package.json +8 -8
package/cjs/app/guards.d.ts
CHANGED
|
@@ -10,7 +10,8 @@ declare type TagTypeMap = {
|
|
|
10
10
|
SELECT: HTMLSelectElement;
|
|
11
11
|
LABEL: HTMLLabelElement;
|
|
12
12
|
IFRAME: HTMLIFrameElement;
|
|
13
|
-
STYLE: HTMLStyleElement
|
|
13
|
+
STYLE: HTMLStyleElement;
|
|
14
|
+
style: SVGStyleElement;
|
|
14
15
|
LINK: HTMLLinkElement;
|
|
15
16
|
};
|
|
16
17
|
export declare function hasTag<T extends keyof TagTypeMap>(el: Node, tagName: T): el is TagTypeMap[typeof tagName];
|
package/cjs/app/guards.js
CHANGED
package/cjs/app/index.d.ts
CHANGED
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 = '3.5.
|
|
35
|
+
this.version = '3.5.15-beta.0'; // TODO: version compatability check inside each plugin.
|
|
36
36
|
this.projectKey = projectKey;
|
|
37
37
|
this.options = Object.assign({
|
|
38
38
|
revID: '',
|
|
@@ -57,14 +57,22 @@ class App {
|
|
|
57
57
|
this.ticker.attach(() => this.commit());
|
|
58
58
|
this.debug = new logger_js_1.default(this.options.__debug__);
|
|
59
59
|
this.notify = new logger_js_1.default(this.options.verbose ? logger_js_1.LogLevel.Warnings : logger_js_1.LogLevel.Silent);
|
|
60
|
-
this.session = new session_js_1.default(
|
|
60
|
+
this.session = new session_js_1.default();
|
|
61
|
+
this.session.attachUpdateCallback(({ userID, metadata }) => {
|
|
62
|
+
if (userID != null) { // TODO: nullable userID
|
|
63
|
+
this.send(new messages_js_1.UserID(userID));
|
|
64
|
+
}
|
|
65
|
+
if (metadata != null) {
|
|
66
|
+
Object.entries(metadata).forEach(([key, value]) => this.send(new messages_js_1.Metadata(key, value)));
|
|
67
|
+
}
|
|
68
|
+
});
|
|
61
69
|
this.localStorage = this.options.localStorage;
|
|
62
70
|
this.sessionStorage = this.options.sessionStorage;
|
|
63
71
|
if (sessionToken != null) {
|
|
64
72
|
this.sessionStorage.setItem(this.options.session_token_key, sessionToken);
|
|
65
73
|
}
|
|
66
74
|
try {
|
|
67
|
-
this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function i(...i){return new t(...i)}return i.prototype=t.prototype,i}const i=new Map;const s=t(class{constructor(t,i,s){this.pageNo=t,this.firstIndex=i,this.timestamp=s,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});i.set(80,s);const e=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});i.set(0,e);const n=t(class{constructor(t,i,s){this.url=t,this.referrer=i,this.navigationStart=s,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});i.set(4,n);const r=t(class{constructor(t,i){this.width=t,this.height=i,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});i.set(5,r);const h=t(class{constructor(t,i){this.x=t,this.y=i,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});i.set(6,h);const o=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});i.set(7,o);const c=t(class{constructor(t,i,s,e,n){this.id=t,this.parentID=i,this.index=s,this.tag=e,this.svg=n,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)}});i.set(8,c);const a=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(9,a);const u=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(10,u);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});i.set(11,d);const l=t(class{constructor(t,i,s){this.id=t,this.name=i,this.value=s,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});i.set(12,l);const p=t(class{constructor(t,i){this.id=t,this.name=i,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});i.set(13,p);const m=t(class{constructor(t,i){this.id=t,this.data=i,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});i.set(14,m);const g=t(class{constructor(t,i,s){this.id=t,this.x=i,this.y=s,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});i.set(16,g);const f=t(class{constructor(t,i){this.id=t,this.label=i,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});i.set(17,f);const y=t(class{constructor(t,i,s){this.id=t,this.value=i,this.mask=s,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});i.set(18,y);const _=t(class{constructor(t,i){this.id=t,this.checked=i,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});i.set(19,_);const v=t(class{constructor(t,i){this.x=t,this.y=i,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});i.set(20,v);const b=t(class{constructor(t,i){this.level=t,this.value=i,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});i.set(22,b);const S=t(class{constructor(t,i,s,e,n,r,h,o,c){this.requestStart=t,this.responseStart=i,this.responseEnd=s,this.domContentLoadedEventStart=e,this.domContentLoadedEventEnd=n,this.loadEventStart=r,this.loadEventEnd=h,this.firstPaint=o,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)}});i.set(23,S);const w=t(class{constructor(t,i,s){this.speedIndex=t,this.visuallyComplete=i,this.timeToInteractive=s,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});i.set(24,w);const E=t(class{constructor(t,i,s){this.name=t,this.message=i,this.payload=s,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});i.set(25,E);const x=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});i.set(27,x);const T=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});i.set(28,T);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});i.set(29,z);const k=t(class{constructor(t,i){this.key=t,this.value=i,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});i.set(30,k);const I=t(class{constructor(t,i,s){this.id=t,this.rule=i,this.index=s,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});i.set(37,I);const M=t(class{constructor(t,i){this.id=t,this.index=i,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});i.set(38,M);const B=t(class{constructor(t,i,s,e,n,r,h){this.method=t,this.url=i,this.request=s,this.response=e,this.status=n,this.timestamp=r,this.duration=h,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)}});i.set(39,B);const L=t(class{constructor(t,i,s,e){this.name=t,this.duration=i,this.args=s,this.result=e,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)}});i.set(40,L);const C=t(class{constructor(t,i){this.key=t,this.value=i,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});i.set(41,C);const A=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});i.set(42,A);const U=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(44,U);const N=t(class{constructor(t,i){this.mutation=t,this.state=i,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});i.set(45,N);const R=t(class{constructor(t,i){this.type=t,this.payload=i,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});i.set(46,R);const O=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(47,O);const P=t(class{constructor(t,i,s,e){this.operationKind=t,this.operationName=i,this.variables=s,this.response=e,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)}});i.set(48,P);const q=t(class{constructor(t,i,s,e){this.frames=t,this.ticks=i,this.totalJSHeapSize=s,this.usedJSHeapSize=e,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)}});i.set(49,q);const D=t(class{constructor(t,i,s,e,n,r,h,o){this.timestamp=t,this.duration=i,this.ttfb=s,this.headerSize=e,this.encodedBodySize=n,this.decodedBodySize=r,this.url=h,this.initiator=o,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)}});i.set(53,D);const W=t(class{constructor(t,i){this.downlink=t,this.type=i,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});i.set(54,W);const H=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});i.set(55,H);const J=t(class{constructor(t,i,s,e,n,r,h){this.timestamp=t,this.duration=i,this.context=s,this.containerType=e,this.containerSrc=n,this.containerId=r,this.containerName=h,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)}});i.set(59,J);const F=t(class{constructor(t,i,s,e){this.id=t,this.name=i,this.value=s,this.baseURL=e,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)}});i.set(60,F);const X=t(class{constructor(t,i,s){this.id=t,this.data=i,this.baseURL=s,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});i.set(61,X);const G=t(class{constructor(t,i){this.type=t,this.value=i,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});i.set(63,G);const K=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});i.set(64,K);const j=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});i.set(65,j);const Q=t(class{constructor(t,i,s,e){this.id=t,this.rule=i,this.index=s,this.baseURL=e,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)}});i.set(67,Q);const V=t(class{constructor(t,i,s,e){this.id=t,this.hesitationTime=i,this.label=s,this.selector=e,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)}});i.set(69,V);const Y=t(class{constructor(t,i){this.frameID=t,this.id=i,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});i.set(70,Y);class Z{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 tt="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(var 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))>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(h+=1,(n=1024*(n-55296)+r-56320+65536)>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 it{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 i=tt.encode(t),s=i.byteLength;return!(!this.uint(s)||this.offset+s>this.size)&&(this.data.set(i,this.offset),this.offset+=s,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class st{constructor(t,i,s){this.pageNo=t,this.timestamp=i,this.onBatch=s,this.nextIndex=0,this.beaconSize=2e5,this.writer=new it(this.beaconSize),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepareBatchMeta()}prepareBatchMeta(){return new s(this.pageNo,this.nextIndex,this.timestamp).encode(this.writer)}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(t instanceof e&&(this.timestamp=t.timestamp),!t.encode(this.writer))for(this.isEmpty||(this.onBatch(this.writer.flush()),this.prepareBatchMeta());!t.encode(this.writer);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message."),this.writer.reset(),this.prepareBatchMeta(),void(this.isEmpty=!0);this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.writer=new it(this.beaconSize),this.prepareBatchMeta()}this.writer.checkpoint(),this.nextIndex++,this.isEmpty=!1}finaliseBatch(){this.isEmpty||(this.onBatch(this.writer.flush()),this.prepareBatchMeta(),this.isEmpty=!0)}clean(){this.writer.reset()}}let et=null,nt=null;function rt(){nt&&nt.finaliseBatch()}function ht(){null!==ct&&(clearInterval(ct),ct=null),nt&&(nt.clean(),nt=null)}let ot,ct=null;self.onmessage=({data:t})=>{if(null!=t){if("stop"===t)return rt(),void ht();if(Array.isArray(t)){if(!nt)throw new Error("WebWorker: writer not initialised.");const s=nt;t.forEach(t=>{const e=new(i.get(t._id));Object.assign(e,t),e instanceof H&&(e.hidden?ot=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ot)),s.writeMessage(e)})}else{if("start"===t.type)return et=new Z(t.ingestPoint,()=>{self.postMessage("restart")},()=>{et&&(et.clean(),et=null),ht(),self.postMessage("failed")},t.connAttemptCount,t.connAttemptGap),nt=new st(t.pageNo,t.timestamp,t=>et&&et.push(t)),void(null===ct&&(ct=setInterval(rt,1e4)));if("auth"===t.type){if(!et)throw new Error("WebWorker: sender not initialised. Recieved auth.");if(!nt)throw new Error("WebWorker: writer not initialised. Recieved auth.");return et.authorise(t.token),void(t.beaconSizeLimit&&nt.setBeaconSizeLimit(t.beaconSizeLimit))}}}else rt()};
|
|
75
|
+
this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function i(...i){return new t(...i)}return i.prototype=t.prototype,i}const i=new Map;const s=t(class{constructor(t,i,s){this.pageNo=t,this.firstIndex=i,this.timestamp=s,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});i.set(80,s);const e=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});i.set(0,e);const n=t(class{constructor(t,i,s){this.url=t,this.referrer=i,this.navigationStart=s,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});i.set(4,n);const r=t(class{constructor(t,i){this.width=t,this.height=i,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});i.set(5,r);const h=t(class{constructor(t,i){this.x=t,this.y=i,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});i.set(6,h);const o=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});i.set(7,o);const c=t(class{constructor(t,i,s,e,n){this.id=t,this.parentID=i,this.index=s,this.tag=e,this.svg=n,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)}});i.set(8,c);const a=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(9,a);const u=t(class{constructor(t,i,s){this.id=t,this.parentID=i,this.index=s,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});i.set(10,u);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});i.set(11,d);const l=t(class{constructor(t,i,s){this.id=t,this.name=i,this.value=s,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});i.set(12,l);const p=t(class{constructor(t,i){this.id=t,this.name=i,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});i.set(13,p);const g=t(class{constructor(t,i){this.id=t,this.data=i,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});i.set(14,g);const m=t(class{constructor(t,i,s){this.id=t,this.x=i,this.y=s,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});i.set(16,m);const f=t(class{constructor(t,i){this.id=t,this.label=i,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});i.set(17,f);const y=t(class{constructor(t,i,s){this.id=t,this.value=i,this.mask=s,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});i.set(18,y);const _=t(class{constructor(t,i){this.id=t,this.checked=i,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});i.set(19,_);const v=t(class{constructor(t,i){this.x=t,this.y=i,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});i.set(20,v);const S=t(class{constructor(t,i){this.level=t,this.value=i,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});i.set(22,S);const b=t(class{constructor(t,i,s,e,n,r,h,o,c){this.requestStart=t,this.responseStart=i,this.responseEnd=s,this.domContentLoadedEventStart=e,this.domContentLoadedEventEnd=n,this.loadEventStart=r,this.loadEventEnd=h,this.firstPaint=o,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)}});i.set(23,b);const w=t(class{constructor(t,i,s){this.speedIndex=t,this.visuallyComplete=i,this.timeToInteractive=s,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});i.set(24,w);const E=t(class{constructor(t,i,s){this.name=t,this.message=i,this.payload=s,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});i.set(25,E);const x=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});i.set(27,x);const T=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});i.set(28,T);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});i.set(29,z);const k=t(class{constructor(t,i){this.key=t,this.value=i,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});i.set(30,k);const A=t(class{constructor(t,i,s){this.id=t,this.rule=i,this.index=s,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});i.set(37,A);const I=t(class{constructor(t,i){this.id=t,this.index=i,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});i.set(38,I);const L=t(class{constructor(t,i,s,e,n,r,h){this.method=t,this.url=i,this.request=s,this.response=e,this.status=n,this.timestamp=r,this.duration=h,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)}});i.set(39,L);const C=t(class{constructor(t,i,s,e){this.name=t,this.duration=i,this.args=s,this.result=e,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)}});i.set(40,C);const M=t(class{constructor(t,i){this.key=t,this.value=i,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});i.set(41,M);const N=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});i.set(42,N);const B=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(44,B);const U=t(class{constructor(t,i){this.mutation=t,this.state=i,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});i.set(45,U);const R=t(class{constructor(t,i){this.type=t,this.payload=i,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});i.set(46,R);const O=t(class{constructor(t,i,s){this.action=t,this.state=i,this.duration=s,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});i.set(47,O);const P=t(class{constructor(t,i,s,e){this.operationKind=t,this.operationName=i,this.variables=s,this.response=e,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)}});i.set(48,P);const q=t(class{constructor(t,i,s,e){this.frames=t,this.ticks=i,this.totalJSHeapSize=s,this.usedJSHeapSize=e,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)}});i.set(49,q);const D=t(class{constructor(t,i,s,e,n,r,h,o){this.timestamp=t,this.duration=i,this.ttfb=s,this.headerSize=e,this.encodedBodySize=n,this.decodedBodySize=r,this.url=h,this.initiator=o,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)}});i.set(53,D);const W=t(class{constructor(t,i){this.downlink=t,this.type=i,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});i.set(54,W);const H=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});i.set(55,H);const J=t(class{constructor(t,i,s,e,n,r,h){this.timestamp=t,this.duration=i,this.context=s,this.containerType=e,this.containerSrc=n,this.containerId=r,this.containerName=h,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)}});i.set(59,J);const F=t(class{constructor(t,i,s,e){this.id=t,this.name=i,this.value=s,this.baseURL=e,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)}});i.set(60,F);const X=t(class{constructor(t,i,s){this.id=t,this.data=i,this.baseURL=s,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});i.set(61,X);const G=t(class{constructor(t,i){this.type=t,this.value=i,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});i.set(63,G);const K=t(class{constructor(t,i){this.name=t,this.payload=i,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});i.set(64,K);const j=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});i.set(65,j);const Q=t(class{constructor(t,i,s,e){this.id=t,this.rule=i,this.index=s,this.baseURL=e,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)}});i.set(67,Q);const V=t(class{constructor(t,i,s,e){this.id=t,this.hesitationTime=i,this.label=s,this.selector=e,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)}});i.set(69,V);const Y=t(class{constructor(t,i){this.frameID=t,this.id=i,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});i.set(70,Y);class Z{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 tt="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(var 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))>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(h+=1,(n=1024*(n-55296)+r-56320+65536)>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 it{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 i=tt.encode(t),s=i.byteLength;return!(!this.uint(s)||this.offset+s>this.size)&&(this.data.set(i,this.offset),this.offset+=s,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}class st{constructor(t,i,s){this.pageNo=t,this.timestamp=i,this.onBatch=s,this.nextIndex=0,this.beaconSize=2e5,this.writer=new it(this.beaconSize),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}prepare(){this.writer.isEmpty()&&new s(this.pageNo,this.nextIndex,this.timestamp).encode(this.writer)}write(t){const i=t.encode(this.writer);return i&&(this.isEmpty=!1,this.writer.checkpoint(),this.nextIndex++),i}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){for(t instanceof e&&(this.timestamp=t.timestamp);!this.write(t);){if(this.finaliseBatch(),this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message."),this.writer.reset(),this.prepare(),void(this.isEmpty=!0);this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.writer=new it(this.beaconSize),this.prepare(),this.isEmpty=!0}}finaliseBatch(){this.isEmpty||(this.onBatch(this.writer.flush()),this.prepare(),this.isEmpty=!0)}clean(){this.writer.reset()}}var et;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(et||(et={}));let nt=null,rt=null;function ht(){rt&&rt.finaliseBatch()}function ot(){et.Stopping,null!==at&&(clearInterval(at),at=null),rt&&(rt.clean(),rt=null),et.NotActive}et.NotActive;let ct,at=null;self.onmessage=({data:t})=>{if(null!=t){if("stop"===t)return ht(),void ot();if(Array.isArray(t)){if(!rt)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const s=rt;t.forEach(t=>{const e=new(i.get(t._id));Object.assign(e,t),e instanceof H&&(e.hidden?ct=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ct)),s.writeMessage(e)})}else{if("start"===t.type)return et.Starting,nt=new Z(t.ingestPoint,()=>{self.postMessage("restart")},()=>{nt&&(nt.clean(),nt=null),ot(),self.postMessage("failed")},t.connAttemptCount,t.connAttemptGap),rt=new st(t.pageNo,t.timestamp,t=>nt&&nt.push(t)),null===at&&(at=setInterval(ht,1e4)),et.Active;if("auth"===t.type){if(!nt)throw new Error("WebWorker: sender not initialised. Received auth.");if(!rt)throw new Error("WebWorker: writer not initialised. Received auth.");return nt.authorise(t.token),void(t.beaconSizeLimit&&rt.setBeaconSizeLimit(t.beaconSizeLimit))}}}else ht()};
|
|
68
76
|
`], { type: 'text/javascript' })));
|
|
69
77
|
this.worker.onerror = e => {
|
|
70
78
|
this._debug("webworker_error", e);
|
|
@@ -72,6 +80,7 @@ class App {
|
|
|
72
80
|
this.worker.onmessage = ({ data }) => {
|
|
73
81
|
if (data === "failed") {
|
|
74
82
|
this.stop();
|
|
83
|
+
this._debug("worker_failed", {}); // add context (from worker)
|
|
75
84
|
}
|
|
76
85
|
else if (data === "restart") {
|
|
77
86
|
this.stop();
|
|
@@ -83,9 +92,10 @@ class App {
|
|
|
83
92
|
this.worker.postMessage(null);
|
|
84
93
|
}
|
|
85
94
|
};
|
|
86
|
-
//
|
|
95
|
+
// keep better tactics, discard others?
|
|
87
96
|
this.attachEventListener(window, 'beforeunload', alertWorker, false);
|
|
88
|
-
this.attachEventListener(document, 'mouseleave', alertWorker, false, false);
|
|
97
|
+
this.attachEventListener(document.body, 'mouseleave', alertWorker, false, false);
|
|
98
|
+
// TODO: stop session after inactivity timeout (make configurable)
|
|
89
99
|
this.attachEventListener(document, 'visibilitychange', alertWorker, false);
|
|
90
100
|
}
|
|
91
101
|
catch (e) {
|
|
@@ -159,8 +169,8 @@ class App {
|
|
|
159
169
|
}
|
|
160
170
|
// TODO: full correct semantic
|
|
161
171
|
checkRequiredVersion(version) {
|
|
162
|
-
const reqVer = version.split(
|
|
163
|
-
const ver = this.version.split(
|
|
172
|
+
const reqVer = version.split(/[.-]/);
|
|
173
|
+
const ver = this.version.split(/[.-]/);
|
|
164
174
|
for (let i = 0; i < 3; i++) {
|
|
165
175
|
if (Number(ver[i]) < Number(reqVer[i]) || isNaN(Number(ver[i])) || isNaN(Number(reqVer[i]))) {
|
|
166
176
|
return false;
|
|
@@ -254,7 +264,13 @@ class App {
|
|
|
254
264
|
connAttemptCount: this.options.connAttemptCount,
|
|
255
265
|
connAttemptGap: this.options.connAttemptGap,
|
|
256
266
|
};
|
|
257
|
-
this.worker.postMessage(startWorkerMsg);
|
|
267
|
+
this.worker.postMessage(startWorkerMsg);
|
|
268
|
+
this.session.update({
|
|
269
|
+
// "updating" with old metadata in order to trigger session's UpdateCallbacks.
|
|
270
|
+
// (for the case of internal .start() calls, like on "restart" webworker signal or assistent connection in tracker-assist )
|
|
271
|
+
metadata: startOpts.metadata || this.session.getInfo().metadata,
|
|
272
|
+
userID: startOpts.userID,
|
|
273
|
+
});
|
|
258
274
|
const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
|
|
259
275
|
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
260
276
|
return window.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
@@ -262,7 +278,7 @@ class App {
|
|
|
262
278
|
headers: {
|
|
263
279
|
'Content-Type': 'application/json',
|
|
264
280
|
},
|
|
265
|
-
body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID:
|
|
281
|
+
body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID: this.session.getInfo().userID, token: this.sessionStorage.getItem(this.options.session_token_key), deviceMemory: performance_js_1.deviceMemory,
|
|
266
282
|
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
|
|
267
283
|
})
|
|
268
284
|
.then(r => {
|
|
@@ -271,7 +287,7 @@ class App {
|
|
|
271
287
|
}
|
|
272
288
|
else {
|
|
273
289
|
return r.text().then(text => text === CANCELED
|
|
274
|
-
? Promise.reject(CANCELED)
|
|
290
|
+
? Promise.reject(CANCELED)
|
|
275
291
|
: Promise.reject(`Server error: ${r.status}. ${text}`));
|
|
276
292
|
}
|
|
277
293
|
})
|
|
@@ -287,20 +303,20 @@ class App {
|
|
|
287
303
|
}
|
|
288
304
|
this.sessionStorage.setItem(this.options.session_token_key, token);
|
|
289
305
|
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
290
|
-
this.session.update(
|
|
291
|
-
this.activityState = ActivityState.Active;
|
|
306
|
+
this.session.update({ sessionID }); // TODO: no no-explicit 'any'
|
|
292
307
|
const startWorkerMsg = {
|
|
293
308
|
type: "auth",
|
|
294
309
|
token,
|
|
295
310
|
beaconSizeLimit
|
|
296
311
|
};
|
|
297
312
|
this.worker.postMessage(startWorkerMsg);
|
|
313
|
+
this.activityState = ActivityState.Active;
|
|
298
314
|
const onStartInfo = { sessionToken: token, userUUID, sessionID };
|
|
299
|
-
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
315
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
|
|
300
316
|
this.observer.observe();
|
|
301
317
|
this.ticker.start();
|
|
302
318
|
this.notify.log("OpenReplay tracking started.");
|
|
303
|
-
//
|
|
319
|
+
// get rid of onStart ?
|
|
304
320
|
if (typeof this.options.onStart === 'function') {
|
|
305
321
|
this.options.onStart(onStartInfo);
|
|
306
322
|
}
|
|
@@ -333,18 +349,21 @@ class App {
|
|
|
333
349
|
});
|
|
334
350
|
}
|
|
335
351
|
}
|
|
336
|
-
stop() {
|
|
352
|
+
stop(calledFromAPI = false) {
|
|
337
353
|
if (this.activityState !== ActivityState.NotActive) {
|
|
338
354
|
try {
|
|
339
|
-
if (this.worker) {
|
|
340
|
-
this.worker.postMessage("stop");
|
|
341
|
-
}
|
|
342
355
|
this.sanitizer.clear();
|
|
343
356
|
this.observer.disconnect();
|
|
344
357
|
this.nodes.clear();
|
|
345
358
|
this.ticker.stop();
|
|
346
359
|
this.stopCallbacks.forEach((cb) => cb());
|
|
360
|
+
if (calledFromAPI) {
|
|
361
|
+
this.session.reset();
|
|
362
|
+
}
|
|
347
363
|
this.notify.log("OpenReplay tracking stopped.");
|
|
364
|
+
if (this.worker) {
|
|
365
|
+
this.worker.postMessage("stop");
|
|
366
|
+
}
|
|
348
367
|
}
|
|
349
368
|
finally {
|
|
350
369
|
this.activityState = ActivityState.NotActive;
|
package/cjs/app/nodes.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
declare type NodeCallback = (node: Node) => void;
|
|
1
|
+
declare type NodeCallback = (node: Node, isStart: boolean) => void;
|
|
2
2
|
export default class Nodes {
|
|
3
3
|
private readonly node_id;
|
|
4
|
-
private
|
|
4
|
+
private nodes;
|
|
5
5
|
private readonly nodeCallbacks;
|
|
6
6
|
private readonly elementListeners;
|
|
7
7
|
constructor(node_id: string);
|
|
@@ -9,7 +9,8 @@ export default class Nodes {
|
|
|
9
9
|
attachElementListener(type: string, node: Element, elementListener: EventListener): void;
|
|
10
10
|
registerNode(node: Node): [id: number, isNew: boolean];
|
|
11
11
|
unregisterNode(node: Node): number | undefined;
|
|
12
|
-
|
|
12
|
+
cleanTree(): (Node | undefined)[];
|
|
13
|
+
callNodeCallbacks(node: Node, isStart: boolean): void;
|
|
13
14
|
getID(node: Node): number | undefined;
|
|
14
15
|
getNode(id: number): Node | undefined;
|
|
15
16
|
clear(): void;
|
package/cjs/app/nodes.js
CHANGED
|
@@ -47,8 +47,11 @@ class Nodes {
|
|
|
47
47
|
}
|
|
48
48
|
return id;
|
|
49
49
|
}
|
|
50
|
-
|
|
51
|
-
this.
|
|
50
|
+
cleanTree() {
|
|
51
|
+
return this.nodes = this.nodes.filter((n) => n !== undefined);
|
|
52
|
+
}
|
|
53
|
+
callNodeCallbacks(node, isStart) {
|
|
54
|
+
this.nodeCallbacks.forEach((cb) => cb(node, isStart));
|
|
52
55
|
}
|
|
53
56
|
getID(node) {
|
|
54
57
|
return node[this.node_id];
|
|
@@ -4,11 +4,10 @@ export default abstract class Observer {
|
|
|
4
4
|
protected readonly isTopContext: boolean;
|
|
5
5
|
private readonly observer;
|
|
6
6
|
private readonly commited;
|
|
7
|
+
private readonly recents;
|
|
7
8
|
private readonly indexes;
|
|
8
|
-
private readonly
|
|
9
|
+
private readonly attributesMap;
|
|
9
10
|
private readonly textSet;
|
|
10
|
-
private readonly newSet;
|
|
11
|
-
private readonly affectedSet;
|
|
12
11
|
constructor(app: App, isTopContext?: boolean);
|
|
13
12
|
private clear;
|
|
14
13
|
private sendNodeAttribute;
|
|
@@ -27,29 +27,40 @@ function isObservable(node) {
|
|
|
27
27
|
}
|
|
28
28
|
return !isIgnored(node);
|
|
29
29
|
}
|
|
30
|
+
/*
|
|
31
|
+
TODO:
|
|
32
|
+
- fix unbinding logic + send all removals first (ensure sequence is correct)
|
|
33
|
+
- use document as a 0-node in the upper context (should be updated in player at first)
|
|
34
|
+
*/
|
|
35
|
+
var RecentsType;
|
|
36
|
+
(function (RecentsType) {
|
|
37
|
+
RecentsType[RecentsType["New"] = 0] = "New";
|
|
38
|
+
RecentsType[RecentsType["Removed"] = 1] = "Removed";
|
|
39
|
+
RecentsType[RecentsType["Changed"] = 2] = "Changed";
|
|
40
|
+
})(RecentsType || (RecentsType = {}));
|
|
30
41
|
class Observer {
|
|
31
42
|
constructor(app, isTopContext = false) {
|
|
32
43
|
this.app = app;
|
|
33
44
|
this.isTopContext = isTopContext;
|
|
34
45
|
this.commited = [];
|
|
46
|
+
this.recents = new Map();
|
|
35
47
|
this.indexes = [];
|
|
36
|
-
this.
|
|
48
|
+
this.attributesMap = new Map();
|
|
37
49
|
this.textSet = new Set();
|
|
38
|
-
this.newSet = new Set();
|
|
39
|
-
this.affectedSet = new Set();
|
|
40
50
|
this.observer = new MutationObserver(this.app.safe((mutations) => {
|
|
41
|
-
for (const mutation of mutations) {
|
|
51
|
+
for (const mutation of mutations) { // mutations order is sequential
|
|
42
52
|
const target = mutation.target;
|
|
43
53
|
const type = mutation.type;
|
|
44
|
-
|
|
54
|
+
// const deleted: number[] = [];
|
|
55
|
+
if (!isObservable(target)) {
|
|
45
56
|
continue;
|
|
46
57
|
}
|
|
47
58
|
if (type === 'childList') {
|
|
48
59
|
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
//
|
|
52
|
-
|
|
60
|
+
// this.bindTree(mutation.removedNodes[i]);
|
|
61
|
+
const id = this.unbindNode(mutation.removedNodes[i]);
|
|
62
|
+
// id && this.recents.delete(id)
|
|
63
|
+
// id && deleted.push(id)
|
|
53
64
|
}
|
|
54
65
|
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
55
66
|
this.bindTree(mutation.addedNodes[i]);
|
|
@@ -60,35 +71,36 @@ class Observer {
|
|
|
60
71
|
if (id === undefined) {
|
|
61
72
|
continue;
|
|
62
73
|
}
|
|
74
|
+
if (!this.recents.has(id)) {
|
|
75
|
+
this.recents.set(id, RecentsType.Changed); // TODO only when altered
|
|
76
|
+
}
|
|
63
77
|
if (type === 'attributes') {
|
|
64
78
|
const name = mutation.attributeName;
|
|
65
79
|
if (name === null) {
|
|
66
80
|
continue;
|
|
67
81
|
}
|
|
68
|
-
let attr = this.
|
|
82
|
+
let attr = this.attributesMap.get(id);
|
|
69
83
|
if (attr === undefined) {
|
|
70
|
-
this.
|
|
84
|
+
this.attributesMap.set(id, attr = new Set());
|
|
71
85
|
}
|
|
72
86
|
attr.add(name);
|
|
73
|
-
this.affectedSet.add(id);
|
|
74
87
|
continue;
|
|
75
88
|
}
|
|
76
89
|
if (type === 'characterData') {
|
|
77
90
|
this.textSet.add(id);
|
|
78
|
-
this.affectedSet.add(id);
|
|
79
91
|
continue;
|
|
80
92
|
}
|
|
81
93
|
}
|
|
82
94
|
this.commitNodes();
|
|
95
|
+
this.app.nodes.cleanTree();
|
|
83
96
|
}));
|
|
84
97
|
}
|
|
85
98
|
clear() {
|
|
86
99
|
this.commited.length = 0;
|
|
100
|
+
this.recents.clear();
|
|
87
101
|
this.indexes.length = 1;
|
|
88
|
-
this.
|
|
102
|
+
this.attributesMap.clear();
|
|
89
103
|
this.textSet.clear();
|
|
90
|
-
this.newSet.clear();
|
|
91
|
-
this.affectedSet.clear();
|
|
92
104
|
}
|
|
93
105
|
sendNodeAttribute(id, node, name, value) {
|
|
94
106
|
if ((0, guards_js_1.isSVGElement)(node)) {
|
|
@@ -138,7 +150,7 @@ class Observer {
|
|
|
138
150
|
this.app.send(new messages_js_1.SetNodeAttribute(id, name, value));
|
|
139
151
|
}
|
|
140
152
|
sendNodeData(id, parentElement, data) {
|
|
141
|
-
if ((0, guards_js_1.hasTag)(parentElement, "STYLE")) {
|
|
153
|
+
if ((0, guards_js_1.hasTag)(parentElement, "STYLE") || (0, guards_js_1.hasTag)(parentElement, "style")) {
|
|
142
154
|
this.app.send(new messages_js_1.SetCSSDataURLBased(id, data, this.app.getBaseHref()));
|
|
143
155
|
return;
|
|
144
156
|
}
|
|
@@ -148,9 +160,11 @@ class Observer {
|
|
|
148
160
|
bindNode(node) {
|
|
149
161
|
const [id, isNew] = this.app.nodes.registerNode(node);
|
|
150
162
|
if (isNew) {
|
|
151
|
-
this.
|
|
163
|
+
this.recents.set(id, RecentsType.New);
|
|
164
|
+
}
|
|
165
|
+
else if (this.recents.get(id) !== RecentsType.New) { // can we do just `else` here?
|
|
166
|
+
this.recents.set(id, RecentsType.Removed);
|
|
152
167
|
}
|
|
153
|
-
this.affectedSet.add(id);
|
|
154
168
|
}
|
|
155
169
|
bindTree(node) {
|
|
156
170
|
if (!isObservable(node)) {
|
|
@@ -170,11 +184,12 @@ class Observer {
|
|
|
170
184
|
}
|
|
171
185
|
unbindNode(node) {
|
|
172
186
|
const id = this.app.nodes.unregisterNode(node);
|
|
173
|
-
|
|
174
|
-
if (id !== undefined && !this.newSet.has(id) && this.affectedSet.has(id)) { // Unbinding logic should be simplified. Node removals should go first.
|
|
187
|
+
if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
|
|
175
188
|
this.app.send(new messages_js_1.RemoveNode(id));
|
|
176
189
|
}
|
|
190
|
+
return id;
|
|
177
191
|
}
|
|
192
|
+
// A top-consumption function on the infinite lists test. (~1% of performance resources)
|
|
178
193
|
_commitNode(id, node) {
|
|
179
194
|
if ((0, guards_js_1.isRootNode)(node)) {
|
|
180
195
|
return true;
|
|
@@ -183,9 +198,11 @@ class Observer {
|
|
|
183
198
|
let parentID;
|
|
184
199
|
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
185
200
|
// TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
|
|
186
|
-
// TODO: Clean the logic (though now it workd fine)
|
|
201
|
+
// TODO: Clean the logic (though now it workd fine)
|
|
187
202
|
if (!(0, guards_js_1.hasTag)(node, "HTML") || !this.isTopContext) {
|
|
188
203
|
if (parent === null) {
|
|
204
|
+
// Sometimes one observation contains attribute mutations for the removimg node, which gets ignored here.
|
|
205
|
+
// That shouldn't affect the visual rendering ( should it? )
|
|
189
206
|
this.unbindNode(node);
|
|
190
207
|
return false;
|
|
191
208
|
}
|
|
@@ -199,7 +216,11 @@ class Observer {
|
|
|
199
216
|
return false;
|
|
200
217
|
}
|
|
201
218
|
this.app.sanitizer.handleNode(id, parentID, node);
|
|
219
|
+
if (this.app.sanitizer.isMaskedContainer(parentID)) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
202
222
|
}
|
|
223
|
+
// From here parentID === undefined if node is top context HTML node
|
|
203
224
|
let sibling = node.previousSibling;
|
|
204
225
|
while (sibling !== null) {
|
|
205
226
|
const siblingID = this.app.nodes.getID(sibling);
|
|
@@ -213,19 +234,28 @@ class Observer {
|
|
|
213
234
|
if (sibling === null) {
|
|
214
235
|
this.indexes[id] = 0;
|
|
215
236
|
}
|
|
216
|
-
const
|
|
237
|
+
const recentsType = this.recents.get(id);
|
|
238
|
+
const isNew = recentsType === RecentsType.New;
|
|
217
239
|
const index = this.indexes[id];
|
|
218
240
|
if (index === undefined) {
|
|
219
241
|
throw 'commitNode: missing node index';
|
|
220
242
|
}
|
|
221
|
-
if (isNew
|
|
243
|
+
if (isNew) {
|
|
222
244
|
if ((0, guards_js_1.isElementNode)(node)) {
|
|
245
|
+
let el = node;
|
|
223
246
|
if (parentID !== undefined) {
|
|
224
|
-
this.app.
|
|
247
|
+
if (this.app.sanitizer.isMaskedContainer(id)) {
|
|
248
|
+
const width = el.clientWidth;
|
|
249
|
+
const height = el.clientHeight;
|
|
250
|
+
el = node.cloneNode();
|
|
251
|
+
el.style.width = width + 'px';
|
|
252
|
+
el.style.height = height + 'px';
|
|
253
|
+
}
|
|
254
|
+
this.app.send(new messages_js_1.CreateElementNode(id, parentID, index, el.tagName, (0, guards_js_1.isSVGElement)(node)));
|
|
225
255
|
}
|
|
226
|
-
for (let i = 0; i <
|
|
227
|
-
const attr =
|
|
228
|
-
this.sendNodeAttribute(id,
|
|
256
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
257
|
+
const attr = el.attributes[i];
|
|
258
|
+
this.sendNodeAttribute(id, el, attr.nodeName, attr.value);
|
|
229
259
|
}
|
|
230
260
|
}
|
|
231
261
|
else if ((0, guards_js_1.isTextNode)(node)) {
|
|
@@ -235,11 +265,10 @@ class Observer {
|
|
|
235
265
|
}
|
|
236
266
|
return true;
|
|
237
267
|
}
|
|
238
|
-
if (
|
|
239
|
-
// does this happen a lot?
|
|
268
|
+
if (recentsType === RecentsType.Removed && parentID !== undefined) {
|
|
240
269
|
this.app.send(new messages_js_1.MoveNode(id, parentID, index));
|
|
241
270
|
}
|
|
242
|
-
const attr = this.
|
|
271
|
+
const attr = this.attributesMap.get(id);
|
|
243
272
|
if (attr !== undefined) {
|
|
244
273
|
if (!(0, guards_js_1.isElementNode)(node)) {
|
|
245
274
|
throw 'commitNode: node is not an element';
|
|
@@ -268,12 +297,12 @@ class Observer {
|
|
|
268
297
|
}
|
|
269
298
|
return (this.commited[id] = this._commitNode(id, node));
|
|
270
299
|
}
|
|
271
|
-
commitNodes() {
|
|
300
|
+
commitNodes(isStart = false) {
|
|
272
301
|
let node;
|
|
273
|
-
this.
|
|
302
|
+
this.recents.forEach((type, id) => {
|
|
274
303
|
this.commitNode(id);
|
|
275
|
-
if (
|
|
276
|
-
this.app.nodes.callNodeCallbacks(node);
|
|
304
|
+
if (type === RecentsType.New && (node = this.app.nodes.getNode(id))) {
|
|
305
|
+
this.app.nodes.callNodeCallbacks(node, isStart);
|
|
277
306
|
}
|
|
278
307
|
});
|
|
279
308
|
this.clear();
|
|
@@ -290,7 +319,7 @@ class Observer {
|
|
|
290
319
|
});
|
|
291
320
|
this.bindTree(nodeToBind);
|
|
292
321
|
beforeCommit(this.app.nodes.getID(node));
|
|
293
|
-
this.commitNodes();
|
|
322
|
+
this.commitNodes(true);
|
|
294
323
|
}
|
|
295
324
|
disconnect() {
|
|
296
325
|
this.observer.disconnect();
|
package/cjs/app/sanitizer.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import App from "./index.js";
|
|
1
|
+
import type App from "./index.js";
|
|
2
2
|
export interface Options {
|
|
3
3
|
obscureTextEmails: boolean;
|
|
4
4
|
obscureTextNumbers: boolean;
|
|
@@ -6,11 +6,13 @@ export interface Options {
|
|
|
6
6
|
export default class Sanitizer {
|
|
7
7
|
private readonly app;
|
|
8
8
|
private readonly masked;
|
|
9
|
+
private readonly maskedContainers;
|
|
9
10
|
private readonly options;
|
|
10
11
|
constructor(app: App, options: Partial<Options>);
|
|
11
12
|
handleNode(id: number, parentID: number, node: Node): void;
|
|
12
13
|
sanitize(id: number, data: string): string;
|
|
13
14
|
isMasked(id: number): boolean;
|
|
15
|
+
isMaskedContainer(id: number): boolean;
|
|
14
16
|
getInnerTextSecure(el: HTMLElement): string;
|
|
15
17
|
clear(): void;
|
|
16
18
|
}
|
package/cjs/app/sanitizer.js
CHANGED
|
@@ -6,6 +6,7 @@ class Sanitizer {
|
|
|
6
6
|
constructor(app, options) {
|
|
7
7
|
this.app = app;
|
|
8
8
|
this.masked = new Set();
|
|
9
|
+
this.maskedContainers = new Set();
|
|
9
10
|
this.options = Object.assign({
|
|
10
11
|
obscureTextEmails: true,
|
|
11
12
|
obscureTextNumbers: false,
|
|
@@ -13,9 +14,15 @@ class Sanitizer {
|
|
|
13
14
|
}
|
|
14
15
|
handleNode(id, parentID, node) {
|
|
15
16
|
if (this.masked.has(parentID) ||
|
|
16
|
-
((0, guards_js_1.isElementNode)(node) &&
|
|
17
|
+
((0, guards_js_1.isElementNode)(node) &&
|
|
18
|
+
(0, utils_js_1.hasOpenreplayAttribute)(node, 'masked'))) {
|
|
17
19
|
this.masked.add(id);
|
|
18
20
|
}
|
|
21
|
+
if (this.maskedContainers.has(parentID) ||
|
|
22
|
+
((0, guards_js_1.isElementNode)(node) &&
|
|
23
|
+
(0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked'))) {
|
|
24
|
+
this.maskedContainers.add(id);
|
|
25
|
+
}
|
|
19
26
|
}
|
|
20
27
|
sanitize(id, data) {
|
|
21
28
|
if (this.masked.has(id)) {
|
|
@@ -33,6 +40,9 @@ class Sanitizer {
|
|
|
33
40
|
isMasked(id) {
|
|
34
41
|
return this.masked.has(id);
|
|
35
42
|
}
|
|
43
|
+
isMaskedContainer(id) {
|
|
44
|
+
return this.maskedContainers.has(id);
|
|
45
|
+
}
|
|
36
46
|
getInnerTextSecure(el) {
|
|
37
47
|
const id = this.app.nodes.getID(el);
|
|
38
48
|
if (!id) {
|
|
@@ -42,6 +52,7 @@ class Sanitizer {
|
|
|
42
52
|
}
|
|
43
53
|
clear() {
|
|
44
54
|
this.masked.clear();
|
|
55
|
+
this.maskedContainers.clear();
|
|
45
56
|
}
|
|
46
57
|
}
|
|
47
58
|
exports.default = Sanitizer;
|
package/cjs/app/session.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import App from "./index.js";
|
|
2
1
|
interface SessionInfo {
|
|
3
2
|
sessionID: string | null;
|
|
4
3
|
metadata: Record<string, string>;
|
|
@@ -6,20 +5,16 @@ interface SessionInfo {
|
|
|
6
5
|
}
|
|
7
6
|
declare type OnUpdateCallback = (i: Partial<SessionInfo>) => void;
|
|
8
7
|
export default class Session {
|
|
9
|
-
private app;
|
|
10
8
|
private metadata;
|
|
11
9
|
private userID;
|
|
12
10
|
private sessionID;
|
|
13
|
-
private activityState;
|
|
14
11
|
private callbacks;
|
|
15
|
-
constructor(app: App);
|
|
16
12
|
attachUpdateCallback(cb: OnUpdateCallback): void;
|
|
17
13
|
private handleUpdate;
|
|
18
|
-
update(
|
|
19
|
-
private _setMetadata;
|
|
20
|
-
private _setUserID;
|
|
14
|
+
update(newInfo: Partial<SessionInfo>): void;
|
|
21
15
|
setMetadata(key: string, value: string): void;
|
|
22
16
|
setUserID(userID: string): void;
|
|
23
17
|
getInfo(): SessionInfo;
|
|
18
|
+
reset(): void;
|
|
24
19
|
}
|
|
25
20
|
export {};
|