| <!doctype html> | |
| <meta name="timeout" content="long"> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <script src="/common/utils.js"></script> | |
| <script src="/preload/resources/preload_helper.js"></script> | |
| <body> | |
| <script> | |
| ['attached', 'detacted'].forEach(state => | |
| promise_test(async t => { | |
| const href = '/common/square.png'; | |
| const sequence = []; | |
| const name = `with-preload-${state}`; | |
| const loaded = new Promise(resolveLoad => { | |
| customElements.define(name, class extends HTMLElement { | |
| constructor() { | |
| super(); | |
| const shadow = this.attachShadow({ mode: "closed" }); | |
| const link = document.createElement('link'); | |
| link.rel = 'preload'; | |
| link.as = 'image'; | |
| link.href = href; | |
| if (state === 'attached') | |
| shadow.appendChild(link); | |
| sequence.push('constructed'); | |
| link.addEventListener('load', () => { | |
| sequence.push('loaded'); | |
| resolveLoad(); | |
| }); | |
| } | |
| connectedCallback() { | |
| sequence.push('connected'); | |
| } | |
| }); | |
| }); | |
| const wrapper = document.createElement(name); | |
| const timeout = 500; | |
| await new Promise(resolve => t.step_timeout(resolve, timeout)); | |
| document.body.appendChild(wrapper); | |
| await Promise.any([loaded, new Promise(resolve => t.step_timeout(() => { | |
| sequence.push('timeout'); | |
| resolve(); | |
| }, timeout))]); | |
| assert_array_equals(sequence, ['constructed', 'connected', state === 'attached' ? 'loaded' : 'timeout']); | |
| }, `preload link should ${state === 'attached' ? 'be fetched when attached' : 'note fetched when detached from'} a shadow DOM`)); | |
| promise_test(async t => { | |
| const href = '/common/square.png'; | |
| const doc = document.implementation.createHTMLDocument(); | |
| const link = doc.createElement('link'); | |
| link.rel = 'preload'; | |
| link.as = 'image'; | |
| link.href = href; | |
| const loaded = new Promise(resolve => link.addEventListener('load', () => resolve('loaded'))); | |
| const timeoutMillis = 1000; | |
| const timeout = new Promise(resolve => t.step_timeout(() => resolve('timeout'), timeoutMillis)); | |
| doc.head.appendChild(link); | |
| const result = await Promise.any([loaded, timeout]); | |
| assert_equals(result, 'timeout'); | |
| }, 'preload links only work for documents within browsing contexts'); | |
| promise_test(async t => { | |
| const href = '/common/square.png'; | |
| const fragment = document.createDocumentFragment(); | |
| const link = document.createElement('link'); | |
| link.rel = 'preload'; | |
| link.as = 'image'; | |
| link.href = href; | |
| fragment.appendChild(link); | |
| const timeoutMillis = 1000; | |
| let didLoad = false; | |
| const loaded = new Promise(resolve => link.addEventListener('load', () => { | |
| resolve('loaded'); | |
| didLoad = true; | |
| })); | |
| const timeout = () => new Promise(resolve => t.step_timeout(() => resolve('timeout'), timeoutMillis)); | |
| await timeout(); | |
| assert_false(didLoad, 'Loaded prematurely, fragment not connected to document yet'); | |
| document.head.appendChild(link); | |
| await Promise.any([loaded, timeout()]); | |
| assert_true(didLoad); | |
| }, 'preload links from DocumentFragment only work when attached'); | |
| promise_test(async t => { | |
| const href = '/common/square.png'; | |
| const link = document.createElement('link'); | |
| link.rel = 'preload'; | |
| link.as = 'image'; | |
| link.href = href; | |
| const loaded = new Promise(resolve => link.addEventListener('load', () => resolve('loaded'))); | |
| const timeoutMillis = 1000; | |
| const timeout = new Promise(resolve => t.step_timeout(() => resolve('timeout'), timeoutMillis)); | |
| const result = await Promise.any([loaded, timeout]); | |
| assert_equals(result, 'timeout'); | |
| }, 'preload links only work when attached to the document'); | |
| </script> | |
| </body> |