| 1 | import { SetArray, put, remove } from './set-array';
|
|---|
| 2 | import {
|
|---|
| 3 | encode,
|
|---|
| 4 | // encodeGeneratedRanges,
|
|---|
| 5 | // encodeOriginalScopes
|
|---|
| 6 | } from '@jridgewell/sourcemap-codec';
|
|---|
| 7 | import { TraceMap, decodedMappings } from '@jridgewell/trace-mapping';
|
|---|
| 8 |
|
|---|
| 9 | import {
|
|---|
| 10 | COLUMN,
|
|---|
| 11 | SOURCES_INDEX,
|
|---|
| 12 | SOURCE_LINE,
|
|---|
| 13 | SOURCE_COLUMN,
|
|---|
| 14 | NAMES_INDEX,
|
|---|
| 15 | } from './sourcemap-segment';
|
|---|
| 16 |
|
|---|
| 17 | import type { SourceMapInput } from '@jridgewell/trace-mapping';
|
|---|
| 18 | // import type { OriginalScope, GeneratedRange } from '@jridgewell/sourcemap-codec';
|
|---|
| 19 | import type { SourceMapSegment } from './sourcemap-segment';
|
|---|
| 20 | import type {
|
|---|
| 21 | DecodedSourceMap,
|
|---|
| 22 | EncodedSourceMap,
|
|---|
| 23 | Pos,
|
|---|
| 24 | Mapping,
|
|---|
| 25 | // BindingExpressionRange,
|
|---|
| 26 | // OriginalPos,
|
|---|
| 27 | // OriginalScopeInfo,
|
|---|
| 28 | // GeneratedRangeInfo,
|
|---|
| 29 | } from './types';
|
|---|
| 30 |
|
|---|
| 31 | export type { DecodedSourceMap, EncodedSourceMap, Mapping };
|
|---|
| 32 |
|
|---|
| 33 | export type Options = {
|
|---|
| 34 | file?: string | null;
|
|---|
| 35 | sourceRoot?: string | null;
|
|---|
| 36 | };
|
|---|
| 37 |
|
|---|
| 38 | const NO_NAME = -1;
|
|---|
| 39 |
|
|---|
| 40 | /**
|
|---|
| 41 | * Provides the state to generate a sourcemap.
|
|---|
| 42 | */
|
|---|
| 43 | export class GenMapping {
|
|---|
| 44 | declare private _names: SetArray<string>;
|
|---|
| 45 | declare private _sources: SetArray<string>;
|
|---|
| 46 | declare private _sourcesContent: (string | null)[];
|
|---|
| 47 | declare private _mappings: SourceMapSegment[][];
|
|---|
| 48 | // private declare _originalScopes: OriginalScope[][];
|
|---|
| 49 | // private declare _generatedRanges: GeneratedRange[];
|
|---|
| 50 | declare private _ignoreList: SetArray<number>;
|
|---|
| 51 | declare file: string | null | undefined;
|
|---|
| 52 | declare sourceRoot: string | null | undefined;
|
|---|
| 53 |
|
|---|
| 54 | constructor({ file, sourceRoot }: Options = {}) {
|
|---|
| 55 | this._names = new SetArray();
|
|---|
| 56 | this._sources = new SetArray();
|
|---|
| 57 | this._sourcesContent = [];
|
|---|
| 58 | this._mappings = [];
|
|---|
| 59 | // this._originalScopes = [];
|
|---|
| 60 | // this._generatedRanges = [];
|
|---|
| 61 | this.file = file;
|
|---|
| 62 | this.sourceRoot = sourceRoot;
|
|---|
| 63 | this._ignoreList = new SetArray();
|
|---|
| 64 | }
|
|---|
| 65 | }
|
|---|
| 66 |
|
|---|
| 67 | interface PublicMap {
|
|---|
| 68 | _names: GenMapping['_names'];
|
|---|
| 69 | _sources: GenMapping['_sources'];
|
|---|
| 70 | _sourcesContent: GenMapping['_sourcesContent'];
|
|---|
| 71 | _mappings: GenMapping['_mappings'];
|
|---|
| 72 | // _originalScopes: GenMapping['_originalScopes'];
|
|---|
| 73 | // _generatedRanges: GenMapping['_generatedRanges'];
|
|---|
| 74 | _ignoreList: GenMapping['_ignoreList'];
|
|---|
| 75 | }
|
|---|
| 76 |
|
|---|
| 77 | /**
|
|---|
| 78 | * Typescript doesn't allow friend access to private fields, so this just casts the map into a type
|
|---|
| 79 | * with public access modifiers.
|
|---|
| 80 | */
|
|---|
| 81 | function cast(map: unknown): PublicMap {
|
|---|
| 82 | return map as any;
|
|---|
| 83 | }
|
|---|
| 84 |
|
|---|
| 85 | /**
|
|---|
| 86 | * A low-level API to associate a generated position with an original source position. Line and
|
|---|
| 87 | * column here are 0-based, unlike `addMapping`.
|
|---|
| 88 | */
|
|---|
| 89 | export function addSegment(
|
|---|
| 90 | map: GenMapping,
|
|---|
| 91 | genLine: number,
|
|---|
| 92 | genColumn: number,
|
|---|
| 93 | source?: null,
|
|---|
| 94 | sourceLine?: null,
|
|---|
| 95 | sourceColumn?: null,
|
|---|
| 96 | name?: null,
|
|---|
| 97 | content?: null,
|
|---|
| 98 | ): void;
|
|---|
| 99 | export function addSegment(
|
|---|
| 100 | map: GenMapping,
|
|---|
| 101 | genLine: number,
|
|---|
| 102 | genColumn: number,
|
|---|
| 103 | source: string,
|
|---|
| 104 | sourceLine: number,
|
|---|
| 105 | sourceColumn: number,
|
|---|
| 106 | name?: null,
|
|---|
| 107 | content?: string | null,
|
|---|
| 108 | ): void;
|
|---|
| 109 | export function addSegment(
|
|---|
| 110 | map: GenMapping,
|
|---|
| 111 | genLine: number,
|
|---|
| 112 | genColumn: number,
|
|---|
| 113 | source: string,
|
|---|
| 114 | sourceLine: number,
|
|---|
| 115 | sourceColumn: number,
|
|---|
| 116 | name: string,
|
|---|
| 117 | content?: string | null,
|
|---|
| 118 | ): void;
|
|---|
| 119 | export function addSegment(
|
|---|
| 120 | map: GenMapping,
|
|---|
| 121 | genLine: number,
|
|---|
| 122 | genColumn: number,
|
|---|
| 123 | source?: string | null,
|
|---|
| 124 | sourceLine?: number | null,
|
|---|
| 125 | sourceColumn?: number | null,
|
|---|
| 126 | name?: string | null,
|
|---|
| 127 | content?: string | null,
|
|---|
| 128 | ): void {
|
|---|
| 129 | return addSegmentInternal(
|
|---|
| 130 | false,
|
|---|
| 131 | map,
|
|---|
| 132 | genLine,
|
|---|
| 133 | genColumn,
|
|---|
| 134 | source,
|
|---|
| 135 | sourceLine,
|
|---|
| 136 | sourceColumn,
|
|---|
| 137 | name,
|
|---|
| 138 | content,
|
|---|
| 139 | );
|
|---|
| 140 | }
|
|---|
| 141 |
|
|---|
| 142 | /**
|
|---|
| 143 | * A high-level API to associate a generated position with an original source position. Line is
|
|---|
| 144 | * 1-based, but column is 0-based, due to legacy behavior in `source-map` library.
|
|---|
| 145 | */
|
|---|
| 146 | export function addMapping(
|
|---|
| 147 | map: GenMapping,
|
|---|
| 148 | mapping: {
|
|---|
| 149 | generated: Pos;
|
|---|
| 150 | source?: null;
|
|---|
| 151 | original?: null;
|
|---|
| 152 | name?: null;
|
|---|
| 153 | content?: null;
|
|---|
| 154 | },
|
|---|
| 155 | ): void;
|
|---|
| 156 | export function addMapping(
|
|---|
| 157 | map: GenMapping,
|
|---|
| 158 | mapping: {
|
|---|
| 159 | generated: Pos;
|
|---|
| 160 | source: string;
|
|---|
| 161 | original: Pos;
|
|---|
| 162 | name?: null;
|
|---|
| 163 | content?: string | null;
|
|---|
| 164 | },
|
|---|
| 165 | ): void;
|
|---|
| 166 | export function addMapping(
|
|---|
| 167 | map: GenMapping,
|
|---|
| 168 | mapping: {
|
|---|
| 169 | generated: Pos;
|
|---|
| 170 | source: string;
|
|---|
| 171 | original: Pos;
|
|---|
| 172 | name: string;
|
|---|
| 173 | content?: string | null;
|
|---|
| 174 | },
|
|---|
| 175 | ): void;
|
|---|
| 176 | export function addMapping(
|
|---|
| 177 | map: GenMapping,
|
|---|
| 178 | mapping: {
|
|---|
| 179 | generated: Pos;
|
|---|
| 180 | source?: string | null;
|
|---|
| 181 | original?: Pos | null;
|
|---|
| 182 | name?: string | null;
|
|---|
| 183 | content?: string | null;
|
|---|
| 184 | },
|
|---|
| 185 | ): void {
|
|---|
| 186 | return addMappingInternal(false, map, mapping as Parameters<typeof addMappingInternal>[2]);
|
|---|
| 187 | }
|
|---|
| 188 |
|
|---|
| 189 | /**
|
|---|
| 190 | * Same as `addSegment`, but will only add the segment if it generates useful information in the
|
|---|
| 191 | * resulting map. This only works correctly if segments are added **in order**, meaning you should
|
|---|
| 192 | * not add a segment with a lower generated line/column than one that came before.
|
|---|
| 193 | */
|
|---|
| 194 | export const maybeAddSegment: typeof addSegment = (
|
|---|
| 195 | map,
|
|---|
| 196 | genLine,
|
|---|
| 197 | genColumn,
|
|---|
| 198 | source,
|
|---|
| 199 | sourceLine,
|
|---|
| 200 | sourceColumn,
|
|---|
| 201 | name,
|
|---|
| 202 | content,
|
|---|
| 203 | ) => {
|
|---|
| 204 | return addSegmentInternal(
|
|---|
| 205 | true,
|
|---|
| 206 | map,
|
|---|
| 207 | genLine,
|
|---|
| 208 | genColumn,
|
|---|
| 209 | source,
|
|---|
| 210 | sourceLine,
|
|---|
| 211 | sourceColumn,
|
|---|
| 212 | name,
|
|---|
| 213 | content,
|
|---|
| 214 | );
|
|---|
| 215 | };
|
|---|
| 216 |
|
|---|
| 217 | /**
|
|---|
| 218 | * Same as `addMapping`, but will only add the mapping if it generates useful information in the
|
|---|
| 219 | * resulting map. This only works correctly if mappings are added **in order**, meaning you should
|
|---|
| 220 | * not add a mapping with a lower generated line/column than one that came before.
|
|---|
| 221 | */
|
|---|
| 222 | export const maybeAddMapping: typeof addMapping = (map, mapping) => {
|
|---|
| 223 | return addMappingInternal(true, map, mapping as Parameters<typeof addMappingInternal>[2]);
|
|---|
| 224 | };
|
|---|
| 225 |
|
|---|
| 226 | /**
|
|---|
| 227 | * Adds/removes the content of the source file to the source map.
|
|---|
| 228 | */
|
|---|
| 229 | export function setSourceContent(map: GenMapping, source: string, content: string | null): void {
|
|---|
| 230 | const {
|
|---|
| 231 | _sources: sources,
|
|---|
| 232 | _sourcesContent: sourcesContent,
|
|---|
| 233 | // _originalScopes: originalScopes,
|
|---|
| 234 | } = cast(map);
|
|---|
| 235 | const index = put(sources, source);
|
|---|
| 236 | sourcesContent[index] = content;
|
|---|
| 237 | // if (index === originalScopes.length) originalScopes[index] = [];
|
|---|
| 238 | }
|
|---|
| 239 |
|
|---|
| 240 | export function setIgnore(map: GenMapping, source: string, ignore = true) {
|
|---|
| 241 | const {
|
|---|
| 242 | _sources: sources,
|
|---|
| 243 | _sourcesContent: sourcesContent,
|
|---|
| 244 | _ignoreList: ignoreList,
|
|---|
| 245 | // _originalScopes: originalScopes,
|
|---|
| 246 | } = cast(map);
|
|---|
| 247 | const index = put(sources, source);
|
|---|
| 248 | if (index === sourcesContent.length) sourcesContent[index] = null;
|
|---|
| 249 | // if (index === originalScopes.length) originalScopes[index] = [];
|
|---|
| 250 | if (ignore) put(ignoreList, index);
|
|---|
| 251 | else remove(ignoreList, index);
|
|---|
| 252 | }
|
|---|
| 253 |
|
|---|
| 254 | /**
|
|---|
| 255 | * Returns a sourcemap object (with decoded mappings) suitable for passing to a library that expects
|
|---|
| 256 | * a sourcemap, or to JSON.stringify.
|
|---|
| 257 | */
|
|---|
| 258 | export function toDecodedMap(map: GenMapping): DecodedSourceMap {
|
|---|
| 259 | const {
|
|---|
| 260 | _mappings: mappings,
|
|---|
| 261 | _sources: sources,
|
|---|
| 262 | _sourcesContent: sourcesContent,
|
|---|
| 263 | _names: names,
|
|---|
| 264 | _ignoreList: ignoreList,
|
|---|
| 265 | // _originalScopes: originalScopes,
|
|---|
| 266 | // _generatedRanges: generatedRanges,
|
|---|
| 267 | } = cast(map);
|
|---|
| 268 | removeEmptyFinalLines(mappings);
|
|---|
| 269 |
|
|---|
| 270 | return {
|
|---|
| 271 | version: 3,
|
|---|
| 272 | file: map.file || undefined,
|
|---|
| 273 | names: names.array,
|
|---|
| 274 | sourceRoot: map.sourceRoot || undefined,
|
|---|
| 275 | sources: sources.array,
|
|---|
| 276 | sourcesContent,
|
|---|
| 277 | mappings,
|
|---|
| 278 | // originalScopes,
|
|---|
| 279 | // generatedRanges,
|
|---|
| 280 | ignoreList: ignoreList.array,
|
|---|
| 281 | };
|
|---|
| 282 | }
|
|---|
| 283 |
|
|---|
| 284 | /**
|
|---|
| 285 | * Returns a sourcemap object (with encoded mappings) suitable for passing to a library that expects
|
|---|
| 286 | * a sourcemap, or to JSON.stringify.
|
|---|
| 287 | */
|
|---|
| 288 | export function toEncodedMap(map: GenMapping): EncodedSourceMap {
|
|---|
| 289 | const decoded = toDecodedMap(map);
|
|---|
| 290 | return Object.assign({}, decoded, {
|
|---|
| 291 | // originalScopes: decoded.originalScopes.map((os) => encodeOriginalScopes(os)),
|
|---|
| 292 | // generatedRanges: encodeGeneratedRanges(decoded.generatedRanges as GeneratedRange[]),
|
|---|
| 293 | mappings: encode(decoded.mappings as SourceMapSegment[][]),
|
|---|
| 294 | });
|
|---|
| 295 | }
|
|---|
| 296 |
|
|---|
| 297 | /**
|
|---|
| 298 | * Constructs a new GenMapping, using the already present mappings of the input.
|
|---|
| 299 | */
|
|---|
| 300 | export function fromMap(input: SourceMapInput): GenMapping {
|
|---|
| 301 | const map = new TraceMap(input);
|
|---|
| 302 | const gen = new GenMapping({ file: map.file, sourceRoot: map.sourceRoot });
|
|---|
| 303 |
|
|---|
| 304 | putAll(cast(gen)._names, map.names);
|
|---|
| 305 | putAll(cast(gen)._sources, map.sources as string[]);
|
|---|
| 306 | cast(gen)._sourcesContent = map.sourcesContent || map.sources.map(() => null);
|
|---|
| 307 | cast(gen)._mappings = decodedMappings(map) as GenMapping['_mappings'];
|
|---|
| 308 | // TODO: implement originalScopes/generatedRanges
|
|---|
| 309 | if (map.ignoreList) putAll(cast(gen)._ignoreList, map.ignoreList);
|
|---|
| 310 |
|
|---|
| 311 | return gen;
|
|---|
| 312 | }
|
|---|
| 313 |
|
|---|
| 314 | /**
|
|---|
| 315 | * Returns an array of high-level mapping objects for every recorded segment, which could then be
|
|---|
| 316 | * passed to the `source-map` library.
|
|---|
| 317 | */
|
|---|
| 318 | export function allMappings(map: GenMapping): Mapping[] {
|
|---|
| 319 | const out: Mapping[] = [];
|
|---|
| 320 | const { _mappings: mappings, _sources: sources, _names: names } = cast(map);
|
|---|
| 321 |
|
|---|
| 322 | for (let i = 0; i < mappings.length; i++) {
|
|---|
| 323 | const line = mappings[i];
|
|---|
| 324 | for (let j = 0; j < line.length; j++) {
|
|---|
| 325 | const seg = line[j];
|
|---|
| 326 |
|
|---|
| 327 | const generated = { line: i + 1, column: seg[COLUMN] };
|
|---|
| 328 | let source: string | undefined = undefined;
|
|---|
| 329 | let original: Pos | undefined = undefined;
|
|---|
| 330 | let name: string | undefined = undefined;
|
|---|
| 331 |
|
|---|
| 332 | if (seg.length !== 1) {
|
|---|
| 333 | source = sources.array[seg[SOURCES_INDEX]];
|
|---|
| 334 | original = { line: seg[SOURCE_LINE] + 1, column: seg[SOURCE_COLUMN] };
|
|---|
| 335 |
|
|---|
| 336 | if (seg.length === 5) name = names.array[seg[NAMES_INDEX]];
|
|---|
| 337 | }
|
|---|
| 338 |
|
|---|
| 339 | out.push({ generated, source, original, name } as Mapping);
|
|---|
| 340 | }
|
|---|
| 341 | }
|
|---|
| 342 |
|
|---|
| 343 | return out;
|
|---|
| 344 | }
|
|---|
| 345 |
|
|---|
| 346 | // This split declaration is only so that terser can elminiate the static initialization block.
|
|---|
| 347 | function addSegmentInternal<S extends string | null | undefined>(
|
|---|
| 348 | skipable: boolean,
|
|---|
| 349 | map: GenMapping,
|
|---|
| 350 | genLine: number,
|
|---|
| 351 | genColumn: number,
|
|---|
| 352 | source: S,
|
|---|
| 353 | sourceLine: S extends string ? number : null | undefined,
|
|---|
| 354 | sourceColumn: S extends string ? number : null | undefined,
|
|---|
| 355 | name: S extends string ? string | null | undefined : null | undefined,
|
|---|
| 356 | content: S extends string ? string | null | undefined : null | undefined,
|
|---|
| 357 | ): void {
|
|---|
| 358 | const {
|
|---|
| 359 | _mappings: mappings,
|
|---|
| 360 | _sources: sources,
|
|---|
| 361 | _sourcesContent: sourcesContent,
|
|---|
| 362 | _names: names,
|
|---|
| 363 | // _originalScopes: originalScopes,
|
|---|
| 364 | } = cast(map);
|
|---|
| 365 | const line = getIndex(mappings, genLine);
|
|---|
| 366 | const index = getColumnIndex(line, genColumn);
|
|---|
| 367 |
|
|---|
| 368 | if (!source) {
|
|---|
| 369 | if (skipable && skipSourceless(line, index)) return;
|
|---|
| 370 | return insert(line, index, [genColumn]);
|
|---|
| 371 | }
|
|---|
| 372 |
|
|---|
| 373 | // Sigh, TypeScript can't figure out sourceLine and sourceColumn aren't nullish if source
|
|---|
| 374 | // isn't nullish.
|
|---|
| 375 | assert<number>(sourceLine);
|
|---|
| 376 | assert<number>(sourceColumn);
|
|---|
| 377 |
|
|---|
| 378 | const sourcesIndex = put(sources, source);
|
|---|
| 379 | const namesIndex = name ? put(names, name) : NO_NAME;
|
|---|
| 380 | if (sourcesIndex === sourcesContent.length) sourcesContent[sourcesIndex] = content ?? null;
|
|---|
| 381 | // if (sourcesIndex === originalScopes.length) originalScopes[sourcesIndex] = [];
|
|---|
| 382 |
|
|---|
| 383 | if (skipable && skipSource(line, index, sourcesIndex, sourceLine, sourceColumn, namesIndex)) {
|
|---|
| 384 | return;
|
|---|
| 385 | }
|
|---|
| 386 |
|
|---|
| 387 | return insert(
|
|---|
| 388 | line,
|
|---|
| 389 | index,
|
|---|
| 390 | name
|
|---|
| 391 | ? [genColumn, sourcesIndex, sourceLine, sourceColumn, namesIndex]
|
|---|
| 392 | : [genColumn, sourcesIndex, sourceLine, sourceColumn],
|
|---|
| 393 | );
|
|---|
| 394 | }
|
|---|
| 395 |
|
|---|
| 396 | function assert<T>(_val: unknown): asserts _val is T {
|
|---|
| 397 | // noop.
|
|---|
| 398 | }
|
|---|
| 399 |
|
|---|
| 400 | function getIndex<T>(arr: T[][], index: number): T[] {
|
|---|
| 401 | for (let i = arr.length; i <= index; i++) {
|
|---|
| 402 | arr[i] = [];
|
|---|
| 403 | }
|
|---|
| 404 | return arr[index];
|
|---|
| 405 | }
|
|---|
| 406 |
|
|---|
| 407 | function getColumnIndex(line: SourceMapSegment[], genColumn: number): number {
|
|---|
| 408 | let index = line.length;
|
|---|
| 409 | for (let i = index - 1; i >= 0; index = i--) {
|
|---|
| 410 | const current = line[i];
|
|---|
| 411 | if (genColumn >= current[COLUMN]) break;
|
|---|
| 412 | }
|
|---|
| 413 | return index;
|
|---|
| 414 | }
|
|---|
| 415 |
|
|---|
| 416 | function insert<T>(array: T[], index: number, value: T) {
|
|---|
| 417 | for (let i = array.length; i > index; i--) {
|
|---|
| 418 | array[i] = array[i - 1];
|
|---|
| 419 | }
|
|---|
| 420 | array[index] = value;
|
|---|
| 421 | }
|
|---|
| 422 |
|
|---|
| 423 | function removeEmptyFinalLines(mappings: SourceMapSegment[][]) {
|
|---|
| 424 | const { length } = mappings;
|
|---|
| 425 | let len = length;
|
|---|
| 426 | for (let i = len - 1; i >= 0; len = i, i--) {
|
|---|
| 427 | if (mappings[i].length > 0) break;
|
|---|
| 428 | }
|
|---|
| 429 | if (len < length) mappings.length = len;
|
|---|
| 430 | }
|
|---|
| 431 |
|
|---|
| 432 | function putAll<T extends string | number>(setarr: SetArray<T>, array: T[]) {
|
|---|
| 433 | for (let i = 0; i < array.length; i++) put(setarr, array[i]);
|
|---|
| 434 | }
|
|---|
| 435 |
|
|---|
| 436 | function skipSourceless(line: SourceMapSegment[], index: number): boolean {
|
|---|
| 437 | // The start of a line is already sourceless, so adding a sourceless segment to the beginning
|
|---|
| 438 | // doesn't generate any useful information.
|
|---|
| 439 | if (index === 0) return true;
|
|---|
| 440 |
|
|---|
| 441 | const prev = line[index - 1];
|
|---|
| 442 | // If the previous segment is also sourceless, then adding another sourceless segment doesn't
|
|---|
| 443 | // genrate any new information. Else, this segment will end the source/named segment and point to
|
|---|
| 444 | // a sourceless position, which is useful.
|
|---|
| 445 | return prev.length === 1;
|
|---|
| 446 | }
|
|---|
| 447 |
|
|---|
| 448 | function skipSource(
|
|---|
| 449 | line: SourceMapSegment[],
|
|---|
| 450 | index: number,
|
|---|
| 451 | sourcesIndex: number,
|
|---|
| 452 | sourceLine: number,
|
|---|
| 453 | sourceColumn: number,
|
|---|
| 454 | namesIndex: number,
|
|---|
| 455 | ): boolean {
|
|---|
| 456 | // A source/named segment at the start of a line gives position at that genColumn
|
|---|
| 457 | if (index === 0) return false;
|
|---|
| 458 |
|
|---|
| 459 | const prev = line[index - 1];
|
|---|
| 460 |
|
|---|
| 461 | // If the previous segment is sourceless, then we're transitioning to a source.
|
|---|
| 462 | if (prev.length === 1) return false;
|
|---|
| 463 |
|
|---|
| 464 | // If the previous segment maps to the exact same source position, then this segment doesn't
|
|---|
| 465 | // provide any new position information.
|
|---|
| 466 | return (
|
|---|
| 467 | sourcesIndex === prev[SOURCES_INDEX] &&
|
|---|
| 468 | sourceLine === prev[SOURCE_LINE] &&
|
|---|
| 469 | sourceColumn === prev[SOURCE_COLUMN] &&
|
|---|
| 470 | namesIndex === (prev.length === 5 ? prev[NAMES_INDEX] : NO_NAME)
|
|---|
| 471 | );
|
|---|
| 472 | }
|
|---|
| 473 |
|
|---|
| 474 | function addMappingInternal<S extends string | null | undefined>(
|
|---|
| 475 | skipable: boolean,
|
|---|
| 476 | map: GenMapping,
|
|---|
| 477 | mapping: {
|
|---|
| 478 | generated: Pos;
|
|---|
| 479 | source: S;
|
|---|
| 480 | original: S extends string ? Pos : null | undefined;
|
|---|
| 481 | name: S extends string ? string | null | undefined : null | undefined;
|
|---|
| 482 | content: S extends string ? string | null | undefined : null | undefined;
|
|---|
| 483 | },
|
|---|
| 484 | ) {
|
|---|
| 485 | const { generated, source, original, name, content } = mapping;
|
|---|
| 486 | if (!source) {
|
|---|
| 487 | return addSegmentInternal(
|
|---|
| 488 | skipable,
|
|---|
| 489 | map,
|
|---|
| 490 | generated.line - 1,
|
|---|
| 491 | generated.column,
|
|---|
| 492 | null,
|
|---|
| 493 | null,
|
|---|
| 494 | null,
|
|---|
| 495 | null,
|
|---|
| 496 | null,
|
|---|
| 497 | );
|
|---|
| 498 | }
|
|---|
| 499 | assert<Pos>(original);
|
|---|
| 500 | return addSegmentInternal(
|
|---|
| 501 | skipable,
|
|---|
| 502 | map,
|
|---|
| 503 | generated.line - 1,
|
|---|
| 504 | generated.column,
|
|---|
| 505 | source as string,
|
|---|
| 506 | original.line - 1,
|
|---|
| 507 | original.column,
|
|---|
| 508 | name,
|
|---|
| 509 | content,
|
|---|
| 510 | );
|
|---|
| 511 | }
|
|---|
| 512 |
|
|---|
| 513 | /*
|
|---|
| 514 | export function addOriginalScope(
|
|---|
| 515 | map: GenMapping,
|
|---|
| 516 | data: {
|
|---|
| 517 | start: Pos;
|
|---|
| 518 | end: Pos;
|
|---|
| 519 | source: string;
|
|---|
| 520 | kind: string;
|
|---|
| 521 | name?: string;
|
|---|
| 522 | variables?: string[];
|
|---|
| 523 | },
|
|---|
| 524 | ): OriginalScopeInfo {
|
|---|
| 525 | const { start, end, source, kind, name, variables } = data;
|
|---|
| 526 | const {
|
|---|
| 527 | _sources: sources,
|
|---|
| 528 | _sourcesContent: sourcesContent,
|
|---|
| 529 | _originalScopes: originalScopes,
|
|---|
| 530 | _names: names,
|
|---|
| 531 | } = cast(map);
|
|---|
| 532 | const index = put(sources, source);
|
|---|
| 533 | if (index === sourcesContent.length) sourcesContent[index] = null;
|
|---|
| 534 | if (index === originalScopes.length) originalScopes[index] = [];
|
|---|
| 535 |
|
|---|
| 536 | const kindIndex = put(names, kind);
|
|---|
| 537 | const scope: OriginalScope = name
|
|---|
| 538 | ? [start.line - 1, start.column, end.line - 1, end.column, kindIndex, put(names, name)]
|
|---|
| 539 | : [start.line - 1, start.column, end.line - 1, end.column, kindIndex];
|
|---|
| 540 | if (variables) {
|
|---|
| 541 | scope.vars = variables.map((v) => put(names, v));
|
|---|
| 542 | }
|
|---|
| 543 | const len = originalScopes[index].push(scope);
|
|---|
| 544 | return [index, len - 1, variables];
|
|---|
| 545 | }
|
|---|
| 546 | */
|
|---|
| 547 |
|
|---|
| 548 | // Generated Ranges
|
|---|
| 549 | /*
|
|---|
| 550 | export function addGeneratedRange(
|
|---|
| 551 | map: GenMapping,
|
|---|
| 552 | data: {
|
|---|
| 553 | start: Pos;
|
|---|
| 554 | isScope: boolean;
|
|---|
| 555 | originalScope?: OriginalScopeInfo;
|
|---|
| 556 | callsite?: OriginalPos;
|
|---|
| 557 | },
|
|---|
| 558 | ): GeneratedRangeInfo {
|
|---|
| 559 | const { start, isScope, originalScope, callsite } = data;
|
|---|
| 560 | const {
|
|---|
| 561 | _originalScopes: originalScopes,
|
|---|
| 562 | _sources: sources,
|
|---|
| 563 | _sourcesContent: sourcesContent,
|
|---|
| 564 | _generatedRanges: generatedRanges,
|
|---|
| 565 | } = cast(map);
|
|---|
| 566 |
|
|---|
| 567 | const range: GeneratedRange = [
|
|---|
| 568 | start.line - 1,
|
|---|
| 569 | start.column,
|
|---|
| 570 | 0,
|
|---|
| 571 | 0,
|
|---|
| 572 | originalScope ? originalScope[0] : -1,
|
|---|
| 573 | originalScope ? originalScope[1] : -1,
|
|---|
| 574 | ];
|
|---|
| 575 | if (originalScope?.[2]) {
|
|---|
| 576 | range.bindings = originalScope[2].map(() => [[-1]]);
|
|---|
| 577 | }
|
|---|
| 578 | if (callsite) {
|
|---|
| 579 | const index = put(sources, callsite.source);
|
|---|
| 580 | if (index === sourcesContent.length) sourcesContent[index] = null;
|
|---|
| 581 | if (index === originalScopes.length) originalScopes[index] = [];
|
|---|
| 582 | range.callsite = [index, callsite.line - 1, callsite.column];
|
|---|
| 583 | }
|
|---|
| 584 | if (isScope) range.isScope = true;
|
|---|
| 585 | generatedRanges.push(range);
|
|---|
| 586 |
|
|---|
| 587 | return [range, originalScope?.[2]];
|
|---|
| 588 | }
|
|---|
| 589 |
|
|---|
| 590 | export function setEndPosition(range: GeneratedRangeInfo, pos: Pos) {
|
|---|
| 591 | range[0][2] = pos.line - 1;
|
|---|
| 592 | range[0][3] = pos.column;
|
|---|
| 593 | }
|
|---|
| 594 |
|
|---|
| 595 | export function addBinding(
|
|---|
| 596 | map: GenMapping,
|
|---|
| 597 | range: GeneratedRangeInfo,
|
|---|
| 598 | variable: string,
|
|---|
| 599 | expression: string | BindingExpressionRange,
|
|---|
| 600 | ) {
|
|---|
| 601 | const { _names: names } = cast(map);
|
|---|
| 602 | const bindings = (range[0].bindings ||= []);
|
|---|
| 603 | const vars = range[1];
|
|---|
| 604 |
|
|---|
| 605 | const index = vars!.indexOf(variable);
|
|---|
| 606 | const binding = getIndex(bindings, index);
|
|---|
| 607 |
|
|---|
| 608 | if (typeof expression === 'string') binding[0] = [put(names, expression)];
|
|---|
| 609 | else {
|
|---|
| 610 | const { start } = expression;
|
|---|
| 611 | binding.push([put(names, expression.expression), start.line - 1, start.column]);
|
|---|
| 612 | }
|
|---|
| 613 | }
|
|---|
| 614 | */
|
|---|