From 55acae40fd20c056e3bb2e80ccb1363169ce982e Mon Sep 17 00:00:00 2001 From: Andrey Lushnikov Date: Tue, 18 Jul 2017 20:53:00 -0700 Subject: [PATCH] Introduce DEBUG module which traces public API calls This patch improves on DEBUG module to trace all puppeteer's public API calls. References #89. --- CONTRIBUTING.md | 5 +++++ lib/Browser.js | 2 ++ lib/Dialog.js | 3 +++ lib/FrameManager.js | 1 + lib/Keyboard.js | 3 +++ lib/NetworkManager.js | 6 +++++- lib/Page.js | 1 + lib/helper.js | 35 +++++++++++++++++++++++++++++++++++ 8 files changed, 55 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 70ab772faad..73ff3bdc490 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,3 +65,8 @@ browser.newPage().then(async page => { browser.close(); }); ``` + +Tips-n-tricks: +- `DEBUG=*,-*:protocol node script.js` - dump everything BUT protocol messages +- `DEBUG=*:page node script.js` - dump only Page's API calls +- `DEBUG=*:mouse,*:keyboard node script.js` - dump only Mouse and Keyboard API calls \ No newline at end of file diff --git a/lib/Browser.js b/lib/Browser.js index 8dd074a33f1..cc234312934 100644 --- a/lib/Browser.js +++ b/lib/Browser.js @@ -16,6 +16,7 @@ let {Duplex} = require('stream'); let path = require('path'); +let helper = require('./helper'); let removeRecursive = require('rimraf').sync; let Page = require('./Page'); let childProcess = require('child_process'); @@ -139,6 +140,7 @@ class Browser { } module.exports = Browser; +helper.tracePublicAPI(Browser); function waitForRemoteDebuggingPort(chromeProcess) { const rl = readline.createInterface({ input: chromeProcess.stderr }); diff --git a/lib/Dialog.js b/lib/Dialog.js index af2cbf34d15..0c14e4ac68b 100644 --- a/lib/Dialog.js +++ b/lib/Dialog.js @@ -14,6 +14,8 @@ * limitations under the License. */ +const helper = require('./helper'); + class Dialog { /** * @param {!Connection} client @@ -67,3 +69,4 @@ Dialog.Type = { }; module.exports = Dialog; +helper.tracePublicAPI(Dialog); diff --git a/lib/FrameManager.js b/lib/FrameManager.js index adf5f556760..c15521685e8 100644 --- a/lib/FrameManager.js +++ b/lib/FrameManager.js @@ -358,5 +358,6 @@ class Frame { this._parentFrame = null; } } +helper.tracePublicAPI(Frame); module.exports = FrameManager; diff --git a/lib/Keyboard.js b/lib/Keyboard.js index 8b17b5dd07a..c12f460af0f 100644 --- a/lib/Keyboard.js +++ b/lib/Keyboard.js @@ -14,6 +14,8 @@ * limitations under the License. */ +const helper = require('./helper'); + class Keyboard { /** * @param {!Connection} client @@ -236,3 +238,4 @@ function codeForKey(key) { } module.exports = Keyboard; +helper.tracePublicAPI(Keyboard); diff --git a/lib/NetworkManager.js b/lib/NetworkManager.js index 42e93db99fb..d9bf810641c 100644 --- a/lib/NetworkManager.js +++ b/lib/NetworkManager.js @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -let EventEmitter = require('events'); +const EventEmitter = require('events'); +const helper = require('./helper'); class NetworkManager extends EventEmitter { /** @@ -280,6 +281,7 @@ class Body { return content.buffer; } } +helper.tracePublicAPI(Body); class Request extends Body { /** @@ -300,6 +302,7 @@ class Request extends Body { return this._response; } } +helper.tracePublicAPI(Request); class Response extends Body { /** @@ -324,6 +327,7 @@ class Response extends Body { return this._request; } } +helper.tracePublicAPI(Response); class InterceptedRequest { /** diff --git a/lib/Page.js b/lib/Page.js index fce6eb860a4..b26527936b6 100644 --- a/lib/Page.js +++ b/lib/Page.js @@ -721,3 +721,4 @@ Page.Events = { Page.Viewport; module.exports = Page; +helper.tracePublicAPI(Page); diff --git a/lib/helper.js b/lib/helper.js index 11a455d2cc8..7b8de5156e9 100644 --- a/lib/helper.js +++ b/lib/helper.js @@ -91,6 +91,41 @@ class Helper { }); } } + + /** + * @param {!Object} classType + */ + static tracePublicAPI(classType) { + let className = classType.prototype.constructor.name; + className = className.substring(0, 1).toLowerCase() + className.substring(1); + const debug = require('debug')(`puppeteer:${className}`); + if (!debug.enabled) + return; + for (let methodName of Reflect.ownKeys(classType.prototype)) { + const method = Reflect.get(classType.prototype, methodName); + if (methodName === 'constructor' || methodName.startsWith('_') || typeof method !== 'function') + continue; + Reflect.set(classType.prototype, methodName, function(...args) { + let argsText = args.map(stringifyArgument).join(', '); + let callsite = `${className}.${methodName}(${argsText})`; + debug(callsite); + return method.call(this, ...args); + }); + } + + /** + * @param {!Object} arg + * @return {string} + */ + function stringifyArgument(arg) { + if (typeof arg !== 'function') + return JSON.stringify(arg); + let text = arg.toString().split('\n').map(line => line.trim()).join(''); + if (text.length > 20) + text = text.substring(0, 20) + '…'; + return `"${text}"`; + } + } } module.exports = Helper;