Skip to content

fix: map functions without closing brace mapping#120

Merged
AriPerkkio merged 2 commits into
AriPerkkio:mainfrom
sapphi-red:fix/map-functions-without-closing-brace-mapping
Dec 26, 2025
Merged

fix: map functions without closing brace mapping#120
AriPerkkio merged 2 commits into
AriPerkkio:mainfrom
sapphi-red:fix/map-functions-without-closing-brace-mapping

Conversation

@sapphi-red

@sapphi-red sapphi-red commented Dec 26, 2025

Copy link
Copy Markdown
Contributor

Same as istanbuljs/istanbuljs#837

Summary by CodeRabbit

  • Bug Fixes

    • Enhanced source mapping to search across multiple lines when an end mapping is missing, improving mapping reliability.
    • Applied a patch to an upstream source-map dependency via package configuration.
  • Tests

    • Added a test covering location mapping when end mapping is absent.
    • Updated snapshots to reflect adjusted coverage counts.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai

coderabbitai Bot commented Dec 26, 2025

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

Adds a pnpm patch for istanbul-lib-source-maps that implements a multi-line fallback for missing end-position mappings; mirrors that fallback in the repository's location mapping logic and adds tests plus updated coverage snapshots.

Changes

Cohort / File(s) Summary
Dependency patch config
package.json, patches/istanbul-lib-source-maps.patch
Added pnpm.patchedDependencies mapping istanbul-lib-source-mapspatches/istanbul-lib-source-maps.patch. Patch changes lib/get-mapping.js to iterate previous generated lines (using large column) when end-position mapping is missing.
Location mapping logic
src/location.ts
End-mapping fallback now scans from endNeedle.line down to startNeedle.line with Infinity/large column to find a mapping; returns null only if no mapping is found after the scan.
Unit tests
test/location.test.ts
Added test "getLoc returns mapped location for positions without end mapping" to validate mapping when end mapping is absent.
Snapshots / coverage tests
test/svelte.test.ts, test/vue.test.ts
Updated inline snapshots: svelte expected functions/statements updated (3→4, 5→6); vue counts increased (lines/statements/functions adjusted) to reflect mapping changes.

Sequence Diagram(s)

sequenceDiagram
  participant Test as Test
  participant Locator as Locator (src/location.ts)
  participant Lib as istanbul-lib-source-maps (patched)
  participant Map as SourceMap

  Note over Test,Locator: Request mapping for a start/end range
  Test->>Locator: getLoc(start, end)
  Locator->>Lib: originalPositionTryBoth(start)
  Lib-->>Locator: mappedStart
  Locator->>Lib: originalPositionTryBoth(end)
  alt end mapping found
    Lib-->>Locator: mappedEnd
  else end mapping missing
    Locator->>Lib: loop request for lines (line-1 ... startLine) with large column
    Lib-->>Locator: first non-null mappedEnd or null
  end
  Locator->>Map: convert original positions back to generated (bump end)
  Locator-->>Test: mapped location (or null)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 Hopping through maps with eager paws,

I hunt lost ends and fix their flaws.
From line to line I softly pry,
Now hidden ends no longer fly.
A patch, a test — hooray, we try! 🥕✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix: map functions without closing brace mapping' accurately summarizes the main change—a bug fix for mapping functions that lack end mappings, which is reflected in the code changes to handle missing end position mappings across multiple files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between cf8b614 and 90e8a29.

📒 Files selected for processing (1)
  • src/location.ts
🔇 Additional comments (1)
src/location.ts (1)

95-106: The backward line search with column: Infinity is correctly implemented.

The loop appropriately searches backward from endNeedle.line to startNeedle.line to find missing end mappings (e.g., when TypeScript omits closing braces from source maps). Version 0.3.31 of @jridgewell/trace-mapping treats column: Infinity as a very large number, allowing the segment-tracing algorithm to locate the last mapping on each line—exactly the behavior needed here. The early termination when a mapping is found and the null return when no mapping exists across the range are both correct.


Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/location.ts (1)

95-101: Fix typo in comment.

Line 96: "doesnt" should be "doesn't".

Otherwise, the multi-line fallback logic looks correct. It properly handles the case where TypeScript and other transpilers omit closing braces from source maps by searching previous lines for valid mappings.

🔎 Proposed fix
-      // e.g. tsc that doesnt include } in source maps
+      // e.g. tsc that doesn't include } in source maps
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3274879 and cf8b614.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (6)
  • package.json
  • patches/istanbul-lib-source-maps.patch
  • src/location.ts
  • test/location.test.ts
  • test/svelte.test.ts
  • test/vue.test.ts
🧰 Additional context used
🧬 Code graph analysis (1)
test/location.test.ts (1)
src/location.ts (1)
  • Locator (27-167)
