docs: function tagUnmount(tag, mustKeepRoot, expressions) {
        var __ = tag.__;
        var root = __.root;
        var tagIndex = __TAGS_CACHE.indexOf(tag);
        var p = root.parentNode;
  
        if (!__.skipAnonymous) { tag.trigger('before-unmount'); }
  
        // clear all attributes coming from the mounted tag
        walkAttributes(__.impl.attrs, function (name) {
          if (startsWith(name, ATTRS_PREFIX))
            { name = name.slice(ATTRS_PREFIX.length); }
  
          removeAttribute(root, name);
        });
  
        // remove all the event listeners
        tag.__.listeners.forEach(function (dom) {
          Object.keys(dom[RIOT_EVENTS_KEY]).forEach(function (eventName) {
            dom.removeEventListener(eventName, dom[RIOT_EVENTS_KEY][eventName]);
          });
        });
  
        // remove tag instance from the global tags cache collection
        if (tagIndex !== -1) { __TAGS_CACHE.splice(tagIndex, 1); }
  
        // clean up the parent tags object
        if (__.parent && !__.isAnonymous) {
          var ptag = getImmediateCustomParent(__.parent);
  
          if (__.isVirtual) {
            Object
              .keys(tag.tags)
              .forEach(function (tagName) { return arrayishRemove(ptag.tags, tagName, tag.tags[tagName]); });
          } else {
            arrayishRemove(ptag.tags, __.tagName, tag);
          }
        }
  
        // unmount all the virtual directives
        if (tag.__.virts) {
          each(tag.__.virts, function (v) {
            if (v.parentNode) { v.parentNode.removeChild(v); }
          });
        }
  
        // allow expressions to unmount themselves
        unmountAll(expressions);
        each(__.instAttrs, function (a) { return a.expr && a.expr.unmount && a.expr.unmount(); });
  
        // clear the tag html if it's necessary
        if (mustKeepRoot) { setInnerHTML(root, ''); }
        // otherwise detach the root tag from the DOM
        else if (p) { p.removeChild(root); }
  
        // custom internal unmount function to avoid relying on the observable
        if (__.onUnmount) { __.onUnmount(); }
  
        // weird fix for a weird edge case #2409 and #2436
        // some users might use your software not as you've expected
        // so I need to add these dirty hacks to mitigate unexpected issues
        if (!tag.isMounted) { setMountState.call(tag, true); }
  
        setMountState.call(tag, false);
  
        delete root._tag;
  
        return tag
      }