Skip to content

perf(bundle-source): cut multi-entry agoric bundling time and add detailed profiling#3099

Draft
turadg wants to merge 22 commits into
masterfrom
codex/bundle-source-profiling
Draft

perf(bundle-source): cut multi-entry agoric bundling time and add detailed profiling#3099
turadg wants to merge 22 commits into
masterfrom
codex/bundle-source-profiling

Conversation

@turadg

@turadg turadg commented Feb 19, 2026

Copy link
Copy Markdown
Member

Refs: (none)

Description

This PR speeds up @endo/bundle-source for multi-entrypoint workloads (notably agoric-sdk) and improves profiling visibility for further tuning.

Primary changes:

  • Add richer end-to-end profiling and trace merge summaries:
    • packages/bundle-source/tools/profile-agoric-bundling.mts
    • packages/bundle-source/tools/trace-merge.js
  • Add import/parse/transform instrumentation in compartment-mapper and evasive-transform.
  • Optimize node-modules graph finalization path (finalizeGraph) and canonical/read behavior:
    • packages/compartment-mapper/src/generic-graph.js
    • packages/compartment-mapper/src/node-modules.js
    • packages/compartment-mapper/src/node-powers.js
    • packages/compartment-mapper/src/import-hook.js
    • packages/compartment-mapper/src/map-parser.js
  • Add cross-bundle parser reuse in archive parsing:
    • packages/compartment-mapper/src/parse-archive-mjs.js
  • Improve archive/zip path and add zip microbenchmark tooling:
    • packages/compartment-mapper/src/archive-lite.js
    • packages/zip/src/writer.js
    • packages/zip/src/format-writer.js
    • packages/zip/tools/benchmark-writer.mjs
  • Add/read cache behavior in bundle-source zip bundling path:
    • packages/bundle-source/src/zip-base64.js

Measured result from yarn workspace @endo/bundle-source profile:agoric-bundling:

  • Baseline: /var/folders/v2/309w97f90q5d0r47d3np62v40000gn/T/profile-agoric-bundling-2026-02-19T21-21-58-060Z
    • bundleSource.total: 13180.267ms
  • Latest: /var/folders/v2/309w97f90q5d0r47d3np62v40000gn/T/profile-agoric-bundling-2026-02-19T23-00-54-856Z
    • bundleSource.total: 7538.092ms

Total win: -42.8% (-5642.175ms)

Optimization contribution checkpoints:

  • Node-modules/read-path optimizations (21:21:58 -> 21:33:22):
    • 13180.267ms -> 10021.350ms (-23.97%)
  • Zip path tuning and profiling (21:33:22 -> 21:53:12):
    • 10021.350ms -> 9884.006ms (-1.37%)
  • Cross-bundle parse reuse (21:53:12 -> 23:00:54):
    • 9884.006ms -> 7538.092ms (-23.74%)
    • cache stats (latest): 3887 hits / 357 misses (~91.6% hit rate)

Security Considerations

No new external runtime dependency is introduced.

Changes are internal performance/instrumentation improvements in bundling and zip writing code paths. New behavior is primarily caching and profiling spans. Cache scope remains process-local and only stores parser output for identical transformed source/module URL combinations.

Scaling Considerations

This PR is intended to reduce CPU and wall-clock time for repeated bundling of overlapping dependency graphs.

Tradeoffs:

  • Added in-process caches increase transient memory usage.
  • Cache in parse-archive-mjs is bounded by an entry cap and resets when exceeding the cap.

Net effect on profiled workload is significantly lower bundling latency.

Documentation Considerations

No end-user API change.

Operationally useful additions:

  • New @endo/zip benchmark script: yarn workspace @endo/zip bench:writer
  • Enhanced profiling summaries for bundle-source tooling.

No migration instructions needed.

Testing Considerations

Executed tests include:

  • yarn workspace @endo/zip test
  • yarn workspace @endo/compartment-mapper test test/map-node-modules.test.js
  • yarn workspace @endo/compartment-mapper test test/node-powers.test.js
  • yarn workspace @endo/compartment-mapper test test/parse-archive-mjs.test.js
  • yarn workspace @endo/compartment-mapper test test/bundle.test.js (known expected failure remains)
  • yarn workspace @endo/bundle-source test test/profiling.test.js
  • yarn workspace @endo/bundle-source test test/comment.test.js
  • Multiple runs of yarn workspace @endo/bundle-source profile:agoric-bundling

