Skip to content

fix(compiler): preserve coverage pragmas in JSX - #3301

Merged
ryansolid merged 4 commits into
solidjs:nextfrom
nickshiro:fix/compiler-istanbul-comments
Sep 30, 2026
Merged

ryansolid merged 4 commits into
solidjs:nextfrom
nickshiro:fix/compiler-istanbul-comments

Conversation

@nickshiro

Copy link
Copy Markdown

Summary

ref #2138

Preserve JSX Istanbul ignore comments when compiling component children, and annotate compiler-generated ref dispatch branches so they do not count toward coverage.

  • Add /* istanbul ignore next */ annotations to compiler-generated conditional ref dispatches.
  • Add regression coverage.

How did you test this change?

  • pnpm --filter @solidjs/babel-plugin exec vitest run
    28 test files passed, 259 tests passed

  • pnpm --filter @solidjs/babel-plugin typecheck

@changeset-bot

changeset-bot Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 3d20da1

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 12 packages
Name Type
@solidjs/babel-plugin Patch
@solidjs/compiler Patch
test-integration Patch
@solidjs/diagnostics Patch
@solidjs/element Patch
@solidjs/h Patch
@solidjs/html Patch
@solidjs/signals Patch
solid-js Patch
@solidjs/universal Patch
@solidjs/web Patch
todos-server-example Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@codspeed

codspeed Bot commented Sep 7, 2026 •

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 185 untouched benchmarks
⏩ 3 skipped benchmarks1


Comparing nickshiro:fix/compiler-istanbul-comments (3d20da1) with next (b0c8489)

Open in CodSpeed

Footnotes

  1. 3 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports. ↩

@ryansolid

Copy link
Copy Markdown
Member

Thanks for taking this on — half of it is exactly what we want, and the diff splits cleanly along that line.

Keep: preserving the user's own pragma. A {/* istanbul ignore next */} the author wrote in JSX should survive onto the get children() getter the compiler emits. That is comment fidelity for a deliberate annotation, and it's the right layer for it. Two asks on this half:

  • Match c8 ignore alongside istanbul ignore (/^\s*(istanbul|c8)\s+ignore\b/). v8-based coverage is what most Vitest users run now, and it's the same regex.
  • Oxc parity. The Babel plugin and packages/compiler share codegen expectations; the same carry-through needs to land in the native compiler with the shared fixture before this can merge.

Drop: injecting /* istanbul ignore next */ on the generated ref dispatch. This is the part that touches dom/element.ts, universal/element.ts, and rewrites fourteen fixture outputs, and we don't want it — not for size, on principle:

  • The compiler would be emitting a specific tool's pragma into every user's output. That's tool knowledge in the wrong layer, and it doesn't stop at one vendor.
  • Coverage of compiler-generated branches is the coverage tool's problem, and the tools have been solving it: v8 coverage with AST-aware remapping attributes back through the source map to the JSX, where there is no branch. Instrumenting post-compile output with Istanbul is the configuration that produces the phantom branches.
  • Every injected comment is dev-build bytes for everyone and one more thing both compilers must mirror forever.

If real demand shows up later, an explicit opt-in is the ceiling we'd consider, but we'd rather not add it speculatively.

Also: @solidjs/web#test-types is red on this branch. It's probably the base (next moved on Sep 7); a rebase should tell.

Once it's down to the preserve half + c8 + Oxc parity, happy to merge.

— Claude via Cursor

@nickshiro

nickshiro commented Sep 9, 2026 •

Copy link
Copy Markdown
Author
  • Removed all automatically injected coverage comments from generated ref dispatches.
  • Preserved only user-authored JSX pragmas, now supporting both istanbul ignore and c8 ignore.
  • Added Oxc parity for DOM, Universal, and SSR.
  • Added a shared fixture consumed by the Babel and native compiler regression tests.

Thanks for your review!

@nickshiro nickshiro changed the title fix(babel): preserve Istanbul ignore comments in generated output fix(compiler): preserve coverage pragmas in JSX Sep 9, 2026

@ryansolid ryansolid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is now exactly the shape we asked for — thanks. The injection is gone, the (istanbul|c8)\s+ignore\b match is right, and the Oxc port is a real one (the closing-} span trick for comment attachment is a good way to do it) with the shared fixture driving both compilers.

One blocker: the native compiler doesn't build. source() was added to the ModeLower trait and implemented for AstDomTransform and AstUniversalTransform, but AstSsrTransform (packages/compiler/src/ssr/transform.rs, the impl ModeLower near the bottom) was missed:

error[E0046]: not all trait items implemented, missing: `source`

Same three lines as the other two impls:

fn source(&self) -> &str {
    self.source
}

Please also rebase onto next — the CodSpeed and Size failures are inherited from the base at the time you branched and will clear — and run the Rust side before pushing (cargo build / pnpm --filter @solidjs/compiler test), since the JS tests alone can't see this.

Two nits, take or leave: the Babel test is in ref-spread.spec.js, which is about intrinsic ref/spread sources — a coverage-pragmas.spec.js (or the shared-fixtures runner) would be a more findable home. And the Oxc path re-emits every comment ahead of the }, so {/* note */ /* c8 ignore next */} prints both where Babel prints only the pragma; fine as is, just noting the fidelity difference.

Once it builds green this merges.

— Claude via Cursor

@nickshiro
nickshiro force-pushed the fix/compiler-istanbul-comments branch from 961bd14 to 03073b2 Compare September 25, 2026 18:38
@nickshiro

Copy link
Copy Markdown
Author

Addressed the build blocker by implementing ModeLower::source() for AstSsrTransform and rebased onto the latest next. Verified with cargo build, the full compiler test suite (5944 tests), and the targeted Babel/Oxc coverage pragma tests. Everything passes now. Thanks and sorry about my vacation)

ryansolid and others added 2 commits September 30, 2026 09:05
Both compilers now agree on which authored pragmas lead a component's
`children` getter:

- Block comments only: line comments are never carried (Oxc dropped
  `{// c8 ignore next}` and misread `// c8 ignore` inside a block comment).
- Pragmas from consecutive empty containers are all carried, in order
  (Oxc kept only the last container).
- A pragma followed by text still leads the getter (Babel dropped it when
  the next child was text or a same-line space).
- Only pragmas print, not neighboring notes in the same container.

Oxc re-anchors each run's pragma comments to the first pragma's start and
spans the getter there. The shared fixture covers every case with
expectations both test suites assert across dom/ssr/universal.

Co-authored-by: Claude via Cursor <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

@ryansolid ryansolid left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nickshiro — the SSR source() fix and the rebase are exactly what was needed, and the native build is green.

On a final parity pass we ran both compilers side by side across DOM, SSR and universal and found four edge cases that were already there at our last review. Rather than ask for another round, we fixed them ourselves in 3d20da1:

  • Line comments: Oxc dropped {// c8 ignore next} and misread // c8 ignore inside a block comment. Both compilers now carry block-comment pragmas only.
  • Consecutive pragma containers: Oxc kept only the last {/* … */}. Both now carry every pragma, in order.
  • Pragma followed by text: Babel dropped the pragma when the next child was text or a same-line space. Both now keep it on the getter.
  • Note beside a pragma: Oxc printed neighboring non-pragma comments too. Both now print only the pragmas.

The shared fixture now covers every case, and both test suites assert one shared set of expectations. It lands in rc.14.

— Claude via Cursor

@ryansolid
ryansolid merged commit 3c1f809 into solidjs:next Sep 30, 2026
5 of 6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants