Skip to content

Commit

Permalink
Add ignoreList support
Browse files Browse the repository at this point in the history
  • Loading branch information
jridgewell committed Mar 1, 2024
1 parent 5e3059f commit 1027ce6
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 16 deletions.
38 changes: 31 additions & 7 deletions src/any-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,13 @@ import {
} from './sourcemap-segment';

import type {
Section,
SectionedSourceMap,
DecodedSourceMap,
SectionedSourceMapInput,
Ro,
DecodedSourceMapXInput,
EncodedSourceMapXInput,
SectionedSourceMapXInput,
SectionXInput,
} from './types';
import type { SourceMapSegment } from './sourcemap-segment';

Expand All @@ -25,14 +27,29 @@ export const AnyMap: AnyMap = function (map, mapUrl) {
const parsed =
typeof map === 'string' ? (JSON.parse(map) as Exclude<SectionedSourceMapInput, string>) : map;

if (!('sections' in parsed)) return new TraceMap(parsed, mapUrl);
if (!('sections' in parsed)) {
return new TraceMap(parsed as DecodedSourceMapXInput | EncodedSourceMapXInput, mapUrl);
}

const mappings: SourceMapSegment[][] = [];
const sources: string[] = [];
const sourcesContent: (string | null)[] = [];
const names: string[] = [];
const ignoreList: number[] = [];

recurse(parsed, mapUrl, mappings, sources, sourcesContent, names, 0, 0, Infinity, Infinity);
recurse(
parsed,
mapUrl,
mappings,
sources,
sourcesContent,
names,
ignoreList,
0,
0,
Infinity,
Infinity,
);

const joined: DecodedSourceMap = {
version: 3,
Expand All @@ -41,18 +58,20 @@ export const AnyMap: AnyMap = function (map, mapUrl) {
sources,
sourcesContent,
mappings,
ignoreList,
};

return presortedDecodedMap(joined);
} as AnyMap;

function recurse(
input: Ro<SectionedSourceMap>,
input: Ro<SectionedSourceMapXInput>,
mapUrl: string | null | undefined,
mappings: SourceMapSegment[][],
sources: string[],
sourcesContent: (string | null)[],
names: string[],
ignoreList: number[],
lineOffset: number,
columnOffset: number,
stopLine: number,
Expand Down Expand Up @@ -82,6 +101,7 @@ function recurse(
sources,
sourcesContent,
names,
ignoreList,
lineOffset + offset.line,
columnOffset + offset.column,
sl,
Expand All @@ -91,12 +111,13 @@ function recurse(
}

function addSection(
input: Ro<Section['map']>,
input: Ro<SectionXInput['map']>,
mapUrl: string | null | undefined,
mappings: SourceMapSegment[][],
sources: string[],
sourcesContent: (string | null)[],
names: string[],
ignoreList: number[],
lineOffset: number,
columnOffset: number,
stopLine: number,
Expand All @@ -108,13 +129,16 @@ function addSection(
const sourcesOffset = sources.length;
const namesOffset = names.length;
const decoded = decodedMappings(map);
const { resolvedSources, sourcesContent: contents } = map;
const { resolvedSources, sourcesContent: contents, ignoreList: ignores } = map;

append(sources, resolvedSources);
append(names, map.names);

if (contents) append(sourcesContent, contents);
else for (let i = 0; i < resolvedSources.length; i++) sourcesContent.push(null);

if (ignores) for (let i = 0; i < ignores.length; i++) ignoreList.push(ignores[i] + sourcesOffset);

for (let i = 0; i < decoded.length; i++) {
const lineI = lineOffset + i;

Expand Down
30 changes: 24 additions & 6 deletions src/trace-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type {
SourceMap,
EachMapping,
Bias,
XInput,
} from './types';
import type { Source } from './by-source';
import type { MemoState } from './binary-search';
Expand Down Expand Up @@ -84,6 +85,7 @@ export class TraceMap implements SourceMap {
declare sourceRoot: SourceMapV3['sourceRoot'];
declare sources: SourceMapV3['sources'];
declare sourcesContent: SourceMapV3['sourcesContent'];
declare ignoreList: SourceMapV3['ignoreList'];

declare resolvedSources: string[];
private declare _encoded: string | undefined;
Expand All @@ -108,6 +110,7 @@ export class TraceMap implements SourceMap {
this.sourceRoot = sourceRoot;
this.sources = sources;
this.sourcesContent = sourcesContent;
this.ignoreList = parsed.ignoreList || (parsed as XInput).x_google_ignoreList || undefined;

const from = resolve(sourceRoot || '', stripFilename(mapUrl));
this.resolvedSources = sources.map((s) => resolve(s || '', from));
Expand Down Expand Up @@ -276,19 +279,33 @@ export function eachMapping(map: TraceMap, cb: (mapping: EachMapping) => void):
}
}

function sourceIndex(map: TraceMap, source: string): number {
const { sources, resolvedSources } = map;
let index = sources.indexOf(source);
if (index === -1) index = resolvedSources.indexOf(source);
return index;
}

/**
* Retrieves the source content for a particular source, if its found. Returns null if not.
*/
export function sourceContentFor(map: TraceMap, source: string): string | null {
const { sources, resolvedSources, sourcesContent } = map;
const { sourcesContent } = map;
if (sourcesContent == null) return null;

let index = sources.indexOf(source);
if (index === -1) index = resolvedSources.indexOf(source);

const index = sourceIndex(map, source);
return index === -1 ? null : sourcesContent[index];
}

/**
* Determines if the source is marked to ignore by the source map.
*/
export function isIgnored(map: TraceMap, source: string): boolean {
const { ignoreList } = map;
if (ignoreList == null) return false;
const index = sourceIndex(map, source);
return index === -1 ? false : ignoreList.includes(index);
}

/**
* A helper that skips sorting of the input map's mappings array, which can be expensive for larger
* maps.
Expand Down Expand Up @@ -318,7 +335,7 @@ export function encodedMap(map: TraceMap): EncodedSourceMap {
}

function clone<T extends string | readonly SourceMapSegment[][]>(
map: TraceMap | DecodedSourceMap | EncodedSourceMap,
map: TraceMap | DecodedSourceMap,
mappings: T,
): T extends string ? EncodedSourceMap : DecodedSourceMap {
return {
Expand All @@ -329,6 +346,7 @@ function clone<T extends string | readonly SourceMapSegment[][]>(
sources: map.sources,
sourcesContent: map.sourcesContent,
mappings,
ignoreList: map.ignoreList || (map as XInput).x_google_ignoreList,
} as any;
}

Expand Down
19 changes: 17 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export interface SourceMapV3 {
sources: (string | null)[];
sourcesContent?: (string | null)[];
version: 3;
ignoreList?: number[];
}

export interface EncodedSourceMap extends SourceMapV3 {
Expand Down Expand Up @@ -57,9 +58,22 @@ export type InvalidGeneratedMapping = {

export type Bias = typeof GREATEST_LOWER_BOUND | typeof LEAST_UPPER_BOUND;

export type SourceMapInput = string | Ro<EncodedSourceMap> | Ro<DecodedSourceMap> | TraceMap;
export type XInput = { x_google_ignoreList?: SourceMapV3['ignoreList'] };
export type EncodedSourceMapXInput = EncodedSourceMap & XInput;
export type DecodedSourceMapXInput = DecodedSourceMap & XInput;
export type SectionedSourceMapXInput = Omit<SectionedSourceMap, 'sections'> & {
sections: SectionXInput[];
};
export type SectionXInput = Omit<Section, 'map'> & {
map: EncodedSourceMapXInput | DecodedSourceMapXInput | SectionedSourceMapXInput;
};

export type SectionedSourceMapInput = SourceMapInput | Ro<SectionedSourceMap>;
export type SourceMapInput =
| string
| Ro<EncodedSourceMapXInput>
| Ro<DecodedSourceMapXInput>
| TraceMap;
export type SectionedSourceMapInput = SourceMapInput | Ro<SectionedSourceMapXInput>;

export type Needle = { line: number; column: number; bias?: Bias };
export type SourceNeedle = { source: string; line: number; column: number; bias?: Bias };
Expand Down Expand Up @@ -90,6 +104,7 @@ export abstract class SourceMap {
declare sources: SourceMapV3['sources'];
declare sourcesContent: SourceMapV3['sourcesContent'];
declare resolvedSources: SourceMapV3['sources'];
declare ignoreList: SourceMapV3['ignoreList'];
}

export type Ro<T> = T extends Array<infer V>
Expand Down
10 changes: 9 additions & 1 deletion test/any-map.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ describe('AnyMap', () => {
sources: ['first.js'],
sourcesContent: ['firstsource'],
mappings: 'AAAAA,CAAC',
ignoreList: [0],
},
},
{
Expand Down Expand Up @@ -58,9 +59,11 @@ describe('AnyMap', () => {
offset: { line: 0, column: 1 },
map: {
version: 3,
names: [],
sources: ['fourth.js'],
sourcesContent: ['fourthsource'],
mappings: 'AAAA',
mappings: [[[0, 0, 0, 0]]],
ignoreList: [0],
},
},
],
Expand Down Expand Up @@ -124,6 +127,11 @@ describe('AnyMap', () => {
'fourthsource',
]);
});

it('ignoreList', () => {
const tracer = new AnyMap(map);
assert.deepEqual(tracer.ignoreList, [0, 3]);
});
});

describe('typescript readonly type', () => {
Expand Down
40 changes: 40 additions & 0 deletions test/trace-mapping.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
GREATEST_LOWER_BOUND,
LEAST_UPPER_BOUND,
allGeneratedPositionsFor,
isIgnored,
} from '../src/trace-mapping';

import type {
Expand Down Expand Up @@ -151,6 +152,45 @@ describe('TraceMap', () => {
});
});

describe('isIgnored', () => {
it('returns false if no ignoreList', () => {
const tracer = new TraceMap(replaceField(map, 'ignoreList', undefined));
const source = tracer.sources[0]!;
assert.equal(isIgnored(tracer, source), false);
});

it('returns false if source not found', () => {
const tracer = new TraceMap(replaceField(map, 'ignoreList', [0]));
assert.equal(isIgnored(tracer, 'foobar'), false);
});

it('returns false if not ignored', () => {
const tracer = new TraceMap(replaceField(map, 'ignoreList', []));
const source = tracer.sources[0]!;
assert.equal(isIgnored(tracer, source), false);
});

it('returns true if ignored', () => {
const tracer = new TraceMap(replaceField(map, 'ignoreList', [0]));
const source = tracer.sources[0]!;
assert.equal(isIgnored(tracer, source), true);
});

it('returns ignored for resolved source', () => {
const tracer = new TraceMap(replaceField(map, 'ignoreList', [0]));
const source = tracer.resolvedSources[0]!;
assert.equal(isIgnored(tracer, source), true);
});

it('supports deprecated x_google_ignoreList', () => {
const tracer = new TraceMap(
replaceField(map, 'x_google_ignoreList' as 'ignoreList', [0]),
);
const source = tracer.sources[0]!;
assert.equal(isIgnored(tracer, source), true);
});
});

describe('resolvedSources', () => {
it('unresolved without sourceRoot', () => {
const tracer = new TraceMap(replaceField(map, 'sourceRoot', undefined));
Expand Down

0 comments on commit 1027ce6

Please sign in to comment.