@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 +277 -844
- package/dist/cjs/entry.js.map +1 -1
- package/dist/cjs/index.js +277 -844
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/main/app/canvas.d.ts +11 -0
- package/dist/lib/entry.js +277 -844
- package/dist/lib/entry.js.map +1 -1
- package/dist/lib/index.js +277 -844
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/main/app/canvas.d.ts +11 -0
- package/dist/types/main/app/canvas.d.ts +11 -0
- package/package.json +11 -12
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 ||
|
|
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 (
|
|
2353
|
-
|
|
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
|
-
|
|
2368
|
-
|
|
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 (
|
|
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
|
|
2402
|
-
|
|
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
|
-
|
|
1704
|
+
this.cleanupCanvas(id);
|
|
2406
1705
|
return;
|
|
2407
1706
|
}
|
|
2408
|
-
if (!
|
|
2409
|
-
this.app.debug.log('Canvas element not in sync',
|
|
2410
|
-
|
|
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
|
-
|
|
2414
|
-
if (
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
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.
|
|
1723
|
+
this.intervals.set(id, int);
|
|
2427
1724
|
};
|
|
2428
|
-
this.fileExt =
|
|
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
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
|
|
2445
|
-
|
|
2446
|
-
|
|
2447
|
-
|
|
2448
|
-
|
|
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
|
-
|
|
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
|
|
2504
|
-
const
|
|
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 =
|
|
2507
|
-
link.download =
|
|
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
|
|
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
|
-
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
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
|
-
|
|
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
|
-
|
|
6794
|
-
|
|
6795
|
-
|
|
6796
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
9266
|
+
trackerVersion: '17.2.1',
|
|
9834
9267
|
projectKey: this.options.projectKey,
|
|
9835
9268
|
doNotTrack,
|
|
9836
9269
|
reason: missingApi.length ? `missing api: ${missingApi.join(',')}` : reason,
|