Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(664)

Side by Side Diff: third_party/WebKit/Source/devtools/scripts/extract_module.js

Issue 2608043002: DevTools: extract modules (with extensions) (Closed)
Patch Set: fixes Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 'use strict';
5 const fs = require('fs');
6 const path = require('path');
7
8 const utils = require('./utils');
9
10 const FRONTEND_PATH = path.resolve(__dirname, '..', 'front_end');
11 const BUILD_GN_PATH = path.resolve(__dirname, '..', 'BUILD.gn');
12
13 const APPLICATION_DESCRIPTORS = [
14 'inspector.json',
15 'unit_test_runner.json',
16 ];
17
18 // Replace based on specified transformation
19
20 const MODULES_TO_REMOVE = ['components_lazy', 'ui_lazy'];
21
22 const JS_FILES_MAPPING = [
23 {file: 'components_lazy/CookiesTable.js', new: 'cookie_table'},
24 {file: 'ui/BezierEditor.js', new: 'inline_editor'},
25 {file: 'ui/BezierUI.js', new: 'inline_editor'},
26 {file: 'ui/ColorSwatch.js', new: 'inline_editor'},
27 {file: 'ui/CSSShadowEditor.js', new: 'inline_editor'},
28 {file: 'ui/SwatchPopoverHelper.js', new: 'inline_editor'},
29 {file: 'components/Spectrum.js', new: 'spectrum'},
30 {file: 'components/DataSaverInfobar.js', existing: 'main'},
31
32 // Cannot extract dom_ui because of cyclic dependency with components
33 // {file: 'components/DOMPresentationUtils.js', new: 'dom_ui'},
34 {file: 'components/EventListenersUtils.js', new: 'js_ui'},
35 {file: 'components/EventListenersView.js', new: 'js_ui'},
36 {file: 'components/ExecutionContextSelector.js', existing: 'main'},
37 {file: 'components_lazy/FilmStripModel.js', existing: 'sdk'},
38
39 // NOTE: switched from network -> components b/c timeline depends on a class
40 {file: 'components_lazy/FilmStripView.js', existing: 'components'},
41 {file: 'components_lazy/GCActionDelegate.js', existing: 'main'},
42 {file: 'components_lazy/LineLevelProfile.js', new: 'perf_ui'},
43 {file: 'components/RequestAppBannerActionDelegate.js', existing: 'main'},
44 {file: 'components/ShortcutsScreen.js', existing: 'ui'},
45 {file: 'components/Reload.js', existing: 'main'},
46 {file: 'ui_lazy/FilteredListWidget.js', new: 'quick_open'},
47 {file: 'ui_lazy/CommandMenu.js', new: 'quick_open'},
48 {file: 'ui_lazy/DataGrid.js', new: 'data_grid'},
49 {file: 'ui_lazy/ViewportDataGrid.js', new: 'data_grid'},
50 {file: 'ui_lazy/SortableDataGrid.js', new: 'data_grid'},
51 {file: 'ui_lazy/ShowMoreDataGridNode.js', new: 'data_grid'},
52 {file: 'ui_lazy/ChartViewport.js', new: 'perf_ui'},
53 {file: 'ui_lazy/FlameChart.js', new: 'perf_ui'},
54 {file: 'ui_lazy/OverviewGrid.js', new: 'perf_ui'},
55 {file: 'ui_lazy/PieChart.js', new: 'perf_ui'},
56 {file: 'ui_lazy/TimelineGrid.js', new: 'perf_ui'},
57 {file: 'ui_lazy/TimelineOverviewPane.js', new: 'perf_ui'}
58 ];
59
60 const MODULE_MAPPING = {
61 cookie_table: {
62 dependencies: ['ui', 'sdk', 'data_grid'],
63 dependents: ['resources', 'network'],
64 applications: ['inspector.json'],
65 autostart: false,
66 },
67 inline_editor: {
68 dependencies: ['ui'],
69 dependents: ['sources', 'elements', 'resources'],
70 applications: ['inspector.json', 'unit_test_runner.json'],
71 autostart: false,
72 },
73 spectrum: {
74 dependencies: ['ui', 'sdk'],
75 dependents: ['sources', 'elements'],
76 applications: ['inspector.json'],
77 autostart: false,
78 },
79 // Cannot extract dom_ui because of cyclic dependency with components
80 // dom_ui: {
81 // dependencies: ['ui', 'sdk', 'components'],
82 // dependents: ['animation', 'console', 'elements', 'network', 'timeline', ' layer_viewer', 'components'],
83 // applications: ['inspector.json'],
84 // autostart: true,
85 // },
86 js_ui: {
87 dependencies: ['ui', 'sdk', 'components'],
88 dependents: ['elements', 'sources'],
89 applications: ['inspector.json'],
90 autostart: true,
91 },
92 perf_ui: {
93 dependencies: ['ui', 'sdk', 'bindings', 'sources', 'text_editor'],
94 dependents: ['network', 'timeline', 'profiler', 'layer_viewer'],
95 applications: ['inspector.json'],
96 autostart: false,
97 },
98 quick_open: {
99 dependencies: ['ui', 'diff'],
100 dependents: ['sources'],
101 applications: ['inspector.json', 'unit_test_runner.json'],
102 autostart: false,
103 },
104 data_grid: {
105 dependencies: ['ui'],
106 dependents: ['network', 'profiler', 'resources', 'console', 'timeline'],
107 applications: ['inspector.json', 'unit_test_runner.json'],
108 autostart: false,
109 },
110 };
111
112 const NEW_DEPENDENCIES_BY_EXISTING_MODULES = {
113 sources: ['main'],
114 resources: ['components'],
115 };
116
117 const DEPENDENCIES_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
118 acc[module] = MODULE_MAPPING[module].dependencies;
119 return acc;
120 }, {});
121
122 const APPLICATIONS_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
123 acc[module] = MODULE_MAPPING[module].applications;
124 return acc;
125 }, {});
126
127 const DEPENDENTS_BY_MODULE = Object.keys(MODULE_MAPPING).reduce((acc, module) => {
128 acc[module] = MODULE_MAPPING[module].dependents;
129 return acc;
130 }, {});
131
132 function extractModule() {
133 const modules = new Set();
134 for (let fileObj of JS_FILES_MAPPING) {
135 let moduleName = fileObj.file.split('/')[0];
136 modules.add(moduleName);
137 }
138 const newModuleSet = JS_FILES_MAPPING.reduce((acc, file) => file.new ? acc.add (file.new) : acc, new Set());
139 const targetToOriginalFilesMap = JS_FILES_MAPPING.reduce((acc, f) => {
140 let components = f.file.split('/');
141 components[0] = f.new || f.existing;
142 acc.set(components.join('/'), f.file);
143 return acc;
144 }, new Map());
145
146 const cssFilesMapping = findCSSFiles();
147 const identifiersByFile = calculateIdentifiers();
148 const identifierMap = mapIdentifiers(identifiersByFile, cssFilesMapping);
149 const extensionMap = removeFromExistingModuleDescriptors(modules, identifierMa p, cssFilesMapping);
150 moveFiles(cssFilesMapping);
151 createNewModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFile, t argetToOriginalFilesMap);
152 updateExistingModuleDescriptors(extensionMap, cssFilesMapping, identifiersByFi le, targetToOriginalFilesMap);
153 addDependenciesToDescriptors();
154 renameIdentifiers(identifierMap);
155 updateBuildGNFile(cssFilesMapping, newModuleSet);
156 for (let descriptor of APPLICATION_DESCRIPTORS)
157 updateApplicationDescriptor(descriptor, newModuleSet);
158
159 // one-off
160 utils.removeRecursive(path.resolve(FRONTEND_PATH, 'components_lazy'));
161 utils.removeRecursive(path.resolve(FRONTEND_PATH, 'ui_lazy'));
162 }
163
164 String.prototype.replaceAll = function(search, replacement) {
165 let target = this;
166 return target.replace(new RegExp('\\b' + search + '\\b', 'g'), replacement);
167 };
168
169 Set.prototype.union = function(setB) {
170 let union = new Set(this);
171 for (let elem of setB)
172 union.add(elem);
173
174 return union;
175 };
176
177 function mapModuleToNamespace(module) {
178 const specialCases = require(path.resolve(__dirname, 'module_to_namespaces.jso n'));
179 return specialCases[module] || toCamelCase(module);
180
181 function toCamelCase(module) {
182 return module.split('_').map(a => a.substring(0, 1).toUpperCase() + a.substr ing(1)).join('');
183 }
184 }
185
186 function findCSSFiles() {
187 let cssFilesMapping = new Map();
188 for (let fileObj of JS_FILES_MAPPING)
189 cssFilesMapping.set(fileObj.file, scrapeCSSFile(fileObj.file));
190
191
192 function scrapeCSSFile(filePath) {
193 let cssFiles = new Set();
194 const fullPath = path.resolve(FRONTEND_PATH, filePath);
195 let content = fs.readFileSync(fullPath).toString();
196 let lines = content.split('\n');
197 for (let line of lines) {
198 let match = line.match(/'(.+\.css)'/);
199 if (!match)
200 continue;
201 let matchPath = match[1];
202 cssFiles.add(path.basename(path.resolve(FRONTEND_PATH, matchPath)));
203 }
204 if (filePath.includes('EventListenersView.js'))
205 cssFiles.delete('objectValue.css');
206 return cssFiles;
207 }
208
209 return cssFilesMapping;
210 }
211
212 function calculateIdentifiers() {
213 const identifiersByFile = new Map();
214 for (let fileObj of JS_FILES_MAPPING) {
215 const fullPath = path.resolve(FRONTEND_PATH, fileObj.file);
216 let content = fs.readFileSync(fullPath).toString();
217 identifiersByFile.set(fileObj.file, scrapeIdentifiers(content));
218 }
219 return identifiersByFile;
220
221 function scrapeIdentifiers(content) {
222 let identifiers = [];
223 let lines = content.split('\n');
224 for (let line of lines) {
225 let match = line.match(new RegExp(`^([a-z_A-Z0-9\.]+)\\s=`)) || line.match (new RegExp(`^([a-z_A-Z0-9\.]+);`));
226 if (!match)
227 continue;
228 let name = match[1];
229 identifiers.push(name);
230 }
231 return identifiers;
232 }
233 }
234
235 function moveFiles(cssFilesMapping) {
236 for (let fileObj of JS_FILES_MAPPING) {
237 let sourceFilePath = path.resolve(FRONTEND_PATH, fileObj.file);
238 let targetFilePath = getMappedFilePath(fileObj);
239 let moduleDir = path.resolve(targetFilePath, '..');
240 if (!fs.existsSync(moduleDir))
241 fs.mkdirSync(moduleDir);
242
243 move(sourceFilePath, targetFilePath);
244 if (cssFilesMapping.has(fileObj.file)) {
245 cssFilesMapping.get(fileObj.file).forEach((file) => {
246 let module = fileObj.new || fileObj.existing;
247 move(path.resolve(FRONTEND_PATH, fileObj.file.split('/')[0], file), path .resolve(FRONTEND_PATH, module, file));
248 });
249 }
250 }
251
252 function move(sourceFilePath, targetFilePath) {
253 try {
254 fs.writeFileSync(targetFilePath, fs.readFileSync(sourceFilePath));
255 fs.unlinkSync(sourceFilePath);
256 } catch (err) {
257 console.log(`error moving ${sourceFilePath} -> ${targetFilePath}`);
258 }
259 }
260
261 function getMappedFilePath(fileObj) {
262 let components = fileObj.file.split('/');
263 components[0] = fileObj.existing || fileObj.new;
264 return path.resolve(FRONTEND_PATH, components.join('/'));
265 }
266 }
267
268 function updateBuildGNFile(cssFilesMapping, newModuleSet) {
269 let content = fs.readFileSync(BUILD_GN_PATH).toString();
270 let newSourcesToAdd = [];
271 let partialPathMapping = calculatePartialPathMapping();
272 for (let module of MODULES_TO_REMOVE) {
273 partialPathMapping.set(`"front_end/${module}/module.json",\n`, '');
274 partialPathMapping.set(`"$resources_out_dir/${module}/${module}_module.js",\ n`, '');
275 }
276 const newNonAutostartModules = [...newModuleSet]
277 .filter(module => !MODULE_MAPPING[module].a utostart)
278 .map(module => `"$resources_out_dir/${modul e}/${module}_module.js",`);
279
280 let newContent = addContentToLinesInSortedOrder({
281 content,
282 startLine: '# this contains non-autostart non-remote modules only.',
283 endLine: ']',
284 linesToInsert: newNonAutostartModules,
285 });
286
287 for (let pair of partialPathMapping.entries())
288 newContent = newContent.replace(pair[0], pair[1]);
289
290 newContent = addContentToLinesInSortedOrder({
291 content: newContent,
292 startLine: 'all_devtools_files = [',
293 endLine: ']',
294 linesToInsert: newSourcesToAdd,
295 });
296
297 fs.writeFileSync(BUILD_GN_PATH, newContent);
298
299 function calculatePartialPathMapping() {
300 let partialPathMapping = new Map();
301 for (let fileObj of JS_FILES_MAPPING) {
302 let components = fileObj.file.split('/');
303 let sourceModule = components[0];
304 let targetModule = fileObj.existing || fileObj.new;
305 components[0] = targetModule;
306 partialPathMapping.set(`"front_end/${fileObj.file}",\n`, '');
307 newSourcesToAdd.push(`"front_end/${components.join('/')}",`);
308 if (cssFilesMapping.has(fileObj.file)) {
309 for (let cssFile of cssFilesMapping.get(fileObj.file)) {
310 partialPathMapping.set(`"front_end/${sourceModule}/${cssFile}",\n`, '' );
311 newSourcesToAdd.push(`"front_end/${targetModule}/${cssFile}",`);
312 }
313 }
314 }
315 return partialPathMapping;
316 }
317
318 function top(array) {
319 return array[array.length - 1];
320 }
321
322 function addContentToLinesInSortedOrder({content, startLine, endLine, linesToI nsert}) {
323 let lines = content.split('\n');
324 let seenStartLine = false;
325 let contentStack = linesToInsert.sort((a, b) => a.toLowerCase().localeCompar e(b.toLowerCase())).reverse();
326 for (var i = 0; i < lines.length; i++) {
327 let line = lines[i].trim();
328 let nextLine = lines[i + 1].trim();
329 if (line === startLine)
330 seenStartLine = true;
331
332 if (line === endLine && seenStartLine)
333 break;
334
335 if (!seenStartLine)
336 continue;
337
338 const nextContent = top(contentStack) ? top(contentStack).toLowerCase() : '';
339 if ((line === startLine || nextContent > line.toLowerCase()) &&
340 (nextLine === endLine || nextContent < nextLine.toLowerCase()))
341 lines.splice(i + 1, 0, contentStack.pop());
342 }
343 if (contentStack.length)
344 lines.splice(i, 0, ...contentStack);
345 return lines.join('\n');
346 }
347 }
348
349 function mapIdentifiers(identifiersByFile, cssFilesMapping) {
350 const filesToTargetModule = new Map();
351 for (let fileObj of JS_FILES_MAPPING)
352 filesToTargetModule.set(fileObj.file, fileObj.existing || fileObj.new);
353
354
355 const map = new Map();
356 for (let [file, identifiers] of identifiersByFile) {
357 let targetModule = filesToTargetModule.get(file);
358 for (let identifier of identifiers) {
359 let components = identifier.split('.');
360 components[0] = mapModuleToNamespace(targetModule);
361 let newIdentifier = components.join('.');
362 map.set(identifier, newIdentifier);
363 }
364 }
365 // one-off fix
366 map.set('SDK.EventListener.frameworkEventListeners', 'JS_UI.frameworkEventList eners');
367 for (let [jsFile, cssFiles] of cssFilesMapping) {
368 let fileObj = JS_FILES_MAPPING.filter(f => f.file === jsFile)[0];
369 let sourceModule = fileObj.file.split('/')[0];
370 let targetModule = fileObj.existing || fileObj.new;
371 for (let cssFile of cssFiles) {
372 let key = `${sourceModule}/${cssFile}`;
373 let value = `${targetModule}/${cssFile}`;
374 map.set(key, value);
375 }
376 }
377 return map;
378 }
379
380 function renameIdentifiers(identifierMap) {
381 walkSync('front_end', write, true);
382
383 walkSync('../../LayoutTests/http/tests/inspector', write, false);
384 walkSync('../../LayoutTests/http/tests/inspector-enabled', write, false);
385 walkSync('../../LayoutTests/http/tests/inspector-protocol', write, false);
386 walkSync('../../LayoutTests/http/tests/inspector-unit', write, false);
387 walkSync('../../LayoutTests/inspector', write, false);
388 walkSync('../../LayoutTests/inspector-enabled', write, false);
389 walkSync('../../LayoutTests/inspector-protocol', write, false);
390
391 function walkSync(currentDirPath, process, json) {
392 fs.readdirSync(currentDirPath).forEach(function(name) {
393 let filePath = path.join(currentDirPath, name);
394 let stat = fs.statSync(filePath);
395 if (stat.isFile() && (filePath.endsWith('.js') || filePath.endsWith('.html ') || filePath.endsWith('.xhtml') ||
396 filePath.endsWith('-expected.txt') || (json && fileP ath.endsWith('.json')))) {
397 if (filePath.includes('ExtensionAPI.js'))
398 return;
399 if (filePath.includes('externs.js'))
400 return;
401 if (filePath.includes('eslint') || filePath.includes('lighthouse-backgro und.js') || filePath.includes('/cm/') ||
402 filePath.includes('/xterm.js/') || filePath.includes('/acorn/') || f ilePath.includes('/gonzales-scss'))
403 return;
404 if (filePath.includes('/cm_modes/') && !filePath.includes('DefaultCodeMi rror') &&
405 !filePath.includes('module.json'))
406 return;
407 process(filePath);
408 } else if (stat.isDirectory()) {
409 walkSync(filePath, process, json);
410 }
411 });
412 }
413
414 function write(filePath) {
415 let content = fs.readFileSync(filePath).toString();
416 let newContent = content;
417 for (let key of identifierMap.keys()) {
418 let originalIdentifier = key;
419 let newIdentifier = identifierMap.get(key);
420 newContent = newContent.replaceAll(originalIdentifier, newIdentifier);
421 }
422 if (filePath.includes('LayoutTests/http/tests/inspector-unit/filtered-item-s election-dialog-filtering.js'))
423 newContent = newContent.replaceAll('ui_lazy', 'quick_open');
424 if (filePath.includes('LayoutTests/inspector/components/cookies-table.html') )
425 newContent = newContent.replaceAll('components_lazy', 'cookie_table');
426 if (filePath.includes('LayoutTests/inspector/components/datagrid-autosize.ht ml'))
427 newContent = newContent.replaceAll('ui_lazy', 'data_grid');
428 if (filePath.includes('LayoutTests/inspector/components/datagrid-test.js'))
429 newContent = newContent.replaceAll('ui_lazy', 'data_grid');
430
431 if (content !== newContent)
432 fs.writeFileSync(filePath, newContent);
433 }
434 }
435
436 function removeFromExistingModuleDescriptors(modules, identifierMap, cssFilesMap ping) {
437 let extensionMap = new Map();
438 let moduleFileMap = new Map();
439
440 for (let fileObj of JS_FILES_MAPPING) {
441 let components = fileObj.file.split('/');
442 let module = components[0];
443 let fileName = components[1];
444
445 if (!moduleFileMap.get(module))
446 moduleFileMap.set(module, []);
447
448 moduleFileMap.set(module, moduleFileMap.get(module).concat(fileName));
449 }
450
451 for (let module of modules) {
452 let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
453 let content = fs.readFileSync(moduleJSONPath).toString();
454 let moduleObj = JSON.parse(content);
455 let removedScripts = removeScripts(moduleObj, module);
456 removeResources(moduleObj, removedScripts);
457 removeExtensions(moduleObj);
458 fs.writeFileSync(moduleJSONPath, JSON.stringify(moduleObj, null, 4));
459 }
460
461 return extensionMap;
462
463 function removeScripts(moduleObj, module) {
464 let remainingScripts = [];
465 let removedScripts = [];
466 let moduleFiles = moduleFileMap.get(module);
467 for (let script of moduleObj.scripts) {
468 if (!moduleFiles.includes(script))
469 remainingScripts.push(script);
470 else
471 removedScripts.push(module + '/' + script);
472 }
473 moduleObj.scripts = remainingScripts;
474 return removedScripts;
475 }
476
477 function removeResources(moduleObj, removedScripts) {
478 if (!moduleObj.resources)
479 return;
480 let remainingResources = [];
481 let removedResources = new Set();
482 for (let script of removedScripts)
483 removedResources = removedResources.union(cssFilesMapping.get(script));
484
485
486 for (let resource of moduleObj.resources) {
487 if (!removedResources.has(resource))
488 remainingResources.push(resource);
489 }
490 moduleObj.resources = remainingResources;
491 }
492
493 function removeExtensions(moduleObj) {
494 if (!moduleObj.extensions)
495 return;
496 let remainingExtensions = [];
497 for (let extension of moduleObj.extensions) {
498 if (!objectIncludesIdentifier(extension))
499 remainingExtensions.push(extension);
500 else
501 extensionMap.set(objectIncludesIdentifier(extension), extension);
502 }
503 moduleObj.extensions = remainingExtensions;
504 }
505
506 function objectIncludesIdentifier(object) {
507 for (let key in object) {
508 let value = object[key];
509 if (identifierMap.has(value))
510 return value;
511 }
512 return false;
513 }
514 }
515
516 function createNewModuleDescriptors(extensionMap, cssFilesMapping, identifiersBy File, targetToOriginalFilesMap) {
517 let filesByNewModule = getFilesByNewModule();
518
519 for (let module of filesByNewModule.keys()) {
520 let moduleObj = {};
521
522 let scripts = getModuleScripts(module);
523 let extensions = getModuleExtensions(scripts, module);
524 if (extensions.length)
525 moduleObj.extensions = extensions;
526
527 moduleObj.dependencies = DEPENDENCIES_BY_MODULE[module];
528
529 moduleObj.scripts = scripts;
530
531 let resources = getModuleResources(moduleObj.scripts, module);
532 if (resources.length)
533 moduleObj.resources = resources;
534
535 let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
536 fs.writeFileSync(moduleJSONPath, JSON.stringify(moduleObj, null, 2));
537 }
538
539 function getFilesByNewModule() {
540 let filesByNewModule = new Map();
541 for (let fileObj of JS_FILES_MAPPING) {
542 if (!fileObj.new)
543 continue;
544 if (!filesByNewModule.has(fileObj.new))
545 filesByNewModule.set(fileObj.new, []);
546
547 filesByNewModule.set(fileObj.new, filesByNewModule.get(fileObj.new).concat ([fileObj.file]));
548 }
549 return filesByNewModule;
550 }
551
552 function getModuleScripts(module) {
553 return filesByNewModule.get(module).map((file) => file.split('/')[1]);
554 }
555
556 function getModuleResources(scripts, module) {
557 let resources = [];
558 scripts.map(script => module + '/' + script).forEach((script) => {
559 script = targetToOriginalFilesMap.get(script);
560 if (!cssFilesMapping.has(script))
561 return;
562
563 resources = resources.concat([...cssFilesMapping.get(script)]);
564 });
565 return resources;
566 }
567
568 function getModuleExtensions(scripts, module) {
569 let extensions = [];
570 let identifiers =
571 scripts.map(script => module + '/' + script)
572 .reduce((acc, file) => acc.concat(identifiersByFile.get(targetToOrig inalFilesMap.get(file))), []);
573 for (let identifier of identifiers) {
574 if (extensionMap.has(identifier))
575 extensions.push(extensionMap.get(identifier));
576 }
577 return extensions;
578 }
579 }
580
581 function calculateFilesByModuleType(type) {
582 let filesByNewModule = new Map();
583 for (let fileObj of JS_FILES_MAPPING) {
584 if (!fileObj[type])
585 continue;
586 if (!filesByNewModule.has(fileObj[type]))
587 filesByNewModule.set(fileObj[type], []);
588
589 filesByNewModule.set(fileObj[type], filesByNewModule.get(fileObj[type]).conc at([fileObj.file]));
590 }
591 return filesByNewModule;
592 }
593
594 function updateExistingModuleDescriptors(extensionMap, cssFilesMapping, identifi ersByFile, targetToOriginalFilesMap) {
595 let filesByExistingModule = calculateFilesByModuleType('existing');
596 for (let module of filesByExistingModule.keys()) {
597 let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
598 let content = fs.readFileSync(moduleJSONPath).toString();
599 let moduleObj = JSON.parse(content);
600
601 let scripts = getModuleScripts(module);
602 let existingExtensions = moduleObj.extensions || [];
603 let extensions = existingExtensions.concat(getModuleExtensions(scripts, modu le));
604 if (extensions.length)
605 moduleObj.extensions = extensions;
606
607 moduleObj.scripts = moduleObj.scripts.concat(scripts);
608
609 let existingResources = moduleObj.resources || [];
610 let resources = existingResources.concat(getModuleResources(scripts, module) );
611 if (resources.length)
612 moduleObj.resources = resources;
613
614 fs.writeFileSync(moduleJSONPath, JSON.stringify(moduleObj, null, 2));
615 }
616
617
618 function getModuleScripts(module) {
619 return filesByExistingModule.get(module).map((file) => file.split('/')[1]);
620 }
621
622 function getModuleResources(scripts, module) {
623 let resources = [];
624 scripts.map(script => module + '/' + script).forEach((script) => {
625 script = targetToOriginalFilesMap.get(script);
626 if (!cssFilesMapping.has(script))
627 return;
628
629 resources = resources.concat([...cssFilesMapping.get(script)]);
630 });
631 return resources;
632 }
633
634 function getModuleExtensions(scripts, module) {
635 let extensions = [];
636 let identifiers =
637 scripts.map(script => module + '/' + script)
638 .reduce((acc, file) => acc.concat(identifiersByFile.get(targetToOrig inalFilesMap.get(file))), []);
639 for (let identifier of identifiers) {
640 if (extensionMap.has(identifier))
641 extensions.push(extensionMap.get(identifier));
642 }
643 return extensions;
644 }
645 }
646
647 function addDependenciesToDescriptors() {
648 for (let module of getModules()) {
649 let moduleJSONPath = path.resolve(FRONTEND_PATH, module, 'module.json');
650 let content = fs.readFileSync(moduleJSONPath).toString();
651 let moduleObj = JSON.parse(content);
652
653 let existingDependencies = moduleObj.dependencies || [];
654 let dependencies = existingDependencies.concat(getModuleDependencies(module) )
655 .filter((module) => !MODULES_TO_REMOVE.includes(modul e));
656 let newDependenciesForExistingModule = NEW_DEPENDENCIES_BY_EXISTING_MODULES[ module];
657 if (newDependenciesForExistingModule)
658 dependencies = dependencies.concat(newDependenciesForExistingModule);
659 if (dependencies.length)
660 moduleObj.dependencies = dependencies;
661 let originalStringified = JSON.stringify(JSON.parse(content), null, 2);
662 let newStringified = JSON.stringify(moduleObj, null, 2);
663 if (originalStringified !== newStringified)
664 fs.writeFileSync(moduleJSONPath, newStringified);
665 }
666
667 function getModuleDependencies(existingModule) {
668 let newDeps = [];
669 for (let newModule in DEPENDENTS_BY_MODULE) {
670 let dependents = DEPENDENTS_BY_MODULE[newModule];
671 if (dependents.includes(existingModule))
672 newDeps.push(newModule);
673 }
674 return newDeps;
675 }
676 }
677
678 function updateApplicationDescriptor(descriptorFileName, newModuleSet) {
679 let descriptorPath = path.join(FRONTEND_PATH, descriptorFileName);
680 let newModules = [...newModuleSet].filter(m => APPLICATIONS_BY_MODULE[m].inclu des(descriptorFileName));
681 let includeNewModules = (acc, line) => {
682 if (line.includes('{') && line.endsWith('}')) {
683 line += ',';
684 acc.push(line);
685 return acc.concat(newModules.map((m, i) => {
686 // Need spacing to preserve indentation
687 let string;
688 if (MODULE_MAPPING[m].autostart)
689 string = ` { "name": "${m}", "type": "autostart"}`;
690 else
691 string = ` { "name": "${m}" }`;
692 if (i !== newModules.length - 1)
693 string += ',';
694 return string;
695 }));
696 }
697 return acc.concat([line]);
698 };
699 let removeModules = (acc, line) => MODULES_TO_REMOVE.every(m => !line.includes (m)) ? acc.concat([line]) : acc;
700 let lines =
701 fs.readFileSync(descriptorPath).toString().split('\n').reduce(includeNewMo dules, []).reduce(removeModules, []);
702 fs.writeFileSync(descriptorPath, lines.join('\n'));
703 }
704
705 function getModules() {
706 return fs.readdirSync(FRONTEND_PATH).filter(function(file) {
707 return fs.statSync(path.join(FRONTEND_PATH, file)).isDirectory() &&
708 utils.isFile(path.join(FRONTEND_PATH, file, 'module.json'));
709 });
710 }
711
712 if (require.main === module)
713 extractModule();
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698