import assert from 'node:assert/strict';
import {it} from 'node:test';
import * as BabelParser from '@babel/parser';
import * as t from '@babel/types';
import {
assertSourceOffsetRanges,
collectSourceOffsetRanges,
} from '../source-locations';
it('checks expression offsets across the output tree', () => {
const ast = BabelParser.parse('function Component(x) { return x + 1; }');
const originalRanges = collectSourceOffsetRanges(ast);
t.traverseFast(ast, node => {
if (t.isBinaryExpression(node) && node.start != null) node.start++;
});
assert.throws(
() => assertSourceOffsetRanges(ast, originalRanges),
/Invalid source offsets for BinaryExpression/,
);
});
it('rejects reversed ranges even when indices match', () => {
const ast = BabelParser.parseExpression('x + 1');
t.traverseFast(ast, node => {
if (t.isBinaryExpression(node) && node.loc != null) {
node.start = node.loc.start.index = 10;
node.end = node.loc.end.index = 5;
}
});
assert.throws(
() => assertSourceOffsetRanges(ast, new Set()),
/Invalid source offsets for BinaryExpression/,
);
});
it('checks range order even without location indices', () => {
const ast = t.identifier('x');
ast.start = 10;
ast.end = 5;
assert.throws(
() => assertSourceOffsetRanges(ast, new Set()),
/Invalid source offsets for Identifier/,
);
});
it('accepts original shifted expression offsets and rejects subsequent changes', () => {
const ast = BabelParser.parseExpression('x + 1');
assert(ast.start != null && ast.end != null);
ast.start += 100;
ast.end += 100;
const originalRanges = collectSourceOffsetRanges(ast);
assertSourceOffsetRanges(ast, originalRanges);
ast.start++;
assert.throws(
() => assertSourceOffsetRanges(ast, originalRanges),
/Invalid source offsets for BinaryExpression/,
);
});
it('does not fill absent or partial raw offsets from location indices', () => {
const ast = BabelParser.parseExpression('x + 1');
delete ast.start;
const end = ast.end;
assertSourceOffsetRanges(ast, new Set());
assert.equal(ast.start, undefined);
assert.equal(ast.end, end);
delete ast.end;
assertSourceOffsetRanges(ast, new Set());
assert.equal(ast.start, undefined);
assert.equal(ast.end, undefined);
});