Skip to content

[rust-compiler] Fix off-by-one in SWC source-location conversion#36502

Merged
poteto merged 1 commit into
pr-36173from
lauren/swc-01-loc-off-by-one
May 21, 2026
Merged

[rust-compiler] Fix off-by-one in SWC source-location conversion#36502
poteto merged 1 commit into
pr-36173from
lauren/swc-01-loc-off-by-one

Conversation

@poteto
Copy link
Copy Markdown
Collaborator

@poteto poteto commented May 21, 2026

SWC's BytePos is 1-based (BytePos(0) is the DUMMY/synthetic sentinel)
while the Babel AST that the rest of the compiler consumes uses
0-based offsets in loc.{start,end}.{line,column,index}. position()
in the SWC convert_ast was binary-searching the 1-based offset
against the 0-based line_offsets table, producing line/column/index
values that were off by 1, and that flipped to "next line, column 0"
when the referenced byte happened to be the byte right before a \n.

Shift the offset down by 1 before the line lookup. BaseNode.start/end
keeps the SWC-native 1-based value because the SWC scope collector
keys its node_to_scope map on span.lo.0 and the HIR builder looks it
up via base.start.

Also drop the e2e harness's oneBasedColumns = variant === 'swc'
workaround that was masking part of this divergence.

Test plan:

  • bash compiler/scripts/test-e2e.sh --variant swc:
    Before: Total 1682/1795 (113 failures)
    After: Total 1742/1795 (53 failures, 60 fixed)
  • bash compiler/scripts/test-e2e.sh --variant babel: 1788/1795 (unchanged)
  • bash compiler/scripts/test-e2e.sh --variant oxc: 1702/1795 (unchanged)
  • cargo test --workspace: 56 passed, 0 failed (unchanged)

SWC's BytePos is 1-based (BytePos(0) is the DUMMY/synthetic sentinel)
while the Babel AST that the rest of the compiler consumes uses
0-based offsets in loc.{start,end}.{line,column,index}. `position()`
in the SWC convert_ast was binary-searching the 1-based offset
against the 0-based line_offsets table, producing line/column/index
values that were off by 1, and that flipped to "next line, column 0"
when the referenced byte happened to be the byte right before a `\n`.

Shift the offset down by 1 before the line lookup. BaseNode.start/end
keeps the SWC-native 1-based value because the SWC scope collector
keys its node_to_scope map on span.lo.0 and the HIR builder looks it
up via base.start.

Also drop the e2e harness's `oneBasedColumns = variant === 'swc'`
workaround that was masking part of this divergence.

Test plan:
- bash compiler/scripts/test-e2e.sh --variant swc:
    Before: Total 1682/1795 (113 failures)
    After:  Total 1742/1795 (53 failures, 60 fixed)
- bash compiler/scripts/test-e2e.sh --variant babel: 1788/1795 (unchanged)
- bash compiler/scripts/test-e2e.sh --variant oxc:   1702/1795 (unchanged)
- cargo test --workspace: 56 passed, 0 failed (unchanged)
@meta-cla meta-cla Bot added the CLA Signed label May 21, 2026
@github-actions github-actions Bot added the React Core Team Opened by a member of the React Core Team label May 21, 2026
@poteto poteto merged commit 85066da into pr-36173 May 21, 2026
21 of 26 checks passed
@poteto poteto deleted the lauren/swc-01-loc-off-by-one branch May 21, 2026 07:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant