| <!DOCTYPE html> |
| <script src="../../resources/js-test.js"></script> |
| <body> |
| <script> |
| var container, child, otherFrame; |
| var testNumber = 0; |
| |
| description("This tests invalidation of :lang selectors when the document element's lang attribute changes and a descendant element is using the 'explicit language matching document element language' optimization"); |
| |
| function matchedLang(element) { |
| for (let lang of ["en", "de", "zh"]) { |
| if (element.matches(`:lang(${lang})`)) |
| return lang; |
| } |
| return ""; |
| } |
| |
| function shouldMatchLang(elementName, lang) { |
| shouldBe(`matchedLang(${elementName})`, `"${lang}"`); |
| } |
| |
| function test(f) { |
| document.documentElement.lang = "en"; |
| f(); |
| container = null; |
| child = null; |
| debug("----"); |
| } |
| |
| function testWithOtherDocument(f) { |
| test(function() { |
| otherFrame = document.createElement("iframe"); |
| otherFrame.srcdoc = "<!DOCTYPE html><html lang=en><body>"; |
| document.body.append(otherFrame); |
| f(); |
| otherFrame.remove(); |
| otherFrame = null; |
| }); |
| } |
| |
| function makeContainer() { |
| container = document.createElement("div"); |
| return container; |
| } |
| |
| function makeChild() { |
| child = document.createElement("div"); |
| return child; |
| } |
| |
| function makeContainerWithChild() { |
| container = document.createElement("div"); |
| child = document.createElement("div"); |
| container.append(child); |
| return container; |
| } |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| document.documentElement.lang = "de"; |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| document.documentElement.lang = "de"; |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| document.documentElement.lang = "de"; |
| container.lang = "de"; |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| document.documentElement.lang = "de"; |
| container.lang = "de"; |
| document.documentElement.lang = "zh"; |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| document.documentElement.lang = "de"; |
| container.removeAttribute("lang"); |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| container.remove(); |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "de"; |
| container.remove(); |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainer()); |
| container.lang = "en"; |
| container.append(makeChild()); |
| shouldMatchLang("child", "en"); |
| container.remove(); |
| }); |
| |
| test(function() { |
| document.body.append(makeContainer()); |
| container.lang = "de"; |
| makeChild(); |
| child.lang = "en"; |
| container.append(child); |
| shouldMatchLang("child", "en"); |
| container.remove(); |
| }); |
| |
| testWithOtherDocument(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| otherFrame.contentDocument.body.append(container); |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| }); |
| |
| testWithOtherDocument(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "de"; |
| otherFrame.contentDocument.body.append(container); |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| }); |
| |
| testWithOtherDocument(function() { |
| document.body.append(makeContainerWithChild()); |
| otherFrame.contentDocument.body.append(container); |
| otherFrame.contentDocument.documentElement.lang = "de"; |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| }); |
| |
| testWithOtherDocument(function() { |
| document.body.append(makeContainerWithChild()); |
| container.lang = "en"; |
| otherFrame.contentDocument.body.append(container); |
| otherFrame.contentDocument.documentElement.lang = "de"; |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| }); |
| |
| test(function() { |
| makeContainerWithChild(); |
| shouldMatchLang("container", ""); |
| shouldMatchLang("child", ""); |
| }); |
| |
| test(function() { |
| makeContainerWithChild(); |
| container.lang = "en"; |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| }); |
| |
| testWithOtherDocument(function() { |
| otherFrame.contentDocument.documentElement.lang = "de"; |
| makeContainerWithChild(); |
| container.lang = "en"; |
| otherFrame.contentDocument.adoptNode(container); |
| shouldMatchLang("container", "en"); |
| shouldMatchLang("child", "en"); |
| }); |
| |
| test(function() { |
| makeContainer(); |
| container.lang = "de"; |
| document.documentElement.append(container); |
| container.removeAttribute("lang"); |
| shouldMatchLang("container", "en"); |
| }); |
| |
| testWithOtherDocument(function() { |
| container = otherFrame.contentDocument.documentElement; |
| container.removeAttribute("lang"); |
| container.remove(); |
| shouldMatchLang("container", ""); |
| }); |
| |
| testWithOtherDocument(function() { |
| otherFrame.contentDocument.documentElement.lang = "de"; |
| makeContainerWithChild(); |
| otherFrame.contentDocument.body.append(container); |
| container.lang = "de"; |
| otherFrame.contentDocument.documentElement.remove(); |
| let newRoot = document.createElement("html"); |
| otherFrame.contentDocument.append(newRoot); |
| newRoot.lang = "zh"; |
| shouldMatchLang("container", "de"); |
| shouldMatchLang("child", "de"); |
| }); |
| |
| testWithOtherDocument(function() { |
| otherFrame.contentDocument.documentElement.lang = "de"; |
| otherFrame.contentDocument.documentElement.remove(); |
| makeContainerWithChild(); |
| container.lang = "zh"; |
| otherFrame.contentDocument.append(container); |
| shouldMatchLang("container", "zh"); |
| shouldMatchLang("child", "zh"); |
| }); |
| |
| testWithOtherDocument(function() { |
| container = otherFrame.contentDocument.documentElement; |
| container.lang = "de"; |
| container.remove(); |
| shouldMatchLang("container", "de"); |
| }); |
| </script> |