From b1947d245524188d3848b48758b611113fc64b0c Mon Sep 17 00:00:00 2001 From: Erick Wendel Date: Tue, 16 Aug 2022 12:19:27 -0300 Subject: [PATCH] inspector: add promisified result for session.post --- doc/api/inspector.md | 10 +++ lib/inspector.js | 20 +++++- ...test-inspector-session-post-promisified.js | 61 +++++++++++++++++++ 3 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 test/parallel/test-inspector-session-post-promisified.js diff --git a/doc/api/inspector.md b/doc/api/inspector.md index c0ab1ed1ce08f1..650c7c3ed87e49 100644 --- a/doc/api/inspector.md +++ b/doc/api/inspector.md @@ -183,15 +183,25 @@ changes: * `method` {string} * `params` {Object} * `callback` {Function} +* Returns: {Promise|undefined} Posts a message to the inspector back-end. `callback` will be notified when a response is received. `callback` is a function that accepts two optional arguments: error and message-specific result. +If the `callback` is not passed, then it'll return a Promise result. + ```js session.post('Runtime.evaluate', { expression: '2 + 2' }, (error, { result }) => console.log(result)); // Output: { type: 'number', value: 4, description: '4' } + +// or for promise +session.post('Runtime.evaluate', { expression: '2 + 2' }) + .then((result) => console.log(result)) + .catch((error) => console.error(error)); + +// Output: { type: 'number', value: 4, description: '4' } ``` The latest version of the V8 inspector protocol is published on the diff --git a/lib/inspector.js b/lib/inspector.js index 5ffb2d9d6658e0..440d399b2f5995 100644 --- a/lib/inspector.js +++ b/lib/inspector.js @@ -22,6 +22,7 @@ const { hasInspector } = internalBinding('config'); if (!hasInspector) throw new ERR_INSPECTOR_NOT_AVAILABLE(); +const { promisify } = require('util'); const EventEmitter = require('events'); const { queueMicrotask } = require('internal/process/task_queues'); const { @@ -108,7 +109,7 @@ class Session extends EventEmitter { * @param {string} method * @param {Record} [params] * @param {Function} [callback] - * @returns {void} + * @returns {void | Promise} */ post(method, params, callback) { validateString(method, 'method'); @@ -128,13 +129,26 @@ class Session extends EventEmitter { } const id = this[nextIdSymbol]++; const message = { id, method }; + const configureCbAndDispatch = (cb) => { + this[messageCallbacksSymbol].set(id, cb); + this[connectionSymbol].dispatch(JSONStringify(message)); + }; + if (params) { message.params = params; } if (callback) { - this[messageCallbacksSymbol].set(id, callback); + configureCbAndDispatch(callback); + return; } - this[connectionSymbol].dispatch(JSONStringify(message)); + + const event = new EventEmitter(); + const kOnFinish = Symbol('kOnFinish'); + const promisifiedResult = promisify(event.once.bind(event))(kOnFinish); + const cb = (err, res) => event.emit(kOnFinish, err, res); + configureCbAndDispatch(cb); + + return promisifiedResult; } /** diff --git a/test/parallel/test-inspector-session-post-promisified.js b/test/parallel/test-inspector-session-post-promisified.js new file mode 100644 index 00000000000000..9be7304ca797d6 --- /dev/null +++ b/test/parallel/test-inspector-session-post-promisified.js @@ -0,0 +1,61 @@ +'use strict'; + +const common = require('../common'); +common.skipIfInspectorDisabled(); + +const assert = require('assert'); +const { + Session +} = require('inspector'); +const { + basename +} = require('path'); +const currentFilename = basename(__filename); + +{ + // Ensure that given a callback to session.post it won't return a promise result + const session = new Session(); + session.connect(); + + const postResult = session.post('Profiler.enable', () => { + session.post('Profiler.start', () => { + session.post('Profiler.stop', (err, { profile }) => { + + const { callFrame: { url } } = profile.nodes.find(({ + callFrame + }) => callFrame.url.includes(currentFilename)); + session.disconnect(); + assert.deepStrictEqual(basename(url), currentFilename); + }); + }); + }); + + assert.strictEqual(postResult, undefined); +} + +(async () => { + { + // Ensure that session.post returns a valid promisified result + const session = new Session(); + session.connect(); + + await session.post('Profiler.enable'); + await session.post('Profiler.start'); + + const { + profile + } = await session.post('Profiler.stop'); + + const { + callFrame: { + url + } + } = profile.nodes.find(({ + callFrame + }) => { + return callFrame.url.includes(currentFilename); + }); + session.disconnect(); + assert.deepStrictEqual(basename(url), currentFilename); + } +})().then(common.mustCall());