import { globalURLPattern as URLPattern } from "./url-pattern-global"; import { URLPatternResult } from "./types"; import { compositeKey } from "@virtualstate/composite-key"; export { URLPatternInit } from "./url-pattern-global"; export { URLPattern } export function isURLPatternStringWildcard(pattern: string): pattern is "*" { return pattern === "*"; } const patternSymbols = Object.values({ // From https://wicg.github.io/urlpattern/#parsing-patterns open: "{", close: "}", regexpOpen: "(", regexpClose: ")", nameStart: ":", asterisk: "*" } as const); export const patternParts = [ "protocol", "hostname", "username", "password", "port", "pathname", "search", "hash" ] as const; export function isURLPatternStringPlain(pattern: string) { for (const symbol of patternSymbols) { if (pattern.includes(symbol)) { return false; } } return true; } export function isURLPatternPlainPathname(pattern: URLPattern) { if (!isURLPatternStringPlain(pattern.pathname)) { return false; } for (const part of patternParts) { if (part === "pathname") continue; if (!isURLPatternStringWildcard(pattern[part])) { return false; } } return true; } type CompositeObjectKey = Readonly<{ __proto__: null }>; // Note, this weak map will contain all urls // matched in the current process. // This may not be wanted by everyone let execCache: WeakMap | undefined = undefined; export function enableURLPatternCache() { execCache = execCache ?? new WeakMap(); } export function exec(pattern: URLPattern, url: URL): URLPatternResult | undefined { if (!execCache) { return pattern.exec(url); } const key = compositeKey( pattern, ...patternParts .filter(part => !isURLPatternStringWildcard(pattern[part])) .map(part => url[part]) ); const existing = execCache.get(key); if (existing) return existing; if (existing === false) return undefined; const result = pattern.exec(url); execCache.set(key, result ?? false); return result; }