@openreplay/tracker 3.4.11 → 3.4.15
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/index.d.ts +2 -2
- package/cjs/app/index.js +17 -5
- package/cjs/app/observer/iframe_observer.d.ts +4 -0
- package/cjs/app/observer/iframe_observer.js +22 -0
- package/cjs/app/observer/observer.d.ts +50 -0
- package/cjs/app/observer/observer.js +381 -0
- package/cjs/app/observer/shadow_root_observer.d.ts +4 -0
- package/cjs/app/observer/shadow_root_observer.js +21 -0
- package/cjs/app/observer/top_observer.d.ts +15 -0
- package/cjs/app/observer/top_observer.js +82 -0
- package/cjs/index.js +1 -1
- package/lib/app/index.d.ts +2 -2
- package/lib/app/index.js +16 -4
- package/lib/app/observer/iframe_observer.d.ts +4 -0
- package/lib/app/observer/iframe_observer.js +19 -0
- package/lib/app/observer/observer.d.ts +50 -0
- package/lib/app/observer/observer.js +376 -0
- package/lib/app/observer/shadow_root_observer.d.ts +4 -0
- package/lib/app/observer/shadow_root_observer.js +18 -0
- package/lib/app/observer/top_observer.d.ts +15 -0
- package/lib/app/observer/top_observer.js +79 -0
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/cjs/app/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Message from "../messages/message.js";
|
|
2
2
|
import Nodes from "./nodes.js";
|
|
3
|
-
import Observer from "./observer.js";
|
|
3
|
+
import Observer from "./observer/top_observer.js";
|
|
4
4
|
import Ticker from "./ticker.js";
|
|
5
|
-
import type { Options as ObserverOptions } from "./observer.js";
|
|
5
|
+
import type { Options as ObserverOptions } from "./observer/top_observer.js";
|
|
6
6
|
import type { Options as WebworkerOptions } from "../messages/webworker.js";
|
|
7
7
|
export interface OnStartInfo {
|
|
8
8
|
sessionID: string;
|
package/cjs/app/index.js
CHANGED
|
@@ -4,7 +4,7 @@ exports.DEFAULT_INGEST_POINT = void 0;
|
|
|
4
4
|
const utils_js_1 = require("../utils.js");
|
|
5
5
|
const index_js_1 = require("../messages/index.js");
|
|
6
6
|
const nodes_js_1 = require("./nodes.js");
|
|
7
|
-
const
|
|
7
|
+
const top_observer_js_1 = require("./observer/top_observer.js");
|
|
8
8
|
const ticker_js_1 = require("./ticker.js");
|
|
9
9
|
const performance_js_1 = require("../modules/performance.js");
|
|
10
10
|
// TODO: use backendHost only
|
|
@@ -17,7 +17,7 @@ class App {
|
|
|
17
17
|
this.commitCallbacks = [];
|
|
18
18
|
this._sessionID = null;
|
|
19
19
|
this.isActive = false;
|
|
20
|
-
this.version = '3.4.
|
|
20
|
+
this.version = '3.4.15';
|
|
21
21
|
this.projectKey = projectKey;
|
|
22
22
|
this.options = Object.assign({
|
|
23
23
|
revID: '',
|
|
@@ -39,11 +39,11 @@ class App {
|
|
|
39
39
|
}
|
|
40
40
|
this.revID = this.options.revID;
|
|
41
41
|
this.nodes = new nodes_js_1.default(this.options.node_id);
|
|
42
|
-
this.observer = new
|
|
42
|
+
this.observer = new top_observer_js_1.default(this, this.options);
|
|
43
43
|
this.ticker = new ticker_js_1.default(this);
|
|
44
44
|
this.ticker.attach(() => this.commit());
|
|
45
45
|
try {
|
|
46
|
-
this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st,it=1e6,nt=4e5,et=new tt(nt),rt="",ot="",ht=0,ct=0,ut=0,at=0,dt=!0;function lt(){return new i(ht,at,ct).encode(et)}const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(dt||""===ot||""===rt)return;const t=et.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",rt+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+ot),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),dt=!0,lt()}function St(){rt="",ot="",clearInterval(st),et.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ct=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),3e5):clearTimeout(ft)),et.checkpoint(),!i.encode(et)&&(vt(),!i.encode(et)))for(;!i.encode(et);){if(nt===it)return console.warn("OpenReplay: beacon size overflow."),et.reset(),void lt();nt=Math.min(2*nt,it),et=new tt(nt),lt()}at++,dt=!1}):(rt=t.ingestPoint||rt,ot=t.token||ot,ht=t.pageNo||ht,ct=t.startTimestamp||ct,ut=t.timeAdjustment||ut,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,it=t.beaconSizeLimit||it,nt=Math.min(it,t.beaconSize||nt),et.isEmpty()&<(),void(null==st&&(st=setInterval(vt,8e3))));vt()};
|
|
46
|
+
this.worker = new Worker(URL.createObjectURL(new Blob([`"use strict";function t(t){function s(...s){return new t(...s)}return s.prototype=t.prototype,s}const s=new Map;const i=t(class{constructor(t,s,i){this.pageNo=t,this.firstIndex=s,this.timestamp=i,this._id=80}encode(t){return t.uint(80)&&t.uint(this.pageNo)&&t.uint(this.firstIndex)&&t.int(this.timestamp)}});s.set(80,i);const n=t(class{constructor(t){this.timestamp=t,this._id=0}encode(t){return t.uint(0)&&t.uint(this.timestamp)}});s.set(0,n);const e=t(class{constructor(t,s,i){this.url=t,this.referrer=s,this.navigationStart=i,this._id=4}encode(t){return t.uint(4)&&t.string(this.url)&&t.string(this.referrer)&&t.uint(this.navigationStart)}});s.set(4,e);const r=t(class{constructor(t,s){this.width=t,this.height=s,this._id=5}encode(t){return t.uint(5)&&t.uint(this.width)&&t.uint(this.height)}});s.set(5,r);const o=t(class{constructor(t,s){this.x=t,this.y=s,this._id=6}encode(t){return t.uint(6)&&t.int(this.x)&&t.int(this.y)}});s.set(6,o);const h=t(class{constructor(){this._id=7}encode(t){return t.uint(7)}});s.set(7,h);const c=t(class{constructor(t,s,i,n,e){this.id=t,this.parentID=s,this.index=i,this.tag=n,this.svg=e,this._id=8}encode(t){return t.uint(8)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)&&t.string(this.tag)&&t.boolean(this.svg)}});s.set(8,c);const u=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=9}encode(t){return t.uint(9)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(9,u);const a=t(class{constructor(t,s,i){this.id=t,this.parentID=s,this.index=i,this._id=10}encode(t){return t.uint(10)&&t.uint(this.id)&&t.uint(this.parentID)&&t.uint(this.index)}});s.set(10,a);const d=t(class{constructor(t){this.id=t,this._id=11}encode(t){return t.uint(11)&&t.uint(this.id)}});s.set(11,d);const l=t(class{constructor(t,s,i){this.id=t,this.name=s,this.value=i,this._id=12}encode(t){return t.uint(12)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)}});s.set(12,l);const g=t(class{constructor(t,s){this.id=t,this.name=s,this._id=13}encode(t){return t.uint(13)&&t.uint(this.id)&&t.string(this.name)}});s.set(13,g);const f=t(class{constructor(t,s){this.id=t,this.data=s,this._id=14}encode(t){return t.uint(14)&&t.uint(this.id)&&t.string(this.data)}});s.set(14,f);const p=t(class{constructor(t,s,i){this.id=t,this.x=s,this.y=i,this._id=16}encode(t){return t.uint(16)&&t.uint(this.id)&&t.int(this.x)&&t.int(this.y)}});s.set(16,p);const m=t(class{constructor(t,s){this.id=t,this.label=s,this._id=17}encode(t){return t.uint(17)&&t.uint(this.id)&&t.string(this.label)}});s.set(17,m);const _=t(class{constructor(t,s,i){this.id=t,this.value=s,this.mask=i,this._id=18}encode(t){return t.uint(18)&&t.uint(this.id)&&t.string(this.value)&&t.int(this.mask)}});s.set(18,_);const y=t(class{constructor(t,s){this.id=t,this.checked=s,this._id=19}encode(t){return t.uint(19)&&t.uint(this.id)&&t.boolean(this.checked)}});s.set(19,y);const v=t(class{constructor(t,s){this.x=t,this.y=s,this._id=20}encode(t){return t.uint(20)&&t.uint(this.x)&&t.uint(this.y)}});s.set(20,v);const S=t(class{constructor(t,s){this.level=t,this.value=s,this._id=22}encode(t){return t.uint(22)&&t.string(this.level)&&t.string(this.value)}});s.set(22,S);const b=t(class{constructor(t,s,i,n,e,r,o,h,c){this.requestStart=t,this.responseStart=s,this.responseEnd=i,this.domContentLoadedEventStart=n,this.domContentLoadedEventEnd=e,this.loadEventStart=r,this.loadEventEnd=o,this.firstPaint=h,this.firstContentfulPaint=c,this._id=23}encode(t){return t.uint(23)&&t.uint(this.requestStart)&&t.uint(this.responseStart)&&t.uint(this.responseEnd)&&t.uint(this.domContentLoadedEventStart)&&t.uint(this.domContentLoadedEventEnd)&&t.uint(this.loadEventStart)&&t.uint(this.loadEventEnd)&&t.uint(this.firstPaint)&&t.uint(this.firstContentfulPaint)}});s.set(23,b);const x=t(class{constructor(t,s,i){this.speedIndex=t,this.visuallyComplete=s,this.timeToInteractive=i,this._id=24}encode(t){return t.uint(24)&&t.uint(this.speedIndex)&&t.uint(this.visuallyComplete)&&t.uint(this.timeToInteractive)}});s.set(24,x);const E=t(class{constructor(t,s,i){this.name=t,this.message=s,this.payload=i,this._id=25}encode(t){return t.uint(25)&&t.string(this.name)&&t.string(this.message)&&t.string(this.payload)}});s.set(25,E);const k=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=27}encode(t){return t.uint(27)&&t.string(this.name)&&t.string(this.payload)}});s.set(27,k);const I=t(class{constructor(t){this.id=t,this._id=28}encode(t){return t.uint(28)&&t.string(this.id)}});s.set(28,I);const z=t(class{constructor(t){this.id=t,this._id=29}encode(t){return t.uint(29)&&t.string(this.id)}});s.set(29,z);const w=t(class{constructor(t,s){this.key=t,this.value=s,this._id=30}encode(t){return t.uint(30)&&t.string(this.key)&&t.string(this.value)}});s.set(30,w);const T=t(class{constructor(t,s,i){this.id=t,this.rule=s,this.index=i,this._id=37}encode(t){return t.uint(37)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)}});s.set(37,T);const L=t(class{constructor(t,s){this.id=t,this.index=s,this._id=38}encode(t){return t.uint(38)&&t.uint(this.id)&&t.uint(this.index)}});s.set(38,L);const A=t(class{constructor(t,s,i,n,e,r,o){this.method=t,this.url=s,this.request=i,this.response=n,this.status=e,this.timestamp=r,this.duration=o,this._id=39}encode(t){return t.uint(39)&&t.string(this.method)&&t.string(this.url)&&t.string(this.request)&&t.string(this.response)&&t.uint(this.status)&&t.uint(this.timestamp)&&t.uint(this.duration)}});s.set(39,A);const C=t(class{constructor(t,s,i,n){this.name=t,this.duration=s,this.args=i,this.result=n,this._id=40}encode(t){return t.uint(40)&&t.string(this.name)&&t.uint(this.duration)&&t.string(this.args)&&t.string(this.result)}});s.set(40,C);const M=t(class{constructor(t,s){this.key=t,this.value=s,this._id=41}encode(t){return t.uint(41)&&t.string(this.key)&&t.string(this.value)}});s.set(41,M);const R=t(class{constructor(t){this.type=t,this._id=42}encode(t){return t.uint(42)&&t.string(this.type)}});s.set(42,R);const N=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=44}encode(t){return t.uint(44)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(44,N);const D=t(class{constructor(t,s){this.mutation=t,this.state=s,this._id=45}encode(t){return t.uint(45)&&t.string(this.mutation)&&t.string(this.state)}});s.set(45,D);const U=t(class{constructor(t,s){this.type=t,this.payload=s,this._id=46}encode(t){return t.uint(46)&&t.string(this.type)&&t.string(this.payload)}});s.set(46,U);const O=t(class{constructor(t,s,i){this.action=t,this.state=s,this.duration=i,this._id=47}encode(t){return t.uint(47)&&t.string(this.action)&&t.string(this.state)&&t.uint(this.duration)}});s.set(47,O);const q=t(class{constructor(t,s,i,n){this.operationKind=t,this.operationName=s,this.variables=i,this.response=n,this._id=48}encode(t){return t.uint(48)&&t.string(this.operationKind)&&t.string(this.operationName)&&t.string(this.variables)&&t.string(this.response)}});s.set(48,q);const H=t(class{constructor(t,s,i,n){this.frames=t,this.ticks=s,this.totalJSHeapSize=i,this.usedJSHeapSize=n,this._id=49}encode(t){return t.uint(49)&&t.int(this.frames)&&t.int(this.ticks)&&t.uint(this.totalJSHeapSize)&&t.uint(this.usedJSHeapSize)}});s.set(49,H);const P=t(class{constructor(t,s,i,n,e,r,o,h){this.timestamp=t,this.duration=s,this.ttfb=i,this.headerSize=n,this.encodedBodySize=e,this.decodedBodySize=r,this.url=o,this.initiator=h,this._id=53}encode(t){return t.uint(53)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.ttfb)&&t.uint(this.headerSize)&&t.uint(this.encodedBodySize)&&t.uint(this.decodedBodySize)&&t.string(this.url)&&t.string(this.initiator)}});s.set(53,P);const B=t(class{constructor(t,s){this.downlink=t,this.type=s,this._id=54}encode(t){return t.uint(54)&&t.uint(this.downlink)&&t.string(this.type)}});s.set(54,B);const J=t(class{constructor(t){this.hidden=t,this._id=55}encode(t){return t.uint(55)&&t.boolean(this.hidden)}});s.set(55,J);const j=t(class{constructor(t,s,i,n,e,r,o){this.timestamp=t,this.duration=s,this.context=i,this.containerType=n,this.containerSrc=e,this.containerId=r,this.containerName=o,this._id=59}encode(t){return t.uint(59)&&t.uint(this.timestamp)&&t.uint(this.duration)&&t.uint(this.context)&&t.uint(this.containerType)&&t.string(this.containerSrc)&&t.string(this.containerId)&&t.string(this.containerName)}});s.set(59,j);const G=t(class{constructor(t,s,i,n){this.id=t,this.name=s,this.value=i,this.baseURL=n,this._id=60}encode(t){return t.uint(60)&&t.uint(this.id)&&t.string(this.name)&&t.string(this.value)&&t.string(this.baseURL)}});s.set(60,G);const K=t(class{constructor(t,s,i){this.id=t,this.data=s,this.baseURL=i,this._id=61}encode(t){return t.uint(61)&&t.uint(this.id)&&t.string(this.data)&&t.string(this.baseURL)}});s.set(61,K);const X=t(class{constructor(t,s){this.type=t,this.value=s,this._id=63}encode(t){return t.uint(63)&&t.string(this.type)&&t.string(this.value)}});s.set(63,X);const F=t(class{constructor(t,s){this.name=t,this.payload=s,this._id=64}encode(t){return t.uint(64)&&t.string(this.name)&&t.string(this.payload)}});s.set(64,F);const Q=t(class{constructor(){this._id=65}encode(t){return t.uint(65)}});s.set(65,Q);const V=t(class{constructor(t,s,i,n){this.id=t,this.rule=s,this.index=i,this.baseURL=n,this._id=67}encode(t){return t.uint(67)&&t.uint(this.id)&&t.string(this.rule)&&t.uint(this.index)&&t.string(this.baseURL)}});s.set(67,V);const W=t(class{constructor(t,s,i,n){this.id=t,this.hesitationTime=s,this.label=i,this.selector=n,this._id=69}encode(t){return t.uint(69)&&t.uint(this.id)&&t.uint(this.hesitationTime)&&t.string(this.label)&&t.string(this.selector)}});s.set(69,W);const Y=t(class{constructor(t,s){this.frameID=t,this.id=s,this._id=70}encode(t){return t.uint(70)&&t.uint(this.frameID)&&t.uint(this.id)}});s.set(70,Y);const Z="function"==typeof TextEncoder?new TextEncoder:{encode(t){const s=t.length,i=new Uint8Array(3*s);let n=-1;for(var e=0,r=0,o=0;o!==s;){if(e=t.charCodeAt(o),o+=1,e>=55296&&e<=56319){if(o===s){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;break}if(!((r=t.charCodeAt(o))>=56320&&r<=57343)){i[n+=1]=239,i[n+=1]=191,i[n+=1]=189;continue}if(o+=1,(e=1024*(e-55296)+r-56320+65536)>65535){i[n+=1]=240|e>>>18,i[n+=1]=128|e>>>12&63,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e;continue}}e<=127?i[n+=1]=0|e:e<=2047?(i[n+=1]=192|e>>>6,i[n+=1]=128|63&e):(i[n+=1]=224|e>>>12,i[n+=1]=128|e>>>6&63,i[n+=1]=128|63&e)}return i.subarray(0,n+1)}};class tt{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}boolean(t){return this.data[this.offset++]=+t,this.offset<=this.size}uint(t){for((t<0||t>Number.MAX_SAFE_INTEGER)&&(t=0);t>=128;)this.data[this.offset++]=t%256|128,t=Math.floor(t/128);return this.data[this.offset++]=t,this.offset<=this.size}int(t){return t=Math.round(t),this.uint(t>=0?2*t:-2*t-1)}string(t){const s=Z.encode(t),i=s.byteLength;return!(!this.uint(i)||this.offset+i>this.size)&&(this.data.set(s,this.offset),this.offset+=i,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}let st=1e6,it=2e5,nt=new tt(it),et="",rt="",ot=0,ht=0,ct=0,ut=0,at=!0;function dt(){return new i(ot,ut,ht).encode(nt)}let lt=null;const gt=[];let ft,pt=!1,mt=0,_t=8e3,yt=10;function vt(){if(at||""===rt||""===et)return;const t=nt.flush();pt?gt.push(t):(pt=!0,function t(s){const i=new XMLHttpRequest;i.open("POST",et+"/v1/web/i",!1),i.setRequestHeader("Authorization","Bearer "+rt),i.onreadystatechange=function(){if(4===this.readyState){if(0==this.status)return;if(this.status>=400)return St(),gt.length=0,401===this.status?void self.postMessage("restart"):void self.postMessage(null);const s=gt.shift();s?t(s):pt=!1}},i.onerror=function(i){if(mt>=yt)return St(),void self.postMessage(null);mt++,setTimeout(()=>t(s),_t)},i.send(s.buffer)}(t)),at=!0,dt()}function St(){et="",rt="",null!==lt&&(clearInterval(lt),lt=null),nt.reset()}self.onmessage=({data:t})=>{if(null!==t)return"stop"===t?(vt(),void St()):Array.isArray(t)?void t.forEach(t=>{const i=new(s.get(t._id));if(Object.assign(i,t),i instanceof n?ht=i.timestamp:i instanceof J&&(i.hidden?ft=setTimeout(()=>self.postMessage("restart"),18e5):clearTimeout(ft)),nt.checkpoint(),!i.encode(nt)&&(vt(),!i.encode(nt)))for(;!i.encode(nt);){if(it===st)return console.warn("OpenReplay: beacon size overflow."),nt.reset(),void dt();it=Math.min(2*it,st),nt=new tt(it),dt()}ut++,at=!1}):(et=t.ingestPoint||et,rt=t.token||rt,ot=t.pageNo||ot,ht=t.startTimestamp||ht,ct=t.timeAdjustment||ct,yt=t.connAttemptCount||yt,_t=t.connAttemptGap||_t,st=t.beaconSizeLimit||st,it=Math.min(st,t.beaconSize||it),nt.isEmpty()&&dt(),void(null===lt&&(lt=setInterval(vt,1e4))));vt()};
|
|
47
47
|
`], { type: 'text/javascript' })));
|
|
48
48
|
this.worker.onerror = e => {
|
|
49
49
|
this._debug("webworker_error", e);
|
|
@@ -203,13 +203,18 @@ class App {
|
|
|
203
203
|
connAttemptGap: this.options.connAttemptGap,
|
|
204
204
|
};
|
|
205
205
|
this.worker.postMessage(messageData); // brings delay of 10th ms?
|
|
206
|
+
let token = sessionStorage.getItem(this.options.session_token_key);
|
|
207
|
+
const tokenIsActive = localStorage.getItem("__or_at_" + token);
|
|
208
|
+
if (tokenIsActive) {
|
|
209
|
+
token = null;
|
|
210
|
+
}
|
|
206
211
|
return window.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
207
212
|
method: 'POST',
|
|
208
213
|
headers: {
|
|
209
214
|
'Content-Type': 'application/json',
|
|
210
215
|
},
|
|
211
216
|
body: JSON.stringify({
|
|
212
|
-
token
|
|
217
|
+
token,
|
|
213
218
|
userUUID: localStorage.getItem(this.options.local_uuid_key),
|
|
214
219
|
projectKey: this.projectKey,
|
|
215
220
|
revID: this.revID,
|
|
@@ -240,6 +245,13 @@ class App {
|
|
|
240
245
|
}
|
|
241
246
|
sessionStorage.setItem(this.options.session_token_key, token);
|
|
242
247
|
localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
248
|
+
localStorage.setItem("__or_at_" + token, "true");
|
|
249
|
+
this.attachEventListener(window, 'beforeunload', () => {
|
|
250
|
+
localStorage.removeItem("__or_at_" + token);
|
|
251
|
+
}, false);
|
|
252
|
+
this.attachEventListener(window, 'pagehide', () => {
|
|
253
|
+
localStorage.removeItem("__or_at_" + token);
|
|
254
|
+
}, false);
|
|
243
255
|
if (typeof sessionID === 'string') {
|
|
244
256
|
this._sessionID = sessionID;
|
|
245
257
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const observer_js_1 = require("./observer.js");
|
|
4
|
+
const index_js_1 = require("../../messages/index.js");
|
|
5
|
+
class IFrameObserver extends observer_js_1.default {
|
|
6
|
+
observe(iframe) {
|
|
7
|
+
const doc = iframe.contentDocument;
|
|
8
|
+
const hostID = this.app.nodes.getID(iframe);
|
|
9
|
+
if (!doc || hostID === undefined) {
|
|
10
|
+
return;
|
|
11
|
+
} //log TODO common app.logger
|
|
12
|
+
// Have to observe document, because the inner <html> might be changed
|
|
13
|
+
this.observeRoot(doc, (docID) => {
|
|
14
|
+
if (docID === undefined) {
|
|
15
|
+
console.log("OpenReplay: Iframe document not bound");
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
this.app.send((0, index_js_1.CreateIFrameDocument)(hostID, docID));
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.default = IFrameObserver;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import App from "../index.js";
|
|
2
|
+
export interface Window extends globalThis.Window {
|
|
3
|
+
HTMLInputElement: typeof HTMLInputElement;
|
|
4
|
+
HTMLLinkElement: typeof HTMLLinkElement;
|
|
5
|
+
HTMLStyleElement: typeof HTMLStyleElement;
|
|
6
|
+
SVGStyleElement: typeof SVGStyleElement;
|
|
7
|
+
HTMLIFrameElement: typeof HTMLIFrameElement;
|
|
8
|
+
Text: typeof Text;
|
|
9
|
+
Element: typeof Element;
|
|
10
|
+
ShadowRoot: typeof ShadowRoot;
|
|
11
|
+
}
|
|
12
|
+
declare type WindowConstructor = Document | Element | Text | ShadowRoot | HTMLInputElement | HTMLLinkElement | HTMLStyleElement | HTMLIFrameElement;
|
|
13
|
+
declare type Constructor<T> = {
|
|
14
|
+
new (...args: any[]): T;
|
|
15
|
+
name: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function isInstance<T extends WindowConstructor>(node: Node, constr: Constructor<T>): node is T;
|
|
18
|
+
export interface Options {
|
|
19
|
+
obscureTextEmails: boolean;
|
|
20
|
+
obscureTextNumbers: boolean;
|
|
21
|
+
}
|
|
22
|
+
export default abstract class Observer<AdditionalOptions = {}> {
|
|
23
|
+
protected readonly app: App;
|
|
24
|
+
protected readonly context: Window;
|
|
25
|
+
private readonly observer;
|
|
26
|
+
private readonly commited;
|
|
27
|
+
private readonly recents;
|
|
28
|
+
private readonly myNodes;
|
|
29
|
+
private readonly indexes;
|
|
30
|
+
private readonly attributesList;
|
|
31
|
+
private readonly textSet;
|
|
32
|
+
private readonly textMasked;
|
|
33
|
+
protected readonly options: Options & AdditionalOptions;
|
|
34
|
+
private readonly inUpperContext;
|
|
35
|
+
constructor(app: App, options: Partial<Options> & AdditionalOptions, context?: Window);
|
|
36
|
+
private clear;
|
|
37
|
+
private sendNodeAttribute;
|
|
38
|
+
getInnerTextSecure(el: HTMLElement): string;
|
|
39
|
+
private checkObscure;
|
|
40
|
+
private sendNodeData;
|
|
41
|
+
private bindNode;
|
|
42
|
+
private bindTree;
|
|
43
|
+
private unbindNode;
|
|
44
|
+
private _commitNode;
|
|
45
|
+
private commitNode;
|
|
46
|
+
private commitNodes;
|
|
47
|
+
protected observeRoot(node: Node, beforeCommit: (id?: number) => unknown, nodeToBind?: Node): void;
|
|
48
|
+
disconnect(): void;
|
|
49
|
+
}
|
|
50
|
+
export {};
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isInstance = void 0;
|
|
4
|
+
const utils_js_1 = require("../../utils.js");
|
|
5
|
+
const index_js_1 = require("../../messages/index.js");
|
|
6
|
+
function isSVGElement(node) {
|
|
7
|
+
return node.namespaceURI === 'http://www.w3.org/2000/svg';
|
|
8
|
+
}
|
|
9
|
+
// TODO: we need a type expert here so we won't have to ignore the lines
|
|
10
|
+
// TODO: use it everywhere (static function; export from which file? <-- global Window typing required)
|
|
11
|
+
function isInstance(node, constr) {
|
|
12
|
+
const doc = node.ownerDocument;
|
|
13
|
+
if (!doc) { // null if Document
|
|
14
|
+
return constr.name === 'Document';
|
|
15
|
+
}
|
|
16
|
+
let context =
|
|
17
|
+
// @ts-ignore (for EI, Safary)
|
|
18
|
+
doc.parentWindow ||
|
|
19
|
+
doc.defaultView; // TODO: smart global typing for Window object
|
|
20
|
+
while (context.parent && context.parent !== context) {
|
|
21
|
+
// @ts-ignore
|
|
22
|
+
if (node instanceof context[constr.name]) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// @ts-ignore
|
|
26
|
+
context = context.parent;
|
|
27
|
+
}
|
|
28
|
+
// @ts-ignore
|
|
29
|
+
return node instanceof context[constr.name];
|
|
30
|
+
}
|
|
31
|
+
exports.isInstance = isInstance;
|
|
32
|
+
function isIgnored(node) {
|
|
33
|
+
if (isInstance(node, Text)) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
if (!isInstance(node, Element)) {
|
|
37
|
+
return true;
|
|
38
|
+
}
|
|
39
|
+
const tag = node.tagName.toUpperCase();
|
|
40
|
+
if (tag === 'LINK') {
|
|
41
|
+
const rel = node.getAttribute('rel');
|
|
42
|
+
const as = node.getAttribute('as');
|
|
43
|
+
return !((rel === null || rel === void 0 ? void 0 : rel.includes('stylesheet')) || as === "style" || as === "font");
|
|
44
|
+
}
|
|
45
|
+
return (tag === 'SCRIPT' ||
|
|
46
|
+
tag === 'NOSCRIPT' ||
|
|
47
|
+
tag === 'META' ||
|
|
48
|
+
tag === 'TITLE' ||
|
|
49
|
+
tag === 'BASE');
|
|
50
|
+
}
|
|
51
|
+
function isRootNode(node) {
|
|
52
|
+
return isInstance(node, Document) || isInstance(node, ShadowRoot);
|
|
53
|
+
}
|
|
54
|
+
function isObservable(node) {
|
|
55
|
+
if (isRootNode(node)) {
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
return !isIgnored(node);
|
|
59
|
+
}
|
|
60
|
+
class Observer {
|
|
61
|
+
constructor(app, options, context = window) {
|
|
62
|
+
this.app = app;
|
|
63
|
+
this.context = context;
|
|
64
|
+
this.commited = [];
|
|
65
|
+
this.recents = [];
|
|
66
|
+
this.myNodes = [];
|
|
67
|
+
this.indexes = [];
|
|
68
|
+
this.attributesList = [];
|
|
69
|
+
this.textSet = new Set();
|
|
70
|
+
this.textMasked = new Set();
|
|
71
|
+
this.options = Object.assign({
|
|
72
|
+
obscureTextEmails: true,
|
|
73
|
+
obscureTextNumbers: false,
|
|
74
|
+
}, options);
|
|
75
|
+
this.inUpperContext = context.parent === context;
|
|
76
|
+
this.observer = new MutationObserver(this.app.safe((mutations) => {
|
|
77
|
+
for (const mutation of mutations) {
|
|
78
|
+
const target = mutation.target;
|
|
79
|
+
const type = mutation.type;
|
|
80
|
+
// TODO TODO TODO: move to iframe_observer/remove??? (check if )
|
|
81
|
+
// Special case
|
|
82
|
+
// 'childList' on Document might happen in case of iframe.
|
|
83
|
+
// TODO: generalize as much as possible
|
|
84
|
+
// if (isInstance(target, Document) // Also ShadowRoot can be here
|
|
85
|
+
// && type === 'childList'
|
|
86
|
+
// //&& new Array(mutation.addedNodes).some(node => isInstance(node, HTMLHtmlElement))
|
|
87
|
+
// ) {
|
|
88
|
+
// const parentFrame = target.defaultView?.frameElement
|
|
89
|
+
// if (!parentFrame) { continue }
|
|
90
|
+
// this.bindTree(target.documentElement)
|
|
91
|
+
// const frameID = this.app.nodes.getID(parentFrame)
|
|
92
|
+
// const docID = this.app.nodes.getID(target.documentElement)
|
|
93
|
+
// if (frameID === undefined || docID === undefined) { continue }
|
|
94
|
+
// this.app.send(CreateIFrameDocument(frameID, docID));
|
|
95
|
+
// continue;
|
|
96
|
+
// }
|
|
97
|
+
if (!isObservable(target) || !context.document.contains(target)) {
|
|
98
|
+
continue;
|
|
99
|
+
}
|
|
100
|
+
if (type === 'childList') {
|
|
101
|
+
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
102
|
+
this.bindTree(mutation.removedNodes[i]);
|
|
103
|
+
}
|
|
104
|
+
for (let i = 0; i < mutation.addedNodes.length; i++) {
|
|
105
|
+
this.bindTree(mutation.addedNodes[i]);
|
|
106
|
+
}
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
const id = this.app.nodes.getID(target);
|
|
110
|
+
if (id === undefined) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
if (id >= this.recents.length) { // TODO: something more convinient
|
|
114
|
+
this.recents[id] = undefined;
|
|
115
|
+
}
|
|
116
|
+
if (type === 'attributes') {
|
|
117
|
+
const name = mutation.attributeName;
|
|
118
|
+
if (name === null) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
let attr = this.attributesList[id];
|
|
122
|
+
if (attr === undefined) {
|
|
123
|
+
this.attributesList[id] = attr = new Set();
|
|
124
|
+
}
|
|
125
|
+
attr.add(name);
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (type === 'characterData') {
|
|
129
|
+
this.textSet.add(id);
|
|
130
|
+
continue;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
this.commitNodes();
|
|
134
|
+
}));
|
|
135
|
+
}
|
|
136
|
+
clear() {
|
|
137
|
+
this.commited.length = 0;
|
|
138
|
+
this.recents.length = 0;
|
|
139
|
+
this.indexes.length = 1;
|
|
140
|
+
this.attributesList.length = 0;
|
|
141
|
+
this.textSet.clear();
|
|
142
|
+
//this.textMasked.clear();
|
|
143
|
+
}
|
|
144
|
+
sendNodeAttribute(id, node, name, value) {
|
|
145
|
+
if (isSVGElement(node)) {
|
|
146
|
+
if (name.substr(0, 6) === 'xlink:') {
|
|
147
|
+
name = name.substr(6);
|
|
148
|
+
}
|
|
149
|
+
if (value === null) {
|
|
150
|
+
this.app.send(new index_js_1.RemoveNodeAttribute(id, name));
|
|
151
|
+
}
|
|
152
|
+
else if (name === 'href') {
|
|
153
|
+
if (value.length > 1e5) {
|
|
154
|
+
value = '';
|
|
155
|
+
}
|
|
156
|
+
this.app.send(new index_js_1.SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
this.app.send(new index_js_1.SetNodeAttribute(id, name, value));
|
|
160
|
+
}
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
if (name === 'src' ||
|
|
164
|
+
name === 'srcset' ||
|
|
165
|
+
name === 'integrity' ||
|
|
166
|
+
name === 'crossorigin' ||
|
|
167
|
+
name === 'autocomplete' ||
|
|
168
|
+
name.substr(0, 2) === 'on') {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
if (name === 'value' &&
|
|
172
|
+
isInstance(node, HTMLInputElement) &&
|
|
173
|
+
node.type !== 'button' &&
|
|
174
|
+
node.type !== 'reset' &&
|
|
175
|
+
node.type !== 'submit') {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (value === null) {
|
|
179
|
+
this.app.send(new index_js_1.RemoveNodeAttribute(id, name));
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (name === 'style' || name === 'href' && isInstance(node, HTMLLinkElement)) {
|
|
183
|
+
this.app.send(new index_js_1.SetNodeAttributeURLBased(id, name, value, this.app.getBaseHref()));
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
if (name === 'href' || value.length > 1e5) {
|
|
187
|
+
value = '';
|
|
188
|
+
}
|
|
189
|
+
this.app.send(new index_js_1.SetNodeAttribute(id, name, value));
|
|
190
|
+
}
|
|
191
|
+
/* TODO: abstract sanitation */
|
|
192
|
+
getInnerTextSecure(el) {
|
|
193
|
+
const id = this.app.nodes.getID(el);
|
|
194
|
+
if (!id) {
|
|
195
|
+
return '';
|
|
196
|
+
}
|
|
197
|
+
return this.checkObscure(id, el.innerText);
|
|
198
|
+
}
|
|
199
|
+
checkObscure(id, data) {
|
|
200
|
+
if (this.textMasked.has(id)) {
|
|
201
|
+
return data.replace(/[^\f\n\r\t\v\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]/g, '█');
|
|
202
|
+
}
|
|
203
|
+
if (this.options.obscureTextNumbers) {
|
|
204
|
+
data = data.replace(/\d/g, '0');
|
|
205
|
+
}
|
|
206
|
+
if (this.options.obscureTextEmails) {
|
|
207
|
+
data = data.replace(/([^\s]+)@([^\s]+)\.([^\s]+)/g, (...f) => (0, utils_js_1.stars)(f[1]) + '@' + (0, utils_js_1.stars)(f[2]) + '.' + (0, utils_js_1.stars)(f[3]));
|
|
208
|
+
}
|
|
209
|
+
return data;
|
|
210
|
+
}
|
|
211
|
+
sendNodeData(id, parentElement, data) {
|
|
212
|
+
if (isInstance(parentElement, HTMLStyleElement) || isInstance(parentElement, SVGStyleElement)) {
|
|
213
|
+
this.app.send(new index_js_1.SetCSSDataURLBased(id, data, this.app.getBaseHref()));
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
data = this.checkObscure(id, data);
|
|
217
|
+
this.app.send(new index_js_1.SetNodeData(id, data));
|
|
218
|
+
}
|
|
219
|
+
/* end TODO: abstract sanitation */
|
|
220
|
+
bindNode(node) {
|
|
221
|
+
const r = this.app.nodes.registerNode(node);
|
|
222
|
+
const id = r[0];
|
|
223
|
+
this.recents[id] = r[1] || this.recents[id] || false;
|
|
224
|
+
this.myNodes[id] = true;
|
|
225
|
+
}
|
|
226
|
+
bindTree(node) {
|
|
227
|
+
if (!isObservable(node)) {
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
this.bindNode(node);
|
|
231
|
+
const walker = document.createTreeWalker(node, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
|
|
232
|
+
acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) !== undefined
|
|
233
|
+
? NodeFilter.FILTER_REJECT
|
|
234
|
+
: NodeFilter.FILTER_ACCEPT,
|
|
235
|
+
},
|
|
236
|
+
// @ts-ignore
|
|
237
|
+
false);
|
|
238
|
+
while (walker.nextNode()) {
|
|
239
|
+
this.bindNode(walker.currentNode);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
unbindNode(node) {
|
|
243
|
+
const id = this.app.nodes.unregisterNode(node);
|
|
244
|
+
if (id !== undefined && this.recents[id] === false) {
|
|
245
|
+
this.app.send(new index_js_1.RemoveNode(id));
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
_commitNode(id, node) {
|
|
249
|
+
if (isRootNode(node)) {
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
const parent = node.parentNode;
|
|
253
|
+
let parentID;
|
|
254
|
+
// Disable parent check for the upper context HTMLHtmlElement, because it is root there... (before)
|
|
255
|
+
// TODO: get rid of "special" cases (there is an issue with CreateDocument altered behaviour though)
|
|
256
|
+
// TODO: Clean the logic (though now it workd fine)
|
|
257
|
+
if (!isInstance(node, HTMLHtmlElement) || !this.inUpperContext) {
|
|
258
|
+
if (parent === null) {
|
|
259
|
+
this.unbindNode(node);
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
parentID = this.app.nodes.getID(parent);
|
|
263
|
+
if (parentID === undefined) {
|
|
264
|
+
this.unbindNode(node);
|
|
265
|
+
return false;
|
|
266
|
+
}
|
|
267
|
+
if (!this.commitNode(parentID)) {
|
|
268
|
+
this.unbindNode(node);
|
|
269
|
+
return false;
|
|
270
|
+
}
|
|
271
|
+
if (this.textMasked.has(parentID) ||
|
|
272
|
+
(isInstance(node, Element) && (0, utils_js_1.hasOpenreplayAttribute)(node, 'masked'))) {
|
|
273
|
+
this.textMasked.add(id);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
let sibling = node.previousSibling;
|
|
277
|
+
while (sibling !== null) {
|
|
278
|
+
const siblingID = this.app.nodes.getID(sibling);
|
|
279
|
+
if (siblingID !== undefined) {
|
|
280
|
+
this.commitNode(siblingID);
|
|
281
|
+
this.indexes[id] = this.indexes[siblingID] + 1;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
sibling = sibling.previousSibling;
|
|
285
|
+
}
|
|
286
|
+
if (sibling === null) {
|
|
287
|
+
this.indexes[id] = 0; //
|
|
288
|
+
}
|
|
289
|
+
const isNew = this.recents[id];
|
|
290
|
+
const index = this.indexes[id];
|
|
291
|
+
if (index === undefined) {
|
|
292
|
+
throw 'commitNode: missing node index';
|
|
293
|
+
}
|
|
294
|
+
if (isNew === true) {
|
|
295
|
+
if (isInstance(node, Element)) {
|
|
296
|
+
if (parentID !== undefined) {
|
|
297
|
+
this.app.send(new index_js_1.CreateElementNode(id, parentID, index, node.tagName, isSVGElement(node)));
|
|
298
|
+
}
|
|
299
|
+
for (let i = 0; i < node.attributes.length; i++) {
|
|
300
|
+
const attr = node.attributes[i];
|
|
301
|
+
this.sendNodeAttribute(id, node, attr.nodeName, attr.value);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
else if (isInstance(node, Text)) {
|
|
305
|
+
// for text node id != 0, hence parentID !== undefined and parent is Element
|
|
306
|
+
this.app.send(new index_js_1.CreateTextNode(id, parentID, index));
|
|
307
|
+
this.sendNodeData(id, parent, node.data);
|
|
308
|
+
}
|
|
309
|
+
return true;
|
|
310
|
+
}
|
|
311
|
+
if (isNew === false && parentID !== undefined) {
|
|
312
|
+
this.app.send(new index_js_1.MoveNode(id, parentID, index));
|
|
313
|
+
}
|
|
314
|
+
const attr = this.attributesList[id];
|
|
315
|
+
if (attr !== undefined) {
|
|
316
|
+
if (!isInstance(node, Element)) {
|
|
317
|
+
throw 'commitNode: node is not an element';
|
|
318
|
+
}
|
|
319
|
+
for (const name of attr) {
|
|
320
|
+
this.sendNodeAttribute(id, node, name, node.getAttribute(name));
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
if (this.textSet.has(id)) {
|
|
324
|
+
if (!isInstance(node, Text)) {
|
|
325
|
+
throw 'commitNode: node is not a text';
|
|
326
|
+
}
|
|
327
|
+
// for text node id != 0, hence parent is Element
|
|
328
|
+
this.sendNodeData(id, parent, node.data);
|
|
329
|
+
}
|
|
330
|
+
return true;
|
|
331
|
+
}
|
|
332
|
+
commitNode(id) {
|
|
333
|
+
const node = this.app.nodes.getNode(id);
|
|
334
|
+
if (node === undefined) {
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
const cmt = this.commited[id];
|
|
338
|
+
if (cmt !== undefined) {
|
|
339
|
+
return cmt;
|
|
340
|
+
}
|
|
341
|
+
return (this.commited[id] = this._commitNode(id, node));
|
|
342
|
+
}
|
|
343
|
+
commitNodes() {
|
|
344
|
+
let node;
|
|
345
|
+
for (let id = 0; id < this.recents.length; id++) {
|
|
346
|
+
// TODO: make things/logic nice here.
|
|
347
|
+
// commit required in any case if recents[id] true or false (in case of unbinding).
|
|
348
|
+
// ???!?!?R@TW:$HKJ$WLKn
|
|
349
|
+
if (!this.myNodes[id]) {
|
|
350
|
+
continue;
|
|
351
|
+
}
|
|
352
|
+
this.commitNode(id);
|
|
353
|
+
if (this.recents[id] === true && (node = this.app.nodes.getNode(id))) {
|
|
354
|
+
this.app.nodes.callNodeCallbacks(node);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
this.clear();
|
|
358
|
+
}
|
|
359
|
+
// ISSSUE
|
|
360
|
+
observeRoot(node, beforeCommit, nodeToBind = node) {
|
|
361
|
+
this.observer.observe(node, {
|
|
362
|
+
childList: true,
|
|
363
|
+
attributes: true,
|
|
364
|
+
characterData: true,
|
|
365
|
+
subtree: true,
|
|
366
|
+
attributeOldValue: false,
|
|
367
|
+
characterDataOldValue: false,
|
|
368
|
+
});
|
|
369
|
+
this.bindTree(nodeToBind);
|
|
370
|
+
beforeCommit(this.app.nodes.getID(node));
|
|
371
|
+
this.commitNodes();
|
|
372
|
+
}
|
|
373
|
+
disconnect() {
|
|
374
|
+
this.observer.disconnect();
|
|
375
|
+
this.clear();
|
|
376
|
+
// to sanitizer
|
|
377
|
+
this.textMasked.clear();
|
|
378
|
+
this.myNodes.length = 0;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
exports.default = Observer;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const observer_js_1 = require("./observer.js");
|
|
4
|
+
const index_js_1 = require("../../messages/index.js");
|
|
5
|
+
class ShadowRootObserver extends observer_js_1.default {
|
|
6
|
+
observe(el) {
|
|
7
|
+
const shRoot = el.shadowRoot;
|
|
8
|
+
const hostID = this.app.nodes.getID(el);
|
|
9
|
+
if (!shRoot || hostID === undefined) {
|
|
10
|
+
return;
|
|
11
|
+
} // log
|
|
12
|
+
this.observeRoot(shRoot, (rootID) => {
|
|
13
|
+
if (rootID === undefined) {
|
|
14
|
+
console.log("OpenReplay: Shadow Root was not bound");
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
this.app.send((0, index_js_1.CreateIFrameDocument)(hostID, rootID));
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
exports.default = ShadowRootObserver;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import Observer from "./observer.js";
|
|
2
|
+
import type { Options as BaseOptions } from "./observer.js";
|
|
3
|
+
import App from "../index.js";
|
|
4
|
+
export interface Options extends Partial<BaseOptions> {
|
|
5
|
+
captureIFrames: boolean;
|
|
6
|
+
}
|
|
7
|
+
export default class TopObserver extends Observer<Options> {
|
|
8
|
+
constructor(app: App, options: Partial<Options>);
|
|
9
|
+
private iframeObservers;
|
|
10
|
+
private handleIframe;
|
|
11
|
+
private shadowRootObservers;
|
|
12
|
+
private handleShadowRoot;
|
|
13
|
+
observe(): void;
|
|
14
|
+
disconnect(): void;
|
|
15
|
+
}
|