forked from mirrors/gecko-dev
		
	
		
			
				
	
	
		
			265 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			265 lines
		
	
	
	
		
			8.6 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| const { NodeCache } = ChromeUtils.importESModule(
 | |
|   "chrome://remote/content/shared/webdriver/NodeCache.sys.mjs"
 | |
| );
 | |
| 
 | |
| function setupTest() {
 | |
|   const browser = Services.appShell.createWindowlessBrowser(false);
 | |
| 
 | |
|   browser.document.body.innerHTML = `
 | |
|     <div id="foo" style="margin: 50px">
 | |
|       <iframe></iframe>
 | |
|       <video></video>
 | |
|       <svg xmlns="http://www.w3.org/2000/svg"></svg>
 | |
|       <textarea></textarea>
 | |
|     </div>
 | |
|     <div id="with-comment"><!-- Comment --></div>
 | |
|   `;
 | |
| 
 | |
|   const divEl = browser.document.querySelector("div");
 | |
|   const svgEl = browser.document.querySelector("svg");
 | |
|   const textareaEl = browser.document.querySelector("textarea");
 | |
|   const videoEl = browser.document.querySelector("video");
 | |
| 
 | |
|   const iframeEl = browser.document.querySelector("iframe");
 | |
|   const childEl = iframeEl.contentDocument.createElement("div");
 | |
|   iframeEl.contentDocument.body.appendChild(childEl);
 | |
| 
 | |
|   const shadowRoot = videoEl.openOrClosedShadowRoot;
 | |
| 
 | |
|   return {
 | |
|     browser,
 | |
|     nodeCache: new NodeCache(),
 | |
|     childEl,
 | |
|     divEl,
 | |
|     iframeEl,
 | |
|     shadowRoot,
 | |
|     seenNodeIds: new Map(),
 | |
|     svgEl,
 | |
|     textareaEl,
 | |
|     videoEl,
 | |
|   };
 | |
| }
 | |
| 
 | |
| add_task(function getOrCreateNodeReference_invalid() {
 | |
|   const { nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const invalidValues = [null, undefined, "foo", 42, true, [], {}];
 | |
| 
 | |
|   for (const value of invalidValues) {
 | |
|     info(`Testing value: ${value}`);
 | |
|     Assert.throws(
 | |
|       () => nodeCache.getOrCreateNodeReference(value, seenNodeIds),
 | |
|       /TypeError/
 | |
|     );
 | |
|   }
 | |
| });
 | |
| 
 | |
| add_task(function getOrCreateNodeReference_supportedNodeTypes() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   // Bug 1820734: No ownerGlobal is available in XPCShell tests
 | |
|   // const xmlDocument = new DOMParser().parseFromString(
 | |
|   //   "<xml></xml>",
 | |
|   //   "application/xml"
 | |
|   // );
 | |
| 
 | |
|   const values = [
 | |
|     { node: divEl, type: Node.ELEMENT_NODE },
 | |
|     { node: divEl.attributes[0], type: Node.ATTRIBUTE_NODE },
 | |
|     { node: browser.document.createTextNode("foo"), type: Node.TEXT_NODE },
 | |
|     // Bug 1820734: No ownerGlobal is available in XPCShell tests
 | |
|     // {
 | |
|     //   node: xmlDocument.createCDATASection("foo"),
 | |
|     //   type: Node.CDATA_SECTION_NODE,
 | |
|     // },
 | |
|     {
 | |
|       node: browser.document.createProcessingInstruction(
 | |
|         "xml-stylesheet",
 | |
|         "href='foo.css'"
 | |
|       ),
 | |
|       type: Node.PROCESSING_INSTRUCTION_NODE_NODE,
 | |
|     },
 | |
|     { node: browser.document.createComment("foo"), type: Node.COMMENT_NODE },
 | |
|     { node: browser.document, type: Node.Document_NODE },
 | |
|     {
 | |
|       node: browser.document.implementation.createDocumentType(
 | |
|         "foo",
 | |
|         "bar",
 | |
|         "dtd"
 | |
|       ),
 | |
|       type: Node.DOCUMENT_TYPE_NODE_NODE,
 | |
|     },
 | |
|     {
 | |
|       node: browser.document.createDocumentFragment(),
 | |
|       type: Node.DOCUMENT_FRAGMENT_NODE,
 | |
|     },
 | |
|   ];
 | |
| 
 | |
|   values.forEach((value, index) => {
 | |
|     info(`Testing value: ${value.type}`);
 | |
|     const nodeRef = nodeCache.getOrCreateNodeReference(value.node, seenNodeIds);
 | |
|     equal(nodeCache.size, index + 1);
 | |
|     equal(typeof nodeRef, "string");
 | |
|     ok(seenNodeIds.get(browser.browsingContext).includes(nodeRef));
 | |
|   });
 | |
| });
 | |
| 
 | |
| add_task(function getOrCreateNodeReference_referenceAlreadyCreated() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   const divElRefOther = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
| 
 | |
|   equal(divElRefOther, divElRef);
 | |
|   equal(nodeCache.size, 1);
 | |
|   equal(seenNodeIds.size, 1);
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(divElRef));
 | |
| });
 | |
| 
 | |
| add_task(function getOrCreateNodeReference_differentReference() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds, shadowRoot } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 1);
 | |
|   equal(seenNodeIds.size, 1);
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(divElRef));
 | |
| 
 | |
|   const shadowRootRef = nodeCache.getOrCreateNodeReference(
 | |
|     shadowRoot,
 | |
|     seenNodeIds
 | |
|   );
 | |
|   equal(nodeCache.size, 2);
 | |
|   equal(seenNodeIds.size, 1);
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(divElRef));
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(shadowRootRef));
 | |
| 
 | |
|   notEqual(divElRef, shadowRootRef);
 | |
| });
 | |
| 
 | |
| add_task(function getOrCreateNodeReference_differentReferencePerNodeCache() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds } = setupTest();
 | |
|   const nodeCache2 = new NodeCache();
 | |
| 
 | |
|   const divElRef1 = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   const divElRef2 = nodeCache2.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
| 
 | |
|   notEqual(divElRef1, divElRef2);
 | |
|   equal(
 | |
|     nodeCache.getNode(browser.browsingContext, divElRef1),
 | |
|     nodeCache2.getNode(browser.browsingContext, divElRef2)
 | |
|   );
 | |
| 
 | |
|   equal(seenNodeIds.size, 1);
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(divElRef1));
 | |
|   ok(seenNodeIds.get(browser.browsingContext).includes(divElRef2));
 | |
| 
 | |
|   equal(nodeCache.getNode(browser.browsingContext, divElRef2), null);
 | |
| });
 | |
| 
 | |
| add_task(function clear() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds, svgEl } = setupTest();
 | |
| 
 | |
|   nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   nodeCache.getOrCreateNodeReference(svgEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 2);
 | |
|   equal(seenNodeIds.size, 1);
 | |
| 
 | |
|   // Clear requires explicit arguments.
 | |
|   Assert.throws(() => nodeCache.clear(), /Error/);
 | |
| 
 | |
|   // Clear references for a different browsing context
 | |
|   const browser2 = Services.appShell.createWindowlessBrowser(false);
 | |
|   const imgEl = browser2.document.createElement("img");
 | |
|   const imgElRef = nodeCache.getOrCreateNodeReference(imgEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 3);
 | |
|   equal(seenNodeIds.size, 2);
 | |
| 
 | |
|   nodeCache.clear({ browsingContext: browser.browsingContext });
 | |
|   equal(nodeCache.size, 1);
 | |
|   equal(nodeCache.getNode(browser2.browsingContext, imgElRef), imgEl);
 | |
| 
 | |
