docs: function recursiveDiff(vtree, elem) {
    var output = '';
    if (vtree == null && elem != null) {
      // If the VTree ran out but DOM still exists
      output += '<ins>' + utils.elementToString(elem, chars) + '</ins>';
    } else if (isVNode(vtree)) {
      if (!elem || elem.nodeType !== utils.NODE_TYPES.ELEMENT) {
        // If vtree is a VNode, but elem isn't an Element
        output += '<del>' + vNodeToString(vtree, true, false) + '</del>';
        if (elem) {
          output += '<ins>' + utils.elementToString(elem, chars) + '</ins>';
        }
      } else {
        // Diff elements and recurse
        output += diffElements(vtree, elem);
      }
    } else if (isVText(vtree)) {
      if (!elem || elem.nodeType !== utils.NODE_TYPES.TEXT) {
        // If vtree is a VText, but elem isn't a textNode
        output += '<del>' + escapeString(vtree.text) + '</del>';
        if (elem) {
          output += '<ins>' + utils.elementToString(elem, chars) + '</ins>';
        }
      } else {
        output += textDiff(vtree.text, elem.textContent);
      }
    } else if (isWidget(vtree)) {
      var widgetName;
      // Widgets are the construct that hold childViews
      if (vtree.constructor === HTMLCommentWidget) {
        // HTMLCommentWidget is a special case
        if (!elem || elem.nodeType !== utils.NODE_TYPES.COMMENT) {
          output += '<del>' + utils.getCommentString(escapeString(vtree.text), chars) + '</del>';
          if (elem) {
            output += '<ins>' + utils.elementToString(elem, chars) + '</ins>';
          }
        } else {
          output += utils.getCommentString(textDiff(escapeString(vtree.text), elem.textContent), chars);
        }
      } else if (vtree && vtree.view) {
        widgetName = vtree.view.getDebugName();
        if (typeof vtree.templateToString === 'function') {
          widgetName = vtree.templateToString(recursiveDiff);
        }
        if (vtree.view.el !== elem) {
          // If the view at this position isn't bound to elem, something has gone terribly wrong
          output += '<del><ins>' + widgetName + '</ins></del>';
        } else {
          output += widgetName;
        }
      } else if (vtree && typeof vtree.diff === 'function') {
        output += vtree.diff(elem, recursiveDiff);
      } else {
        output += '<del>[Uninitialized child view]</del>';
        output += '<ins>' + utils.elementToString(elem, chars) + '</ins>';
      }
    }
    return output;
  }