@openreplay/tracker 17.1.5 → 17.2.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/dist/cjs/entry.js CHANGED
@@ -2,719 +2,6 @@
2
2
 
3
3
  Object.defineProperty(exports, '__esModule', { value: true });
4
4
 
5
- // DEFLATE is a complex format; to read this code, you should probably check the RFC first:
6
- // https://tools.ietf.org/html/rfc1951
7
- // You may also wish to take a look at the guide I made about this program:
8
- // https://gist.github.com/101arrowz/253f31eb5abc3d9275ab943003ffecad
9
- // Some of the following code is similar to that of UZIP.js:
10
- // https://github.com/photopea/UZIP.js
11
- // However, the vast majority of the codebase has diverged from UZIP.js to increase performance and reduce bundle size.
12
- // Sometimes 0 will appear where -1 would be more appropriate. This is because using a uint
13
- // is better for memory in most engines (I *think*).
14
- var ch2 = {};
15
- var wk = (function (c, id, msg, transfer, cb) {
16
- var w = new Worker(ch2[id] || (ch2[id] = URL.createObjectURL(new Blob([
17
- c + ';addEventListener("error",function(e){e=e.error;postMessage({$e$:[e.message,e.code,e.stack]})})'
18
- ], { type: 'text/javascript' }))));
19
- w.onmessage = function (e) {
20
- var d = e.data, ed = d.$e$;
21
- if (ed) {
22
- var err = new Error(ed[0]);
23
- err['code'] = ed[1];
24
- err.stack = ed[2];
25
- cb(err, null);
26
- }
27
- else
28
- cb(null, d);
29
- };
30
- w.postMessage(msg, transfer);
31
- return w;
32
- });
33
-
34
- // aliases for shorter compressed code (most minifers don't do this)
35
- var u8 = Uint8Array, u16 = Uint16Array, i32 = Int32Array;
36
- // fixed length extra bits
37
- var fleb = new u8([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, /* unused */ 0, 0, /* impossible */ 0]);
38
- // fixed distance extra bits
39
- var fdeb = new u8([0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, /* unused */ 0, 0]);
40
- // code length index map
41
- var clim = new u8([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
42
- // get base, reverse index map from extra bits
43
- var freb = function (eb, start) {
44
- var b = new u16(31);
45
- for (var i = 0; i < 31; ++i) {
46
- b[i] = start += 1 << eb[i - 1];
47
- }
48
- // numbers here are at max 18 bits
49
- var r = new i32(b[30]);
50
- for (var i = 1; i < 30; ++i) {
51
- for (var j = b[i]; j < b[i + 1]; ++j) {
52
- r[j] = ((j - b[i]) << 5) | i;
53
- }
54
- }
55
- return { b: b, r: r };
56
- };
57
- var _a = freb(fleb, 2), fl = _a.b, revfl = _a.r;
58
- // we can ignore the fact that the other numbers are wrong; they never happen anyway
59
- fl[28] = 258, revfl[258] = 28;
60
- var _b = freb(fdeb, 0), revfd = _b.r;
61
- // map of value to reverse (assuming 16 bits)
62
- var rev = new u16(32768);
63
- for (var i$1 = 0; i$1 < 32768; ++i$1) {
64
- // reverse table algorithm from SO
65
- var x$1 = ((i$1 & 0xAAAA) >> 1) | ((i$1 & 0x5555) << 1);
66
- x$1 = ((x$1 & 0xCCCC) >> 2) | ((x$1 & 0x3333) << 2);
67
- x$1 = ((x$1 & 0xF0F0) >> 4) | ((x$1 & 0x0F0F) << 4);
68
- rev[i$1] = (((x$1 & 0xFF00) >> 8) | ((x$1 & 0x00FF) << 8)) >> 1;
69
- }
70
- // create huffman tree from u8 "map": index -> code length for code index
71
- // mb (max bits) must be at most 15
72
- // TODO: optimize/split up?
73
- var hMap = (function (cd, mb, r) {
74
- var s = cd.length;
75
- // index
76
- var i = 0;
77
- // u16 "map": index -> # of codes with bit length = index
78
- var l = new u16(mb);
79
- // length of cd must be 288 (total # of codes)
80
- for (; i < s; ++i) {
81
- if (cd[i])
82
- ++l[cd[i] - 1];
83
- }
84
- // u16 "map": index -> minimum code for bit length = index
85
- var le = new u16(mb);
86
- for (i = 1; i < mb; ++i) {
87
- le[i] = (le[i - 1] + l[i - 1]) << 1;
88
- }
89
- var co;
90
- if (r) {
91
- // u16 "map": index -> number of actual bits, symbol for code
92
- co = new u16(1 << mb);
93
- // bits to remove for reverser
94
- var rvb = 15 - mb;
95
- for (i = 0; i < s; ++i) {
96
- // ignore 0 lengths
97
- if (cd[i]) {
98
- // num encoding both symbol and bits read
99
- var sv = (i << 4) | cd[i];
100
- // free bits
101
- var r_1 = mb - cd[i];
102
- // start value
103
- var v = le[cd[i] - 1]++ << r_1;
104
- // m is end value
105
- for (var m = v | ((1 << r_1) - 1); v <= m; ++v) {
106
- // every 16 bit value starting with the code yields the same result
107
- co[rev[v] >> rvb] = sv;
108
- }
109
- }
110
- }
111
- }
112
- else {
113
- co = new u16(s);
114
- for (i = 0; i < s; ++i) {
115
- if (cd[i]) {
116
- co[i] = rev[le[cd[i] - 1]++] >> (15 - cd[i]);
117
- }
118
- }
119
- }
120
- return co;
121
- });
122
- // fixed length tree
123
- var flt = new u8(288);
124
- for (var i$1 = 0; i$1 < 144; ++i$1)
125
- flt[i$1] = 8;
126
- for (var i$1 = 144; i$1 < 256; ++i$1)
127
- flt[i$1] = 9;
128
- for (var i$1 = 256; i$1 < 280; ++i$1)
129
- flt[i$1] = 7;
130
- for (var i$1 = 280; i$1 < 288; ++i$1)
131
- flt[i$1] = 8;
132
- // fixed distance tree
133
- var fdt = new u8(32);
134
- for (var i$1 = 0; i$1 < 32; ++i$1)
135
- fdt[i$1] = 5;
136
- // fixed length map
137
- var flm = /*#__PURE__*/ hMap(flt, 9, 0);
138
- // fixed distance map
139
- var fdm = /*#__PURE__*/ hMap(fdt, 5, 0);
140
- // get end of byte
141
- var shft = function (p) { return ((p + 7) / 8) | 0; };
142
- // typed array slice - allows garbage collector to free original reference,
143
- // while being more compatible than .slice
144
- var slc = function (v, s, e) {
145
- if (s == null || s < 0)
146
- s = 0;
147
- if (e == null || e > v.length)
148
- e = v.length;
149
- // can't use .constructor in case user-supplied
150
- return new u8(v.subarray(s, e));
151
- };
152
- // error codes
153
- var ec = [
154
- 'unexpected EOF',
155
- 'invalid block type',
156
- 'invalid length/literal',
157
- 'invalid distance',
158
- 'stream finished',
159
- 'no stream handler',
160
- ,
161
- 'no callback',
162
- 'invalid UTF-8 data',
163
- 'extra field too long',
164
- 'date not in range 1980-2099',
165
- 'filename too long',
166
- 'stream finishing',
167
- 'invalid zip data'
168
- // determined by unknown compression method
169
- ];
170
- var err = function (ind, msg, nt) {
171
- var e = new Error(msg || ec[ind]);
172
- e.code = ind;
173
- if (Error.captureStackTrace)
174
- Error.captureStackTrace(e, err);
175
- if (!nt)
176
- throw e;
177
- return e;
178
- };
179
- // starting at p, write the minimum number of bits that can hold v to d
180
- var wbits = function (d, p, v) {
181
- v <<= p & 7;
182
- var o = (p / 8) | 0;
183
- d[o] |= v;
184
- d[o + 1] |= v >> 8;
185
- };
186
- // starting at p, write the minimum number of bits (>8) that can hold v to d
187
- var wbits16 = function (d, p, v) {
188
- v <<= p & 7;
189
- var o = (p / 8) | 0;
190
- d[o] |= v;
191
- d[o + 1] |= v >> 8;
192
- d[o + 2] |= v >> 16;
193
- };
194
- // creates code lengths from a frequency table
195
- var hTree = function (d, mb) {
196
- // Need extra info to make a tree
197
- var t = [];
198
- for (var i = 0; i < d.length; ++i) {
199
- if (d[i])
200
- t.push({ s: i, f: d[i] });
201
- }
202
- var s = t.length;
203
- var t2 = t.slice();
204
- if (!s)
205
- return { t: et, l: 0 };
206
- if (s == 1) {
207
- var v = new u8(t[0].s + 1);
208
- v[t[0].s] = 1;
209
- return { t: v, l: 1 };
210
- }
211
- t.sort(function (a, b) { return a.f - b.f; });
212
- // after i2 reaches last ind, will be stopped
213
- // freq must be greater than largest possible number of symbols
214
- t.push({ s: -1, f: 25001 });
215
- var l = t[0], r = t[1], i0 = 0, i1 = 1, i2 = 2;
216
- t[0] = { s: -1, f: l.f + r.f, l: l, r: r };
217
- // efficient algorithm from UZIP.js
218
- // i0 is lookbehind, i2 is lookahead - after processing two low-freq
219
- // symbols that combined have high freq, will start processing i2 (high-freq,
220
- // non-composite) symbols instead
221
- // see https://reddit.com/r/photopea/comments/ikekht/uzipjs_questions/
222
- while (i1 != s - 1) {
223
- l = t[t[i0].f < t[i2].f ? i0++ : i2++];
224
- r = t[i0 != i1 && t[i0].f < t[i2].f ? i0++ : i2++];
225
- t[i1++] = { s: -1, f: l.f + r.f, l: l, r: r };
226
- }
227
- var maxSym = t2[0].s;
228
- for (var i = 1; i < s; ++i) {
229
- if (t2[i].s > maxSym)
230
- maxSym = t2[i].s;
231
- }
232
- // code lengths
233
- var tr = new u16(maxSym + 1);
234
- // max bits in tree
235
- var mbt = ln(t[i1 - 1], tr, 0);
236
- if (mbt > mb) {
237
- // more algorithms from UZIP.js
238
- // TODO: find out how this code works (debt)
239
- // ind debt
240
- var i = 0, dt = 0;
241
- // left cost
242
- var lft = mbt - mb, cst = 1 << lft;
243
- t2.sort(function (a, b) { return tr[b.s] - tr[a.s] || a.f - b.f; });
244
- for (; i < s; ++i) {
245
- var i2_1 = t2[i].s;
246
- if (tr[i2_1] > mb) {
247
- dt += cst - (1 << (mbt - tr[i2_1]));
248
- tr[i2_1] = mb;
249
- }
250
- else
251
- break;
252
- }
253
- dt >>= lft;
254
- while (dt > 0) {
255
- var i2_2 = t2[i].s;
256
- if (tr[i2_2] < mb)
257
- dt -= 1 << (mb - tr[i2_2]++ - 1);
258
- else
259
- ++i;
260
- }
261
- for (; i >= 0 && dt; --i) {
262
- var i2_3 = t2[i].s;
263
- if (tr[i2_3] == mb) {
264
- --tr[i2_3];
265
- ++dt;
266
- }
267
- }
268
- mbt = mb;
269
- }
270
- return { t: new u8(tr), l: mbt };
271
- };
272
- // get the max length and assign length codes
273
- var ln = function (n, l, d) {
274
- return n.s == -1
275
- ? Math.max(ln(n.l, l, d + 1), ln(n.r, l, d + 1))
276
- : (l[n.s] = d);
277
- };
278
- // length codes generation
279
- var lc = function (c) {
280
- var s = c.length;
281
- // Note that the semicolon was intentional
282
- while (s && !c[--s])
283
- ;
284
- var cl = new u16(++s);
285
- // ind num streak
286
- var cli = 0, cln = c[0], cls = 1;
287
- var w = function (v) { cl[cli++] = v; };
288
- for (var i = 1; i <= s; ++i) {
289
- if (c[i] == cln && i != s)
290
- ++cls;
291
- else {
292
- if (!cln && cls > 2) {
293
- for (; cls > 138; cls -= 138)
294
- w(32754);
295
- if (cls > 2) {
296
- w(cls > 10 ? ((cls - 11) << 5) | 28690 : ((cls - 3) << 5) | 12305);
297
- cls = 0;
298
- }
299
- }
300
- else if (cls > 3) {
301
- w(cln), --cls;
302
- for (; cls > 6; cls -= 6)
303
- w(8304);
304
- if (cls > 2)
305
- w(((cls - 3) << 5) | 8208), cls = 0;
306
- }
307
- while (cls--)
308
- w(cln);
309
- cls = 1;
310
- cln = c[i];
311
- }
312
- }
313
- return { c: cl.subarray(0, cli), n: s };
314
- };
315
- // calculate the length of output from tree, code lengths
316
- var clen = function (cf, cl) {
317
- var l = 0;
318
- for (var i = 0; i < cl.length; ++i)
319
- l += cf[i] * cl[i];
320
- return l;
321
- };
322
- // writes a fixed block
323
- // returns the new bit pos
324
- var wfblk = function (out, pos, dat) {
325
- // no need to write 00 as type: TypedArray defaults to 0
326
- var s = dat.length;
327
- var o = shft(pos + 2);
328
- out[o] = s & 255;
329
- out[o + 1] = s >> 8;
330
- out[o + 2] = out[o] ^ 255;
331
- out[o + 3] = out[o + 1] ^ 255;
332
- for (var i = 0; i < s; ++i)
333
- out[o + i + 4] = dat[i];
334
- return (o + 4 + s) * 8;
335
- };
336
- // writes a block
337
- var wblk = function (dat, out, final, syms, lf, df, eb, li, bs, bl, p) {
338
- wbits(out, p++, final);
339
- ++lf[256];
340
- var _a = hTree(lf, 15), dlt = _a.t, mlb = _a.l;
341
- var _b = hTree(df, 15), ddt = _b.t, mdb = _b.l;
342
- var _c = lc(dlt), lclt = _c.c, nlc = _c.n;
343
- var _d = lc(ddt), lcdt = _d.c, ndc = _d.n;
344
- var lcfreq = new u16(19);
345
- for (var i = 0; i < lclt.length; ++i)
346
- ++lcfreq[lclt[i] & 31];
347
- for (var i = 0; i < lcdt.length; ++i)
348
- ++lcfreq[lcdt[i] & 31];
349
- var _e = hTree(lcfreq, 7), lct = _e.t, mlcb = _e.l;
350
- var nlcc = 19;
351
- for (; nlcc > 4 && !lct[clim[nlcc - 1]]; --nlcc)
352
- ;
353
- var flen = (bl + 5) << 3;
354
- var ftlen = clen(lf, flt) + clen(df, fdt) + eb;
355
- var dtlen = clen(lf, dlt) + clen(df, ddt) + eb + 14 + 3 * nlcc + clen(lcfreq, lct) + 2 * lcfreq[16] + 3 * lcfreq[17] + 7 * lcfreq[18];
356
- if (bs >= 0 && flen <= ftlen && flen <= dtlen)
357
- return wfblk(out, p, dat.subarray(bs, bs + bl));
358
- var lm, ll, dm, dl;
359
- wbits(out, p, 1 + (dtlen < ftlen)), p += 2;
360
- if (dtlen < ftlen) {
361
- lm = hMap(dlt, mlb, 0), ll = dlt, dm = hMap(ddt, mdb, 0), dl = ddt;
362
- var llm = hMap(lct, mlcb, 0);
363
- wbits(out, p, nlc - 257);
364
- wbits(out, p + 5, ndc - 1);
365
- wbits(out, p + 10, nlcc - 4);
366
- p += 14;
367
- for (var i = 0; i < nlcc; ++i)
368
- wbits(out, p + 3 * i, lct[clim[i]]);
369
- p += 3 * nlcc;
370
- var lcts = [lclt, lcdt];
371
- for (var it = 0; it < 2; ++it) {
372
- var clct = lcts[it];
373
- for (var i = 0; i < clct.length; ++i) {
374
- var len = clct[i] & 31;
375
- wbits(out, p, llm[len]), p += lct[len];
376
- if (len > 15)
377
- wbits(out, p, (clct[i] >> 5) & 127), p += clct[i] >> 12;
378
- }
379
- }
380
- }
381
- else {
382
- lm = flm, ll = flt, dm = fdm, dl = fdt;
383
- }
384
- for (var i = 0; i < li; ++i) {
385
- var sym = syms[i];
386
- if (sym > 255) {
387
- var len = (sym >> 18) & 31;
388
- wbits16(out, p, lm[len + 257]), p += ll[len + 257];
389
- if (len > 7)
390
- wbits(out, p, (sym >> 23) & 31), p += fleb[len];
391
- var dst = sym & 31;
392
- wbits16(out, p, dm[dst]), p += dl[dst];
393
- if (dst > 3)
394
- wbits16(out, p, (sym >> 5) & 8191), p += fdeb[dst];
395
- }
396
- else {
397
- wbits16(out, p, lm[sym]), p += ll[sym];
398
- }
399
- }
400
- wbits16(out, p, lm[256]);
401
- return p + ll[256];
402
- };
403
- // deflate options (nice << 13) | chain
404
- var deo = /*#__PURE__*/ new i32([65540, 131080, 131088, 131104, 262176, 1048704, 1048832, 2114560, 2117632]);
405
- // empty
406
- var et = /*#__PURE__*/ new u8(0);
407
- // compresses data into a raw DEFLATE buffer
408
- var dflt = function (dat, lvl, plvl, pre, post, st) {
409
- var s = st.z || dat.length;
410
- var o = new u8(pre + s + 5 * (1 + Math.ceil(s / 7000)) + post);
411
- // writing to this writes to the output buffer
412
- var w = o.subarray(pre, o.length - post);
413
- var lst = st.l;
414
- var pos = (st.r || 0) & 7;
415
- if (lvl) {
416
- if (pos)
417
- w[0] = st.r >> 3;
418
- var opt = deo[lvl - 1];
419
- var n = opt >> 13, c = opt & 8191;
420
- var msk_1 = (1 << plvl) - 1;
421
- // prev 2-byte val map curr 2-byte val map
422
- var prev = st.p || new u16(32768), head = st.h || new u16(msk_1 + 1);
423
- var bs1_1 = Math.ceil(plvl / 3), bs2_1 = 2 * bs1_1;
424
- var hsh = function (i) { return (dat[i] ^ (dat[i + 1] << bs1_1) ^ (dat[i + 2] << bs2_1)) & msk_1; };
425
- // 24576 is an arbitrary number of maximum symbols per block
426
- // 424 buffer for last block
427
- var syms = new i32(25000);
428
- // length/literal freq distance freq
429
- var lf = new u16(288), df = new u16(32);
430
- // l/lcnt exbits index l/lind waitdx blkpos
431
- var lc_1 = 0, eb = 0, i = st.i || 0, li = 0, wi = st.w || 0, bs = 0;
432
- for (; i + 2 < s; ++i) {
433
- // hash value
434
- var hv = hsh(i);
435
- // index mod 32768 previous index mod
436
- var imod = i & 32767, pimod = head[hv];
437
- prev[imod] = pimod;
438
- head[hv] = imod;
439
- // We always should modify head and prev, but only add symbols if
440
- // this data is not yet processed ("wait" for wait index)
441
- if (wi <= i) {
442
- // bytes remaining
443
- var rem = s - i;
444
- if ((lc_1 > 7000 || li > 24576) && (rem > 423 || !lst)) {
445
- pos = wblk(dat, w, 0, syms, lf, df, eb, li, bs, i - bs, pos);
446
- li = lc_1 = eb = 0, bs = i;
447
- for (var j = 0; j < 286; ++j)
448
- lf[j] = 0;
449
- for (var j = 0; j < 30; ++j)
450
- df[j] = 0;
451
- }
452
- // len dist chain
453
- var l = 2, d = 0, ch_1 = c, dif = imod - pimod & 32767;
454
- if (rem > 2 && hv == hsh(i - dif)) {
455
- var maxn = Math.min(n, rem) - 1;
456
- var maxd = Math.min(32767, i);
457
- // max possible length
458
- // not capped at dif because decompressors implement "rolling" index population
459
- var ml = Math.min(258, rem);
460
- while (dif <= maxd && --ch_1 && imod != pimod) {
461
- if (dat[i + l] == dat[i + l - dif]) {
462
- var nl = 0;
463
- for (; nl < ml && dat[i + nl] == dat[i + nl - dif]; ++nl)
464
- ;
465
- if (nl > l) {
466
- l = nl, d = dif;
467
- // break out early when we reach "nice" (we are satisfied enough)
468
- if (nl > maxn)
469
- break;
470
- // now, find the rarest 2-byte sequence within this
471
- // length of literals and search for that instead.
472
- // Much faster than just using the start
473
- var mmd = Math.min(dif, nl - 2);
474
- var md = 0;
475
- for (var j = 0; j < mmd; ++j) {
476
- var ti = i - dif + j & 32767;
477
- var pti = prev[ti];
478
- var cd = ti - pti & 32767;
479
- if (cd > md)
480
- md = cd, pimod = ti;
481
- }
482
- }
483
- }
484
- // check the previous match
485
- imod = pimod, pimod = prev[imod];
486
- dif += imod - pimod & 32767;
487
- }
488
- }
489
- // d will be nonzero only when a match was found
490
- if (d) {
491
- // store both dist and len data in one int32
492
- // Make sure this is recognized as a len/dist with 28th bit (2^28)
493
- syms[li++] = 268435456 | (revfl[l] << 18) | revfd[d];
494
- var lin = revfl[l] & 31, din = revfd[d] & 31;
495
- eb += fleb[lin] + fdeb[din];
496
- ++lf[257 + lin];
497
- ++df[din];
498
- wi = i + l;
499
- ++lc_1;
500
- }
501
- else {
502
- syms[li++] = dat[i];
503
- ++lf[dat[i]];
504
- }
505
- }
506
- }
507
- for (i = Math.max(i, wi); i < s; ++i) {
508
- syms[li++] = dat[i];
509
- ++lf[dat[i]];
510
- }
511
- pos = wblk(dat, w, lst, syms, lf, df, eb, li, bs, i - bs, pos);
512
- if (!lst) {
513
- st.r = (pos & 7) | w[(pos / 8) | 0] << 3;
514
- // shft(pos) now 1 less if pos & 7 != 0
515
- pos -= 7;
516
- st.h = head, st.p = prev, st.i = i, st.w = wi;
517
- }
518
- }
519
- else {
520
- for (var i = st.w || 0; i < s + lst; i += 65535) {
521
- // end
522
- var e = i + 65535;
523
- if (e >= s) {
524
- // write final block
525
- w[(pos / 8) | 0] = lst;
526
- e = s;
527
- }
528
- pos = wfblk(w, pos + 1, dat.subarray(i, e));
529
- }
530
- st.i = s;
531
- }
532
- return slc(o, 0, pre + shft(pos) + post);
533
- };
534
- // CRC32 table
535
- var crct = /*#__PURE__*/ (function () {
536
- var t = new Int32Array(256);
537
- for (var i = 0; i < 256; ++i) {
538
- var c = i, k = 9;
539
- while (--k)
540
- c = ((c & 1) && -306674912) ^ (c >>> 1);
541
- t[i] = c;
542
- }
543
- return t;
544
- })();
545
- // CRC32
546
- var crc = function () {
547
- var c = -1;
548
- return {
549
- p: function (d) {
550
- // closures have awful performance
551
- var cr = c;
552
- for (var i = 0; i < d.length; ++i)
553
- cr = crct[(cr & 255) ^ d[i]] ^ (cr >>> 8);
554
- c = cr;
555
- },
556
- d: function () { return ~c; }
557
- };
558
- };
559
- // deflate with opts
560
- var dopt = function (dat, opt, pre, post, st) {
561
- if (!st) {
562
- st = { l: 1 };
563
- if (opt.dictionary) {
564
- var dict = opt.dictionary.subarray(-32768);
565
- var newDat = new u8(dict.length + dat.length);
566
- newDat.set(dict);
567
- newDat.set(dat, dict.length);
568
- dat = newDat;
569
- st.w = dict.length;
570
- }
571
- }
572
- return dflt(dat, opt.level == null ? 6 : opt.level, opt.mem == null ? (st.l ? Math.ceil(Math.max(8, Math.min(13, Math.log(dat.length))) * 1.5) : 20) : (12 + opt.mem), pre, post, st);
573
- };
574
- // Walmart object spread
575
- var mrg = function (a, b) {
576
- var o = {};
577
- for (var k in a)
578
- o[k] = a[k];
579
- for (var k in b)
580
- o[k] = b[k];
581
- return o;
582
- };
583
- // worker clone
584
- // This is possibly the craziest part of the entire codebase, despite how simple it may seem.
585
- // The only parameter to this function is a closure that returns an array of variables outside of the function scope.
586
- // We're going to try to figure out the variable names used in the closure as strings because that is crucial for workerization.
587
- // We will return an object mapping of true variable name to value (basically, the current scope as a JS object).
588
- // The reason we can't just use the original variable names is minifiers mangling the toplevel scope.
589
- // This took me three weeks to figure out how to do.
590
- var wcln = function (fn, fnStr, td) {
591
- var dt = fn();
592
- var st = fn.toString();
593
- var ks = st.slice(st.indexOf('[') + 1, st.lastIndexOf(']')).replace(/\s+/g, '').split(',');
594
- for (var i = 0; i < dt.length; ++i) {
595
- var v = dt[i], k = ks[i];
596
- if (typeof v == 'function') {
597
- fnStr += ';' + k + '=';
598
- var st_1 = v.toString();
599
- if (v.prototype) {
600
- // for global objects
601
- if (st_1.indexOf('[native code]') != -1) {
602
- var spInd = st_1.indexOf(' ', 8) + 1;
603
- fnStr += st_1.slice(spInd, st_1.indexOf('(', spInd));
604
- }
605
- else {
606
- fnStr += st_1;
607
- for (var t in v.prototype)
608
- fnStr += ';' + k + '.prototype.' + t + '=' + v.prototype[t].toString();
609
- }
610
- }
611
- else
612
- fnStr += st_1;
613
- }
614
- else
615
- td[k] = v;
616
- }
617
- return fnStr;
618
- };
619
- var ch = [];
620
- // clone bufs
621
- var cbfs = function (v) {
622
- var tl = [];
623
- for (var k in v) {
624
- if (v[k].buffer) {
625
- tl.push((v[k] = new v[k].constructor(v[k])).buffer);
626
- }
627
- }
628
- return tl;
629
- };
630
- // use a worker to execute code
631
- var wrkr = function (fns, init, id, cb) {
632
- if (!ch[id]) {
633
- var fnStr = '', td_1 = {}, m = fns.length - 1;
634
- for (var i = 0; i < m; ++i)
635
- fnStr = wcln(fns[i], fnStr, td_1);
636
- ch[id] = { c: wcln(fns[m], fnStr, td_1), e: td_1 };
637
- }
638
- var td = mrg({}, ch[id].e);
639
- return wk(ch[id].c + ';onmessage=function(e){for(var k in e.data)self[k]=e.data[k];onmessage=' + init.toString() + '}', id, td, cbfs(td), cb);
640
- };
641
- var bDflt = function () { return [u8, u16, i32, fleb, fdeb, clim, revfl, revfd, flm, flt, fdm, fdt, rev, deo, et, hMap, wbits, wbits16, hTree, ln, lc, clen, wfblk, wblk, shft, slc, dflt, dopt, deflateSync, pbf]; };
642
- // gzip extra
643
- var gze = function () { return [gzh, gzhl, wbytes, crc, crct]; };
644
- // post buf
645
- var pbf = function (msg) { return postMessage(msg, [msg.buffer]); };
646
- // async helper
647
- var cbify = function (dat, opts, fns, init, id, cb) {
648
- var w = wrkr(fns, init, id, function (err, dat) {
649
- w.terminate();
650
- cb(err, dat);
651
- });
652
- w.postMessage([dat, opts], opts.consume ? [dat.buffer] : []);
653
- return function () { w.terminate(); };
654
- };
655
- // write bytes
656
- var wbytes = function (d, b, v) {
657
- for (; v; ++b)
658
- d[b] = v, v >>>= 8;
659
- };
660
- // gzip header
661
- var gzh = function (c, o) {
662
- var fn = o.filename;
663
- c[0] = 31, c[1] = 139, c[2] = 8, c[8] = o.level < 2 ? 4 : o.level == 9 ? 2 : 0, c[9] = 3; // assume Unix
664
- if (o.mtime != 0)
665
- wbytes(c, 4, Math.floor(new Date(o.mtime || Date.now()) / 1000));
666
- if (fn) {
667
- c[3] = 8;
668
- for (var i = 0; i <= fn.length; ++i)
669
- c[i + 10] = fn.charCodeAt(i);
670
- }
671
- };
672
- // gzip header length
673
- var gzhl = function (o) { return 10 + (o.filename ? o.filename.length + 1 : 0); };
674
- /**
675
- * Compresses data with DEFLATE without any wrapper
676
- * @param data The data to compress
677
- * @param opts The compression options
678
- * @returns The deflated version of the data
679
- */
680
- function deflateSync(data, opts) {
681
- return dopt(data, opts || {}, 0, 0);
682
- }
683
- function gzip(data, opts, cb) {
684
- if (!cb)
685
- cb = opts, opts = {};
686
- if (typeof cb != 'function')
687
- err(7);
688
- return cbify(data, opts, [
689
- bDflt,
690
- gze,
691
- function () { return [gzipSync]; }
692
- ], function (ev) { return pbf(gzipSync(ev.data[0], ev.data[1])); }, 2, cb);
693
- }
694
- /**
695
- * Compresses data with GZIP
696
- * @param data The data to compress
697
- * @param opts The compression options
698
- * @returns The gzipped version of the data
699
- */
700
- function gzipSync(data, opts) {
701
- if (!opts)
702
- opts = {};
703
- var c = crc(), l = data.length;
704
- c.p(data);
705
- var d = dopt(data, opts, gzhl(opts), 8), s = d.length;
706
- return gzh(d, opts), wbytes(d, s - 8, c.d()), wbytes(d, s - 4, l), d;
707
- }
708
- // text decoder
709
- var td = typeof TextDecoder != 'undefined' && /*#__PURE__*/ new TextDecoder();
710
- // text decoder stream
711
- var tds = 0;
712
- try {
713
- td.decode(et, { stream: true });
714
- tds = 1;
715
- }
716
- catch (e) { }
717
-
718
5
  class StringDictionary {
719
6
  constructor() {
720
7
  this.lastTs = 0;
@@ -1135,7 +422,7 @@ const stars = 'repeat' in String.prototype
1135
422
  ? (str) => '*'.repeat(str.length)
1136
423
  : (str) => str.replace(/./g, '*');
1137
424
  function normSpaces(str) {
1138
- return str.trim().replace(/\s+/g, ' ');
425
+ return str ? str.trim().replace(/\s+/g, ' ') : '';
1139
426
  }
1140
427
  // isAbsoluteUrl regexp: /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url)
1141
428
  function isURL(s) {
@@ -2332,7 +1619,13 @@ class CanvasRecorder {
2332
1619
  this.app = app;
2333
1620
  this.options = options;
2334
1621
  this.snapshots = {};
2335
- this.intervals = [];
1622
+ this.intervals = new Map();
1623
+ this.observers = new Map();
1624
+ this.uploadQueue = 0;
1625
+ this.MAX_CONCURRENT_UPLOADS = 2;
1626
+ this.MAX_QUEUE_SIZE = 50; // ~500 images max (50 batches × 10 images)
1627
+ this.pendingBatches = [];
1628
+ this.isProcessingQueue = false;
2336
1629
  this.restartTracking = () => {
2337
1630
  this.clear();
2338
1631
  this.app.nodes.scanTree(this.captureCanvas);
@@ -2343,34 +1636,33 @@ class CanvasRecorder {
2343
1636
  return;
2344
1637
  }
2345
1638
  const isIgnored = this.app.sanitizer.isObscured(id) || this.app.sanitizer.isHidden(id);
2346
- if (isIgnored || !hasTag(node, 'canvas') || this.snapshots[id]) {
1639
+ if (isIgnored || this.snapshots[id]) {
2347
1640
  return;
2348
1641
  }
2349
1642
  const observer = new IntersectionObserver((entries) => {
2350
1643
  entries.forEach((entry) => {
2351
1644
  if (entry.isIntersecting) {
2352
- if (entry.target) {
2353
- if (this.snapshots[id] && this.snapshots[id].createdAt) {
2354
- this.snapshots[id].paused = false;
2355
- }
2356
- else {
2357
- this.recordCanvas(entry.target, id);
2358
- }
2359
- /**
2360
- * We can switch this to start observing when element is in the view
2361
- * but otherwise right now we're just pausing when it's not
2362
- * just to save some bandwidth and space on backend
2363
- * */
2364
- // observer.unobserve(entry.target)
1645
+ if (this.snapshots[id] && this.snapshots[id].createdAt) {
1646
+ this.snapshots[id].paused = false;
2365
1647
  }
2366
1648
  else {
2367
- if (this.snapshots[id]) {
2368
- this.snapshots[id].paused = true;
2369
- }
1649
+ this.recordCanvas(entry.target, id);
1650
+ }
1651
+ /**
1652
+ * We can switch this to start observing when element is in the view
1653
+ * but otherwise right now we're just pausing when it's not
1654
+ * just to save some bandwidth and space on backend
1655
+ * */
1656
+ // observer.unobserve(entry.target)
1657
+ }
1658
+ else {
1659
+ if (this.snapshots[id]) {
1660
+ this.snapshots[id].paused = true;
2370
1661
  }
2371
1662
  }
2372
1663
  });
2373
1664
  });
1665
+ this.observers.set(id, observer);
2374
1666
  observer.observe(node);
2375
1667
  };
2376
1668
  this.recordCanvas = (node, id) => {
@@ -2380,15 +1672,23 @@ class CanvasRecorder {
2380
1672
  createdAt: ts,
2381
1673
  paused: false,
2382
1674
  dummy: document.createElement('canvas'),
1675
+ isCapturing: false,
1676
+ isStopped: false,
2383
1677
  };
2384
1678
  const canvasMsg = CanvasNode(id.toString(), ts);
2385
1679
  this.app.send(canvasMsg);
1680
+ const cachedCanvas = node;
2386
1681
  const captureFn = (canvas) => {
1682
+ if (!this.snapshots[id] || this.snapshots[id].isCapturing || this.snapshots[id].isStopped) {
1683
+ return;
1684
+ }
1685
+ this.snapshots[id].isCapturing = true;
2387
1686
  captureSnapshot(canvas, this.options.quality, this.snapshots[id].dummy, this.options.fixedScaling, this.fileExt, (blob) => {
2388
- if (!blob)
1687
+ if (this.snapshots[id]) {
1688
+ this.snapshots[id].isCapturing = false;
1689
+ }
1690
+ if (!blob || !this.snapshots[id] || this.snapshots[id].isStopped) {
2389
1691
  return;
2390
- if (!this.snapshots[id]) {
2391
- return this.app.debug.warn('Canvas not present in snapshots after capture:', this.snapshots, id);
2392
1692
  }
2393
1693
  this.snapshots[id].images.push({ id: this.app.timestamp(), data: blob });
2394
1694
  if (this.snapshots[id].images.length > 9) {
@@ -2398,34 +1698,31 @@ class CanvasRecorder {
2398
1698
  });
2399
1699
  };
2400
1700
  const int = setInterval(() => {
2401
- const cid = this.app.nodes.getID(node);
2402
- const canvas = cid ? this.app.nodes.getNode(cid) : undefined;
2403
- if (!this.snapshots[id]) {
1701
+ const snapshot = this.snapshots[id];
1702
+ if (!snapshot || snapshot.isStopped) {
2404
1703
  this.app.debug.log('Canvas is not present in {snapshots}');
2405
- clearInterval(int);
1704
+ this.cleanupCanvas(id);
2406
1705
  return;
2407
1706
  }
2408
- if (!canvas || !hasTag(canvas, 'canvas') || canvas !== node) {
2409
- this.app.debug.log('Canvas element not in sync', canvas, node);
2410
- clearInterval(int);
1707
+ if (!document.contains(cachedCanvas)) {
1708
+ this.app.debug.log('Canvas element not in sync', cachedCanvas, node);
1709
+ this.cleanupCanvas(id);
2411
1710
  return;
2412
1711
  }
2413
- else {
2414
- if (!this.snapshots[id].paused) {
2415
- if (this.options.useAnimationFrame) {
2416
- requestAnimationFrame(() => {
2417
- captureFn(canvas);
2418
- });
2419
- }
2420
- else {
2421
- captureFn(canvas);
2422
- }
1712
+ if (!snapshot.paused) {
1713
+ if (this.options.useAnimationFrame) {
1714
+ requestAnimationFrame(() => {
1715
+ captureFn(cachedCanvas);
1716
+ });
1717
+ }
1718
+ else {
1719
+ captureFn(cachedCanvas);
2423
1720
  }
2424
1721
  }
2425
1722
  }, this.interval);
2426
- this.intervals.push(int);
1723
+ this.intervals.set(id, int);
2427
1724
  };
2428
- this.fileExt = options.fileExt ?? 'webp';
1725
+ this.fileExt = 'webp';
2429
1726
  this.interval = 1000 / options.fps;
2430
1727
  }
2431
1728
  startTracking() {
@@ -2438,16 +1735,90 @@ class CanvasRecorder {
2438
1735
  if (Object.keys(this.snapshots).length === 0) {
2439
1736
  return;
2440
1737
  }
2441
- const formData = new FormData();
2442
- images.forEach((snapshot) => {
2443
- const blob = snapshot.data;
2444
- if (!blob)
2445
- return;
2446
- formData.append('snapshot', blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`);
2447
- if (this.options.isDebug) {
2448
- saveImageData(blob, `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`);
1738
+ if (this.pendingBatches.length >= this.MAX_QUEUE_SIZE) {
1739
+ this.app.debug.warn('Upload queue full, dropping canvas batch');
1740
+ return;
1741
+ }
1742
+ this.pendingBatches.push({ images, canvasId, createdAt });
1743
+ if (!this.isProcessingQueue) {
1744
+ this.processUploadQueue();
1745
+ }
1746
+ }
1747
+ async processUploadQueue() {
1748
+ this.isProcessingQueue = true;
1749
+ while (this.pendingBatches.length > 0) {
1750
+ if (this.uploadQueue >= this.MAX_CONCURRENT_UPLOADS) {
1751
+ await new Promise((resolve) => setTimeout(resolve, 100));
1752
+ continue;
2449
1753
  }
2450
- });
1754
+ const batch = this.pendingBatches.shift();
1755
+ if (!batch)
1756
+ break;
1757
+ this.uploadBatch(batch.images, batch.canvasId, batch.createdAt);
1758
+ }
1759
+ this.isProcessingQueue = false;
1760
+ }
1761
+ async uploadBatch(images, canvasId, createdAt) {
1762
+ if (this.options.isDebug) {
1763
+ const fileEntries = [];
1764
+ images.forEach((snapshot) => {
1765
+ if (!snapshot.data)
1766
+ return;
1767
+ fileEntries.push({ data: snapshot.data, name: `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}` });
1768
+ });
1769
+ void saveArchive(fileEntries, `canvas_${canvasId}_${createdAt}`);
1770
+ return;
1771
+ }
1772
+ let formData;
1773
+ if (this.options.framesSupport) {
1774
+ // Pack frames into binary format: [uint64 LE timestamp][uint32 LE size][data] per frame
1775
+ const buffers = [];
1776
+ let totalSize = 0;
1777
+ for (const snapshot of images) {
1778
+ if (!snapshot.data)
1779
+ continue;
1780
+ const ab = await snapshot.data.arrayBuffer();
1781
+ buffers.push(ab);
1782
+ totalSize += 8 + 4 + ab.byteLength; // uint64 ts + uint32 size + data
1783
+ }
1784
+ if (totalSize === 0)
1785
+ return;
1786
+ const packed = new ArrayBuffer(totalSize);
1787
+ const view = new DataView(packed);
1788
+ const bytes = new Uint8Array(packed);
1789
+ let offset = 0;
1790
+ for (let i = 0; i < images.length; i++) {
1791
+ if (!images[i].data)
1792
+ continue;
1793
+ const ab = buffers.shift();
1794
+ const ts = images[i].id;
1795
+ // uint64 LE as two uint32 LE writes -- timestamp
1796
+ view.setUint32(offset, ts % 0x100000000, true);
1797
+ view.setUint32(offset + 4, Math.floor(ts / 0x100000000), true);
1798
+ offset += 8;
1799
+ // uint32 LE -- size
1800
+ view.setUint32(offset, ab.byteLength, true);
1801
+ offset += 4;
1802
+ // image data
1803
+ bytes.set(new Uint8Array(ab), offset);
1804
+ offset += ab.byteLength;
1805
+ }
1806
+ formData = new FormData();
1807
+ formData.append('type', 'frames');
1808
+ const fileName = `${createdAt}_${canvasId}.${this.fileExt}.frames`;
1809
+ formData.append('frames', new Blob([packed]), fileName);
1810
+ }
1811
+ else {
1812
+ // Legacy: send individual image files
1813
+ formData = new FormData();
1814
+ images.forEach((snapshot) => {
1815
+ const blob = snapshot.data;
1816
+ if (!blob)
1817
+ return;
1818
+ const name = `${createdAt}_${canvasId}_${snapshot.id}.${this.fileExt}`;
1819
+ formData.append('snapshot', blob, name);
1820
+ });
1821
+ }
2451
1822
  const initRestart = () => {
2452
1823
  this.app.debug.log('Restarting tracker; token expired');
2453
1824
  this.app.stop(false);
@@ -2455,6 +1826,7 @@ class CanvasRecorder {
2455
1826
  void this.app.start({}, true);
2456
1827
  }, 250);
2457
1828
  };
1829
+ this.uploadQueue++;
2458
1830
  fetch(this.app.options.ingestPoint + '/v1/web/images', {
2459
1831
  method: 'POST',
2460
1832
  headers: {
@@ -2470,10 +1842,50 @@ class CanvasRecorder {
2470
1842
  })
2471
1843
  .catch((e) => {
2472
1844
  this.app.debug.error('error saving canvas', e);
1845
+ })
1846
+ .finally(() => {
1847
+ this.uploadQueue--;
2473
1848
  });
2474
1849
  }
1850
+ cleanupCanvas(id) {
1851
+ if (this.snapshots[id]) {
1852
+ this.snapshots[id].isStopped = true;
1853
+ }
1854
+ const interval = this.intervals.get(id);
1855
+ if (interval) {
1856
+ clearInterval(interval);
1857
+ this.intervals.delete(id);
1858
+ }
1859
+ const observer = this.observers.get(id);
1860
+ if (observer) {
1861
+ observer.disconnect();
1862
+ this.observers.delete(id);
1863
+ }
1864
+ if (this.snapshots[id]?.dummy) {
1865
+ const dummy = this.snapshots[id].dummy;
1866
+ dummy.width = 0;
1867
+ dummy.height = 0;
1868
+ }
1869
+ delete this.snapshots[id];
1870
+ }
2475
1871
  clear() {
2476
- this.intervals.forEach((int) => clearInterval(int));
1872
+ // Flush remaining images before cleanup
1873
+ Object.keys(this.snapshots).forEach((idStr) => {
1874
+ const id = parseInt(idStr, 10);
1875
+ const snapshot = this.snapshots[id];
1876
+ if (snapshot && snapshot.images.length > 0) {
1877
+ this.sendSnaps(snapshot.images, id, snapshot.createdAt);
1878
+ snapshot.images = [];
1879
+ }
1880
+ });
1881
+ Object.keys(this.snapshots).forEach((idStr) => {
1882
+ const id = parseInt(idStr, 10);
1883
+ this.cleanupCanvas(id);
1884
+ });
1885
+ // don't clear pendingBatches or stop queue processing
1886
+ // to allow flushed images to finish uploading in the background
1887
+ this.intervals.clear();
1888
+ this.observers.clear();
2477
1889
  this.snapshots = {};
2478
1890
  }
2479
1891
  }
@@ -2500,15 +1912,80 @@ function captureSnapshot(canvas, quality = 'medium', dummy, fixedScaling = false
2500
1912
  canvas.toBlob(onBlob, imageFormat, qualityInt[quality]);
2501
1913
  }
2502
1914
  }
2503
- function saveImageData(imageDataBlob, name) {
2504
- const imageDataUrl = URL.createObjectURL(imageDataBlob);
1915
+ async function saveArchive(files, archiveName) {
1916
+ const zipBlob = await createZipBlob(files);
1917
+ const url = URL.createObjectURL(zipBlob);
2505
1918
  const link = document.createElement('a');
2506
- link.href = imageDataUrl;
2507
- link.download = name;
1919
+ link.href = url;
1920
+ link.download = `${archiveName}.zip`;
2508
1921
  link.style.display = 'none';
2509
1922
  document.body.appendChild(link);
2510
1923
  link.click();
2511
1924
  document.body.removeChild(link);
1925
+ URL.revokeObjectURL(url);
1926
+ }
1927
+ async function createZipBlob(files) {
1928
+ const parts = [];
1929
+ const centralDir = [];
1930
+ let offset = 0;
1931
+ for (const file of files) {
1932
+ const nameBytes = new TextEncoder().encode(file.name);
1933
+ const dataBytes = new Uint8Array(await file.data.arrayBuffer());
1934
+ const crc = crc32(dataBytes);
1935
+ // Local file header (30 bytes + filename)
1936
+ const local = new Uint8Array(30 + nameBytes.length);
1937
+ const lv = new DataView(local.buffer);
1938
+ lv.setUint32(0, 0x04034b50, true);
1939
+ lv.setUint16(4, 20, true);
1940
+ lv.setUint16(8, 0, true);
1941
+ lv.setUint32(14, crc, true);
1942
+ lv.setUint32(18, dataBytes.length, true);
1943
+ lv.setUint32(22, dataBytes.length, true);
1944
+ lv.setUint16(26, nameBytes.length, true);
1945
+ local.set(nameBytes, 30);
1946
+ // Central directory entry (46 bytes + filename)
1947
+ const cd = new Uint8Array(46 + nameBytes.length);
1948
+ const cv = new DataView(cd.buffer);
1949
+ cv.setUint32(0, 0x02014b50, true);
1950
+ cv.setUint16(4, 20, true);
1951
+ cv.setUint16(6, 20, true);
1952
+ cv.setUint32(16, crc, true);
1953
+ cv.setUint32(20, dataBytes.length, true);
1954
+ cv.setUint32(24, dataBytes.length, true);
1955
+ cv.setUint16(28, nameBytes.length, true);
1956
+ cv.setUint32(42, offset, true);
1957
+ cd.set(nameBytes, 46);
1958
+ parts.push(local);
1959
+ parts.push(dataBytes);
1960
+ centralDir.push(cd);
1961
+ offset += local.length + dataBytes.length;
1962
+ }
1963
+ const cdOffset = offset;
1964
+ let cdSize = 0;
1965
+ for (const entry of centralDir) {
1966
+ parts.push(entry);
1967
+ cdSize += entry.length;
1968
+ }
1969
+ // End of central directory (22 bytes)
1970
+ const eocd = new Uint8Array(22);
1971
+ const ev = new DataView(eocd.buffer);
1972
+ ev.setUint32(0, 0x06054b50, true);
1973
+ ev.setUint16(8, files.length, true);
1974
+ ev.setUint16(10, files.length, true);
1975
+ ev.setUint32(12, cdSize, true);
1976
+ ev.setUint32(16, cdOffset, true);
1977
+ parts.push(eocd);
1978
+ return new Blob(parts, { type: 'application/zip' });
1979
+ }
1980
+ function crc32(data) {
1981
+ let crc = 0xffffffff;
1982
+ for (let i = 0; i < data.length; i++) {
1983
+ crc ^= data[i];
1984
+ for (let j = 0; j < 8; j++) {
1985
+ crc = (crc >>> 1) ^ (crc & 1 ? 0xedb88320 : 0);
1986
+ }
1987
+ }
1988
+ return (crc ^ 0xffffffff) >>> 0;
2512
1989
  }
2513
1990
 
2514
1991
  const LogLevel = {
@@ -4349,7 +3826,7 @@ class App {
4349
3826
  this.stopCallbacks = [];
4350
3827
  this.commitCallbacks = [];
4351
3828
  this.activityState = ActivityState.NotActive;
4352
- this.version = '17.1.5'; // TODO: version compatability check inside each plugin.
3829
+ this.version = '17.2.1'; // TODO: version compatability check inside each plugin.
4353
3830
  this.socketMode = false;
4354
3831
  this.compressionThreshold = 24 * 1000;
4355
3832
  this.bc = null;
@@ -4757,9 +4234,7 @@ class App {
4757
4234
  });
4758
4235
  this.session.attachUpdateCallback(({ userID, metadata }) => {
4759
4236
  if (userID != null) {
4760
- if (!userID ||
4761
- typeof userID !== 'string' ||
4762
- userID.trim().length === 0) {
4237
+ if (!userID || typeof userID !== 'string' || userID.trim().length === 0) {
4763
4238
  this.debug.warn('Invalid userID (must be type string), ignoring.');
4764
4239
  return;
4765
4240
  }
@@ -4946,15 +4421,21 @@ class App {
4946
4421
  else if (data.type === 'compress') {
4947
4422
  const batch = data.batch;
4948
4423
  const batchSize = batch.byteLength;
4949
- if (batchSize > this.compressionThreshold) {
4950
- gzip(data.batch, { mtime: 0 }, (err, result) => {
4951
- if (err) {
4952
- this.debug.error('Openreplay compression error:', err);
4953
- this.worker?.postMessage({ type: 'uncompressed', batch: batch });
4954
- }
4955
- else {
4956
- this.worker?.postMessage({ type: 'compressed', batch: result });
4957
- }
4424
+ const hasCompressionAPI = 'CompressionStream' in globalThis;
4425
+ if (batchSize > this.compressionThreshold && hasCompressionAPI) {
4426
+ const blob = new Blob([batch]);
4427
+ const stream = blob.stream().pipeThrough(new CompressionStream('gzip'));
4428
+ new Response(stream)
4429
+ .arrayBuffer()
4430
+ .then((compressedBuffer) => {
4431
+ this.worker?.postMessage({
4432
+ type: 'compressed',
4433
+ batch: new Uint8Array(compressedBuffer),
4434
+ });
4435
+ })
4436
+ .catch((err) => {
4437
+ this.debug.error('Openreplay compression error:', err);
4438
+ this.worker?.postMessage({ type: 'uncompressed', batch: batch });
4958
4439
  });
4959
4440
  }
4960
4441
  else {
@@ -5473,7 +4954,7 @@ class App {
5473
4954
  delay, // derived from token
5474
4955
  sessionID, // derived from token
5475
4956
  startTimestamp, // real startTS (server time), derived from sessionID
5476
- userBrowser, userCity, userCountry, userDevice, userOS, userState, canvasEnabled, canvasQuality, canvasFPS, assistOnly: socketOnly, } = await r.json();
4957
+ userBrowser, userCity, userCountry, userDevice, userOS, userState, canvasEnabled, canvasQuality, canvasFPS, framesSupport, assistOnly: socketOnly, } = await r.json();
5477
4958
  if (typeof token !== 'string' ||
5478
4959
  typeof userUUID !== 'string' ||
5479
4960
  (typeof startTimestamp !== 'number' && typeof startTimestamp !== 'undefined') ||
@@ -5546,6 +5027,7 @@ class App {
5546
5027
  isDebug: this.options.canvas.__save_canvas_locally,
5547
5028
  fixedScaling: this.options.canvas.fixedCanvasScaling,
5548
5029
  useAnimationFrame: this.options.canvas.useAnimationFrame,
5030
+ framesSupport: !!framesSupport,
5549
5031
  });
5550
5032
  }
5551
5033
  /** --------------- COLD START BUFFER ------------------*/
@@ -6657,7 +6139,7 @@ function getUniqueSiblingClass(el) {
6657
6139
  return null;
6658
6140
  }
6659
6141
 
6660
- let e=-1;const t=t=>{addEventListener("pageshow",(n=>{n.persisted&&(e=n.timeStamp,t(n));}),true);},n=(e,t,n,i)=>{let s,o;return r=>{t.value>=0&&(r||i)&&(o=t.value-(s??0),(o||void 0===s)&&(s=t.value,t.delta=o,t.rating=((e,t)=>e>t[1]?"poor":e>t[0]?"needs-improvement":"good")(t.value,n),e(t)));}},i=e=>{requestAnimationFrame((()=>requestAnimationFrame((()=>e()))));},s=()=>{const e=performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},o=()=>{const e=s();return e?.activationStart??0},r=(t,n=-1)=>{const i=s();let r="navigate";e>=0?r="back-forward-cache":i&&(document.prerendering||o()>0?r="prerender":document.wasDiscarded?r="restore":i.type&&(r=i.type.replace(/_/g,"-")));return {name:t,value:n,rating:"good",delta:0,entries:[],id:`v5-${Date.now()}-${Math.floor(8999999999999*Math.random())+1e12}`,navigationType:r}},c=new WeakMap;function a(e,t){return c.get(e)||c.set(e,new t),c.get(e)}class d{t;i=0;o=[];h(e){if(e.hadRecentInput)return;const t=this.o[0],n=this.o.at(-1);this.i&&t&&n&&e.startTime-n.startTime<1e3&&e.startTime-t.startTime<5e3?(this.i+=e.value,this.o.push(e)):(this.i=e.value,this.o=[e]),this.t?.(e);}}const h=(e,t,n={})=>{try{if(PerformanceObserver.supportedEntryTypes.includes(e)){const i=new PerformanceObserver((e=>{Promise.resolve().then((()=>{t(e.getEntries());}));}));return i.observe({type:e,buffered:!0,...n}),i}}catch{}},f=e=>{let t=false;return ()=>{t||(e(),t=true);}};let u=-1;const l=new Set,m=()=>"hidden"!==document.visibilityState||document.prerendering?1/0:0,p=e=>{if("hidden"===document.visibilityState){if("visibilitychange"===e.type)for(const e of l)e();isFinite(u)||(u="visibilitychange"===e.type?e.timeStamp:0,removeEventListener("prerenderingchange",p,true));}},v=()=>{if(u<0){const e=o(),n=document.prerendering?void 0:globalThis.performance.getEntriesByType("visibility-state").filter((t=>"hidden"===t.name&&t.startTime>e))[0]?.startTime;u=n??m(),addEventListener("visibilitychange",p,true),addEventListener("prerenderingchange",p,true),t((()=>{setTimeout((()=>{u=m();}));}));}return {get firstHiddenTime(){return u},onHidden(e){l.add(e);}}},g=e=>{document.prerendering?addEventListener("prerenderingchange",(()=>e()),true):e();},y=[1800,3e3],E=(e,s={})=>{g((()=>{const c=v();let a,d=r("FCP");const f=h("paint",(e=>{for(const t of e)"first-contentful-paint"===t.name&&(f.disconnect(),t.startTime<c.firstHiddenTime&&(d.value=Math.max(t.startTime-o(),0),d.entries.push(t),a(true)));}));f&&(a=n(e,d,y,s.reportAllChanges),t((t=>{d=r("FCP"),a=n(e,d,y,s.reportAllChanges),i((()=>{d.value=performance.now()-t.timeStamp,a(true);}));})));}));},b=[.1,.25],L=(e,s={})=>{const o=v();E(f((()=>{let c,f=r("CLS",0);const u=a(s,d),l=e=>{for(const t of e)u.h(t);u.i>f.value&&(f.value=u.i,f.entries=u.o,c());},m=h("layout-shift",l);m&&(c=n(e,f,b,s.reportAllChanges),o.onHidden((()=>{l(m.takeRecords()),c(true);})),t((()=>{u.i=0,f=r("CLS",0),c=n(e,f,b,s.reportAllChanges),i((()=>c()));})),setTimeout(c));})));};let P=0,T=1/0,_=0;const M=e=>{for(const t of e)t.interactionId&&(T=Math.min(T,t.interactionId),_=Math.max(_,t.interactionId),P=_?(_-T)/7+1:0);};let w;const C=()=>w?P:performance.interactionCount??0,I=()=>{"interactionCount"in performance||w||(w=h("event",M,{type:"event",buffered:true,durationThreshold:0}));};let F=0;class k{u=[];l=new Map;m;p;v(){F=C(),this.u.length=0,this.l.clear();}L(){const e=Math.min(this.u.length-1,Math.floor((C()-F)/50));return this.u[e]}h(e){if(this.m?.(e),!e.interactionId&&"first-input"!==e.entryType)return;const t=this.u.at(-1);let n=this.l.get(e.interactionId);if(n||this.u.length<10||e.duration>t.P){if(n?e.duration>n.P?(n.entries=[e],n.P=e.duration):e.duration===n.P&&e.startTime===n.entries[0].startTime&&n.entries.push(e):(n={id:e.interactionId,entries:[e],P:e.duration},this.l.set(n.id,n),this.u.push(n)),this.u.sort(((e,t)=>t.P-e.P)),this.u.length>10){const e=this.u.splice(10);for(const t of e)this.l.delete(t.id);}this.p?.(n);}}}const A=e=>{const t=globalThis.requestIdleCallback||setTimeout;"hidden"===document.visibilityState?e():(e=f(e),addEventListener("visibilitychange",e,{once:true,capture:true}),t((()=>{e(),removeEventListener("visibilitychange",e,{capture:true});})));},B=[200,500],S=(e,i={})=>{if(!globalThis.PerformanceEventTiming||!("interactionId"in PerformanceEventTiming.prototype))return;const s=v();g((()=>{I();let o,c=r("INP");const d=a(i,k),f=e=>{A((()=>{for(const t of e)d.h(t);const t=d.L();t&&t.P!==c.value&&(c.value=t.P,c.entries=t.entries,o());}));},u=h("event",f,{durationThreshold:i.durationThreshold??40});o=n(e,c,B,i.reportAllChanges),u&&(u.observe({type:"first-input",buffered:true}),s.onHidden((()=>{f(u.takeRecords()),o(true);})),t((()=>{d.v(),c=r("INP"),o=n(e,c,B,i.reportAllChanges);})));}));};class N{m;h(e){this.m?.(e);}}const q=[2500,4e3],x=(e,s={})=>{g((()=>{const c=v();let d,u=r("LCP");const l=a(s,N),m=e=>{s.reportAllChanges||(e=e.slice(-1));for(const t of e)l.h(t),t.startTime<c.firstHiddenTime&&(u.value=Math.max(t.startTime-o(),0),u.entries=[t],d());},p=h("largest-contentful-paint",m);if(p){d=n(e,u,q,s.reportAllChanges);const o=f((()=>{m(p.takeRecords()),p.disconnect(),d(true);})),c=e=>{e.isTrusted&&(A(o),removeEventListener(e.type,c,{capture:true}));};for(const e of ["keydown","click","visibilitychange"])addEventListener(e,c,{capture:true});t((t=>{u=r("LCP"),d=n(e,u,q,s.reportAllChanges),i((()=>{u.value=performance.now()-t.timeStamp,d(true);}));}));}}));},H=[800,1800],O=e=>{document.prerendering?g((()=>O(e))):"complete"!==document.readyState?addEventListener("load",(()=>O(e)),true):setTimeout(e);},$=(e,i={})=>{let c=r("TTFB"),a=n(e,c,H,i.reportAllChanges);O((()=>{const d=s();d&&(c.value=Math.max(d.responseStart-o(),0),c.entries=[d],a(true),t((()=>{c=r("TTFB",0),a=n(e,c,H,i.reportAllChanges),a(true);})));}));};
6142
+ var e,o=-1,a=function(e){addEventListener("pageshow",(function(n){n.persisted&&(o=n.timeStamp,e(n));}),true);},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType("navigation")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r="navigate";o>=0?r="back-forward-cache":t&&(document.prerendering||u()>0?r="prerender":document.wasDiscarded?r="restore":t.type&&(r=t.type.replace(/_/g,"-")));return {name:e,value:void 0===n?-1:n,rating:"good",delta:0,entries:[],id:"v4-".concat(Date.now(),"-").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries());}));}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?"poor":e>n[0]?"needs-improvement":"good"}(n.value,t),e(n));}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}));},p=function(e){document.addEventListener("visibilitychange",(function(){"hidden"===document.visibilityState&&e();}));},v=function(e){var n=false;return function(){n||(e(),n=true);}},m=-1,h=function(){return "hidden"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){"hidden"===document.visibilityState&&m>-1&&(m="visibilitychange"===e.type?e.timeStamp:0,T());},y=function(){addEventListener("visibilitychange",g,true),addEventListener("prerenderingchange",g,true);},T=function(){removeEventListener("visibilitychange",g,true),removeEventListener("prerenderingchange",g,true);},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y();}),0);}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener("prerenderingchange",(function(){return e()}),true):e();},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("FCP"),o=s("paint",(function(e){e.forEach((function(e){"first-contentful-paint"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(true)));}));}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f("FCP"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(true);}));})));}));},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f("CLS",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e]);}})),i>r.value&&(r.value=i,r.entries=o,t());},u=s("layout-shift",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(true);})),a((function(){i=0,r=f("CLS",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}));})),setTimeout(t,0));})));},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0);}));},k=function(){return e?A:performance.interactionCount||0},F=function(){"interactionCount"in performance||e||(e=s("event",M,{type:"event",buffered:true,durationThreshold:0}));},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||"first-input"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else {var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r);}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}));}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),"hidden"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){"PerformanceEventTiming"in self&&"interactionId"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f("INP"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r());}));},c=s("event",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:"first-input",buffered:true}),p((function(){o(c.takeRecords()),r(true);})),a((function(){R=k(),D.length=0,x.clear(),i=f("INP"),r=d(e,i,N,n.reportAllChanges);})));})));},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f("LCP"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t());}));},c=s("largest-contentful-paint",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=true,t(true));}));["keydown","click"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:true,capture:true});})),p(m),a((function(r){i=f("LCP"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=true,t(true);}));}));}}));},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):"complete"!==document.readyState?addEventListener("load",(function(){return e(n)}),true):setTimeout(n,0);},Q=function(e,n){n=n||{};var t=f("TTFB"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(true),a((function(){t=f("TTFB",0),(r=d(e,t,J,n.reportAllChanges))(true);})));}));};
6661
6143
 
6662
6144
  function getPaintBlocks(resources) {
6663
6145
  const paintBlocks = [];
@@ -6790,10 +6272,10 @@ function Timing (app, opts) {
6790
6272
  // onINP(): Chromium
6791
6273
  // onLCP(): Chromium, Firefox
6792
6274
  // onTTFB(): Chromium, Firefox, Safari
6793
- L(onVitalsSignal);
6794
- S(onVitalsSignal);
6795
- x(onVitalsSignal);
6796
- $(onVitalsSignal);
6275
+ w(onVitalsSignal);
6276
+ j(onVitalsSignal);
6277
+ G(onVitalsSignal);
6278
+ Q(onVitalsSignal);
6797
6279
  });
6798
6280
  app.attachStopCallback(function () {
6799
6281
  observer.disconnect();
@@ -7594,9 +7076,7 @@ class NetworkMessage {
7594
7076
  });
7595
7077
  if (!messageInfo)
7596
7078
  return null;
7597
- const gqlHeader = "application/graphql-response";
7598
- const isGraphql = messageInfo.url.includes("/graphql")
7599
- || Object.values(messageInfo.request.headers).some(v => v.includes(gqlHeader));
7079
+ const isGraphql = messageInfo.url.includes("/graphql");
7600
7080
  if (isGraphql && messageInfo.response.body && typeof messageInfo.response.body === 'string') {
7601
7081
  const isError = messageInfo.response.body.includes("errors");
7602
7082
  messageInfo.status = isError ? 400 : 200;
@@ -7902,7 +7382,6 @@ class FetchProxyHandler {
7902
7382
  this.tokenUrlMatcher = tokenUrlMatcher;
7903
7383
  }
7904
7384
  apply(target, _, argsList) {
7905
- var _a;
7906
7385
  const input = argsList[0];
7907
7386
  const init = argsList[1];
7908
7387
  if (!input ||
@@ -7918,31 +7397,6 @@ class FetchProxyHandler {
7918
7397
  }
7919
7398
  const item = new NetworkMessage(this.ignoredHeaders, this.setSessionTokenHeader, this.sanitize);
7920
7399
  this.beforeFetch(item, input, init);
7921
- const signal = (argsList[0] instanceof Request ? argsList[0].signal : undefined) ||
7922
- ((_a = argsList[1]) === null || _a === void 0 ? void 0 : _a.signal);
7923
- // guard to avoid double-send
7924
- let abortedNotified = false;
7925
- const notifyAbort = () => {
7926
- if (abortedNotified)
7927
- return;
7928
- abortedNotified = true;
7929
- item.endTime = performance.now();
7930
- item.duration = item.endTime - (item.startTime || item.endTime);
7931
- item.status = 0;
7932
- item.statusText = "Aborted";
7933
- item.readyState = 0;
7934
- const msg = item.getMessage();
7935
- if (msg)
7936
- this.sendMessage(msg);
7937
- };
7938
- if (signal) {
7939
- if (signal.aborted) {
7940
- notifyAbort();
7941
- }
7942
- else {
7943
- signal.addEventListener("abort", notifyAbort, { once: true });
7944
- }
7945
- }
7946
7400
  this.setSessionTokenHeader((name, value) => {
7947
7401
  if (this.tokenUrlMatcher !== undefined) {
7948
7402
  if (!this.tokenUrlMatcher(item.url)) {
@@ -7971,22 +7425,11 @@ class FetchProxyHandler {
7971
7425
  }
7972
7426
  });
7973
7427
  return target.apply(window, argsList)
7974
- .then(this.afterFetch(item, () => {
7975
- abortedNotified = true;
7976
- }))
7428
+ .then(this.afterFetch(item))
7977
7429
  .catch((e) => {
7430
+ // mock finally
7978
7431
  item.endTime = performance.now();
7979
7432
  item.duration = item.endTime - (item.startTime || item.endTime);
7980
- if (e && e.name === "AbortError") {
7981
- item.status = 0;
7982
- item.statusText = "Aborted";
7983
- item.readyState = 0;
7984
- if (!abortedNotified) {
7985
- const msg = item.getMessage();
7986
- if (msg)
7987
- this.sendMessage(msg);
7988
- }
7989
- }
7990
7433
  throw e;
7991
7434
  });
7992
7435
  }
@@ -8038,10 +7481,8 @@ class FetchProxyHandler {
8038
7481
  item.requestData = genStringBody(init.body);
8039
7482
  }
8040
7483
  }
8041
- afterFetch(item, onResolved) {
7484
+ afterFetch(item) {
8042
7485
  return (resp) => {
8043
- if (onResolved)
8044
- onResolved === null || onResolved === void 0 ? void 0 : onResolved();
8045
7486
  item.endTime = performance.now();
8046
7487
  item.duration = item.endTime - (item.startTime || item.endTime);
8047
7488
  item.status = resp.status;
@@ -8077,15 +7518,7 @@ class FetchProxyHandler {
8077
7518
  }
8078
7519
  })
8079
7520
  .catch((e) => {
8080
- if (e.name === "AbortError") {
8081
- item.status = 0;
8082
- item.statusText = "Aborted";
8083
- item.readyState = 0;
8084
- const msg = item.getMessage();
8085
- if (msg)
8086
- this.sendMessage(msg);
8087
- }
8088
- else {
7521
+ if (e.name !== "AbortError") {
8089
7522
  throw e;
8090
7523
  }
8091
7524
  });
@@ -9186,7 +8619,7 @@ class ConstantProperties {
9186
8619
  user_id: this.user_id,
9187
8620
  distinct_id: this.deviceId,
9188
8621
  sdk_edition: 'web',
9189
- sdk_version: '17.1.5',
8622
+ sdk_version: '17.2.1',
9190
8623
  timezone: getUTCOffsetString(),
9191
8624
  search_engine: this.searchEngine,
9192
8625
  };
@@ -9628,7 +9061,7 @@ class Batcher {
9628
9061
  body: JSON.stringify(sentBatch),
9629
9062
  })
9630
9063
  .then((response) => {
9631
- if (response.status === 403) {
9064
+ if ([403, 401].includes(response.status)) {
9632
9065
  this.init().then(() => {
9633
9066
  send();
9634
9067
  });
@@ -9830,7 +9263,7 @@ class API {
9830
9263
  this.signalStartIssue = (reason, missingApi) => {
9831
9264
  const doNotTrack = this.checkDoNotTrack();
9832
9265
  console.log("Tracker couldn't start due to:", JSON.stringify({
9833
- trackerVersion: '17.1.5',
9266
+ trackerVersion: '17.2.1',
9834
9267
  projectKey: this.options.projectKey,
9835
9268
  doNotTrack,
9836
9269
  reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,