1 | var rollup = require('rollup');
|
2 | var traverseTree = require('./arithmetic').traverseTree;
|
3 | var getConditionModule = require('./trace').getConditionModule;
|
4 | var extend = require('./utils').extend;
|
5 | var getAlias = require('./utils').getAlias;
|
6 | var pluginBundleHook = require('./compile').pluginBundleHook;
|
7 |
|
8 | exports.rollupTree = function(loader, tree, entryPoints, traceOpts, compileOpts, outputOpts) {
|
9 | |
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 | entryPoints = entryPoints.concat([]);
|
23 |
|
24 | var optimizationPoints = [];
|
25 |
|
26 | var entryMap = {};
|
27 |
|
28 | function isESM(moduleName) {
|
29 | return tree[moduleName] && tree[moduleName].metadata && tree[moduleName].metadata.format == 'esm' && !tree[moduleName].metadata.originalSource;
|
30 | }
|
31 |
|
32 |
|
33 |
|
34 | Object.keys(tree).forEach(function(entryPoint) {
|
35 | traverseTree(tree, entryPoint, function(depName, parentName) {
|
36 |
|
37 | if (parentName && isESM(depName) && !isESM(parentName) && optimizationPoints.indexOf(depName) == -1)
|
38 | optimizationPoints.push(depName);
|
39 |
|
40 |
|
41 | if (entryMap[depName])
|
42 | return false;
|
43 |
|
44 | if (parentName)
|
45 | entryMap[depName] = entryPoint;
|
46 | }, traceOpts);
|
47 | });
|
48 |
|
49 |
|
50 | Object.keys(tree).forEach(function(entryPoint) {
|
51 | if (!entryMap[entryPoint] && tree[entryPoint] && entryPoints.indexOf(entryPoint) == -1)
|
52 | entryPoints.push(entryPoint);
|
53 | });
|
54 |
|
55 |
|
56 |
|
57 |
|
58 | var esmEntryPoints = 0;
|
59 | entryPoints.forEach(function(entryPoint) {
|
60 | if (tree[entryPoint].metadata && tree[entryPoint].metadata.format == 'esm')
|
61 | esmEntryPoints ++;
|
62 | });
|
63 |
|
64 | if (esmEntryPoints > 1 && esmEntryPoints == entryPoints.length) {
|
65 | var dummySource = 'export * from "' + entryPoints[0] + '";\n';
|
66 | var dummyDepMap = {};
|
67 |
|
68 | entryPoints.forEach(function(entryPoint) {
|
69 | dummyDepMap[entryPoint] = entryPoint;
|
70 |
|
71 | dummySource += 'import "' + entryPoint + '";';
|
72 | });
|
73 |
|
74 | tree['@dummy-entry-point'] = {
|
75 | name: '@dummy-entry-point',
|
76 | path: null,
|
77 | metadata: { format: 'esm' },
|
78 | deps: entryPoints,
|
79 | depMap: dummyDepMap,
|
80 | source: dummySource
|
81 | };
|
82 | entryPoints = ['@dummy-entry-point'];
|
83 | }
|
84 |
|
85 |
|
86 | entryPoints.forEach(function(entryPoint) {
|
87 | if (isESM(entryPoint) && optimizationPoints.indexOf(entryPoint) == -1)
|
88 | optimizationPoints.push(entryPoint);
|
89 | });
|
90 |
|
91 | |
92 |
|
93 |
|
94 |
|
95 |
|
96 |
|
97 |
|
98 |
|
99 |
|
100 |
|
101 |
|
102 |
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 |
|
110 | var optimizationParentMap = {};
|
111 |
|
112 |
|
113 |
|
114 | for (var i = 0; i < optimizationPoints.length; i++) {
|
115 | var entryPoint = optimizationPoints[i];
|
116 | traverseTree(tree, entryPoint, function(depName, parentName) {
|
117 |
|
118 |
|
119 | if (!isESM(depName))
|
120 | return false;
|
121 |
|
122 | if (depName == entryPoint)
|
123 | return;
|
124 |
|
125 |
|
126 | if (optimizationPoints.indexOf(depName) != -1)
|
127 | return false;
|
128 |
|
129 | if (!optimizationParentMap[depName]) {
|
130 | optimizationParentMap[depName] = entryPoint;
|
131 | return;
|
132 | }
|
133 |
|
134 |
|
135 | if (optimizationParentMap[depName] != entryPoint) {
|
136 | optimizationParentMap[depName] = undefined;
|
137 |
|
138 |
|
139 | optimizationPoints.push(depName);
|
140 | }
|
141 | }, traceOpts);
|
142 | }
|
143 |
|
144 | |
145 |
|
146 |
|
147 |
|
148 |
|
149 |
|
150 |
|
151 |
|
152 |
|
153 |
|
154 |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 | var inlinedModules = [];
|
160 | var optimizationGraphExternals = {};
|
161 |
|
162 | optimizationPoints.forEach(function(entryPoint) {
|
163 |
|
164 |
|
165 | var externals = [];
|
166 |
|
167 |
|
168 |
|
169 | traverseTree(tree, entryPoint, function(depName, parentName) {
|
170 | if (!isESM(depName) || (depName != entryPoint && optimizationPoints.indexOf(depName) != -1))
|
171 | return false;
|
172 |
|
173 | var depLoad = tree[depName];
|
174 | depLoad.deps && depLoad.deps.forEach(function(depName) {
|
175 | depName = depLoad.depMap[depName];
|
176 | if (depName == entryPoint)
|
177 | return;
|
178 |
|
179 |
|
180 | if (!isESM(depName) || optimizationPoints.indexOf(depName) != -1) {
|
181 | if (externals.indexOf(depName) == -1)
|
182 | externals.push(depName);
|
183 | }
|
184 | else {
|
185 | if (inlinedModules.indexOf(depName) == -1)
|
186 | inlinedModules.push(depName);
|
187 | }
|
188 | }, traceOpts);
|
189 | });
|
190 |
|
191 | optimizationGraphExternals[entryPoint] = externals;
|
192 | });
|
193 |
|
194 |
|
195 | var rolledUpTree = {};
|
196 | Object.keys(tree).forEach(function(moduleName) {
|
197 | if (inlinedModules.indexOf(moduleName) == -1)
|
198 | rolledUpTree[moduleName] = tree[moduleName];
|
199 | });
|
200 |
|
201 |
|
202 | var inlineMap = {};
|
203 | inlinedModules.forEach(function(moduleName) {
|
204 | var optimizationParent = optimizationParentMap[moduleName];
|
205 | (inlineMap[optimizationParent] = inlineMap[optimizationParent] || []).push(moduleName);
|
206 | });
|
207 |
|
208 |
|
209 | var fullTreeRollup = entryPoints.length == 1 && optimizationPoints.length == 1 && Object.keys(optimizationGraphExternals).length == 1;
|
210 |
|
211 | return Promise.all(Object.keys(optimizationGraphExternals).map(function(entryPoint) {
|
212 | var externals = optimizationGraphExternals[entryPoint];
|
213 | var loadList = [];
|
214 |
|
215 |
|
216 |
|
217 | if (fullTreeRollup)
|
218 | externals.forEach(function(external) {
|
219 | if (external.substr(0, 5) == '@node' || tree[external])
|
220 | fullTreeRollup = false;
|
221 | });
|
222 |
|
223 | var aliasedExternals = externals.map(function(external) {
|
224 | var alias = getAlias(loader, external) || externals;
|
225 | if (alias.indexOf('#:') != -1)
|
226 | alias = alias.replace('#:', '/');
|
227 | return alias;
|
228 | });
|
229 |
|
230 | return rollup.rollup({
|
231 | entry: entryPoint,
|
232 | external: aliasedExternals,
|
233 | plugins: [{
|
234 | resolveId: function(id, importer, options) {
|
235 | var resolved = importer ? tree[importer].depMap[id] : id;
|
236 | var externalIndex = externals.indexOf(resolved);
|
237 | if (externalIndex != -1)
|
238 | return aliasedExternals[externalIndex];
|
239 | return resolved;
|
240 | },
|
241 | load: function(id, options) {
|
242 | if (loadList.indexOf(tree[id]) == -1)
|
243 | loadList.push(tree[id]);
|
244 | loadList.push(tree[id]);
|
245 | return {
|
246 | code: tree[id].metadata.originalSource || tree[id].source,
|
247 | map: tree[id].metadata.sourceMap
|
248 | };
|
249 | }
|
250 | }],
|
251 | onwarn: function(message) {}
|
252 | })
|
253 | .then(function(bundle) {
|
254 | var entryPointLoad = tree[entryPoint];
|
255 |
|
256 | var defaultExport = compileOpts.defaultExport;
|
257 | if (entryPointLoad.metadata.format == 'register')
|
258 | throw new Error('Assertion failed: internal format should be "system" not "register".');
|
259 |
|
260 | if (entryPointLoad.metadata.format != 'esm' && entryPointLoad.metadata.format != 'system')
|
261 | defaultExport = true;
|
262 |
|
263 | var generateOptions = {
|
264 | sourceMap: !!compileOpts.sourceMaps,
|
265 | exports: defaultExport ? 'default' : 'named',
|
266 | dest: 'output.js'
|
267 | };
|
268 |
|
269 |
|
270 | if (fullTreeRollup) {
|
271 | generateOptions.format = compileOpts.format;
|
272 | if (generateOptions.format == 'global')
|
273 | generateOptions.format = 'iife';
|
274 | if (generateOptions.format == 'esm')
|
275 | generateOptions.format = 'es6';
|
276 |
|
277 | if ((generateOptions.format == 'iife' || generateOptions.format == 'umd') &&
|
278 | !compileOpts.globalName)
|
279 | throw new Error('The globalName option must be set for full-tree rollup global and UMD builds.');
|
280 |
|
281 | if (compileOpts.globalName)
|
282 | generateOptions.moduleName = compileOpts.globalName;
|
283 |
|
284 | if (compileOpts.globalDeps)
|
285 | generateOptions.globals = compileOpts.globalDeps;
|
286 | }
|
287 |
|
288 | var output = bundle.generate(generateOptions);
|
289 |
|
290 |
|
291 | if (output.map) {
|
292 | output.map.sources = output.map.sources.map(function(name) {
|
293 | name = loader.getCanonicalName(loader.decanonicalize(name));
|
294 | return tree[name] && tree[name].path || loader.decanonicalize(name);
|
295 | });
|
296 | }
|
297 |
|
298 | if (fullTreeRollup)
|
299 | return {
|
300 | source: output.code,
|
301 | sourceMap: output.map
|
302 | };
|
303 |
|
304 |
|
305 | var curInlined = inlineMap[entryPoint] || [];
|
306 |
|
307 |
|
308 |
|
309 | var inlinedDepMap = {};
|
310 | aliasedExternals.forEach(function(dep, index) {
|
311 | inlinedDepMap[dep] = externals[index];
|
312 | });
|
313 |
|
314 | rolledUpTree[entryPoint] = extend(extend({}, entryPointLoad), {
|
315 | deps: aliasedExternals,
|
316 | depMap: inlinedDepMap,
|
317 | metadata: extend(extend({}, entryPointLoad.metadata), {
|
318 | originalSource: undefined,
|
319 | sourceMap: output.map
|
320 | }),
|
321 | source: output.code,
|
322 | compactedLoads: loadList
|
323 | });
|
324 | });
|
325 | }))
|
326 | .then(function(outputs) {
|
327 | if (fullTreeRollup) {
|
328 |
|
329 | return pluginBundleHook(loader, Object.keys(tree).map(function(name) {
|
330 | return tree[name];
|
331 | }).filter(function(load) {
|
332 | return load;
|
333 | }), compileOpts, outputOpts)
|
334 | .then(function(pluginResult) {
|
335 | return {
|
336 | outputs: outputs.concat(pluginResult.outputs),
|
337 | assetList: pluginResult.assetList
|
338 | };
|
339 | });
|
340 | }
|
341 |
|
342 | return {
|
343 | tree: rolledUpTree,
|
344 | inlineMap: inlineMap
|
345 | };
|
346 | });
|
347 | };
|