@openreplay/tracker 18.1.0 → 18.1.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/dist/cjs/entry.js +78 -8
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +78 -8
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/guards.d.ts +1 -0
- package/dist/cjs/main/app/index.d.ts +4 -0
- package/dist/cjs/main/app/observer/top_observer.d.ts +4 -0
- package/dist/lib/entry.js +78 -8
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +78 -8
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/guards.d.ts +1 -0
- package/dist/lib/main/app/index.d.ts +4 -0
- package/dist/lib/main/app/observer/top_observer.d.ts +4 -0
- package/dist/types/main/app/guards.d.ts +1 -0
- package/dist/types/main/app/index.d.ts +4 -0
- package/dist/types/main/app/observer/top_observer.d.ts +4 -0
- package/package.json +2 -3
|
@@ -19,6 +19,7 @@ type TagTypeMap = {
|
|
|
19
19
|
link: HTMLLinkElement;
|
|
20
20
|
canvas: HTMLCanvasElement;
|
|
21
21
|
slot: HTMLSlotElement;
|
|
22
|
+
dialog: HTMLDialogElement;
|
|
22
23
|
};
|
|
23
24
|
export declare function hasTag<T extends keyof TagTypeMap>(el: Node, tagName: T): el is TagTypeMap[typeof tagName];
|
|
24
25
|
export {};
|
|
@@ -319,6 +319,10 @@ export default class App {
|
|
|
319
319
|
coldStartTs: number;
|
|
320
320
|
singleBuffer: boolean;
|
|
321
321
|
private getSessionVersionHash;
|
|
322
|
+
private get sessionVersionKey();
|
|
323
|
+
private storeSessionVersion;
|
|
324
|
+
/** a tab adopting a session over BroadcastChannel inherits its version too */
|
|
325
|
+
private adoptSessionVersion;
|
|
322
326
|
private checkSessionToken;
|
|
323
327
|
/**
|
|
324
328
|
* start buffering messages without starting the actual session, which gives
|
|
@@ -46,6 +46,10 @@ export default class TopObserver extends Observer {
|
|
|
46
46
|
private shadowRootObservers;
|
|
47
47
|
private handleShadowRoot;
|
|
48
48
|
observe(): void;
|
|
49
|
+
private colorSchemeMQL;
|
|
50
|
+
private colorSchemeListener;
|
|
51
|
+
/** Send resolved used color-scheme ('dark'|'light'|'normal') for the player to force on replay. */
|
|
52
|
+
private sendColorScheme;
|
|
49
53
|
crossdomainObserve(rootNodeId: number, frameOder: number, frameLevel: number): void;
|
|
50
54
|
disconnect(): void;
|
|
51
55
|
}
|
package/dist/lib/entry.js
CHANGED
|
@@ -3308,6 +3308,25 @@ class Observer {
|
|
|
3308
3308
|
}
|
|
3309
3309
|
return;
|
|
3310
3310
|
}
|
|
3311
|
+
// `open` alone can't tell showModal() (modal/top-layer) from show()/`<dialog open>`
|
|
3312
|
+
// (non-modal); emit the mode alongside it so the player replays the right call (see DOMManager).
|
|
3313
|
+
if (name === 'open' && hasTag(node, 'dialog')) {
|
|
3314
|
+
let mode;
|
|
3315
|
+
if (value === null) {
|
|
3316
|
+
mode = 'closed';
|
|
3317
|
+
}
|
|
3318
|
+
else {
|
|
3319
|
+
let isModal = false;
|
|
3320
|
+
try {
|
|
3321
|
+
isModal = node.matches('dialog:modal');
|
|
3322
|
+
}
|
|
3323
|
+
catch (e) {
|
|
3324
|
+
/* :modal pseudo-class unsupported on this browser */
|
|
3325
|
+
}
|
|
3326
|
+
mode = isModal ? 'modal' : 'nonmodal';
|
|
3327
|
+
}
|
|
3328
|
+
this.app.send(SetNodeAttribute(id, '__openreplay_dialog', mode));
|
|
3329
|
+
}
|
|
3311
3330
|
if (name === 'src' ||
|
|
3312
3331
|
name === 'srcset' ||
|
|
3313
3332
|
name === 'integrity' ||
|
|
@@ -3916,6 +3935,8 @@ class TopObserver extends Observer {
|
|
|
3916
3935
|
this.iframeObservers = new WeakMap();
|
|
3917
3936
|
this.docObservers = new WeakMap();
|
|
3918
3937
|
this.shadowRootObservers = new WeakMap();
|
|
3938
|
+
this.colorSchemeMQL = null;
|
|
3939
|
+
this.colorSchemeListener = null;
|
|
3919
3940
|
this.app = params.app;
|
|
3920
3941
|
this.options = opts;
|
|
3921
3942
|
// IFrames
|
|
@@ -4010,9 +4031,36 @@ class TopObserver extends Observer {
|
|
|
4010
4031
|
// it has no node_id here
|
|
4011
4032
|
this.app.nodes.callNodeCallbacks(document, true);
|
|
4012
4033
|
}, window.document.documentElement);
|
|
4034
|
+
// Send before `orloaded` so it lands in the initial visual batch (see sendColorScheme).
|
|
4035
|
+
this.sendColorScheme();
|
|
4013
4036
|
// "DOM parsed" signal: observeRoot sent the full initial tree synchronously above.
|
|
4014
4037
|
// The worker keys on this attribute (BatchWriter) to finalize the visual batch.
|
|
4015
4038
|
this.app.send(SetNodeAttribute(0, 'orloaded', 'true'));
|
|
4039
|
+
if (IN_BROWSER && window.matchMedia) {
|
|
4040
|
+
this.colorSchemeMQL = window.matchMedia('(prefers-color-scheme: dark)');
|
|
4041
|
+
this.colorSchemeListener = this.app.safe(() => this.sendColorScheme());
|
|
4042
|
+
this.colorSchemeMQL.addEventListener?.('change', this.colorSchemeListener);
|
|
4043
|
+
}
|
|
4044
|
+
}
|
|
4045
|
+
/** Send resolved used color-scheme ('dark'|'light'|'normal') for the player to force on replay. */
|
|
4046
|
+
sendColorScheme() {
|
|
4047
|
+
if (!IN_BROWSER)
|
|
4048
|
+
return;
|
|
4049
|
+
const root = document.documentElement;
|
|
4050
|
+
let declared = getComputedStyle(root).colorScheme;
|
|
4051
|
+
if (!declared || declared === 'normal') {
|
|
4052
|
+
const meta = document.querySelector('meta[name="color-scheme" i]');
|
|
4053
|
+
const content = meta && meta.getAttribute('content');
|
|
4054
|
+
if (content)
|
|
4055
|
+
declared = content;
|
|
4056
|
+
}
|
|
4057
|
+
let used = 'normal';
|
|
4058
|
+
if (declared && declared !== 'normal') {
|
|
4059
|
+
const prefersDark = !!window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
4060
|
+
// resolve declared support against OS preference into the concrete used scheme
|
|
4061
|
+
used = declared.includes('dark') && (prefersDark || !declared.includes('light')) ? 'dark' : 'light';
|
|
4062
|
+
}
|
|
4063
|
+
this.app.send(SetNodeAttribute(0, '__openreplay_color_scheme', used));
|
|
4016
4064
|
}
|
|
4017
4065
|
crossdomainObserve(rootNodeId, frameOder, frameLevel) {
|
|
4018
4066
|
const observer = this;
|
|
@@ -4032,6 +4080,11 @@ class TopObserver extends Observer {
|
|
|
4032
4080
|
iframeObserver.syntheticObserve(rootNodeId, window.document);
|
|
4033
4081
|
}
|
|
4034
4082
|
disconnect() {
|
|
4083
|
+
if (this.colorSchemeMQL && this.colorSchemeListener) {
|
|
4084
|
+
this.colorSchemeMQL.removeEventListener?.('change', this.colorSchemeListener);
|
|
4085
|
+
}
|
|
4086
|
+
this.colorSchemeMQL = null;
|
|
4087
|
+
this.colorSchemeListener = null;
|
|
4035
4088
|
this.iframeOffsets.clear();
|
|
4036
4089
|
Element.prototype.attachShadow = attachShadowNativeFn;
|
|
4037
4090
|
this.iframeObserversArr.forEach((observer) => observer.disconnect());
|
|
@@ -4307,7 +4360,7 @@ class App {
|
|
|
4307
4360
|
this.stopCallbacks = [];
|
|
4308
4361
|
this.commitCallbacks = [];
|
|
4309
4362
|
this.activityState = ActivityState.NotActive;
|
|
4310
|
-
this.version = '18.1.
|
|
4363
|
+
this.version = '18.1.2'; // TODO: version compatability check inside each plugin.
|
|
4311
4364
|
this.socketMode = false;
|
|
4312
4365
|
this.compressionThreshold = 24 * 1000;
|
|
4313
4366
|
this.bc = null;
|
|
@@ -5062,12 +5115,14 @@ class App {
|
|
|
5062
5115
|
if (ev.data.line === proto.resp) {
|
|
5063
5116
|
const sessionToken = ev.data.token;
|
|
5064
5117
|
this.session.setSessionToken(sessionToken, this.projectKey);
|
|
5118
|
+
this.adoptSessionVersion(ev.data.version);
|
|
5065
5119
|
this.allowAppStart();
|
|
5066
5120
|
}
|
|
5067
5121
|
if (ev.data.line === proto.reg) {
|
|
5068
5122
|
const sessionToken = ev.data.token;
|
|
5069
5123
|
this.session.regenerateTabId();
|
|
5070
5124
|
this.session.setSessionToken(sessionToken, this.projectKey);
|
|
5125
|
+
this.adoptSessionVersion(ev.data.version);
|
|
5071
5126
|
this.allowAppStart();
|
|
5072
5127
|
}
|
|
5073
5128
|
if (ev.data.line === proto.ask) {
|
|
@@ -5076,6 +5131,7 @@ class App {
|
|
|
5076
5131
|
this.bc.postMessage({
|
|
5077
5132
|
line: ev.data.source === thisTab ? proto.reg : proto.resp,
|
|
5078
5133
|
token,
|
|
5134
|
+
version: this.getSessionVersionHash(),
|
|
5079
5135
|
source: thisTab,
|
|
5080
5136
|
context: this.contextId,
|
|
5081
5137
|
projectKey: this.projectKey,
|
|
@@ -5563,15 +5619,29 @@ class App {
|
|
|
5563
5619
|
const PROTO_VERSION = '2';
|
|
5564
5620
|
return `${PROTO_VERSION}x${this.version}`;
|
|
5565
5621
|
}
|
|
5622
|
+
get sessionVersionKey() {
|
|
5623
|
+
return `${this.options.session_token_key}_version`;
|
|
5624
|
+
}
|
|
5625
|
+
storeSessionVersion(version) {
|
|
5626
|
+
this.sessionStorage.setItem(this.sessionVersionKey, version);
|
|
5627
|
+
}
|
|
5628
|
+
/** a tab adopting a session over BroadcastChannel inherits its version too */
|
|
5629
|
+
adoptSessionVersion(version) {
|
|
5630
|
+
if (version) {
|
|
5631
|
+
this.storeSessionVersion(version);
|
|
5632
|
+
}
|
|
5633
|
+
}
|
|
5566
5634
|
checkSessionToken(forceNew) {
|
|
5567
5635
|
const versionHash = this.getSessionVersionHash();
|
|
5568
5636
|
const needReset = this.sessionStorage.getItem(this.options.session_reset_key) !== null;
|
|
5569
|
-
let needNewSessionID = forceNew || needReset;
|
|
5637
|
+
let needNewSessionID = Boolean(forceNew || needReset);
|
|
5570
5638
|
const sessionToken = this.session.getSessionToken(this.projectKey);
|
|
5571
5639
|
if (sessionToken) {
|
|
5572
|
-
const storedVersion = this.sessionStorage.getItem(
|
|
5573
|
-
|
|
5574
|
-
|
|
5640
|
+
const storedVersion = this.sessionStorage.getItem(this.sessionVersionKey);
|
|
5641
|
+
if (!storedVersion || storedVersion !== versionHash) {
|
|
5642
|
+
needNewSessionID = true;
|
|
5643
|
+
}
|
|
5644
|
+
this.storeSessionVersion(versionHash);
|
|
5575
5645
|
}
|
|
5576
5646
|
return needNewSessionID || !sessionToken;
|
|
5577
5647
|
}
|
|
@@ -5895,7 +5965,7 @@ class App {
|
|
|
5895
5965
|
}
|
|
5896
5966
|
this.delay = delay;
|
|
5897
5967
|
this.session.setSessionToken(token, this.projectKey);
|
|
5898
|
-
this.
|
|
5968
|
+
this.storeSessionVersion(this.getSessionVersionHash());
|
|
5899
5969
|
if (sessionToken && sessionToken !== token) {
|
|
5900
5970
|
this.bc?.postMessage({
|
|
5901
5971
|
type: proto.reset,
|
|
@@ -9720,7 +9790,7 @@ class ConstantProperties {
|
|
|
9720
9790
|
user_id: this.user_id,
|
|
9721
9791
|
distinct_id: this.deviceId,
|
|
9722
9792
|
sdk_edition: 'web',
|
|
9723
|
-
sdk_version: '18.1.
|
|
9793
|
+
sdk_version: '18.1.2',
|
|
9724
9794
|
timezone: getUTCOffsetString(),
|
|
9725
9795
|
search_engine: this.searchEngine,
|
|
9726
9796
|
};
|
|
@@ -10461,7 +10531,7 @@ class API {
|
|
|
10461
10531
|
this.signalStartIssue = (reason, missingApi) => {
|
|
10462
10532
|
const doNotTrack = this.checkDoNotTrack();
|
|
10463
10533
|
console.log("Tracker couldn't start due to:", JSON.stringify({
|
|
10464
|
-
trackerVersion: '18.1.
|
|
10534
|
+
trackerVersion: '18.1.2',
|
|
10465
10535
|
projectKey: this.options.projectKey,
|
|
10466
10536
|
doNotTrack,
|
|
10467
10537
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|