@openreplay/tracker 14.0.5 → 14.0.6-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/app/index.js +1 -1
- package/cjs/app/observer/observer.d.ts +4 -0
- package/cjs/app/observer/observer.js +37 -5
- package/cjs/index.js +1 -1
- package/lib/app/index.js +1 -1
- package/lib/app/observer/observer.d.ts +4 -0
- package/lib/app/observer/observer.js +37 -5
- package/lib/index.js +1 -1
- package/package.json +1 -1
package/cjs/app/index.js
CHANGED
|
@@ -94,7 +94,7 @@ class App {
|
|
|
94
94
|
this.stopCallbacks = [];
|
|
95
95
|
this.commitCallbacks = [];
|
|
96
96
|
this.activityState = ActivityState.NotActive;
|
|
97
|
-
this.version = '14.0.
|
|
97
|
+
this.version = '14.0.6-beta.1'; // TODO: version compatability check inside each plugin.
|
|
98
98
|
this.socketMode = false;
|
|
99
99
|
this.compressionThreshold = 24 * 1000;
|
|
100
100
|
this.bc = null;
|
|
@@ -10,6 +10,10 @@ export default abstract class Observer {
|
|
|
10
10
|
private readonly textSet;
|
|
11
11
|
constructor(app: App, isTopContext?: boolean);
|
|
12
12
|
private clear;
|
|
13
|
+
/**
|
|
14
|
+
* Unbinds the removed nodes in case of iframe src change.
|
|
15
|
+
*/
|
|
16
|
+
private handleIframeSrcChange;
|
|
13
17
|
private sendNodeAttribute;
|
|
14
18
|
private sendNodeData;
|
|
15
19
|
private bindNode;
|
|
@@ -48,6 +48,7 @@ class Observer {
|
|
|
48
48
|
this.attributesMap = new Map();
|
|
49
49
|
this.textSet = new Set();
|
|
50
50
|
this.observer = (0, utils_js_1.createMutationObserver)(this.app.safe((mutations) => {
|
|
51
|
+
console.log(mutations);
|
|
51
52
|
for (const mutation of mutations) {
|
|
52
53
|
// mutations order is sequential
|
|
53
54
|
const target = mutation.target;
|
|
@@ -57,7 +58,6 @@ class Observer {
|
|
|
57
58
|
}
|
|
58
59
|
if (type === 'childList') {
|
|
59
60
|
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
60
|
-
// Should be the same as bindTree(mutation.removedNodes[i]), but logic needs to be be untied
|
|
61
61
|
if (isObservable(mutation.removedNodes[i])) {
|
|
62
62
|
this.bindNode(mutation.removedNodes[i]);
|
|
63
63
|
}
|
|
@@ -79,6 +79,9 @@ class Observer {
|
|
|
79
79
|
if (name === null) {
|
|
80
80
|
continue;
|
|
81
81
|
}
|
|
82
|
+
if (target instanceof HTMLIFrameElement && name === 'src') {
|
|
83
|
+
this.handleIframeSrcChange(target);
|
|
84
|
+
}
|
|
82
85
|
let attr = this.attributesMap.get(id);
|
|
83
86
|
if (attr === undefined) {
|
|
84
87
|
this.attributesMap.set(id, (attr = new Set()));
|
|
@@ -88,7 +91,6 @@ class Observer {
|
|
|
88
91
|
}
|
|
89
92
|
if (type === 'characterData') {
|
|
90
93
|
this.textSet.add(id);
|
|
91
|
-
continue;
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
this.commitNodes();
|
|
@@ -101,10 +103,40 @@ class Observer {
|
|
|
101
103
|
this.attributesMap.clear();
|
|
102
104
|
this.textSet.clear();
|
|
103
105
|
}
|
|
106
|
+
/**
|
|
107
|
+
* Unbinds the removed nodes in case of iframe src change.
|
|
108
|
+
*/
|
|
109
|
+
handleIframeSrcChange(iframe) {
|
|
110
|
+
const oldContentDocument = iframe.contentDocument;
|
|
111
|
+
if (oldContentDocument) {
|
|
112
|
+
const id = this.app.nodes.getID(oldContentDocument);
|
|
113
|
+
if (id !== undefined) {
|
|
114
|
+
const walker = document.createTreeWalker(oldContentDocument, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
|
|
115
|
+
acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) === undefined
|
|
116
|
+
? NodeFilter.FILTER_REJECT
|
|
117
|
+
: NodeFilter.FILTER_ACCEPT,
|
|
118
|
+
},
|
|
119
|
+
// @ts-ignore
|
|
120
|
+
false);
|
|
121
|
+
let removed = 0;
|
|
122
|
+
const totalBeforeRemove = this.app.nodes.getNodeCount();
|
|
123
|
+
while (walker.nextNode()) {
|
|
124
|
+
if (!iframe.contentDocument.contains(walker.currentNode)) {
|
|
125
|
+
removed += 1;
|
|
126
|
+
this.app.nodes.unregisterNode(walker.currentNode);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const removedPercent = Math.floor((removed / totalBeforeRemove) * 100);
|
|
130
|
+
if (removedPercent > 30) {
|
|
131
|
+
this.app.send((0, messages_gen_js_1.UnbindNodes)(removedPercent));
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
104
136
|
sendNodeAttribute(id, node, name, value) {
|
|
105
137
|
if ((0, guards_js_1.isSVGElement)(node)) {
|
|
106
|
-
if (name.
|
|
107
|
-
name = name.
|
|
138
|
+
if (name.substring(0, 6) === 'xlink:') {
|
|
139
|
+
name = name.substring(6);
|
|
108
140
|
}
|
|
109
141
|
if (value === null) {
|
|
110
142
|
this.app.send((0, messages_gen_js_1.RemoveNodeAttribute)(id, name));
|
|
@@ -125,7 +157,7 @@ class Observer {
|
|
|
125
157
|
name === 'integrity' ||
|
|
126
158
|
name === 'crossorigin' ||
|
|
127
159
|
name === 'autocomplete' ||
|
|
128
|
-
name.
|
|
160
|
+
name.substring(0, 2) === 'on') {
|
|
129
161
|
return;
|
|
130
162
|
}
|
|
131
163
|
if (name === 'value' &&
|
package/cjs/index.js
CHANGED
|
@@ -98,7 +98,7 @@ class API {
|
|
|
98
98
|
const orig = this.options.ingestPoint || index_js_1.DEFAULT_INGEST_POINT;
|
|
99
99
|
req.open('POST', orig + '/v1/web/not-started');
|
|
100
100
|
req.send(JSON.stringify({
|
|
101
|
-
trackerVersion: '14.0.
|
|
101
|
+
trackerVersion: '14.0.6-beta.1',
|
|
102
102
|
projectKey: this.options.projectKey,
|
|
103
103
|
doNotTrack,
|
|
104
104
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|
package/lib/app/index.js
CHANGED
|
@@ -65,7 +65,7 @@ export default class App {
|
|
|
65
65
|
this.stopCallbacks = [];
|
|
66
66
|
this.commitCallbacks = [];
|
|
67
67
|
this.activityState = ActivityState.NotActive;
|
|
68
|
-
this.version = '14.0.
|
|
68
|
+
this.version = '14.0.6-beta.1'; // TODO: version compatability check inside each plugin.
|
|
69
69
|
this.socketMode = false;
|
|
70
70
|
this.compressionThreshold = 24 * 1000;
|
|
71
71
|
this.bc = null;
|
|
@@ -10,6 +10,10 @@ export default abstract class Observer {
|
|
|
10
10
|
private readonly textSet;
|
|
11
11
|
constructor(app: App, isTopContext?: boolean);
|
|
12
12
|
private clear;
|
|
13
|
+
/**
|
|
14
|
+
* Unbinds the removed nodes in case of iframe src change.
|
|
15
|
+
*/
|
|
16
|
+
private handleIframeSrcChange;
|
|
13
17
|
private sendNodeAttribute;
|
|
14
18
|
private sendNodeData;
|
|
15
19
|
private bindNode;
|
|
@@ -46,6 +46,7 @@ export default class Observer {
|
|
|
46
46
|
this.attributesMap = new Map();
|
|
47
47
|
this.textSet = new Set();
|
|
48
48
|
this.observer = createMutationObserver(this.app.safe((mutations) => {
|
|
49
|
+
console.log(mutations);
|
|
49
50
|
for (const mutation of mutations) {
|
|
50
51
|
// mutations order is sequential
|
|
51
52
|
const target = mutation.target;
|
|
@@ -55,7 +56,6 @@ export default class Observer {
|
|
|
55
56
|
}
|
|
56
57
|
if (type === 'childList') {
|
|
57
58
|
for (let i = 0; i < mutation.removedNodes.length; i++) {
|
|
58
|
-
// Should be the same as bindTree(mutation.removedNodes[i]), but logic needs to be be untied
|
|
59
59
|
if (isObservable(mutation.removedNodes[i])) {
|
|
60
60
|
this.bindNode(mutation.removedNodes[i]);
|
|
61
61
|
}
|
|
@@ -77,6 +77,9 @@ export default class Observer {
|
|
|
77
77
|
if (name === null) {
|
|
78
78
|
continue;
|
|
79
79
|
}
|
|
80
|
+
if (target instanceof HTMLIFrameElement && name === 'src') {
|
|
81
|
+
this.handleIframeSrcChange(target);
|
|
82
|
+
}
|
|
80
83
|
let attr = this.attributesMap.get(id);
|
|
81
84
|
if (attr === undefined) {
|
|
82
85
|
this.attributesMap.set(id, (attr = new Set()));
|
|
@@ -86,7 +89,6 @@ export default class Observer {
|
|
|
86
89
|
}
|
|
87
90
|
if (type === 'characterData') {
|
|
88
91
|
this.textSet.add(id);
|
|
89
|
-
continue;
|
|
90
92
|
}
|
|
91
93
|
}
|
|
92
94
|
this.commitNodes();
|
|
@@ -99,10 +101,40 @@ export default class Observer {
|
|
|
99
101
|
this.attributesMap.clear();
|
|
100
102
|
this.textSet.clear();
|
|
101
103
|
}
|
|
104
|
+
/**
|
|
105
|
+
* Unbinds the removed nodes in case of iframe src change.
|
|
106
|
+
*/
|
|
107
|
+
handleIframeSrcChange(iframe) {
|
|
108
|
+
const oldContentDocument = iframe.contentDocument;
|
|
109
|
+
if (oldContentDocument) {
|
|
110
|
+
const id = this.app.nodes.getID(oldContentDocument);
|
|
111
|
+
if (id !== undefined) {
|
|
112
|
+
const walker = document.createTreeWalker(oldContentDocument, NodeFilter.SHOW_ELEMENT + NodeFilter.SHOW_TEXT, {
|
|
113
|
+
acceptNode: (node) => isIgnored(node) || this.app.nodes.getID(node) === undefined
|
|
114
|
+
? NodeFilter.FILTER_REJECT
|
|
115
|
+
: NodeFilter.FILTER_ACCEPT,
|
|
116
|
+
},
|
|
117
|
+
// @ts-ignore
|
|
118
|
+
false);
|
|
119
|
+
let removed = 0;
|
|
120
|
+
const totalBeforeRemove = this.app.nodes.getNodeCount();
|
|
121
|
+
while (walker.nextNode()) {
|
|
122
|
+
if (!iframe.contentDocument.contains(walker.currentNode)) {
|
|
123
|
+
removed += 1;
|
|
124
|
+
this.app.nodes.unregisterNode(walker.currentNode);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const removedPercent = Math.floor((removed / totalBeforeRemove) * 100);
|
|
128
|
+
if (removedPercent > 30) {
|
|
129
|
+
this.app.send(UnbindNodes(removedPercent));
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
102
134
|
sendNodeAttribute(id, node, name, value) {
|
|
103
135
|
if (isSVGElement(node)) {
|
|
104
|
-
if (name.
|
|
105
|
-
name = name.
|
|
136
|
+
if (name.substring(0, 6) === 'xlink:') {
|
|
137
|
+
name = name.substring(6);
|
|
106
138
|
}
|
|
107
139
|
if (value === null) {
|
|
108
140
|
this.app.send(RemoveNodeAttribute(id, name));
|
|
@@ -123,7 +155,7 @@ export default class Observer {
|
|
|
123
155
|
name === 'integrity' ||
|
|
124
156
|
name === 'crossorigin' ||
|
|
125
157
|
name === 'autocomplete' ||
|
|
126
|
-
name.
|
|
158
|
+
name.substring(0, 2) === 'on') {
|
|
127
159
|
return;
|
|
128
160
|
}
|
|
129
161
|
if (name === 'value' &&
|
package/lib/index.js
CHANGED
|
@@ -67,7 +67,7 @@ export default class API {
|
|
|
67
67
|
const orig = this.options.ingestPoint || DEFAULT_INGEST_POINT;
|
|
68
68
|
req.open('POST', orig + '/v1/web/not-started');
|
|
69
69
|
req.send(JSON.stringify({
|
|
70
|
-
trackerVersion: '14.0.
|
|
70
|
+
trackerVersion: '14.0.6-beta.1',
|
|
71
71
|
projectKey: this.options.projectKey,
|
|
72
72
|
doNotTrack,
|
|
73
73
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|