if (!Element.prototype.getInnerHTML) {
  Element.prototype.getInnerHTML = function(opts) {
    var html = this.innerHTML;
    if (!opts || !opts.includeShadowRoots) return html;
    var m = new (self.WeakMap || Map)();
    for (var c of (opts.closedRoots || [])) m.set(c.host, c);
    var p = [];
    function walk(node) {
      var c, shadow = node.shadowRoot || m.get(node);
      if (shadow) p.push(node.innerHTML, `<template shadowroot="${shadow.mode}">${shadow.innerHTML}</template>`);
      var c = node.firstElementChild;
      while (c) { walk(c); c = c.nextElementSibling; }
    }
    walk(this);
    var out = '', c = 0, i = 0, o;
    for (; c<p.length; c+=2) {
      o = html.indexOf(p[c], i);
      if (o < 0) continue;
      out += html.substring(i, o) + p[c+1];
      i = o;
    }
    return out + html.substring(i);
  };
}