Compatibility Considerations

No intentional breaking changes.

Behavior should remain compatible; changes are performance-oriented and profiling-oriented with conservative cache bypass conditions where side effects may exist.

Upgrade Considerations

No special upgrade action required.

No *BREAKING* change in commit message and no NEWS.md entry added, since this is internal perf and tooling behavior.

Copilot AI review requested due to automatic review settings February 19, 2026 23:07
@changeset-bot

changeset-bot Bot commented Feb 19, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: a5ef3f0

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces significant performance optimizations for @endo/bundle-source targeting multi-entry bundling workloads, achieving a reported ~43% speedup on agoric-sdk bundling tasks. The changes focus on three main areas: profiling infrastructure, caching mechanisms, and algorithmic optimizations.

Changes:

  • Adds comprehensive Chrome trace profiling with tooling for aggregation and analysis
  • Implements multiple caching layers: process-global read cache, parse result cache, canonical path memoization, and import hook read cache
  • Optimizes graph shortest-path computation by computing Dijkstra once from source
  • Adds fast-path optimization in evasive-transform to skip parsing when no risky patterns are detected
  • Enhances ZIP writing with pre-allocation and profiling instrumentation

Reviewed changes

Copilot reviewed 33 out of 34 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
packages/bundle-source/src/profile.js New profiling module with Chrome trace output
packages/bundle-source/src/zip-base64.js Adds process-global read cache and profiling integration
packages/bundle-source/src/script.js Integrates profiling into script bundling path
packages/bundle-source/src/endo.js Adds profiling spans to transform and type-erasure steps
packages/bundle-source/tools/profile-agoric-bundling.mts Tool for profiling agoric-sdk bundle workloads
packages/bundle-source/tools/trace-merge.js Merges and summarizes multiple trace files
packages/bundle-source/test/profiling.test.js Basic profiling functionality test
packages/compartment-mapper/src/parse-archive-mjs.js Adds parse result caching with 20k entry limit
packages/compartment-mapper/src/node-powers.js Adds canonical path memoization and concurrent read limiting
packages/compartment-mapper/src/import-hook.js Adds per-operation read cache and suffix expansion optimization
packages/compartment-mapper/src/generic-graph.js New makeShortestPathFromSource for single-source shortest paths
packages/compartment-mapper/src/node-modules.js Uses optimized single-source Dijkstra algorithm
packages/compartment-mapper/src/archive-lite.js Adds profiling and optimizes synchronous write detection
packages/evasive-transform/src/index.js Adds fast-path to skip transform when no risky patterns detected
packages/zip/src/writer.js Pre-allocates buffer and adds profiling support
packages/zip/src/format-writer.js Adds profiling spans and optimizes record building
packages/zip/tools/benchmark-writer.mjs New ZIP writer microbenchmark tool
Comments suppressed due to low confidence (6)

packages/compartment-mapper/src/import-hook.js:669

  • The cached read promise is removed from cache on rejection (line 666), but successful reads are never removed. This cache is scoped to a single mapping run via makeImportHookMaker, so it's bounded by the lifetime of a single bundle operation. However, there's no maximum size limit, so a bundle with thousands of modules could accumulate all successful reads in memory without bound during that operation.
  const cachedMaybeRead = location => {
    const cached = maybeReadCache.get(location);
    if (cached !== undefined) {
      return cached;
    }
    const pending = Promise.resolve(maybeRead(location));
    maybeReadCache.set(location, pending);
    pending.catch(() => {
      maybeReadCache.delete(location);
    });
    return pending;
  };

