@openreplay/tracker 4.0.0 → 4.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/app/guards.d.ts +1 -0
- package/cjs/app/guards.js +6 -1
- package/cjs/app/index.d.ts +1 -1
- package/cjs/app/index.js +16 -10
- package/cjs/app/messages.gen.d.ts +1 -0
- package/cjs/app/messages.gen.js +10 -1
- package/cjs/app/nodes.d.ts +1 -1
- package/cjs/app/nodes.js +3 -5
- package/cjs/app/observer/iframe_observer.js +1 -0
- package/cjs/app/observer/iframe_offsets.d.ts +8 -0
- package/cjs/app/observer/iframe_offsets.js +59 -0
- package/cjs/app/observer/observer.js +4 -4
- package/cjs/app/observer/top_observer.d.ts +2 -4
- package/cjs/app/observer/top_observer.js +11 -21
- package/cjs/app/sanitizer.d.ts +10 -4
- package/cjs/app/sanitizer.js +33 -15
- package/cjs/app/session.js +1 -1
- package/cjs/common/messages.gen.d.ts +8 -2
- package/cjs/common/messages.gen.js +1 -0
- package/cjs/index.d.ts +1 -0
- package/cjs/index.js +7 -7
- package/cjs/modules/constructedStyleSheets.d.ts +4 -0
- package/cjs/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +21 -20
- package/cjs/modules/cssrules.js +65 -18
- package/cjs/modules/img.js +27 -19
- package/cjs/modules/input.js +2 -2
- package/cjs/modules/mouse.js +11 -7
- package/cjs/modules/scroll.js +32 -12
- package/cjs/utils.d.ts +5 -3
- package/cjs/utils.js +18 -13
- package/lib/app/guards.d.ts +1 -0
- package/lib/app/guards.js +4 -0
- package/lib/app/index.d.ts +1 -1
- package/lib/app/index.js +16 -10
- package/lib/app/messages.gen.d.ts +1 -0
- package/lib/app/messages.gen.js +8 -0
- package/lib/app/nodes.d.ts +1 -1
- package/lib/app/nodes.js +3 -5
- package/lib/app/observer/iframe_observer.js +1 -0
- package/lib/app/observer/iframe_offsets.d.ts +8 -0
- package/lib/app/observer/iframe_offsets.js +56 -0
- package/lib/app/observer/observer.js +4 -4
- package/lib/app/observer/top_observer.d.ts +2 -4
- package/lib/app/observer/top_observer.js +11 -21
- package/lib/app/sanitizer.d.ts +10 -4
- package/lib/app/sanitizer.js +32 -15
- package/lib/app/session.js +1 -1
- package/lib/common/messages.gen.d.ts +8 -2
- package/lib/common/messages.gen.js +1 -0
- package/lib/common/tsconfig.tsbuildinfo +1 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +5 -6
- package/lib/modules/constructedStyleSheets.d.ts +4 -0
- package/lib/modules/{adoptedStyleSheets.js → constructedStyleSheets.js} +20 -21
- package/lib/modules/cssrules.js +67 -19
- package/lib/modules/img.js +28 -20
- package/lib/modules/input.js +3 -3
- package/lib/modules/mouse.js +11 -7
- package/lib/modules/scroll.js +33 -13
- package/lib/utils.d.ts +5 -3
- package/lib/utils.js +17 -11
- package/package.json +1 -1
- package/cjs/modules/adoptedStyleSheets.d.ts +0 -2
- package/lib/modules/adoptedStyleSheets.d.ts +0 -2
package/cjs/app/guards.d.ts
CHANGED
package/cjs/app/guards.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.hasTag = exports.isRootNode = exports.isDocument = exports.isTextNode = exports.isElementNode = exports.isSVGElement = void 0;
|
|
3
|
+
exports.hasTag = exports.isRootNode = exports.isDocument = exports.isTextNode = exports.isElementNode = exports.isSVGElement = exports.isNode = void 0;
|
|
4
|
+
//@ts-ignore
|
|
5
|
+
function isNode(sth) {
|
|
6
|
+
return !!sth && sth.nodeType != null;
|
|
7
|
+
}
|
|
8
|
+
exports.isNode = isNode;
|
|
4
9
|
function isSVGElement(node) {
|
|
5
10
|
return node.namespaceURI === 'http://www.w3.org/2000/svg';
|
|
6
11
|
}
|
package/cjs/app/index.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export default class App {
|
|
|
77
77
|
private _debug;
|
|
78
78
|
send(message: Message, urgent?: boolean): void;
|
|
79
79
|
private commit;
|
|
80
|
-
safe<T extends (...args: any[]) => void>(fn: T): T;
|
|
80
|
+
safe<T extends (this: any, ...args: any[]) => void>(fn: T): T;
|
|
81
81
|
attachCommitCallback(cb: CommitCallback): void;
|
|
82
82
|
attachStartCallback(cb: StartCallback, useSafe?: boolean): void;
|
|
83
83
|
attachStopCallback(cb: () => any, useSafe?: boolean): void;
|
package/cjs/app/index.js
CHANGED
|
@@ -32,7 +32,7 @@ class App {
|
|
|
32
32
|
this.stopCallbacks = [];
|
|
33
33
|
this.commitCallbacks = [];
|
|
34
34
|
this.activityState = ActivityState.NotActive;
|
|
35
|
-
this.version = '4.0.
|
|
35
|
+
this.version = '4.0.2'; // TODO: version compatability check inside each plugin.
|
|
36
36
|
this.projectKey = projectKey;
|
|
37
37
|
this.options = Object.assign({
|
|
38
38
|
revID: '',
|
|
@@ -74,17 +74,17 @@ class App {
|
|
|
74
74
|
this.session.applySessionHash(sessionToken);
|
|
75
75
|
}
|
|
76
76
|
try {
|
|
77
|
-
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}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=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==
|
|
77
|
+
this.worker = new Worker(URL.createObjectURL(new Blob(['"use strict";class t{constructor(t,i,s,e=10,n=1e3){this.onUnauthorised=i,this.onFailure=s,this.MAX_ATTEMPTS_COUNT=e,this.ATTEMPT_TIMEOUT=n,this.attemptsCount=0,this.busy=!1,this.queue=[],this.token=null,this.ingestURL=t+"/v1/web/i"}authorise(t){this.token=t}push(t){this.busy||!this.token?this.queue.push(t):this.sendBatch(t)}retry(t){this.attemptsCount>=this.MAX_ATTEMPTS_COUNT?this.onFailure():(this.attemptsCount++,setTimeout(()=>this.sendBatch(t),this.ATTEMPT_TIMEOUT*this.attemptsCount))}sendBatch(t){this.busy=!0,fetch(this.ingestURL,{body:t,method:"POST",headers:{Authorization:"Bearer "+this.token},keepalive:t.length<65536}).then(i=>{if(401===i.status)return this.busy=!1,void this.onUnauthorised();if(i.status>=400)return void this.retry(t);this.attemptsCount=0;const s=this.queue.shift();s?this.sendBatch(s):this.busy=!1}).catch(i=>{console.warn("OpenReplay:",i),this.retry(t)})}clean(){this.queue.length=0}}const i="function"==typeof TextEncoder?new TextEncoder:{encode(t){const i=t.length,s=new Uint8Array(3*i);let e=-1;for(let n=0,r=0,h=0;h!==i;){if(n=t.charCodeAt(h),h+=1,n>=55296&&n<=56319){if(h===i){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;break}if(r=t.charCodeAt(h),!(r>=56320&&r<=57343)){s[e+=1]=239,s[e+=1]=191,s[e+=1]=189;continue}if(n=1024*(n-55296)+r-56320+65536,h+=1,n>65535){s[e+=1]=240|n>>>18,s[e+=1]=128|n>>>12&63,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n;continue}}n<=127?s[e+=1]=0|n:n<=2047?(s[e+=1]=192|n>>>6,s[e+=1]=128|63&n):(s[e+=1]=224|n>>>12,s[e+=1]=128|n>>>6&63,s[e+=1]=128|63&n)}return s.subarray(0,e+1)}};class s extends class{constructor(t){this.size=t,this.offset=0,this.checkpointOffset=0,this.data=new Uint8Array(t)}getCurrentOffset(){return this.offset}checkpoint(){this.checkpointOffset=this.offset}isEmpty(){return 0===this.offset}skip(t){return this.offset+=t,this.offset<=this.size}set(t,i){this.data.set(t,i)}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=i.encode(t),e=s.byteLength;return!(!this.uint(e)||this.offset+e>this.size)&&(this.data.set(s,this.offset),this.offset+=e,!0)}reset(){this.offset=0,this.checkpointOffset=0}flush(){const t=this.data.slice(0,this.checkpointOffset);return this.reset(),t}}{encode(t){switch(t[0]){case 81:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.int(t[4])&&this.string(t[5]);case 82:return this.uint(t[1])&&this.uint(t[2]);case 0:return this.uint(t[1]);case 4:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 5:return this.uint(t[1])&&this.uint(t[2]);case 6:return this.int(t[1])&&this.int(t[2]);case 7:return!0;case 8:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.string(t[4])&&this.boolean(t[5]);case 9:case 10:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 11:return this.uint(t[1]);case 12:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 13:case 14:return this.uint(t[1])&&this.string(t[2]);case 16:return this.uint(t[1])&&this.int(t[2])&&this.int(t[3]);case 17:return this.uint(t[1])&&this.string(t[2]);case 18:return this.uint(t[1])&&this.string(t[2])&&this.int(t[3]);case 19:return this.uint(t[1])&&this.boolean(t[2]);case 20:return this.uint(t[1])&&this.uint(t[2]);case 22:return this.string(t[1])&&this.string(t[2]);case 23:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7])&&this.uint(t[8])&&this.uint(t[9]);case 24:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3]);case 25:return this.string(t[1])&&this.string(t[2])&&this.string(t[3]);case 27:return this.string(t[1])&&this.string(t[2]);case 28:case 29:return this.string(t[1]);case 30:return this.string(t[1])&&this.string(t[2]);case 37:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3]);case 38:return this.uint(t[1])&&this.uint(t[2]);case 39:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.uint(t[7]);case 40:return this.string(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 41:return this.string(t[1])&&this.string(t[2]);case 42:return this.string(t[1]);case 44:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 45:case 46:return this.string(t[1])&&this.string(t[2]);case 47:return this.string(t[1])&&this.string(t[2])&&this.uint(t[3]);case 48:return this.string(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 49:return this.int(t[1])&&this.int(t[2])&&this.uint(t[3])&&this.uint(t[4]);case 53:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.uint(t[5])&&this.uint(t[6])&&this.string(t[7])&&this.string(t[8]);case 54:return this.uint(t[1])&&this.string(t[2]);case 55:return this.boolean(t[1]);case 59:return this.uint(t[1])&&this.uint(t[2])&&this.uint(t[3])&&this.uint(t[4])&&this.string(t[5])&&this.string(t[6])&&this.string(t[7]);case 60:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3])&&this.string(t[4]);case 61:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 63:case 64:return this.string(t[1])&&this.string(t[2]);case 67:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 69:return this.uint(t[1])&&this.uint(t[2])&&this.string(t[3])&&this.string(t[4]);case 70:return this.uint(t[1])&&this.uint(t[2]);case 71:return this.uint(t[1])&&this.string(t[2])&&this.string(t[3]);case 73:return this.uint(t[1])&&this.string(t[2])&&this.uint(t[3])&&this.string(t[4]);case 75:case 76:case 77:return this.uint(t[1])&&this.uint(t[2]);case 79:return this.string(t[1])&&this.string(t[2])}}}class e{constructor(t,i,e,n){this.pageNo=t,this.timestamp=i,this.url=e,this.onBatch=n,this.nextIndex=0,this.beaconSize=2e5,this.encoder=new s(this.beaconSize),this.sizeBuffer=new Uint8Array(3),this.isEmpty=!0,this.beaconSizeLimit=1e6,this.prepare()}writeType(t){return this.encoder.uint(t[0])}writeFields(t){return this.encoder.encode(t)}writeSizeAt(t,i){for(let i=0;i<3;i++)this.sizeBuffer[i]=t>>8*i;this.encoder.set(this.sizeBuffer,i)}prepare(){if(!this.encoder.isEmpty())return;const t=[81,1,this.pageNo,this.nextIndex,this.timestamp,this.url];this.writeType(t),this.writeFields(t),this.isEmpty=!0}writeWithSize(t){const i=this.encoder;if(!this.writeType(t)||!i.skip(3))return!1;const s=i.getCurrentOffset(),e=this.writeFields(t);if(e){const e=i.getCurrentOffset()-s;if(e>16777215)return console.warn("OpenReplay: max message size overflow."),!1;this.writeSizeAt(e,s-3),i.checkpoint(),this.isEmpty=this.isEmpty&&0===t[0],this.nextIndex++}return e}setBeaconSizeLimit(t){this.beaconSizeLimit=t}writeMessage(t){if(0===t[0]&&(this.timestamp=t[1]),4===t[0]&&(this.url=t[1]),!this.writeWithSize(t))for(this.finaliseBatch();!this.writeWithSize(t);){if(this.beaconSize===this.beaconSizeLimit)return console.warn("OpenReplay: beacon size overflow. Skipping large message.",t,this),this.encoder.reset(),void this.prepare();this.beaconSize=Math.min(2*this.beaconSize,this.beaconSizeLimit),this.encoder=new s(this.beaconSize),this.prepare()}}finaliseBatch(){this.isEmpty||(this.onBatch(this.encoder.flush()),this.prepare())}clean(){this.encoder.reset()}}var n;!function(t){t[t.NotActive=0]="NotActive",t[t.Starting=1]="Starting",t[t.Stopping=2]="Stopping",t[t.Active=3]="Active"}(n||(n={}));let r=null,h=null;function u(){h&&h.finaliseBatch()}function a(){n.Stopping,null!==f&&(clearInterval(f),f=null),h&&(h.clean(),h=null),r&&(r.clean(),r=null),n.NotActive}function o(){self.postMessage("restart"),a()}n.NotActive;let c,f=null;self.onmessage=({data:i})=>{if(null!=i){if("stop"===i)return u(),void a();if(Array.isArray(i)){if(!h)throw new Error("WebWorker: writer not initialised. Service Should be Started.");const t=h;i.forEach(i=>{55===i[0]&&(i[1]?c=setTimeout(()=>o(),18e5):clearTimeout(c)),t.writeMessage(i)})}else{if("start"===i.type)return n.Starting,r=new t(i.ingestPoint,()=>{o()},()=>{self.postMessage("failed"),a()},i.connAttemptCount,i.connAttemptGap),h=new e(i.pageNo,i.timestamp,i.url,t=>r&&r.push(t)),null===f&&(f=setInterval(u,1e4)),n.Active;if("auth"===i.type){if(!r)throw new Error("WebWorker: sender not initialised. Received auth.");if(!h)throw new Error("WebWorker: writer not initialised. Received auth.");return r.authorise(i.token),void(i.beaconSizeLimit&&h.setBeaconSizeLimit(i.beaconSizeLimit))}}}else u()};'], { type: 'text/javascript' })));
|
|
78
78
|
this.worker.onerror = (e) => {
|
|
79
79
|
this._debug('webworker_error', e);
|
|
80
80
|
};
|
|
81
81
|
this.worker.onmessage = ({ data }) => {
|
|
82
82
|
if (data === 'failed') {
|
|
83
|
-
this.stop();
|
|
83
|
+
this.stop(false);
|
|
84
84
|
this._debug('worker_failed', {}); // add context (from worker)
|
|
85
85
|
}
|
|
86
86
|
else if (data === 'restart') {
|
|
87
|
-
this.stop();
|
|
87
|
+
this.stop(false);
|
|
88
88
|
this.start({ forceNew: true });
|
|
89
89
|
}
|
|
90
90
|
};
|
|
@@ -153,8 +153,6 @@ class App {
|
|
|
153
153
|
}; // TODO: correct typing
|
|
154
154
|
}
|
|
155
155
|
attachCommitCallback(cb) {
|
|
156
|
-
// TODO!: what if start callback added when activityState === Active ?
|
|
157
|
-
// For example - attachEventListener() called during dynamic <iframe> appearance
|
|
158
156
|
this.commitCallbacks.push(cb);
|
|
159
157
|
}
|
|
160
158
|
attachStartCallback(cb, useSafe = false) {
|
|
@@ -169,6 +167,7 @@ class App {
|
|
|
169
167
|
}
|
|
170
168
|
this.stopCallbacks.push(cb);
|
|
171
169
|
}
|
|
170
|
+
// Use app.nodes.attachNodeListener for registered nodes instead
|
|
172
171
|
attachEventListener(target, type, listener, useSafe = true, useCapture = true) {
|
|
173
172
|
if (useSafe) {
|
|
174
173
|
listener = this.safe(listener);
|
|
@@ -220,7 +219,7 @@ class App {
|
|
|
220
219
|
return this.options.ingestPoint.replace(/ingest$/, `${projectID}/session/${sessionID}`);
|
|
221
220
|
}
|
|
222
221
|
getHost() {
|
|
223
|
-
return new URL(this.options.ingestPoint).
|
|
222
|
+
return new URL(this.options.ingestPoint).host;
|
|
224
223
|
}
|
|
225
224
|
getProjectKey() {
|
|
226
225
|
return this.projectKey;
|
|
@@ -291,14 +290,15 @@ class App {
|
|
|
291
290
|
});
|
|
292
291
|
const sReset = this.sessionStorage.getItem(this.options.session_reset_key);
|
|
293
292
|
this.sessionStorage.removeItem(this.options.session_reset_key);
|
|
293
|
+
const shouldReset = startOpts.forceNew || sReset !== null;
|
|
294
294
|
return window
|
|
295
295
|
.fetch(this.options.ingestPoint + '/v1/web/start', {
|
|
296
296
|
method: 'POST',
|
|
297
297
|
headers: {
|
|
298
298
|
'Content-Type': 'application/json',
|
|
299
299
|
},
|
|
300
|
-
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: this.session.getSessionToken(), deviceMemory: performance_js_1.deviceMemory,
|
|
301
|
-
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit
|
|
300
|
+
body: JSON.stringify(Object.assign(Object.assign({}, this.getTrackerInfo()), { timestamp, userID: this.session.getInfo().userID, token: shouldReset ? undefined : this.session.getSessionToken(), deviceMemory: performance_js_1.deviceMemory,
|
|
301
|
+
jsHeapSizeLimit: performance_js_1.jsHeapSizeLimit })),
|
|
302
302
|
})
|
|
303
303
|
.then((r) => {
|
|
304
304
|
if (r.status === 200) {
|
|
@@ -316,6 +316,9 @@ class App {
|
|
|
316
316
|
if (!this.worker) {
|
|
317
317
|
return Promise.reject('no worker found after start request (this might not happen)');
|
|
318
318
|
}
|
|
319
|
+
if (this.activityState === ActivityState.NotActive) {
|
|
320
|
+
return Promise.reject('Tracker stopped during authorisation');
|
|
321
|
+
}
|
|
319
322
|
const { token, userUUID, sessionID, projectID, beaconSizeLimit, startTimestamp, // real startTS, derived from sessionID
|
|
320
323
|
} = r;
|
|
321
324
|
if (typeof token !== 'string' ||
|
|
@@ -325,9 +328,12 @@ class App {
|
|
|
325
328
|
(typeof beaconSizeLimit !== 'number' && typeof beaconSizeLimit !== 'undefined')) {
|
|
326
329
|
return Promise.reject(`Incorrect server response: ${JSON.stringify(r)}`);
|
|
327
330
|
}
|
|
331
|
+
if (sessionID !== this.session.getInfo().sessionID) {
|
|
332
|
+
this.session.reset();
|
|
333
|
+
}
|
|
328
334
|
this.session.setSessionToken(token);
|
|
329
|
-
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
330
335
|
this.session.update({ sessionID, timestamp: startTimestamp || timestamp, projectID }); // TODO: no no-explicit 'any'
|
|
336
|
+
this.localStorage.setItem(this.options.local_uuid_key, userUUID);
|
|
331
337
|
const startWorkerMsg = {
|
|
332
338
|
type: 'auth',
|
|
333
339
|
token,
|
|
@@ -55,3 +55,4 @@ export declare function AdoptedSSInsertRuleURLBased(sheetID: number, rule: strin
|
|
|
55
55
|
export declare function AdoptedSSDeleteRule(sheetID: number, index: number): Messages.AdoptedSSDeleteRule;
|
|
56
56
|
export declare function AdoptedSSAddOwner(sheetID: number, id: number): Messages.AdoptedSSAddOwner;
|
|
57
57
|
export declare function AdoptedSSRemoveOwner(sheetID: number, id: number): Messages.AdoptedSSRemoveOwner;
|
|
58
|
+
export declare function Zustand(mutation: string, state: string): Messages.Zustand;
|
package/cjs/app/messages.gen.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// Auto-generated, do not edit
|
|
3
|
+
/* eslint-disable */
|
|
3
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
5
|
exports.CreateIFrameDocument = exports.MouseClick = exports.CSSInsertRuleURLBased = exports.CustomIssue = exports.TechnicalInfo = exports.SetCSSDataURLBased = exports.SetNodeAttributeURLBased = exports.LongTask = exports.SetPageVisibility = exports.ConnectionInformation = exports.ResourceTiming = exports.PerformanceTrack = exports.GraphQL = exports.NgRx = exports.MobX = exports.Vuex = exports.Redux = exports.StateAction = exports.OTable = exports.Profiler = exports.Fetch = exports.CSSDeleteRule = exports.CSSInsertRule = exports.Metadata = exports.UserAnonymousID = exports.UserID = exports.RawCustomEvent = exports.JSException = exports.PageRenderTiming = exports.PageLoadTiming = exports.ConsoleLog = exports.MouseMove = exports.SetInputChecked = exports.SetInputValue = exports.SetInputTarget = exports.SetNodeScroll = exports.SetNodeData = exports.RemoveNodeAttribute = exports.SetNodeAttribute = exports.RemoveNode = exports.MoveNode = exports.CreateTextNode = exports.CreateElementNode = exports.CreateDocument = exports.SetViewportScroll = exports.SetViewportSize = exports.SetPageLocation = exports.Timestamp = exports.PartitionedMessage = exports.BatchMetadata = void 0;
|
|
5
|
-
exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
|
|
6
|
+
exports.Zustand = exports.AdoptedSSRemoveOwner = exports.AdoptedSSAddOwner = exports.AdoptedSSDeleteRule = exports.AdoptedSSInsertRuleURLBased = exports.AdoptedSSReplaceURLBased = void 0;
|
|
6
7
|
function BatchMetadata(version, pageNo, firstIndex, timestamp, location) {
|
|
7
8
|
return [
|
|
8
9
|
81 /* BatchMetadata */,
|
|
@@ -491,3 +492,11 @@ function AdoptedSSRemoveOwner(sheetID, id) {
|
|
|
491
492
|
];
|
|
492
493
|
}
|
|
493
494
|
exports.AdoptedSSRemoveOwner = AdoptedSSRemoveOwner;
|
|
495
|
+
function Zustand(mutation, state) {
|
|
496
|
+
return [
|
|
497
|
+
79 /* Zustand */,
|
|
498
|
+
mutation,
|
|
499
|
+
state,
|
|
500
|
+
];
|
|
501
|
+
}
|
|
502
|
+
exports.Zustand = Zustand;
|
package/cjs/app/nodes.d.ts
CHANGED
|
@@ -6,7 +6,7 @@ export default class Nodes {
|
|
|
6
6
|
private readonly elementListeners;
|
|
7
7
|
constructor(node_id: string);
|
|
8
8
|
attachNodeCallback(nodeCallback: NodeCallback): void;
|
|
9
|
-
|
|
9
|
+
attachNodeListener(node: Node, type: string, listener: EventListener): void;
|
|
10
10
|
registerNode(node: Node): [/*id:*/ number, /*isNew:*/ boolean];
|
|
11
11
|
unregisterNode(node: Node): number | undefined;
|
|
12
12
|
cleanTree(): void;
|
package/cjs/app/nodes.js
CHANGED
|
@@ -11,20 +11,18 @@ class Nodes {
|
|
|
11
11
|
attachNodeCallback(nodeCallback) {
|
|
12
12
|
this.nodeCallbacks.push(nodeCallback);
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
attachElementListener(type, node, elementListener) {
|
|
14
|
+
attachNodeListener(node, type, listener) {
|
|
16
15
|
const id = this.getID(node);
|
|
17
16
|
if (id === undefined) {
|
|
18
17
|
return;
|
|
19
18
|
}
|
|
20
|
-
node.addEventListener(type,
|
|
19
|
+
node.addEventListener(type, listener);
|
|
21
20
|
let listeners = this.elementListeners.get(id);
|
|
22
21
|
if (listeners === undefined) {
|
|
23
22
|
listeners = [];
|
|
24
23
|
this.elementListeners.set(id, listeners);
|
|
25
|
-
return;
|
|
26
24
|
}
|
|
27
|
-
listeners.push([type,
|
|
25
|
+
listeners.push([type, listener]);
|
|
28
26
|
}
|
|
29
27
|
registerNode(node) {
|
|
30
28
|
let id = node[this.node_id];
|
|
@@ -11,6 +11,7 @@ class IFrameObserver extends observer_js_1.default {
|
|
|
11
11
|
} //log TODO common app.logger
|
|
12
12
|
// Have to observe document, because the inner <html> might be changed
|
|
13
13
|
this.observeRoot(doc, (docID) => {
|
|
14
|
+
//MBTODO: do not send if empty (send on load? it might be in-place iframe, like our replayer, which does not get loaded)
|
|
14
15
|
if (docID === undefined) {
|
|
15
16
|
console.log('OpenReplay: Iframe document not bound');
|
|
16
17
|
return;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Le truc - for defining an absolute offset for (nested) iframe documents. (To track mouse movments)
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
class IFrameOffsets {
|
|
5
|
+
constructor() {
|
|
6
|
+
this.states = new Map();
|
|
7
|
+
}
|
|
8
|
+
calcOffset(state) {
|
|
9
|
+
let parLeft = 0, parTop = 0;
|
|
10
|
+
if (state.parent) {
|
|
11
|
+
;
|
|
12
|
+
[parLeft, parTop] = this.calcOffset(state.parent);
|
|
13
|
+
}
|
|
14
|
+
if (!state.offset) {
|
|
15
|
+
const { left, top } = state.iFrame.getBoundingClientRect();
|
|
16
|
+
state.offset = [left, top];
|
|
17
|
+
}
|
|
18
|
+
const [left, top] = state.offset;
|
|
19
|
+
return [parLeft + left, parTop + top]; // TODO: store absolute sum, invalidate whole subtree. Otherwise it is summated on each mousemove
|
|
20
|
+
}
|
|
21
|
+
getDocumentOffset(doc) {
|
|
22
|
+
const state = this.states.get(doc);
|
|
23
|
+
if (!state) {
|
|
24
|
+
return [0, 0];
|
|
25
|
+
} // topmost doc
|
|
26
|
+
return this.calcOffset(state);
|
|
27
|
+
}
|
|
28
|
+
observe(iFrame) {
|
|
29
|
+
var _a;
|
|
30
|
+
const doc = iFrame.contentDocument;
|
|
31
|
+
if (!doc) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const parentDoc = iFrame.ownerDocument;
|
|
35
|
+
const parentState = this.states.get(parentDoc);
|
|
36
|
+
const state = {
|
|
37
|
+
offset: null,
|
|
38
|
+
iFrame,
|
|
39
|
+
parent: parentState || null,
|
|
40
|
+
clear: () => {
|
|
41
|
+
var _a;
|
|
42
|
+
parentDoc.removeEventListener('scroll', invalidateOffset);
|
|
43
|
+
(_a = parentDoc.defaultView) === null || _a === void 0 ? void 0 : _a.removeEventListener('resize', invalidateOffset);
|
|
44
|
+
},
|
|
45
|
+
};
|
|
46
|
+
const invalidateOffset = () => {
|
|
47
|
+
state.offset = null;
|
|
48
|
+
};
|
|
49
|
+
// anything more reliable? This does not cover all cases (layout changes are ignored, for ex.)
|
|
50
|
+
parentDoc.addEventListener('scroll', invalidateOffset);
|
|
51
|
+
(_a = parentDoc.defaultView) === null || _a === void 0 ? void 0 : _a.addEventListener('resize', invalidateOffset);
|
|
52
|
+
this.states.set(doc, state);
|
|
53
|
+
}
|
|
54
|
+
clear() {
|
|
55
|
+
this.states.forEach((s) => s.clear());
|
|
56
|
+
this.states.clear();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
exports.default = IFrameOffsets;
|
|
@@ -223,7 +223,7 @@ class Observer {
|
|
|
223
223
|
return false;
|
|
224
224
|
}
|
|
225
225
|
this.app.sanitizer.handleNode(id, parentID, node);
|
|
226
|
-
if (this.app.sanitizer.
|
|
226
|
+
if (this.app.sanitizer.isHidden(parentID)) {
|
|
227
227
|
return false;
|
|
228
228
|
}
|
|
229
229
|
}
|
|
@@ -251,12 +251,12 @@ class Observer {
|
|
|
251
251
|
if ((0, guards_js_1.isElementNode)(node)) {
|
|
252
252
|
let el = node;
|
|
253
253
|
if (parentID !== undefined) {
|
|
254
|
-
if (this.app.sanitizer.
|
|
254
|
+
if (this.app.sanitizer.isHidden(id)) {
|
|
255
255
|
const width = el.clientWidth;
|
|
256
256
|
const height = el.clientHeight;
|
|
257
257
|
el = node.cloneNode();
|
|
258
|
-
el.style.width = width
|
|
259
|
-
el.style.height = height
|
|
258
|
+
el.style.width = `${width}px`;
|
|
259
|
+
el.style.height = `${height}px`;
|
|
260
260
|
}
|
|
261
261
|
this.app.send((0, messages_gen_js_1.CreateElementNode)(id, parentID, index, el.tagName, (0, guards_js_1.isSVGElement)(node)));
|
|
262
262
|
}
|
|
@@ -1,16 +1,14 @@
|
|
|
1
1
|
import Observer from './observer.js';
|
|
2
|
+
import { Offset } from './iframe_offsets.js';
|
|
2
3
|
import App from '../index.js';
|
|
3
4
|
export interface Options {
|
|
4
5
|
captureIFrames: boolean;
|
|
5
6
|
}
|
|
6
7
|
declare type Context = Window & typeof globalThis;
|
|
7
8
|
declare type ContextCallback = (context: Context) => void;
|
|
8
|
-
declare type Offset = {
|
|
9
|
-
top: number;
|
|
10
|
-
left: number;
|
|
11
|
-
};
|
|
12
9
|
export default class TopObserver extends Observer {
|
|
13
10
|
private readonly options;
|
|
11
|
+
private readonly iframeOffsets;
|
|
14
12
|
constructor(app: App, options: Partial<Options>);
|
|
15
13
|
private readonly contextCallbacks;
|
|
16
14
|
private readonly contextsSet;
|
|
@@ -4,16 +4,14 @@ const observer_js_1 = require("./observer.js");
|
|
|
4
4
|
const guards_js_1 = require("../guards.js");
|
|
5
5
|
const iframe_observer_js_1 = require("./iframe_observer.js");
|
|
6
6
|
const shadow_root_observer_js_1 = require("./shadow_root_observer.js");
|
|
7
|
+
const iframe_offsets_js_1 = require("./iframe_offsets.js");
|
|
7
8
|
const messages_gen_js_1 = require("../messages.gen.js");
|
|
8
9
|
const utils_js_1 = require("../../utils.js");
|
|
9
|
-
function isPatchedDocument(doc) {
|
|
10
|
-
// @ts-ignore
|
|
11
|
-
return typeof doc.__openreplay__getOffset === 'function';
|
|
12
|
-
}
|
|
13
10
|
const attachShadowNativeFn = utils_js_1.IN_BROWSER ? Element.prototype.attachShadow : () => new ShadowRoot();
|
|
14
11
|
class TopObserver extends observer_js_1.default {
|
|
15
12
|
constructor(app, options) {
|
|
16
13
|
super(app, true);
|
|
14
|
+
this.iframeOffsets = new iframe_offsets_js_1.default();
|
|
17
15
|
this.contextCallbacks = [];
|
|
18
16
|
// Attached once per Tracker instance
|
|
19
17
|
this.contextsSet = new Set();
|
|
@@ -40,17 +38,14 @@ class TopObserver extends observer_js_1.default {
|
|
|
40
38
|
attachContextCallback(cb) {
|
|
41
39
|
this.contextCallbacks.push(cb);
|
|
42
40
|
}
|
|
43
|
-
// Le truc
|
|
44
41
|
getDocumentOffset(doc) {
|
|
45
|
-
|
|
46
|
-
return doc.__openreplay__getOffset();
|
|
47
|
-
}
|
|
48
|
-
return { top: 0, left: 0 };
|
|
42
|
+
return this.iframeOffsets.getDocumentOffset(doc);
|
|
49
43
|
}
|
|
50
44
|
handleIframe(iframe) {
|
|
51
45
|
let doc = null;
|
|
52
|
-
|
|
53
|
-
|
|
46
|
+
// setTimeout is required. Otherwise some event listeners (scroll, mousemove) applied in modules
|
|
47
|
+
// do not work on the iframe document when it 've been loaded dynamically ((why?))
|
|
48
|
+
const handle = this.app.safe(() => setTimeout(() => {
|
|
54
49
|
const id = this.app.nodes.getID(iframe);
|
|
55
50
|
if (id === undefined) {
|
|
56
51
|
//log
|
|
@@ -61,27 +56,21 @@ class TopObserver extends observer_js_1.default {
|
|
|
61
56
|
if (currentDoc && currentDoc !== doc) {
|
|
62
57
|
const observer = new iframe_observer_js_1.default(this.app);
|
|
63
58
|
this.iframeObservers.push(observer);
|
|
64
|
-
observer.observe(iframe);
|
|
59
|
+
observer.observe(iframe); // TODO: call unregisterNode for the previous doc if present (incapsulate: one iframe - one observer)
|
|
65
60
|
doc = currentDoc;
|
|
66
|
-
|
|
67
|
-
const { top, left } = this.getDocumentOffset(iframe.ownerDocument);
|
|
68
|
-
return {
|
|
69
|
-
top: iframe.offsetTop + top,
|
|
70
|
-
left: iframe.offsetLeft + left,
|
|
71
|
-
};
|
|
72
|
-
};
|
|
61
|
+
this.iframeOffsets.observe(iframe);
|
|
73
62
|
}
|
|
74
63
|
if (currentWin &&
|
|
75
64
|
// Sometimes currentWin.window is null (not in specification). Such window object is not functional
|
|
76
65
|
currentWin === currentWin.window &&
|
|
77
66
|
!this.contextsSet.has(currentWin) // for each context callbacks called once per Tracker (TopObserver) instance
|
|
67
|
+
//TODO: more explicit logic
|
|
78
68
|
) {
|
|
79
69
|
this.contextsSet.add(currentWin);
|
|
80
70
|
//@ts-ignore https://github.com/microsoft/TypeScript/issues/41684
|
|
81
71
|
this.contextCallbacks.forEach((cb) => cb(currentWin));
|
|
82
|
-
win = currentWin;
|
|
83
72
|
}
|
|
84
|
-
});
|
|
73
|
+
}, 0));
|
|
85
74
|
iframe.addEventListener('load', handle); // why app.attachEventListener not working?
|
|
86
75
|
handle();
|
|
87
76
|
}
|
|
@@ -110,6 +99,7 @@ class TopObserver extends observer_js_1.default {
|
|
|
110
99
|
}, window.document.documentElement);
|
|
111
100
|
}
|
|
112
101
|
disconnect() {
|
|
102
|
+
this.iframeOffsets.clear();
|
|
113
103
|
Element.prototype.attachShadow = attachShadowNativeFn;
|
|
114
104
|
this.iframeObservers.forEach((o) => o.disconnect());
|
|
115
105
|
this.iframeObservers = [];
|
package/cjs/app/sanitizer.d.ts
CHANGED
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import type App from './index.js';
|
|
2
|
+
export declare enum SanitizeLevel {
|
|
3
|
+
Plain = 0,
|
|
4
|
+
Obscured = 1,
|
|
5
|
+
Hidden = 2
|
|
6
|
+
}
|
|
2
7
|
export interface Options {
|
|
3
8
|
obscureTextEmails: boolean;
|
|
4
9
|
obscureTextNumbers: boolean;
|
|
10
|
+
domSanitizer?: (node: Element) => SanitizeLevel;
|
|
5
11
|
}
|
|
6
12
|
export default class Sanitizer {
|
|
7
13
|
private readonly app;
|
|
8
|
-
private readonly
|
|
9
|
-
private readonly
|
|
14
|
+
private readonly obscured;
|
|
15
|
+
private readonly hidden;
|
|
10
16
|
private readonly options;
|
|
11
17
|
constructor(app: App, options: Partial<Options>);
|
|
12
18
|
handleNode(id: number, parentID: number, node: Node): void;
|
|
13
19
|
sanitize(id: number, data: string): string;
|
|
14
|
-
|
|
15
|
-
|
|
20
|
+
isObscured(id: number): boolean;
|
|
21
|
+
isHidden(id: number): boolean;
|
|
16
22
|
getInnerTextSecure(el: HTMLElement): string;
|
|
17
23
|
clear(): void;
|
|
18
24
|
}
|
package/cjs/app/sanitizer.js
CHANGED
|
@@ -1,29 +1,47 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SanitizeLevel = void 0;
|
|
3
4
|
const utils_js_1 = require("../utils.js");
|
|
4
5
|
const guards_js_1 = require("./guards.js");
|
|
6
|
+
var SanitizeLevel;
|
|
7
|
+
(function (SanitizeLevel) {
|
|
8
|
+
SanitizeLevel[SanitizeLevel["Plain"] = 0] = "Plain";
|
|
9
|
+
SanitizeLevel[SanitizeLevel["Obscured"] = 1] = "Obscured";
|
|
10
|
+
SanitizeLevel[SanitizeLevel["Hidden"] = 2] = "Hidden";
|
|
11
|
+
})(SanitizeLevel = exports.SanitizeLevel || (exports.SanitizeLevel = {}));
|
|
5
12
|
class Sanitizer {
|
|
6
13
|
constructor(app, options) {
|
|
7
14
|
this.app = app;
|
|
8
|
-
this.
|
|
9
|
-
this.
|
|
15
|
+
this.obscured = new Set();
|
|
16
|
+
this.hidden = new Set();
|
|
10
17
|
this.options = Object.assign({
|
|
11
18
|
obscureTextEmails: true,
|
|
12
19
|
obscureTextNumbers: false,
|
|
13
20
|
}, options);
|
|
14
21
|
}
|
|
15
22
|
handleNode(id, parentID, node) {
|
|
16
|
-
if (this.
|
|
17
|
-
((0, guards_js_1.isElementNode)(node) &&
|
|
18
|
-
|
|
23
|
+
if (this.obscured.has(parentID) ||
|
|
24
|
+
((0, guards_js_1.isElementNode)(node) &&
|
|
25
|
+
((0, utils_js_1.hasOpenreplayAttribute)(node, 'masked') || (0, utils_js_1.hasOpenreplayAttribute)(node, 'obscured')))) {
|
|
26
|
+
this.obscured.add(id);
|
|
19
27
|
}
|
|
20
|
-
if (this.
|
|
21
|
-
((0, guards_js_1.isElementNode)(node) &&
|
|
22
|
-
|
|
28
|
+
if (this.hidden.has(parentID) ||
|
|
29
|
+
((0, guards_js_1.isElementNode)(node) &&
|
|
30
|
+
((0, utils_js_1.hasOpenreplayAttribute)(node, 'htmlmasked') || (0, utils_js_1.hasOpenreplayAttribute)(node, 'hidden')))) {
|
|
31
|
+
this.hidden.add(id);
|
|
32
|
+
}
|
|
33
|
+
if (this.options.domSanitizer !== undefined && (0, guards_js_1.isElementNode)(node)) {
|
|
34
|
+
const sanitizeLevel = this.options.domSanitizer(node);
|
|
35
|
+
if (sanitizeLevel === SanitizeLevel.Obscured) {
|
|
36
|
+
this.obscured.add(id);
|
|
37
|
+
}
|
|
38
|
+
if (sanitizeLevel === SanitizeLevel.Hidden) {
|
|
39
|
+
this.hidden.add(id);
|
|
40
|
+
}
|
|
23
41
|
}
|
|
24
42
|
}
|
|
25
43
|
sanitize(id, data) {
|
|
26
|
-
if (this.
|
|
44
|
+
if (this.obscured.has(id)) {
|
|
27
45
|
// TODO: is it the best place to put trim() ? Might trimmed spaces be considered in layout in certain cases?
|
|
28
46
|
return data
|
|
29
47
|
.trim()
|
|
@@ -37,11 +55,11 @@ class Sanitizer {
|
|
|
37
55
|
}
|
|
38
56
|
return data;
|
|
39
57
|
}
|
|
40
|
-
|
|
41
|
-
return this.
|
|
58
|
+
isObscured(id) {
|
|
59
|
+
return this.obscured.has(id);
|
|
42
60
|
}
|
|
43
|
-
|
|
44
|
-
return this.
|
|
61
|
+
isHidden(id) {
|
|
62
|
+
return this.hidden.has(id);
|
|
45
63
|
}
|
|
46
64
|
getInnerTextSecure(el) {
|
|
47
65
|
const id = this.app.nodes.getID(el);
|
|
@@ -51,8 +69,8 @@ class Sanitizer {
|
|
|
51
69
|
return this.sanitize(id, el.innerText);
|
|
52
70
|
}
|
|
53
71
|
clear() {
|
|
54
|
-
this.
|
|
55
|
-
this.
|
|
72
|
+
this.obscured.clear();
|
|
73
|
+
this.hidden.clear();
|
|
56
74
|
}
|
|
57
75
|
}
|
|
58
76
|
exports.default = Sanitizer;
|
package/cjs/app/session.js
CHANGED
|
@@ -53,7 +53,8 @@ export declare const enum Type {
|
|
|
53
53
|
AdoptedSSInsertRuleURLBased = 73,
|
|
54
54
|
AdoptedSSDeleteRule = 75,
|
|
55
55
|
AdoptedSSAddOwner = 76,
|
|
56
|
-
AdoptedSSRemoveOwner = 77
|
|
56
|
+
AdoptedSSRemoveOwner = 77,
|
|
57
|
+
Zustand = 79
|
|
57
58
|
}
|
|
58
59
|
export declare type BatchMetadata = [
|
|
59
60
|
Type.BatchMetadata,
|
|
@@ -378,5 +379,10 @@ export declare type AdoptedSSRemoveOwner = [
|
|
|
378
379
|
number,
|
|
379
380
|
number
|
|
380
381
|
];
|
|
381
|
-
declare type
|
|
382
|
+
export declare type Zustand = [
|
|
383
|
+
Type.Zustand,
|
|
384
|
+
string,
|
|
385
|
+
string
|
|
386
|
+
];
|
|
387
|
+
declare type Message = BatchMetadata | PartitionedMessage | Timestamp | SetPageLocation | SetViewportSize | SetViewportScroll | CreateDocument | CreateElementNode | CreateTextNode | MoveNode | RemoveNode | SetNodeAttribute | RemoveNodeAttribute | SetNodeData | SetNodeScroll | SetInputTarget | SetInputValue | SetInputChecked | MouseMove | ConsoleLog | PageLoadTiming | PageRenderTiming | JSException | RawCustomEvent | UserID | UserAnonymousID | Metadata | CSSInsertRule | CSSDeleteRule | Fetch | Profiler | OTable | StateAction | Redux | Vuex | MobX | NgRx | GraphQL | PerformanceTrack | ResourceTiming | ConnectionInformation | SetPageVisibility | LongTask | SetNodeAttributeURLBased | SetCSSDataURLBased | TechnicalInfo | CustomIssue | CSSInsertRuleURLBased | MouseClick | CreateIFrameDocument | AdoptedSSReplaceURLBased | AdoptedSSInsertRuleURLBased | AdoptedSSDeleteRule | AdoptedSSAddOwner | AdoptedSSRemoveOwner | Zustand;
|
|
382
388
|
export default Message;
|
package/cjs/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ import App from './app/index.js';
|
|
|
2
2
|
export { default as App } from './app/index.js';
|
|
3
3
|
import * as _Messages from './app/messages.gen.js';
|
|
4
4
|
export declare const Messages: typeof _Messages;
|
|
5
|
+
export { SanitizeLevel } from './app/sanitizer.js';
|
|
5
6
|
import type { Options as AppOptions } from './app/index.js';
|
|
6
7
|
import type { Options as ConsoleOptions } from './modules/console.js';
|
|
7
8
|
import type { Options as ExceptionOptions } from './modules/exception.js';
|