@@ -17,7 +17,7 @@ import {
17
17
import { createHash } from 'crypto' ;
18
18
import * as fs from 'fs' ;
19
19
import * as path from 'path' ;
20
- import { RawSourceMap , SourceMapConsumer , SourceMapGenerator } from 'source-map' ;
20
+ import { RawSourceMap } from 'source-map' ;
21
21
import { minify } from 'terser' ;
22
22
import * as v8 from 'v8' ;
23
23
import { SourceMapSource } from 'webpack-sources' ;
@@ -108,23 +108,19 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
108
108
const filename = path . basename ( options . filename ) ;
109
109
const downlevelFilename = filename . replace ( / \- e s 2 0 \d { 2 } / , '-es5' ) ;
110
110
const downlevel = ! options . optimizeOnly ;
111
-
112
- // if code size is larger than 500kB, manually handle sourcemaps with newer source-map package.
113
- // babel currently uses an older version that still supports sync calls
114
- const codeSize = Buffer . byteLength ( options . code ) ;
115
- const mapSize = options . map ? Buffer . byteLength ( options . map ) : 0 ;
116
- const manualSourceMaps = codeSize >= 500 * 1024 || mapSize >= 500 * 1024 ;
117
111
const sourceCode = options . code ;
118
- const sourceMap = options . map ? JSON . parse ( options . map ) : false ;
112
+ const sourceMap = options . map ? JSON . parse ( options . map ) : undefined ;
119
113
120
114
let downlevelCode ;
121
115
let downlevelMap ;
122
116
if ( downlevel ) {
123
117
// Downlevel the bundle
124
118
const transformResult = await transformAsync ( sourceCode , {
125
- filename : options . filename ,
119
+ filename,
126
120
// using false ensures that babel will NOT search and process sourcemap comments (large memory usage)
127
- inputSourceMap : manualSourceMaps ? false : sourceMap ,
121
+ // The types do not include the false option even though it is valid
122
+ // tslint:disable-next-line: no-any
123
+ inputSourceMap : false as any ,
128
124
babelrc : false ,
129
125
presets : [ [
130
126
require . resolve ( '@babel/preset-env' ) ,
@@ -147,11 +143,14 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
147
143
}
148
144
downlevelCode = transformResult . code ;
149
145
150
- if ( manualSourceMaps && sourceMap && transformResult . map ) {
151
- downlevelMap = await mergeSourceMapsFast ( sourceMap , transformResult . map ) ;
152
- } else {
153
- // undefined is needed here to normalize the property type
154
- downlevelMap = transformResult . map || undefined ;
146
+ if ( sourceMap && transformResult . map ) {
147
+ downlevelMap = mergeSourceMaps (
148
+ sourceCode ,
149
+ sourceMap ,
150
+ downlevelCode ,
151
+ transformResult . map ,
152
+ filename ,
153
+ ) ;
155
154
}
156
155
}
157
156
@@ -175,15 +174,14 @@ export async function process(options: ProcessBundleOptions): Promise<ProcessBun
175
174
return result ;
176
175
}
177
176
177
+ // SourceMapSource produces high-quality sourcemaps
178
178
function mergeSourceMaps (
179
179
inputCode : string ,
180
180
inputSourceMap : RawSourceMap ,
181
181
resultCode : string ,
182
182
resultSourceMap : RawSourceMap ,
183
183
filename : string ,
184
184
) : RawSourceMap {
185
- // More accurate but significantly more costly
186
-
187
185
// The last argument is not yet in the typings
188
186
// tslint:disable-next-line: no-any
189
187
return new ( SourceMapSource as any ) (
@@ -196,58 +194,6 @@ function mergeSourceMaps(
196
194
) . map ( ) ;
197
195
}
198
196
199
- async function mergeSourceMapsFast ( first : RawSourceMap , second : RawSourceMap ) {
200
- const sourceRoot = first . sourceRoot ;
201
- const generator = new SourceMapGenerator ( ) ;
202
-
203
- // sourcemap package adds the sourceRoot to all position source paths if not removed
204
- delete first . sourceRoot ;
205
-
206
- await SourceMapConsumer . with ( first , null , originalConsumer => {
207
- return SourceMapConsumer . with ( second , null , newConsumer => {
208
- newConsumer . eachMapping ( mapping => {
209
- if ( mapping . originalLine === null ) {
210
- return ;
211
- }
212
- const originalPosition = originalConsumer . originalPositionFor ( {
213
- line : mapping . originalLine ,
214
- column : mapping . originalColumn ,
215
- } ) ;
216
- if (
217
- originalPosition . line === null ||
218
- originalPosition . column === null ||
219
- originalPosition . source === null
220
- ) {
221
- return ;
222
- }
223
- generator . addMapping ( {
224
- generated : {
225
- line : mapping . generatedLine ,
226
- column : mapping . generatedColumn ,
227
- } ,
228
- name : originalPosition . name || undefined ,
229
- original : {
230
- line : originalPosition . line ,
231
- column : originalPosition . column ,
232
- } ,
233
- source : originalPosition . source ,
234
- } ) ;
235
- } ) ;
236
- } ) ;
237
- } ) ;
238
-
239
- const map = generator . toJSON ( ) ;
240
- map . file = second . file ;
241
- map . sourceRoot = sourceRoot ;
242
-
243
- // Put the sourceRoot back
244
- if ( sourceRoot ) {
245
- first . sourceRoot = sourceRoot ;
246
- }
247
-
248
- return map ;
249
- }
250
-
251
197
async function processBundle (
252
198
options : Omit < ProcessBundleOptions , 'map' > & { isOriginal : boolean ; map ?: string | RawSourceMap } ,
253
199
) : Promise < ProcessBundleFile > {
@@ -270,6 +216,10 @@ async function processBundle(
270
216
map : RawSourceMap | undefined ,
271
217
} ;
272
218
219
+ if ( rawMap ) {
220
+ rawMap . file = filename ;
221
+ }
222
+
273
223
if ( optimize ) {
274
224
result = terserMangle ( code , {
275
225
filename,
@@ -278,10 +228,6 @@ async function processBundle(
278
228
ecma : isOriginal ? 6 : 5 ,
279
229
} ) ;
280
230
} else {
281
- if ( rawMap ) {
282
- rawMap . file = filename ;
283
- }
284
-
285
231
result = {
286
232
map : rawMap ,
287
233
code,
@@ -328,7 +274,7 @@ function terserMangle(
328
274
// estree -> terser is already supported; need babel -> estree/terser
329
275
330
276
// Mangle downlevel code
331
- const minifyOutput = minify ( code , {
277
+ const minifyOutput = minify ( options . filename ? { [ options . filename ] : code } : code , {
332
278
compress : options . compress || false ,
333
279
ecma : options . ecma || 5 ,
334
280
mangle : ! manglingDisabled ,
@@ -340,10 +286,6 @@ function terserMangle(
340
286
sourceMap :
341
287
! ! options . map &&
342
288
( {
343
- filename : options . filename ,
344
- // terser uses an old version of the sourcemap typings
345
- // tslint:disable-next-line: no-any
346
- content : options . map as any ,
347
289
asObject : true ,
348
290
// typings don't include asObject option
349
291
// tslint:disable-next-line: no-any
@@ -355,7 +297,20 @@ function terserMangle(
355
297
}
356
298
357
299
// tslint:disable-next-line: no-non-null-assertion
358
- return { code : minifyOutput . code ! , map : minifyOutput . map as RawSourceMap | undefined } ;
300
+ const outputCode = minifyOutput . code ! ;
301
+
302
+ let outputMap ;
303
+ if ( options . map && minifyOutput . map ) {
304
+ outputMap = mergeSourceMaps (
305
+ code ,
306
+ options . map ,
307
+ outputCode ,
308
+ minifyOutput . map as unknown as RawSourceMap ,
309
+ options . filename || '0' ,
310
+ ) ;
311
+ }
312
+
313
+ return { code : outputCode , map : outputMap } ;
359
314
}
360
315
361
316
function createFileEntry (
@@ -493,7 +448,8 @@ export async function inlineLocales(options: InlineOptions) {
493
448
return inlineCopyOnly ( options ) ;
494
449
}
495
450
496
- let content = new MagicString ( options . code ) ;
451
+ // tslint:disable-next-line: no-any
452
+ let content = new MagicString ( options . code , { filename : options . filename } as any ) ;
497
453
const inputMap = options . map && ( JSON . parse ( options . map ) as RawSourceMap ) ;
498
454
let contentClone ;
499
455
for ( const locale of i18n . inlineLocales ) {
0 commit comments