packages/bundle-source/src/zip-base64.js:62

  • The cache eviction in cacheReadValue uses FIFO (first-in-first-out) by removing the first entry from the Map iterator. However, JavaScript Map iteration order is insertion order, not access order. This means frequently accessed entries can be evicted before rarely accessed ones. Consider using an LRU (Least Recently Used) eviction policy for better cache hit rates, or at minimum document this FIFO behavior.
  while (cachedReadBytes > readCacheMaxBytes && cachedReads.size > 0) {
    const oldestKey = cachedReads.keys().next().value;
    if (oldestKey === undefined) {
      break;
    }
    const value = cachedReads.get(oldestKey);
    cachedReads.delete(oldestKey);
    if (value !== undefined) {
      cachedReadBytes -= value.length;
    }
  }

packages/bundle-source/src/script.js:112

  • Inconsistent indentation: lines 111-112 have different indentation from surrounding lines (lines 110 and 113-129). Line 111 should be indented to align with line 110, and line 112 should be indented to align with line 113.
      commonDependencies,
      profileStartSpan: profiler.startSpan,

packages/compartment-mapper/src/archive-lite.js:102

  • The duck-typing check for Promise (lines 97-101) is fragile. It checks for an object with a then property that's a function, but this will incorrectly treat any thenable (including user-defined thenables or objects that happen to have a then method) as a Promise. Use maybeWrite instanceof Promise or Promise.resolve(maybeWrite) === maybeWrite for more robust Promise detection, or check for maybeWrite?.constructor?.name === 'Promise'.
          if (
            maybeWrite &&
            typeof maybeWrite === 'object' &&
            'then' in maybeWrite &&
            typeof maybeWrite.then === 'function'
          ) {

packages/bundle-source/src/profile.js:10

  • The nextTraceFileId counter at module scope will never reset and could theoretically overflow after 2^53 trace files in a long-running process. While extremely unlikely in practice, consider resetting it periodically or using a timestamp-based approach instead. Alternatively, document that this is acceptable given the improbability of reaching Number.MAX_SAFE_INTEGER trace files.
let nextTraceFileId = 0;

packages/zip/src/writer.js:20

  • The size estimation assumes ASCII-only filenames (comment on line 18-19 acknowledges this). However, for non-ASCII paths, the BufferWriter may need to grow significantly. Consider using TextEncoder.encode(file.name).length for more accurate size estimation of UTF-8 encoded paths, especially since the actual encoding uses UTF-8.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/compartment-mapper/src/parse-archive-mjs.js Outdated
Comment thread packages/compartment-mapper/src/parse-archive-mjs.js
Comment thread packages/bundle-source/src/zip-base64.js Outdated
Comment thread packages/compartment-mapper/src/import-hook.js
Comment thread packages/compartment-mapper/src/import-hook.js Outdated
@turadg turadg marked this pull request as draft February 19, 2026 23:20
Comment thread packages/bundle-source/src/profile.js Outdated
Comment thread packages/bundle-source/src/profile.js Outdated
Comment thread packages/bundle-source/src/profile.js Outdated
Comment thread packages/bundle-source/src/profile.js Outdated
Comment thread packages/bundle-source/src/profile.js
Comment thread packages/compartment-mapper/src/import-hook.js Outdated
Comment thread packages/compartment-mapper/src/node-powers.js
Comment thread packages/compartment-mapper/src/parse-archive-mjs.js Outdated
Comment thread packages/compartment-mapper/src/parse-archive-mjs.js
Comment thread packages/evasive-transform/src/index.js
kriscendobot pushed a commit to kriskowal/garden that referenced this pull request May 22, 2026
e9cc5a: builder mirrors endojs/endo#3099 (bundle-source perf + profiling) onto master.
9ecbfc: designer authors stacked siblings of designs/gateway-package.md — packaging-CI + AWS deployment (+ optional AWS-attuned variant).
kriscendobot pushed a commit to kriskowal/garden that referenced this pull request May 22, 2026
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
…ailed profiling

Squashed mirror of endojs/endo#3099 (10 commits by Turadg Aleahmad,
2026-02 to 2026-02-19) collapsing the profiling work into one commit
for mirror-side rebase tractability.

Speed up @endo/bundle-source for multi-entrypoint workloads (notably
agoric-sdk) and add richer profiling spans across compartment-mapper,
evasive-transform, module-source, and zip. Optimizes node-modules
graph finalization, adds cross-bundle parser reuse in archive parsing,
improves the archive/zip path, and adds zip microbenchmark tooling.

