| <!DOCTYPE html> |
| <html> |
| <head> |
| <script src="../../resources/js-test.js"></script> |
| <script src="resources/svgtags.js"></script> |
| </head> |
| <body> |
| <div id="console"></div> |
| <div id="container" style="position: fixed;"></div> |
| |
| <script> |
| var svgNS = "http://www.w3.org/2000/svg"; |
| |
| function createNode(tag, container) { |
| var node = document.createElementNS(svgNS, tag); |
| container.appendChild(node); |
| return node; |
| } |
| |
| function createValidNode(tag, container, createAncestors) { |
| var realContainer = container; |
| |
| if (createAncestors && SvgTags[tag].needParent) |
| realContainer = createValidNode(SvgTags[tag].needParent, container, true); |
| |
| var node = createNode(tag, realContainer); |
| for (var attr in SvgTags[tag].needAttr) |
| node.setAttribute(attr, SvgTags[tag].needAttr[attr]); |
| |
| var requiredChildren = SvgTags[tag].needChild || []; |
| for (var childTag of requiredChildren) |
| createValidNode(childTag, node, false); |
| |
| return node; |
| } |
| |
| function expandClasses(tags) { |
| var expandedTags = []; |
| for (var tag of tags) |
| Array.prototype.push.apply(expandedTags, SvgTagClasses[tag] || [tag]); |
| return expandedTags; |
| } |
| |
| function createsRenderer(parentTag, childTag) { |
| var divContainer = document.getElementById('container'); |
| var svgContainer = createNode('svg', divContainer); |
| var parentNode = createValidNode(parentTag, svgContainer, true); |
| createValidNode(childTag, parentNode, false); |
| |
| var drt = internals.elementLayoutTreeAsText(divContainer); |
| divContainer.removeChild(svgContainer); |
| |
| // Skip 4 lines to get to the child tag subtree (layer, div, svg and parent). |
| var skip = 0; |
| for (var i = 0; i < 4; i++) |
| skip = drt.indexOf('\n', skip) + 1; |
| |
| return drt.substr(skip).search(new RegExp('\\{' + childTag + '\\}|\\[' + childTag + '[\\] ]')) > 0; |
| } |
| |
| function validateTag(tag, validChildren) { |
| var expandedValidChildren = expandClasses(validChildren); |
| var unexpectedValid = []; |
| var unexpectedInvalid = []; |
| |
| for (var childTag in SvgTags) { |
| // Only testing elements with renderers. |
| if (SvgTags[childTag].noRenderer) |
| continue; |
| |
| if (createsRenderer(tag, childTag)) { |
| if (expandedValidChildren.indexOf(childTag) < 0) |
| unexpectedValid.push(childTag); |
| } else { |
| if (expandedValidChildren.indexOf(childTag) >= 0) |
| unexpectedInvalid.push(childTag); |
| } |
| } |
| |
| var msg = '<' + tag + '>: '; |
| var passed = (unexpectedValid.length == 0 && unexpectedInvalid.length == 0); |
| if (passed) { |
| msg += '[' + validChildren + ']'; |
| testPassed(msg); |
| } else { |
| if (unexpectedValid.length > 0) |
| msg += 'unexpected valid [' + unexpectedValid + '] '; |
| if (unexpectedInvalid.length > 0) |
| msg += 'unexpected invalid [' + unexpectedInvalid + ']'; |
| testFailed(msg); |
| } |
| } |
| |
| |
| if (!window.testRunner || !window.internals) |
| testFailed('this test requires DumpRenderTree.'); |
| |
| description('This test validates renderer instantiation against the SVG content model.'); |
| |
| validateTag('filter', [ |
| // http://dev.w3.org/fxtf/filters/#FilterElement |
| 'CLASS_DESCRIPTIVE', 'CLASS_FILTER_PRIMITIVE', 'animate', 'set' |
| ]); |
| validateTag('linearGradient', [ |
| // https://svgwg.org/svg2-draft/pservers.html#LinearGradientElement |
| 'CLASS_DESCRIPTIVE', 'CLASS_PAINT_SERVER', 'animate', 'animateTransform', 'script', 'set', |
| 'stop' |
| ]); |
| validateTag('g', [ |
| // https://svgwg.org/svg2-draft/struct.html#GElement |
| 'CLASS_ANIMATION', 'CLASS_DESCRIPTIVE', 'CLASS_PAINT_SERVER', 'CLASS_SHAPE', |
| 'CLASS_STRUCTURAL', 'a', 'clipPath', 'cursor', 'filter', 'foreignObject', 'image', 'marker', |
| 'mask', 'script', 'style', 'switch', 'text', 'view' |
| ]); |
| validateTag('radialGradient', [ |
| // https://svgwg.org/svg2-draft/pservers.html#RadialGradientElement |
| 'CLASS_DESCRIPTIVE', 'CLASS_PAINT_SERVER', 'animate', 'animateTransform', 'script', 'set', |
| 'stop' |
| ]); |
| validateTag('svg', [ |
| // https://svgwg.org/svg2-draft/struct.html#SVGElement |
| 'CLASS_ANIMATION', 'CLASS_DESCRIPTIVE', 'CLASS_PAINT_SERVER', 'CLASS_SHAPE', |
| 'CLASS_STRUCTURAL', 'a', 'clipPath', 'cursor', 'filter', 'foreignObject', 'image', 'marker', |
| 'mask', 'script', 'style', 'switch', 'text', 'view' |
| ]); |
| </script> |
| </body> |
| </html> |