@openreplay/tracker 3.5.13-beta.0 → 3.5.13
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 +2 -2
- package/cjs/app/nodes.js +2 -2
- package/cjs/app/observer/observer.d.ts +2 -3
- package/cjs/app/observer/observer.js +56 -35
- 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 +12 -5
- package/cjs/modules/input.d.ts +1 -0
- package/cjs/modules/input.js +5 -8
- package/cjs/modules/scroll.js +6 -5
- 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 +2 -2
- package/lib/app/nodes.js +2 -2
- package/lib/app/observer/observer.d.ts +2 -3
- package/lib/app/observer/observer.js +56 -35
- 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 +12 -5
- package/lib/modules/input.d.ts +1 -0
- package/lib/modules/input.js +5 -8
- package/lib/modules/scroll.js +6 -5
- package/package.json +2 -2
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.13
|
|
35
|
+
this.version = '3.5.13'; // 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,ht=et.NotActive;function ot(){rt&&rt.finaliseBatch()}function ct(){ht=et.Stopping,null!==ut&&(clearInterval(ut),ut=null),rt&&(rt.clean(),rt=null),ht=et.NotActive}let at,ut=null;self.onmessage=({data:t})=>{if(null!=t){if("stop"===t)return ot(),void ct();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?at=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(at)),s.writeMessage(e)})}else{if("start"===t.type)return ht=et.Starting,nt=new Z(t.ingestPoint,()=>{self.postMessage("restart")},()=>{nt&&(nt.clean(),nt=null),ct(),self.postMessage("failed")},t.connAttemptCount,t.connAttemptGap),rt=new st(t.pageNo,t.timestamp,t=>nt&&nt.push(t)),null===ut&&(ut=setInterval(ot,1e4)),ht=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 ot()};
|
|
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,4 +1,4 @@
|
|
|
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
4
|
private readonly nodes;
|
|
@@ -9,7 +9,7 @@ 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
|
-
callNodeCallbacks(node: Node): void;
|
|
12
|
+
callNodeCallbacks(node: Node, isStart: boolean): void;
|
|
13
13
|
getID(node: Node): number | undefined;
|
|
14
14
|
getNode(id: number): Node | undefined;
|
|
15
15
|
clear(): void;
|
package/cjs/app/nodes.js
CHANGED
|
@@ -47,8 +47,8 @@ class Nodes {
|
|
|
47
47
|
}
|
|
48
48
|
return id;
|
|
49
49
|
}
|
|
50
|
-
callNodeCallbacks(node) {
|
|
51
|
-
this.nodeCallbacks.forEach((cb) => cb(node));
|
|
50
|
+
callNodeCallbacks(node, isStart) {
|
|
51
|
+
this.nodeCallbacks.forEach((cb) => cb(node, isStart));
|
|
52
52
|
}
|
|
53
53
|
getID(node) {
|
|
54
54
|
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,28 +27,35 @@ 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
|
-
if (!isObservable(target)
|
|
54
|
+
if (!isObservable(target)) {
|
|
45
55
|
continue;
|
|
46
56
|
}
|
|
47
57
|
if (type === 'childList') {
|
|
48
58
|
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
49
|
-
// TODO: handle node removal separately from binding.
|
|
50
|
-
// Node removals should go first in the commit.
|
|
51
|
-
// To check: MoveNode and other possible unbinding behaviours
|
|
52
59
|
this.bindTree(mutation.removedNodes[i]);
|
|
53
60
|
}
|
|
54
61
|
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
@@ -60,22 +67,23 @@ class Observer {
|
|
|
60
67
|
if (id === undefined) {
|
|
61
68
|
continue;
|
|
62
69
|
}
|
|
70
|
+
if (!this.recents.has(id)) {
|
|
71
|
+
this.recents.set(id, RecentsType.Changed); // TODO only when altered
|
|
72
|
+
}
|
|
63
73
|
if (type === 'attributes') {
|
|
64
74
|
const name = mutation.attributeName;
|
|
65
75
|
if (name === null) {
|
|
66
76
|
continue;
|
|
67
77
|
}
|
|
68
|
-
let attr = this.
|
|
78
|
+
let attr = this.attributesMap.get(id);
|
|
69
79
|
if (attr === undefined) {
|
|
70
|
-
this.
|
|
80
|
+
this.attributesMap.set(id, attr = new Set());
|
|
71
81
|
}
|
|
72
82
|
attr.add(name);
|
|
73
|
-
this.affectedSet.add(id);
|
|
74
83
|
continue;
|
|
75
84
|
}
|
|
76
85
|
if (type === 'characterData') {
|
|
77
86
|
this.textSet.add(id);
|
|
78
|
-
this.affectedSet.add(id);
|
|
79
87
|
continue;
|
|
80
88
|
}
|
|
81
89
|
}
|
|
@@ -84,11 +92,10 @@ class Observer {
|
|
|
84
92
|
}
|
|
85
93
|
clear() {
|
|
86
94
|
this.commited.length = 0;
|
|
95
|
+
this.recents.clear();
|
|
87
96
|
this.indexes.length = 1;
|
|
88
|
-
this.
|
|
97
|
+
this.attributesMap.clear();
|
|
89
98
|
this.textSet.clear();
|
|
90
|
-
this.newSet.clear();
|
|
91
|
-
this.affectedSet.clear();
|
|
92
99
|
}
|
|
93
100
|
sendNodeAttribute(id, node, name, value) {
|
|
94
101
|
if ((0, guards_js_1.isSVGElement)(node)) {
|
|
@@ -138,7 +145,7 @@ class Observer {
|
|
|
138
145
|
this.app.send(new messages_js_1.SetNodeAttribute(id, name, value));
|
|
139
146
|
}
|
|
140
147
|
sendNodeData(id, parentElement, data) {
|
|
141
|
-
if ((0, guards_js_1.hasTag)(parentElement, "STYLE")) {
|
|
148
|
+
if ((0, guards_js_1.hasTag)(parentElement, "STYLE") || (0, guards_js_1.hasTag)(parentElement, "style")) {
|
|
142
149
|
this.app.send(new messages_js_1.SetCSSDataURLBased(id, data, this.app.getBaseHref()));
|
|
143
150
|
return;
|
|
144
151
|
}
|
|
@@ -148,9 +155,11 @@ class Observer {
|
|
|
148
155
|
bindNode(node) {
|
|
149
156
|
const [id, isNew] = this.app.nodes.registerNode(node);
|
|
150
157
|
if (isNew) {
|
|
151
|
-
this.
|
|
158
|
+
this.recents.set(id, RecentsType.New);
|
|
159
|
+
}
|
|
160
|
+
else if (!this.recents.has(id)) {
|
|
161
|
+
this.recents.set(id, RecentsType.Removed);
|
|
152
162
|
}
|
|
153
|
-
this.affectedSet.add(id);
|
|
154
163
|
}
|
|
155
164
|
bindTree(node) {
|
|
156
165
|
if (!isObservable(node)) {
|
|
@@ -170,11 +179,11 @@ class Observer {
|
|
|
170
179
|
}
|
|
171
180
|
unbindNode(node) {
|
|
172
181
|
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.
|
|
182
|
+
if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
|
|
175
183
|
this.app.send(new messages_js_1.RemoveNode(id));
|
|
176
184
|
}
|
|
177
185
|
}
|
|
186
|
+
// A top-consumption function on the infinite lists test. (~1% of performance resources)
|
|
178
187
|
_commitNode(id, node) {
|
|
179
188
|
if ((0, guards_js_1.isRootNode)(node)) {
|
|
180
189
|
return true;
|
|
@@ -183,7 +192,7 @@ class Observer {
|
|
|
183
192
|
let parentID;
|
|
184
193
|
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
185
194
|
// 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)
|
|
195
|
+
// TODO: Clean the logic (though now it workd fine)
|
|
187
196
|
if (!(0, guards_js_1.hasTag)(node, "HTML") || !this.isTopContext) {
|
|
188
197
|
if (parent === null) {
|
|
189
198
|
this.unbindNode(node);
|
|
@@ -199,7 +208,11 @@ class Observer {
|
|
|
199
208
|
return false;
|
|
200
209
|
}
|
|
201
210
|
this.app.sanitizer.handleNode(id, parentID, node);
|
|
211
|
+
if (this.app.sanitizer.isMaskedContainer(parentID)) {
|
|
212
|
+
return false;
|
|
213
|
+
}
|
|
202
214
|
}
|
|
215
|
+
// From here parentID === undefined if node is top context HTML node
|
|
203
216
|
let sibling = node.previousSibling;
|
|
204
217
|
while (sibling !== null) {
|
|
205
218
|
const siblingID = this.app.nodes.getID(sibling);
|
|
@@ -213,19 +226,28 @@ class Observer {
|
|
|
213
226
|
if (sibling === null) {
|
|
214
227
|
this.indexes[id] = 0;
|
|
215
228
|
}
|
|
216
|
-
const
|
|
229
|
+
const recentsType = this.recents.get(id);
|
|
230
|
+
const isNew = recentsType === RecentsType.New;
|
|
217
231
|
const index = this.indexes[id];
|
|
218
232
|
if (index === undefined) {
|
|
219
233
|
throw 'commitNode: missing node index';
|
|
220
234
|
}
|
|
221
|
-
if (isNew
|
|
235
|
+
if (isNew) {
|
|
222
236
|
if ((0, guards_js_1.isElementNode)(node)) {
|
|
237
|
+
let el = node;
|
|
223
238
|
if (parentID !== undefined) {
|
|
224
|
-
this.app.
|
|
239
|
+
if (this.app.sanitizer.isMaskedContainer(id)) {
|
|
240
|
+
const width = el.clientWidth;
|
|
241
|
+
const height = el.clientHeight;
|
|
242
|
+
el = node.cloneNode();
|
|
243
|
+
el.style.width = width + 'px';
|
|
244
|
+
el.style.height = height + 'px';
|
|
245
|
+
}
|
|
246
|
+
this.app.send(new messages_js_1.CreateElementNode(id, parentID, index, el.tagName, (0, guards_js_1.isSVGElement)(node)));
|
|
225
247
|
}
|
|
226
|
-
for (let i = 0; i <
|
|
227
|
-
const attr =
|
|
228
|
-
this.sendNodeAttribute(id,
|
|
248
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
249
|
+
const attr = el.attributes[i];
|
|
250
|
+
this.sendNodeAttribute(id, el, attr.nodeName, attr.value);
|
|
229
251
|
}
|
|
230
252
|
}
|
|
231
253
|
else if ((0, guards_js_1.isTextNode)(node)) {
|
|
@@ -235,11 +257,10 @@ class Observer {
|
|
|
235
257
|
}
|
|
236
258
|
return true;
|
|
237
259
|
}
|
|
238
|
-
if (
|
|
239
|
-
// does this happen a lot?
|
|
260
|
+
if (recentsType === RecentsType.Removed && parentID !== undefined) {
|
|
240
261
|
this.app.send(new messages_js_1.MoveNode(id, parentID, index));
|
|
241
262
|
}
|
|
242
|
-
const attr = this.
|
|
263
|
+
const attr = this.attributesMap.get(id);
|
|
243
264
|
if (attr !== undefined) {
|
|
244
265
|
if (!(0, guards_js_1.isElementNode)(node)) {
|
|
245
266
|
throw 'commitNode: node is not an element';
|
|
@@ -268,12 +289,12 @@ class Observer {
|
|
|
268
289
|
}
|
|
269
290
|
return (this.commited[id] = this._commitNode(id, node));
|
|
270
291
|
}
|
|
271
|
-
commitNodes() {
|
|
292
|
+
commitNodes(isStart = false) {
|
|
272
293
|
let node;
|
|
273
|
-
this.
|
|
294
|
+
this.recents.forEach((type, id) => {
|
|
274
295
|
this.commitNode(id);
|
|
275
|
-
if (
|
|
276
|
-
this.app.nodes.callNodeCallbacks(node);
|
|
296
|
+
if (type === RecentsType.New && (node = this.app.nodes.getNode(id))) {
|
|
297
|
+
this.app.nodes.callNodeCallbacks(node, isStart);
|
|
277
298
|
}
|
|
278
299
|
});
|
|
279
300
|
this.clear();
|
|
@@ -290,7 +311,7 @@ class Observer {
|
|
|
290
311
|
});
|
|
291
312
|
this.bindTree(nodeToBind);
|
|
292
313
|
beforeCommit(this.app.nodes.getID(node));
|
|
293
|
-
this.commitNodes();
|
|
314
|
+
this.commitNodes(true);
|
|
294
315
|
}
|
|
295
316
|
disconnect() {
|
|
296
317
|
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 {};
|