@openreplay/tracker 3.5.11 → 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/README.md +5 -1
- package/cjs/app/guards.d.ts +18 -0
- package/cjs/app/guards.js +24 -0
- package/cjs/app/index.d.ts +18 -4
- package/cjs/app/index.js +69 -43
- package/cjs/app/nodes.d.ts +3 -3
- package/cjs/app/nodes.js +2 -2
- package/cjs/app/observer/observer.d.ts +1 -2
- package/cjs/app/observer/observer.js +73 -60
- package/cjs/app/observer/top_observer.js +3 -3
- package/cjs/app/sanitizer.d.ts +3 -1
- package/cjs/app/sanitizer.js +13 -2
- package/cjs/app/session.d.ts +2 -7
- package/cjs/app/session.js +24 -37
- package/cjs/index.d.ts +2 -2
- package/cjs/index.js +2 -2
- package/cjs/modules/console.d.ts +1 -1
- package/cjs/modules/console.js +2 -1
- package/cjs/modules/cssrules.d.ts +1 -1
- package/cjs/modules/cssrules.js +2 -4
- package/cjs/modules/exception.d.ts +1 -1
- package/cjs/modules/img.d.ts +1 -1
- package/cjs/modules/img.js +14 -6
- package/cjs/modules/input.d.ts +2 -1
- package/cjs/modules/input.js +18 -20
- package/cjs/modules/longtasks.d.ts +1 -1
- package/cjs/modules/mouse.d.ts +1 -1
- package/cjs/modules/mouse.js +3 -2
- package/cjs/modules/performance.d.ts +1 -1
- package/cjs/modules/scroll.d.ts +1 -1
- package/cjs/modules/scroll.js +3 -2
- package/cjs/modules/timing.d.ts +1 -1
- package/cjs/modules/timing.js +2 -1
- package/cjs/modules/viewport.d.ts +1 -1
- package/lib/app/guards.d.ts +18 -0
- package/lib/app/guards.js +16 -0
- package/lib/app/index.d.ts +18 -4
- package/lib/app/index.js +68 -42
- package/lib/app/nodes.d.ts +3 -3
- package/lib/app/nodes.js +2 -2
- package/lib/app/observer/observer.d.ts +1 -2
- package/lib/app/observer/observer.js +70 -57
- package/lib/app/observer/top_observer.js +3 -3
- package/lib/app/sanitizer.d.ts +3 -1
- package/lib/app/sanitizer.js +13 -2
- 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.d.ts +2 -2
- package/lib/index.js +2 -2
- package/lib/modules/console.d.ts +1 -1
- package/lib/modules/console.js +2 -1
- package/lib/modules/cssrules.d.ts +1 -1
- package/lib/modules/cssrules.js +2 -4
- package/lib/modules/exception.d.ts +1 -1
- package/lib/modules/img.d.ts +1 -1
- package/lib/modules/img.js +14 -6
- package/lib/modules/input.d.ts +2 -1
- package/lib/modules/input.js +18 -20
- package/lib/modules/longtasks.d.ts +1 -1
- package/lib/modules/mouse.d.ts +1 -1
- package/lib/modules/mouse.js +3 -2
- package/lib/modules/performance.d.ts +1 -1
- package/lib/modules/scroll.d.ts +1 -1
- package/lib/modules/scroll.js +3 -2
- package/lib/modules/timing.d.ts +1 -1
- package/lib/modules/timing.js +2 -1
- package/lib/modules/viewport.d.ts +1 -1
- package/package.json +2 -2
- package/cjs/app/context.d.ts +0 -18
- package/cjs/app/context.js +0 -73
- package/lib/app/context.d.ts +0 -18
- package/lib/app/context.js +0 -68
package/lib/app/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Timestamp } from "../common/messages.js";
|
|
1
|
+
import { Timestamp, Metadata, UserID } from "../common/messages.js";
|
|
2
2
|
import { timestamp } from "../utils.js";
|
|
3
3
|
import Nodes from "./nodes.js";
|
|
4
4
|
import Observer from "./observer/top_observer.js";
|
|
@@ -7,13 +7,16 @@ import Ticker from "./ticker.js";
|
|
|
7
7
|
import Logger, { LogLevel } from "./logger.js";
|
|
8
8
|
import Session from "./session.js";
|
|
9
9
|
import { deviceMemory, jsHeapSizeLimit } from "../modules/performance.js";
|
|
10
|
+
const CANCELED = "canceled";
|
|
11
|
+
const START_ERROR = ":(";
|
|
12
|
+
const UnsuccessfulStart = (reason) => ({ reason, success: false });
|
|
13
|
+
const SuccessfulStart = (body) => (Object.assign(Object.assign({}, body), { success: true }));
|
|
10
14
|
var ActivityState;
|
|
11
15
|
(function (ActivityState) {
|
|
12
16
|
ActivityState[ActivityState["NotActive"] = 0] = "NotActive";
|
|
13
17
|
ActivityState[ActivityState["Starting"] = 1] = "Starting";
|
|
14
18
|
ActivityState[ActivityState["Active"] = 2] = "Active";
|
|
15
19
|
})(ActivityState || (ActivityState = {}));
|
|
16
|
-
export const CANCELED = "canceled";
|
|
17
20
|
// TODO: use backendHost only
|
|
18
21
|
export const DEFAULT_INGEST_POINT = 'https://api.openreplay.com/ingest';
|
|
19
22
|
export default class App {
|
|
@@ -26,7 +29,7 @@ export default class App {
|
|
|
26
29
|
this.stopCallbacks = [];
|
|
27
30
|
this.commitCallbacks = [];
|
|
28
31
|
this.activityState = ActivityState.NotActive;
|
|
29
|
-
this.version = '3.5.
|
|
32
|
+
this.version = '3.5.13'; // TODO: version compatability check inside each plugin.
|
|
30
33
|
this.projectKey = projectKey;
|
|
31
34
|
this.options = Object.assign({
|
|
32
35
|
revID: '',
|
|
@@ -40,10 +43,9 @@ export default class App {
|
|
|
40
43
|
verbose: false,
|
|
41
44
|
__is_snippet: false,
|
|
42
45
|
__debug_report_edp: null,
|
|
46
|
+
localStorage: window.localStorage,
|
|
47
|
+
sessionStorage: window.sessionStorage,
|
|
43
48
|
}, options);
|
|
44
|
-
if (sessionToken != null) {
|
|
45
|
-
sessionStorage.setItem(this.options.session_token_key, sessionToken);
|
|
46
|
-
}
|
|
47
49
|
this.revID = this.options.revID;
|
|
48
50
|
this.sanitizer = new Sanitizer(this, options);
|
|
49
51
|
this.nodes = new Nodes(this.options.node_id);
|
|
@@ -52,9 +54,22 @@ export default class App {
|
|
|
52
54
|
this.ticker.attach(() => this.commit());
|
|
53
55
|
this.debug = new Logger(this.options.__debug__);
|
|
54
56
|
this.notify = new Logger(this.options.verbose ? LogLevel.Warnings : LogLevel.Silent);
|
|
55
|
-
this.session = new Session(
|
|
57
|
+
this.session = new Session();
|
|
58
|
+
this.session.attachUpdateCallback(({ userID, metadata }) => {
|
|
59
|
+
if (userID != null) { // TODO: nullable userID
|
|
60
|
+
this.send(new UserID(userID));
|
|
61
|
+
}
|
|
62
|
+
if (metadata != null) {
|
|
63
|
+
Object.entries(metadata).forEach(([key, value]) => this.send(new Metadata(key, value)));
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
this.localStorage = this.options.localStorage;
|
|
67
|
+
this.sessionStorage = this.options.sessionStorage;
|
|
68
|
+
if (sessionToken != null) {
|
|
69
|
+
this.sessionStorage.setItem(this.options.session_token_key, sessionToken);
|
|
70
|
+
}
|
|
56
71
|
try {
|
|
57
|
-
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()};
|
|
72
|
+
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()};
|
|
58
73
|
`], { type: 'text/javascript' })));
|
|
59
74
|
this.worker.onerror = e => {
|
|
60
75
|
this._debug("webworker_error", e);
|
|
@@ -62,6 +77,7 @@ export default class App {
|
|
|
62
77
|
this.worker.onmessage = ({ data }) => {
|
|
63
78
|
if (data === "failed") {
|
|
64
79
|
this.stop();
|
|
80
|
+
this._debug("worker_failed", {}); // add context (from worker)
|
|
65
81
|
}
|
|
66
82
|
else if (data === "restart") {
|
|
67
83
|
this.stop();
|
|
@@ -73,9 +89,10 @@ export default class App {
|
|
|
73
89
|
this.worker.postMessage(null);
|
|
74
90
|
}
|
|
75
91
|
};
|
|
76
|
-
//
|
|
92
|
+
// keep better tactics, discard others?
|
|
77
93
|
this.attachEventListener(window, 'beforeunload', alertWorker, false);
|
|
78
|
-
this.attachEventListener(document, 'mouseleave', alertWorker, false, false);
|
|
94
|
+
this.attachEventListener(document.body, 'mouseleave', alertWorker, false, false);
|
|
95
|
+
// TODO: stop session after inactivity timeout (make configurable)
|
|
79
96
|
this.attachEventListener(document, 'visibilitychange', alertWorker, false);
|
|
80
97
|
}
|
|
81
98
|
catch (e) {
|
|
@@ -149,8 +166,8 @@ export default class App {
|
|
|
149
166
|
}
|
|
150
167
|
// TODO: full correct semantic
|
|
151
168
|
checkRequiredVersion(version) {
|
|
152
|
-
const reqVer = version.split(
|
|
153
|
-
const ver = this.version.split(
|
|
169
|
+
const reqVer = version.split(/[.-]/);
|
|
170
|
+
const ver = this.version.split(/[.-]/);
|
|
154
171
|
for (let i = 0; i < 3; i++) {
|
|
155
172
|
if (Number(ver[i]) < Number(reqVer[i]) || isNaN(Number(ver[i])) || isNaN(Number(reqVer[i]))) {
|
|
156
173
|
return false;
|
|
@@ -160,7 +177,7 @@ export default class App {
|
|
|
160
177
|
}
|
|
161
178
|
getStartInfo() {
|
|
162
179
|
return {
|
|
163
|
-
userUUID: localStorage.getItem(this.options.local_uuid_key),
|
|
180
|
+
userUUID: this.localStorage.getItem(this.options.local_uuid_key),
|
|
164
181
|
projectKey: this.projectKey,
|
|
165
182
|
revID: this.revID,
|
|
166
183
|
timestamp: timestamp(),
|
|
@@ -172,7 +189,7 @@ export default class App {
|
|
|
172
189
|
return Object.assign(Object.assign({}, this.session.getInfo()), this.getStartInfo());
|
|
173
190
|
}
|
|
174
191
|
getSessionToken() {
|
|
175
|
-
const token = sessionStorage.getItem(this.options.session_token_key);
|
|
192
|
+
const token = this.sessionStorage.getItem(this.options.session_token_key);
|
|
176
193
|
if (token !== null) {
|
|
177
194
|
return token;
|
|
178
195
|
}
|
|
@@ -214,27 +231,27 @@ export default class App {
|
|
|
214
231
|
}
|
|
215
232
|
resetNextPageSession(flag) {
|
|
216
233
|
if (flag) {
|
|
217
|
-
sessionStorage.setItem(this.options.session_reset_key, 't');
|
|
234
|
+
this.sessionStorage.setItem(this.options.session_reset_key, 't');
|
|
218
235
|
}
|
|
219
236
|
else {
|
|
220
|
-
sessionStorage.removeItem(this.options.session_reset_key);
|
|
237
|
+
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
221
238
|
}
|
|
222
239
|
}
|
|
223
240
|
_start(startOpts) {
|
|
224
241
|
if (!this.worker) {
|
|
225
|
-
return Promise.
|
|
242
|
+
return Promise.resolve(UnsuccessfulStart("No worker found: perhaps, CSP is not set."));
|
|
226
243
|
}
|
|
227
244
|
if (this.activityState !== ActivityState.NotActive) {
|
|
228
|
-
return Promise.
|
|
245
|
+
return Promise.resolve(UnsuccessfulStart("OpenReplay: trying to call `start()` on the instance that has been started already."));
|
|
229
246
|
}
|
|
230
247
|
this.activityState = ActivityState.Starting;
|
|
231
248
|
let pageNo = 0;
|
|
232
|
-
const pageNoStr = sessionStorage.getItem(this.options.session_pageno_key);
|
|
249
|
+
const pageNoStr = this.sessionStorage.getItem(this.options.session_pageno_key);
|
|
233
250
|
if (pageNoStr != null) {
|
|
234
251
|
pageNo = parseInt(pageNoStr);
|
|
235
252
|
pageNo++;
|
|
236
253
|
}
|
|
237
|
-
sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
|
|
254
|
+
this.sessionStorage.setItem(this.options.session_pageno_key, pageNo.toString());
|
|
238
255
|
const startInfo = this.getStartInfo();
|
|
239
256
|
const startWorkerMsg = {
|
|
240
257
|
type: "start",
|
|
@@ -244,15 +261,21 @@ export default class App {
|
|
|
244
261
|
connAttemptCount: this.options.connAttemptCount,
|
|
245
262
|
connAttemptGap: this.options.connAttemptGap,
|
|
246
263
|
};
|
|
247
|
-
this.worker.postMessage(startWorkerMsg);
|
|
248
|
-
|
|
249
|
-
|
|
264
|
+
this.worker.postMessage(startWorkerMsg);
|
|
265
|
+
this.session.update({
|
|
266
|
+
// "updating" with old metadata in order to trigger session's UpdateCallbacks.
|
|
267
|
+
// (for the case of internal .start() calls, like on "restart" webworker signal or assistent connection in tracker-assist )
|
|
268
|
+
metadata: startOpts.metadata || this.session.getInfo().metadata,
|
|
269
|
+
userID: startOpts.userID,
|
|
270
|
+
});
|
|
271
|
+
const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
|
|
272
|
+
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
250
273
|
return window.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
251
274
|
method: 'POST',
|
|
252
275
|
headers: {
|
|
253
276
|
'Content-Type': 'application/json',
|
|
254
277
|
},
|
|
255
|
-
body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID:
|
|
278
|
+
body: JSON.stringify(Object.assign(Object.assign({}, startInfo), { userID: this.session.getInfo().userID, token: this.sessionStorage.getItem(this.options.session_token_key), deviceMemory,
|
|
256
279
|
jsHeapSizeLimit, reset: startOpts.forceNew || sReset !== null })),
|
|
257
280
|
})
|
|
258
281
|
.then(r => {
|
|
@@ -261,7 +284,7 @@ export default class App {
|
|
|
261
284
|
}
|
|
262
285
|
else {
|
|
263
286
|
return r.text().then(text => text === CANCELED
|
|
264
|
-
? Promise.reject(CANCELED)
|
|
287
|
+
? Promise.reject(CANCELED)
|
|
265
288
|
: Promise.reject(`Server error: ${r.status}. ${text}`));
|
|
266
289
|
}
|
|
267
290
|
})
|
|
@@ -275,36 +298,36 @@ export default class App {
|
|
|
275
298
|
(typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
|
|
276
299
|
return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
|
|
277
300
|
}
|
|
278
|
-
sessionStorage.setItem(this.options.session_token_key, token);
|
|
279
|
-
localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
280
|
-
this.session.update(
|
|
281
|
-
this.activityState = ActivityState.Active;
|
|
301
|
+
this.sessionStorage.setItem(this.options.session_token_key, token);
|
|
302
|
+
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
303
|
+
this.session.update({ sessionID }); // TODO: no no-explicit 'any'
|
|
282
304
|
const startWorkerMsg = {
|
|
283
305
|
type: "auth",
|
|
284
306
|
token,
|
|
285
307
|
beaconSizeLimit
|
|
286
308
|
};
|
|
287
309
|
this.worker.postMessage(startWorkerMsg);
|
|
310
|
+
this.activityState = ActivityState.Active;
|
|
288
311
|
const onStartInfo = { sessionToken: token, userUUID, sessionID };
|
|
289
|
-
this.startCallbacks.forEach((cb) => cb(onStartInfo));
|
|
312
|
+
this.startCallbacks.forEach((cb) => cb(onStartInfo)); // TODO: start as early as possible (before receiving the token)
|
|
290
313
|
this.observer.observe();
|
|
291
314
|
this.ticker.start();
|
|
292
315
|
this.notify.log("OpenReplay tracking started.");
|
|
293
|
-
//
|
|
316
|
+
// get rid of onStart ?
|
|
294
317
|
if (typeof this.options.onStart === 'function') {
|
|
295
318
|
this.options.onStart(onStartInfo);
|
|
296
319
|
}
|
|
297
|
-
return onStartInfo;
|
|
320
|
+
return SuccessfulStart(onStartInfo);
|
|
298
321
|
})
|
|
299
322
|
.catch(reason => {
|
|
300
|
-
sessionStorage.removeItem(this.options.session_token_key);
|
|
323
|
+
this.sessionStorage.removeItem(this.options.session_token_key);
|
|
301
324
|
this.stop();
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
this.notify.log("OpenReplay was unable to start. ", reason);
|
|
305
|
-
this._debug("session_start", reason);
|
|
325
|
+
if (reason === CANCELED) {
|
|
326
|
+
return UnsuccessfulStart(CANCELED);
|
|
306
327
|
}
|
|
307
|
-
|
|
328
|
+
this.notify.log("OpenReplay was unable to start. ", reason);
|
|
329
|
+
this._debug("session_start", reason);
|
|
330
|
+
return UnsuccessfulStart(START_ERROR);
|
|
308
331
|
});
|
|
309
332
|
}
|
|
310
333
|
start(options = {}) {
|
|
@@ -323,18 +346,21 @@ export default class App {
|
|
|
323
346
|
});
|
|
324
347
|
}
|
|
325
348
|
}
|
|
326
|
-
stop() {
|
|
349
|
+
stop(calledFromAPI = false) {
|
|
327
350
|
if (this.activityState !== ActivityState.NotActive) {
|
|
328
351
|
try {
|
|
329
|
-
if (this.worker) {
|
|
330
|
-
this.worker.postMessage("stop");
|
|
331
|
-
}
|
|
332
352
|
this.sanitizer.clear();
|
|
333
353
|
this.observer.disconnect();
|
|
334
354
|
this.nodes.clear();
|
|
335
355
|
this.ticker.stop();
|
|
336
356
|
this.stopCallbacks.forEach((cb) => cb());
|
|
357
|
+
if (calledFromAPI) {
|
|
358
|
+
this.session.reset();
|
|
359
|
+
}
|
|
337
360
|
this.notify.log("OpenReplay tracking stopped.");
|
|
361
|
+
if (this.worker) {
|
|
362
|
+
this.worker.postMessage("stop");
|
|
363
|
+
}
|
|
338
364
|
}
|
|
339
365
|
finally {
|
|
340
366
|
this.activityState = ActivityState.NotActive;
|
package/lib/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;
|
|
@@ -7,9 +7,9 @@ export default class Nodes {
|
|
|
7
7
|
constructor(node_id: string);
|
|
8
8
|
attachNodeCallback(nodeCallback: NodeCallback): void;
|
|
9
9
|
attachElementListener(type: string, node: Element, elementListener: EventListener): void;
|
|
10
|
-
registerNode(node: Node): [number, boolean];
|
|
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/lib/app/nodes.js
CHANGED
|
@@ -45,8 +45,8 @@ export default class Nodes {
|
|
|
45
45
|
}
|
|
46
46
|
return id;
|
|
47
47
|
}
|
|
48
|
-
callNodeCallbacks(node) {
|
|
49
|
-
this.nodeCallbacks.forEach((cb) => cb(node));
|
|
48
|
+
callNodeCallbacks(node, isStart) {
|
|
49
|
+
this.nodeCallbacks.forEach((cb) => cb(node, isStart));
|
|
50
50
|
}
|
|
51
51
|
getID(node) {
|
|
52
52
|
return node[this.node_id];
|
|
@@ -5,9 +5,8 @@ export default abstract class Observer {
|
|
|
5
5
|
private readonly observer;
|
|
6
6
|
private readonly commited;
|
|
7
7
|
private readonly recents;
|
|
8
|
-
private readonly myNodes;
|
|
9
8
|
private readonly indexes;
|
|
10
|
-
private readonly
|
|
9
|
+
private readonly attributesMap;
|
|
11
10
|
private readonly textSet;
|
|
12
11
|
constructor(app: App, isTopContext?: boolean);
|
|
13
12
|
private clear;
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
import { RemoveNodeAttribute, SetNodeAttribute, SetNodeAttributeURLBased, SetCSSDataURLBased, SetNodeData, CreateTextNode, CreateElementNode, MoveNode, RemoveNode, } from "../../common/messages.js";
|
|
2
|
-
import {
|
|
3
|
-
function isSVGElement(node) {
|
|
4
|
-
return node.namespaceURI === 'http://www.w3.org/2000/svg';
|
|
5
|
-
}
|
|
2
|
+
import { isRootNode, isTextNode, isElementNode, isSVGElement, hasTag, } from "../guards.js";
|
|
6
3
|
function isIgnored(node) {
|
|
7
|
-
if (
|
|
4
|
+
if (isTextNode(node)) {
|
|
8
5
|
return false;
|
|
9
6
|
}
|
|
10
|
-
if (!
|
|
7
|
+
if (!isElementNode(node)) {
|
|
11
8
|
return true;
|
|
12
9
|
}
|
|
13
10
|
const tag = node.tagName.toUpperCase();
|
|
@@ -22,30 +19,37 @@ function isIgnored(node) {
|
|
|
22
19
|
tag === 'TITLE' ||
|
|
23
20
|
tag === 'BASE');
|
|
24
21
|
}
|
|
25
|
-
function isRootNode(node) {
|
|
26
|
-
return isInstance(node, Document) || isInstance(node, ShadowRoot);
|
|
27
|
-
}
|
|
28
22
|
function isObservable(node) {
|
|
29
23
|
if (isRootNode(node)) {
|
|
30
24
|
return true;
|
|
31
25
|
}
|
|
32
26
|
return !isIgnored(node);
|
|
33
27
|
}
|
|
28
|
+
/*
|
|
29
|
+
TODO:
|
|
30
|
+
- fix unbinding logic + send all removals first (ensure sequence is correct)
|
|
31
|
+
- use document as a 0-node in the upper context (should be updated in player at first)
|
|
32
|
+
*/
|
|
33
|
+
var RecentsType;
|
|
34
|
+
(function (RecentsType) {
|
|
35
|
+
RecentsType[RecentsType["New"] = 0] = "New";
|
|
36
|
+
RecentsType[RecentsType["Removed"] = 1] = "Removed";
|
|
37
|
+
RecentsType[RecentsType["Changed"] = 2] = "Changed";
|
|
38
|
+
})(RecentsType || (RecentsType = {}));
|
|
34
39
|
export default class Observer {
|
|
35
40
|
constructor(app, isTopContext = false) {
|
|
36
41
|
this.app = app;
|
|
37
42
|
this.isTopContext = isTopContext;
|
|
38
43
|
this.commited = [];
|
|
39
|
-
this.recents =
|
|
40
|
-
this.myNodes = [];
|
|
44
|
+
this.recents = new Map();
|
|
41
45
|
this.indexes = [];
|
|
42
|
-
this.
|
|
46
|
+
this.attributesMap = new Map();
|
|
43
47
|
this.textSet = new Set();
|
|
44
48
|
this.observer = new MutationObserver(this.app.safe((mutations) => {
|
|
45
|
-
for (const mutation of mutations) {
|
|
49
|
+
for (const mutation of mutations) { // mutations order is sequential
|
|
46
50
|
const target = mutation.target;
|
|
47
51
|
const type = mutation.type;
|
|
48
|
-
if (!isObservable(target)
|
|
52
|
+
if (!isObservable(target)) {
|
|
49
53
|
continue;
|
|
50
54
|
}
|
|
51
55
|
if (type === 'childList') {
|
|
@@ -61,17 +65,17 @@ export default class Observer {
|
|
|
61
65
|
if (id === undefined) {
|
|
62
66
|
continue;
|
|
63
67
|
}
|
|
64
|
-
if (
|
|
65
|
-
this.recents
|
|
68
|
+
if (!this.recents.has(id)) {
|
|
69
|
+
this.recents.set(id, RecentsType.Changed); // TODO only when altered
|
|
66
70
|
}
|
|
67
71
|
if (type === 'attributes') {
|
|
68
72
|
const name = mutation.attributeName;
|
|
69
73
|
if (name === null) {
|
|
70
74
|
continue;
|
|
71
75
|
}
|
|
72
|
-
let attr = this.
|
|
76
|
+
let attr = this.attributesMap.get(id);
|
|
73
77
|
if (attr === undefined) {
|
|
74
|
-
this.
|
|
78
|
+
this.attributesMap.set(id, attr = new Set());
|
|
75
79
|
}
|
|
76
80
|
attr.add(name);
|
|
77
81
|
continue;
|
|
@@ -86,9 +90,9 @@ export default class Observer {
|
|
|
86
90
|
}
|
|
87
91
|
clear() {
|
|
88
92
|
this.commited.length = 0;
|
|
89
|
-
this.recents.
|
|
93
|
+
this.recents.clear();
|
|
90
94
|
this.indexes.length = 1;
|
|
91
|
-
this.
|
|
95
|
+
this.attributesMap.clear();
|
|
92
96
|
this.textSet.clear();
|
|
93
97
|
}
|
|
94
98
|
sendNodeAttribute(id, node, name, value) {
|
|
@@ -119,7 +123,7 @@ export default class Observer {
|
|
|
119
123
|
return;
|
|
120
124
|
}
|
|
121
125
|
if (name === 'value' &&
|
|
122
|
-
|
|
126
|
+
hasTag(node, "INPUT") &&
|
|
123
127
|
node.type !== 'button' &&
|
|
124
128
|
node.type !== 'reset' &&
|
|
125
129
|
node.type !== 'submit') {
|
|
@@ -129,7 +133,7 @@ export default class Observer {
|
|
|
129
133
|
this.app.send(new RemoveNodeAttribute(id, name));
|
|
130
134
|
return;
|
|
131
135
|
}
|
|
132
|
-
if (name === 'style' || name === 'href' &&
|
|
136
|
+
if (name === 'style' || name === 'href' && hasTag(node, "LINK")) {
|
|
133
137
|
this.app.send(new SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
|
|
134
138
|
return;
|
|
135
139
|
}
|
|
@@ -139,7 +143,7 @@ export default class Observer {
|
|
|
139
143
|
this.app.send(new SetNodeAttribute(id, name, value));
|
|
140
144
|
}
|
|
141
145
|
sendNodeData(id, parentElement, data) {
|
|
142
|
-
if (
|
|
146
|
+
if (hasTag(parentElement, "STYLE") || hasTag(parentElement, "style")) {
|
|
143
147
|
this.app.send(new SetCSSDataURLBased(id, data, this.app.getBaseHref()));
|
|
144
148
|
return;
|
|
145
149
|
}
|
|
@@ -147,10 +151,13 @@ export default class Observer {
|
|
|
147
151
|
this.app.send(new SetNodeData(id, data));
|
|
148
152
|
}
|
|
149
153
|
bindNode(node) {
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
+
const [id, isNew] = this.app.nodes.registerNode(node);
|
|
155
|
+
if (isNew) {
|
|
156
|
+
this.recents.set(id, RecentsType.New);
|
|
157
|
+
}
|
|
158
|
+
else if (!this.recents.has(id)) {
|
|
159
|
+
this.recents.set(id, RecentsType.Removed);
|
|
160
|
+
}
|
|
154
161
|
}
|
|
155
162
|
bindTree(node) {
|
|
156
163
|
if (!isObservable(node)) {
|
|
@@ -170,10 +177,11 @@ export default class Observer {
|
|
|
170
177
|
}
|
|
171
178
|
unbindNode(node) {
|
|
172
179
|
const id = this.app.nodes.unregisterNode(node);
|
|
173
|
-
if (id !== undefined && this.recents
|
|
180
|
+
if (id !== undefined && this.recents.get(id) === RecentsType.Removed) {
|
|
174
181
|
this.app.send(new RemoveNode(id));
|
|
175
182
|
}
|
|
176
183
|
}
|
|
184
|
+
// A top-consumption function on the infinite lists test. (~1% of performance resources)
|
|
177
185
|
_commitNode(id, node) {
|
|
178
186
|
if (isRootNode(node)) {
|
|
179
187
|
return true;
|
|
@@ -182,8 +190,8 @@ export default class Observer {
|
|
|
182
190
|
let parentID;
|
|
183
191
|
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
184
192
|
// TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
|
|
185
|
-
// TODO: Clean the logic (though now it workd fine)
|
|
186
|
-
if (!
|
|
193
|
+
// TODO: Clean the logic (though now it workd fine)
|
|
194
|
+
if (!hasTag(node, "HTML") || !this.isTopContext) {
|
|
187
195
|
if (parent === null) {
|
|
188
196
|
this.unbindNode(node);
|
|
189
197
|
return false;
|
|
@@ -198,7 +206,11 @@ export default class Observer {
|
|
|
198
206
|
return false;
|
|
199
207
|
}
|
|
200
208
|
this.app.sanitizer.handleNode(id, parentID, node);
|
|
209
|
+
if (this.app.sanitizer.isMaskedContainer(parentID)) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
201
212
|
}
|
|
213
|
+
// From here parentID === undefined if node is top context HTML node
|
|
202
214
|
let sibling = node.previousSibling;
|
|
203
215
|
while (sibling !== null) {
|
|
204
216
|
const siblingID = this.app.nodes.getID(sibling);
|
|
@@ -210,36 +222,45 @@ export default class Observer {
|
|
|
210
222
|
sibling = sibling.previousSibling;
|
|
211
223
|
}
|
|
212
224
|
if (sibling === null) {
|
|
213
|
-
this.indexes[id] = 0;
|
|
225
|
+
this.indexes[id] = 0;
|
|
214
226
|
}
|
|
215
|
-
const
|
|
227
|
+
const recentsType = this.recents.get(id);
|
|
228
|
+
const isNew = recentsType === RecentsType.New;
|
|
216
229
|
const index = this.indexes[id];
|
|
217
230
|
if (index === undefined) {
|
|
218
231
|
throw 'commitNode: missing node index';
|
|
219
232
|
}
|
|
220
|
-
if (isNew
|
|
221
|
-
if (
|
|
233
|
+
if (isNew) {
|
|
234
|
+
if (isElementNode(node)) {
|
|
235
|
+
let el = node;
|
|
222
236
|
if (parentID !== undefined) {
|
|
223
|
-
this.app.
|
|
237
|
+
if (this.app.sanitizer.isMaskedContainer(id)) {
|
|
238
|
+
const width = el.clientWidth;
|
|
239
|
+
const height = el.clientHeight;
|
|
240
|
+
el = node.cloneNode();
|
|
241
|
+
el.style.width = width + 'px';
|
|
242
|
+
el.style.height = height + 'px';
|
|
243
|
+
}
|
|
244
|
+
this.app.send(new CreateElementNode(id, parentID, index, el.tagName, isSVGElement(node)));
|
|
224
245
|
}
|
|
225
|
-
for (let i = 0; i <
|
|
226
|
-
const attr =
|
|
227
|
-
this.sendNodeAttribute(id,
|
|
246
|
+
for (let i = 0; i < el.attributes.length; i++) {
|
|
247
|
+
const attr = el.attributes[i];
|
|
248
|
+
this.sendNodeAttribute(id, el, attr.nodeName, attr.value);
|
|
228
249
|
}
|
|
229
250
|
}
|
|
230
|
-
else if (
|
|
251
|
+
else if (isTextNode(node)) {
|
|
231
252
|
// for text node id != 0, hence parentID !== undefined and parent is Element
|
|
232
253
|
this.app.send(new CreateTextNode(id, parentID, index));
|
|
233
254
|
this.sendNodeData(id, parent, node.data);
|
|
234
255
|
}
|
|
235
256
|
return true;
|
|
236
257
|
}
|
|
237
|
-
if (
|
|
258
|
+
if (recentsType === RecentsType.Removed && parentID !== undefined) {
|
|
238
259
|
this.app.send(new MoveNode(id, parentID, index));
|
|
239
260
|
}
|
|
240
|
-
const attr = this.
|
|
261
|
+
const attr = this.attributesMap.get(id);
|
|
241
262
|
if (attr !== undefined) {
|
|
242
|
-
if (!
|
|
263
|
+
if (!isElementNode(node)) {
|
|
243
264
|
throw 'commitNode: node is not an element';
|
|
244
265
|
}
|
|
245
266
|
for (const name of attr) {
|
|
@@ -247,7 +268,7 @@ export default class Observer {
|
|
|
247
268
|
}
|
|
248
269
|
}
|
|
249
270
|
if (this.textSet.has(id)) {
|
|
250
|
-
if (!
|
|
271
|
+
if (!isTextNode(node)) {
|
|
251
272
|
throw 'commitNode: node is not a text';
|
|
252
273
|
}
|
|
253
274
|
// for text node id != 0, hence parent is Element
|
|
@@ -266,21 +287,14 @@ export default class Observer {
|
|
|
266
287
|
}
|
|
267
288
|
return (this.commited[id] = this._commitNode(id, node));
|
|
268
289
|
}
|
|
269
|
-
commitNodes() {
|
|
290
|
+
commitNodes(isStart = false) {
|
|
270
291
|
let node;
|
|
271
|
-
|
|
272
|
-
// TODO: make things/logic nice here.
|
|
273
|
-
// commit required in any case if recents[id] true or false (in case of unbinding) or undefined (in case of attr change).
|
|
274
|
-
// Possible solution: separate new node commit (recents) and new attribute/move node commit
|
|
275
|
-
// Otherwise commitNode is called on each node, which might be a lot
|
|
276
|
-
if (!this.myNodes[id]) {
|
|
277
|
-
continue;
|
|
278
|
-
}
|
|
292
|
+
this.recents.forEach((type, id) => {
|
|
279
293
|
this.commitNode(id);
|
|
280
|
-
if (
|
|
281
|
-
this.app.nodes.callNodeCallbacks(node);
|
|
294
|
+
if (type === RecentsType.New && (node = this.app.nodes.getNode(id))) {
|
|
295
|
+
this.app.nodes.callNodeCallbacks(node, isStart);
|
|
282
296
|
}
|
|
283
|
-
}
|
|
297
|
+
});
|
|
284
298
|
this.clear();
|
|
285
299
|
}
|
|
286
300
|
// ISSSUE
|
|
@@ -295,11 +309,10 @@ export default class Observer {
|
|
|
295
309
|
});
|
|
296
310
|
this.bindTree(nodeToBind);
|
|
297
311
|
beforeCommit(this.app.nodes.getID(node));
|
|
298
|
-
this.commitNodes();
|
|
312
|
+
this.commitNodes(true);
|
|
299
313
|
}
|
|
300
314
|
disconnect() {
|
|
301
315
|
this.observer.disconnect();
|
|
302
316
|
this.clear();
|
|
303
|
-
this.myNodes.length = 0;
|
|
304
317
|
}
|
|
305
318
|
}
|