Measured on yarn workspace @endo/bundle-source profile:agoric-bundling:
13180ms baseline to 7538ms latest, a 42.8% reduction.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
Three logical items the panel surfaced on the cleaner head 2586a99, all
flowing from type-narrowness gaps the perf instrumentation introduced:

1. packages/bundle-source/src/profile.js: type the disabled-profiler
   noop's startSpan and flush to the same shape published by
   BundlingKitOptions.profiler in types.ts; the discriminated noop now
   accepts Record<string, unknown> args like the live profiler. Closes
   TS2322 at script.js:93,115 and zip-base64.js:188,204,227; closes
   TS2345 at script.js:171 and zip-base64.js:264.

2. packages/zip/src/writer.js: replace `Array<ZFile>` with
   `Array<ArchivedFile>` via a top-level `@import` from types.js, fix the
   orphaned `/** type {Map<string, ZFile>} */` JSDoc tag (missing leading
   @) on this.files, and propagate the type through the writeZip
   declarations. Closes TS2552. Drive-by: widen the write() options.date
   to `Date | null` and default to null so the assignment to
   ArchivedFile.date (which is Date?) typechecks; add the missing
   `type: 'file'` discriminant on the ArchivedFile record.

3. packages/compartment-mapper/src/import-hook.js,
   packages/compartment-mapper/src/map-parser.js,
   packages/bundle-source/src/zip-base64.js: seed `moduleBytes`,
   `language`, `endoZipBase64` with explicit `undefined` defaults at
   declaration (and widen the type to `T | undefined` where needed) so
   the `finally`-block reads pass TS flow analysis. Closes TS2454 at all
   three sites.

Gate-driven collateral (no behavior change):
- packages/compartment-mapper/src/import-hook.js: lift the inline
  `import('ses').Harden` JSDoc to a top-level `@import {Harden} from 'ses'`
  to satisfy no-inline-import-jsdoc.
- packages/evasive-transform/src/index.js: lift the inline
  `import('./parse-ast.js').SourceType` and
  `import('@babel/traverse').NodePath` JSDoc into the existing top-level
  `@import` block.
- packages/bundle-source/README.md: split the two-sentence physical line
  "Each bundle call writes one *.trace.json file. Open these in Chrome
  tracing tools..." per the sentence-per-line markdown style.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
Seven of the eight items the panel surfaced as `summary-fix` on the
cleaner head 2586a99. Item 8 (the orphaned `/** type {Map<string,
ZFile>} */` JSDoc tag at zip/src/writer.js:37) shipped in the must-fix
commit alongside the ZFile -> ArchivedFile rename it interacts with.

1. packages/bundle-source/src/profile.js: when ENDO_BUNDLE_SOURCE_PROFILE_STDERR
   is truthy, emit the resolved trace path at profiler construction (one
   line), not only at successful flush. Surfaces an auto-resolved
   `os.tmpdir()` fallback path early enough for the user to redirect or
   pre-create the directory when the default is non-writable.

2. packages/bundle-source/src/zip-base64.js: warn to stderr when
   `ENDO_BUNDLE_SOURCE_READ_CACHE_MAX_BYTES` has a non-numeric tail
   (e.g., "100mb") that `Number.parseInt` would silently truncate. The
   README documents the env as a raw byte count; surface the truncation
   rather than honoring a misleading value.

3. packages/bundle-source/src/zip-base64.js: document the
   insertion-order (FIFO) eviction discipline of `cachedReads` in a
   file-header comment. Cache hits do not promote; under a working set
   larger than `readCacheMaxBytes` the cache degrades gracefully but is
   not classic LRU. Documenting the choice rather than implementing LRU
   because the agoric-sdk workload the cache was sized for fits within
   the default cap.

4. packages/compartment-mapper/src/parse-archive-mjs.js: lift the
   hardcoded `MAX_PARSE_ARCHIVE_MJS_CACHE_ENTRIES = 20_000` to an env
   override (`ENDO_PARSE_ARCHIVE_MJS_CACHE_ENTRIES`) and emit a one-time
   stderr warning on cap-hit so a workload exceeding the default surface
   the situation rather than silently thrashing the cache to one entry.

