верни имена переменным из старого кода

Новый код
import "requestidlecallback-polyfill";
import { EventImpl } from "./EventImpl.js";
import debug from "./debug.ts";

const adKeywords = new Set([
  "advertise",
  "promo",
  "sponsor",
  "banner",
  "commercial",
  "preroll",
  "midroll",
  "postroll",
  "ad-container",
  "sponsored",
]);

const adKeywordsRegex = (() => {
  const pattern = Array.from(adKeywords).join("|");
  return new RegExp(pattern, "i");
})();

const filterVideoNodes = (nodes) => {
  const result = [];
  for (let i = 0; i < nodes.length; i++) {
    const node = nodes[i];
    if (node instanceof HTMLVideoElement) {
      result.push(node);
    } else if (node instanceof HTMLElement) {
      const videos = node.querySelectorAll("video");
      for (let j = 0; j < videos.length; j++) {
        result.push(videos[j]);
      }
    }
  }
  return result;
};

const isAdVideo = (video) => {
  if (
    adKeywordsRegex.test(video.className) ||
    adKeywordsRegex.test(video.title)
  )
    return true;

  let parent = video.parentElement;
  while (parent) {
    if (
      adKeywordsRegex.test(parent.className) ||
      adKeywordsRegex.test(parent.id)
    )
      return true;
    parent = parent.parentElement;
  }

  return false;
};

const isMutedVideo = (video) => {
  return (
    video.hasAttribute("muted") &&
    !video.classList.contains("vjs-tech") &&
    !video.preload
  );
};

const isVideoReady = (video) => video.readyState >= 3;

const waitForVideoReady = (video, callback) => {
  const checkVideoState = () => {
    if (isVideoReady(video)) {
      callback(video);
    } else {
      requestAnimationFrame(checkVideoState);
    }
  };

  checkVideoState();
};

export class VideoObserver {
  constructor() {
    this.videoCache = new Set();
    this.onVideoAdded = new EventImpl();
    this.onVideoRemoved = new EventImpl();
    this.observers = new Set();
    this.hasProcessedRoot = new Set();
    
    // Bind the handler to ensure correct 'this' context
    this.handleMutations = this.handleMutations.bind(this);
  }

  // Метод для наблюдения за любым корнем (document или shadowRoot)
  observeRoot(root) {
    if (this.hasProcessedRoot.has(root)) {
      return; // Избежать двойного наблюдения за одним и тем же корнем
    }
    this.hasProcessedRoot.add(root);

    const observer = new MutationObserver(this.handleMutations);
    observer.observe(root, { childList: true, subtree: true });
    this.observers.add(observer);

    // Инициальная обработка существующих видео и ShadowDOM внутри данного корня
    const initialVideos = filterVideoNodes(root.childNodes);
    initialVideos.forEach((video) => this.checkAndHandleVideo(video));

    // Поиск и наблюдение за любыми уже существующими ShadowRoot внутри данного корня
    const shadowHosts = root.querySelectorAll("*");
    shadowHosts.forEach((host) => {
      if (host.shadowRoot) {
        this.observeRoot(host.shadowRoot);
      }
    });
  }

  handleMutations(mutationsList) {
    mutationsList.forEach((mutation) => {
      if (mutation.type !== "childList") return;

      // Обработка добавленных узлов
      mutation.addedNodes.forEach((node) => {
        this.processNode(node);
      });

      // Обработка удаленных узлов
      mutation.removedNodes.forEach((node) => {
        this.processRemovedNode(node);
      });
    });
  }

