Introduce weakmap for node property

Bug: chromium:1011811, chromium:1135143
Change-Id: I4369f82447b3dd9555ea5077f637c48c9b482258
Reviewed-on: https://chromium-review.googlesource.com/c/devtools/devtools-frontend/+/2463359
Reviewed-by: Jack Franklin <[email protected]>
Commit-Queue: Sigurd Schneider <[email protected]>
diff --git a/front_end/console/ConsoleViewMessage.js b/front_end/console/ConsoleViewMessage.js
index 301d0fe..a9b82e6 100644
--- a/front_end/console/ConsoleViewMessage.js
+++ b/front_end/console/ConsoleViewMessage.js
@@ -40,6 +40,16 @@
 
 import {ConsoleViewportElement} from './ConsoleViewport.js';  // eslint-disable-line no-unused-vars
 
+/** @type {!WeakMap<!Element, !ConsoleViewMessage>} */
+const elementToMessage = new WeakMap();
+
+/**
+ * @param {!Element} element
+ */
+export const getMessageForElement = element => {
+  return elementToMessage.get(element);
+};
+
 /**
  * @implements {ConsoleViewportElement}
  * @unrestricted
@@ -1369,8 +1379,7 @@
       this._nestingLevelMarkers.push(this._element.createChild('div', 'nesting-level-marker'));
     }
     this._updateCloseGroupDecorations();
-    // @ts-ignore
-    this._element.message = this;
+    elementToMessage.set(this._element, this);
 
     switch (this._message.level) {
       case SDK.ConsoleModel.MessageLevel.Verbose:
@@ -1928,6 +1937,82 @@
   }
 }
 
+export class ConsoleCommand extends ConsoleViewMessage {
+  /**
+   * @param {!SDK.ConsoleModel.ConsoleMessage} consoleMessage
+   * @param {!Components.Linkifier.Linkifier} linkifier
+   * @param {number} nestingLevel
+   * @param {function(!Common.EventTarget.EventTargetEvent):void} onResize
+   */
+  constructor(consoleMessage, linkifier, nestingLevel, onResize) {
+    super(consoleMessage, linkifier, nestingLevel, onResize);
+    /** @type {?HTMLElement} */
+    this._formattedCommand = null;
+  }
+
+  /**
+   * @override
+   * @return {!HTMLElement}
+   */
+  contentElement() {
+    const contentElement = this.getContentElement();
+    if (contentElement) {
+      return contentElement;
+    }
+    const newContentElement = /** @type {!HTMLElement} */ (document.createElement('div'));
+    this.setContentElement(newContentElement);
+    newContentElement.classList.add('console-user-command');
+    const icon = UI.Icon.Icon.create('smallicon-user-command', 'command-result-icon');
+    newContentElement.appendChild(icon);
+
+    elementToMessage.set(newContentElement, this);
+
+    this._formattedCommand = /** @type {!HTMLElement} */ (document.createElement('span'));
+    this._formattedCommand.classList.add('source-code');
+    this._formattedCommand.textContent = Platform.StringUtilities.replaceControlCharacters(this.text);
+    newContentElement.appendChild(this._formattedCommand);
+
+    if (this._formattedCommand.textContent.length < MaxLengthToIgnoreHighlighter) {
+      const javascriptSyntaxHighlighter = new UI.SyntaxHighlighter.SyntaxHighlighter('text/javascript', true);
+      javascriptSyntaxHighlighter.syntaxHighlightNode(this._formattedCommand).then(this._updateSearch.bind(this));
+    } else {
+      this._updateSearch();
+    }
+
+    this.updateTimestamp();
+    return newContentElement;
+  }
+
+  _updateSearch() {
+    this.setSearchRegex(this.searchRegex());
+  }
+}
+
+export class ConsoleCommandResult extends ConsoleViewMessage {
+  /**
+   * @override
+   * @return {!HTMLElement}
+   */
+  contentElement() {
+    const element = super.contentElement();
+    if (!element.classList.contains('console-user-command-result')) {
+      element.classList.add('console-user-command-result');
+      if (this.consoleMessage().level === SDK.ConsoleModel.MessageLevel.Info) {
+        const icon = UI.Icon.Icon.create('smallicon-command-result', 'command-result-icon');
+        element.insertBefore(icon, element.firstChild);
+      }
+    }
+    return element;
+  }
+}
+
+/**
+ * The maximum length before strings are considered too long for syntax highlighting.
+ * @const
+ * @type {number}
+ */
+const MaxLengthToIgnoreHighlighter = 10000;
+
 /**
  * @const
  * @type {number}