1 | const {SourceMapGenerator, SourceMapConsumer} = require('source-map');
|
2 | const {warn} = require('./log');
|
3 |
|
4 | if (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 |
|
10 | const SLOW_TRANSFORM = 10000;
|
11 |
|
12 | module.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 |
|
59 | function mergeUnit(unit, newUnit) {
|
60 | if (!newUnit) {
|
61 |
|
62 | return unit;
|
63 | }
|
64 |
|
65 |
|
66 | const {path, contents, sourceMap, moduleId, packageName, defined, deps, ...others} = newUnit;
|
67 | const merged = {...unit, ...others};
|
68 |
|
69 | if (typeof contents === 'string' && unit.contents !== contents) {
|
70 | merged.contents = contents;
|
71 | }
|
72 |
|
73 | let p = Promise.resolve();
|
74 | if (sourceMap) {
|
75 |
|
76 | if (unit.sourceMap && unit.sourceMap.mappings !== '') {
|
77 | p = Promise.all([
|
78 | new SourceMapConsumer(sourceMap),
|
79 | new SourceMapConsumer(unit.sourceMap)
|
80 | ]).then(([newConsumer, oldConsumer]) => {
|
81 | try {
|
82 | const generator = SourceMapGenerator.fromSourceMap(newConsumer);
|
83 | generator.applySourceMap(oldConsumer);
|
84 | merged.sourceMap = JSON.parse(generator.toString());
|
85 | } catch (err) {
|
86 | warn('merging sourceMap failed for ' + unit.path);
|
87 | warn(err);
|
88 | merged.sourceMap = undefined;
|
89 | }
|
90 |
|
91 | newConsumer.destroy();
|
92 | oldConsumer.destroy();
|
93 | });
|
94 | } else {
|
95 | merged.sourceMap = sourceMap;
|
96 | }
|
97 | }
|
98 |
|
99 | return p.then(() => {
|
100 | const mergedDefined = mergeArray(unit.defined, defined);
|
101 | const mergedDefs = mergeArray(unit.deps, deps);
|
102 |
|
103 | if (mergedDefined) merged.defined = mergedDefined;
|
104 | if (mergedDefs) merged.deps = mergedDefs;
|
105 |
|
106 | return merged;
|
107 | });
|
108 | }
|
109 |
|
110 | function mergeArray(arr1, arr2) {
|
111 | if (!arr1) return arr2;
|
112 | if (!arr2) return undefined;
|
113 |
|
114 | const merged = [...arr1];
|
115 | arr2.forEach(a => {
|
116 | if (merged.indexOf(a) === -1) merged.push(a);
|
117 | });
|
118 |
|
119 | return merged;
|
120 | }
|