cross-origin-subframe.html (4950B)
1 <!DOCTYPE html> 2 <div style="height: 200px; width: 100px;"></div> 3 <div id="target" style="background-color: green; width:100px; height:100px"></div> 4 <div id="empty-target" style="width: 100px"></div> 5 <div style="height: 200px; width: 100px;"></div> 6 7 <script> 8 var port; 9 var entries = []; 10 var target = document.getElementById("target"); 11 var emptyTarget = document.getElementById("empty-target"); 12 var scroller = document.scrollingElement; 13 var nextStep; 14 15 function clientRectToJson(rect) { 16 if (!rect) 17 return "null"; 18 return { 19 top: rect.top, 20 right: rect.right, 21 bottom: rect.bottom, 22 left: rect.left 23 }; 24 } 25 26 function entryToJson(entry) { 27 return { 28 boundingClientRect: clientRectToJson(entry.boundingClientRect), 29 intersectionRect: clientRectToJson(entry.intersectionRect), 30 rootBounds: clientRectToJson(entry.rootBounds), 31 isIntersecting: entry.isIntersecting, 32 target: entry.target === document.documentElement ? "html" : entry.target.id 33 }; 34 } 35 36 function boundingClientRectToJson(element) { 37 let r = element.getBoundingClientRect(); 38 return [r.left, r.right, r.top, r.bottom]; 39 } 40 41 // Note that we never use RAF in this code, because this frame might get render-throttled. 42 // Instead of RAF-ing, we just post an empty message to the parent window, which will 43 // RAF when it is received, and then send us a message to cause the next step to run. 44 45 // Use a rootMargin here, and verify it does NOT get applied for the cross-origin case. 46 var observer = new IntersectionObserver(function(changes) { 47 entries = entries.concat(changes) 48 }, { rootMargin: "7px" }); 49 observer.observe(target); 50 observer.observe(emptyTarget); 51 observer.observe(document.documentElement); 52 53 function step0() { 54 entries = entries.concat(observer.takeRecords()); 55 nextStep = step1; 56 var expected = [{ 57 boundingClientRect: [8, 108, 208, 308], 58 intersectionRect: [0, 0, 0, 0], 59 rootBounds: "null", 60 isIntersecting: false, 61 target: target.id 62 }, { 63 boundingClientRect: [8, 108, 308, 308], 64 intersectionRect: [0, 0, 0, 0], 65 rootBounds: "null", 66 isIntersecting: false, 67 target: emptyTarget.id 68 }, { 69 boundingClientRect: boundingClientRectToJson(document.documentElement), 70 intersectionRect: [0, 0, 0, 0], 71 rootBounds: "null", 72 isIntersecting: false, 73 target: "html" 74 }]; 75 port.postMessage({ 76 actual: entries.map(entryToJson), 77 expected: expected, 78 description: "First rAF" 79 }, "*"); 80 entries = []; 81 port.postMessage({scrollTo: 200}, "*"); 82 } 83 84 function step1() { 85 entries = entries.concat(observer.takeRecords()); 86 var client_rect = boundingClientRectToJson(document.documentElement); 87 // When the top document is scrolled all the way up, the iframe element is 88 // 108px below the scrolling viewport, and the iframe has a 2px border. When 89 // the top document is scrolled to y=200, the top 90px of the iframe's content 90 // is visible. 91 var expected = [{ 92 boundingClientRect: client_rect, 93 intersectionRect: client_rect.slice(0, 3).concat(90), 94 rootBounds: "null", 95 isIntersecting: true, 96 target: "html" 97 }]; 98 port.postMessage({ 99 actual: entries.map(entryToJson), 100 expected: expected, 101 description: "topDocument.scrollingElement.scrollTop = 200" 102 }, "*"); 103 entries = []; 104 scroller.scrollTop = 250; 105 nextStep = step2; 106 port.postMessage({}, "*"); 107 } 108 109 function step2() { 110 entries = entries.concat(observer.takeRecords()); 111 var expected = [{ 112 boundingClientRect: [8, 108, -42, 58], 113 intersectionRect: [8, 108, 0, 58], 114 rootBounds: "null", 115 isIntersecting: true, 116 target: target.id 117 }, { 118 boundingClientRect: [8, 108, 58, 58], 119 intersectionRect: [8, 108, 58, 58], 120 rootBounds: "null", 121 isIntersecting: true, 122 target: emptyTarget.id 123 }]; 124 port.postMessage({ 125 actual: entries.map(entryToJson), 126 expected: expected, 127 description: "iframeDocument.scrollingElement.scrollTop = 250" 128 }, "*"); 129 entries = []; 130 nextStep = step3; 131 port.postMessage({scrollTo: 100}, "*"); 132 } 133 134 function step3() { 135 entries = entries.concat(observer.takeRecords()); 136 var expected = [{ 137 boundingClientRect: [8, 108, -42, 58], 138 intersectionRect: [0, 0, 0, 0], 139 rootBounds: "null", 140 isIntersecting: false, 141 target: target.id 142 }, { 143 boundingClientRect: [8, 108, 58, 58], 144 intersectionRect: [0, 0, 0, 0], 145 rootBounds: "null", 146 isIntersecting: false, 147 target: emptyTarget.id 148 }, { 149 boundingClientRect: boundingClientRectToJson(document.documentElement), 150 intersectionRect: [0, 0, 0, 0], 151 rootBounds: "null", 152 isIntersecting: false, 153 target: "html" 154 }]; 155 port.postMessage({ 156 actual: entries.map(entryToJson), 157 expected: expected, 158 description: "topDocument.scrollingElement.scrollTop = 100" 159 }, "*"); 160 port.postMessage({DONE: 1}, "*"); 161 } 162 163 function handleMessage(event) 164 { 165 port = event.source; 166 nextStep(); 167 } 168 169 nextStep = step0; 170 window.addEventListener("message", handleMessage); 171 </script>