5. packages/bundle-source/README.md: document
   `ENDO_BUNDLE_SOURCE_READ_CACHE_MAX_BYTES` in the Profiling section's
   env list (default 64 MiB, `0` disables); also tighten the STDERR var
   description to match the now-construction-time announce semantics.

6. packages/bundle-source/src/profile.js: append a 4-byte random hex
   suffix to the trace filename so concurrent bundle calls from sibling
   processes in the same millisecond on the same pid (or different pids
   landing on the same Date.now() tick) cannot collide in the shared
   traceDir.

7. packages/evasive-transform/test/evade-censor.test.js: three asserts
   pinning the cleaner's widened `importLikePattern` (`\bimport\s*(?:\(|\/[/*])`):
   `import (` (space-paren) in a string literal, `import //` (line
   comment), `import /*` (block comment). Each embeds the risky token
   inside a position SES rejects unless the censor has already escaped
   it; the assert checks the slow path ran by confirming the output
   differs from the input.

Plus the gate-driven `@import` lift of the inline
`import('./types.js').ParserImplementation` JSDoc in parse-archive-mjs.js
(the file touched by item 4 had a pre-existing inline import the
no-inline-import-jsdoc probe surfaced).

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
…ailed profiling

Squashed mirror of endojs/endo#3099 (10 commits by Turadg Aleahmad,
2026-02 to 2026-02-19) collapsing the profiling work into one commit
for mirror-side rebase tractability.

Speed up @endo/bundle-source for multi-entrypoint workloads (notably
agoric-sdk) and add richer profiling spans across compartment-mapper,
evasive-transform, module-source, and zip. Optimizes node-modules
graph finalization, adds cross-bundle parser reuse in archive parsing,
improves the archive/zip path, and adds zip microbenchmark tooling.

Measured on yarn workspace @endo/bundle-source profile:agoric-bundling:
13180ms baseline to 7538ms latest, a 42.8% reduction.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
Three logical items the panel surfaced on the cleaner head 2586a99, all
flowing from type-narrowness gaps the perf instrumentation introduced:

1. packages/bundle-source/src/profile.js: type the disabled-profiler
   noop's startSpan and flush to the same shape published by
   BundlingKitOptions.profiler in types.ts; the discriminated noop now
   accepts Record<string, unknown> args like the live profiler. Closes
   TS2322 at script.js:93,115 and zip-base64.js:188,204,227; closes
   TS2345 at script.js:171 and zip-base64.js:264.

2. packages/zip/src/writer.js: replace `Array<ZFile>` with
   `Array<ArchivedFile>` via a top-level `@import` from types.js, fix the
   orphaned `/** type {Map<string, ZFile>} */` JSDoc tag (missing leading
   @) on this.files, and propagate the type through the writeZip
   declarations. Closes TS2552. Drive-by: widen the write() options.date
   to `Date | null` and default to null so the assignment to
   ArchivedFile.date (which is Date?) typechecks; add the missing
   `type: 'file'` discriminant on the ArchivedFile record.

3. packages/compartment-mapper/src/import-hook.js,
   packages/compartment-mapper/src/map-parser.js,
   packages/bundle-source/src/zip-base64.js: seed `moduleBytes`,
   `language`, `endoZipBase64` with explicit `undefined` defaults at
   declaration (and widen the type to `T | undefined` where needed) so
   the `finally`-block reads pass TS flow analysis. Closes TS2454 at all
   three sites.

Gate-driven collateral (no behavior change):
- packages/compartment-mapper/src/import-hook.js: lift the inline
  `import('ses').Harden` JSDoc to a top-level `@import {Harden} from 'ses'`
  to satisfy no-inline-import-jsdoc.
- packages/evasive-transform/src/index.js: lift the inline
  `import('./parse-ast.js').SourceType` and
  `import('@babel/traverse').NodePath` JSDoc into the existing top-level
  `@import` block.
- packages/bundle-source/README.md: split the two-sentence physical line
  "Each bundle call writes one *.trace.json file. Open these in Chrome
  tracing tools..." per the sentence-per-line markdown style.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 22, 2026
