destroy() is a no-op before ready, leaving pending provider setup alive
Current behavior
Calling destroy() before an embedded provider reaches Plyr's ready state is a no-op. By that point the constructor has already wrapped the target, registered container/global listeners, and started asynchronous provider setup.
For YouTube, the pending setup can later continue even though the consumer already called destroy(). In an SPA this can retain a detached instance and its listeners after navigation.
Minimal reproduction
Using Plyr 3.8.4:
<div
id="player"
data-plyr-provider="youtube"
data-plyr-embed-id="bTqVqk7FSmY"
></div>import Plyr from "plyr";
const target = document.querySelector("#player");
const player = new Plyr(target);
// Run synchronously, before the YouTube API can make Plyr ready.
player.destroy();
// The generated wrapper is still present because destroy() returned early.
console.log(document.querySelector(".plyr")); // <div class="plyr ...">The same result is especially easy to observe with the YouTube iframe API blocked or delayed in DevTools.
Expected behavior
destroy() should also dispose an instance whose provider is still initializing:
- cancel or invalidate pending provider setup;
- remove listeners installed by the constructor;
- restore/remove generated DOM;
- prevent late provider callbacks or timers from rebuilding the destroyed player.
It should be safe and idempotent to call during SPA/component teardown without first waiting for ready.
Related issues checked
I searched the open and closed issues before filing. The closest reports appear distinct:
- #1001 concerns
stopVideo()throwing when a ready YouTube player's DOM was already removed. - #1010 concerns synchronous framework DOM replacement during teardown.
- #1698 concerns instances remaining at
ready: false, but does not coverdestroy()skipping cleanup. - #77 was the original request to add a destroy API and is closed.
This report is specifically about the early return when teardown happens before provider readiness.
Cause
In v3.8.4, destroy() returns immediately when this.ready is false:
https://github.com/sampotts/plyr/blob/v3.8.4/src/js/plyr.js#L1072-L1075
However, listener and provider setup has already started during construction:
https://github.com/sampotts/plyr/blob/v3.8.4/src/js/plyr.js#L244-L287
Environment
- Plyr 3.8.4
- YouTube provider
- Reproduced in Chromium
Source: sampotts/plyr