mirror of
https://github.com/oxc-project/oxc.git
synced 2026-09-14 19:36:11 +08:00
300763f328
## Summary
Align `oxc-codegen` source maps with Rust `oxc_codegen`, using the Rust implementation as the conformance oracle.
This PR:
- changes `printSync` to return `{ code, map? }`;
- returns a standard Source Map v3 object;
- exposes Rust’s generated source map through `codegen_conformance`;
- compares the complete JS and Rust source maps;
- supports Oxc `start`/`end` offsets and TS-ESTree `range` offsets;
- uses `sourceText` to convert UTF-16 offsets and recover original identifier spellings;
- validates both maps and no-maps builds in both `preserveParens` modes;
- aligns mapping placement across JavaScript, TypeScript, JSX, templates, imports, destructuring, delimiters, and postfix chains;
- handles astral characters and all ECMAScript line terminators.
`loc`-only ASTs are not supported for source maps.
## API change
```ts
const { code, map } = printSync(program, {
sourcemap: true,
sourceFileName: "input.js",
sourceText,
});
```
`map` is a Source Map v3 object:
```ts
interface SourceMap {
version: 3;
mappings: string;
names: string[];
sources: string[];
sourcesContent?: string[];
}
```
## Implementation
Mapped writes collect only:
- the generated UTF-16 offset;
- the original source offset;
- the optional original identifier name.
After printing, the generator builds line tables for the generated output and `sourceText`, converts the offsets to line/column positions, suppresses duplicate source positions, and encodes the result as base64 VLQ.
The no-maps builds continue to remove mapping-specific writes at build time.
## Validation flow
```mermaid
flowchart TB
fixture["Fixture<br/>filename + sourceText + parse options"]
fixture --> rustParse
fixture --> jsParse
subgraph rust["Rust oracle"]
direction TB
rustParse["Parse with oxc_parser"]
normalize["Normalize Rust-only AST information"]
rustPrint["Print with oxc_codegen<br/>source maps enabled"]
rustResult["Expected result<br/>{ code, map }"]
rustParse --> normalize
normalize --> rustPrint
rustPrint --> rustResult
end
subgraph js["JavaScript candidate"]
direction TB
jsParse["Parse ESTree with oxc-parser<br/>start/end or range offsets"]
plainPrint["Print with no-maps build"]
plainResult["Actual code"]
mappedPrint["Print with maps-enabled build"]
deferred["Record generated offsets,<br/>source offsets, and names"]
encode["Convert UTF-16 offsets to positions<br/>deduplicate and encode VLQ"]
mappedResult["Actual result<br/>{ code, map }"]
jsParse --> plainPrint
plainPrint --> plainResult
jsParse --> mappedPrint
mappedPrint --> deferred
deferred --> encode
encode --> mappedResult
end
rustParse --> parseGate
jsParse --> parseGate
rustResult --> codeGate
plainResult --> codeGate
mappedResult --> codeGate
rustResult --> mapGate
mappedResult --> mapGate
parseGate["Parse agreement<br/>Rust success requires no JS errors"]
codeGate["Code equality<br/>both JS builds equal Rust"]
mapGate["Source Map v3 equality<br/>mappings + names + sources + content"]
parseGate --> pass["Fixture passes"]
codeGate --> pass
mapGate --> pass
```
Each fixture runs with both `preserveParens: false` and `preserveParens: true`.
## AST normalization
Rust’s AST contains information that ESTree cannot represent. The Rust AST is normalized before printing so the comparison measures code generation rather than representation differences.
This includes:
- parenthesized function and arrow-expression flags;
- `import "m"` versus `import {} from "m"`;
- absent versus empty import-attribute clauses;
- `assert` versus `with` attribute keywords;
- the unavailable ESTree span for a complete `with` clause.
37 lines
965 B
TOML
37 lines
965 B
TOML
[package]
|
|
name = "oxc_codegen_conformance"
|
|
version = "0.0.0"
|
|
authors.workspace = true
|
|
edition.workspace = true
|
|
homepage.workspace = true
|
|
keywords.workspace = true
|
|
license.workspace = true
|
|
publish = false
|
|
repository.workspace = true
|
|
rust-version.workspace = true
|
|
description = "Node API binding around `oxc_parser` + `oxc_codegen`, used as the reference output for the `oxc-codegen` package's conformance tests."
|
|
|
|
[lints]
|
|
workspace = true
|
|
|
|
[lib]
|
|
crate-type = ["cdylib", "lib"]
|
|
test = false
|
|
doctest = false
|
|
|
|
[dependencies]
|
|
oxc_allocator = { workspace = true }
|
|
oxc_ast = { workspace = true }
|
|
oxc_ast_visit = { workspace = true }
|
|
oxc_codegen = { workspace = true, features = ["sourcemap"] }
|
|
oxc_napi = { workspace = true }
|
|
oxc_parser = { workspace = true }
|
|
oxc_sourcemap = { workspace = true, features = ["napi"] }
|
|
oxc_syntax = { workspace = true }
|
|
|
|
napi = { workspace = true }
|
|
napi-derive = { workspace = true }
|
|
|
|
[build-dependencies]
|
|
napi-build = { workspace = true }
|