[typescript] TypeScript-ify accessibility/AccessibilityNodeView.js

Bug: 1011811
Change-Id: I53ed9976ad387bfc2574da8572e58b5cffaf335f
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2387724
Commit-Queue: Peter Marshall <[email protected]>
Reviewed-by: Paul Lewis <[email protected]>
diff --git a/front_end/accessibility/AccessibilityNodeView.js b/front_end/accessibility/AccessibilityNodeView.js
index 75ba5c5..b88d1aa 100644
--- a/front_end/accessibility/AccessibilityNodeView.js
+++ b/front_end/accessibility/AccessibilityNodeView.js
@@ -2,9 +2,6 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-// @ts-nocheck
-// TODO(crbug.com/1011811): Enable TypeScript compiler checks
-
 import * as Common from '../common/common.js';
 import * as SDK from '../sdk/sdk.js';
 import * as UI from '../ui/ui.js';
@@ -23,6 +20,7 @@
     /**
      * @protected
      * @suppress {accessControls}
+     * @type {?AccessibilityNode}
      */
     this._axNode = null;
 
@@ -156,7 +154,7 @@
     let valueElement;
     const AXValueType = Protocol.Accessibility.AXValueType;
     if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString) {
-      valueElement = createElement('span');
+      valueElement = document.createElement('span');
     } else {
       valueElement = document.createElement('span');
       valueElement.classList.add('monospace');
@@ -166,7 +164,6 @@
     if (isStringProperty) {
       // Render \n as a nice unicode cr symbol.
       valueText = '"' + value.replace(/\n/g, '\u21B5') + '"';
-      valueElement._originalTextContent = value;
     } else {
       valueText = String(value);
     }
@@ -187,7 +184,8 @@
    * @return {!Element}
    */
   static createExclamationMark(tooltip) {
-    const exclamationElement = createElement('span', 'dt-icon-label');
+    const exclamationElement =
+        /** @type {!UI.UIUtils.DevToolsIconLabel} */ (document.createElement('span', {is: 'dt-icon-label'}));
     exclamationElement.type = 'smallicon-warning';
     exclamationElement.title = tooltip;
     return exclamationElement;
@@ -197,10 +195,12 @@
    * @param {string} name
    */
   appendNameElement(name) {
-    const nameElement = createElement('span');
+    const nameElement = document.createElement('span');
     if (name in AXAttributes) {
-      nameElement.textContent = AXAttributes[name].name;
-      nameElement.title = AXAttributes[name].description;
+      // @ts-ignore TS can't cast name here but we checked it's valid.
+      const attribute = AXAttributes[name];
+      nameElement.textContent = attribute.name;
+      nameElement.title = attribute.description;
       nameElement.classList.add('ax-readable-name');
     } else {
       nameElement.textContent = name;
@@ -240,7 +240,8 @@
   appendRelatedNode(relatedNode, index) {
     const deferredNode =
         new SDK.DOMModel.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
-    const nodeTreeElement = new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode}, relatedNode);
+    const nodeTreeElement =
+        new AXRelatedNodeSourceTreeElement({deferredNode: deferredNode, idref: undefined}, relatedNode);
     this.appendChild(nodeTreeElement);
   }
 
@@ -250,7 +251,7 @@
   appendRelatedNodeInline(relatedNode) {
     const deferredNode =
         new SDK.DOMModel.DeferredDOMNode(this._axNode.accessibilityModel().target(), relatedNode.backendDOMNodeId);
-    const linkedNode = new AXRelatedNodeElement({deferredNode: deferredNode}, relatedNode);
+    const linkedNode = new AXRelatedNodeElement({deferredNode: deferredNode, idref: undefined}, relatedNode);
     this.listItemElement.appendChild(linkedNode.render());
   }
 
@@ -258,13 +259,15 @@
    * @param {!Protocol.Accessibility.AXValue} value
    */
   appendRelatedNodeListValueElement(value) {
-    if (value.relatedNodes.length === 1 && !value.value) {
+    if (value.relatedNodes && value.relatedNodes.length === 1 && !value.value) {
       this.appendRelatedNodeInline(value.relatedNodes[0]);
       return;
     }
 
-    value.relatedNodes.forEach(this.appendRelatedNode, this);
-    if (value.relatedNodes.length <= 3) {
+    if (value.relatedNodes) {
+      value.relatedNodes.forEach(this.appendRelatedNode, this);
+    }
+    if (value.relatedNodes && value.relatedNodes.length <= 3) {
       this.expand();
     } else {
       this.collapse();
@@ -392,9 +395,9 @@
       if (matchingNode) {
         this.appendRelatedNodeWithIdref(matchingNode, idref);
       } else if (idrefs.length === 1) {
-        this.listItemElement.appendChild(new Accessibility.AXRelatedNodeElement({idref: idref}).render());
+        this.listItemElement.appendChild(new AXRelatedNodeElement({deferredNode: undefined, idref: idref}).render());
       } else {
-        this.appendChild(new Accessibility.AXRelatedNodeSourceTreeElement({idref: idref}));
+        this.appendChild(new AXRelatedNodeSourceTreeElement({deferredNode: undefined, idref: idref}));
       }
     }
   }
@@ -405,7 +408,7 @@
    */
   appendRelatedNodeListValueElement(value) {
     const relatedNodes = value.relatedNodes;
-    const numNodes = relatedNodes.length;
+    const numNodes = relatedNodes ? relatedNodes.length : 0;
 
     if (value.type === Protocol.Accessibility.AXValueType.IdrefList ||
         value.type === Protocol.Accessibility.AXValueType.Idref) {
@@ -426,7 +429,7 @@
    * @param {!Protocol.Accessibility.AXValueSource} source
    */
   appendSourceNameElement(source) {
-    const nameElement = createElement('span');
+    const nameElement = document.createElement('span');
     const AXValueSourceType = Protocol.Accessibility.AXValueSourceType;
     const type = source.type;
     switch (type) {
@@ -440,7 +443,7 @@
           nameElement.classList.add('ax-readable-name');
           break;
         }
-        nameElement.textContent = source.attribute;
+        nameElement.textContent = source.attribute || null;
         nameElement.classList.add('ax-name');
         nameElement.classList.add('monospace');
         break;
@@ -554,19 +557,18 @@
    * @return {!Element}
    */
   render() {
-    const element = createElement('span');
-    let valueElement;
+    const element = document.createElement('span');
 
     if (this._deferredNode) {
-      valueElement = createElement('span');
+      const valueElement = document.createElement('span');
       element.appendChild(valueElement);
       this._deferredNode.resolvePromise().then(node => {
-        Common.Linkifier.Linkifier.linkify(node, {preventKeyboardFocus: true})
+        Common.Linkifier.Linkifier.linkify(node, {tooltip: undefined, preventKeyboardFocus: true})
             .then(linkfied => valueElement.appendChild(linkfied));
       });
     } else if (this._idref) {
       element.classList.add('invalid');
-      valueElement = AXNodePropertyTreeElement.createExclamationMark(ls`No node with this ID.`);
+      const valueElement = AXNodePropertyTreeElement.createExclamationMark(ls`No node with this ID.`);
       valueElement.createTextChild(this._idref);
       element.appendChild(valueElement);
     }
@@ -578,7 +580,9 @@
    * Attempts to cause the node referred to by the related node to be selected in the tree.
    */
   revealNode() {
-    this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
+    if (this._deferredNode) {
+      this._deferredNode.resolvePromise().then(node => Common.Revealer.reveal(node));
+    }
   }
 }
 
@@ -613,13 +617,13 @@
         reasonElement = UI.UIUtils.formatLocalized('Ancestor\'s children are all presentational:\xA0', []);
         break;
       case 'ariaHiddenElement': {
-        const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
+        const ariaHiddenSpan = document.createElement('span', {is: 'source-code'}).textContent = 'aria-hidden';
         reasonElement = UI.UIUtils.formatLocalized('Element is %s.', [ariaHiddenSpan]);
         break;
       }
       case 'ariaHiddenSubtree': {
-        const ariaHiddenSpan = createElement('span', 'source-code').textContent = 'aria-hidden';
-        const trueSpan = createElement('span', 'source-code').textContent = 'true';
+        const ariaHiddenSpan = document.createElement('span', {is: 'source-code'}).textContent = 'aria-hidden';
+        const trueSpan = document.createElement('span', {is: 'source-code'}).textContent = 'true';
         reasonElement = UI.UIUtils.formatLocalized('%s is %s on ancestor:\xA0', [ariaHiddenSpan, trueSpan]);
         break;
       }
@@ -651,7 +655,8 @@
         reasonElement = UI.UIUtils.formatLocalized('Element is not visible.', []);
         break;
       case 'presentationalRole': {
-        const rolePresentationSpan = createElement('span', 'source-code').textContent = 'role=' + axNode.role().value;
+        const role = axNode && axNode.role() || '';
+        const rolePresentationSpan = document.createElement('span', {is: 'source-code'}).textContent = 'role=' + role;
         reasonElement = UI.UIUtils.formatLocalized('Element has %s.', [rolePresentationSpan]);
         break;
       }