chore(deps): see imports through comment trivia; name vitest.shared.mts in the README
Both suppressed comments from Copilot's fourth pass of #1962. TypeScript allows a comment anywhere whitespace is legal, so `import(/* webpackIgnore: true */ "pkg")` and `from /* why */ "pkg"` are valid imports the patterns stepped over. That is the dangerous direction: a missed specifier never enters the candidate set, so the package's skew passes the guard silently, against the over-approximation the module claims. A `TRIVIA` fragment now stands in for `\s*` at every inter-token position, with regression cases for the commented static, dynamic, side-effect, and `require` forms. I did not move to the TypeScript parser. This is a root `scripts/` `.mjs` tool with no bundler and no TS dependency; pulling in a compiler API to read import specifiers is a lot of machinery for a scan that only needs to over-approximate, and each missed form is a one-line pattern with a test beside it. The derived set is unchanged at 18 real names, so nothing here widens what is checked today. The README's command row also still described the candidate scan as `core/` and `test-servers/src` only, omitting the `vitest.shared.mts` the guard now includes; it also never mentioned that an allowlisted package is tolerated only within a major. Both stated. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HDdo1rNRVQnVRRdsqSrvG3
This commit is contained in:
parent
35317fd9ed
commit
2dcf1450b2
2 changed files with 39 additions and 5 deletions
|
|
@ -130,11 +130,27 @@ export function packageNameOf(specifier) {
|
|||
// `tools`…" would otherwise enter the candidate set as a package named
|
||||
// `tools`. Inert today, but a prose word that collides with a real package
|
||||
// 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]*?\*/)*`;
|
||||
const SPECIFIER_FORMS = [
|
||||
/\bfrom\s*["']([^"']+)["']/g, // import … from "x" / export … from "x"
|
||||
/\bimport\s+["']([^"']+)["']/g, // side-effect import "x"
|
||||
/\bimport\s*\(\s*["'`]([^"'`]+)["'`]/g, // dynamic import("x"[, opts])
|
||||
/\brequire\s*\(\s*["'`]([^"'`]+)["'`]/g, // import x = require("x"), require("x")
|
||||
// import … from "x" / export … from "x"
|
||||
new RegExp(String.raw`\bfrom${TRIVIA}["']([^"']+)["']`, "g"),
|
||||
// side-effect import "x"
|
||||
new RegExp(String.raw`\bimport${TRIVIA}["']([^"']+)["']`, "g"),
|
||||
// dynamic import("x"[, opts])
|
||||
new RegExp(
|
||||
String.raw`\bimport${TRIVIA}\(${TRIVIA}["'\`]([^"'\`]+)["'\`]`,
|
||||
"g",
|
||||
),
|
||||
// import x = require("x"), require("x")
|
||||
new RegExp(
|
||||
String.raw`\brequire${TRIVIA}\(${TRIVIA}["'\`]([^"'\`]+)["'\`]`,
|
||||
"g",
|
||||
),
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -100,6 +100,24 @@ test("importedPackageNames: CommonJS and awkward dynamic-import forms (Copilot,
|
|||
]);
|
||||
});
|
||||
|
||||
test("importedPackageNames: comment trivia between tokens (Copilot, #1962)", () => {
|
||||
// TypeScript allows a comment anywhere whitespace is legal, so all of these
|
||||
// are valid imports. Missing one is the dangerous direction: the package
|
||||
// never enters the candidate set and its skew passes the guard silently.
|
||||
const source = `
|
||||
import { a } from /* explanation */ "express";
|
||||
const b = await import(/* webpackIgnore: true */ "undici");
|
||||
const c = require(/* lazy */ "yaml");
|
||||
import /* side effect */ "pino";
|
||||
`;
|
||||
assert.deepEqual([...importedPackageNames(source)].sort(), [
|
||||
"express",
|
||||
"pino",
|
||||
"undici",
|
||||
"yaml",
|
||||
]);
|
||||
});
|
||||
|
||||
test("importedPackageNames: the three specifier forms that introduce types", () => {
|
||||
const source = `
|
||||
import { z } from "zod/v4";
|
||||
|
|
|
|||
Loading…
Reference in a new issue