  processNode(node) {
    if (node instanceof HTMLVideoElement) {
      this.checkAndHandleVideo(node);
    } else if (node instanceof HTMLElement) {
      // Обработка видео внутри добавленного элемента
      const videos = filterVideoNodes([node]);
      videos.forEach((video) => this.checkAndHandleVideo(video));

      // Если у элемента уже есть ShadowRoot, начать наблюдение за ним
      if (node.shadowRoot) {
        this.observeRoot(node.shadowRoot);
      }

      // Если элемент еще не имеет ShadowRoot, слушать событие его присоединения
      const observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
          if (mutation.type === "childList") {
            mutation.addedNodes.forEach((child) => {
              if (child instanceof HTMLElement && child.shadowRoot) {
                this.observeRoot(child.shadowRoot);
              }
            });
          }
        });
      });

      observer.observe(node, { childList: true, subtree: true });
      this.observers.add(observer);
    }
  }

  processRemovedNode(node) {
    if (node instanceof HTMLVideoElement) {
      this.handleVideoRemoved(node);
    } else if (node instanceof HTMLElement) {
      const videos = filterVideoNodes([node]);
      videos.forEach((video) => this.handleVideoRemoved(video));

      // Если у элемента было ShadowRoot, прекратить наблюдение за ним
      if (node.shadowRoot) {
        this.disconnectObserverFromRoot(node.shadowRoot);
      }
    }
  }

  disconnectObserverFromRoot(root) {
    for (let observer of this.observers) {
      // Проверяем, наблюдает ли observer за данным корнем
      // К сожалению, стандартный MutationObserver не предоставляет прямого способа узнать, за какими корнями он наблюдает
      // Поэтому, если необходимо, можно создать маппинг между observer и корнями
      // Для простоты предполагаем, что один observer отвечает за один корень
      observer.disconnect();
      this.observers.delete(observer);
      break; // Предполагаем, что один observer на корень
    }
  }

  enable() {
    this.observeRoot(document);
  }

  disable() {
    this.observers.forEach((observer) => observer.disconnect());
    this.observers.clear();
    if (this.mutationTimeout) {
      clearTimeout(this.mutationTimeout);
    }
  }

  checkAndHandleVideo = (video) => {
    if (this.videoCache.has(video)) return;
    this.videoCache.add(video);

    if (isAdVideo(video) || isMutedVideo(video)) {
      debug.log("The promotional/muted video was ignored", video);
      return;
    }
    waitForVideoReady(video, this.handleVideoAdded);
  };

  handleVideoAdded = (video) => {
    this.onVideoAdded.dispatch(video);
  };

  handleVideoRemoved = (video) => {
    if (!document.contains(video) && !this.isInAnyObservedShadowRoot(video)) {
      this.videoCache.delete(video);
      this.onVideoRemoved.dispatch(video);
    }
  };

  isInAnyObservedShadowRoot(video) {
    let node = video.parentElement;
    while (node) {
      if (node.shadowRoot && this.hasProcessedRoot.has(node.shadowRoot)) {
        return true;
      }
      node = node.parentElement;
    }
    return false;
  }
}



Старый код
import "requestidlecallback-polyfill";
import { EventImpl } from "./EventImpl.js";
import debug from "./debug.ts";

const adKeywords = new Set([
  "advertise",
  "promo",
  "sponsor",
  "banner",
  "commercial",
  "preroll",
  "midroll",
  "postroll",
  "ad-container",
  "sponsored",
]);

const adKeywordsRegex = (() => {
  const pattern = Array.from(adKeywords).join("|");
  return new RegExp(pattern, "i");
})();

const filterVideoNodes = (nodes) => {
  const result = [];
  for (let i = 0; i < nodes.length; i++) {
    const node = nodes[i];
    if (node instanceof HTMLVideoElement) {
      result.push(node);
    } else if (node instanceof HTMLElement) {
      const videos = node.querySelectorAll("video");
      for (let j = 0; j < videos.length; j++) {
        result.push(videos[j]);
      }
    } else if (node.shadowRoot) {
      const shadowVideos = node.shadowRoot.querySelectorAll("video");
      for (let k = 0; k < shadowVideos.length; k++) {
        result.push(shadowVideos[k]);
      }
    }
  }
  return result;
};

const isAdVideo = (video) => {
  if (
    adKeywordsRegex.test(video.className) ||
    adKeywordsRegex.test(video.title)
  )
    return true;

  let parent = video.parentElement;
  while (parent) {
    if (
      adKeywordsRegex.test(parent.className) ||
      adKeywordsRegex.test(parent.id)
    )
      return true;
    parent = parent.parentElement;
  }

  return false;
};

const isMutedVideo = (video) => {
  return (
    video.hasAttribute("muted") &&
    !video.classList.contains("vjs-tech") &&
    !video.preload
  );
};

const isVideoReady = (video) => video.readyState >= 3;

