| <!DOCTYPE html> | |
| <head> | |
| <meta charset="utf-8" /> | |
| <title>This test validates the render blocking status of resources.</title> | |
| <link rel="help" href="https://www.w3.org/TR/resource-timing-2/#sec-performanceresourcetiming"/> | |
| <script src="/resources/testharness.js"></script> | |
| <script src="/resources/testharnessreport.js"></script> | |
| <!-- Start of test cases --> | |
| <script src="resources/empty_script.js?script-head"></script> | |
| <script type="module" src="resources/empty_script.js?script-head-module"></script> | |
| <script async type=module | |
| src="resources/empty_script.js?script-head-async-module"> | |
| </script> | |
| <script async src="resources/empty_script.js?script-head-async"></script> | |
| <script defer src="resources/empty_script.js?script-head-defer"></script> | |
| <script blocking=render | |
| src="resources/empty_script.js?script-head-blocking-render"> | |
| </script> | |
| <script async blocking=render | |
| src="resources/empty_script.js?script-head-async-blocking-render"> | |
| </script> | |
| <script type=module blocking=render | |
| src="resources/empty_script.js?script-head-module-blocking-render"> | |
| </script> | |
| <script async type=module blocking=render | |
| src="resources/empty_script.js?script-head-async-module-blocking-render"> | |
| </script> | |
| <script defer blocking=render | |
| src="resources/empty_script.js?script-head-defer-blocking-render"> | |
| </script> | |
| <script id="script-head-remove-attr" blocking=render | |
| src="resources/empty_script.js?script-head-blocking-render-remove-attr"> | |
| </script> | |
| <script> | |
| document.write(` | |
| <script defer | |
| src="resources/empty_script.js?script-head-defer-dynamic-docwrite"> | |
| <\/script>`); | |
| </script> | |
| </head> | |
| <body> | |
| <script src="resources/empty_script.js?script-body"></script> | |
| <script type="module" src="resources/empty_script.js?script-body-module"></script> | |
| <script async type=module | |
| src="resources/empty_script.js?script-body-async-module"> | |
| </script> | |
| <script async src="resources/empty_script.js?script-body-async"></script> | |
| <script defer src="resources/empty_script.js?script-body-defer"></script> | |
| <script> | |
| const script = document.createElement("script"); | |
| script.src = "resources/empty_script.js?script-head-dynamic-dom"; | |
| document.head.appendChild(script); | |
| // Dynamic explicitly async script | |
| const async_script = document.createElement("script"); | |
| async_script.src = "resources/empty_script.js?script-head-async-dynamic-dom"; | |
| async_script.async = true; | |
| document.head.appendChild(async_script); | |
| // Dynamic non-async script | |
| // https://html.spec.whatwg.org/multipage/scripting.html#script-processing-model | |
| // mentions that a script element has to be parser-inserted to be | |
| // implicitly potentially render-blocking | |
| const non_async_script = document.createElement("script"); | |
| non_async_script.src = "resources/empty_script.js?script-head-non-async-dynamic-dom"; | |
| non_async_script.async = false; | |
| document.head.appendChild(non_async_script); | |
| // Dynamic defer script | |
| const defer_script = document.createElement("script"); | |
| defer_script.src = "resources/empty_script.js?script-head-defer-dynamic-dom"; | |
| defer_script.defer = true; | |
| document.head.appendChild(defer_script); | |
| // Dynamic explicitly render-blocking script | |
| const blocking_script = document.createElement("script"); | |
| blocking_script.src = "resources/empty_script.js?script-head-blocking-render-dynamic-dom"; | |
| blocking_script.blocking = "render"; | |
| document.head.appendChild(blocking_script); | |
| // Dynamic explicitly render-blocking module script | |
| const blocking_module_script = document.createElement("script"); | |
| blocking_module_script.src = "resources/empty_script.js?script-head-module-blocking-render-dynamic-dom"; | |
| blocking_module_script.type = "module"; | |
| blocking_module_script.blocking = "render"; | |
| document.head.appendChild(blocking_module_script); | |
| // Dynamic async module script | |
| const async_module_script = document.createElement("script"); | |
| async_module_script.src = "resources/empty_script.js?script-head-async-module-dynamic-dom"; | |
| async_module_script.type = "module"; | |
| async_module_script.async = true; | |
| document.head.appendChild(async_module_script); | |
| // Dynamic async render-blocking module script | |
| const async_blocking_module_script = document.createElement("script"); | |
| async_blocking_module_script.src = "resources/empty_script.js?script-head-async-module-blocking-render-dynamic-dom"; | |
| async_blocking_module_script.type = "module"; | |
| async_blocking_module_script.async = true; | |
| async_blocking_module_script.blocking = "render" | |
| document.head.appendChild(async_blocking_module_script); | |
| // Add a module that imports more modules | |
| const importer_script = document.createElement("script"); | |
| importer_script.src = "resources/fake_responses.py?url=importer.js"; | |
| importer_script.type = "module"; | |
| document.head.appendChild(importer_script); | |
| // Add an async module that imports more modules | |
| const importer_async_script = document.createElement("script"); | |
| importer_async_script.src = "resources/fake_responses.py?url=importer_async.js"; | |
| importer_async_script.type = "module"; | |
| importer_async_script.async = true; | |
| document.head.appendChild(importer_async_script); | |
| // Removing blocking render attribute after request is made | |
| const script_element = document.getElementById("script-head-remove-attr"); | |
| script_element.blocking = ""; | |
| </script> | |
| <script> | |
| const wait_for_onload = () => { | |
| return new Promise(resolve => { | |
| window.addEventListener("load", resolve); | |
| })}; | |
| promise_test( | |
| async () => { | |
| const expectedRenderBlockingStatus = { | |
| 'script-head': 'blocking', | |
| 'script-head-module' : 'non-blocking', | |
| 'script-head-async-module' : 'non-blocking', | |
| 'script-head-async' : 'non-blocking', | |
| 'script-head-defer' : 'non-blocking', | |
| 'script-head-blocking-render' : 'blocking', | |
| 'script-head-async-blocking-render' : 'blocking', | |
| 'script-head-module-blocking-render' : 'blocking', | |
| 'script-head-async-module-blocking-render' : 'blocking', | |
| 'script-head-defer-blocking-render' : 'blocking', | |
| 'script-head-blocking-render-remove-attr' : 'blocking', | |
| 'script-head-defer-dynamic-docwrite' : 'non-blocking', | |
| 'script-body' : 'non-blocking', | |
| 'script-body-module' : 'non-blocking', | |
| 'script-body-async-module' : 'non-blocking', | |
| 'script-body-async' : 'non-blocking', | |
| 'script-body-defer' : 'non-blocking', | |
| 'script-head-dynamic-dom': 'non-blocking', | |
| 'script-head-async-dynamic-dom' : 'non-blocking', | |
| 'script-head-non-async-dynamic-dom': 'non-blocking', | |
| 'script-head-defer-dynamic-dom' : 'non-blocking', | |
| 'script-head-blocking-render-dynamic-dom' : 'blocking', | |
| 'script-head-module-blocking-render-dynamic-dom' : 'blocking', | |
| 'script-head-async-module-dynamic-dom' : 'non-blocking', | |
| 'script-head-async-module-blocking-render-dynamic-dom' : 'blocking', | |
| 'script-head-import-defer' : 'non-blocking', | |
| 'script-head-import-defer-dynamic' : 'non-blocking', | |
| 'script-head-import-async' : 'non-blocking', | |
| 'script-head-import-async-dynamic' : 'non-blocking', | |
| 'script-importer' : 'non-blocking', | |
| 'script-importer-async' : 'non-blocking' | |
| }; | |
| await wait_for_onload(); | |
| const entry_list = performance.getEntriesByType("resource"); | |
| for (entry of entry_list) { | |
| if (entry.name.includes("empty_script.js")) { | |
| key = entry.name.split("?").pop(); | |
| expectedStatus = expectedRenderBlockingStatus[key]; | |
| assert_equals(entry.renderBlockingStatus, expectedStatus, | |
| `render blocking status for ${entry.name} should be ${expectedStatus}`); | |
| } | |
| else if (entry.name.includes("importer.js")){ | |
| key = 'script-importer'; | |
| expectedStatus = expectedRenderBlockingStatus[key]; | |
| assert_equals(entry.renderBlockingStatus, expectedStatus, | |
| `render blocking status for ${entry.name} should be ${expectedStatus}`); | |
| } | |
| else if (entry.name.includes("importer_async.js")){ | |
| key = 'script-importer-async'; | |
| expectedStatus = expectedRenderBlockingStatus[key]; | |
| assert_equals(entry.renderBlockingStatus, expectedStatus, | |
| `render blocking status for ${entry.name} should be ${expectedStatus}`); | |
| } | |
| } | |
| }, "Validate render blocking status of script resources in PerformanceResourceTiming"); | |
| </script> |