<!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>