mirror of
https://github.com/aphrody-labs/oxc.git
synced 2026-10-15 22:59:17 +00:00
docs(packages/codegen): reformat docs and comments (#25848)
Follow-on after #25585. Pure style change. I hate the way LLMs put line breaks in weird places like after "the" - it makes comments hard to read. And what's with all the colons and semicolons? No substantive changes, just reformatting comments and docs to avoid this unreadable formatting.
This commit is contained in:
1 parent
300763f328
commit
58f7ab9c1d
13 files changed
+129
-86
No files matched your search
@@ -509,9 +509,9 @@ from `start` / `end`. Nodes without offsets are not mapped, and `sourceText` is
|
||||
source offsets to line/column positions.
|
||||
|
||||
`generateSourceMap` then walks the output once at the end, counting ECMAScript line terminators,
|
||||
builds the equivalent line table for `sourceText`, turns both sets of offsets into line/column, and
|
||||
encodes the mappings as base64 VLQ. Tracking lines and columns throughout would cost every write in
|
||||
every build.
|
||||
builds the equivalent line table for `sourceText`, turns both sets of offsets into line/column,
|
||||
and encodes the mappings as base64 VLQ. Tracking lines and columns throughout would cost every write
|
||||
in every build.
|
||||
|
||||
#### Potential future improvement
|
||||
|
||||
|
||||
@@ -82,8 +82,8 @@ const { code } = printSync(program, {
|
||||
function printSync(node: Node, options?: Options): { code: string; map?: SourceMap };
|
||||
```
|
||||
|
||||
Prints a complete `Program` or a single statement and returns the generated source code and,
|
||||
when requested, a standard Source Map v3 object.
|
||||
Prints a complete `Program` or a single statement and returns the generated source code,
|
||||
and (when requested) a standard Source Map v3 object.
|
||||
|
||||
```js
|
||||
import { printSync } from "oxc-codegen";
|
||||
@@ -98,9 +98,9 @@ const { code, map } = printSync(program, {
|
||||
});
|
||||
```
|
||||
|
||||
Source-map mappings require `sourceText` and nodes with valid Oxc `start` / `end` offsets. A
|
||||
manually constructed AST without offsets can still be printed, but its source map has an empty
|
||||
`mappings` string.
|
||||
Source-map mappings require `sourceText` and nodes with valid Oxc `start` / `end` offsets.
|
||||
A manually constructed AST without offsets can still be printed, but its source map has
|
||||
an empty `mappings` string.
|
||||
|
||||
### Options
|
||||
|
||||
|
||||
@@ -859,8 +859,8 @@ function printTemplateLiteral(node: ESTree.TemplateLiteral, state: State): void
|
||||
|
||||
const quasi = quasis[i + 1];
|
||||
const raw = templateQuasiRaw(quasi);
|
||||
// A TS-shaped Oxc ESTree quasi includes the substitution's closing `}` in its span; the
|
||||
// JS-shaped ESTree quasi and Oxc's Rust AST both start at the raw template text.
|
||||
// A TS-shaped Oxc ESTree quasi includes the substitution's closing `}` in its span.
|
||||
// The JS-shaped ESTree quasi and Oxc's Rust AST both start at the raw template text.
|
||||
if (raw.length > 0) markWithMapAtStartOffset(state, quasi, TS ? 1 : 0);
|
||||
writeNoLast(state, raw);
|
||||
}
|
||||
|
||||
@@ -101,8 +101,8 @@ function printParams(params: ESTree.ParamPattern[], state: State): void {
|
||||
|
||||
const param = params[i];
|
||||
|
||||
// Oxc stores TypeScript's special `this` parameter separately from formal parameters and
|
||||
// prints it without a source mapping.
|
||||
// Oxc stores TypeScript's special `this` parameter separately from formal parameters
|
||||
// and prints it without a source mapping.
|
||||
if (TS && param.type === "Identifier" && param.name === "this") {
|
||||
write(state, "this", CAT_IDENT);
|
||||
if (param.typeAnnotation != null) printTypeAnnotation(param.typeAnnotation, state);
|
||||
|
||||
@@ -140,8 +140,8 @@ function printImportAttributes(
|
||||
const { length } = attributes;
|
||||
if (length === 0) return;
|
||||
|
||||
// ESTree omits the `WithClause` wrapper. The Rust reference normalizes its mapping anchor to the
|
||||
// first attribute, which is the first location both representations carry.
|
||||
// ESTree omits the `WithClause` wrapper. The Rust reference normalizes its mapping anchor
|
||||
// to the first attribute, which is the first location both representations carry.
|
||||
write(state, " ", CAT_OTHER);
|
||||
markWithMapAtStartOffset(state, attributes[0], 0);
|
||||
write(state, "with { ", CAT_OTHER);
|
||||
|
||||
@@ -43,7 +43,9 @@ export interface Options {
|
||||
*/
|
||||
ts?: boolean;
|
||||
|
||||
/** Original source text. Required for source-map mappings. */
|
||||
/**
|
||||
* Original source text. Required for source-map mappings.
|
||||
*/
|
||||
sourceText?: string;
|
||||
|
||||
/**
|
||||
@@ -51,6 +53,8 @@ export interface Options {
|
||||
*/
|
||||
sourcemap?: boolean;
|
||||
|
||||
/** Original source filename recorded in the returned source map. */
|
||||
/**
|
||||
* Original source filename recorded in the returned source map.
|
||||
*/
|
||||
sourceFileName?: string;
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
// Source map generation.
|
||||
//
|
||||
// Mapped writes record output offsets and original positions while printing. This module converts
|
||||
// them to generated positions and encodes a standard Source Map v3 in one pass at the end.
|
||||
// Mapped writes record output offsets and original positions while printing.
|
||||
// `generateSourceMap` defined here converts them to generated positions
|
||||
// and encodes a standard Source Map v3 in one pass at the end.
|
||||
|
||||
import { Buffer } from "node:buffer";
|
||||
|
||||
@@ -10,7 +11,9 @@ import { debugAssert } from "../asserts.ts";
|
||||
import type { Options, SourceMap } from "./options.ts";
|
||||
import type { State } from "../state.ts";
|
||||
|
||||
/** Convert deferred mapping data into a standard Source Map v3 object. */
|
||||
/**
|
||||
* Convert deferred mapping data into a standard Source Map v3 object.
|
||||
*/
|
||||
export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
debugAssert(
|
||||
state.mapPositions !== null,
|
||||
@@ -50,14 +53,14 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
let sourceLineStart = 0;
|
||||
let replayedSourceScanTotal = 0;
|
||||
let lineStart = 0;
|
||||
// Proving an output contains only `\n` takes a full scan. Amortize it only when enough mappings
|
||||
// will benefit; sparse maps and huge one-line literals stay on the single-pass regexp path.
|
||||
// Proving an output contains only `\n` takes a full scan. Amortize it only when enough mappings will benefit.
|
||||
// Sparse maps and huge one-line literals stay on the single-pass regexp path.
|
||||
const useOutputLineFeedFastPath =
|
||||
mappingCount >= MIN_LF_FAST_PATH_MAPPINGS &&
|
||||
output.length <= mappingCount * MAX_LF_FAST_PATH_CHARS_PER_MAPPING &&
|
||||
!hasUncommonLineTerminator(output);
|
||||
// Require mappings to cover a substantial part of the source, so looking for the first line
|
||||
// break cannot scan a huge unmapped suffix. Reordered inputs conservatively take the slow path.
|
||||
// Require mappings to cover a substantial part of the source, so looking for the first line break
|
||||
// cannot scan a huge unmapped suffix. Reordered inputs conservatively take the slow path.
|
||||
const useSourceLineBoundaryCache =
|
||||
mappingCount >= MIN_LF_FAST_PATH_MAPPINGS &&
|
||||
sourceText.length <= mappingCount * MAX_LF_FAST_PATH_CHARS_PER_MAPPING &&
|
||||
@@ -89,8 +92,8 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
|
||||
const generatedColumn = offset - lineStart;
|
||||
let sourceOffset = mapPositions[positionIndex + 1];
|
||||
// Rust end mappings use `span.end - 1`, which may land inside a multi-byte code point. The JS
|
||||
// equivalent can land on a low surrogate; normalize it back to the code point's start.
|
||||
// Rust end mappings use `span.end - 1`, which may land inside a multi-byte code point.
|
||||
// The JS equivalent can land on a low surrogate - normalize it back to the code point's start.
|
||||
if (sourceOffset > 0) {
|
||||
const char = sourceText.charCodeAt(sourceOffset);
|
||||
if (
|
||||
@@ -106,8 +109,8 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
let originalColumn: number;
|
||||
if (sourceLineStarts === undefined) {
|
||||
if (sourceOffset >= sourceScanOffset) {
|
||||
// Mappings almost always advance through the source. Scan only the text between this
|
||||
// mapping and the last one instead of building a line table for the whole source.
|
||||
// Mappings almost always advance through the source. Scan only the text between this mapping
|
||||
// and the last one, instead of building a line table for the whole source.
|
||||
if (useSourceLineBoundaryCache) {
|
||||
while (sourceOffset >= nextSourceLineStart) {
|
||||
sourceLineStart = nextSourceLineStart;
|
||||
@@ -143,12 +146,13 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
replayedSourceScanTotal + sourceScanOffset - sourceOffset <=
|
||||
Math.max(MAX_REPLAYED_SOURCE_SCAN, sourceText.length))
|
||||
) {
|
||||
// Parent/end mappings and locally reordered nodes can step backwards. These moves are
|
||||
// normally within the current line or a nearby one, so a short reverse scan is cheaper
|
||||
// than allocating a complete line table.
|
||||
// A same-line backtrack needs no scan and leaves the forward cursor where it is. When the
|
||||
// mapping crosses a line, count the text a later forward step must replay; once replaying
|
||||
// costs as much as building a line table, the fallback below becomes cheaper.
|
||||
// Parent/end mappings and locally reordered nodes can step backwards.
|
||||
// These moves are normally within the current line or a nearby one, so a short reverse scan
|
||||
// is cheaper than allocating a complete line table.
|
||||
//
|
||||
// A same-line backtrack needs no scan and leaves the forward cursor where it is.
|
||||
// When the mapping crosses a line, count the text a later forward step must replay.
|
||||
// Once replaying costs as much as building a line table, the fallback below becomes cheaper.
|
||||
if (sourceOffset < sourceLineStart) {
|
||||
replayedSourceScanTotal += sourceScanOffset - sourceOffset;
|
||||
while (sourceOffset < sourceLineStart) {
|
||||
@@ -204,7 +208,7 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
mappingLength,
|
||||
generatedColumn - previousGeneratedColumn,
|
||||
);
|
||||
// All mappings point into the one source file, so the source-index delta is always zero (`A`).
|
||||
// All mappings point into the one source file, so the source-index delta is always zero (`A`)
|
||||
mappingBuffer[mappingLength++] = 65;
|
||||
mappingLength = writeVlq(mappingBuffer, mappingLength, originalLine - previousOriginalLine);
|
||||
mappingLength = writeVlq(mappingBuffer, mappingLength, originalColumn - previousOriginalColumn);
|
||||
@@ -240,7 +244,9 @@ export function generateSourceMap(state: State, options: Options): SourceMap {
|
||||
return map;
|
||||
}
|
||||
|
||||
/** Build UTF-16 offsets to the start of every ECMAScript source line. */
|
||||
/**
|
||||
* Build UTF-16 offsets to the start of every ECMAScript source line.
|
||||
*/
|
||||
function getLineStarts(sourceText: string): number[] {
|
||||
const lineStarts = [0];
|
||||
for (let index = 0; index < sourceText.length; index++) {
|
||||
@@ -252,11 +258,13 @@ function getLineStarts(sourceText: string): number[] {
|
||||
return lineStarts;
|
||||
}
|
||||
|
||||
/** Find the source line containing `sourceOffset`, starting close to the previous result. */
|
||||
/**
|
||||
* Find the source line containing `sourceOffset`, starting close to the previous result.
|
||||
*/
|
||||
function findSourceLine(lineStarts: number[], sourceOffset: number, previousLine: number): number {
|
||||
// Source mappings normally advance through the original file. Search the next few lines
|
||||
// linearly, as V8 optimizes this small predictable loop well, then fall back for large jumps or
|
||||
// transformed ASTs whose source locations move backwards.
|
||||
// Source mappings normally advance through the original file. Search the next few lines linearly,
|
||||
// as V8 optimizes this small predictable loop well, then fall back for large jumps or transformed ASTs
|
||||
// whose source locations move backwards.
|
||||
if (sourceOffset >= lineStarts[previousLine]) {
|
||||
const end = Math.min(previousLine + LINE_SEARCH_ITERATIONS + 1, lineStarts.length);
|
||||
for (let line = previousLine + 1; line < end; line++) {
|
||||
@@ -280,7 +288,9 @@ function findSourceLine(lineStarts: number[], sourceOffset: number, previousLine
|
||||
return low - 1;
|
||||
}
|
||||
|
||||
/** Write one signed source-map delta as base64 VLQ, returning the next buffer position. */
|
||||
/**
|
||||
* Write one signed source-map delta as base64 VLQ, returning the next buffer position.
|
||||
*/
|
||||
function writeVlq(buffer: Buffer, index: number, value: number): number {
|
||||
let vlq = value < 0 ? -value * 2 + 1 : value * 2;
|
||||
if (vlq <= MAX_BITWISE_VLQ) {
|
||||
@@ -302,7 +312,9 @@ function writeVlq(buffer: Buffer, index: number, value: number): number {
|
||||
return index;
|
||||
}
|
||||
|
||||
/** Grow the mappings buffer to contain `requiredLength`, preserving its written prefix. */
|
||||
/**
|
||||
* Grow the mappings buffer to contain `requiredLength`, preserving its written prefix.
|
||||
*/
|
||||
function growMappingBuffer(buffer: Buffer, writtenLength: number, requiredLength: number): Buffer {
|
||||
let capacity = buffer.length * 2;
|
||||
while (capacity < requiredLength) capacity *= 2;
|
||||
@@ -311,22 +323,25 @@ function growMappingBuffer(buffer: Buffer, writtenLength: number, requiredLength
|
||||
return next;
|
||||
}
|
||||
|
||||
/** Find the UTF-16 offset after the next ECMAScript line terminator. */
|
||||
/**
|
||||
* Find the UTF-16 offset after the next ECMAScript line terminator.
|
||||
*/
|
||||
function findNextLineStart(output: string, from: number, useLineFeedFastPath: boolean): number {
|
||||
if (useLineFeedFastPath) {
|
||||
const index = output.indexOf("\n", from);
|
||||
return index === -1 ? Infinity : index + 1;
|
||||
}
|
||||
|
||||
// Let the regexp engine scan long generated lines. A JS `charCodeAt` loop is much slower for
|
||||
// large literals, while `lastIndex` avoids allocating a substring just to start the search at
|
||||
// `from`.
|
||||
// Let the regexp engine scan long generated lines. A JS `charCodeAt` loop is much slower for large literals,
|
||||
// while `lastIndex` avoids allocating a substring just to start the search at `from`.
|
||||
NEXT_LINE_TERMINATOR_REGEX.lastIndex = from;
|
||||
const match = NEXT_LINE_TERMINATOR_REGEX.exec(output);
|
||||
return match === null ? Infinity : match.index + match[0].length;
|
||||
}
|
||||
|
||||
/** Whether output contains a line terminator other than `\n`. */
|
||||
/**
|
||||
* Whether output contains a line terminator other than `\n`.
|
||||
*/
|
||||
function hasUncommonLineTerminator(output: string): boolean {
|
||||
// V8's specialized substring search is substantially faster than a regexp scan here, even when
|
||||
// all three searches miss. This also avoids allocating regexp match state for the common path.
|
||||
@@ -337,7 +352,9 @@ function hasUncommonLineTerminator(output: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/** Whether every source line terminator can be found by searching for `\n`. */
|
||||
/**
|
||||
* Whether every source line terminator can be found by searching for `\n`.
|
||||
*/
|
||||
function hasOnlyLineFeedsAndCrLf(sourceText: string): boolean {
|
||||
if (sourceText.indexOf("\u2028") !== -1 || sourceText.indexOf("\u2029") !== -1) return false;
|
||||
|
||||
|
||||
@@ -330,22 +330,30 @@ export function writeWithMapEnd(
|
||||
}
|
||||
}
|
||||
|
||||
/** Record a start mapping at the current output position without writing anything. */
|
||||
/**
|
||||
* Record a start mapping at the current output position without writing anything.
|
||||
*/
|
||||
export function markWithMap(state: State, node: MappableNode): void {
|
||||
recordSourceMapping(state, node, false);
|
||||
}
|
||||
|
||||
/** Record a start mapping without attaching an identifier name. */
|
||||
/**
|
||||
* Record a start mapping without attaching an identifier name.
|
||||
*/
|
||||
export function markWithMapNoName(state: State, node: MappableNode): void {
|
||||
recordSourceMapping(state, node, 3);
|
||||
}
|
||||
|
||||
/** Record a mapping for `node`'s end offset at the current output position. */
|
||||
/**
|
||||
* Record a mapping for `node`'s end offset at the current output position.
|
||||
*/
|
||||
export function markWithMapAfter(state: State, node: MappableNode): void {
|
||||
recordSourceMapping(state, node, 2);
|
||||
}
|
||||
|
||||
/** Record a mapping a fixed number of columns after `node`'s start offset. */
|
||||
/**
|
||||
* Record a mapping a fixed number of columns after `node`'s start offset.
|
||||
*/
|
||||
export function markWithMapAtStartOffset(
|
||||
state: State,
|
||||
node: MappableNode,
|
||||
@@ -379,7 +387,9 @@ export function markWithMapAtStartOffset(
|
||||
state.mapPositions.push(state.output.length, sourceOffset);
|
||||
}
|
||||
|
||||
/** Record one mapping, if source maps and a non-empty location are available. */
|
||||
/**
|
||||
* Record one mapping, if source maps and a non-empty location are available.
|
||||
*/
|
||||
function recordSourceMapping(state: State, node: MappableNode, location: false | 1 | 2 | 3): void {
|
||||
if (!SOURCEMAPS) return;
|
||||
const { sourceText } = state;
|
||||
@@ -432,8 +442,8 @@ function recordSourceMapping(state: State, node: MappableNode, location: false |
|
||||
(nameEnd === end || isDefinitelyIdentifierBoundary(sourceText.charCodeAt(nameEnd)))
|
||||
? printedName
|
||||
: originalNameFromSource(sourceText, node, start, end);
|
||||
// A transformed or hand-authored AST can carry ranges unrelated to `sourceText`. Preserve
|
||||
// the existing fallback in that case instead of recording an arbitrary source substring.
|
||||
// A transformed or hand-authored AST can carry ranges unrelated to `sourceText`.
|
||||
// Preserve the existing fallback in that case instead of recording an arbitrary source substring.
|
||||
name =
|
||||
originalName === undefined
|
||||
? printedName
|
||||
@@ -452,7 +462,9 @@ function recordSourceMapping(state: State, node: MappableNode, location: false |
|
||||
}
|
||||
}
|
||||
|
||||
/** Recover the original identifier spelling from validated source offsets. */
|
||||
/**
|
||||
* Recover the original identifier spelling from validated source offsets.
|
||||
*/
|
||||
function originalNameFromSource(
|
||||
sourceText: string,
|
||||
node: MappableNode,
|
||||
@@ -492,7 +504,9 @@ function originalNameFromSource(
|
||||
return index === identifierStart ? undefined : sourceText.slice(start, index);
|
||||
}
|
||||
|
||||
/** Return the UTF-16 length of a `\\u` identifier escape within `end`, or `0` if invalid. */
|
||||
/**
|
||||
* Return the UTF-16 length of a `\\u` identifier escape within `end`, or `0` if invalid.
|
||||
*/
|
||||
function unicodeEscapeLength(sourceText: string, index: number, end: number): number {
|
||||
if (sourceText.charCodeAt(index + 1) !== 117) return 0; // `u`
|
||||
|
||||
@@ -512,7 +526,9 @@ function unicodeEscapeLength(sourceText: string, index: number, end: number): nu
|
||||
return escapeEnd - index;
|
||||
}
|
||||
|
||||
/** Decode the code point in a syntactically valid identifier escape. */
|
||||
/**
|
||||
* Decode the code point in a syntactically valid identifier escape.
|
||||
*/
|
||||
function unicodeEscapeCodePoint(sourceText: string, index: number, length: number): number {
|
||||
const braced = sourceText.charCodeAt(index + 2) === 123;
|
||||
const digitsStart = index + (braced ? 3 : 2);
|
||||
@@ -520,12 +536,16 @@ function unicodeEscapeCodePoint(sourceText: string, index: number, length: numbe
|
||||
return Number.parseInt(sourceText.slice(digitsStart, digitsEnd), 16);
|
||||
}
|
||||
|
||||
/** Whether `code` is an ASCII hexadecimal digit. */
|
||||
/**
|
||||
* Whether `code` is an ASCII hexadecimal digit.
|
||||
*/
|
||||
function isHexDigit(code: number): boolean {
|
||||
return (code >= 48 && code <= 57) || (code >= 65 && code <= 70) || (code >= 97 && code <= 102);
|
||||
}
|
||||
|
||||
/** Whether an ASCII character definitely cannot continue any supported identifier spelling. */
|
||||
/**
|
||||
* Whether an ASCII character definitely cannot continue any supported identifier spelling.
|
||||
*/
|
||||
function isDefinitelyIdentifierBoundary(code: number): boolean {
|
||||
return (
|
||||
code <= 0x7f &&
|
||||
@@ -537,7 +557,9 @@ function isDefinitelyIdentifierBoundary(code: number): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
/** Track the final byte category Rust's postfix source-map hook checks, without reading `output`. */
|
||||
/**
|
||||
* Track the final byte category Rust's postfix source-map hook checks, without reading `output`.
|
||||
*/
|
||||
function updatePostfixClose(state: State, code: string): void {
|
||||
if (SOURCEMAPS && code.length > 0) {
|
||||
const last = code.charCodeAt(code.length - 1);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Source map tests.
|
||||
//
|
||||
// The conformance checker compares the complete Source Map v3 object against Rust `oxc_codegen`.
|
||||
// The remaining tests here check invariants which give a more local failure than a full mapping
|
||||
// diff: positions stay in bounds and ordered, indentation is respected, identifier text agrees,
|
||||
// The remaining tests here check invariants which give a more local failure than a full mapping diff -
|
||||
// positions stay in bounds and ordered, indentation is respected, identifier text agrees,
|
||||
// and turning source maps on does not change the generated code.
|
||||
//
|
||||
// Mappings use Oxc `start` / `end` offsets.
|
||||
@@ -18,8 +18,8 @@ import { checkFixture, getEcmaScriptLineTable } from "./utils/common.ts";
|
||||
import type { Program } from "oxc-parser";
|
||||
import type { SourceMap } from "../dist/index.js";
|
||||
|
||||
// Same directory the benchmarks download their fixtures to. Whichever are already cached are used;
|
||||
// the inline fixtures below always run.
|
||||
// Same directory the benchmarks download their fixtures to. Whichever are already cached are used.
|
||||
// The inline fixtures below always run.
|
||||
const CACHE_DIR_PATH = pathJoin(import.meta.dirname, "../../../target");
|
||||
|
||||
// `preserveParens: false` because this printer deliberately does not support the redundant
|
||||
@@ -118,7 +118,7 @@ describe("Rust conformance", () => {
|
||||
const identifier = statement.declarations[0].id;
|
||||
if (identifier.type !== "Identifier") throw new Error("Expected identifier");
|
||||
|
||||
// Simulate a transformed AST whose old offsets are no longer valid for the source text.
|
||||
// Simulate a transformed AST whose old offsets are no longer valid for the source text
|
||||
identifier.end = code.length + 1;
|
||||
|
||||
const { map } = printSync(program, {
|
||||
@@ -137,7 +137,7 @@ describe("Rust conformance", () => {
|
||||
const identifier = statement.declarations[0].id;
|
||||
if (identifier.type !== "Identifier") throw new Error("Expected identifier");
|
||||
|
||||
// Simulate a transformed AST whose stale offsets are in bounds but start on whitespace.
|
||||
// Simulate a transformed AST whose stale offsets are in bounds but start on whitespace
|
||||
identifier.start = code.indexOf(" ");
|
||||
identifier.end = identifier.start + 1;
|
||||
|
||||
@@ -247,7 +247,9 @@ interface Recorded {
|
||||
source: string;
|
||||
}
|
||||
|
||||
/** Decode a Source Map v3 mapping string for the local invariant checks below. */
|
||||
/**
|
||||
* Decode a Source Map v3 mapping string for the local invariant checks below.
|
||||
*/
|
||||
function decodeSourceMap(map: SourceMap): Recorded[] {
|
||||
const mappings: Recorded[] = [];
|
||||
let sourceId = 0;
|
||||
@@ -284,7 +286,9 @@ function decodeSourceMap(map: SourceMap): Recorded[] {
|
||||
return mappings;
|
||||
}
|
||||
|
||||
/** Decode one comma-delimited source-map segment. */
|
||||
/**
|
||||
* Decode one comma-delimited source-map segment.
|
||||
*/
|
||||
function decodeVlqSegment(segment: string): number[] {
|
||||
const values: number[] = [];
|
||||
let value = 0;
|
||||
@@ -333,8 +337,8 @@ interface Printed {
|
||||
}
|
||||
|
||||
for (const fixture of FIXTURES) {
|
||||
// A cached fixture which has not been downloaded is reported as skipped rather than passing
|
||||
// quietly. `pnpm run bench` downloads them.
|
||||
// A cached fixture which has not been downloaded is reported as skipped rather than passing quietly.
|
||||
// `pnpm run bench` downloads them.
|
||||
const describeFixture = fixture.code === null ? describe.skip : describe;
|
||||
|
||||
describeFixture(fixture.name, () => {
|
||||
@@ -345,8 +349,8 @@ for (const fixture of FIXTURES) {
|
||||
const program = parseProgram(fixture.name, code);
|
||||
const { jsx, ts } = fixture;
|
||||
|
||||
// Both builds through the public API - `printSync` picks the maps build when `sourcemap`
|
||||
// is true, and the no-maps build when it is not.
|
||||
// Both builds through the public API.
|
||||
// `printSync` picks the maps build when `sourcemap` is true, and the no-maps build when it is not.
|
||||
const { code: withMaps, map } = printSync(program, {
|
||||
jsx,
|
||||
ts,
|
||||
@@ -444,8 +448,8 @@ for (const fixture of FIXTURES) {
|
||||
|
||||
// --- Indentation ----------------------------------------------------------------------------
|
||||
|
||||
// `printIndent` goes through the same write path as everything else, so the `indent` option and
|
||||
// the mappings have to agree: indentation is honoured, and no mapping ever points into the middle
|
||||
// `printIndent` goes through the same write path as everything else, so the `indent` option
|
||||
// and the mappings have to agree: indentation is honoured, and no mapping ever points into the middle
|
||||
// of an indent run.
|
||||
const INDENT_CASES = [undefined, "\t", " ", " ", "\t\t", " \t", "\t "];
|
||||
|
||||
|
||||
@@ -126,9 +126,8 @@ export function checkFixture(
|
||||
const { code: actual } = printSync(program, { ts, jsx });
|
||||
expect(actual, `preserveParens: ${preserveParens}`).toBe(expected.code);
|
||||
|
||||
// Source maps use the maps-enabled build, which is compiled separately from the normal
|
||||
// printer. Source offsets are converted at the end. Compare both its code and complete
|
||||
// Source Map v3 output against Rust.
|
||||
// Source maps use the maps-enabled build, which is compiled separately from the normal printer.
|
||||
// Source offsets are converted at the end. Compare both its code and complete Source Map v3 output against Rust.
|
||||
const { code: actualWithSourceMap, map } = printSync(program, {
|
||||
ts,
|
||||
jsx,
|
||||
|
||||
@@ -13,7 +13,7 @@ import type { Plugin } from "rolldown";
|
||||
* write(state, "declare ", CAT_OTHER);
|
||||
* ```
|
||||
*
|
||||
* The mapped writes and `markWithMap` exist to record a source mapping for the node they are given.
|
||||
* The mapped writes and `markWithMap*` exist to record a source mapping for the node they are given.
|
||||
* A build without source map support has nothing to record, so the call becomes the plain write
|
||||
* it would otherwise be, and the node argument goes with it - it would still be evaluated,
|
||||
* and held live across the call, for a function which ignores it.
|
||||
|
||||
Vendored
+1
-2
@@ -1,8 +1,7 @@
|
||||
/* auto-generated by NAPI-RS */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* Parse `source_text` with `oxc_parser` and print the AST with `oxc_codegen`, including a source
|
||||
* map.
|
||||
* Parse `source_text` with `oxc_parser` and print the AST with `oxc_codegen`, including a source map.
|
||||
*
|
||||
* Returns `null` if the source text could not be parsed without errors, which tells the caller
|
||||
* there is nothing to compare for this fixture.
|
||||
|
||||
@@ -2,8 +2,7 @@
|
||||
//!
|
||||
//! This is the reference the `oxc-codegen` package's conformance tests are checked against.
|
||||
//! For each fixture, the tests parse the source twice - once here in Rust, and once with `oxc-parser`
|
||||
//! on the JS side - and require both printers to produce the same output and decoded source map
|
||||
//! positions.
|
||||
//! on the JS side - and require both printers to produce the same output and decoded source map positions.
|
||||
//!
|
||||
//! Both sides are given the same source text and the same `SourceType`, via [`oxc_napi::get_source_type`],
|
||||
//! which is the same function `oxc-parser` itself uses to turn a filename and `lang` / `sourceType` options
|
||||
@@ -53,8 +52,7 @@ pub struct CodegenResult {
|
||||
pub map: SourceMap,
|
||||
}
|
||||
|
||||
/// Parse `source_text` with `oxc_parser` and print the AST with `oxc_codegen`, including a source
|
||||
/// map.
|
||||
/// Parse `source_text` with `oxc_parser` and print the AST with `oxc_codegen`, including a source map.
|
||||
///
|
||||
/// Returns `null` if the source text could not be parsed without errors, which tells the caller
|
||||
/// there is nothing to compare for this fixture.
|
||||
@@ -202,8 +200,8 @@ fn normalize_with_clause(
|
||||
inner.keyword = WithClauseKeyword::With;
|
||||
|
||||
if let Some(first) = inner.with_entries.first() {
|
||||
// ESTree exposes the entries but not the `WithClause` wrapper or its `{` span. Use the
|
||||
// first location both representations can carry as the clause's mapping anchor.
|
||||
// ESTree exposes the entries but not the `WithClause` wrapper or its `{` span.
|
||||
// Use the first location both representations can carry as the clause's mapping anchor.
|
||||
inner.span.start = first.span.start;
|
||||
} else {
|
||||
*with_clause = None;
|
||||
|
||||
Reference in new issue
Block a user