[GH-ISSUE #2598] fix(browser): recovered type declarations produce module dependencies #914

Closed
opened 2026-10-15 18:29:32 +00:00 by bsakaguchi · 1 comment
Owner

Originally created by @coygeek on GitHub (Oct 13, 2026).
Original GitHub issue: https://github.com/morluto/rea/issues/2598

Summary

An approved source map containing TypeScript originals produces static module dependency edges for import type and export type declarations. Those type declarations should remain in the recovered source without becoming runtime module relationships.

Steps to reproduce

Save the following controlled-fetch test as src/browser/type-declarations.probe.test.ts and run npm run test:focused -- src/browser/type-declarations.probe.test.ts. It confirms current output against the canonical extractor and includes ordinary import/export controls. No browser or external request is needed.

import { expect, it } from 'vitest';
import { fetchWebSourceMaps } from './WebSourceMapFetcher.js';
import { analyzeWebBundleInputSchema } from '../domain/webBundleAnalysis.js';
import { collectWebModuleImports } from '../domain/webModuleImports.js';
it('compares erased and value module declarations in recovered sources', async () => {
 const origin='https://app.example.test';
 const url=origin+'/app.js.map';
 const input=analyzeWebBundleInputSchema.parse({cdp_endpoint:'http://127.0.0.1:9222',target_id:'page',allowed_origins:[origin],fetch_source_maps:true});
 for(const [source,erased] of [
 ['import type { X } from "./types";',true],
 ['export type { X } from "./types";',true],
 ['import { type X } from "./types";',true],
 ['import { X } from "./types";',false],
 ['export { X } from "./types";',false],
 ] as const) {
   const result=await fetchWebSourceMaps([{scriptKey:'script',declaredUrl:url,fetchUrl:url}],input,undefined,{fetch:async()=>new Response(JSON.stringify({version:3,names:[],sources:['main.ts'],sourcesContent:[source],mappings:'AAAA'}))});
   const item=result.items[0];
   expect(item?.status).toBe('included');
   if(item?.status!=='included') throw new Error('map not included');
   expect(item.original_module_edges).toEqual([{from_source:origin+'/main.ts',kind:'static_import',specifier:'./types',resolved_source:origin+'/types'}]);
   expect(item.original_sources[0]?.artifact?.text).toBe(source);
   expect(item.mappings).toHaveLength(1);
   expect(collectWebModuleImports(source).imports).toHaveLength(erased?0:1);
 }
});

Expected behavior

Recover the source and its mapping while excluding type-only declarations from module dependency edges, using the same native import semantics as the repository owner. Ordinary value imports and exports must remain represented.

Actual behavior

The focused probe observed an included map, retained source text, one mapping, and a static_import edge for each type-only fixture. The canonical native-import extractor returned no imports for those fixtures. Ordinary value controls produced one edge in both representations.

Evidence

  • Expected source: src/domain/webModuleImports.ts:8,57-86 explicitly excludes type-only references; AGENTS.md, Architecture and Cleanup, requires consumers to use the owner’s parsed facts.
  • Failure source: src/browser/WebSourceMapFetcher.ts:1033-1048 treats sourced declarations as static imports without checking their kinds, and src/browser/WebSourceMapFetcher.ts:744-779 records them.
  • Evidence provenance: observed
  • Local verification: reproduced
  • Reproduction completeness: complete

Restoration check

The type-only fixtures must retain their source and mapping but produce no module edge. The ordinary value import/export fixtures must still produce one edge. These results must hold without changing original source bytes.

Runtime or environment

Source revision 8b181716aca2cb467be499cba226abfb5ae19141, Node v26.10.0, npm 11.19.1, Vitest 5.0.3, and the installed lockfile dependencies.

Triage assessment

  • Impact level: P2
  • Assessment status: supported
  • Impact basis: The affected source-map dependency evidence adds relationships for type declarations and can mislead dependency analysis. Source text and mappings remain usable.
  • Workaround status: available
  • Workaround basis: The probe confirms the exact original text is retained, so an analyst can distinguish these declarations manually when reviewing edges.
Originally created by @coygeek on GitHub (Oct 13, 2026). Original GitHub issue: https://github.com/morluto/rea/issues/2598 ## Summary An approved source map containing TypeScript originals produces static module dependency edges for `import type` and `export type` declarations. Those type declarations should remain in the recovered source without becoming runtime module relationships. ## Steps to reproduce Save the following controlled-fetch test as `src/browser/type-declarations.probe.test.ts` and run `npm run test:focused -- src/browser/type-declarations.probe.test.ts`. It confirms current output against the canonical extractor and includes ordinary import/export controls. No browser or external request is needed. ```ts import { expect, it } from 'vitest'; import { fetchWebSourceMaps } from './WebSourceMapFetcher.js'; import { analyzeWebBundleInputSchema } from '../domain/webBundleAnalysis.js'; import { collectWebModuleImports } from '../domain/webModuleImports.js'; it('compares erased and value module declarations in recovered sources', async () => { const origin='https://app.example.test'; const url=origin+'/app.js.map'; const input=analyzeWebBundleInputSchema.parse({cdp_endpoint:'http://127.0.0.1:9222',target_id:'page',allowed_origins:[origin],fetch_source_maps:true}); for(const [source,erased] of [ ['import type { X } from "./types";',true], ['export type { X } from "./types";',true], ['import { type X } from "./types";',true], ['import { X } from "./types";',false], ['export { X } from "./types";',false], ] as const) { const result=await fetchWebSourceMaps([{scriptKey:'script',declaredUrl:url,fetchUrl:url}],input,undefined,{fetch:async()=>new Response(JSON.stringify({version:3,names:[],sources:['main.ts'],sourcesContent:[source],mappings:'AAAA'}))}); const item=result.items[0]; expect(item?.status).toBe('included'); if(item?.status!=='included') throw new Error('map not included'); expect(item.original_module_edges).toEqual([{from_source:origin+'/main.ts',kind:'static_import',specifier:'./types',resolved_source:origin+'/types'}]); expect(item.original_sources[0]?.artifact?.text).toBe(source); expect(item.mappings).toHaveLength(1); expect(collectWebModuleImports(source).imports).toHaveLength(erased?0:1); } }); ``` ## Expected behavior Recover the source and its mapping while excluding type-only declarations from module dependency edges, using the same native import semantics as the repository owner. Ordinary value imports and exports must remain represented. ## Actual behavior The focused probe observed an included map, retained source text, one mapping, and a `static_import` edge for each type-only fixture. The canonical native-import extractor returned no imports for those fixtures. Ordinary value controls produced one edge in both representations. ## Evidence - Expected source: `src/domain/webModuleImports.ts:8,57-86` explicitly excludes type-only references; `AGENTS.md`, Architecture and Cleanup, requires consumers to use the owner’s parsed facts. - Failure source: `src/browser/WebSourceMapFetcher.ts:1033-1048` treats sourced declarations as static imports without checking their kinds, and `src/browser/WebSourceMapFetcher.ts:744-779` records them. - Evidence provenance: observed - Local verification: reproduced - Reproduction completeness: complete ## Restoration check The type-only fixtures must retain their source and mapping but produce no module edge. The ordinary value import/export fixtures must still produce one edge. These results must hold without changing original source bytes. ## Runtime or environment Source revision `8b181716aca2cb467be499cba226abfb5ae19141`, Node v26.10.0, npm 11.19.1, Vitest 5.0.3, and the installed lockfile dependencies. ## Triage assessment - Impact level: P2 - Assessment status: supported - Impact basis: The affected source-map dependency evidence adds relationships for type declarations and can mislead dependency analysis. Source text and mappings remain usable. - Workaround status: available - Workaround basis: The probe confirms the exact original text is retained, so an analyst can distinguish these declarations manually when reviewing edges.
bsakaguchi 2026-10-15 18:29:32 +00:00
Author
Owner

@morluto commented on GitHub (Oct 14, 2026):

Addressed on main in bffdd91053fb5d076b762cf1b325e8dcb5ab2d8c.

Recovered type-only imports and exports no longer create runtime dependency edges.

Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit.

Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.

<!-- gh-comment-id:6159215129 --> @morluto commented on GitHub (Oct 14, 2026): Addressed on main in [bffdd91053fb5d076b762cf1b325e8dcb5ab2d8c](https://github.com/morluto/rea/commit/bffdd91053fb5d076b762cf1b325e8dcb5ab2d8c). Recovered type-only imports and exports no longer create runtime dependency edges. Validation: Affected suites passed in the merged 65-file run (1169 passed, 2 explicit skips), with full static/architecture checks and documentation checks passing. Final installed-package verification is recorded separately in the audit. Verification scope: Controlled source and production-boundary verification on macOS with pinned Node 24.18.0; real external engines and Windows hosts were not independently rerun. Closure covers the described source defect, not broader provider conformance or performance.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#914
No description provided.