fixhunt

biome style/useSelfClosingElements

labelled safe
Runs / 2026-10-17T21-07-02-600Z-c2ro-biome-style_useSelfClosingElementsbiome 2.5.152026-10-17 21:07 UTC8 programs × 2 round(s)16 programs, 0 fired, 0 fixed, 0 findings, 15 rejectedmodel cost $0.0031

Analysis Nemotron 3 Super

Flags JSX elements without children that have explicit closing tags.

Fix: Replaces the explicit opening and closing tags with a single self-closing tag, preserving all attributes, whitespace between '<' and tag name, and whitespace between tag name and '>' if present; removes the entire closing tag including its preceding whitespace.

10 hazards
  • Rewriting <>...</> changes the semantics because React.Fragment without a key cannot be expressed as a self-closing fragment, so the fix would drop the implicit key prop and potentially break reconciliation when used in lists.
  • If the closing tag contains a comment (e.g., </div><!-- note -->), removing it deletes that comment, altering the source file’s comment structure.
  • When ignoreHtmlElements is true, the rule does not fire on HTML elements, but if mistakenly applied, rewriting <div></div> to <div /> could be treated differently by the browser in rare cases involving custom elements or formatting-sensitive contexts.
  • If the opening tag has a spread attribute like <div {...props}></div>, the fix preserves it, but if the spread evaluates to an object containing a children property, removing the closing tag could cause the element to receive an unexpected children prop, altering behavior.
  • If the element is a custom component that relies on receiving children via props.children even when empty (e.g., for layout measurements), changing to self-closing may cause it to receive undefined instead of an empty array, breaking logic that checks Array.isArray(props.children).
  • If the JSX is inside a type assertion or embedded in a larger expression where the parser expects a closing tag to delimit the JSX scope, removing it could cause the parser to consume too many tokens, resulting in a syntax error.
  • If the closing tag is on a separate line and preceded by a line comment (e.g., <div></div> // note ), the fix’s removal of the newline before the closing tag could bring the comment onto the previous line, potentially changing its association or causing trailing whitespace issues.
  • If the element uses a namespace prefix like <svg:circle></svg:circle>, rewriting to <svg:circle /> is valid, but some older JSX transformers might not recognize self-closing namespaced tags, leading to a parse error.
  • If the opening tag contains a JSX expression attribute like <div data-value={getValue()}></div> and getValue() has side effects, the fix does not change evaluation order, but if the closing tag were mistakenly thought to delay execution, removing it could be incorrectly assumed to affect timing—though in reality, no such delay exists.
  • If the file is being processed by a tool that relies on the presence of closing tags to match regions for folding or refactoring, removing them could break those tool’s region detection.

Programs

idresulttitlehazard
r1-p001invalidComments attached to removed/closed tagcomments attached to the removed or moved code
r1-p002silentHTML element misfire under ignoreHtmlElementsWhen ignoreHtmlElements is true, the rule does not fire on HTML elements, but if mistakenly applied, rewriting <div></div> to <div /> could be treated differently by the browser in rare cases involvin
r1-p003invalidVar hoisting and redeclaration inside loopvar hoisting and re-declaration inside loops or after use
r1-p004invalidOrder of evaluation with side effectsorder of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
r1-p005invalidSpread attribute injecting childrenIf the opening tag has a spread attribute like <div {...props}></div>, the fix preserves it, but if the spread evaluates to an object containing a children property, removing the closing tag could cau
r1-p006invalidClass fields, static blocks, private names, superclass fields, static blocks, private names, super calls
r1-p007invalidNamespaced tag with old transformerIf the element uses a namespace prefix like <svg:circle></svg:circle>, rewriting to <svg:circle /> is valid, but some older JSX transformers might not recognize self-closing namespaced tags, leading t
r1-p008invalidSparse arrays and array-likes interactionsparse arrays, holes, Array(n) vs [n], array-likes
r2-p001invalidSpread attribute with children propIf the opening tag has a spread attribute like <div {...props}></div>, the fix preserves it, but if the spread evaluates to an object containing a children property, removing the closing tag could cau
r2-p002invalidName collision across scopes after movename collisions across scopes after a move (shadowing)
r2-p003invalidSparse arrays and array-likes interactionsparse arrays, holes, Array(n) vs [n], array-likes
r2-p004invalidNumeric/string coercion with toString/valueOfnumeric/string coercion: + vs template literal, objects with toString/valueOf, Symbol, BigInt
r2-p005invalidOrder of evaluation with side effectsorder of evaluation when expressions are merged, duplicated or deleted (side effects run twice or never)
r2-p006invalidFragment rewrite drops implicit keyRewriting <>...</> changes the semantics because React.Fragment without a key cannot be expressed as a self-closing fragment, so the fix would drop the implicit key prop and potentially break reconcil
r2-p007invalidComment in closing tag removed by fixIf the closing tag contains a comment (e.g., </div><!-- note -->), removing it deletes that comment, altering the source file’s comment structure.
r2-p008invalidJSX expression attribute with side effectIf the opening tag contains a JSX expression attribute like <div data-value={getValue()}></div> and getValue() has side effects, the fix does not change evaluation order, but if the closing tag were m

Sources

r1-p001 · Comments attached to removed/closed tag (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1let x = 1;
2/* pre */
3<div /* attr */></div>
4/* post */
5x++;
6console.log(x);
r1-p002 · HTML element misfire under ignoreHtmlElements
1const el = document.createElement('div');
2el.innerHTML = '<div></div><span>';// rely on parsing
3console.log(el.childElementCount);
r1-p003 · Var hoisting and redeclaration inside loop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1for (let i = 0; i < 2; i++) {
2 var tmp = i;
3 <span></span> {/* trigger */}
4 console.log(tmp);
5}
r1-p004 · Order of evaluation with side effects (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1let log = [];
2function f() { log.push(1); return {}; }
3<div {...f()}></div>
4console.log(log.length);
r1-p005 · Spread attribute injecting children (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const props = { children: 'bad' };
2const comp = ({ children }) => children || 'ok';
3console.log(<div {...props}>{comp(props)}</div>);
r1-p006 · Class fields, static blocks, private names, super (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1class C {
2 static { <static></static>; }
3 #x = 1;
4 method() { <inst></inst>; return this.#x; }
5}
6console.log(new C().method());
r1-p007 · Namespaced tag with old transformer (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1try {
2 const jsx = <svg:circle></svg:circle>;
3 console.log('parsed', typeof jsx);
4} catch (e) {
5 console.log(e.name + ': ' + e.message);
6}
r1-p008 · Sparse arrays and array-likes interaction (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const arr = Array(3);
2arr[1] = <hole></hole>;
3console.log(arr.length, arr[0] === undefined, arr[1] !== undefined);
r2-p001 · Spread attribute with children prop (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const props = { children: 'unexpected', className: 'box' };
2let result = '';
3const el = <div {...props}></div>;
4if (el.props && el.props.children) {
5 result += el.props.children;
6}
7console.log(result);
r2-p002 · Name collision across scopes after move (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1let x = 1;
2function test() {
3 let x = 2;
4 const inner = <span></span>;
5 { let x = 3; console.log(x); }
6 console.log(x);
7}
8test();
r2-p003 · Sparse arrays and array-likes interaction (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const arr = Array(3);
2arr[1] = 'filled';
3const len = arr.length;
4let count = 0;
5for (let i = 0; i < len; i++) {
6 if (arr[i] !== undefined) count++;
7}
8const el = <div>{count}</div>;
9console.log(el.props.children);
r2-p004 · Numeric/string coercion with toString/valueOf (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const obj = {
2 valueOf() { return 42; },
3 toString() { return 'hello'; }
4};
5const str = `${obj}`;
6const num = +obj;
7const el = <div data-val={str} data-num={num}></div>;
8console.log(el.props['data-val'] + el.props['data-num']);
r2-p005 · Order of evaluation with side effects (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1let side = 0;
2function inc() { return side++; }
3const a = inc();
4const b = inc();
5const el = <div data-a={a} data-b={b}></div>;
6console.log(el.props['data-a'] + el.props['data-b']);
r2-p006 · Fragment rewrite drops implicit key (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1const items = ['a', 'b'];
2const fragments = items.map((item, index) => {
3 return <>key={index}</>;
4});
5console.log(fragments[0].props.key === 0 ? 'ok' : 'broken');
r2-p007 · Comment in closing tag removed by fix (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1// before
2const el = <div></div><!-- note -->;
3// after fix: <div /><!-- note --> becomes <div /> and comment is gone
4console.log('comment presence affects minification safety');
r2-p008 · JSX expression attribute with side effect (generated program does not parse: /home/sun/dev/diaghunt/runs/2026-10-17T21-07-0)
1let log = '';
2function getValue() { log += 'called'; return 42; }
3const el = <div data={getValue()}></div>;
4console.log(log);