Skip to content

Commit 64a5ecd

Browse files
committed
Gate calls to decodeURIComponent() in url-match.ts. Calling it is very slow, so no need to call if we don't have any %-encoded entities left
1 parent b5938ef commit 64a5ecd

File tree

1 file changed

+20
-13
lines changed

1 file changed

+20
-13
lines changed

src/match/url-match.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -272,19 +272,26 @@ function removePercentEncoding(anchorText: string): string {
272272
// First, convert a few of the known % encodings to the corresponding
273273
// HTML entities that could accidentally be interpretted as special
274274
// HTML characters
275-
const preProcessedEntityAnchorText = anchorText
276-
.replace(/%22/gi, '"') // " char
277-
.replace(/%26/gi, '&') // & char
278-
.replace(/%27/gi, ''') // ' char
279-
.replace(/%3C/gi, '&lt;') // < char
280-
.replace(/%3E/gi, '&gt;'); // > char
275+
// NOTE: This used to be written as 5 separate .replace() calls, but that
276+
// was 25% slower than the current form below according to jsperf
277+
const preProcessedEntityAnchorText = anchorText.replace(/%(?:22|26|27|3C|3E)/gi, match => {
278+
if (match === '%22') return '&quot;'; // %22: '"' char
279+
if (match === '%26') return '&amp;'; // %26: '&' char
280+
if (match === '%27') return '&#39;'; // %27: "'" char
281+
if (match === '%3C' || match === '%3c') return '&lt;'; // %3C: '<' char
282+
/*if (match === '%3E' || match === '%3e')*/ return '&gt;'; // %3E: '>' char
283+
});
281284

282-
try {
283-
// Now attempt to decode the rest of the anchor text
284-
return decodeURIComponent(preProcessedEntityAnchorText);
285-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
286-
} catch (error: unknown) {
287-
// Invalid % escape sequence in the anchor text
288-
return preProcessedEntityAnchorText;
285+
// Now attempt to decode the rest of the anchor text. However, decodeURIComponent()
286+
// is a slow function. Only call if we have remaining %-encoded entities
287+
if (preProcessedEntityAnchorText.includes('%')) {
288+
try {
289+
return decodeURIComponent(preProcessedEntityAnchorText);
290+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
291+
} catch (error: unknown) {
292+
// Invalid % escape sequence in the anchor text, we'll simply return
293+
// the preProcessedEntityAnchorText below
294+
}
289295
}
296+
return preProcessedEntityAnchorText;
290297
}

0 commit comments

Comments
 (0)