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