Skip to content

Commit 6feb9ec

Browse files
committed
fix(tools): close two edge-detection gaps in the registry boundary guard
Review found the walker missed two forms, both verified against a matrix of every import/export shape: export * as ns from '…' namespace re-export — the star branch had no alias import('…') dynamic import A dynamic import splits the registry into its own chunk rather than the route's initial one, so it does not show up in cold-compile time — but it still puts 4,300 tools' worth of executable config on a client path, which is what this guard exists to prevent. It counts as reaching the registry. No such import exists today; this is purely closing the hole. Adding both raised the measured counts (tables 1,217 -> 1,261, files 1,310 -> 1,419) because lazily-loaded modules are now counted. The registry stays unreachable from all five entries. Also checked and rejected: side-effect imports (`import '@/x'`) were reported as missed, but are matched both standalone and after another import — the `from` clause is already optional.
1 parent 4404d5c commit 6feb9ec

1 file changed

Lines changed: 12 additions & 4 deletions

File tree

scripts/check-tool-registry-boundary.ts

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,19 @@ const ENTRIES = [
5050
const EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.mjs']
5151

5252
/**
53-
* Matches value imports and re-exports, skipping `import type` — a type-only
54-
* edge is erased at compile time and costs nothing at runtime.
53+
* Matches value imports and re-exports, skipping `import type` and
54+
* `export type` — a type-only edge is erased at compile time and costs nothing.
55+
*
56+
* `REEXPORT_RE` allows an alias after the star so `export * as ns from` is not
57+
* missed, and `DYNAMIC_IMPORT_RE` covers `import('…')`. A dynamic import splits
58+
* the registry into its own chunk rather than the route's initial one, but it
59+
* still puts 4,300 tools' worth of executable config on a client path, so it
60+
* counts as reaching it.
5561
*/
5662
const IMPORT_RE = /(?:^|\n)\s*import\s+(?!type\b)(?:[\s\S]*?from\s*)?['"]([^'"]+)['"]/g
57-
const REEXPORT_RE = /(?:^|\n)\s*export\s+(?!type\b)(?:\*|\{[\s\S]*?\})\s*from\s*['"]([^'"]+)['"]/g
63+
const REEXPORT_RE =
64+
/(?:^|\n)\s*export\s+(?!type\b)(?:\*(?:\s+as\s+[\w$]+)?|\{[\s\S]*?\})\s*from\s*['"]([^'"]+)['"]/g
65+
const DYNAMIC_IMPORT_RE = /\bimport\s*\(\s*['"]([^'"]+)['"]\s*\)/g
5866

5967
/** Resolves `@/` and relative specifiers. Bare package specifiers are ignored. */
6068
function resolveSpecifier(specifier: string, importer: string): string | null {
@@ -94,7 +102,7 @@ function walk(entry: string): Walk {
94102
} catch {
95103
continue
96104
}
97-
for (const pattern of [IMPORT_RE, REEXPORT_RE]) {
105+
for (const pattern of [IMPORT_RE, REEXPORT_RE, DYNAMIC_IMPORT_RE]) {
98106
pattern.lastIndex = 0
99107
let match = pattern.exec(source)
100108
while (match !== null) {

0 commit comments

Comments
 (0)