Seven of the eight items the panel surfaced as `summary-fix` on the
cleaner head 2586a99. Item 8 (the orphaned `/** type {Map<string,
ZFile>} */` JSDoc tag at zip/src/writer.js:37) shipped in the must-fix
commit alongside the ZFile -> ArchivedFile rename it interacts with.

1. packages/bundle-source/src/profile.js: when ENDO_BUNDLE_SOURCE_PROFILE_STDERR
   is truthy, emit the resolved trace path at profiler construction (one
   line), not only at successful flush. Surfaces an auto-resolved
   `os.tmpdir()` fallback path early enough for the user to redirect or
   pre-create the directory when the default is non-writable.

2. packages/bundle-source/src/zip-base64.js: warn to stderr when
   `ENDO_BUNDLE_SOURCE_READ_CACHE_MAX_BYTES` has a non-numeric tail
   (e.g., "100mb") that `Number.parseInt` would silently truncate. The
   README documents the env as a raw byte count; surface the truncation
   rather than honoring a misleading value.

3. packages/bundle-source/src/zip-base64.js: document the
   insertion-order (FIFO) eviction discipline of `cachedReads` in a
   file-header comment. Cache hits do not promote; under a working set
   larger than `readCacheMaxBytes` the cache degrades gracefully but is
   not classic LRU. Documenting the choice rather than implementing LRU
   because the agoric-sdk workload the cache was sized for fits within
   the default cap.

4. packages/compartment-mapper/src/parse-archive-mjs.js: lift the
   hardcoded `MAX_PARSE_ARCHIVE_MJS_CACHE_ENTRIES = 20_000` to an env
   override (`ENDO_PARSE_ARCHIVE_MJS_CACHE_ENTRIES`) and emit a one-time
   stderr warning on cap-hit so a workload exceeding the default surface
   the situation rather than silently thrashing the cache to one entry.

5. packages/bundle-source/README.md: document
   `ENDO_BUNDLE_SOURCE_READ_CACHE_MAX_BYTES` in the Profiling section's
   env list (default 64 MiB, `0` disables); also tighten the STDERR var
   description to match the now-construction-time announce semantics.

6. packages/bundle-source/src/profile.js: append a 4-byte random hex
   suffix to the trace filename so concurrent bundle calls from sibling
   processes in the same millisecond on the same pid (or different pids
   landing on the same Date.now() tick) cannot collide in the shared
   traceDir.

7. packages/evasive-transform/test/evade-censor.test.js: three asserts
   pinning the cleaner's widened `importLikePattern` (`\bimport\s*(?:\(|\/[/*])`):
   `import (` (space-paren) in a string literal, `import //` (line
   comment), `import /*` (block comment). Each embeds the risky token
   inside a position SES rejects unless the censor has already escaped
   it; the assert checks the slow path ran by confirming the output
   differs from the input.

Plus the gate-driven `@import` lift of the inline
`import('./types.js').ParserImplementation` JSDoc in parse-archive-mjs.js
(the file touched by item 4 had a pre-existing inline import the
no-inline-import-jsdoc probe surfaced).

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 23, 2026
The barrister summary-fix bundle for #355 (commit c88cd69) refined the
`nominateCandidates` optimization to short-circuit suffix expansion when
`leaf.includes('.')` returned true. That condition matches *any* leaf
with a literal `.` in its name, which violates the contract that
`fixtures-resolve/node_modules/path-with-dot` was added to lock in via
master commit `3768a3eaa fix(compartment-mapper): allow specifier to
include period and omit extension`.

The fixture has:

    path-with-dot/
      module.with.dot.js       <- `./module.with.dot` resolves via `.js`
      dir.with.dot/index.js    <- `./dir.with.dot` resolves via `/index.js`

The summary-fix early-return blocked both because the leaf contains `.`,
and the four `test (22.x|24.x x ubuntu/macos)` jobs failed with eleven
`compartment-mapper` failures plus a `bundle-source` `./demo/fortune.js`
failure.

