@@ -382,6 +382,40 @@ it("paints canvas pixels into the capture as the canvas's own background", () =>
382382 expect ( canvas . getAttribute ( "style" ) ) . toBe ( "border: 4px solid gold;" ) ;
383383} ) ;
384384
385+ it ( "decodes every image a capture embeds before the page paints in WebKit, without drawing it" , ( ) => {
386+ const { harness, iframe } = createPlayer ( ) ;
387+ const doc = iframe . contentDocument ! ;
388+ jest . spyOn ( navigator , "vendor" , "get" ) . mockReturnValue ( "Apple Computer, Inc." ) ;
389+ const photo = "data:image/jpeg;base64,/9j/4AAQ" ;
390+ const style = doc . createElement ( "style" ) ;
391+ style . textContent = `.hero{background:url(${ photo } ) center/cover} .again{background-image:url('${ photo } ')} .grain{background:url('data:image/svg+xml;utf8,<svg/>')}` ;
392+ doc . head . appendChild ( style ) ;
393+ const canvas = doc . createElement ( "canvas" ) ;
394+ doc . body . replaceChildren ( Object . assign ( doc . createElement ( "div" ) , { className : "hero" } ) , canvas ) ;
395+ jest . spyOn ( Object . getPrototypeOf ( canvas ) as HTMLCanvasElement , "toDataURL" ) . mockReturnValue ( "data:image/png;base64,AAAA" ) ;
396+
397+ const parsed = new DOMParser ( ) . parseFromString ( harness . captureIframeAsForeignObjectSvg ( 1080 , 1920 ) , "image/svg+xml" ) ;
398+ const [ decoders , page ] = Array . from ( parsed . documentElement . children ) ;
399+ const images = Array . from ( decoders . querySelectorAll ( "img" ) ) ;
400+
401+ expect ( parsed . querySelector ( "parsererror" ) ) . toBeNull ( ) ;
402+ expect ( images . map ( img => img . getAttribute ( "src" ) ) ) . toEqual ( [ photo , "data:image/png;base64,AAAA" ] ) ;
403+ expect ( images . every ( img => img . getAttribute ( "decoding" ) === "sync" && img . getAttribute ( "style" ) ! . includes ( "filter:opacity(0)" ) ) ) . toBe ( true ) ;
404+ expect ( page . querySelector ( ".hero" ) ) . not . toBeNull ( ) ;
405+ } ) ;
406+
407+ it ( "leaves embedded images to the page outside WebKit" , ( ) => {
408+ const { harness, iframe } = createPlayer ( ) ;
409+ const doc = iframe . contentDocument ! ;
410+ jest . spyOn ( navigator , "vendor" , "get" ) . mockReturnValue ( "Google Inc." ) ;
411+ doc . body . replaceChildren ( Object . assign ( doc . createElement ( "img" ) , { src : "data:image/jpeg;base64,/9j/4AAQ" } ) ) ;
412+
413+ const parsed = new DOMParser ( ) . parseFromString ( harness . captureIframeAsForeignObjectSvg ( 1080 , 1920 ) , "image/svg+xml" ) ;
414+
415+ expect ( parsed . documentElement . children ) . toHaveLength ( 1 ) ;
416+ expect ( parsed . querySelectorAll ( "img" ) ) . toHaveLength ( 1 ) ;
417+ } ) ;
418+
385419it ( "keeps a failed capture inside its canvas layer and retries only after the asset changes" , async ( ) => {
386420 const { player, harness, iframe, events, edit } = createPlayer ( ) ;
387421 jest . spyOn ( console , "warn" ) . mockImplementation ( ( ) => { } ) ;
0 commit comments