🔇 Additional comments (5)
test/svelte.test.ts (1)

22-24: LGTM! Snapshot update reflects improved function mapping.

The increased function and statement counts (from 3 to 4 functions, 5 to 6 statements) align with the PR's objective to correctly map functions without closing brace mappings.

test/vue.test.ts (1)

22-24: LGTM! Snapshot correctly reflects the mapping improvements.

The metrics now detect 1 function (previously 0/0) and corresponding increases in lines and statements, consistent with the improved end-position mapping behavior.

package.json (1)

81-83: LGTM! Patch configuration is correct.

The patchedDependencies entry properly references the patch file for istanbul-lib-source-maps, enabling the multi-line fallback behavior in the external dependency.

test/location.test.ts (1)

106-140: LGTM! Test effectively validates the fallback behavior.

The test correctly verifies that getLoc can map positions when end mappings are absent, exercising the multi-line fallback logic introduced in this PR.

patches/istanbul-lib-source-maps.patch (1)

8-36: LGTM! Patch correctly implements the fallback logic.

The changes mirror the implementation in src/location.ts:

  • Variable changed to let to enable reassignment (line 13)
  • Multi-line backward search added (lines 20-30)
  • Proper null check after exhausting search (lines 31-33)

Note: Patches to dependencies may require updates when bumping the istanbul-lib-source-maps version. Consider monitoring the upstream PR (istanbuljs/istanbuljs#837) for merge status.

Comment thread package.json
Comment on lines +80 to +82
},
"patchedDependencies": {
"istanbul-lib-source-maps": "patches/istanbul-lib-source-maps.patch"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added this patch temporarily to make the test pass.

Comment thread test/vue.test.ts
"functions": "0/0 (100%)",
"lines": "0/2 (0%)",
"statements": "0/2 (0%)",
"functions": "0/1 (0%)",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

v-for is transformed to _renderList(..., () => { ... }) and this callback is now mapped correctly.

Comment thread test/svelte.test.ts
{
"branches": "0/0 (100%)",
"functions": "0/3 (0%)",
"functions": "0/4 (0%)",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Similar to vue, #each is transformed to $.each(..., ..., () => ..., () => ..., () => { ... }) and this last callback is now mapped correctly.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This and the Vue test are here mostly to verify this library and Istanbul packages remap the same code similarly. In Svelte and Vue, I wouldn't necessarily call any of this "correct", but it's what their compilers output:

@pkg-pr-new

pkg-pr-new Bot commented Dec 26, 2025

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/AriPerkkio/ast-v8-to-istanbul@120

commit: 90e8a29

Comment thread src/location.ts Outdated
if (end === null) {
// search the previous lines as the mapping was not found on the same line
// e.g. tsc that doesnt include } in source maps
for (let line = endNeedle.line; line > 0 && end === null; line--) {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Would replacing line > 0 with line >= startNeedle.line make more sense? I guess it should always match once line === startNeedle.line is reached though. We should not look for end mappings above start line.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

We can replace this with line >= startNeedle.line. I used line > 0 as startNeedle wasn't available in istanbul-lib-source-maps.

Comment thread src/location.ts Outdated
// search the previous lines as the mapping was not found on the same line
// e.g. tsc that doesnt include } in source maps
for (let line = endNeedle.line; line > 0 && end === null; line--) {
end = getPosition({ line, column: Number.MAX_SAFE_INTEGER }, this.#map);

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Does Number.MAX_SAFE_INTEGER have some special meaning here or could this be Infinity too? It's just to search the end of the line?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Number.MAX_SAFE_INTEGER was the one that came up in my head first. I'll replace it with Infinity. It would have a small overhead because of float & integer mix, but I guess it would be negligible.

@AriPerkkio AriPerkkio left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Looks good, thanks!

I have a feeling this might cause issues in some cases where nodes are nested, and we are looking for the outer one only. It might not come up with functions, but this remapping logic is used for all cases. But I can't really point out any examples to demonstrate this. Let's merge this as-is and see if it breaks anything.

Comment thread test/svelte.test.ts
{
"branches": "0/0 (100%)",
"functions": "0/3 (0%)",
"functions": "0/4 (0%)",

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This and the Vue test are here mostly to verify this library and Istanbul packages remap the same code similarly. In Svelte and Vue, I wouldn't necessarily call any of this "correct", but it's what their compilers output:

@AriPerkkio AriPerkkio merged commit 4cbe2ec into AriPerkkio:main Dec 26, 2025
9 checks passed
@sapphi-red sapphi-red deleted the fix/map-functions-without-closing-brace-mapping branch January 7, 2026 04:57
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.

2 participants