@@ -6,32 +6,109 @@ export interface SourceMapCursor {
66 /**
77 * The source map being traversed.
88 */
9- sourceMap : SourceMap ;
9+ readonly sourceMap : SourceMap ;
1010 /**
1111 * The current index in the source map.
1212 */
13- idx : number ;
13+ readonly idx : number ;
1414 /**
1515 * The base offset in the source text.
1616 */
17- base0 : number ;
17+ readonly begin0 : number ;
1818 /**
1919 * The base offset in the transformed text.
2020 */
21- base1 : number ;
21+ readonly begin1 : number ;
22+
23+ reset ( ) : void ;
24+
25+ mapOffsetToDest ( offsetInSrc : number ) : number ;
26+ mapOffsetToSrc ( offsetInDst : number ) : number ;
2227}
2328
2429class SourceMapCursorImpl implements SourceMapCursor {
2530 sourceMap : SourceMap ;
2631 idx : number ;
27- base0 : number ;
28- base1 : number ;
32+ begin0 : number ;
33+ begin1 : number ;
34+ /**
35+ * The delta in the source
36+ */
37+ d0 : number ;
38+ /**
39+ * The delta in the transformed text.
40+ */
41+ d1 : number ;
42+ /**
43+ * Indicates whether the current segment is linear (1:1) or non-linear.
44+ * A linear segment has equal deltas in the source and transformed text,
45+ * while a non-linear segment has different deltas.
46+ * It is possible that a non-linear segment has the same deltas,
47+ * but it is not possible for a linear segment to have different deltas.
48+ */
49+ linear : boolean ;
50+ /**
51+ * indicates that the cursor has reached the end of the source map.
52+ */
53+ done : boolean ;
2954
3055 constructor ( sourceMap : SourceMap ) {
3156 this . sourceMap = sourceMap ;
32- this . idx = 0 ;
33- this . base0 = 0 ;
34- this . base1 = 0 ;
57+ this . idx = - 2 ;
58+ this . begin0 = 0 ;
59+ this . begin1 = 0 ;
60+ this . d0 = 0 ;
61+ this . d1 = 0 ;
62+ this . linear = true ;
63+ this . done = false ;
64+ this . next ( ) ;
65+ }
66+
67+ next ( ) : boolean {
68+ if ( this . done ) return false ;
69+ this . idx += 2 ;
70+ this . begin0 += this . d0 ;
71+ this . begin1 += this . d1 ;
72+ this . d0 = this . sourceMap [ this . idx ] || 0 ;
73+ this . d1 = this . sourceMap [ this . idx + 1 ] || 0 ;
74+ this . linear = this . d0 === this . d1 ;
75+ this . done = this . idx >= this . sourceMap . length ;
76+ if ( this . d0 === 0 && this . d1 === 0 && ! this . done ) {
77+ this . next ( ) ;
78+ this . linear = this . done ;
79+ }
80+ return ! this . done ;
81+ }
82+
83+ mapOffsetToDest ( offsetInSrc : number ) : number {
84+ if ( offsetInSrc < this . begin0 ) this . reset ( ) ;
85+ while ( ! this . done && offsetInSrc >= this . begin0 + this . d0 ) {
86+ this . next ( ) ;
87+ }
88+ if ( this . linear ) {
89+ return offsetInSrc - this . begin0 + this . begin1 ;
90+ }
91+ // For a non-linear segment, the offset in the source maps to the start of the segment in the transformed text.
92+ return this . begin1 ;
93+ }
94+
95+ mapOffsetToSrc ( offsetInDst : number ) : number {
96+ if ( offsetInDst < this . begin1 ) this . reset ( ) ;
97+ while ( ! this . done && offsetInDst >= this . begin1 + this . d1 ) {
98+ this . next ( ) ;
99+ }
100+ if ( this . linear ) {
101+ return offsetInDst - this . begin1 + this . begin0 ;
102+ }
103+ // For a non-linear segment, the offset in the source maps to the start of the segment in the transformed text.
104+ return this . begin0 ;
105+ }
106+
107+ reset ( ) : void {
108+ this . idx = - 2 ;
109+ this . begin0 = 0 ;
110+ this . begin1 = 0 ;
111+ this . next ( ) ;
35112 }
36113}
37114
@@ -50,12 +127,6 @@ export function createSourceMapCursor(sourceMap: SourceMap | undefined): SourceM
50127 return new SourceMapCursorImpl ( sourceMap ) ;
51128}
52129
53- export function resetCursor ( cursor : SourceMapCursor ) : void {
54- cursor . idx = 0 ;
55- cursor . base0 = 0 ;
56- cursor . base1 = 0 ;
57- }
58-
59130/**
60131 * Calculated the transformed offset in the destination text based on the source map and the offset in the source text.
61132 * @param cursor - The cursor to use for the mapping. If undefined or empty, the input offset is returned, assuming it is a 1:1 mapping.
@@ -67,33 +138,7 @@ export function calcOffsetInDst(cursor: SourceMapCursor | undefined, offsetInSrc
67138 return offsetInSrc ;
68139 }
69140
70- if ( offsetInSrc < cursor . base0 ) {
71- // If the offset is before the current base, reset the cursor to the start of the map.
72- resetCursor ( cursor ) ;
73- }
74-
75- const srcMap = cursor . sourceMap ;
76-
77- let idx = cursor . idx ;
78- let base0 = cursor . base0 ;
79- let base1 = cursor . base1 ;
80- for ( ; idx < srcMap . length && offsetInSrc > srcMap [ idx ] + base0 ; idx += 2 ) {
81- base0 += srcMap [ idx ] ;
82- base1 += srcMap [ idx + 1 ] ;
83- }
84-
85- cursor . idx = idx ;
86- cursor . base0 = base0 ;
87- cursor . base1 = base1 ;
88-
89- if ( offsetInSrc === srcMap [ idx ] + base1 ) {
90- base0 += srcMap [ idx ] ;
91- base1 += srcMap [ idx + 1 ] ;
92- idx += 2 ;
93- }
94- const d0 = srcMap [ idx ] ;
95- const d1 = srcMap [ idx + 1 ] ;
96- return d0 === d1 ? offsetInSrc - base0 + base1 : base1 ;
141+ return cursor . mapOffsetToDest ( offsetInSrc ) ;
97142}
98143
99144/**
@@ -107,34 +152,7 @@ export function calcOffsetInSrc(cursor: SourceMapCursor | undefined, offsetInDst
107152 return offsetInDst ;
108153 }
109154
110- if ( offsetInDst < cursor . base1 ) {
111- // If the offset is before the current base, reset the cursor to the start of the map.
112- resetCursor ( cursor ) ;
113- }
114-
115- const srcMap = cursor . sourceMap ;
116-
117- let idx = cursor . idx ;
118- let base0 = cursor . base0 ;
119- let base1 = cursor . base1 ;
120- for ( ; idx < srcMap . length && offsetInDst > srcMap [ idx + 1 ] + base1 ; idx += 2 ) {
121- base0 += srcMap [ idx ] ;
122- base1 += srcMap [ idx + 1 ] ;
123- }
124-
125- cursor . idx = idx ;
126- cursor . base0 = base0 ;
127- cursor . base1 = base1 ;
128-
129- if ( offsetInDst === srcMap [ idx + 1 ] + base1 ) {
130- base0 += srcMap [ idx ] ;
131- base1 += srcMap [ idx + 1 ] ;
132- idx += 2 ;
133- }
134-
135- const d0 = srcMap [ idx ] ;
136- const d1 = srcMap [ idx + 1 ] ;
137- return d0 === d1 ? offsetInDst - base1 + base0 : base0 ;
155+ return cursor . mapOffsetToSrc ( offsetInDst ) ;
138156}
139157
140158/**
0 commit comments