setInternalValue (internalValue) {
    let childValue, child, visible
    let i, j
    const notUpdateDom = false
    const previousChilds = this.childs

    this.type = internalValue.type

    if (internalValue.type === 'array') {
      // array
      if (!this.childs) {
        this.childs = []
      }

      for (i = 0; i < internalValue.childs.length; i++) {
        childValue = internalValue.childs[i]
        if (childValue !== undefined && !(childValue instanceof Function)) {
          if (i < this.childs.length) {
            // reuse existing child, keep its state
            child = this.childs[i]

            child.fieldEditable = false
            child.index = i
            child.setInternalValue(childValue)
          } else {
            // create a new child
            child = new Node(this.editor, {
              internalValue: childValue
            })
            visible = i < this.getMaxVisibleChilds()
            this.appendChild(child, visible, notUpdateDom)
          }
        }
      }

      // cleanup redundant childs
      // we loop backward to prevent issues with shifting index numbers
      for (j = this.childs.length; j >= internalValue.childs.length; j--) {
        this.removeChild(this.childs[j], notUpdateDom)
      }
    } else if (internalValue.type === 'object') {
      // object
      if (!this.childs) {
        this.childs = []
      }

      for (i = 0; i < internalValue.childs.length; i++) {
        childValue = internalValue.childs[i]
        if (childValue !== undefined && !(childValue instanceof Function)) {
          if (i < this.childs.length) {
            // reuse existing child, keep its state
            child = this.childs[i]

            delete child.index
            child.setField(childValue.field, true)
            child.setInternalValue(childValue.value)
          } else {
            // create a new child
            child = new Node(this.editor, {
              field: childValue.field,
              internalValue: childValue.value
            })
            visible = i < this.getMaxVisibleChilds()
            this.appendChild(child, visible, notUpdateDom)
          }
        }
      }

      // cleanup redundant childs
      // we loop backward to prevent issues with shifting index numbers
      for (j = this.childs.length; j >= internalValue.childs.length; j--) {
        this.removeChild(this.childs[j], notUpdateDom)
      }
    } else {
      // value
      this.hideChilds()

      delete this.append
      delete this.showMore
      delete this.expanded
      delete this.childs

      this.value = internalValue.value
    }

    // recreate the DOM if switching from an object/array to auto/string or vice versa
    // needed to recreated the expand button for example
    if (Array.isArray(previousChilds) !== Array.isArray(this.childs)) {
      this.recreateDom()
    }

    this.updateDom({ updateIndexes: true })

    this.previousValue = this.value // used only to check for changes in DOM vs JS model
  }
Set internal value
@param {*} internalValue  Internal value structure keeping type,
                          order and duplicates in objects