/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * @unrestricted
 */
export default class ObjectPropertiesSection extends UI.TreeOutlineInShadow {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {?string|!Element=} title
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} ignoreHasOwnProperty
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   * @param {boolean=} showOverflow
   */
  constructor(object, title, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, showOverflow) {
    super();
    this._object = object;
    this._editable = true;
    if (!showOverflow) {
      this.hideOverflow();
    }
    this.setFocusable(true);
    this.setShowSelectionOnKeyboardFocus(true);
    this._objectTreeElement =
        new RootElement(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties);
    this.appendChild(this._objectTreeElement);
    if (typeof title === 'string' || !title) {
      this.titleElement = this.element.createChild('span');
      this.titleElement.textContent = title || '';
    } else {
      this.titleElement = title;
      this.element.appendChild(title);
    }
    if (!this.titleElement.hasAttribute('tabIndex')) {
      this.titleElement.tabIndex = -1;
    }

    this.element._section = this;
    this.registerRequiredCSS('object_ui/objectValue.css');
    this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
    this.rootElement().childrenListElement.classList.add('source-code', 'object-properties-section');
  }

  /**
   * @param {!SDK.RemoteObject} object
   * @param {!Components.Linkifier=} linkifier
   * @param {boolean=} skipProto
   * @param {boolean=} readOnly
   * @return {!Element}
   */
  static defaultObjectPresentation(object, linkifier, skipProto, readOnly) {
    const objectPropertiesSection =
        ObjectPropertiesSection.defaultObjectPropertiesSection(object, linkifier, skipProto, readOnly);
    if (!object.hasChildren) {
      return objectPropertiesSection.titleElement;
    } else {
      return objectPropertiesSection.element;
    }
  }

  /**
   * @param {!SDK.RemoteObject} object
   * @param {!Components.Linkifier=} linkifier
   * @param {boolean=} skipProto
   * @param {boolean=} readOnly
   * @return {!ObjectPropertiesSection}
   */
  static defaultObjectPropertiesSection(object, linkifier, skipProto, readOnly) {
    const titleElement = createElementWithClass('span', 'source-code');
    const shadowRoot = UI.createShadowRootWithCoreStyles(titleElement, 'object_ui/objectValue.css');
    shadowRoot.appendChild(
        ObjectPropertiesSection.createValueElement(object, /* wasThrown */ false, /* showPreview */ true));
    const objectPropertiesSection = new ObjectPropertiesSection(object, titleElement, linkifier);
    objectPropertiesSection.editable = false;
    if (skipProto) {
      objectPropertiesSection.skipProto();
    }
    if (readOnly) {
      objectPropertiesSection.setEditable(false);
    }

    return objectPropertiesSection;
  }

  /**
   * @param {!SDK.RemoteObjectProperty} propertyA
   * @param {!SDK.RemoteObjectProperty} propertyB
   * @return {number}
   */
  static CompareProperties(propertyA, propertyB) {
    const a = propertyA.name;
    const b = propertyB.name;
    if (a === '__proto__') {
      return 1;
    }
    if (b === '__proto__') {
      return -1;
    }
    if (!propertyA.enumerable && propertyB.enumerable) {
      return 1;
    }
    if (!propertyB.enumerable && propertyA.enumerable) {
      return -1;
    }
    if (a.startsWith('_') && !b.startsWith('_')) {
      return 1;
    }
    if (b.startsWith('_') && !a.startsWith('_')) {
      return -1;
    }
    if (propertyA.symbol && !propertyB.symbol) {
      return 1;
    }
    if (propertyB.symbol && !propertyA.symbol) {
      return -1;
    }
    if (propertyA.private && !propertyB.private) {
      return 1;
    }
    if (propertyB.private && !propertyA.private) {
      return -1;
    }
    return String.naturalOrderComparator(a, b);
  }

  /**
   * @param {?string} name
   * @param {boolean=} isPrivate
   * @return {!Element}
   */
  static createNameElement(name, isPrivate) {
    if (name === null) {
      return UI.html`<span class="name"></span>`;
    }
    if (/^\s|\s$|^$|\n/.test(name)) {
      return UI.html`<span class="name">"${name.replace(/\n/g, '\u21B5')}"</span>`;
    }
    if (isPrivate) {
      return UI.html`<span class="name">
        <span class="private-property-hash">${name[0]}</span>${name.substring(1)}
      </span>`;
    }
    return UI.html`<span class="name">${name}</span>`;
  }

  /**
   * @param {?string=} description
   * @param {boolean=} includePreview
   * @param {string=} defaultName
   * @return {!Element} valueElement
   */
  static valueElementForFunctionDescription(description, includePreview, defaultName) {
    const valueElement = createElementWithClass('span', 'object-value-function');
    description = description || '';
    const text = description.replace(/^function [gs]et /, 'function ')
                     .replace(/^function [gs]et\(/, 'function\(')
                     .replace(/^[gs]et /, '');
    defaultName = defaultName || '';

    // This set of best-effort regular expressions captures common function descriptions.
    // Ideally, some parser would provide prefix, arguments, function body text separately.
    const asyncMatch = text.match(/^(async\s+function)/);
    const isGenerator = text.startsWith('function*');
    const isGeneratorShorthand = text.startsWith('*');
    const isBasic = !isGenerator && text.startsWith('function');
    const isClass = text.startsWith('class ') || text.startsWith('class{');
    const firstArrowIndex = text.indexOf('=>');
    const isArrow = !asyncMatch && !isGenerator && !isBasic && !isClass && firstArrowIndex > 0;

    let textAfterPrefix;
    if (isClass) {
      textAfterPrefix = text.substring('class'.length);
      const classNameMatch = /^[^{\s]+/.exec(textAfterPrefix.trim());
      let className = defaultName;
      if (classNameMatch) {
        className = classNameMatch[0].trim() || defaultName;
      }
      addElements('class', textAfterPrefix, className);
    } else if (asyncMatch) {
      textAfterPrefix = text.substring(asyncMatch[1].length);
      addElements('async \u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isGenerator) {
      textAfterPrefix = text.substring('function*'.length);
      addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isGeneratorShorthand) {
      textAfterPrefix = text.substring('*'.length);
      addElements('\u0192*', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isBasic) {
      textAfterPrefix = text.substring('function'.length);
      addElements('\u0192', textAfterPrefix, nameAndArguments(textAfterPrefix));
    } else if (isArrow) {
      const maxArrowFunctionCharacterLength = 60;
      let abbreviation = text;
      if (defaultName) {
        abbreviation = defaultName + '()';
      } else if (text.length > maxArrowFunctionCharacterLength) {
        abbreviation = text.substring(0, firstArrowIndex + 2) + ' {\u2026}';
      }
      addElements('', text, abbreviation);
    } else {
      addElements('\u0192', text, nameAndArguments(text));
    }
    valueElement.title = description.trimEndWithMaxLength(500);
    return valueElement;

    /**
     * @param {string} contents
     * @return {string}
     */
    function nameAndArguments(contents) {
      const startOfArgumentsIndex = contents.indexOf('(');
      const endOfArgumentsMatch = contents.match(/\)\s*{/);
      if (startOfArgumentsIndex !== -1 && endOfArgumentsMatch && endOfArgumentsMatch.index > startOfArgumentsIndex) {
        const name = contents.substring(0, startOfArgumentsIndex).trim() || defaultName;
        const args = contents.substring(startOfArgumentsIndex, endOfArgumentsMatch.index + 1);
        return name + args;
      }
      return defaultName + '()';
    }

    /**
     * @param {string} prefix
     * @param {string} body
     * @param {string} abbreviation
     */
    function addElements(prefix, body, abbreviation) {
      const maxFunctionBodyLength = 200;
      if (prefix.length) {
        valueElement.createChild('span', 'object-value-function-prefix').textContent = prefix + ' ';
      }
      if (includePreview) {
        valueElement.createTextChild(body.trim().trimEndWithMaxLength(maxFunctionBodyLength));
      } else {
        valueElement.createTextChild(abbreviation.replace(/\n/g, ' '));
      }
    }
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @param {boolean} wasThrown
   * @param {boolean} showPreview
   * @param {!Element=} parentElement
   * @param {!Components.Linkifier=} linkifier
   * @return {!Element}
   */
  static createValueElementWithCustomSupport(value, wasThrown, showPreview, parentElement, linkifier) {
    if (value.customPreview()) {
      const result = (new ObjectUI.CustomPreviewComponent(value)).element;
      result.classList.add('object-properties-section-custom-section');
      return result;
    }
    return ObjectPropertiesSection.createValueElement(value, wasThrown, showPreview, parentElement, linkifier);
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @param {boolean} wasThrown
   * @param {boolean} showPreview
   * @param {!Element=} parentElement
   * @param {!Components.Linkifier=} linkifier
   * @return {!Element}
   */
  static createValueElement(value, wasThrown, showPreview, parentElement, linkifier) {
    let valueElement;
    const type = value.type;
    const subtype = value.subtype;
    const description = value.description;
    if (type === 'object' && subtype === 'internal#location') {
      const rawLocation = value.debuggerModel().createRawLocationByScriptId(
          value.value.scriptId, value.value.lineNumber, value.value.columnNumber);
      if (rawLocation && linkifier) {
        return linkifier.linkifyRawLocation(rawLocation, '');
      }
      valueElement = createUnknownInternalLocationElement();
    } else if (type === 'string' && typeof description === 'string') {
      valueElement = createStringElement();
    } else if (type === 'function') {
      valueElement = ObjectPropertiesSection.valueElementForFunctionDescription(description);
    } else if (type === 'object' && subtype === 'node' && description) {
      valueElement = createNodeElement();
    } else if (type === 'number' && description && description.indexOf('e') !== -1) {
      valueElement = createNumberWithExponentElement();
      if (parentElement)  // FIXME: do it in the caller.
      {
        parentElement.classList.add('hbox');
      }
    } else {
      valueElement = createElementWithClass('span', 'object-value-' + (subtype || type));
      valueElement.title = description || '';
      if (value.preview && showPreview) {
        const previewFormatter = new ObjectUI.RemoteObjectPreviewFormatter();
        previewFormatter.appendObjectPreview(valueElement, value.preview, false /* isEntry */);
      } else if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength) {
        valueElement.appendChild(UI.createExpandableText(description, 50));
      } else {
        valueElement.textContent = description;
      }
    }

    if (wasThrown) {
      const wrapperElement = createElementWithClass('span', 'error value');
      wrapperElement.appendChild(UI.formatLocalized('[Exception: %s]', [valueElement]));
      return wrapperElement;
    }
    valueElement.classList.add('value');
    return valueElement;

    /**
     * @return {!Element}
     */
    function createUnknownInternalLocationElement() {
      const valueElement = createElementWithClass('span');
      valueElement.textContent = '<' + Common.UIString('unknown') + '>';
      valueElement.title = description || '';
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createStringElement() {
      const valueElement = createElementWithClass('span', 'object-value-string');
      const text = description.replace(/\n/g, '\u21B5');
      valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
      if (description.length > ObjectUI.ObjectPropertiesSection._maxRenderableStringLength) {
        valueElement.appendChild(UI.createExpandableText(text, 50));
      } else {
        valueElement.createTextChild(text);
      }
      valueElement.createChild('span', 'object-value-string-quote').textContent = '"';
      valueElement.title = description || '';
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createNodeElement() {
      const valueElement = createElementWithClass('span', 'object-value-node');
      ObjectUI.RemoteObjectPreviewFormatter.createSpansForNodeTitle(valueElement, /** @type {string} */ (description));
      valueElement.addEventListener('click', event => {
        Common.Revealer.reveal(value);
        event.consume(true);
      }, false);
      valueElement.addEventListener('mousemove', () => SDK.OverlayModel.highlightObjectAsDOMNode(value), false);
      valueElement.addEventListener('mouseleave', () => SDK.OverlayModel.hideDOMNodeHighlight(), false);
      return valueElement;
    }

    /**
     * @return {!Element}
     */
    function createNumberWithExponentElement() {
      const valueElement = createElementWithClass('span', 'object-value-number');
      const numberParts = description.split('e');
      valueElement.createChild('span', 'object-value-scientific-notation-mantissa').textContent = numberParts[0];
      valueElement.createChild('span', 'object-value-scientific-notation-exponent').textContent = 'e' + numberParts[1];
      valueElement.classList.add('object-value-scientific-notation-number');
      valueElement.title = description || '';
      return valueElement;
    }
  }

  /**
   * @param {!SDK.RemoteObject} func
   * @param {!Element} element
   * @param {boolean} linkify
   * @param {boolean=} includePreview
   * @return {!Promise}
   */
  static formatObjectAsFunction(func, element, linkify, includePreview) {
    return func.debuggerModel().functionDetailsPromise(func).then(didGetDetails);

    /**
     * @param {?SDK.DebuggerModel.FunctionDetails} response
     */
    function didGetDetails(response) {
      if (linkify && response && response.location) {
        element.classList.add('linkified');
        element.addEventListener('click', () => Common.Revealer.reveal(response.location) && false);
      }

      // The includePreview flag is false for formats such as console.dir().
      let defaultName = includePreview ? '' : 'anonymous';
      if (response && response.functionName) {
        defaultName = response.functionName;
      }
      const valueElement =
          ObjectPropertiesSection.valueElementForFunctionDescription(func.description, includePreview, defaultName);
      element.appendChild(valueElement);
    }
  }

  /**
   * @param {!SDK.RemoteObjectProperty} property
   * @param {!SDK.RemoteObjectProperty=} parentProperty
   * @return {boolean}
   */
  static _isDisplayableProperty(property, parentProperty) {
    if (!parentProperty || !parentProperty.synthetic) {
      return true;
    }
    const name = property.name;
    const useless = (parentProperty.name === '[[Entries]]' && (name === 'length' || name === '__proto__'));
    return !useless;
  }

  skipProto() {
    this._skipProto = true;
  }

  expand() {
    this._objectTreeElement.expand();
  }

  /**
   * @param {boolean} value
   */
  setEditable(value) {
    this._editable = value;
  }

  /**
   * @return {!UI.TreeElement}
   */
  objectTreeElement() {
    return this._objectTreeElement;
  }

  enableContextMenu() {
    this.element.addEventListener('contextmenu', this._contextMenuEventFired.bind(this), false);
  }

  _contextMenuEventFired(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.appendApplicableItems(this._object);
    if (this._object instanceof SDK.LocalJSONObject) {
      contextMenu.viewSection().appendItem(
          ls`Expand recursively`,
          this._objectTreeElement.expandRecursively.bind(this._objectTreeElement, Number.MAX_VALUE));
      contextMenu.viewSection().appendItem(
          ls`Collapse children`, this._objectTreeElement.collapseChildren.bind(this._objectTreeElement));
    }
    contextMenu.show();
  }

  titleLessMode() {
    this._objectTreeElement.listItemElement.classList.add('hidden');
    this._objectTreeElement.childrenListElement.classList.add('title-less-mode');
    this._objectTreeElement.expand();
  }
}

/** @const */
const _arrayLoadThreshold = 100;

/** @const */
export const _maxRenderableStringLength = 10000;

export class ObjectPropertiesSectionsTreeOutline extends UI.TreeOutlineInShadow {
  /**
   * @param {?ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions=} options
   */
  constructor(options) {
    super();
    this.registerRequiredCSS('object_ui/objectValue.css');
    this.registerRequiredCSS('object_ui/objectPropertiesSection.css');
    this._editable = !(options && options.readOnly);
    this.contentElement.classList.add('source-code');
    this.contentElement.classList.add('object-properties-section');
    this.hideOverflow();
  }
}

/**
 * @unrestricted
 */
export class RootElement extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} ignoreHasOwnProperty
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   */
  constructor(object, linkifier, emptyPlaceholder, ignoreHasOwnProperty, extraProperties) {
    const contentElement = createElement('slot');
    super(contentElement);

    this._object = object;
    this._extraProperties = extraProperties || [];
    this._ignoreHasOwnProperty = !!ignoreHasOwnProperty;
    this._emptyPlaceholder = emptyPlaceholder;

    this.setExpandable(true);
    this.selectable = true;
    this.toggleOnClick = true;
    this.listItemElement.classList.add('object-properties-section-root-element');
    this._linkifier = linkifier;
  }

  /**
   * @override
   */
  onexpand() {
    if (this.treeOutline) {
      this.treeOutline.element.classList.add('expanded');
    }
  }

  /**
   * @override
   */
  oncollapse() {
    if (this.treeOutline) {
      this.treeOutline.element.classList.remove('expanded');
    }
  }

  /**
   * @override
   * @param {!Event} e
   * @return {boolean}
   */
  ondblclick(e) {
    return true;
  }

  /**
   * @override
   * @returns {!Promise}
   */
  async onpopulate() {
    return ObjectPropertyTreeElement._populate(
        this, this._object, !!this.treeOutline._skipProto, this._linkifier, this._emptyPlaceholder,
        this._ignoreHasOwnProperty, this._extraProperties);
  }
}

/**
 * @unrestricted
 */
export class ObjectPropertyTreeElement extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObjectProperty} property
   * @param {!Components.Linkifier=} linkifier
   */
  constructor(property, linkifier) {
    // Pass an empty title, the title gets made later in onattach.
    super();

    this.property = property;
    this.toggleOnClick = true;
    /** @type {!Array.<!Object>} */
    this._highlightChanges = [];
    this._linkifier = linkifier;
    this.listItemElement.addEventListener('contextmenu', this._contextMenuFired.bind(this), false);
  }

  /**
   * @param {!UI.TreeElement} treeElement
   * @param {!SDK.RemoteObject} value
   * @param {boolean} skipProto
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   * @param {boolean=} flattenProtoChain
   * @param {!Array.<!SDK.RemoteObjectProperty>=} extraProperties
   * @param {!SDK.RemoteObject=} targetValue
   * @return {!Promise}
   */
  static async _populate(
      treeElement, value, skipProto, linkifier, emptyPlaceholder, flattenProtoChain, extraProperties, targetValue) {
    if (value.arrayLength() > _arrayLoadThreshold) {
      treeElement.removeChildren();
      ArrayGroupingTreeElement._populateArray(treeElement, value, 0, value.arrayLength() - 1, linkifier);
      return;
    }

    let allProperties;
    if (flattenProtoChain) {
      allProperties = await value.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */);
    } else {
      allProperties = await SDK.RemoteObject.loadFromObjectPerProto(value, true /* generatePreview */);
    }
    const properties = allProperties.properties;
    const internalProperties = allProperties.internalProperties;
    treeElement.removeChildren();
    if (!properties) {
      return;
    }

    extraProperties = extraProperties || [];
    for (let i = 0; i < extraProperties.length; ++i) {
      properties.push(extraProperties[i]);
    }

    ObjectPropertyTreeElement.populateWithProperties(
        treeElement, properties, internalProperties, skipProto, targetValue || value, linkifier, emptyPlaceholder);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!Array.<!SDK.RemoteObjectProperty>} properties
   * @param {?Array.<!SDK.RemoteObjectProperty>} internalProperties
   * @param {boolean} skipProto
   * @param {?SDK.RemoteObject} value
   * @param {!Components.Linkifier=} linkifier
   * @param {?string=} emptyPlaceholder
   */
  static populateWithProperties(
      treeNode,
      properties,
      internalProperties,
      skipProto,
      value,
      linkifier,
      emptyPlaceholder) {
    internalProperties = internalProperties || [];

    const entriesProperty = internalProperties.find(property => property.name === '[[Entries]]');
    if (entriesProperty) {
      entriesProperty.parentObject = value;
      const treeElement = new ObjectPropertyTreeElement(entriesProperty, linkifier);
      treeElement.setExpandable(true);
      treeElement.expand();
      treeNode.appendChild(treeElement);
    }

    const tailProperties = [];
    let protoProperty = null;
    for (let i = 0; i < properties.length; ++i) {
      const property = properties[i];
      property.parentObject = value;
      if (!ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property)) {
        continue;
      }
      if (property.name === '__proto__' && !property.isAccessorProperty()) {
        protoProperty = property;
        continue;
      }

      if (property.isOwn && property.getter) {
        const getterProperty = new SDK.RemoteObjectProperty('get ' + property.name, property.getter, false);
        getterProperty.parentObject = value;
        tailProperties.push(getterProperty);
      }
      if (property.isOwn && property.setter) {
        const setterProperty = new SDK.RemoteObjectProperty('set ' + property.name, property.setter, false);
        setterProperty.parentObject = value;
        tailProperties.push(setterProperty);
      }
      const canShowProperty = property.getter || !property.isAccessorProperty();
      if (canShowProperty && property.name !== '__proto__') {
        treeNode.appendChild(new ObjectPropertyTreeElement(property, linkifier));
      }
    }
    for (let i = 0; i < tailProperties.length; ++i) {
      treeNode.appendChild(new ObjectPropertyTreeElement(tailProperties[i], linkifier));
    }
    if (!skipProto && protoProperty) {
      treeNode.appendChild(new ObjectPropertyTreeElement(protoProperty, linkifier));
    }

    for (const property of internalProperties) {
      property.parentObject = value;
      const treeElement = new ObjectPropertyTreeElement(property, linkifier);
      if (property.name === '[[Entries]]') {
        continue;
      }
      treeNode.appendChild(treeElement);
    }

    ObjectPropertyTreeElement._appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {?string=} emptyPlaceholder
   */
  static _appendEmptyPlaceholderIfNeeded(treeNode, emptyPlaceholder) {
    if (treeNode.childCount()) {
      return;
    }
    const title = createElementWithClass('div', 'gray-info-message');
    title.textContent = emptyPlaceholder || Common.UIString('No properties');
    const infoElement = new UI.TreeElement(title);
    treeNode.appendChild(infoElement);
  }

  /**
   * @param {?SDK.RemoteObject} object
   * @param {!Array.<string>} propertyPath
   * @param {function(!SDK.CallFunctionResult)} callback
   * @return {!Element}
   */
  static createRemoteObjectAccessorPropertySpan(object, propertyPath, callback) {
    const rootElement = createElement('span');
    const element = rootElement.createChild('span');
    element.textContent = Common.UIString('(...)');
    if (!object) {
      return rootElement;
    }
    element.classList.add('object-value-calculate-value-button');
    element.title = Common.UIString('Invoke property getter');
    element.addEventListener('click', onInvokeGetterClick, false);

    function onInvokeGetterClick(event) {
      event.consume();
      object.callFunction(invokeGetter, [{value: JSON.stringify(propertyPath)}]).then(callback);
    }

    /**
     * @param {string} arrayStr
     * @suppressReceiverCheck
     * @this {Object}
     */
    function invokeGetter(arrayStr) {
      let result = this;
      const properties = JSON.parse(arrayStr);
      for (let i = 0, n = properties.length; i < n; ++i) {
        result = result[properties[i]];
      }
      return result;
    }

    return rootElement;
  }

  /**
   * @param {!RegExp} regex
   * @param {string=} additionalCssClassName
   * @return {boolean}
   */
  setSearchRegex(regex, additionalCssClassName) {
    let cssClasses = UI.highlightedSearchResultClassName;
    if (additionalCssClassName) {
      cssClasses += ' ' + additionalCssClassName;
    }
    this.revertHighlightChanges();

    this._applySearch(regex, this.nameElement, cssClasses);
    const valueType = this.property.value.type;
    if (valueType !== 'object') {
      this._applySearch(regex, this.valueElement, cssClasses);
    }

    return !!this._highlightChanges.length;
  }

  /**
   * @param {!RegExp} regex
   * @param {!Element} element
   * @param {string} cssClassName
   */
  _applySearch(regex, element, cssClassName) {
    const ranges = [];
    const content = element.textContent;
    regex.lastIndex = 0;
    let match = regex.exec(content);
    while (match) {
      ranges.push(new TextUtils.SourceRange(match.index, match[0].length));
      match = regex.exec(content);
    }
    if (ranges.length) {
      UI.highlightRangesWithStyleClass(element, ranges, cssClassName, this._highlightChanges);
    }
  }

  revertHighlightChanges() {
    UI.revertDomChanges(this._highlightChanges);
    this._highlightChanges = [];
  }

  /**
   * @override
   * @returns {!Promise}
   */
  async onpopulate() {
    const propertyValue = /** @type {!SDK.RemoteObject} */ (this.property.value);
    console.assert(propertyValue);
    const skipProto = this.treeOutline ? this.treeOutline._skipProto : true;
    const targetValue = this.property.name !== '__proto__' ? propertyValue : this.property.parentObject;
    await ObjectPropertyTreeElement._populate(
        this, propertyValue, skipProto, this._linkifier, undefined, undefined, undefined, targetValue);
  }

  /**
   * @override
   * @return {boolean}
   */
  ondblclick(event) {
    const inEditableElement = event.target.isSelfOrDescendant(this.valueElement) ||
        (this.expandedValueElement && event.target.isSelfOrDescendant(this.expandedValueElement));
    if (!this.property.value.customPreview() && inEditableElement && (this.property.writable || this.property.setter)) {
      this._startEditing();
    }
    return false;
  }

  /**
   * @override
   * @return {boolean}
   */
  onenter() {
    if (!this.property.value.customPreview() && (this.property.writable || this.property.setter)) {
      this._startEditing();
      return true;
    }
    return false;
  }

  /**
   * @override
   */
  onattach() {
    this.update();
    this._updateExpandable();
  }

  /**
   * @override
   */
  onexpand() {
    this._showExpandedValueElement(true);
  }

  /**
   * @override
   */
  oncollapse() {
    this._showExpandedValueElement(false);
  }

  /**
   * @param {boolean} value
   */
  _showExpandedValueElement(value) {
    if (!this.expandedValueElement) {
      return;
    }
    if (value) {
      this._rowContainer.replaceChild(this.expandedValueElement, this.valueElement);
    } else {
      this._rowContainer.replaceChild(this.valueElement, this.expandedValueElement);
    }
  }

  /**
   * @param {!SDK.RemoteObject} value
   * @return {?Element}
   */
  _createExpandedValueElement(value) {
    const needsAlternateValue = value.hasChildren && !value.customPreview() && value.subtype !== 'node' &&
        value.type !== 'function' && (value.type !== 'object' || value.preview);
    if (!needsAlternateValue) {
      return null;
    }

    const valueElement = createElementWithClass('span', 'value');
    if (value.description === 'Object') {
      valueElement.textContent = '';
    } else {
      valueElement.setTextContentTruncatedIfNeeded(value.description || '');
    }
    valueElement.classList.add('object-value-' + (value.subtype || value.type));
    valueElement.title = value.description || '';
    return valueElement;
  }

  update() {
    this.nameElement = ObjectPropertiesSection.createNameElement(this.property.name, this.property.private);
    if (!this.property.enumerable) {
      this.nameElement.classList.add('object-properties-section-dimmed');
    }
    if (this.property.synthetic) {
      this.nameElement.classList.add('synthetic-property');
    }

    this._updatePropertyPath();

    const isInternalEntries = this.property.synthetic && this.property.name === '[[Entries]]';
    if (isInternalEntries) {
      this.valueElement = createElementWithClass('span', 'value');
    } else if (this.property.value) {
      const showPreview = this.property.name !== '__proto__';
      this.valueElement = ObjectPropertiesSection.createValueElementWithCustomSupport(
          this.property.value, this.property.wasThrown, showPreview, this.listItemElement, this._linkifier);
    } else if (this.property.getter) {
      this.valueElement = ObjectPropertyTreeElement.createRemoteObjectAccessorPropertySpan(
          this.property.parentObject, [this.property.name], this._onInvokeGetterClick.bind(this));
    } else {
      this.valueElement = createElementWithClass('span', 'object-value-undefined');
      this.valueElement.textContent = Common.UIString('<unreadable>');
      this.valueElement.title = Common.UIString('No property getter');
    }

    const valueText = this.valueElement.textContent;
    if (this.property.value && valueText && !this.property.wasThrown) {
      this.expandedValueElement = this._createExpandedValueElement(this.property.value);
    }

    this.listItemElement.removeChildren();
    if (isInternalEntries) {
      this._rowContainer = UI.html`<span class='name-and-value'>${this.nameElement}</span>`;
    } else {
      this._rowContainer = UI.html`<span class='name-and-value'>${this.nameElement}: ${this.valueElement}</span>`;
    }
    this.listItemElement.appendChild(this._rowContainer);
  }

  _updatePropertyPath() {
    if (this.nameElement.title) {
      return;
    }

    const name = this.property.name;

    if (this.property.synthetic) {
      this.nameElement.title = name;
      return;
    }

    const useDotNotation = /^(_|\$|[A-Z])(_|\$|[A-Z]|\d)*$/i;
    const isInteger = /^[1-9]\d*$/;

    const parentPath =
        (this.parent.nameElement && !this.parent.property.synthetic) ? this.parent.nameElement.title : '';

    if (this.property.private || useDotNotation.test(name)) {
      this.nameElement.title = parentPath ? `${parentPath}.${name}` : name;
    } else if (isInteger.test(name)) {
      this.nameElement.title = parentPath + '[' + name + ']';
    } else {
      this.nameElement.title = parentPath + '["' + JSON.stringify(name) + '"]';
    }
  }

  /**
   * @param {!Event} event
   */
  _contextMenuFired(event) {
    const contextMenu = new UI.ContextMenu(event);
    contextMenu.appendApplicableItems(this);
    if (this.property.symbol) {
      contextMenu.appendApplicableItems(this.property.symbol);
    }
    if (this.property.value) {
      contextMenu.appendApplicableItems(this.property.value);
    }
    if (!this.property.synthetic && this.nameElement && this.nameElement.title) {
      const copyPathHandler =
          Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, this.nameElement.title);
      contextMenu.clipboardSection().appendItem(ls`Copy property path`, copyPathHandler);
    }
    if (this.property.parentObject instanceof SDK.LocalJSONObject) {
      contextMenu.viewSection().appendItem(ls`Expand recursively`, this.expandRecursively.bind(this, Number.MAX_VALUE));
      contextMenu.viewSection().appendItem(ls`Collapse children`, this.collapseChildren.bind(this));
    }
    contextMenu.show();
  }

  _startEditing() {
    if (this._prompt || !this.treeOutline._editable || this._readOnly) {
      return;
    }

    this._editableDiv = this._rowContainer.createChild('span', 'editable-div');

    let text = this.property.value.description;
    if (this.property.value.type === 'string' && typeof text === 'string') {
      text = '"' + text + '"';
    }

    this._editableDiv.setTextContentTruncatedIfNeeded(text, Common.UIString('<string is too large to edit>'));
    const originalContent = this._editableDiv.textContent;

    // Lie about our children to prevent expanding on double click and to collapse subproperties.
    this.setExpandable(false);
    this.listItemElement.classList.add('editing-sub-part');
    this.valueElement.classList.add('hidden');

    this._prompt = new ObjectPropertyPrompt();

    const proxyElement =
        this._prompt.attachAndStartEditing(this._editableDiv, this._editingCommitted.bind(this, originalContent));
    proxyElement.classList.add('property-prompt');
    this.listItemElement.getComponentSelection().selectAllChildren(this._editableDiv);
    proxyElement.addEventListener('keydown', this._promptKeyDown.bind(this, originalContent), false);
  }

  _editingEnded() {
    this._prompt.detach();
    delete this._prompt;
    this._editableDiv.remove();
    this._updateExpandable();
    this.listItemElement.scrollLeft = 0;
    this.listItemElement.classList.remove('editing-sub-part');
    this.select();
  }

  _editingCancelled() {
    this.valueElement.classList.remove('hidden');
    this._editingEnded();
  }

  /**
   * @param {string} originalContent
   * @returns {!Promise}
   */
  async _editingCommitted(originalContent) {
    const userInput = this._prompt.text();
    if (userInput === originalContent) {
      this._editingCancelled();  // nothing changed, so cancel
      return;
    }

    this._editingEnded();
    await this._applyExpression(userInput);
  }

  /**
   * @param {string} originalContent
   * @param {!Event} event
   */
  _promptKeyDown(originalContent, event) {
    if (isEnterKey(event)) {
      event.consume();
      this._editingCommitted(originalContent);
      return;
    }
    if (event.key === 'Escape') {
      event.consume();
      this._editingCancelled();
      return;
    }
  }

  /**
   * @param {string} expression
   */
  async _applyExpression(expression) {
    const property = SDK.RemoteObject.toCallArgument(this.property.symbol || this.property.name);
    expression = ObjectUI.JavaScriptREPL.wrapObjectLiteral(expression.trim());

    if (this.property.synthetic) {
      let invalidate = false;
      if (expression) {
        invalidate = await this.property.setSyntheticValue(expression);
      }
      if (invalidate) {
        const parent = this.parent;
        parent.invalidateChildren();
        parent.onpopulate();
      } else {
        this.update();
      }
      return;
    }

    const errorPromise = expression ? this.property.parentObject.setPropertyValue(property, expression) :
                                      this.property.parentObject.deleteProperty(property);
    const error = await errorPromise;
    if (error) {
      this.update();
      return;
    }

    if (!expression) {
      // The property was deleted, so remove this tree element.
      this.parent.removeChild(this);
    } else {
      // Call updateSiblings since their value might be based on the value that just changed.
      const parent = this.parent;
      parent.invalidateChildren();
      parent.onpopulate();
    }
  }

  /**
   * @param {!SDK.CallFunctionResult} result
   */
  _onInvokeGetterClick(result) {
    if (!result.object) {
      return;
    }
    this.property.value = result.object;
    this.property.wasThrown = result.wasThrown;

    this.update();
    this.invalidateChildren();
    this._updateExpandable();
  }

  _updateExpandable() {
    if (this.property.value) {
      this.setExpandable(
          !this.property.value.customPreview() && this.property.value.hasChildren && !this.property.wasThrown);
    } else {
      this.setExpandable(false);
    }
  }

  /**
   * @return {string}
   */
  path() {
    return this.nameElement.title;
  }
}


/**
 * @unrestricted
 */
class ArrayGroupingTreeElement extends UI.TreeElement {
  /**
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {number} propertyCount
   * @param {!Components.Linkifier=} linkifier
   */
  constructor(object, fromIndex, toIndex, propertyCount, linkifier) {
    super(String.sprintf('[%d \u2026 %d]', fromIndex, toIndex), true);
    this.toggleOnClick = true;
    this._fromIndex = fromIndex;
    this._toIndex = toIndex;
    this._object = object;
    this._readOnly = true;
    this._propertyCount = propertyCount;
    this._linkifier = linkifier;
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {!Components.Linkifier=} linkifier
   * @returns {!Promise}
   */
  static async _populateArray(treeNode, object, fromIndex, toIndex, linkifier) {
    await ArrayGroupingTreeElement._populateRanges(treeNode, object, fromIndex, toIndex, true, linkifier);
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {boolean} topLevel
   * @param {!Components.Linkifier=} linkifier
   * @this {ArrayGroupingTreeElement}
   * @returns {!Promise}
   */
  static async _populateRanges(treeNode, object, fromIndex, toIndex, topLevel, linkifier) {
    const jsonValue = await object.callFunctionJSON(packRanges, [
      {value: fromIndex}, {value: toIndex}, {value: ArrayGroupingTreeElement._bucketThreshold},
      {value: ArrayGroupingTreeElement._sparseIterationThreshold},
      {value: ArrayGroupingTreeElement._getOwnPropertyNamesThreshold}
    ]);

    await callback(jsonValue);

    /**
     * Note: must declare params as optional.
     * @param {number=} fromIndex
     * @param {number=} toIndex
     * @param {number=} bucketThreshold
     * @param {number=} sparseIterationThreshold
     * @param {number=} getOwnPropertyNamesThreshold
     * @suppressReceiverCheck
     * @this {Object}
     */
    function packRanges(fromIndex, toIndex, bucketThreshold, sparseIterationThreshold, getOwnPropertyNamesThreshold) {
      let ownPropertyNames = null;
      const consecutiveRange = (toIndex - fromIndex >= sparseIterationThreshold) && ArrayBuffer.isView(this);
      const skipGetOwnPropertyNames = consecutiveRange && (toIndex - fromIndex >= getOwnPropertyNamesThreshold);

      function* arrayIndexes(object) {
        if (toIndex - fromIndex < sparseIterationThreshold) {
          for (let i = fromIndex; i <= toIndex; ++i) {
            if (i in object) {
              yield i;
            }
          }
        } else {
          ownPropertyNames = ownPropertyNames || Object.getOwnPropertyNames(object);
          for (let i = 0; i < ownPropertyNames.length; ++i) {
            const name = ownPropertyNames[i];
            const index = name >>> 0;
            if (('' + index) === name && fromIndex <= index && index <= toIndex) {
              yield index;
            }
          }
        }
      }

      let count = 0;
      if (consecutiveRange) {
        count = toIndex - fromIndex + 1;
      } else {
        for (const i of arrayIndexes(this))  // eslint-disable-line
          ++count;
      }

      let bucketSize = count;
      if (count <= bucketThreshold) {
        bucketSize = count;
      } else {
        bucketSize = Math.pow(bucketThreshold, Math.ceil(Math.log(count) / Math.log(bucketThreshold)) - 1);
      }

      const ranges = [];
      if (consecutiveRange) {
        for (let i = fromIndex; i <= toIndex; i += bucketSize) {
          const groupStart = i;
          let groupEnd = groupStart + bucketSize - 1;
          if (groupEnd > toIndex) {
            groupEnd = toIndex;
          }
          ranges.push([groupStart, groupEnd, groupEnd - groupStart + 1]);
        }
      } else {
        count = 0;
        let groupStart = -1;
        let groupEnd = 0;
        for (const i of arrayIndexes(this)) {
          if (groupStart === -1) {
            groupStart = i;
          }
          groupEnd = i;
          if (++count === bucketSize) {
            ranges.push([groupStart, groupEnd, count]);
            count = 0;
            groupStart = -1;
          }
        }
        if (count > 0) {
          ranges.push([groupStart, groupEnd, count]);
        }
      }

      return {ranges: ranges, skipGetOwnPropertyNames: skipGetOwnPropertyNames};
    }

    async function callback(result) {
      if (!result) {
        return;
      }
      const ranges = /** @type {!Array.<!Array.<number>>} */ (result.ranges);
      if (ranges.length === 1) {
        await ArrayGroupingTreeElement._populateAsFragment(treeNode, object, ranges[0][0], ranges[0][1], linkifier);
      } else {
        for (let i = 0; i < ranges.length; ++i) {
          const fromIndex = ranges[i][0];
          const toIndex = ranges[i][1];
          const count = ranges[i][2];
          if (fromIndex === toIndex) {
            await ArrayGroupingTreeElement._populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier);
          } else {
            treeNode.appendChild(new ArrayGroupingTreeElement(object, fromIndex, toIndex, count, linkifier));
          }
        }
      }
      if (topLevel) {
        await ArrayGroupingTreeElement._populateNonIndexProperties(
            treeNode, object, result.skipGetOwnPropertyNames, linkifier);
      }
    }
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {number} fromIndex
   * @param {number} toIndex
   * @param {!Components.Linkifier=} linkifier
   * @return {!Promise}
   * @this {ArrayGroupingTreeElement}
   */
  static async _populateAsFragment(treeNode, object, fromIndex, toIndex, linkifier) {
    const result = await object.callFunction(
        buildArrayFragment,
        [{value: fromIndex}, {value: toIndex}, {value: ArrayGroupingTreeElement._sparseIterationThreshold}]);
    if (!result.object || result.wasThrown) {
      return;
    }
    const arrayFragment = result.object;
    const allProperties =
        await arrayFragment.getAllProperties(false /* accessorPropertiesOnly */, true /* generatePreview */);
    arrayFragment.release();
    const properties = allProperties.properties;
    if (!properties) {
      return;
    }
    properties.sort(ObjectPropertiesSection.CompareProperties);
    for (let i = 0; i < properties.length; ++i) {
      properties[i].parentObject = this._object;
      const childTreeElement = new ObjectPropertyTreeElement(properties[i], linkifier);
      childTreeElement._readOnly = true;
      treeNode.appendChild(childTreeElement);
    }

    /**
     * @suppressReceiverCheck
     * @this {Object}
     * @param {number=} fromIndex // must declare optional
     * @param {number=} toIndex // must declare optional
     * @param {number=} sparseIterationThreshold // must declare optional
     */
    function buildArrayFragment(fromIndex, toIndex, sparseIterationThreshold) {
      const result = Object.create(null);
      if (toIndex - fromIndex < sparseIterationThreshold) {
        for (let i = fromIndex; i <= toIndex; ++i) {
          if (i in this) {
            result[i] = this[i];
          }
        }
      } else {
        const ownPropertyNames = Object.getOwnPropertyNames(this);
        for (let i = 0; i < ownPropertyNames.length; ++i) {
          const name = ownPropertyNames[i];
          const index = name >>> 0;
          if (String(index) === name && fromIndex <= index && index <= toIndex) {
            result[index] = this[index];
          }
        }
      }
      return result;
    }
  }

  /**
   * @param {!UI.TreeElement} treeNode
   * @param {!SDK.RemoteObject} object
   * @param {boolean} skipGetOwnPropertyNames
   * @param {!Components.Linkifier=} linkifier
   * @return {!Promise<undefined>}
   * @this {ArrayGroupingTreeElement}
   */
  static async _populateNonIndexProperties(treeNode, object, skipGetOwnPropertyNames, linkifier) {
    const result = await object.callFunction(buildObjectFragment, [{value: skipGetOwnPropertyNames}]);
    if (!result.object || result.wasThrown) {
      return;
    }
    const allProperties = await result.object.getOwnProperties(true /* generatePreview */);
    result.object.release();
    if (!allProperties.properties) {
      return;
    }
    const properties = allProperties.properties;
    properties.sort(ObjectPropertiesSection.CompareProperties);
    for (const property of properties) {
      property.parentObject = this._object;
      if (!ObjectPropertiesSection._isDisplayableProperty(property, treeNode.property)) {
        continue;
      }
      const childTreeElement = new ObjectPropertyTreeElement(property, linkifier);
      childTreeElement._readOnly = true;
      treeNode.appendChild(childTreeElement);
    }

    /**
     * @param {boolean=} skipGetOwnPropertyNames
     * @suppressReceiverCheck
     * @this {Object}
     */
    function buildObjectFragment(skipGetOwnPropertyNames) {
      const result = {__proto__: this.__proto__};
      if (skipGetOwnPropertyNames) {
        return result;
      }
      const names = Object.getOwnPropertyNames(this);
      for (let i = 0; i < names.length; ++i) {
        const name = names[i];
        // Array index check according to the ES5-15.4.
        if (String(name >>> 0) === name && name >>> 0 !== 0xffffffff) {
          continue;
        }
        const descriptor = Object.getOwnPropertyDescriptor(this, name);
        if (descriptor) {
          Object.defineProperty(result, name, descriptor);
        }
      }
      return result;
    }
  }

  /**
   * @override
   * @returns {!Promise}
   */
  async onpopulate() {
    if (this._propertyCount >= ArrayGroupingTreeElement._bucketThreshold) {
      await ArrayGroupingTreeElement._populateRanges(
          this, this._object, this._fromIndex, this._toIndex, false, this._linkifier);
      return;
    }
    await ArrayGroupingTreeElement._populateAsFragment(
        this, this._object, this._fromIndex, this._toIndex, this._linkifier);
  }

  /**
   * @override
   */
  onattach() {
    this.listItemElement.classList.add('object-properties-section-name');
  }
}

ArrayGroupingTreeElement._bucketThreshold = 100;
ArrayGroupingTreeElement._sparseIterationThreshold = 250000;
ArrayGroupingTreeElement._getOwnPropertyNamesThreshold = 500000;


/**
 * @unrestricted
 */
export class ObjectPropertyPrompt extends UI.TextPrompt {
  constructor() {
    super();
    this.initialize(
        ObjectUI.javaScriptAutocomplete.completionsForTextInCurrentContext.bind(ObjectUI.javaScriptAutocomplete));
  }
}

/**
 * @unrestricted
 */
export class ObjectPropertiesSectionsTreeExpandController {
  /**
   * @param {!UI.TreeOutline} treeOutline
   */
  constructor(treeOutline) {
    /** @type {!Set.<string>} */
    this._expandedProperties = new Set();
    treeOutline.addEventListener(UI.TreeOutline.Events.ElementAttached, this._elementAttached, this);
    treeOutline.addEventListener(UI.TreeOutline.Events.ElementExpanded, this._elementExpanded, this);
    treeOutline.addEventListener(UI.TreeOutline.Events.ElementCollapsed, this._elementCollapsed, this);
  }

  /**
   * @param {string} id
   * @param {!RootElement} section
   */
  watchSection(id, section) {
    section[ObjectPropertiesSectionsTreeExpandController._treeOutlineId] = id;

    if (this._expandedProperties.has(id)) {
      section.expand();
    }
  }

  /**
   * @param {string} id
   */
  stopWatchSectionsWithId(id) {
    for (const property of this._expandedProperties) {
      if (property.startsWith(id + ':')) {
        this._expandedProperties.delete(property);
      }
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _elementAttached(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    if (element.isExpandable() && this._expandedProperties.has(this._propertyPath(element))) {
      element.expand();
    }
  }

  /**
   * @param {!Common.Event} event
   */
  _elementExpanded(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    this._expandedProperties.add(this._propertyPath(element));
  }

  /**
   * @param {!Common.Event} event
   */
  _elementCollapsed(event) {
    const element = /** @type {!UI.TreeElement} */ (event.data);
    this._expandedProperties.delete(this._propertyPath(element));
  }

  /**
   * @param {!UI.TreeElement} treeElement
   * @return {string}
   */
  _propertyPath(treeElement) {
    const cachedPropertyPath = treeElement[ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol];
    if (cachedPropertyPath) {
      return cachedPropertyPath;
    }

    let current = treeElement;
    let sectionRoot = current;
    const rootElement = treeElement.treeOutline.rootElement();

    let result;

    while (current !== rootElement) {
      let currentName = '';
      if (current.property) {
        currentName = current.property.name;
      } else {
        currentName = typeof current.title === 'string' ? current.title : current.title.textContent;
      }

      result = currentName + (result ? '.' + result : '');
      sectionRoot = current;
      current = current.parent;
    }
    const treeOutlineId = sectionRoot[ObjectPropertiesSectionsTreeExpandController._treeOutlineId];
    result = treeOutlineId + (result ? ':' + result : '');
    treeElement[ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol] = result;
    return result;
  }
}

ObjectPropertiesSectionsTreeExpandController._cachedPathSymbol = Symbol('cachedPath');
ObjectPropertiesSectionsTreeExpandController._treeOutlineId = Symbol('treeOutlineId');

/**
 * @implements {UI.Renderer}
 */
export class Renderer {
  /**
   * @override
   * @param {!Object} object
   * @param {!UI.Renderer.Options=} options
   * @return {!Promise<?{node: !Node, tree: ?UI.TreeOutline}>}
   */
  render(object, options) {
    if (!(object instanceof SDK.RemoteObject)) {
      return Promise.reject(new Error('Can\'t render ' + object));
    }
    options = options || {};
    const title = options.title;
    const section = new ObjectPropertiesSection(object, title);
    if (!title) {
      section.titleLessMode();
    }
    section.editable = !!options.editable;
    return Promise.resolve(
        /** @type {?{node: !Node, tree: ?UI.TreeOutline}} */ ({node: section.element, tree: section}));
  }
}

/* Legacy exported object */
self.ObjectUI = self.ObjectUI || {};

/* Legacy exported object */
ObjectUI = ObjectUI || {};

ObjectUI.ArrayGroupingTreeElement = ArrayGroupingTreeElement;

/** @constructor */
ObjectUI.ObjectPropertiesSection = ObjectPropertiesSection;

ObjectUI.ObjectPropertiesSection._maxRenderableStringLength = _maxRenderableStringLength;

/** @constructor */
ObjectUI.ObjectPropertiesSectionsTreeOutline = ObjectPropertiesSectionsTreeOutline;

/**
 * @constructor
 */
ObjectUI.ObjectPropertiesSection.RootElement = RootElement;

/**
 * @constructor
 */
ObjectUI.ObjectPropertiesSection.Renderer = Renderer;

/** @constructor */
ObjectUI.ObjectPropertyTreeElement = ObjectPropertyTreeElement;

/** @constructor */
ObjectUI.ObjectPropertyPrompt = ObjectPropertyPrompt;

/** @constructor */
ObjectUI.ObjectPropertiesSectionsTreeExpandController = ObjectPropertiesSectionsTreeExpandController;

/**
 * @typedef {{
 *   readOnly: (boolean|undefined),
 * }}
 */
ObjectUI.ObjectPropertiesSectionsTreeOutlineOptions;
