cross-origin-tall-subframe.sub.html (1979B)
1 <!doctype html> 2 <style> 3 body { margin: 0 } 4 .spacer { 5 height: 5000px; 6 } 7 #target { 8 height: 100px; 9 background-color: green; 10 } 11 #next { 12 position: absolute; 13 inset: 0; 14 width: 100%; 15 height: 100%; 16 border: 0; 17 } 18 #leaf { 19 display: none; 20 } 21 .leaf #next { 22 display: none; 23 } 24 .leaf #leaf { 25 display: block; 26 } 27 </style> 28 <iframe id="next" sandbox="allow-scripts"></iframe> 29 <div id="leaf"> 30 <div class=spacer></div> 31 <div id="target"></div> 32 </div> 33 <script> 34 const A = "http://{{hosts[alt][]}}:{{ports[http][0]}}"; 35 const B = "http://{{hosts[][]}}:{{ports[http][0]}}"; 36 37 const nestingLevel = parseInt(new URL(document.URL).searchParams.get("nest"), 10); 38 39 const isLeaf = nestingLevel == 0; 40 document.documentElement.classList.toggle("leaf", isLeaf); 41 if (!isLeaf) { 42 next.src = `${location.origin == A ? B : A}${location.pathname}?nest=${nestingLevel - 1}`; 43 } 44 45 window.addEventListener("message", function(e) { 46 if (e.data.entries) { 47 // This is a response from another frame, there's another listener that 48 // will forward it. 49 return; 50 } 51 let port = e.source; 52 if (!isLeaf) { 53 function respond(e) { 54 if (!e.data.entries) { 55 return; 56 } 57 port.postMessage(e.data, "*"); 58 window.removeEventListener("message", respond); 59 } 60 window.addEventListener("message", respond); 61 next.contentWindow.postMessage(e.data, "*"); 62 return; 63 } 64 let observer = new IntersectionObserver(function(entries) { 65 port.postMessage({ 66 entries: entries.map(e => { 67 return { 68 isIntersecting: e.isIntersecting, 69 intersectionRatio: e.intersectionRatio, 70 intersectionRect: e.intersectionRect, 71 boundingClientRect: e.boundingClientRect.toJSON(), 72 } 73 }), 74 }, "*") 75 observer.disconnect(); 76 }); 77 observer.observe(document.getElementById("target")); 78 }); 79 </script>