Narrow the heuristic: skip suffix expansion only when the leaf already
ends with one of the configured `searchSuffixes` (`.js`, `.json`,
`/index.js`, `/index.json`). Otherwise, expand all suffixes as before.
This preserves the performance intent (no redundant candidates when
`./foo.js` already names the file) while honoring the `path-with-dot`
contract.

Regression evidence: with this change reverted, `yarn test` in
`packages/compartment-mapper` fails eleven tests in
`test/fixtures-resolve.test.js` and the related makeArchive /
writeArchive / loadArchive variants; with the change applied, all 887
tests pass and the 6 known failures match the pre-fixer baseline.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 23, 2026
The barrister must-fix-loop cluster (commit cb5e2b7) lifted
`NodePath` from an inline `import('@babel/traverse').NodePath` JSDoc
form into a top-level `@import {NodePath} from '@babel/traverse'`, to
satisfy the `no-inline-import-jsdoc` pre-push probe.

The TypeScript .d.ts emitter, however, does not emit a top-level type
import for a JSDoc `@import` whose source is an external package; it
leaves the type name dangling in the generated declaration. The
`viable-release` job's `yarn pack` step then fails when it tries to
consume the package's `.d.ts`:

    ../evasive-transform/src/index.d.ts(85,29):
      error TS2304: Cannot find name 'NodePath'.

Define a local `@typedef BabelNodePath` aliased through an inline
`import('@babel/traverse').NodePath` (the `no-inline-import-jsdoc`
probe has an explicit `@typedef` carve-out, since `@typedef` is the
legitimate place to declare type aliases). Use `BabelNodePath` in the
`customVisitor` property type. The generated `.d.ts` now contains a
top-level `export type BabelNodePath = any;` plus
`customVisitor?: ((path: BabelNodePath) => void)`, which is
self-contained and matches the type-loss profile master ships for the
same Babel re-export pattern.

The remaining `@import` block (covering local-module `TransformedResult`,
`SourceMapOption`, `SourceType`) is unaffected; only the `@babel/traverse`
external is at issue.

Refs: endojs/endo#3099
kriscendobot pushed a commit to endojs/endo-but-for-bots that referenced this pull request May 23, 2026
The `lint` CI job runs `yarn docs` (typedoc) after `yarn lint`. typedoc
type-checks each package and surfaced 24 TS errors on the perf PR's
head, all in PR-added or PR-modified files. Three sites:

1. `bundle-source/tools/trace-merge.js` (new file): `parseArgs`'s
   return-type unions `string | string[] | undefined` for every value
   regardless of whether `multiple: true` is set. Narrow once at the
   site of the destructure to a single-value record so downstream uses
   of `outTrace`, `outSummary`, `outMarkdown`, `topRaw` typecheck. The
   per-event `copy.ts` / `copy.dur` reads needed an explicit
   `Record<string, unknown>` type on `copy` so the property lookups
   are not narrowed to the spread's `args`-only type.

2. `compartment-mapper/test/integrity.test.js`: three sites read
   `node.content` after `writer.files.get(...)` returns `T | undefined`.
   Guard with `if (!node) { t.fail(...); return; }`. The fixture always
   contains the file, so the guard never fires in practice; it is purely
   a type narrowing.

3. `compartment-mapper/test/node-powers.test.js`: `canonical`'s parameter
   type is `` `file://${string}` ``; `pathToFileURL(...).href` is typed
   as `string`. Cast the local with a JSDoc `@type` to the template-literal
   shape (a file:// URL by construction).

All three changes preserve runtime behavior. After this commit, `yarn
docs` reports 0 errors (down from 24).

Refs: endojs/endo#3099
@turadg turadg force-pushed the codex/bundle-source-profiling branch from b03648b to 3a448fc Compare June 9, 2026 21:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 34 out of 35 changed files in this pull request and generated 4 comments.

Comment thread packages/zip/src/writer.js Outdated
Comment thread packages/bundle-source/tools/trace-merge.js Outdated
Comment thread packages/bundle-source/tools/profile-agoric-bundling.mts Outdated
Comment thread packages/bundle-source/package.json Outdated
@turadg turadg force-pushed the codex/bundle-source-profiling branch 6 times, most recently from 286fcae to a5ef3f0 Compare June 12, 2026 18:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants