Skip to content

fix(code-frame): use 0-based columns to match Babel AST locations (#1…#17849

Open
nehemiyawicks wants to merge 1 commit intobabel:mainfrom
nehemiyawicks:fix/code-frame-zero-based-columns
Open

fix(code-frame): use 0-based columns to match Babel AST locations (#1…#17849
nehemiyawicks wants to merge 1 commit intobabel:mainfrom
nehemiyawicks:fix/code-frame-zero-based-columns

Conversation

@nehemiyawicks
Copy link
Copy Markdown

Q A
Fixed Issues? Fixes #17316
Patch: Bug Fix? 👍
Major: Breaking Change? Potentially
Minor: New Feature?
Tests Added + Pass? Yes
Documentation PR Link N/A
Any Dependency Changes? No
License MIT

Summary

Fixes #17316

codeFrameColumns currently treats columns as 1-based, while Babel AST locations are 0-based. This mismatch causes caret/underline markers to be off by one character when codeFrameColumns is called with AST locations directly.

This PR updates @babel/code-frame to treat columns as 0-based, and removes the corresponding + 1 compensations in internal callers (@babel/core, @babel/traverse) that were working around the previous behavior.

Changes

@babel/code-frame (common.ts)

  • Changed default column sentinel from 0 to null so that column 0 is a valid position
  • Replaced falsy checks (!startColumn, if (startColumn)) with explicit null checks (startColumn == null, startColumn != null)
  • Removed + 1 compensation in marker length calculation
  • Removed - 1 offset in marker spacing calculation

@babel/core and @babel/traverse

  • Removed column: loc.column + 1 in 3 call sites that were converting 0-based AST columns to 1-based before passing them to codeFrameColumns

Tests

  • Updated existing test inputs from 1-based to 0-based columns
  • Added 2 new tests verifying correct behavior with 0-based columns (including column 0)

Breaking change note

This may be a breaking change for external consumers who manually pass 1-based column values to codeFrameColumns.

Consumers passing Babel AST .loc objects (the primary use case) will now receive correct results without manual adjustment.

If preferred, this change can be targeted for Babel 8.

Test plan

  • All @babel/code-frame tests pass (31 tests)
  • All @babel/core tests pass (483 tests)
  • All @babel/parser tests pass (16,083 tests)
  • All @babel/traverse tests pass (650 tests)
  • Verified manually with @babel/parser output for both valid code (AST loc) and syntax errors (error loc)

@babel-bot
Copy link
Copy Markdown
Collaborator

babel-bot commented Mar 3, 2026

Build successful! You can test your changes in the REPL here: https://babeljs.io/repl/build/61092

…bel#17316)

`codeFrameColumns` treated the `column` property as 1-based, but Babel
AST locations use 0-based columns. This caused the caret/underline to
be off by one character when passing AST `.loc` objects directly.

- Removed the `- 1` offset in marker spacing calculation
- Removed the `+ 1` in multiline start marker count
- Changed default column sentinel from `0` to `null` so that
  `column: 0` is treated as a valid position
- Updated falsiness checks (`!startColumn`) to null checks
- Removed `+ 1` workarounds in babel-core and babel-traverse callers

This is a breaking change for external consumers of `@babel/code-frame`
who passed 1-based columns manually.
@nehemiyawicks nehemiyawicks force-pushed the fix/code-frame-zero-based-columns branch from 0a17403 to 4b94a8d Compare March 3, 2026 08:29
@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new bot commented Mar 3, 2026

Open in StackBlitz

commit: 4b94a8d

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.

Off-by-one columns in babel/code-frame

2 participants