@openreplay/tracker 18.0.15 → 18.0.17-beta.0

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.
@@ -20,6 +20,8 @@ declare class Maintainer {
20
20
  private readonly nodes;
21
21
  private readonly unregisterNode;
22
22
  private interval;
23
+ private batchTimeout;
24
+ private isScanning;
23
25
  private readonly options;
24
26
  constructor(nodes: Map<number, Node | void>, unregisterNode: (node: Node) => void, options?: Partial<MaintainerOptions>);
25
27
  start: () => void;
@@ -1,5 +1,6 @@
1
1
  import App from '../index.js';
2
2
  export declare function parseUseEl(useElement: SVGUseElement, mode: 'inline' | 'dataurl' | 'svgtext', domParser: DOMParser): Promise<any>;
3
+ export declare function shouldSkipValueAttribute(node: Element): boolean;
3
4
  interface Options {
4
5
  disableSprites?: boolean;
5
6
  disableThrottling?: boolean;
package/dist/lib/entry.js CHANGED
@@ -2213,22 +2213,32 @@ class Logger {
2213
2213
  }
2214
2214
 
2215
2215
  const SECOND = 1000;
2216
- function processMapInBatches(map, batchSize, processBatchCallback) {
2216
+ function processMapInBatches(map, batchSize, processBatchCallback,
2217
+ // reports the pending inter-batch timeout so the caller can cancel it on stop()
2218
+ onScheduled,
2219
+ // called once the whole map has been walked (or there was nothing to walk)
2220
+ onComplete) {
2217
2221
  const iterator = map.entries();
2218
2222
  function processNextBatch() {
2219
- const batch = [];
2223
+ let processed = 0;
2220
2224
  let result = iterator.next();
2221
- while (!result.done && batch.length < batchSize) {
2222
- batch.push(result.value);
2225
+ // process inline as we pull from the iterator — no intermediate array.
2226
+ // deleting from the map during iteration (via unregisterNode) is safe:
2227
+ // unvisited deleted entries are skipped, newly added nodes get visited.
2228
+ while (!result.done && processed < batchSize) {
2229
+ const node = result.value[1];
2230
+ if (node) {
2231
+ processBatchCallback(node);
2232
+ }
2233
+ processed++;
2223
2234
  result = iterator.next();
2224
2235
  }
2225
- if (batch.length > 0) {
2226
- batch.forEach(([_, node]) => {
2227
- if (node) {
2228
- processBatchCallback(node);
2229
- }
2230
- });
2231
- setTimeout(processNextBatch, 50);
2236
+ if (processed > 0) {
2237
+ // yield the thread between batches so the browser can run other work
2238
+ onScheduled(setTimeout(processNextBatch, 50));
2239
+ }
2240
+ else {
2241
+ onComplete();
2232
2242
  }
2233
2243
  }
2234
2244
  processNextBatch();
@@ -2267,17 +2277,29 @@ class Maintainer {
2267
2277
  constructor(nodes, unregisterNode, options) {
2268
2278
  this.nodes = nodes;
2269
2279
  this.unregisterNode = unregisterNode;
2280
+ this.isScanning = false;
2270
2281
  this.start = () => {
2271
2282
  if (!this.options.enabled) {
2272
2283
  return;
2273
2284
  }
2274
2285
  this.stop();
2275
2286
  this.interval = setInterval(() => {
2287
+ // a previous scan may still be walking the map across batch timeouts
2288
+ // (large DOM and/or background-tab timer throttling). don't pile up.
2289
+ if (this.isScanning) {
2290
+ return;
2291
+ }
2292
+ this.isScanning = true;
2276
2293
  processMapInBatches(this.nodes, this.options.batchSize, (node) => {
2277
2294
  const isActive = isNodeStillActive(node)[0];
2278
2295
  if (!isActive) {
2279
2296
  this.unregisterNode(node);
2280
2297
  }
2298
+ }, (timeout) => {
2299
+ this.batchTimeout = timeout;
2300
+ }, () => {
2301
+ this.batchTimeout = undefined;
2302
+ this.isScanning = false;
2281
2303
  });
2282
2304
  }, this.options.interval);
2283
2305
  };
@@ -2285,6 +2307,11 @@ class Maintainer {
2285
2307
  if (this.interval) {
2286
2308
  clearInterval(this.interval);
2287
2309
  }
2310
+ if (this.batchTimeout) {
2311
+ clearTimeout(this.batchTimeout);
2312
+ this.batchTimeout = undefined;
2313
+ }
2314
+ this.isScanning = false;
2288
2315
  };
2289
2316
  this.options = { ...defaults$1, ...options };
2290
2317
  }
@@ -3070,6 +3097,10 @@ function isObservable(node) {
3070
3097
  }
3071
3098
  return !isIgnored(node);
3072
3099
  }
3100
+ const PRESERVE_VALUE_INPUT_TYPES = new Set(['button', 'reset', 'submit', 'checkbox', 'radio']);
3101
+ function shouldSkipValueAttribute(node) {
3102
+ return hasTag(node, 'input') && !PRESERVE_VALUE_INPUT_TYPES.has(node.type);
3103
+ }
3073
3104
  /*
3074
3105
  TODO:
3075
3106
  - fix unbinding logic + send all removals first (ensure sequence is correct)
@@ -3250,11 +3281,7 @@ class Observer {
3250
3281
  name.substring(0, 2) === 'on') {
3251
3282
  return;
3252
3283
  }
3253
- if (name === 'value' &&
3254
- hasTag(node, 'input') &&
3255
- node.type !== 'button' &&
3256
- node.type !== 'reset' &&
3257
- node.type !== 'submit') {
3284
+ if (name === 'value' && shouldSkipValueAttribute(node)) {
3258
3285
  return;
3259
3286
  }
3260
3287
  if (value === null) {
@@ -4245,7 +4272,7 @@ class App {
4245
4272
  this.stopCallbacks = [];
4246
4273
  this.commitCallbacks = [];
4247
4274
  this.activityState = ActivityState.NotActive;
4248
- this.version = '18.0.15'; // TODO: version compatability check inside each plugin.
4275
+ this.version = '18.0.17-beta.0'; // TODO: version compatability check inside each plugin.
4249
4276
  this.socketMode = false;
4250
4277
  this.compressionThreshold = 24 * 1000;
4251
4278
  this.bc = null;
@@ -9580,7 +9607,7 @@ class ConstantProperties {
9580
9607
  user_id: this.user_id,
9581
9608
  distinct_id: this.deviceId,
9582
9609
  sdk_edition: 'web',
9583
- sdk_version: '18.0.15',
9610
+ sdk_version: '18.0.17-beta.0',
9584
9611
  timezone: getUTCOffsetString(),
9585
9612
  search_engine: this.searchEngine,
9586
9613
  };
@@ -10282,7 +10309,7 @@ class API {
10282
10309
  this.signalStartIssue = (reason, missingApi) => {
10283
10310
  const doNotTrack = this.checkDoNotTrack();
10284
10311
  console.log("Tracker couldn't start due to:", JSON.stringify({
10285
- trackerVersion: '18.0.15',
10312
+ trackerVersion: '18.0.17-beta.0',
10286
10313
  projectKey: this.options.projectKey,
10287
10314
  doNotTrack,
10288
10315
  reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,