// Flags: --expose-internals 'use strict'; const common = require('../common'); common.skipIfInspectorDisabled(); const assert = require('assert'); const { EventEmitter } = require('events'); const { waitForDebugger, } = require('internal/debugger/inspect_helpers'); function assertListenersRemoved(client) { assert.strictEqual( client.listenerCount('NodeRuntime.waitingForDebugger'), 0, ); assert.strictEqual(client.listenerCount('close'), 0); } async function testWaitingNotification(beforeEnableReply) { const client = new EventEmitter(); const calls = []; client.callMethod = common.mustCall(async (method) => { calls.push(method); const emitWaiting = () => { client.emit('NodeRuntime.waitingForDebugger'); }; if (method === 'NodeRuntime.enable') { if (beforeEnableReply) { emitWaiting(); } else { setImmediate(emitWaiting); } } else { assert.strictEqual(method, 'NodeRuntime.disable'); } }, 2); await waitForDebugger(client); assert.deepStrictEqual(calls, [ 'NodeRuntime.enable', 'NodeRuntime.disable', ]); assertListenersRemoved(client); } async function testCloseWhileWaiting(beforeEnableReply) { const client = new EventEmitter(); client.callMethod = common.mustCall((method) => { assert.strictEqual(method, 'NodeRuntime.enable'); setImmediate(() => client.emit('close')); return beforeEnableReply ? new Promise(() => {}) : Promise.resolve(); }); await assert.rejects( waitForDebugger(client), { code: 'ERR_DEBUGGER_ERROR', message: 'Debugger session ended while waiting for target startup', }, ); assertListenersRemoved(client); } async function testCloseWhileDisabling() { const client = new EventEmitter(); client.callMethod = common.mustCall((method) => { if (method === 'NodeRuntime.enable') { client.emit('NodeRuntime.waitingForDebugger'); return Promise.resolve(); } assert.strictEqual(method, 'NodeRuntime.disable'); setImmediate(() => client.emit('close')); return new Promise(() => {}); }, 2); await assert.rejects( waitForDebugger(client), { code: 'ERR_DEBUGGER_ERROR', message: 'Debugger session ended while waiting for target startup', }, ); assertListenersRemoved(client); } async function testEnableFailure() { const client = new EventEmitter(); const expected = new Error('NodeRuntime.enable failed'); client.callMethod = common.mustCall(async (method) => { assert.strictEqual(method, 'NodeRuntime.enable'); throw expected; }); await assert.rejects( waitForDebugger(client), (error) => { assert.strictEqual(error, expected); return true; }, ); assertListenersRemoved(client); } async function testDisableFailure() { const client = new EventEmitter(); const expected = new Error('NodeRuntime.disable failed'); client.callMethod = common.mustCall(async (method) => { if (method === 'NodeRuntime.enable') { client.emit('NodeRuntime.waitingForDebugger'); return; } assert.strictEqual(method, 'NodeRuntime.disable'); throw expected; }, 2); await assert.rejects( waitForDebugger(client), (error) => { assert.strictEqual(error, expected); return true; }, ); assertListenersRemoved(client); } (async () => { await testWaitingNotification(true); await testWaitingNotification(false); await testCloseWhileWaiting(true); await testCloseWhileWaiting(false); await testCloseWhileDisabling(); await testEnableFailure(); await testDisableFailure(); })().then(common.mustCall());