@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 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.5'; // TODO: version compatability check inside each plugin.
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.substr(0, 6) === 'xlink:') {
107
- name = name.substr(6);
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.substr(0, 2) === 'on') {
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.5',
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.5'; // TODO: version compatability check inside each plugin.
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.substr(0, 6) === 'xlink:') {
105
- name = name.substr(6);
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.substr(0, 2) === 'on') {
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.5',
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,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@openreplay/tracker",
3
3
  "description": "The OpenReplay tracker main package",
4
- "version": "14.0.5",
4
+ "version": "14.0.6-beta.1",
5
5
  "keywords": [
6
6
  "logging",
7
7
  "replay"