browser_inspector-anonymous.js (6375B)
1 /* Any copyright is dedicated to the Public Domain. 2 http://creativecommons.org/publicdomain/zero/1.0/ */ 3 4 "use strict"; 5 6 // Test for Bug 777674 7 8 add_task(async function () { 9 await SpecialPowers.pushPermissions([ 10 { type: "allowXULXBL", allow: true, context: MAIN_DOMAIN_HTTPS }, 11 ]); 12 13 const { walker } = await initInspectorFront( 14 MAIN_DOMAIN_HTTPS + "inspector-traversal-data.html" 15 ); 16 17 await testXBLAnonymousInHTMLDocument(walker); 18 await testNativeAnonymous(walker); 19 await testNativeAnonymousStartingNode(walker); 20 21 await testPseudoElements(walker); 22 await testEmptyWithPseudo(walker); 23 await testShadowAnonymous(walker); 24 }); 25 26 async function testXBLAnonymousInHTMLDocument(walker) { 27 info("Testing XBL anonymous in an HTML document."); 28 await SpecialPowers.spawn(gBrowser.selectedBrowser, [], function () { 29 const XUL_NS = 30 "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; 31 const rawToolbarbutton = content.document.createElementNS( 32 XUL_NS, 33 "toolbarbutton" 34 ); 35 content.document.documentElement.appendChild(rawToolbarbutton); 36 }); 37 38 const toolbarbutton = await walker.querySelector( 39 walker.rootNode, 40 "toolbarbutton" 41 ); 42 const children = await walker.children(toolbarbutton); 43 44 is(toolbarbutton.numChildren, 0, "XBL content is not visible in HTML doc"); 45 is(children.nodes.length, 0, "XBL content is not returned in HTML doc"); 46 } 47 48 async function testNativeAnonymous(walker) { 49 info("Testing native anonymous content with walker."); 50 51 const select = await walker.querySelector(walker.rootNode, "select"); 52 const children = await walker.children(select); 53 54 is(select.numChildren, 2, "No native anon content for form control"); 55 is(children.nodes.length, 2, "No native anon content for form control"); 56 } 57 58 async function testNativeAnonymousStartingNode(walker) { 59 info("Tests attaching an element that a walker can't see."); 60 61 await SpecialPowers.spawn( 62 gBrowser.selectedBrowser, 63 [[walker.actorID]], 64 async function (actorID) { 65 const { require } = ChromeUtils.importESModule( 66 "resource://devtools/shared/loader/Loader.sys.mjs" 67 ); 68 const { 69 DevToolsServer, 70 } = require("resource://devtools/server/devtools-server.js"); 71 72 const { 73 DocumentWalker, 74 } = require("resource://devtools/server/actors/inspector/document-walker.js"); 75 const nodeFilterConstants = require("resource://devtools/shared/dom-node-filter-constants.js"); 76 77 const docwalker = new DocumentWalker( 78 content.document.querySelector("select"), 79 content, 80 { 81 filter: () => { 82 return nodeFilterConstants.FILTER_ACCEPT; 83 }, 84 } 85 ); 86 const scrollbar = docwalker.lastChild(); 87 is(scrollbar.tagName, "scrollbar", "An anonymous child has been fetched"); 88 89 // Convert actorID to current compartment string otherwise 90 // searchAllConnectionsForActor is confused and won't find the actor. 91 actorID = String(actorID); 92 const serverWalker = DevToolsServer.searchAllConnectionsForActor(actorID); 93 const node = await serverWalker.attachElement(scrollbar); 94 95 ok(node, "A response has arrived"); 96 ok(node.node, "A node is in the response"); 97 is( 98 node.node.rawNode.tagName, 99 "SELECT", 100 "The node has changed to a parent that the walker recognizes" 101 ); 102 } 103 ); 104 } 105 106 async function testPseudoElements(walker) { 107 info("Testing pseudo elements with walker."); 108 109 // Markup looks like: <div><::before /><span /><::after /></div> 110 const pseudo = await walker.querySelector(walker.rootNode, "#pseudo"); 111 const children = await walker.children(pseudo); 112 113 is( 114 pseudo.numChildren, 115 1, 116 "::before/::after are not counted if there is a child" 117 ); 118 is(children.nodes.length, 3, "Correct number of children"); 119 120 const before = children.nodes[0]; 121 ok(before.isNativeAnonymous, "Child is native anonymous"); 122 123 const span = children.nodes[1]; 124 ok(!span.isNativeAnonymous, "Child is not anonymous"); 125 126 const after = children.nodes[2]; 127 ok(after.isNativeAnonymous, "Child is native anonymous"); 128 } 129 130 async function testEmptyWithPseudo(walker) { 131 info("Testing elements with no childrent, except for pseudos."); 132 133 info("Checking an element whose only child is a pseudo element"); 134 const pseudo = await walker.querySelector(walker.rootNode, "#pseudo-empty"); 135 const children = await walker.children(pseudo); 136 137 is( 138 pseudo.numChildren, 139 1, 140 "::before/::after are is counted if there are no other children" 141 ); 142 is(children.nodes.length, 1, "Correct number of children"); 143 144 const before = children.nodes[0]; 145 ok(before.isNativeAnonymous, "Child is native anonymous"); 146 } 147 148 async function testShadowAnonymous(walker) { 149 info("Testing shadow DOM content."); 150 151 const host = await walker.querySelector(walker.rootNode, "#shadow"); 152 const children = await walker.children(host); 153 154 // #shadow-root, ::before, light dom 155 is(host.numChildren, 3, "Children of the shadow root are counted"); 156 is(children.nodes.length, 3, "Children returned from walker"); 157 158 const before = children.nodes[1]; 159 is( 160 before._form.nodeName, 161 "_moz_generated_content_before", 162 "Should be the ::before pseudo-element" 163 ); 164 ok(before.isNativeAnonymous, "::before is native anonymous"); 165 info(JSON.stringify(before._form)); 166 167 const shadow = children.nodes[0]; 168 const shadowChildren = await walker.children(shadow); 169 // <h3>...</h3>, <select multiple></select> 170 is(shadow.numChildren, 2, "Children of the shadow root are counted"); 171 is(shadowChildren.nodes.length, 2, "Children returned from walker"); 172 173 // <h3>Shadow <em>DOM</em></h3> 174 const shadowChild1 = shadowChildren.nodes[0]; 175 ok(!shadowChild1.isNativeAnonymous, "Shadow child is not native anonymous"); 176 177 const shadowSubChildren = await walker.children(shadowChild1); 178 is(shadowChild1.numChildren, 2, "Subchildren of the shadow root are counted"); 179 is(shadowSubChildren.nodes.length, 2, "Subchildren are returned from walker"); 180 181 // <em>DOM</em> 182 const shadowSubChild = shadowSubChildren.nodes[1]; 183 ok( 184 !shadowSubChild.isNativeAnonymous, 185 "Subchildren of shadow root are not native anonymous" 186 ); 187 188 // <select multiple></select> 189 const shadowChild2 = shadowChildren.nodes[1]; 190 ok(!shadowChild2.isNativeAnonymous, "Child is native anonymous"); 191 }