From 5a360b304e913d18db21f589677b7cfd8ffd9ec7 Mon Sep 17 00:00:00 2001 From: Bing Dai Date: Fri, 24 Sep 2021 23:10:22 -0700 Subject: [PATCH] Use bounds to find component instead of id --- ember_debug/models/profile-manager.js | 98 ++++++++++++++++++++++++++- ember_debug/models/profile-node.js | 7 +- ember_debug/render-debug.js | 34 +--------- 3 files changed, 102 insertions(+), 37 deletions(-) diff --git a/ember_debug/models/profile-manager.js b/ember_debug/models/profile-manager.js index e00fc480e5..e949f1e45c 100644 --- a/ember_debug/models/profile-manager.js +++ b/ember_debug/models/profile-manager.js @@ -2,9 +2,84 @@ import ProfileNode from './profile-node'; import Ember from '../utils/ember'; const { - run: { later, scheduleOnce }, + run: { later, scheduleOnce }, guidFor } = Ember; +function _findRoots({ first, last, parent }) { + const roots = []; + const closest = parent.childNodes; + if (first.node === last.node) + return [first.node]; + + let start = null; + let end = null; + for (let i = 0; i < closest.length; i++) { + if (closest.item(i) === first.node) + start = i; + else if (closest.item(i) === last.node) + end = i; + } + + if (start === null || end === null) + return []; + + + for (let i = start; i <= end; i++) + roots.push(closest.item(i)); + + + return roots.filter((el) => { + if (el.nodeType === 3) { + if (el.nodeValue.trim() === '') { + return false; + } + } + return el; + }) +} + +function makeHighlight(id) { + return ``; +} +function _insertHTML(id) { + document.body.insertAdjacentHTML('beforeend', makeHighlight(id).trim()); + return document.body.lastChild; +} + +function _insertStylesheet() { + const content = ` + .ember-inspector-render-highlight { + border: 1px solid red; + } + ` + const style = document.createElement('style'); + style.appendChild(document.createTextNode(content)); + document.head.appendChild(style); + return style; +} + +function _renderHighlight(node, guid) { + if (!node?.getBoundingClientRect) { + return; + } + const rect = node.getBoundingClientRect() + const id = guid || (Math.random() * 100000000).toFixed(0); + const highlight = _insertHTML(id); + const { top, left, width, height } = rect; + const { scrollX, scrollY } = window; + const { style } = highlight; + if (style) { + style.position = 'absolute'; + style.top = `${top + scrollY}px`; + style.left = `${left + scrollX}px`; + style.width = `${width}px`; + style.height = `${height}px`; + style.zIndex = `1000000`; + } + setTimeout(() => { + highlight.remove() + }, 1000); +} /** * A class for keeping track of active rendering profiles as a list. */ @@ -15,11 +90,16 @@ export default class ProfileManager { this.currentSet = []; this._profilesAddedCallbacks = []; this.queue = []; + this.shouldHighlightRender = false; + this.stylesheet = _insertStylesheet(); } began(timestamp, payload, now) { return this.wrapForErrors(this, function () { this.current = new ProfileNode(timestamp, payload, this.current, now); + if (this.shouldHighlightRender && payload.view) { + this.renderHighLight(payload.view); + } return this.current; }); } @@ -45,6 +125,16 @@ export default class ProfileManager { return callback.call(context); } + renderHighLight(view) { + const symbols = Object.getOwnPropertySymbols(view); + const bounds = view[symbols.find(sym => sym.description === "BOUNDS")]; + const elements = _findRoots(bounds); + + elements.forEach((node) => { + _renderHighlight(node, guidFor(view)) + }); + } + /** * Push a new profile into the queue * @param info @@ -80,6 +170,12 @@ export default class ProfileManager { } } + teardown() { + this.stylesheet.remove(); + } + + + _flush() { let entry, i; for (i = 0; i < this.queue.length; i++) { diff --git a/ember_debug/models/profile-node.js b/ember_debug/models/profile-node.js index 679b0878e3..58e49c510b 100644 --- a/ember_debug/models/profile-node.js +++ b/ember_debug/models/profile-node.js @@ -6,7 +6,6 @@ import Ember from '../utils/ember'; const { get, guidFor } = Ember; - const ProfileNode = function (start, payload, parent, now) { let name; this.start = start; @@ -15,15 +14,15 @@ const ProfileNode = function (start, payload, parent, now) { if (payload) { if (payload.template) { name = payload.template; - debugger; } else if (payload.view) { - debugger; const view = payload.view; + this.viewGuid = guidFor(view); + name = get(view, 'instrumentDisplay') || get(view, '_debugContainerKey'); if (name) { name = name.replace(/^view:/, ''); } - this.viewGuid = guidFor(view); + } if (!name && payload.object) { diff --git a/ember_debug/render-debug.js b/ember_debug/render-debug.js index 6720c5c50d..75c06dc24c 100644 --- a/ember_debug/render-debug.js +++ b/ember_debug/render-debug.js @@ -33,42 +33,13 @@ export default EmberObject.extend(PortMixin, { this.profileManager.offProfilesAdded(this, this.sendAdded); this.profileManager.offProfilesAdded(this, this._updateComponentTree); + this.profileManager.teardown() }, sendAdded(profiles) { - if (this.shouldHighlightRender) { - profiles.forEach((profile) => { - this._hightLightNode(profile); - }); - } this.sendMessage('profilesAdded', { profiles }); }, - _hightLightNode({ viewGuid, children }) { - const hasChildren = children?.length > 0; - if (viewGuid) { - this._createOutline(viewGuid, hasChildren); - } - if (hasChildren) { - children.forEach((childNode) => { - this._hightLightNode(childNode); - }); - } - }, - - _createOutline(viewGuid, hasChildren) { - const element = document.getElementById(viewGuid); - if (element) { - const outline = element.style.outline; - element.style.outline = `${hasChildren ? '0.5' : '1'}px solid ${ - hasChildren ? 'blue' : 'red' - }`; - setTimeout(() => { - element.style.outline = outline ?? 'none'; - }, 1000); - } - }, - /** * Update the components tree. Called on each `render.component` event. * @private @@ -95,7 +66,7 @@ export default EmberObject.extend(PortMixin, { }, updateShouldHighlightRender({ shouldHighlightRender }) { - this.shouldHighlightRender = shouldHighlightRender; + this.profileManager.shouldHighlightRender = shouldHighlightRender; }, }, }); @@ -114,7 +85,6 @@ function _subscribeToRenderEvents() { payload, now: Date.now(), }; - return profileManager.addToQueue(info); },