@openreplay/tracker 3.4.9 → 3.4.10

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