From 2f1d97e7bbf4dc38de7cf0f47bab8fa74e202e07 Mon Sep 17 00:00:00 2001 From: cliffhall Date: Mon, 10 Aug 2026 21:13:56 -0400 Subject: [PATCH] chore(deps): treat line comments as trivia too in the import scan MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From Copilot's fifth pass of #1962. `TRIVIA` covered block comments but not `//`, despite the contract right above it saying a comment is legal wherever whitespace is — so `import(// lazy\n"pkg")`, `require(// lazy\n"pkg")`, and `from // reason\n"pkg"` were stepped over, and such a package would never enter the candidate set. Same silent-miss direction as the block-comment gap. Both comment syntaxes are now covered. The line-comment branch runs to end-of-line only; the newline itself is matched by TRIVIA's `\s` branch. Regression test added alongside the block-comment one. The derived set is unchanged at 18 real names — widening trivia does not admit prose, since a specifier must still follow immediately and `packageNameOf` rejects anything not shaped like one. Co-Authored-By: Claude Opus 5 (1M context) Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3 --- scripts/verify-dep-lockstep.mjs | 10 ++++++---- scripts/verify-dep-lockstep.test.mjs | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/scripts/verify-dep-lockstep.mjs b/scripts/verify-dep-lockstep.mjs index 0a328e44..5d29497b 100644 --- a/scripts/verify-dep-lockstep.mjs +++ b/scripts/verify-dep-lockstep.mjs @@ -132,10 +132,12 @@ export function packageNameOf(specifier) { // name would silently widen the set. // // Whitespace between tokens is really *trivia*: TypeScript allows a comment -// anywhere whitespace is legal, so `import(/* webpackIgnore: true */ "pkg")` -// and `from /* why */ "pkg"` are valid and must still be seen (Copilot, -// #1962). `TRIVIA` stands in for `\s*` at every such position. -const TRIVIA = String.raw`(?:\s|/\*[\s\S]*?\*/)*`; +// anywhere whitespace is legal, so `import(/* webpackIgnore: true */ "pkg")`, +// `from /* why */ "pkg"`, and the line-comment forms (`import(// lazy\n"pkg")`) +// are all valid and must still be seen (Copilot, #1962). `TRIVIA` stands in for +// `\s*` at every such position and covers both comment syntaxes. A line comment +// runs to end-of-line only — the newline itself is matched by the `\s` branch. +const TRIVIA = String.raw`(?:\s|/\*[\s\S]*?\*/|//[^\n]*)*`; const SPECIFIER_FORMS = [ // import … from "x" / export … from "x" new RegExp(String.raw`\bfrom${TRIVIA}["']([^"']+)["']`, "g"), diff --git a/scripts/verify-dep-lockstep.test.mjs b/scripts/verify-dep-lockstep.test.mjs index 6d0840d7..eee81432 100644 --- a/scripts/verify-dep-lockstep.test.mjs +++ b/scripts/verify-dep-lockstep.test.mjs @@ -118,6 +118,25 @@ test("importedPackageNames: comment trivia between tokens (Copilot, #1962)", () ]); }); +test("importedPackageNames: line-comment trivia, not just block (Copilot, #1962)", () => { + // `//` runs to end-of-line and is legal in every position a block comment is, + // so these are valid imports too. The newline is matched by TRIVIA's `\\s` + // branch rather than by the line-comment branch. + const source = [ + "import { a } from // reason", + ' "express";', + "const b = await import(// lazy", + ' "undici");', + "const c = require(// lazy", + ' "yaml");', + ].join("\n"); + assert.deepEqual([...importedPackageNames(source)].sort(), [ + "express", + "undici", + "yaml", + ]); +}); + test("importedPackageNames: the three specifier forms that introduce types", () => { const source = ` import { z } from "zod/v4";