1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
// Daemon diagnostic traces (WA_CLI_TRACE=1 or "trace": true in config.json).
// Logs: CDP/evaluate calls still pending after >15 s, exceptions inside functions exposed
// to the page (puppeteer swallows them), navigations and client events.
// Useful to see where whatsapp-web.js hangs when it never reaches `ready`.
import { createRequire } from 'node:module';
const require = createRequire(import.meta.url);
const QUIET = new Set(['loading_screen', 'message', 'message_create', 'message_ack', 'unread_count', 'media_uploaded']);
export function enableTrace(log) {
const { CdpPage } = require('puppeteer-core/lib/cjs/puppeteer/cdp/Page.js');
const { CdpCDPSession } = require('puppeteer-core/lib/cjs/puppeteer/cdp/CdpSession.js');
const wweb = require('whatsapp-web.js');
const t = (...a) => log('trace:', ...a);
const pending = new Map();
let seq = 0;
const track = (desc, p) => {
const id = ++seq;
pending.set(id, { desc, start: Date.now() });
const done = () => pending.delete(id);
p.then(done, (e) => {
done();
t('error', desc, String(e?.message ?? e).slice(0, 200));
});
return p;
};
setInterval(() => {
for (const p of pending.values()) {
const s = Math.round((Date.now() - p.start) / 1000);
if (s >= 15 && s % 15 === 0) t(`pendiente ${s}s:`, p.desc);
}
}, 1000).unref();
const send = CdpCDPSession.prototype.send;
CdpCDPSession.prototype.send = function (method, ...args) {
return track(`cdp ${method}`, send.call(this, method, ...args));
};
const expose = CdpPage.prototype.exposeFunction;
CdpPage.prototype.exposeFunction = function (name, fn) {
const wrapped = async (...args) => {
try {
return await fn(...args);
} catch (e) {
t(`exception in ${name}:`, String(e?.stack ?? e).split('\n').slice(0, 4).join(' | '));
throw e;
}
};
return track(`exposeFunction(${name})`, expose.call(this, name, wrapped));
};
const emit = wweb.Client.prototype.emit;
wweb.Client.prototype.emit = function (event, ...args) {
if (!QUIET.has(event)) t('evento', event, event === 'disconnected' || event === 'change_state' ? args[0] : '');
return emit.call(this, event, ...args);
};
const init = wweb.Client.prototype.initialize;
wweb.Client.prototype.initialize = function (...args) {
const iv = setInterval(() => {
if (!this.pupPage) return;
clearInterval(iv);
const page = this.pupPage;
page.on('framenavigated', (f) => t('framenavigated', f === page.mainFrame() ? 'main' : 'iframe', f.url().slice(0, 60)));
page.on('load', () => t('load'));
page.on('pageerror', (e) => t('pageerror', String(e?.message ?? e).slice(0, 150)));
}, 20);
return init.apply(this, args);
};
const inject = wweb.Client.prototype.inject;
wweb.Client.prototype.inject = function (...args) {
t('inject()');
return track('inject()', inject.apply(this, args));
};
if (inject.waCompat) wweb.Client.prototype.inject.waCompat = true;
}
|