Surfaced while implementing #6849. Filed unassigned; not fixed there — that card's guard carries a local, documented workaround instead, because js-comment-mask.mjs is shared by many gates and changing it is its own change with its own blast radius.
The defect
scanSource decides a / opens a REGEX when the preceding character is not a value:
if(c==='/'&&!(IDENT_CHAR.test(prev)||prev===')'||prev===']')){/* regex literal */}In a JSX closing tag — IDENT.MEMBER style, e.g. the / in a LT SLASH div GT sequence — the preceding character is LT, which is not a value. So a phantom regex opens and runs to the end of the line, flagging everything after it as literal content.
Measured, on 9ce20233f
const C = ({ open, children }: any) => (open ? <div>{children}</div> : null);
^^^^^^^^^^^^^^^ all flagged literal
Everything from the d of the closing tag to end of line is flagged, including the ) that closes the enclosing call. Any consumer doing delimiter matching over the mask therefore fails to balance.
Concretely, walking every vi.mock call site in the tree, 7 sites in 5 files could not have their argument list delimited:
packages/app-shell/src/console/organizations/__tests__/InviteMemberDialog.placement.test.tsx
packages/app-shell/src/console/organizations/__tests__/InviteMemberDialog.roleCap.test.tsx
packages/app-shell/src/console/organizations/__tests__/acceptInvitationLink.mount.test.tsx
packages/app-shell/src/console/organizations/__tests__/members-role-gating-4475.test.tsx
packages/app-shell/src/console/organizations/__tests__/org-i18n-holdouts-4474.test.tsx
packages/plugin-dashboard/src/__tests__/ObjectDataTable.cells.test.tsx
packages/plugin-dashboard/src/__tests__/ObjectPivotTable.stableEmptyRows.test.tsx
Length-preservingly neutralising the closing tag's slash before masking takes that count to 0, with no site changing verdict — so the closing tag really is the whole cause.
Why it matters beyond the one consumer
check-vi-mock-specifiers.mjs only reads the SPECIFIER, so it never needed to balance anything and has not noticed. But it uses the same literal flags to decide whether a call is embedded (a code sample inside a string) versus real code. A vi.mock call sitting inside a phantom span would be classified embedded and silently dropped from the judged population — a call site that reads as out of scope rather than as unresolved. Not measured to occur today; recorded because the failure direction is the silent one.
The general statement: any gate that uses this module's literal flags for structure over a .tsx/.jsx file is reading flags that are wrong in a shape this repository writes on nearly every line of JSX.
The header's own framing supports filing rather than patching
js-comment-mask.mjs says in as many words that its coverage is "a set of shapes someone thought of — it is strictly weaker than a corpus sweep, and no claim here should be read as covering shapes nobody wrote a case for." JSX is such a shape. The header also records that objectstack has a corpus sweep (check-comment-mask-corpus.mjs) that is not ported here, which is why nothing measured this.
Shape of a fix (for triage, not a decision)
Options, cheapest first:
- Do nothing in the shared module; let each JSX-reading consumer neutralise closing tags itself. Cheap, but it is one copy per consumer of exactly the kind of private workaround this module was created to abolish.
- Teach
scanSource the two JSX slashes (LT SLASH opens no regex; SLASH GT closes a tag). Correct for this tree, but the module is deliberately language-level rather than dialect-level, and the second half collides with a genuine regex spelled SLASH GT SLASH. - Port objectstack's corpus sweep first, then change the module against a measurement rather than against cases. Most expensive, and the only route that answers "which direction does it fail in" instead of guessing.
⭐ Recommend deciding 2-vs-3 rather than 1: the workaround in #6849 is documented and pinned in both directions (it asserts the mis-mask is REAL, so it fails loudly if the shared module is ever fixed), but a second copy of it would be the drift this module exists to stop.
Surfaced while implementing #6849. Filed unassigned; not fixed there — that card's guard carries a local, documented workaround instead, because
js-comment-mask.mjsis shared by many gates and changing it is its own change with its own blast radius.The defect
scanSourcedecides a/opens a REGEX when the preceding character is not a value:In a JSX closing tag —
IDENT.MEMBERstyle, e.g. the/in aLT SLASH div GTsequence — the preceding character isLT, which is not a value. So a phantom regex opens and runs to the end of the line, flagging everything after it as literal content.Measured, on
9ce20233fEverything from the
dof the closing tag to end of line is flagged, including the)that closes the enclosing call. Any consumer doing delimiter matching over the mask therefore fails to balance.Concretely, walking every
vi.mockcall site in the tree, 7 sites in 5 files could not have their argument list delimited:Length-preservingly neutralising the closing tag's slash before masking takes that count to 0, with no site changing verdict — so the closing tag really is the whole cause.
Why it matters beyond the one consumer
check-vi-mock-specifiers.mjsonly reads the SPECIFIER, so it never needed to balance anything and has not noticed. But it uses the sameliteralflags to decide whether a call isembedded(a code sample inside a string) versus real code. Avi.mockcall sitting inside a phantom span would be classifiedembeddedand silently dropped from the judged population — a call site that reads as out of scope rather than as unresolved. Not measured to occur today; recorded because the failure direction is the silent one.The general statement: any gate that uses this module's
literalflags for structure over a.tsx/.jsxfile is reading flags that are wrong in a shape this repository writes on nearly every line of JSX.The header's own framing supports filing rather than patching
js-comment-mask.mjssays in as many words that its coverage is "a set of shapes someone thought of — it is strictly weaker than a corpus sweep, and no claim here should be read as covering shapes nobody wrote a case for." JSX is such a shape. The header also records that objectstack has a corpus sweep (check-comment-mask-corpus.mjs) that is not ported here, which is why nothing measured this.Shape of a fix (for triage, not a decision)
Options, cheapest first:
scanSourcethe two JSX slashes (LT SLASHopens no regex;SLASH GTcloses a tag). Correct for this tree, but the module is deliberately language-level rather than dialect-level, and the second half collides with a genuine regex spelledSLASH GT SLASH.⭐ Recommend deciding 2-vs-3 rather than 1: the workaround in #6849 is documented and pinned in both directions (it asserts the mis-mask is REAL, so it fails loudly if the shared module is ever fixed), but a second copy of it would be the drift this module exists to stop.