docs: function updateExpression(expr) {
        if (this.root && getAttribute(this.root,'virtualized')) { return }
  
        var dom = expr.dom;
        // remove the riot- prefix
        var attrName = normalizeAttrName(expr.attr);
        var isToggle = contains([SHOW_DIRECTIVE, HIDE_DIRECTIVE], attrName);
        var isVirtual = expr.root && expr.root.tagName === 'VIRTUAL';
        var ref = this.__;
        var isAnonymous = ref.isAnonymous;
        var parent = dom && (expr.parent || dom.parentNode);
        // detect the style attributes
        var isStyleAttr = attrName === 'style';
        var isClassAttr = attrName === 'class';
  
        var value;
  
        // if it's a tag we could totally skip the rest
        if (expr._riot_id) {
          if (expr.__.wasCreated) {
            expr.update();
          // if it hasn't been mounted yet, do that now.
          } else {
            expr.mount();
            if (isVirtual) {
              makeReplaceVirtual(expr, expr.root);
            }
          }
          return
        }
  
        // if this expression has the update method it means it can handle the DOM changes by itself
        if (expr.update) { return expr.update() }
  
        var context = isToggle && !isAnonymous ? inheritParentProps.call(this) : this;
  
        // ...it seems to be a simple expression so we try to calculate its value
        value = tmpl(expr.expr, context);
  
        var hasValue = !isBlank(value);
        var isObj = isObject$1(value);
  
        // convert the style/class objects to strings
        if (isObj) {
          if (isClassAttr) {
            value = tmpl(JSON.stringify(value), this);
          } else if (isStyleAttr) {
            value = styleObjectToString(value);
          }
        }
  
        // remove original attribute
        if (expr.attr && (!expr.wasParsedOnce || !hasValue || value === false)) {
          // remove either riot-* attributes or just the attribute name
          removeAttribute(dom, getAttribute(dom, expr.attr) ? expr.attr : attrName);
        }
  
        // for the boolean attributes we don't need the value
        // we can convert it to checked=true to checked=checked
        if (expr.bool) { value = value ? attrName : false; }
        if (expr.isRtag) { return updateDataIs(expr, this, value) }
        if (expr.wasParsedOnce && expr.value === value) { return }
  
        // update the expression value
        expr.value = value;
        expr.wasParsedOnce = true;
  
        // if the value is an object (and it's not a style or class attribute) we can not do much more with it
        if (isObj && !isClassAttr && !isStyleAttr && !isToggle) { return }
        // avoid to render undefined/null values
        if (!hasValue) { value = ''; }
  
        // textarea and text nodes have no attribute name
        if (!attrName) {
          // about #815 w/o replace: the browser converts the value to a string,
          // the comparison by "==" does too, but not in the server
          value += '';
          // test for parent avoids error with invalid assignment to nodeValue
          if (parent) {
            // cache the parent node because somehow it will become null on IE
            // on the next iteration
            expr.parent = parent;
            if (parent.tagName === 'TEXTAREA') {
              parent.value = value;                    // #1113
              if (!IE_VERSION) { dom.nodeValue = value; }  // #1625 IE throws here, nodeValue
            }                                         // will be available on 'updated'
            else { dom.nodeValue = value; }
          }
          return
        }
  
  
        // event handler
        if (isFunction$1(value)) {
          setEventHandler(attrName, value, dom, this);
        // show / hide
        } else if (isToggle) {
          toggleVisibility(dom, attrName === HIDE_DIRECTIVE ? !value : value);
        // handle attributes
        } else {
          if (expr.bool) {
            dom[attrName] = value;
          }
  
          if (attrName === 'value' && dom.value !== value) {
            dom.value = value;
          } else if (hasValue && value !== false) {
            setAttribute(dom, attrName, value);
          }
  
          // make sure that in case of style changes
          // the element stays hidden
          if (isStyleAttr && dom.hidden) { toggleVisibility(dom, false); }
        }
      }