Skip to content

Conversation

@renandincer
Copy link
Collaborator

@renandincer renandincer commented Dec 6, 2025

Problem

When removing a <video-moq> element from the DOM, the browser would freeze for 5+ seconds, causing:

  • UI hangs during element removal
  • Test timeouts when programmatically removing elements
  • Poor user experience in applications that dynamically create/destroy players

Root Cause

The disconnectedCallback() was calling destroy(), which internally calls AudioContext.close(). This Web Audio API method performs expensive cleanup that blocks the main thread for several seconds while releasing audio resources.

Reproduction

// Create and add a video-moq element
const player = document.createElement('video-moq');
player.setAttribute('src', 'https://relay.example.com?namespace=mystream');
document.body.appendChild(player);

// Wait for it to load...

// Try to remove it - this will freeze the UI for 5+ seconds
player.parentNode.removeChild(player);  // ❌ BLOCKS for 5+ seconds

Solution

Skip cleanup in disconnectedCallback() and rely on JavaScript's garbage collection to clean up resources asynchronously:

  • Element is removed from DOM immediately (no blocking)
  • When all references are cleared, GC will:
    • Terminate the web worker
    • Release the AudioContext without blocking
    • Free associated memory

This is safe because the Web Audio API is designed to handle this - when an AudioContext becomes unreachable, the browser cleans it up in the background.

Testing

After this fix:

  • Element removal completes instantly
  • No UI freezes
  • Tests that create/destroy players pass reliably

Alternative Considered

We considered deferring cleanup with setTimeout() or requestAnimationFrame(), but those still caused issues. The cleanest solution is to let the browser handle cleanup through garbage collection.

The disconnectedCallback was calling destroy() which closes AudioContext,
blocking the main thread for several seconds. This caused UI freezes when
removing the element from DOM.

Solution: Skip cleanup in disconnectedCallback and let garbage collection
handle resource cleanup asynchronously without blocking the UI.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants