diff --git a/pygitweb/src/pygitweb/static_tests/dom_shim.js b/pygitweb/src/pygitweb/static_tests/dom_shim.js
index b5859f1..5d75b45 100644
--- a/pygitweb/src/pygitweb/static_tests/dom_shim.js
+++ b/pygitweb/src/pygitweb/static_tests/dom_shim.js
@@ -913,6 +913,148 @@
     location.hash = hash;
   }
 
+  function encodeQuery(value) {
+    return encodeURIComponent(String(value)).replace(/%20/g, "+");
+  }
+  function decodeQuery(value) {
+    return decodeURIComponent(String(value).replace(/\+/g, " "));
+  }
+  function queryIterator(items) {
+    var i = 0;
+    var iter = {
+      next: function () {
+        if (i >= items.length) return { done: true };
+        return { done: false, value: items[i++] };
+      },
+    };
+    iter[Symbol.iterator] = function () { return this; };
+    return iter;
+  }
+  function URLSearchParams(init) {
+    this._pairs = [];
+    if (init == null || init === "") return;
+    if (typeof init === "string") {
+      var raw = init.charAt(0) === "?" ? init.slice(1) : init;
+      if (!raw) return;
+      var parts = raw.split("&");
+      for (var i = 0; i < parts.length; i++) {
+        if (!parts[i]) continue;
+        var eq = parts[i].indexOf("=");
+        var key = eq >= 0 ? parts[i].slice(0, eq) : parts[i];
+        var val = eq >= 0 ? parts[i].slice(eq + 1) : "";
+        this._pairs.push([decodeQuery(key), decodeQuery(val)]);
+      }
+      return;
+    }
+    if (init instanceof URLSearchParams) {
+      this._pairs = init._pairs.map(function (pair) { return pair.slice(); });
+      return;
+    }
+    if (typeof init === "object") {
+      for (var name in init) {
+        if (Object.prototype.hasOwnProperty.call(init, name)) this._pairs.push([String(name), String(init[name])]);
+      }
+    }
+  }
+  URLSearchParams.prototype.append = function (name, value) {
+    this._pairs.push([String(name), String(value)]);
+  };
+  URLSearchParams.prototype.set = function (name, value) {
+    name = String(name);
+    value = String(value);
+    var replaced = false;
+    var next = [];
+    for (var i = 0; i < this._pairs.length; i++) {
+      if (this._pairs[i][0] !== name) next.push(this._pairs[i]);
+      else if (!replaced) {
+        next.push([name, value]);
+        replaced = true;
+      }
+    }
+    if (!replaced) next.push([name, value]);
+    this._pairs = next;
+  };
+  URLSearchParams.prototype.get = function (name) {
+    name = String(name);
+    for (var i = 0; i < this._pairs.length; i++) {
+      if (this._pairs[i][0] === name) return this._pairs[i][1];
+    }
+    return null;
+  };
+  URLSearchParams.prototype.has = function (name) {
+    return this.get(name) !== null;
+  };
+  URLSearchParams.prototype.delete = function (name) {
+    name = String(name);
+    this._pairs = this._pairs.filter(function (pair) { return pair[0] !== name; });
+  };
+  URLSearchParams.prototype.toString = function () {
+    return this._pairs.map(function (pair) {
+      return encodeQuery(pair[0]) + "=" + encodeQuery(pair[1]);
+    }).join("&");
+  };
+  URLSearchParams.prototype.keys = function () {
+    return queryIterator(this._pairs.map(function (pair) { return pair[0]; }));
+  };
+  URLSearchParams.prototype.entries = function () {
+    return queryIterator(this._pairs.map(function (pair) { return pair.slice(); }));
+  };
+  URLSearchParams.prototype[Symbol.iterator] = function () { return this.entries(); };
+
+  function URL(href) {
+    this._parse(String(href));
+  }
+  URL.prototype._parse = function (abs) {
+    var hash = "";
+    var hashAt = abs.indexOf("#");
+    if (hashAt >= 0) {
+      hash = abs.slice(hashAt);
+      abs = abs.slice(0, hashAt);
+    }
+    var q = abs.indexOf("?");
+    var path = q >= 0 ? abs.slice(0, q) : abs;
+    var search = q >= 0 ? abs.slice(q) : "";
+    var origin = "";
+    var proto = path.indexOf("://");
+    if (proto >= 0) {
+      var slash = path.indexOf("/", proto + 3);
+      origin = slash >= 0 ? path.slice(0, slash) : path;
+      path = slash >= 0 ? path.slice(slash) : "/";
+    }
+    this.origin = origin;
+    this.pathname = path || "/";
+    this.search = search;
+    this.hash = hash;
+    this.href = origin + this.pathname + search + hash;
+    this._params = null;
+  };
+  URL.prototype.toString = function () { return this.href; };
+  Object.defineProperty(URL.prototype, "searchParams", {
+    get: function () {
+      if (this._params) return this._params;
+      var self = this;
+      var params = new URLSearchParams(this.search);
+      function sync() {
+        var query = params.toString();
+        self.search = query ? "?" + query : "";
+        self.href = self.origin + self.pathname + self.search + (self.hash || "");
+      }
+      ["append", "set", "delete"].forEach(function (method) {
+        var original = params[method];
+        params[method] = function () {
+          var result = original.apply(params, arguments);
+          sync();
+          return result;
+        };
+      });
+      this._params = params;
+      return params;
+    },
+  });
+
+  if (typeof globalThis.URLSearchParams !== "function") globalThis.URLSearchParams = URLSearchParams;
+  if (typeof globalThis.URL !== "function") globalThis.URL = URL;
+
   globalThis.Node = Node;
   globalThis.NodeFilter = NodeFilter;
   globalThis.HTMLElement = HTMLElement;
