Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eligrey/32d6f885e71c6b4cb569fabdd6da2832 to your computer and use it in GitHub Desktop.
Save eligrey/32d6f885e71c6b4cb569fabdd6da2832 to your computer and use it in GitHub Desktop.
airgap.js optimized URL parser screenshot
/**
* Parses potentially stringifiable URL input into a URL instance and returns null if the input is
* an invalid URL or if the input is a data URI, as processing those uses significant resources and we
* don't need to regulate them anyway.
*
* Implemented with four tiers:
* 1. fastest: URL.parse()
* 2. second fastest: URLPattern validation + new URL()
* 3. fast for absolute URLs: DOM validation + new URL() for absolute URLs / try...catch new URL() for relative URLs
* 4. slowest: try...catch new URL()
*
* @param input - Stringifiable URL input (e.g. a string or URL instance)
* @param context - Context URL
* @returns Parsed URL or null
*/
export const parsePotentialURL: (
input: unknown,
context?: URL | Stringifiable,
) => URL | null = parseURLSafe
? // native URL.parse() is supported
(input, context) => (isDataURI(input) ? null : parseURLSafe(input, context))
: validateURL
? // URLPattern validator can be used instead of try...catch
(input, context) =>
!isDataURI(input) && validateURL(input)
? parseURL(input, context)
: null
: HAS_DOM
? // if DOM is available, use input[type=url] validation for absolute URLs
(() => {
const validator = document.createElementNS(
HTML_NS,
'input',
) as HTMLInputElement;
validator.type = 'url';
const validityState = validator.validity;
const setValue = getPropertyDescriptor(HTMLInputElement, 'value').set;
const getValidity = getPropertyDescriptor(ValidityState, 'valid').get;
return (
input: unknown,
context: URL | Stringifiable = locationHref,
) => {
if (isDataURI(input)) {
return null;
}
// DOM can only validate absolute urls, so we still have to fallback
// to parseAndValidateURL for everything that doesn't pass this check
call(setValue, validator, input);
return call(getValidity, validityState)
? parseURL(input, context)
: parseAndValidateURL(input, context);
};
})()
: parseAndValidateURL;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment