| // Copyright 2016 The Chromium Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| 'use strict'; | |
| var childProcess = require('child_process'); | |
| const fs = require('fs'); | |
| var http = require('http'); | |
| const path = require('path'); | |
| var parseURL = require('url').parse; | |
| const utils = require('../utils'); | |
| const FRONTEND_PATH = path.resolve(__dirname, '..', '..', 'front_end'); | |
| const OUT_DIR_PATH = path.resolve(__dirname, 'out'); | |
| const OUT_FILE_PATH = path.resolve(OUT_DIR_PATH, 'dependencies.dot'); | |
| const SERVER_PORT = parseInt(process.env.PORT, 10) || 8001; | |
| function main() { | |
| generateDot(); | |
| try { | |
| childProcess.execSync(`dot -O -Tsvg ${OUT_FILE_PATH}`); | |
| } catch (err) { | |
| console.log(`Could not generate dot svg because: ${err}`); | |
| console.log('Make sure you have graphviz installed (e.g. sudo apt install graphviz)'); | |
| return; | |
| } | |
| console.log('Generated dot file & svg'); | |
| startServer(); | |
| console.log(`Go to: http://localhost:${SERVER_PORT}/jquery_svg.html`); | |
| } | |
| function generateDot() { | |
| if (!utils.isDir(OUT_DIR_PATH)) | |
| fs.mkdirSync(OUT_DIR_PATH); | |
| const modules = new Set(); | |
| const moduleToDependencyList = ['digraph dependencies {']; | |
| moduleToDependencyList.push('fixedsize = true;'); | |
| fs.readdirSync(FRONTEND_PATH).forEach(function(file) { | |
| const moduleJSONPath = path.join(FRONTEND_PATH, file, 'module.json'); | |
| if (fs.statSync(path.join(FRONTEND_PATH, file)).isDirectory() && utils.isFile(moduleJSONPath)) { | |
| const module = file; | |
| if (module === 'audits_worker') | |
| return; | |
| modules.add(module); | |
| const moduleJSON = require(moduleJSONPath); | |
| let moduleSize = 0; | |
| let resources = (moduleJSON.scripts || []).concat((moduleJSON.resources || [])); | |
| for (let script of resources) { | |
| if (fs.existsSync(path.join(FRONTEND_PATH, module, script))) | |
| moduleSize += fs.statSync(path.join(FRONTEND_PATH, module, script)).size; | |
| } | |
| moduleSize /= 200000; | |
| moduleSize = Math.max(0.5, moduleSize); | |
| let fontSize = Math.max(moduleSize * 14, 14); | |
| moduleToDependencyList.push(`${module} [width=${moduleSize}, height=${moduleSize} fontsize=${fontSize}];`); | |
| if (moduleJSON.dependencies) { | |
| for (let d of moduleJSON.dependencies) | |
| moduleToDependencyList.push(` ${module} -> ${d}`); | |
| } | |
| } | |
| }); | |
| moduleToDependencyList.push('}'); | |
| const content = moduleToDependencyList.join('\n'); | |
| fs.writeFileSync(OUT_FILE_PATH, content); | |
| } | |
| function startServer() { | |
| http.createServer(requestHandler).listen(SERVER_PORT); | |
| function requestHandler(request, response) { | |
| var filePath = parseURL(request.url).pathname; | |
| var absoluteFilePath = path.join(__dirname, filePath); | |
| if (!path.resolve(absoluteFilePath).startsWith(__dirname)) { | |
| console.log(`File requested is outside of folder: ${__dirname}`); | |
| sendResponse(403, `403 - Access denied. File requested is outside of folder: ${__dirname}`); | |
| return; | |
| } | |
| fs.exists(absoluteFilePath, fsExistsCallback); | |
| function fsExistsCallback(fileExists) { | |
| if (!fileExists) { | |
| console.log(`Cannot find file ${absoluteFilePath}`); | |
| sendResponse(404, '404 - File not found'); | |
| return; | |
| } | |
| fs.readFile(absoluteFilePath, 'binary', readFileCallback); | |
| } | |
| function readFileCallback(err, file) { | |
| if (err) { | |
| console.log(`Unable to read local file ${absoluteFilePath}:`, err); | |
| sendResponse(500, '500 - Internal Server Error'); | |
| return; | |
| } | |
| sendResponse(200, file); | |
| } | |
| function sendResponse(statusCode, data) { | |
| response.writeHead(statusCode); | |
| response.write(data, 'binary'); | |
| response.end(); | |
| } | |
| } | |
| } | |
| if (require.main === module) | |
| main(); |