1
- import { DecodedSourceMap , RawSourceMap , SourceMapSegment , SourceMapLoader } from '@ampproject/remapping/dist/types/types' ;
1
+ import { DecodedSourceMap , RawSourceMap , SourceMapLoader } from '@ampproject/remapping/dist/types/types' ;
2
2
import remapping from '@ampproject/remapping' ;
3
+ import { SourceMap } from 'magic-string' ;
3
4
4
5
type SourceLocation = {
5
6
line : number ;
@@ -14,17 +15,21 @@ function last_line_length(s: string) {
14
15
export function sourcemap_add_offset (
15
16
map : DecodedSourceMap , offset : SourceLocation
16
17
) {
18
+ if ( map . mappings . length == 0 ) return map ;
17
19
// shift columns in first line
18
- const m = map . mappings ;
19
- m [ 0 ] . forEach ( seg => {
20
+ const segment_list = map . mappings [ 0 ] ;
21
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
22
+ const seg = segment_list [ segment ] ;
20
23
if ( seg [ 3 ] ) seg [ 3 ] += offset . column ;
21
- } ) ;
24
+ }
22
25
// shift lines
23
- m . forEach ( line => {
24
- line . forEach ( seg => {
26
+ for ( let line = 0 ; line < map . mappings . length ; line ++ ) {
27
+ const segment_list = map . mappings [ line ] ;
28
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
29
+ const seg = segment_list [ segment ] ;
25
30
if ( seg [ 2 ] ) seg [ 2 ] += offset . line ;
26
- } ) ;
27
- } ) ;
31
+ }
32
+ }
28
33
}
29
34
30
35
function merge_tables < T > ( this_table : T [ ] , other_table ) : [ T [ ] , number [ ] , boolean , boolean ] {
@@ -91,6 +96,8 @@ export class StringWithSourcemap {
91
96
const m1 = this . map ;
92
97
const m2 = other . map ;
93
98
99
+ if ( m2 . mappings . length == 0 ) return this ;
100
+
94
101
// combine sources and names
95
102
const [ sources , new_source_idx , sources_changed , sources_idx_changed ] = merge_tables ( m1 . sources , m2 . sources ) ;
96
103
const [ names , new_name_idx , names_changed , names_idx_changed ] = merge_tables ( m1 . names , m2 . names ) ;
@@ -100,24 +107,30 @@ export class StringWithSourcemap {
100
107
101
108
// unswitched loops are faster
102
109
if ( sources_idx_changed && names_idx_changed ) {
103
- m2 . mappings . forEach ( line => {
104
- line . forEach ( seg => {
110
+ for ( let line = 0 ; line < m2 . mappings . length ; line ++ ) {
111
+ const segment_list = m2 . mappings [ line ] ;
112
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
113
+ const seg = segment_list [ segment ] ;
105
114
if ( seg [ 1 ] ) seg [ 1 ] = new_source_idx [ seg [ 1 ] ] ;
106
115
if ( seg [ 4 ] ) seg [ 4 ] = new_name_idx [ seg [ 4 ] ] ;
107
- } ) ;
108
- } ) ;
116
+ }
117
+ }
109
118
} else if ( sources_idx_changed ) {
110
- m2 . mappings . forEach ( line => {
111
- line . forEach ( seg => {
119
+ for ( let line = 0 ; line < m2 . mappings . length ; line ++ ) {
120
+ const segment_list = m2 . mappings [ line ] ;
121
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
122
+ const seg = segment_list [ segment ] ;
112
123
if ( seg [ 1 ] ) seg [ 1 ] = new_source_idx [ seg [ 1 ] ] ;
113
- } ) ;
114
- } ) ;
124
+ }
125
+ }
115
126
} else if ( names_idx_changed ) {
116
- m2 . mappings . forEach ( line => {
117
- line . forEach ( seg => {
127
+ for ( let line = 0 ; line < m2 . mappings . length ; line ++ ) {
128
+ const segment_list = m2 . mappings [ line ] ;
129
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
130
+ const seg = segment_list [ segment ] ;
118
131
if ( seg [ 4 ] ) seg [ 4 ] = new_name_idx [ seg [ 4 ] ] ;
119
- } ) ;
120
- } ) ;
132
+ }
133
+ }
121
134
}
122
135
123
136
// combine the mappings
@@ -129,10 +142,10 @@ export class StringWithSourcemap {
129
142
130
143
const column_offset = last_line_length ( this . string ) ;
131
144
if ( m2 . mappings . length > 0 && column_offset > 0 ) {
132
- // shift columns in first line
133
- m2 . mappings [ 0 ] . forEach ( seg => {
134
- seg [ 0 ] += column_offset ;
135
- } ) ;
145
+ const first_line = m2 . mappings [ 0 ] ;
146
+ for ( let i = 0 ; i < first_line . length ; i ++ ) {
147
+ first_line [ i ] [ 0 ] += column_offset ;
148
+ }
136
149
}
137
150
138
151
// combine last line + first line
@@ -146,38 +159,40 @@ export class StringWithSourcemap {
146
159
147
160
static from_processed ( string : string , map ?: DecodedSourceMap ) : StringWithSourcemap {
148
161
if ( map ) return new StringWithSourcemap ( string , map ) ;
162
+ if ( string == '' ) return new StringWithSourcemap ( ) ;
149
163
map = { version : 3 , names : [ ] , sources : [ ] , mappings : [ ] } ;
150
- if ( string == '' ) return new StringWithSourcemap ( string , map ) ;
164
+
151
165
// add empty SourceMapSegment[] for every line
152
- const lineCount = string . split ( '\n ') . length ;
153
- map . mappings = Array . from ( { length : lineCount } ) . map ( _ => [ ] ) ;
166
+ const line_count = ( string . match ( / \n / g ) || ' ') . length ;
167
+ for ( let i = 0 ; i < line_count ; i ++ ) map . mappings . push ( [ ] ) ;
154
168
return new StringWithSourcemap ( string , map ) ;
155
169
}
156
170
157
171
static from_source (
158
- source_file : string , source : string , offset_in_source ?: SourceLocation
172
+ source_file : string , source : string , offset ?: SourceLocation
159
173
) : StringWithSourcemap {
160
- const offset = offset_in_source || { line : 0 , column : 0 } ;
174
+ if ( ! offset ) offset = { line : 0 , column : 0 } ;
161
175
const map : DecodedSourceMap = { version : 3 , names : [ ] , sources : [ source_file ] , mappings : [ ] } ;
162
- if ( source . length == 0 ) return new StringWithSourcemap ( source , map ) ;
176
+ if ( source == '' ) return new StringWithSourcemap ( source , map ) ;
163
177
164
178
// we create a high resolution identity map here,
165
179
// we know that it will eventually be merged with svelte's map,
166
180
// at which stage the resolution will decrease.
167
- map . mappings = source . split ( '\n' ) . map ( ( line , line_idx ) => {
168
- let pos = 0 ;
169
- const segs = line . split ( / ( [ ^ \d \w \s ] | \s + ) / g)
170
- . filter ( s => s !== '' ) . map ( s => {
171
- const seg : SourceMapSegment = [
172
- pos , 0 ,
173
- line_idx + offset . line ,
174
- pos + ( line_idx == 0 ? offset . column : 0 ) // shift first line
175
- ] ;
176
- pos = pos + s . length ;
177
- return seg ;
178
- } ) ;
179
- return segs ;
180
- } ) ;
181
+ const line_list = source . split ( '\n' ) ;
182
+ for ( let line = 0 ; line < line_list . length ; line ++ ) {
183
+ map . mappings . push ( [ ] ) ;
184
+ const token_list = line_list [ line ] . split ( / ( [ ^ \d \w \s ] | \s + ) / g) ;
185
+ for ( let token = 0 , column = 0 ; token < token_list . length ; token ++ ) {
186
+ if ( token_list [ token ] == '' ) continue ;
187
+ map . mappings [ line ] . push ( [ column , 0 , offset . line + line , column ] ) ;
188
+ column += token_list [ token ] . length ;
189
+ }
190
+ }
191
+ // shift columns in first line
192
+ const segment_list = map . mappings [ 0 ] ;
193
+ for ( let segment = 0 ; segment < segment_list . length ; segment ++ ) {
194
+ segment_list [ segment ] [ 3 ] += offset . column ;
195
+ }
181
196
return new StringWithSourcemap ( source , map ) ;
182
197
}
183
198
}
@@ -191,34 +206,51 @@ export function combine_sourcemaps(
191
206
let map_idx = 1 ;
192
207
const map : RawSourceMap =
193
208
sourcemap_list . slice ( 0 , - 1 )
194
- . find ( m => m . sources . length !== 1 ) === undefined
209
+ . find ( m => m . sources . length !== 1 ) === undefined
195
210
196
211
? remapping ( // use array interface
197
- // only the oldest sourcemap can have multiple sources
198
- sourcemap_list ,
199
- ( ) => null ,
200
- true // skip optional field `sourcesContent`
201
- )
212
+ // only the oldest sourcemap can have multiple sources
213
+ sourcemap_list ,
214
+ ( ) => null ,
215
+ true // skip optional field `sourcesContent`
216
+ )
202
217
203
218
: remapping ( // use loader interface
204
- sourcemap_list [ 0 ] , // last map
205
- function loader ( sourcefile ) {
206
- if ( sourcefile === filename && sourcemap_list [ map_idx ] ) {
207
- return sourcemap_list [ map_idx ++ ] ; // idx 1, 2, ...
208
- // bundle file = branch node
209
- }
210
- else return null ; // source file = leaf node
211
- } as SourceMapLoader ,
212
- true
213
- ) ;
219
+ sourcemap_list [ 0 ] , // last map
220
+ function loader ( sourcefile ) {
221
+ if ( sourcefile === filename && sourcemap_list [ map_idx ] ) {
222
+ return sourcemap_list [ map_idx ++ ] ; // idx 1, 2, ...
223
+ // bundle file = branch node
224
+ }
225
+ else return null ; // source file = leaf node
226
+ } as SourceMapLoader ,
227
+ true
228
+ ) ;
214
229
215
230
if ( ! map . file ) delete map . file ; // skip optional field `file`
216
231
217
232
return map ;
218
233
}
219
234
220
- export function sourcemap_define_tostring_tourl ( map ) {
221
- Object . defineProperties ( map , {
235
+ // browser vs node.js
236
+ const b64enc = typeof btoa == 'function' ? btoa : b => Buffer . from ( b ) . toString ( 'base64' ) ;
237
+
238
+ export function apply_preprocessor_sourcemap ( filename : string , svelte_map : SourceMap , preprocessor_map_input : string | DecodedSourceMap | RawSourceMap ) : SourceMap {
239
+ if ( ! svelte_map || ! preprocessor_map_input ) return svelte_map ;
240
+
241
+ const preprocessor_map = typeof preprocessor_map_input === 'string' ? JSON . parse ( preprocessor_map_input ) : preprocessor_map_input ;
242
+
243
+ const result_map = combine_sourcemaps (
244
+ filename ,
245
+ [
246
+ svelte_map as RawSourceMap ,
247
+ preprocessor_map
248
+ ]
249
+ ) as RawSourceMap ;
250
+
251
+ //Svelte expects a SourceMap which includes toUrl and toString. Instead of using the magic-string constructor that takes a decoded map
252
+ //we just tack on the extra properties.
253
+ Object . defineProperties ( result_map , {
222
254
toString : {
223
255
enumerable : false ,
224
256
value : function toString ( ) {
@@ -228,8 +260,10 @@ export function sourcemap_define_tostring_tourl(map) {
228
260
toUrl : {
229
261
enumerable : false ,
230
262
value : function toUrl ( ) {
231
- return 'data:application/json;charset=utf-8;base64,' + btoa ( this . toString ( ) ) ;
263
+ return 'data:application/json;charset=utf-8;base64,' + b64enc ( this . toString ( ) ) ;
232
264
}
233
265
}
234
266
} ) ;
267
+
268
+ return result_map as SourceMap ;
235
269
}
0 commit comments