Problem/Motivation
Since the fix for #3538028 in 3.0.18, dBlazy.find(el, selector) silently falls back to querying the entire document whenever el has no descendant matching selector, instead of returning nothing. See context() in js/src/dblazy.js.
Drupal.behaviors.blazyMedia (js/src/components/blazy.media.js) relies on scoped, possibly-empty lookups like $el.find('iframe') to find an iframe already inside a not-yet-clicked .media--player element (there normally isn't one) and unconditionally calls $.remove() on the result. Because of the fallback above, that "not found" lookup instead returns the first iframe anywhere on the page, and blazyMedia deletes it — even if it has nothing to do with Blazy.
- Confirmed with a page that has a Blazy oEmbed field (click-to-play, unclicked) plus an unrelated iframe elsewhere (e.g. a plain core Media
oembedformatter field, appearing earlier in the DOM) - The unrelated iframe is silently removed from the DOM on page load, with no console error
- Confirmed via instrumented
Node.prototype.removeChild, stack trace shows removal originates fromblazyMedia'sattach→ internalprocess()→dBlazy.remove() - Confirmed root cause by patching
dBlazy.findat runtime to not fall back todocumenton no-match — the unrelated iframe then survives
Note: the 3.0.19 changelog entry "Fixed for Colorbox local/remote video collapsed against modern CSS aspect ratio" is CSS-only (css/components/blazy.media.css) and does not touch this code path. It does not fix this bug, since the affected iframe is removed from the DOM entirely rather than collapsed by CSS.
Steps to reproduce
- On one page, add a Blazy-formatted oEmbed/video field using the click-to-play
media--playerpattern, left in its default unclicked state - On the same page, earlier in DOM order, add any other iframe that loads on page load and is unrelated to Blazy (e.g. a core Media
oembedformatter field, a raw embedded video/iframe, a share-widget iframe) - Load the page and let
Drupal.attachBehaviorsrun - Observe the earlier, unrelated iframe disappears from the DOM
Proposed resolution
In js/src/components/blazy.media.js, verify a found iframe is actually a descendant of the relevant player element before removing it, rather than trusting find()'s fallback semantics, e.g.:
var iframe = $el.find(IFRAME); if (iframe && el.contains(iframe)) { $.remove(iframe); }
Apply the same guard to the other $.remove(iframe) calls in play()/playNow()/stop() in the same file that rely on scoped find() results.
Separately, context() in js/src/dblazy.js should not widen an element-scoped query to document merely because nothing matched — "no match" is a valid, expected result of a scoped query.
Remaining tasks
- Confirm whether the
context()fallback is still needed for the original #3538028 case onceblazy.media.jsstops relying on it, or whether it needs tightening rather than removal - Add JS test coverage for a page containing both a click-to-play Blazy player and an unrelated third-party iframe
User interface changes
None.
API changes
None.
Data model changes
None.
Issue fork blazy-3619552
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
Comments
Comment #2
freelockFix in MR. Issue summary and patch created with assistance from Claude Sonnet.
Comment #4
gausarts commentedThank you.
I haven't been able to reproduce or trace the root cause.
Just based-on my own understanding:
dBlazy.remove()is scoped toparentElement, henceel=.media--player, neverdocument. Not a culprit as you suspected.dBlazy.find()does fallback todocument, which likely should not, but no real issues so far, since it's usage in blazyMediaprocessis already scoped toel=.media--player, notdocumentas you suspected. Not a culprit, either.process()will not be invoked if no elements are found. Thus nodocumentfallback here:https://git.drupalcode.org/project/blazy/-/blob/3.0.19/js/src/plugin/bla...
dBlazy.context()is the culprit? But I am hesitant since it is still scoped to.media--playeras the selector. Thus element inprocess()is always a.media--player, never fallback todocumentas you suspected.To prove it is the culprit, please remove this line:
https://git.drupalcode.org/project/blazy/-/blob/3.0.x/js/src/components/...
If that solves your issues, please update your patch with that alone.
Leave the rest of
$.remove()intact for now. If persists, then adjust them as you did.A better solution might be to change
iframeselector toiframe.media__elementas needed.If anyone has the same issue, please confirm. I may need some time to investigate this any better.