fixhunt

biome performance/useGoogleFontPreconnect

labelled safe
Runs / 2026-10-17T20-55-33-669Z-4qfn-biome-performance_useGoogleFontPreconnectbiome 2.5.152026-10-17 20:55 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 5 rejectedmodel cost $0.0033

Analysis Nemotron 3 Super

The rule flags `<link>` elements pointing to `https://fonts.gstatic.com` without a `rel="preconnect"` attribute.

Fix: Adds the attribute `rel="preconnect"` to the `<link>` element if it is missing; if other `rel` values are present, they are preserved and `preconnect` is added as an additional value (e.g., `rel="preload preconnect"`).

8 hazards
  • Adding `preconnect` to `rel` may conflict with existing values like `stylesheet` if the browser prioritizes one over the other, potentially altering resource loading behavior.
  • If the `<link>` tag is inside a conditional comment or template literal that is not parsed as HTML, the rewrite could break syntax or produce invalid markup.
  • The fix may duplicate `preconnect` if the attribute already exists in a different case (e.g., `rel="PreConnect"`), leading to redundant or non-standard values.
  • In JSX, if the `rel` value is dynamically generated via an expression (e.g., `rel={condition ? 'preload' : ''}`), the static rewrite cannot safely inject `preconnect` without risking incorrect runtime values.
  • If the `<link>` element is rendered via `dangerouslySetInnerHTML`, the autofix cannot modify the internal string, so the fix would be inapplicable or misapplied.
  • Moving or dropping comments inside the `<link>` tag (e.g., `<!-- preconnect -->`) during rewrite could remove developer annotations or conditional debugging flags.
  • When the `href` value is constructed via string concatenation or variables (e.g., `href={"https://fonts.gstatic.com" + suffix}`), the rule may incorrectly fire or fail to recognize the target, leading to false positives or missed fixes.
  • In server-side rendering contexts, adding `preconnect` may alter the order of resource hints in the head, potentially affecting how browsers prioritize early connections versus other resources.

Programs