|   // Clear all references
 | |
|   nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 2);
 | |
|   equal(seenNodeIds.size, 2);
 | |
| 
 | |
|   nodeCache.clear({ all: true });
 | |
|   equal(nodeCache.size, 0);
 | |
| });
 | |
| 
 | |
| add_task(function getNode_multiple_nodes() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds, svgEl } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   const svgElRef = nodeCache.getOrCreateNodeReference(svgEl, seenNodeIds);
 | |
| 
 | |
|   equal(nodeCache.getNode(browser.browsingContext, svgElRef), svgEl);
 | |
|   equal(nodeCache.getNode(browser.browsingContext, divElRef), divEl);
 | |
| });
 | |
| 
 | |
| add_task(function getNode_differentBrowsingContextInSameGroup() {
 | |
|   const { iframeEl, divEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 1);
 | |
| 
 | |
|   equal(
 | |
|     nodeCache.getNode(iframeEl.contentWindow.browsingContext, divElRef),
 | |
|     divEl
 | |
|   );
 | |
| });
 | |
| 
 | |
| add_task(function getNode_differentBrowsingContextInOtherGroup() {
 | |
|   const { divEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
|   equal(nodeCache.size, 1);
 | |
| 
 | |
|   const browser2 = Services.appShell.createWindowlessBrowser(false);
 | |
|   equal(nodeCache.getNode(browser2.browsingContext, divElRef), null);
 | |
| });
 | |
| 
 | |
| add_task(async function getNode_nodeDeleted() {
 | |
|   const { browser, nodeCache, seenNodeIds } = setupTest();
 | |
|   let el = browser.document.createElement("div");
 | |
| 
 | |
|   const elRef = nodeCache.getOrCreateNodeReference(el, seenNodeIds);
 | |
| 
 | |
|   // Delete element and force a garbage collection
 | |
|   el = null;
 | |
| 
 | |
|   await doGC();
 | |
| 
 | |
|   equal(nodeCache.getNode(browser.browsingContext, elRef), null);
 | |
| });
 | |
| 
 | |
| add_task(function getNodeDetails_forTopBrowsingContext() {
 | |
|   const { browser, divEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const divElRef = nodeCache.getOrCreateNodeReference(divEl, seenNodeIds);
 | |
| 
 | |
|   const nodeDetails = nodeCache.getReferenceDetails(divElRef);
 | |
|   equal(nodeDetails.browserId, browser.browsingContext.browserId);
 | |
|   equal(nodeDetails.browsingContextGroupId, browser.browsingContext.group.id);
 | |
|   equal(nodeDetails.browsingContextId, browser.browsingContext.id);
 | |
|   ok(nodeDetails.isTopBrowsingContext);
 | |
|   ok(nodeDetails.nodeWeakRef);
 | |
|   equal(nodeDetails.nodeWeakRef.get(), divEl);
 | |
| });
 | |
| 
 | |
| add_task(async function getNodeDetails_forChildBrowsingContext() {
 | |
|   const { browser, iframeEl, childEl, nodeCache, seenNodeIds } = setupTest();
 | |
| 
 | |
|   const childElRef = nodeCache.getOrCreateNodeReference(childEl, seenNodeIds);
 | |
| 
 | |
|   const nodeDetails = nodeCache.getReferenceDetails(childElRef);
 | |
|   equal(nodeDetails.browserId, browser.browsingContext.browserId);
 | |
|   equal(nodeDetails.browsingContextGroupId, browser.browsingContext.group.id);
 | |
|   equal(
 | |
|     nodeDetails.browsingContextId,
 | |
|     iframeEl.contentWindow.browsingContext.id
 | |
|   );
 | |
|   ok(!nodeDetails.isTopBrowsingContext);
 | |
|   ok(nodeDetails.nodeWeakRef);
 | |
|   equal(nodeDetails.nodeWeakRef.get(), childEl);
 | |
| });
 | 