const waitForVideoReady = (video, callback) => {
  const checkVideoState = () => {
    if (isVideoReady(video)) {
      callback(video);
    } else {
      requestAnimationFrame(checkVideoState);
    }
  };

  checkVideoState();
};

export class VideoObserver {
  constructor() {
    this.videoCache = new Set();
    this.onVideoAdded = new EventImpl();
    this.onVideoRemoved = new EventImpl();
    this.mutationTimeout = null;
    this.isSearchingShadowRoot = false;
    this.hasDoneInitialShadowSearch = false;

    this.observer = new MutationObserver(this.handleMutations);
  }

  handleMutations = (mutationsList) => {
    if (this.mutationTimeout) {
      clearTimeout(this.mutationTimeout);
    }

    window.requestIdleCallback(
      () => {
        for (let i = 0; i < mutationsList.length; i++) {
          const mutation = mutationsList[i];
          if (mutation.type !== "childList") continue;

          const addedVideos = filterVideoNodes(mutation.addedNodes);
          for (let j = 0; j < addedVideos.length; j++) {
            this.checkAndHandleVideo(addedVideos[j]);
          }

          const removedVideos = filterVideoNodes(mutation.removedNodes);
          for (let k = 0; k < removedVideos.length; k++) {
            this.handleVideoRemoved(removedVideos[k]);
          }
        }

        if (!this.hasDoneInitialShadowSearch) {
          this.mutationTimeout = setTimeout(() => {
            this.searchInShadowRoots();
            this.hasDoneInitialShadowSearch = true;
          }, 5000);
        }
      },
      { timeout: 1000 },
    );
  };

  searchInShadowRoots = () => {
    if (this.isSearchingShadowRoot) return;
    this.isSearchingShadowRoot = true;

    const findVideosInShadowDOM = (root) => {
      const videos = new Set();
      
      // Helper function to recursively search shadow roots
      const searchNode = (node) => {
        // Check if the node itself is a video
        if (node instanceof HTMLVideoElement) {
          videos.add(node);
        }

        // Search in regular DOM
        const directVideos = node.querySelectorAll('video');
        directVideos.forEach(video => videos.add(video));

        // Search in shadow DOM
        if (node.shadowRoot) {
          const shadowVideos = node.shadowRoot.querySelectorAll('video');
          shadowVideos.forEach(video => videos.add(video));
          
          // Recursively search all elements in shadow root
          node.shadowRoot.querySelectorAll('*').forEach(searchNode);
        }

        // Search children's shadow roots
        if (node.children) {
          Array.from(node.children).forEach(searchNode);
        }
      };

      searchNode(root);
      return Array.from(videos);
    };

    // Start search from document root
    const foundVideos = findVideosInShadowDOM(document.documentElement);
    foundVideos.forEach(video => {
      this.checkAndHandleVideo(video);
    });

    this.isSearchingShadowRoot = false;
  };

  enable() {
    this.observer.observe(document, { childList: true, subtree: true });
    
    // Initial scan of regular DOM
    const regularVideos = document.querySelectorAll("video");
    for (let i = 0; i < regularVideos.length; i++) {
      this.checkAndHandleVideo(regularVideos[i]);
    }
    
    if (!this.hasDoneInitialShadowSearch) {
      this.mutationTimeout = setTimeout(() => {
        this.searchInShadowRoots();
        this.hasDoneInitialShadowSearch = true;
      }, 5000);
    }
  }

  disable() {
    this.observer.disconnect();
    if (this.mutationTimeout) {
      clearTimeout(this.mutationTimeout);
    }
  }

  checkAndHandleVideo = (video) => {
    if (this.videoCache.has(video)) return;
    this.videoCache.add(video);
    
    if (isAdVideo(video) || isMutedVideo(video)) {
      debug.log("The promotional/muted video was ignored", video);
      return;
    }
    waitForVideoReady(video, this.handleVideoAdded);
  };

  handleVideoAdded = (video) => {
    this.onVideoAdded.dispatch(video);
  };

  handleVideoRemoved = (video) => {
    if (!document.contains(video)) {
      this.videoCache.delete(video);
      this.onVideoRemoved.dispatch(video);
    }
  };
}