idresulttitlehazard
r1-p001silent prediction offNull/undefined distinction with link flagged by useGoogleFontPreconnectnull/undefined distinction, optional chaining short-circuit, nullish vs falsy
r1-p002silent prediction offASI risk when link precedes parenthesized expressionASI and semicolon-less code, leading ( or [ on the next line
r1-p003silent prediction offThis binding confusion with extracted getter returning flagged linkthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r1-p004silent prediction offArguments object mutation affecting subsequent calls after flagged link creationarguments object, function.length, default parameters, rest parameters
r1-p005silentDangerouslySetInnerHTML prevents external modification of flagged link substringIf the <link> element is rendered via dangerouslySetInnerHTML, the autofix cannot modify the internal string, so the fix would be inapplicable or misapplied.
r1-p006silent prediction offName collision after renaming causes duplicated preconnect attemptsname collisions across scopes after a move (shadowing)
r1-p007silent prediction offGetter/setter side effects interfere with post-fix attribute observationgetters, setters and Object.defineProperty side effects
r1-p008silent prediction offBlock-scoped function declaration redeclaration interacts with loop over flagged linksfunction declarations inside blocks, switch cases, labeled statements
r2-p001invalidConditional comment breaks link rewriteIf the <link> tag is inside a conditional comment or template literal that is not parsed as HTML, the rewrite could break syntax or produce invalid markup.
r2-p002invalidComment removal inside link tag removes debug annotationMoving or dropping comments inside the <link> tag (e.g., <!-- preconnect -->) during rewrite could remove developer annotations or conditional debugging flags.
r2-p003invalidJSX dynamic rel expression prevents safe injectionIn JSX, if the rel value is dynamically generated via an expression (e.g., rel={condition ? 'preload' : ''}), the static rewrite cannot safely inject preconnect without risking incorrect runtime value
r2-p004invalidComments attached to removed/moved code are lostcomments attached to the removed or moved code
r2-p005silent prediction offVar hoisting causes redeclaration conflict after rewritevar hoisting and re-declaration inside loops or after use
r2-p006silent prediction offThis binding confusion in extracted getterthis binding: arrow vs function, methods extracted from objects, call/apply/bind
r2-p007invalidRegex lastIndex interference with global flagregular expressions: escapes, unicode flag, lastIndex with the g flag
r2-p008silent prediction offNumeric/string coercion affects attribute serializationnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt

Sources

r1-p001 · Null/undefined distinction with link flagged by useGoogleFontPreconnect
1let x = document.createElement('link');
2x.href = 'https://fonts.gstatic.com';
3console.log(x.getAttribute('rel') ?? 'missing');
4x.setAttribute('rel', 'preconnect');
5console.log((x.getAttribute('rel') || '') + '-ok');
r1-p002 · ASI risk when link precedes parenthesized expression
1const el = document.createElement('link')
2el.href = 'https://fonts.gstatic.com'
3(function(){ console.log(el.hasAttribute('rel') ? 'has-rel' : 'no-rel') })()
4el.setAttribute('rel', 'preconnect')
5console.log(el.getAttribute('rel'));
r1-p003 · This binding confusion with extracted getter returning flagged link
1const obj = {
2 get link() {
3 const l = document.createElement('link');
4 l.href = 'https://fonts.gstatic.com';
5 return l;
6 }
7};
8const f = obj.link;
9try { console.log(f.getAttribute('href')); } catch(e) { console.log(e.name); }
10const bound = obj.link.bind(obj);
11bound().setAttribute('rel', 'preconnect');
12console.log(bound().getAttribute('rel'));
r1-p004 · Arguments object mutation affecting subsequent calls after flagged link creation
1function makeLink(...args) {
2 const lnk = document.createElement('link');
3 lnk.href = args[0] || 'https://fonts.gstatic.com';
4 arguments[0] = 'changed';
5 return lnk;
6}
7const l1 = makeLink();
8console.log(l1.getAttribute('rel'));
9l1.setAttribute('rel', 'preconnect');
10console.log(l1.getAttribute('rel'));
11const l2 = makeLink();
12console.log(l2.getAttribute('href'));
r1-p005 · DangerouslySetInnerHTML prevents external modification of flagged link substring
1const html = '<link href="https://fonts.gstatic.com" />';
2console.log(html.includes('<link') && html.includes('fonts.gstatic.com'));
3try {
4 const parser = new DOMParser();
5 const doc = parser.parseFromString(html, 'text/html');
6 const link = doc.querySelector('link');
7 console.log(link ? 'parsed' : 'failed');
8 link.setAttribute('rel', 'preconnect');
9 console.log(link.outerHTML);
10} catch(e) { console.log(e.name); }
true
ReferenceError
r1-p006 · Name collision after renaming causes duplicated preconnect attempts
1let link = document.createElement('link');
2link.href = 'https://fonts.gstatic.com';
3{
4 const link = document.createElement('link');
5 link.href = 'https://fonts.gstatic.com';
6 console.log(link.getAttribute('rel'));
7}
8link.setAttribute('rel', 'preconnect');
9console.log(link.getAttribute('rel'));
r1-p007 · Getter/setter side effects interfere with post-fix attribute observation
1const proto = {
2 get tag() { return this._tag || 'link'; },
3 set tag(v) { this._tag = v; }
4};
5const lnk = Object.create(proto);
6lnk.tag = 'link';
7lnk.href = 'https://fonts.gstatic.com';
8Object.defineProperty(lnk, 'rel', {
9 get() { return this.getAttribute('rel'); },
10 set(v) { this.setAttribute('rel', v); this._relSet = true; }
11});
12console.log(lnk.rel);
13lnk.rel = 'preconnect';
14console.log(lnk.rel, lnk._relSet);
r1-p008 · Block-scoped function declaration redeclaration interacts with loop over flagged links
1switch(0) {
2 case 0:
3 function create() {
4 const l = document.createElement('link');
5 l.href = 'https://fonts.gstatic.com';
6 return l;
7 }
8 break;
9}
10const links = [create(), create()];
11links.forEach((l, i) => {
12 if (!l.hasAttribute('rel')) l.setAttribute('rel', 'preconnect');
13 console.log(i, l.getAttribute('rel'));
14});
r2-p001 · Conditional comment breaks link rewrite (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-55-3)
1<!--[if lt IE 9]><link href="https://fonts.gstatic.com"><![endif]-->
2console.log('Template processed')
r2-p002 · Comment removal inside link tag removes debug annotation (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-55-3)
1<link href="https://fonts.gstatic.com" /* preconnect hint */ />
2console.log(document.querySelector('link').outerHTML)
r2-p003 · JSX dynamic rel expression prevents safe injection (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-55-3)
1const condition = true;
2const element = <link href="https://fonts.gstatic.com" rel={condition ? 'preload' : ''} />;
3console.log(element.props.rel)
r2-p004 · Comments attached to removed/moved code are lost (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-55-3)
1// stylesheet link
2<link href="https://fonts.gstatic.com" rel="stylesheet" />
3// end stylesheet
4console.log(document.querySelector('link').outerHTML)
r2-p005 · Var hoisting causes redeclaration conflict after rewrite
1for (var i = 0; i < 2; i++) {
2 var link = document.createElement('link');
3 link.href = 'https://fonts.gstatic.com';
4 document.head.appendChild(link);
5}
6console.log(document.head.children.length)
r2-p006 · This binding confusion in extracted getter
1const obj = {
2 get link() {
3 return '<link href="https://fonts.gstatic.com" />';
4 }
5};
6const getLink = obj.link;
7console.log(getLink())
r2-p007 · Regex lastIndex interference with global flag (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T20-55-3)
1const regex = /https:\/\/fonts\.gstatic\.com/g;
2const str = '<link href="https://fonts.gstatic.com"/> <link href="https://fonts.gstatic.com"/>;
3let match;
4while ((match = regex.exec(str)) !== null) {
5 console.log(match.index);
6}
r2-p008 · Numeric/string coercion affects attribute serialization
1const href = { toString: () => 'https://fonts.gstatic.com' };
2const link = document.createElement('link');
3link.href = href;
4console.log(link.outerHTML)