Skip to content
Merged
Changes from all 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
24 changes: 17 additions & 7 deletions userscripts/src/yt-pro.user.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,18 +406,28 @@
obs.observe(e);
};
const lazy = () => document.querySelectorAll(sel).forEach(processNode);
const debounceLazy = debounce(lazy, 50);
let moTimeout;
const mo = new MutationObserver((mutations) => {
let added = false;
let hasAdded = false;
for (let i = 0; i < mutations.length; i++) {
const nodes = mutations[i].addedNodes;
for (let j = 0; j < nodes.length; j++) {
if (nodes[j].nodeType === 1) {
added = true;
const added = mutations[i].addedNodes;
for (let j = 0; j < added.length; j++) {
if (added[j].nodeType === 1) {
hasAdded = true;
break;
}
}
if (added) break;
if (hasAdded) break;
}
Comment on lines +411 to +421

if (hasAdded) {
if (moTimeout) clearTimeout(moTimeout);
moTimeout = setTimeout(() => {
const els = document.querySelectorAll(sel);
for (let i = 0; i < els.length; i++) {
processNode(els[i]);
}
}, 100);
Comment on lines +423 to +430
}
Comment on lines +411 to 431
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

The current implementation introduces two significant issues:

  1. Visual Flicker: Delaying processNode by 100ms allows elements to render before being hidden, causing a noticeable flicker. Top-level elements should be processed immediately.
  2. Debounce Starvation: The nodeType === 1 check is too broad. Frequent minor DOM updates (like progress bar changes or timestamps) will constantly reset the timer, potentially preventing the batch processing from ever running on a busy page.

Additionally, the use of index-based for loops for mutations deviates from the for...of style used elsewhere in the file (Rule 5 of the Repository Style Guide).

      let hasAdded = false;
      for (const m of mutations) {
        for (const node of m.addedNodes) {
          if (node.nodeType !== 1) continue;
          const n = node.nodeName;
          // Immediate process to avoid flicker for top-level elements
          if (
            (n === "YTD-RICH-ITEM-RENDERER" || n === "YTD-COMPACT-VIDEO-RENDERER" || n === "YTD-THUMBNAIL") &&
            !node.dataset.lazyOpt
          ) {
            processNode(node);
          }
          // Check if this is a YouTube component that might contain target elements
          if (n.startsWith("YTD-") || n.startsWith("YT-")) hasAdded = true;
        }
      }

      if (hasAdded) {
        if (moTimeout) clearTimeout(moTimeout);
        moTimeout = setTimeout(() => {
          const els = document.querySelectorAll(sel);
          for (let i = 0; i < els.length; i++) {
            processNode(els[i]);
          }
        }, 100);
      }
References
  1. Match the existing style of the touched file. The file predominantly uses for...of for iterating over mutations and addedNodes. (link)

if (added) debounceLazy();
});
Expand Down
Loading