parseRequest vs regex vs ufo

Benchmark created on


Setup

// ufo
function parseQuery(parametersString = "") {
  const object = {};
  if (parametersString[0] === "?") {
    parametersString = parametersString.slice(1);
  }
  for (const parameter of parametersString.split("&")) {
    const s = parameter.match(/([^=]+)=?(.*)/) || [];
    if (s.length < 2) {
      continue;
    }
    const key = decodeQueryKey(s[1]);
    if (key === "__proto__" || key === "constructor") {
      continue;
    }
    const value = decodeQueryValue(s[2] || "");
    if (object[key] === undefined) {
      object[key] = value;
    } else if (Array.isArray(object[key])) {
      (object[key]).push(value);
    } else {
      object[key] = [object[key], value];
    }
  }
  return object;
}
const PLUS_RE = /\+/g;
function decodeQueryKey(text) {
  return decode(text.replace(PLUS_RE, " "));
}
function decodeQueryValue(text) {
  return decode(text.replace(PLUS_RE, " "));
}
function decode(text = "") {
  try {
    return decodeURIComponent("" + text);
  } catch {
    return "" + text;
  }
}

// vite
const requestQuerySplitRE = /\?(?!.*[/|}])/
function parseRequest(id){
  const [_, search] = id.split(requestQuerySplitRE, 2)
  if (!search) {
    return null
  }
  return Object.fromEntries(new URLSearchParams(search))
}

const workerRe = /(\?|&)worker(?:&|$)/
const urlRe = /(\?|&)url(?:&|$)/
const rawRe = /(\?|&)raw(?:&|$)/

// data
const urls = [
  '/foo/bar.js',
  '/foo/bar.js?worker',
  '/foo/bar.js?url',
  '/foo/bar.js?worker&url',
  '/foo/bar.js?raw',
  ''
]
  .join('__')
  .repeat(100)
  .split('__')

Test runner

Ready to run.

Testing in
TestOps/sec
ufo
let a = 0, b = 0, c = 0, d = 0
for (const url of urls) {
  let [_, search] = url.split(requestQuerySplitRE, 2)
  if (!search) continue
  search = '?' + search
  const query = parseQuery(search)
  if (!query) continue
  if (query.worker != null) a++
  else if (query.url != null) b++
  else if (query.raw != null) c++
  else d++
}
console.log(a, b, c, d)
ready
regex
let a = 0, b = 0, c = 0, d = 0
for (const url of urls) {
  let [_, search] = url.split(requestQuerySplitRE, 2)
  if (!search) continue
  search = '?' + search
  if (workerRe.test(search)) a++
  else if (urlRe.test(search)) b++
  else if (rawRe.test(search)) c++
  else d++
}
console.log(a, b, c, d)
ready
parseRequest
let a = 0, b = 0, c = 0, d = 0
for (const url of urls) {
  const query = parseRequest(url)
  if (!query) continue
  if (query.worker != null) a++
  else if (query.url != null) b++
  else if (query.raw != null) c++
  else d++
}
console.log(a, b, c, d)
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.