From 401acd7721ff6edd06740e95432695fee09dae9b Mon Sep 17 00:00:00 2001 From: Godfrey Chan Date: Wed, 18 Dec 2019 07:12:08 -0800 Subject: [PATCH] Update `inspectNode` implementation (#1105) A while ago we discovered the reason this dance was needed, so we documented the reason and simplified the implementation a little bit while we are at it. --- app/adapters/web-extension.js | 9 ++++-- app/routes/component-tree.js | 4 +-- ember_debug/adapters/basic.js | 12 ++++---- ember_debug/adapters/web-extension.js | 43 +++++++++++++++++---------- ember_debug/view-debug.js | 2 +- 5 files changed, 42 insertions(+), 28 deletions(-) diff --git a/app/adapters/web-extension.js b/app/adapters/web-extension.js index 2d341556eb..e7db10a6b1 100644 --- a/app/adapters/web-extension.js +++ b/app/adapters/web-extension.js @@ -80,10 +80,13 @@ export default BasicAdapter.extend({ * Open the devtools "Elements" tab and select a specific DOM node. * * @method inspectDOMNode - * @param {String} selector XPath selector + * @param {String} name */ - inspectDOMNode(selector) { - chrome.devtools.inspectedWindow.eval(`inspect($x('${selector}')[0])`); + inspectDOMNode(name) { + chrome.devtools.inspectedWindow.eval(` + inspect(window[${JSON.stringify(name)}]); + delete window[${JSON.stringify(name)}]; + `); }, /** diff --git a/app/routes/component-tree.js b/app/routes/component-tree.js index a0d54e67b4..e5e885fe06 100644 --- a/app/routes/component-tree.js +++ b/app/routes/component-tree.js @@ -58,8 +58,8 @@ export default TabRoute.extend({ this.set('controller.inspectingViews', false); }, - inspectDOMNode({ selector }) { - this.get('port.adapter').inspectDOMNode(selector); + inspectDOMNode({ name }) { + this.port.adapter.inspectDOMNode(name); }, actions: { diff --git a/ember_debug/adapters/basic.js b/ember_debug/adapters/basic.js index ff6319561e..fd121039cc 100644 --- a/ember_debug/adapters/basic.js +++ b/ember_debug/adapters/basic.js @@ -60,17 +60,17 @@ export default EmberObject.extend({ }, /** - Inspect a specific element. This usually + Inspect a specific DOM node. This usually means using the current environment's tools - to inspect the element in the DOM. + to inspect the node in the DOM. - For example, in chrome, `inspect(elem)` + For example, in chrome, `inspect(node)` will open the Elements tab in dev tools - and highlight the element. + and highlight the DOM node. - @param {DOM Element} elem + @param {Node} node */ - inspectElement(/* elem */) {}, + inspectNode(/* node */) {}, _messageReceived(message) { this._messageCallbacks.forEach(callback => { diff --git a/ember_debug/adapters/web-extension.js b/ember_debug/adapters/web-extension.js index bbbe8bd362..08620da9fc 100644 --- a/ember_debug/adapters/web-extension.js +++ b/ember_debug/adapters/web-extension.js @@ -32,24 +32,35 @@ export default BasicAdapter.extend({ }, /** - * Open the devtools "Elements" and select an element. + * Open the devtools "Elements" and select an DOM node. * - * NOTE: - * This method was supposed to call `inspect` which is a Chrome specific function - * that can either be called from the console or from code evaled using `inspectedWindow.eval` - * (which is how this code is executed). See https://developer.chrome.com/extensions/devtools#evaluating-js. - * However for some reason Chrome 52+ has started throwing an Error that `inspect` - * is not a function when called from this code. The current workaround is to - * message the Ember Ibspector asking it to execute `inspected.Window.eval('inspect(element)')` - * for us. - * - * @param {HTMLElement} elem The element to select + * @param {Node} node The DOM node to select */ - inspectElement(elem) { - /* inspect(elem); */ - this.get('namespace.port').send('view:inspectDOMNode', { - selector: `//*[@id="${elem.getAttribute('id')}"]` - }); + inspectNode(node) { + // NOTE: + // + // Basically, we are just trying to call `inspect(node)` here. + // However, `inspect` is a special function that is in the global + // scope but not on the global object (i.e. `window.inspect`) does + // not work. This sometimes causes problems, because, e.g. if the + // page has a div with the ID `inspect`, `window.inspect` will point + // to that div and shadown the "global" inspect function with no way + // to get it back. That causes "`inspect` is not a function" errors. + // + // As it turns out, however, when the extension page evals, the + // `inspect` function does not get shadowed. So, we can ask the + // inspector extension page to call that function for us, using + // `inspected.Window.eval('inspect(node)')`. + // + // However, since we cannot just send the DOM node directly to the + // extension, we will have to store it in a temporary global variable + // so that the extension can find it. + + let name = `__EMBER_INSPECTOR_${(Math.random() * 100000000).toFixed(0)}`; + + window[name] = node; + + this.get('namespace.port').send('view:inspectDOMNode', { name }); }, _listen() { diff --git a/ember_debug/view-debug.js b/ember_debug/view-debug.js index 57ed9e13c5..4595334040 100644 --- a/ember_debug/view-debug.js +++ b/ember_debug/view-debug.js @@ -168,7 +168,7 @@ export default EmberObject.extend(PortMixin, { * @param {Element} element The element to inspect */ inspectElement(element) { - this.get('adapter').inspectElement(element); + this.get('adapter').inspectNode(element); }, sendTree() {