Repository: mozilla/pdf.js
File: src/display/display_utils.js (JavaScript)

Code before:
    reFilename.exec(splitURI[3]);
  if (suggestedFilename) {
    suggestedFilename = suggestedFilename[0];
    if (suggestedFilename.includes("%")) {
      // URL-encoded %2Fpath%2Fto%2Ffile.pdf should be file.pdf
      try {
        suggestedFilename = reFilename.exec(
          decodeURIComponent(suggestedFilename)
        )[0];
      } catch {
        // Possible (extremely rare) errors:
        // URIError "Malformed URI", e.g. for "%AA.pdf"
        // TypeError "null has no properties", e.g. for "%2F.pdf"
      }
    }
  }
  return suggestedFilename || defaultFilename;
}

class StatTimer {
  started = Object.create(null);

  times = [];

  time(name) {
    if (name in this.started) {
      warn(`Timer is already running for ${name}`);
    }
    this.started[name] = Date.now();
  }

  timeEnd(name) {
    if (!(name in this.started)) {
      warn(`Timer has not been started for ${name}`);
    }
    this.times.push({
      name,
      start: this.started[name],
      end: Date.now(),
    });
    // Remove timer from started so it can be called again.
    delete this.started[name];
  }

  toString() {
    // Find the longest name for padding purposes.
    const outBuf = [];
    let longest = 0;
    for (const { name } of this.times) {
      longest = Math.max(name.length, longest);
    }

Review comment (bug):
@calixteman While rebasing patches I noticed this new code, and as far as I can tell this line will *always* throw!? Currently that's obscured by it being placed inside a `try`-block.

Here `decoded` is a string, and String-instances don't have a `test`-method; try running the following in the console:
```javascript
var decoded = "abc";
decoded.test(/^\.pdf$/i)
```
which results in:
```
Uncaught TypeError: decoded.test is not a function
    <anonymous> debugger eval code:2
debugger eval code:2:9
```

This can be "fixed" by swapping the order, i.e. `/^\.pdf$/i.test(decoded)`, however I don't really understand this code to know if that's correct.

Code after:
        try {
          // Attempt to parse the URL using the document's base URI.
          return new URL(urlString, "https://foo.bar");
        } catch {
          try {
            return new URL(decodeURIComponent(urlString), "https://foo.bar");
          } catch {
            return null;
          }
        }
      }
    }
  };

  const newURL = getURL(url);
  if (!newURL) {
    // If the URL is invalid, return the default filename.
    return defaultFilename;
  }

  const decode = name => {
    try {
      let decoded = decodeURIComponent(name);
      if (decoded.includes("/")) {
        decoded = decoded.split("/").at(-1);
        if (decoded.test(/^\.pdf$/i)) {
          return decoded;
        }
        return name;
      }
      return decoded;
    } catch {
      return name;
    }
  };

  const pdfRegex = /\.pdf$/i;
  const filename = newURL.pathname.split("/").at(-1);
  if (pdfRegex.test(filename)) {
    return decode(filename);
  }

  if (newURL.searchParams.size > 0) {
    const values = Array.from(newURL.searchParams.values()).reverse();
    for (const value of values) {
      if (pdfRegex.test(value)) {
        // If any of the search parameters ends with ".pdf", return it.
        return decode(value);
      }
    }
    const keys = Array.from(newURL.searchParams.keys()).reverse();