UNPKG

scc

Version:

This is a simple combo & compress tool for seajs project.

152 lines (120 loc) 3.35 kB
/** * @fileoverview Extracts module dependencies. * @author lifesinger@gmail.com (Frank Wang) */ var fs = require('fs'); var astParser = require('uglify-js').parser; var Ast = require('./ast.js'); var fsExt = require('./fs_ext.js'); var moduleHelp = require('./module_help.js'); var Dependences = exports; function parse(inputFile, charset) { var ast = getAst(inputFile, charset); var deps = parseStatic(ast); if (deps === undefined) { deps = parseDynamic(ast); } return deps; } function parseStatic(inputFile, charset) { var ast = getAst(inputFile, charset); var deps, times = 0; Ast.walk(ast, 'stat', function(stat) { if (stat.toString().indexOf('stat,call,name,define,') !== 0) { return stat; } // only process the first one. if (++times > 1) { return; } // stat[1]: // [ 'call', // [ 'name', 'define' ], // [ [Object], [Object], [Object ] ] ] var argsAst = stat[1][2]; var depsAst; // argsAst: // [ [ 'string', 'a' ], // [ 'array', [ [Object], [Object] ] ], // [ 'function', null, [], [] ] ] argsAst.some(function(item, i) { // NOTICE: the deps MUST be literal, it can NOT be a reference. if (item[0] === 'array' && i !== argsAst.length - 1) { depsAst = item[1]; return true; } }); if (!depsAst) { return stat; } // depsAst: // [ [ 'string', 'b' ], [ 'string', 'c' ] ] deps = []; depsAst.forEach(function(item) { if (item[0] === 'string') { deps.push(item[1]); } }); return stat; }); return deps; } function parseDynamic(inputFile, charset) { var ast = getAst(inputFile, charset); var deps = []; Ast.walk(ast, 'call', function(stat) { if (stat.toString().indexOf('call,name,require,') !== 0) { return stat; } // stat: // [ 'call', [ 'name', 'require' ], [ [ 'string', 'a' ] ] ] var argsAst = stat[2]; argsAst.forEach(function(item) { if (item[0] === 'string') { deps.push(item[1]); } }); return stat; }); return deps; } function replaceRequire(code, project, debug) { var ast = getAst(code); Ast.walk(ast, 'call', function(stat) { if (stat.toString().indexOf('call,name,require,') !== 0) { return stat; } // stat: // [ 'call', [ 'name', 'require' ], [ [ 'string', 'a' ] ] ] var argsAst = stat[2]; argsAst.forEach(function(item) { if (item[0] === 'string') { var depModName = item[1]; if (moduleHelp.isRelative(depModName)) { depModName = moduleHelp.getBaseModule(depModName) + debug; } else { depModName = project.getGlobalModuleId(depModName) + debug; } item[1] = depModName; } }); return stat; }); return Ast.gen_code(ast, { beautify: true }); } function getAst(inputFile, charset) { if (typeof inputFile !== 'string') { return inputFile; } if (!fsExt.existsSync(inputFile)) { return astParser.parse(inputFile); } return astParser.parse(fs.readFileSync(inputFile, charset || 'utf8')); } Dependences.getAst = getAst; Dependences.parse = parse; Dependences.replaceRequire = replaceRequire; Dependences._parseStatic = parseStatic; Dependences._parseDynamic = parseDynamic;