function test_frame_timing_before_load_event(type) { promise_test(async t => { const {document, performance} = type === 'frame' ? window.parent : window; const delay = 500; const frame = document.createElement(type); t.add_cleanup(() => frame.remove()); await new Promise(resolve => { frame.addEventListener('load', resolve); frame.src = `/resource-timing/resources/iframe-with-delay.sub.html?delay=${delay}`; (type === 'frame' ? document.querySelector('frameset') : document.body).appendChild(frame); }); const entries = performance.getEntriesByName(frame.src); const navigationEntry = frame.contentWindow.performance.getEntriesByType('navigation')[0]; assert_equals(entries.length, 1); assert_equals(entries[0].initiatorType, type); assert_greater_than(performance.now(), entries[0].responseEnd + delay); const domContentLoadedEventAbsoluteTime = navigationEntry.domContentLoadedEventStart + frame.contentWindow.performance.timeOrigin; const frameResponseEndAbsoluteTime = entries[0].responseEnd + performance.timeOrigin; assert_greater_than(domContentLoadedEventAbsoluteTime, frameResponseEndAbsoluteTime); }, `A ${type} should report its RT entry when the response is done and before it is completely loaded`); } function test_frame_timing_change_src(type, origin1 = document.origin, origin2 = document.origin, tao = false, label = '') { const uid = token(); promise_test(async t => { const {document, performance} = type === 'frame' ? window.parent : window; const frame = document.createElement(type); t.add_cleanup(() => frame.remove()); function createURL(origin) { const url = new URL(`${origin}/resource-timing/resources/green.html`, location.href); url.searchParams.set("uid", uid); if (tao) url.searchParams.set("pipe", "header(Timing-Allow-Origin, *)"); return url.toString(); } await new Promise(resolve => { const done = () => { resolve(); frame.removeEventListener('load', done); } frame.addEventListener('load', done); frame.src = createURL(origin1); const root = type === 'frame' ? document.querySelector('frameset') : document.body; root.appendChild(frame); }); await new Promise(resolve => { frame.addEventListener('load', resolve); frame.src = createURL(origin2); }); const entries = performance.getEntries().filter(e => e.name.includes(uid)); assert_equals(entries.length, 2); }, label || `A ${type} should report separate RT entries if its src changed from the outside`); }