Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/react-devtools-extensions/chrome/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Adds React debugging tools to the Chrome Developer Tools.",
"version": "6.1.1",
"version_name": "6.1.1",
"minimum_chrome_version": "102",
"minimum_chrome_version": "114",
"icons": {
"16": "icons/16-production.png",
"32": "icons/32-production.png",
Expand Down
2 changes: 1 addition & 1 deletion packages/react-devtools-extensions/edge/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "Adds React debugging tools to the Microsoft Edge Developer Tools.",
"version": "6.1.1",
"version_name": "6.1.1",
"minimum_chrome_version": "102",
"minimum_chrome_version": "114",
"icons": {
"16": "icons/16-production.png",
"32": "icons/32-production.png",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,26 @@ function drawNative(nodeToData: Map<HostInstance, Data>, agent: Agent) {
}

function drawWeb(nodeToData: Map<HostInstance, Data>) {
// if there are no nodes to draw, detach from top layer
if (nodeToData.size === 0) {
if (canvas !== null) {
if (canvas.matches(':popover-open')) {
// $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
canvas.hidePopover();
}
}
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this new code changes the behaviour of the drawWeb function.

Before this change, we would clear out canvas and draw nothing. Also, even if canvas was not initialized yet and drawWeb was called, we would initialize it as empty.

I think we should preserve the previous approach:

  1. Remove canvas.showPopover() from initialize.
  2. In the the end of drawWeb function call, add canvas.showPopover or canvas.hidePopover calls, based on nodeToData.size and popover state.

Something like this:

function drawWeb(nodeToData: Map<HostInstance, Data>) {
 <all code before your changes>
 ...
 
 if (nodeToData.size === 0 && canvas.matches(':popover-open')) {
   canvas.hidePopover();
 } else if (!canvas.matches(':popover-open') && nodeToData.size !== 0) {
   canvas.openPopover();
 }
 }

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Totally agree that we should first finish all drawWeb logic and then decide at the end whether or not to promote it to the top-layer.
I think that approach better fits the responsibilities of each method. Thanks for clarifying this!
Considering your comments, I've tested two different approaches:

1. Hiding the canvas only when there's nothing to draw (the current method):

function drawWeb(nodeToData: Map<HostInstance, Data>) {
  // ... previous code
  if (canvas !== null) {
    if (nodeToData.size === 0 && canvas.matches(':popover-open')) {
      canvas.hidePopover();
    } else if (nodeToData.size > 0 && !canvas.matches(':popover-open')) {
      canvas.showPopover();
    }
  }
} // end of drawWeb

Result: This method avoids frequent updates to the top-layer.
However, as you mentioned in your comment, if another top-layer element appears while highlights still remain, the highlight canvas might fall behind the new element.

2. Re-promoting canvas to top-layer on every update call:

function drawWeb(nodeToData: Map<HostInstance, Data>) {
  // ... previous code
  if (canvas !== null) {
    if (nodeToData.size === 0 && canvas.matches(':popover-open')) {
      canvas.hidePopover();
      return;
    }
    if (canvas.matches(':popover-open')) {
      canvas.hidePopover();
    }
    canvas.showPopover();
  }
} // end of drawWeb

Result: Frequent changes to the top-layer occur, but the highlights consistently remain on top, ensuring they never get hidden by other elements.
I think method #2 seems preferable in terms of clearly maintaining highlight visibility too.
However, I couldn't find any mentions of performance issues in either the W3C review or blink-dev discussions regarding frequent top-layer changes. Unless highlights are triggered continuously at extremely high frequency over a prolonged period, there shouldn't be any noticeable performance impact.


if (canvas === null) {
initialize();
} else {
if (!canvas.matches(':popover-open')) {
// $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
canvas.showPopover();
}
}

const dpr = window.devicePixelRatio || 1;
Expand Down Expand Up @@ -191,7 +209,13 @@ function destroyNative(agent: Agent) {

function destroyWeb() {
if (canvas !== null) {
// $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
canvas.hidePopover();

// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API and loses canvas nullability tracking
if (canvas.parentNode != null) {
// $FlowFixMe[incompatible-call]: Flow doesn't track that canvas is non-null here
canvas.parentNode.removeChild(canvas);
}
canvas = null;
Expand All @@ -204,6 +228,9 @@ export function destroy(agent: Agent): void {

function initialize(): void {
canvas = window.document.createElement('canvas');
canvas.setAttribute('popover', 'manual');

// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
canvas.style.cssText = `
xx-background-color: red;
xx-opacity: 0.5;
Expand All @@ -213,9 +240,16 @@ function initialize(): void {
position: fixed;
right: 0;
top: 0;
z-index: 1000000000;
background-color: transparent;
outline: none;
box-shadow: none;
border: none;
`;

const root = window.document.documentElement;
root.insertBefore(canvas, root.firstChild);

// $FlowFixMe[prop-missing]: Flow doesn't recognize Popover API
// $FlowFixMe[incompatible-use]: Flow doesn't recognize Popover API
canvas.showPopover();
}
Loading