| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../resources/js-test-pre.js"></script> |
| <style> |
| * { |
| color: black; |
| } |
| [myattr] target { |
| color: rgb(1, 0, 0); |
| } |
| |
| [myattr=value2] > inert target { |
| color: rgb(2, 0, 0); |
| } |
| |
| [myattr~=value3] inert + target { |
| color: rgb(3, 0, 0); |
| } |
| |
| [MYATTR|=value4] inert ~ target { |
| color: rgb(4, 0, 0); |
| } |
| |
| [myAttr^=value5] target { |
| color: rgb(5, 0, 0); |
| } |
| |
| [myattr$=value6] target { |
| color: rgb(6, 0, 0); |
| } |
| |
| [myATTR*=value7] target { |
| color: rgb(7, 0, 0); |
| } |
| |
| [myattr*=vaLUE8 i] target { |
| color: rgb(8, 0, 0); |
| } |
| |
| [myattr2] > target { |
| color: rgb(9, 0, 0); |
| } |
| |
| root:not([mynotattr]) target { |
| color: rgb(10, 0, 0); |
| } |
| |
| [myattr=value11] target { |
| color: rgb(11, 0, 0); |
| } |
| |
| [myattr3] notarget { |
| color: rgb(99, 0, 0); |
| } |
| |
| </style> |
| </head> |
| <body> |
| <root> |
| <!-- With renderer --> |
| <inert> |
| <inert> |
| <inert></inert> |
| <target> |
| <inert></inert> |
| <target></target> |
| </target> |
| </inert> |
| <target></target> |
| <inert></inert> |
| </inert> |
| </root> |
| <root style="display:none;"> |
| <!-- Without renderer --> |
| <inert> |
| <inert> |
| <inert></inert> |
| <target> |
| <inert></inert> |
| <target></target> |
| </target> |
| </inert> |
| <target></target> |
| <inert></inert> |
| </inert> |
| </root> |
| </body> |
| <script> |
| |
| description('Test that we invalidate the element subtree minimally on attribute change'); |
| |
| function testStyleChangeType(tag, type) |
| { |
| var elements = document.querySelectorAll(tag); |
| for (var i = 0; i < elements.length; ++i) { |
| if (window.internals.styleChangeType(elements[i]) != type) |
| return false; |
| } |
| return true; |
| } |
| |
| function testStyleInvalidation(expectedDescendantStyleChange) { |
| // Ideally we would't invalidate the root at all. |
| shouldBeTrue('testStyleChangeType("root", "NoStyleChange") || testStyleChangeType("root", "InlineStyleChange")'); |
| |
| shouldBeTrue('testStyleChangeType("target", "' + expectedDescendantStyleChange +'")'); |
| |
| shouldBeTrue('testStyleChangeType("inert", "NoStyleChange")'); |
| } |
| |
| function setAttribute(name, value) { |
| debug("Setting attribute '" + name + "' value '" + value + "'"); |
| var allRoots = document.querySelectorAll("root"); |
| allRoots[0].setAttribute(name, value); |
| allRoots[1].setAttribute(name, value); |
| } |
| |
| function removeAttribute(name) { |
| debug("Removing attribute '" + name + "'"); |
| var allRoots = document.querySelectorAll("root"); |
| allRoots[0].removeAttribute(name); |
| allRoots[1].removeAttribute(name); |
| } |
| |
| function checkStyle(n) { |
| document.documentElement.offsetTop; |
| |
| hasExpectedStyle = true; |
| expectedColor = 'rgb('+n+', 0, 0)'; |
| var targets = document.querySelectorAll("target"); |
| for (var i = 0; i < targets.length; ++i) { |
| hasExpectedStyle = getComputedStyle(targets[i]).color == expectedColor; |
| if (!hasExpectedStyle) |
| break; |
| } |
| shouldBeTrue("hasExpectedStyle"); |
| } |
| |
| setAttribute('mynotattr', ''); |
| |
| checkStyle(0); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(0); |
| |
| setAttribute('myattr', ''); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'value2'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(2); |
| |
| setAttribute('myattr', 'foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| removeAttribute('myattr'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(0); |
| |
| setAttribute('myattr', 'value3'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(3); |
| |
| setAttribute('myattr', 'dummy value3'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(3); |
| |
| setAttribute('myattr', 'value4-foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(4); |
| |
| setAttribute('myattr', 'value4-foobar'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(4); |
| |
| setAttribute('myattr', 'dummy value4-foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'value5foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(5); |
| |
| setAttribute('myattr', 'value5foobar'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(5); |
| |
| setAttribute('myattr', 'foovalue5'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'foovalue6'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(6); |
| |
| setAttribute('myAttr', 'foobarvalue6'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(6); |
| |
| setAttribute('MYATTR', 'value6foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'value7'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(7); |
| |
| setAttribute('myattr', 'value7foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(7); |
| |
| setAttribute('myATTR', 'foovalue7foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(7); |
| |
| setAttribute('myattr', 'VALUE7foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'Value8'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(8); |
| |
| setAttribute('myattr', 'value8foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(8); |
| |
| setAttribute('myATTR', 'FOOVALue8foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(8); |
| |
| setAttribute('myattr', 'VALUE8foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(8); |
| |
| setAttribute('myattr', 'VALUE 8foo'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr2', ''); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr2', 'foo'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(1); |
| |
| removeAttribute('mynotattr'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(10); |
| |
| setAttribute('mynotattr', 'value'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(1); |
| |
| setAttribute('myattr', 'value11'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(11); |
| |
| setAttribute('myattr3', ''); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(11); |
| |
| removeAttribute('myattr3'); |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(11); |
| |
| var dynamicSheet = document.createElement("style"); |
| dynamicSheet.innerHTML = "[myattr3] target { color:rgb(12, 0, 0); }" |
| debug("Inserting stylesheet '" + dynamicSheet.innerHTML + "'"); |
| document.head.appendChild(dynamicSheet); |
| |
| testStyleInvalidation("NoStyleChange"); |
| checkStyle(11); |
| |
| setAttribute('myattr3', ''); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(12); |
| |
| removeAttribute('myattr3'); |
| testStyleInvalidation("InlineStyleChange"); |
| checkStyle(11); |
| |
| </script> |
| <script src="../../resources/js-test-post.js"></script> |
| </html> |