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