diff options
Diffstat (limited to 'testing/web-platform/tests/resource-timing/resources/resource-loaders.js')
-rw-r--r-- | testing/web-platform/tests/resource-timing/resources/resource-loaders.js | 174 |
1 files changed, 174 insertions, 0 deletions
diff --git a/testing/web-platform/tests/resource-timing/resources/resource-loaders.js b/testing/web-platform/tests/resource-timing/resources/resource-loaders.js new file mode 100644 index 0000000000..37fea16b17 --- /dev/null +++ b/testing/web-platform/tests/resource-timing/resources/resource-loaders.js @@ -0,0 +1,174 @@ +const load = { + + cache_bust: path => { + let url = new URL(path, location.origin); + url.href += (url.href.includes("?")) ? '&' : '?'; + // The `Number` type in Javascript, when interpreted as an integer, can only + // safely represent [-2^53 + 1, 2^53 - 1] without the loss of precision [1]. + // We do not generate a global value and increment from it, as the increment + // might not have enough precision to be reflected. + // + // [1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number + url.href += "unique=" + Math.random().toString().substring(2); + return url.href; + }, + + image_with_attrs: async (path, attribute_map) => { + return new Promise(resolve => { + const img = new Image(); + for (const key in attribute_map) + img[key] = attribute_map[key]; + img.onload = img.onerror = resolve; + img.src = load.cache_bust(path); + }); + }, + + // Returns a promise that settles once the given path has been fetched as an + // image resource. + image: path => { + return load.image_with_attrs(path, undefined); + }, + + // Returns a promise that settles once the given path has been fetched as an + // image resource. + image_cors: path => load.image_with_attrs(path, {crossOrigin: "anonymous"}), + + // Returns a promise that settles once the given path has been fetched as a + // font resource. + font: path => { + const div = document.createElement('div'); + div.innerHTML = ` + <style> + @font-face { + font-family: ahem; + src: url('${load.cache_bust(path)}'); + } + </style> + <div style="font-family: ahem;">This fetches ahem font.</div> + `; + document.body.appendChild(div); + return document.fonts.ready.then(() => { + document.body.removeChild(div); + }); + }, + + stylesheet_with_attrs: async (path, attribute_map) => { + const link = document.createElement("link"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + link[key] = value; + } + } + link.rel = "stylesheet"; + link.type = "text/css"; + link.href = load.cache_bust(path); + + const loaded = new Promise(resolve => { + link.onload = link.onerror = resolve; + }); + + document.head.appendChild(link); + await loaded; + document.head.removeChild(link); + }, + + // Returns a promise that settles once the given path has been fetched as a + // stylesheet resource. + stylesheet: async path => { + return load.stylesheet_with_attrs(path, undefined); + }, + + iframe_with_attrs: async (path, attribute_map, validator, skip_wait_for_navigation) => { + const frame = document.createElement("iframe"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + frame[key] = value; + } + } + const loaded = new Promise(resolve => { + frame.onload = frame.onerror = resolve; + }); + frame.src = load.cache_bust(path); + document.body.appendChild(frame); + if ( !skip_wait_for_navigation ) { + await loaded; + } + if (validator instanceof Function) { + validator(frame); + } + // since we skipped the wait for load animation, we cannot + // remove the iframe here since the request could get cancelled + if ( !skip_wait_for_navigation ) { + document.body.removeChild(frame); + } + }, + + // Returns a promise that settles once the given path has been fetched as an + // iframe. + iframe: async (path, validator) => { + return load.iframe_with_attrs(path, undefined, validator); + }, + + script_with_attrs: async (path, attribute_map) => { + const script = document.createElement("script"); + if (attribute_map instanceof Object) { + for (const [key, value] of Object.entries(attribute_map)) { + script[key] = value; + } + } + const loaded = new Promise(resolve => { + script.onload = script.onerror = resolve; + }); + script.src = load.cache_bust(path); + document.body.appendChild(script); + await loaded; + document.body.removeChild(script); + }, + + // Returns a promise that settles once the given path has been fetched as a + // script. + script: async path => { + return load.script_with_attrs(path, undefined); + }, + + // Returns a promise that settles once the given path has been fetched as an + // object. + object: async (path, type) => { + const object = document.createElement("object"); + const object_load_settled = new Promise(resolve => { + object.onload = object.onerror = resolve; + }); + object.data = load.cache_bust(path); + if (type) { + object.type = type; + } + document.body.appendChild(object); + await await_with_timeout(2000, + "Timeout was reached before load or error events fired", + object_load_settled, + () => { document.body.removeChild(object) } + ); + }, + + // Returns a promise that settles once the given path has been fetched + // through a synchronous XMLHttpRequest. + xhr_sync: async (path, headers) => { + const xhr = new XMLHttpRequest; + xhr.open("GET", path, /* async = */ false); + if (headers instanceof Object) { + for (const [key, value] of Object.entries(headers)) { + xhr.setRequestHeader(key, value); + } + } + xhr.send(); + }, + + xhr_async: path => { + const xhr = new XMLHttpRequest(); + xhr.open("GET", path) + xhr.send(); + return new Promise(resolve => { + xhr.onload = xhr.onerror = resolve; + }); + } +}; |