Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workaround 1Password browser extension bug #1932

Merged
merged 1 commit into from
Jan 22, 2025

Conversation

victorlin
Copy link
Member

@victorlin victorlin commented Jan 18, 2025

preview on auspice.us, nextstrain.org

Description of proposed changes

The bug pathologically slows down (and sometimes crashes) pages with thousands/millions of SVG elements in the DOM, which happens in reasonably sized datasets.¹

Short circuit the extension's calls to the very slow .innerText in its function:

  RM = (e) => {
    if (e == null) return null;
    let t = e.parentNode,
      n = 0;
    for (; n < 4 /*LM*/ && t !== null; ) {
      if (
        t instanceof HTMLElement &&
        t.innerText &&
        t.innerText.trim().length > 0
      )
        return t.innerText;
      (t = t.parentNode), n++;
    }
    return null;
  },

by nesting each panel's D3 elements deeper than extension's traversal limit of 4. That is, we're moving the closest HTMLElement (e.g. <div>s containing <svg>s) further away from the leaf SVG elements.

For most panels, fewer <g>s would do, but adding four guards against future changes to D3 implementation.

The workaround was trivial for entropy and frequencies panels which already have a separation where size/styles are applied on a parent <svg> and D3 operations happen on a child <g>. It was still not too bad for map and measurements panels - those did not have a pre-existing separation, but adding the separation was trivial.

The tree panel was the least trivial - the code and type annotations assumed that the root SVG element for D3 operations was an <svg>, so switching it to <g> required updating those assumptions. Additionally, there is code that retrieves the width/height from the root SVG element, so it must be retained on the child element even when nested under an <svg>, which requires width and height to be set explicitly.

¹ #1919

Related issue(s)

#1919

Checklist

  • Checks pass (docs build failure is a linting error that can be ignored)
  • If making user-facing changes, add a message in CHANGELOG.md summarizing the changes in this PR
  • (to be done by a Nextstrain team member) Create preview PRs on downstream repositories.
  • test entropy: tb before, after
  • test frequencies: ncov color by pango lineage before, after
    • The extension effects aren't as noticeable here, I had to use dev tools profiling to confirm that innerText is not excessively called
  • test map: ncov color by pango lineage before, after
  • test tree: ncov before, after
  • test measurements: tested locally with Auspice test dataset (no link)

src/components/tree/tree.tsx Outdated Show resolved Hide resolved
src/components/entropy/index.js Show resolved Hide resolved
The bug pathologically slows down (and sometimes crashes) pages with
thousands/millions of SVG elements in the DOM, which happens in
reasonably sized datasets.¹

Short circuit the extension's calls to the very slow .innerText in its
function:

  RM = (e) => {
    if (e == null) return null;
    let t = e.parentNode,
      n = 0;
    for (; n < 4 /*LM*/ && t !== null; ) {
      if (
        t instanceof HTMLElement &&
        t.innerText &&
        t.innerText.trim().length > 0
      )
        return t.innerText;
      (t = t.parentNode), n++;
    }
    return null;
  },

by nesting each panel's D3 elements deeper than extension's traversal
limit of 4.  That is, we're moving the closest HTMLElement (e.g. <div>s
containing <svg>s) further away from the leaf SVG elements.

For most panels, fewer <g>s would do, but adding four guards against
future changes to D3 implementation.

The workaround was trivial for entropy and frequencies panels which
already have a separation where size/styles are applied on a parent
<svg> and D3 operations happen on a child <g>. It was still not too bad
for map and measurements panels - those did not have a pre-existing
separation, but adding the separation was trivial.

The tree panel was the least trivial - the code and type annotations
assumed that the root SVG element for D3 operations was an <svg>, so
switching it to <g> required updating those assumptions. Additionally,
there is code that retrieves the width/height from the root SVG element,
so it must be retained on the child element even when nested under an
<svg>, which requires width and height to be set explicitly.

¹ <#1919>

Co-authored-by: Thomas Sibley <[email protected]>
@victorlin victorlin force-pushed the victorlin/1password-extension-patch branch from 58a6530 to 17b3f5c Compare January 21, 2025 18:42
@victorlin victorlin temporarily deployed to auspice-victorlin-1pass-snqoxz January 21, 2025 18:43 Inactive
Copy link
Member

@jameshadfield jameshadfield left a comment

Choose a reason for hiding this comment

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

I haven't tested this with the 1password extension, but gave it a quick test on its own and (as expected) it works fine. A minor annoyance for me when inspecting elements that there's more <g> elements to open in dev-tools, but overall a nice and simple fix for a big problem (assuming it does fix the problem).

@victorlin victorlin merged commit b8c0772 into master Jan 22, 2025
20 checks passed
@victorlin victorlin deleted the victorlin/1password-extension-patch branch January 22, 2025 00:36
victorlin added a commit that referenced this pull request Jan 22, 2025
Accidentally skipped in the pull request 🤦

<#1932>
@victorlin victorlin linked an issue Jan 23, 2025 that may be closed by this pull request
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Unresponsiveness with 1Password extension
4 participants