1
- import { SetArray , put } from '@jridgewell/set-array ' ;
2
- import { presortedDecodedMap , traceSegment , decodedMappings } from '@jridgewell/trace-mapping' ;
1
+ import { GenMapping , addSegment , setSourceContent } from '@jridgewell/gen-mapping ' ;
2
+ import { traceSegment , decodedMappings } from '@jridgewell/trace-mapping' ;
3
3
4
4
import type { TraceMap } from '@jridgewell/trace-mapping' ;
5
- import type { SourceMapSegment , SourceMapSegmentObject } from './types' ;
6
5
7
- const INVALID_MAPPING = undefined ;
8
- const SOURCELESS_MAPPING = null ;
6
+ export type SourceMapSegmentObject =
7
+ | {
8
+ column : number ;
9
+ line : number ;
10
+ name : string ;
11
+ source : string ;
12
+ content : string | null ;
13
+ }
14
+ | {
15
+ column : null ;
16
+ line : null ;
17
+ name : null ;
18
+ source : null ;
19
+ content : null ;
20
+ } ;
21
+
22
+ const SOURCELESS_MAPPING = {
23
+ source : null ,
24
+ column : null ,
25
+ line : null ,
26
+ name : null ,
27
+ content : null ,
28
+ } ;
9
29
const EMPTY_SOURCES : Sources [ ] = [ ] ;
10
30
11
- type MappingSource = SourceMapSegmentObject | typeof INVALID_MAPPING | typeof SOURCELESS_MAPPING ;
12
-
13
31
type OriginalSource = {
14
32
map : TraceMap ;
15
33
sources : Sources [ ] ;
@@ -60,28 +78,24 @@ export function OriginalSource(source: string, content: string | null): Original
60
78
* traceMappings is only called on the root level SourceMapTree, and begins the process of
61
79
* resolving each mapping in terms of the original source files.
62
80
*/
63
- export function traceMappings ( tree : Sources ) : TraceMap {
64
- const mappings : SourceMapSegment [ ] [ ] = [ ] ;
65
- const names = new SetArray ( ) ;
66
- const sources = new SetArray ( ) ;
67
- const sourcesContent : ( string | null ) [ ] = [ ] ;
81
+ export function traceMappings ( tree : Sources ) : GenMapping {
82
+ const gen = new GenMapping ( tree . map . file ) ;
68
83
const { sources : rootSources , map } = tree ;
69
84
const rootNames = map . names ;
70
85
const rootMappings = decodedMappings ( map ) ;
71
86
72
- let lastLineWithSegment = - 1 ;
73
87
for ( let i = 0 ; i < rootMappings . length ; i ++ ) {
74
88
const segments = rootMappings [ i ] ;
75
- const tracedSegments : SourceMapSegment [ ] = [ ] ;
76
89
77
- let lastSourcesIndex = - 1 ;
78
- let lastSourceLine = - 1 ;
79
- let lastSourceColumn = - 1 ;
90
+ let lastSource = null ;
91
+ let lastSourceLine = null ;
92
+ let lastSourceColumn = null ;
80
93
81
94
for ( let j = 0 ; j < segments . length ; j ++ ) {
82
95
const segment = segments [ j ] ;
96
+ const genCol = segment [ 0 ] ;
97
+ let traced : SourceMapSegmentObject | null = SOURCELESS_MAPPING ;
83
98
84
- let traced : MappingSource = SOURCELESS_MAPPING ;
85
99
// 1-length segments only move the current generated column, there's no source information
86
100
// to gather from it.
87
101
if ( segment . length !== 1 ) {
@@ -95,71 +109,26 @@ export function traceMappings(tree: Sources): TraceMap {
95
109
96
110
// If the trace is invalid, then the trace ran into a sourcemap that doesn't contain a
97
111
// respective segment into an original source.
98
- if ( traced === INVALID_MAPPING ) continue ;
99
- }
100
-
101
- const genCol = segment [ 0 ] ;
102
- if ( traced === SOURCELESS_MAPPING ) {
103
- if ( lastSourcesIndex === - 1 ) {
104
- // This is a consecutive source-less segment, which doesn't carry any new information.
105
- continue ;
106
- }
107
- lastSourcesIndex = lastSourceLine = lastSourceColumn = - 1 ;
108
- tracedSegments . push ( [ genCol ] ) ;
109
- continue ;
112
+ if ( traced == null ) continue ;
110
113
}
111
114
112
115
// So we traced a segment down into its original source file. Now push a
113
116
// new segment pointing to this location.
114
117
const { column, line, name, content, source } = traced ;
115
-
116
- // Store the source location, and ensure we keep sourcesContent up to
117
- // date with the sources array.
118
- const sourcesIndex = put ( sources , source ) ;
119
- sourcesContent [ sourcesIndex ] = content ;
120
-
121
- if (
122
- lastSourcesIndex === sourcesIndex &&
123
- lastSourceLine === line &&
124
- lastSourceColumn === column
125
- ) {
126
- // This is a duplicate mapping pointing at the exact same starting point in the source
127
- // file. It doesn't carry any new information, and only bloats the sourcemap.
118
+ if ( line === lastSourceLine && column === lastSourceColumn && source === lastSource ) {
128
119
continue ;
129
120
}
130
- lastLineWithSegment = i ;
131
- lastSourcesIndex = sourcesIndex ;
132
121
lastSourceLine = line ;
133
122
lastSourceColumn = column ;
123
+ lastSource = source ;
134
124
135
- // This looks like unnecessary duplication, but it noticeably increases performance. If we
136
- // were to push the nameIndex onto length-4 array, v8 would internally allocate 22 slots!
137
- // That's 68 wasted bytes! Array literals have the same capacity as their length, saving
138
- // memory.
139
- tracedSegments . push (
140
- name
141
- ? [ genCol , sourcesIndex , line , column , put ( names , name ) ]
142
- : [ genCol , sourcesIndex , line , column ]
143
- ) ;
125
+ // Sigh, TypeScript can't figure out source/line/column are either all null, or all non-null...
126
+ ( addSegment as any ) ( gen , i , genCol , source , line , column , name ) ;
127
+ if ( content != null ) setSourceContent ( gen , source , content ) ;
144
128
}
145
-
146
- mappings . push ( tracedSegments ) ;
147
129
}
148
130
149
- if ( mappings . length > lastLineWithSegment + 1 ) {
150
- mappings . length = lastLineWithSegment + 1 ;
151
- }
152
-
153
- return presortedDecodedMap (
154
- Object . assign ( { } , tree . map , {
155
- mappings,
156
- // TODO: Make all sources relative to the sourceRoot.
157
- sourceRoot : undefined ,
158
- names : names . array ,
159
- sources : sources . array ,
160
- sourcesContent,
161
- } )
162
- ) ;
131
+ return gen ;
163
132
}
164
133
165
134
/**
@@ -171,15 +140,15 @@ export function originalPositionFor(
171
140
line : number ,
172
141
column : number ,
173
142
name : string
174
- ) : MappingSource {
143
+ ) : SourceMapSegmentObject | null {
175
144
if ( ! source . map ) {
176
145
return { column, line, name, source : source . source , content : source . content } ;
177
146
}
178
147
179
148
const segment = traceSegment ( source . map , line , column ) ;
180
149
181
150
// If we couldn't find a segment, then this doesn't exist in the sourcemap.
182
- if ( segment == null ) return INVALID_MAPPING ;
151
+ if ( segment == null ) return null ;
183
152
// 1-length segments only move the current generated column, there's no source information
184
153
// to gather from it.
185
154
if ( segment . length === 1 ) return SOURCELESS_MAPPING ;
0 commit comments