UNPKG

3.6 kBJavaScriptView Raw
1const {SourceMapGenerator, SourceMapConsumer} = require('source-map');
2const {warn} = require('./log');
3
4if (typeof process === 'undefined' || process.browser) {
5 SourceMapConsumer.initialize({
6 "lib/mappings.wasm": "https://unpkg.com/source-map@0.7.3/lib/mappings.wasm"
7 });
8}
9
10const SLOW_TRANSFORM = 10000;
11
12module.exports = function (unit, ...transformers) {
13 const {packageName, moduleId, path} = unit;
14 const size = unit.contents.length;
15 let p = Promise.resolve(unit);
16 const start = (new Date()).getTime();
17 let previous = start;
18 const timers = [];
19
20 for (let i = 0, ii = transformers.length; i < ii; i++) {
21 p = p.then(unit => {
22
23 return Promise.resolve(transformers[i](unit))
24 .then(newUnit => {
25 const now = (new Date()).getTime();
26 const period = now - previous;
27 previous = now;
28 timers.push({name: transformers[i].name, period: period / 1000});
29 return mergeUnit(unit, newUnit)
30 })
31 });
32 }
33
34 p = p.then(newUnit => {
35 const total = (new Date()).getTime() - start;
36 if (total >= SLOW_TRANSFORM) {
37 warn('==================================');
38 warn(' Detected slow code transform');
39 if (packageName) warn(` Package : ${packageName}`);
40 warn(` Module : ${moduleId}`);
41 warn(` Path : ${path}`);
42 warn(` Size : ${size}`);
43 warn('----------------------------------');
44 timers.forEach(timer => {
45 if (timer.period >= 0.01) {
46 warn(` ${timer.name.padEnd(20)} ${timer.period.toFixed(3).padStart(7)}s`);
47 }
48 });
49 warn('----------------------------------');
50 warn(` Total time ${(total / 1000).toFixed(2).padStart(7)}s`);
51 warn('==================================');
52 }
53 return newUnit;
54 })
55
56 return p;
57};
58
59function mergeUnit(unit, newUnit) {
60 if (!newUnit) {
61 // bypass nil transform
62 return unit;
63 }
64
65 if (newUnit.parsed) {
66 // reuse parsed on unchanged code
67 return {...unit, parsed: newUnit.parsed};
68 }
69
70 // eslint-disable-next-line no-unused-vars
71 const {path, contents, sourceMap, moduleId, packageName, defined, deps, ...others} = newUnit;
72 const merged = {...unit, ...others};
73 delete merged.parsed;
74
75 if (typeof contents === 'string' && unit.contents !== contents) {
76 merged.contents = contents;
77 }
78
79 let p = Promise.resolve();
80 if (sourceMap) {
81 // merge source map
82 if (unit.sourceMap && unit.sourceMap.mappings !== '') {
83 p = Promise.all([
84 new SourceMapConsumer(sourceMap),
85 new SourceMapConsumer(unit.sourceMap)
86 ]).then(([newConsumer, oldConsumer]) => {
87 try {
88 const generator = SourceMapGenerator.fromSourceMap(newConsumer);
89 generator.applySourceMap(oldConsumer);
90 merged.sourceMap = JSON.parse(generator.toString());
91 } catch (err) {
92 warn('merging sourceMap failed for ' + unit.path);
93 warn(err);
94 merged.sourceMap = undefined;
95 }
96
97 newConsumer.destroy();
98 oldConsumer.destroy();
99 });
100 } else {
101 merged.sourceMap = sourceMap;
102 }
103 }
104
105 return p.then(() => {
106 const mergedDefined = mergeArray(unit.defined, defined);
107 const mergedDefs = mergeArray(unit.deps, deps);
108
109 if (mergedDefined) merged.defined = mergedDefined;
110 if (mergedDefs) merged.deps = mergedDefs;
111
112 return merged;
113 });
114}
115
116function mergeArray(arr1, arr2) {
117 if (!arr1) return arr2;
118 if (!arr2) return undefined;
119
120 const merged = [...arr1];
121 arr2.forEach(a => {
122 if (merged.indexOf(a) === -1) merged.push(a);
123 });
124
125 return merged;
126}