function testScript(url, script) {
  let matex1; // main @match / @exclude-match
  let matex2; // custom @match / @exclude-match
  let inex1; // main @include / @exclude
  let inex2; // custom @include / @exclude
  const { custom, meta } = script;
  const len = (matex1 = custom.origMatch && meta.match || '').length
    + (matex2 = custom.match || '').length
    + (inex1 = custom.origInclude && meta.include || '').length
    + (inex2 = custom.include || '').length;
  const ok = (
    // Ok if lists are empty or @match + @include apply
    !len || testRules(url, script, matex1, matex2, inex1, inex2)
  ) && !(
    // and no excludes apply
    ((matex1 = custom.origExcludeMatch && meta.excludeMatch || '').length
      + (matex2 = custom.excludeMatch || '').length
      + (inex1 = custom.origExclude && meta.exclude || '').length
      + (inex2 = custom.exclude || '').length
    ) && testRules(url, script, matex1, matex2, inex1, inex2)
  );
  return ok;
}
As this code is *very* hot, we avoid calling functions or creating possibly big arrays
or creating copies of thousands of keys by prefixing them in `cache`, thus we avoid pauses
due to major GC. The speedup is ~3x (from ~40ms to ~14ms) on a 4GHz CPU
with popular scripts that have lots of @match e.g. Handy Image.