UNPKG

jsx

Version:

a faster, safer, easier JavaScript

448 lines (415 loc) 13.1 kB
/*** * Platform-independent JSX compiler command */ /* * Copyright (c) 2012 DeNA Co., Ltd. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to * deal in the Software without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ import "./meta.jsx"; import "./compiler.jsx"; import "./completion.jsx"; import "./doc.jsx"; import "./platform.jsx"; import "./emitter.jsx"; import "./jsemitter.jsx"; import "./optimizer.jsx"; import "./analysis.jsx"; class JSXCommand { static function help() : string { return ( "JSX compiler version " + Meta.VERSION_STRING + "\n" + "\n" + "Usage: jsx [options] source-file\n" + "\n" + "Options:\n" + " --add-search-path path adds a path to library search paths\n" + " --executable RUNENV adds launcher to call _Main.main(:string[]):void\n" + " supported RUNENV is node, commonjs and web.\n" + " --run runs _Main.main(:string[]):void after compiling\n" + " --test runs _Test#test*():void after compiling\n" + " --output file output file (default:stdout)\n" + " --input-filename file names input filename\n" + " --mode (compile|parse|doc) specifies compilation mode (default:compile)\n" + " --target (javascript|c++) specifies target language (default:javascript)\n" + " --release disables run-time type checking and enables optimizations (" + Optimizer.getReleaseOptimizationCommands().join(",") + ")\n" + " --profile enables the profiler (experimental)\n" + " --optimize cmd1,cmd2,... enables optimization commands\n" + " --warn type1,type2,... enables warnings (all, deprecated, none)\n" + " --disable-type-check disables run-time type checking\n" + " --minify compresses the target JavaScript code\n" + " --enable-source-map enables source map debugging info\n" + " --complete line:column shows code completion at line:column\n" + " --version displays the version and compiler identifier and exits\n" + " --version-number displays the version as number and exits\n" + " --help displays this help and exits\n" + "\n" + "Env:\n" + " JSX_OPTS options of jsx(1)\n" + " JSX_RUNJS JavaScript engine used by --run and --test\n" + ""); } static function main (platform : Platform, args : string[]) : number { var argIndex = 0; var getopt = function () : Nullable.<string> { if (args.length <= argIndex) return null; var arg = args[argIndex++]; if (arg == "--") return null; if (arg.match(/^-/)) return arg; else { --argIndex; return null; } }; var getoptarg = function () : Nullable.<string> { if (args.length <= argIndex) { platform.error("option " + args[argIndex - 1] + " requires a value"); return null; } return args[argIndex++]; }; var compiler = new Compiler(platform); var tasks = new Array.<() -> void>; var optimizer = null : Optimizer; var completionRequest = null : CompletionRequest; var emitter = null : Emitter; var outputFile = null : Nullable.<string>; var inputFilename = null : Nullable.<string>; var executable = null : Nullable.<string>; var setBootstrapMode = function (sourceFile : string) : void {}; var runImmediately = false; var optimizeCommands = new string[]; var opt, optarg; while ((opt = getopt()) != null) { NEXTOPT: switch (opt) { case "--add-search-path": if((optarg= getoptarg()) == null) { return 1; } compiler.addSearchPath(optarg); break; case "--output": if((outputFile = getoptarg()) == null) { return 1; } break; case "--input-filename": if((inputFilename = getoptarg()) == null) { return 1; } break; case "--working-dir": // working directory if((optarg = getoptarg()) == null) { return 1; } platform.setWorkingDir(optarg); break; case "--mode": if ((optarg = getoptarg()) == null) { return 1; } switch (optarg) { case "compile": compiler.setMode(Compiler.MODE_COMPILE); break; case "parse": compiler.setMode(Compiler.MODE_PARSE); break; case "doc": compiler.setMode(Compiler.MODE_DOC); break; default: platform.error("unknown mode: " + optarg); return 1; } break; case "--complete": if ((optarg = getoptarg()) == null) { return 1; } completionRequest = function () : CompletionRequest { var a = optarg.split(/:/); return new CompletionRequest((a[0] as number), (a[1] as number) - 1); }(); compiler.setMode(Compiler.MODE_COMPLETE); break; case "--target": if ((optarg = getoptarg()) == null) { return 1; } switch (optarg) { case "javascript": emitter = new JavaScriptEmitter(platform); break; case "c++": throw new Error("FIXME"); default: platform.error("unknown target: " + optarg); return 1; } break; case "--release": tasks.push(function () : void { emitter.setEnableRunTimeTypeCheck(false); optimizer.setEnableRunTimeTypeCheck(false); }); optimizeCommands = Optimizer.getReleaseOptimizationCommands(); break; case "--optimize": if ((optarg = getoptarg()) == null) { return 1; } if (optarg == "release") { optimizeCommands = Optimizer.getReleaseOptimizationCommands(); } else { optimizeCommands = optimizeCommands.concat(optarg.split(",")); } break; case "--disable-optimize": if ((optarg = getoptarg()) == null) { return 1; } optimizeCommands = optimizeCommands.filter((item) -> { return optarg.split(",").indexOf(item) == -1; }); break; case "--warn": if ((optarg = getoptarg()) == null) { return 1; } optarg.split(",").forEach(function (type) { switch (type) { case "none": compiler.getWarningFilters().unshift(function (warning : CompileWarning) : Nullable.<boolean> { return false; }); break; case "all": compiler.getWarningFilters().unshift(function (warning : CompileWarning) : Nullable.<boolean> { return true; }); break; case "deprecated": compiler.getWarningFilters().unshift(function (warning : CompileWarning) : Nullable.<boolean> { if (warning instanceof DeprecatedWarning) { return true; } return null; }); break; default: platform.error("unknown warning type: " + type); } }); break; case "--warn-error": compiler.setWarningAsError(true); break; case "--executable": if ((optarg = getoptarg()) == null) { return 1; } switch (optarg) { case "web": // implies JavaScriptEmitter break; case "commonjs": // implies JavaScriptEmitter break; case "node": // implies JavaScriptEmitter break; default: platform.error("unknown executable type (node|web)"); return 1; } setBootstrapMode = function (sourceFile) { (emitter as JavaScriptEmitter).setBootstrapMode(JavaScriptEmitter.BOOTSTRAP_EXECUTABLE, sourceFile, executable); }; executable = optarg; break; case "--run": setBootstrapMode = function (sourceFile) { (emitter as JavaScriptEmitter).setBootstrapMode(JavaScriptEmitter.BOOTSTRAP_EXECUTABLE, sourceFile, executable); }; executable = executable ?: "node"; runImmediately = true; break; case "--test": setBootstrapMode = function (sourceFile) { (emitter as JavaScriptEmitter).setBootstrapMode(JavaScriptEmitter.BOOTSTRAP_TEST, sourceFile, executable); }; executable = executable ?: "node"; runImmediately = true; break; case "--profile": tasks.push(function () : void { emitter.setEnableProfiler(true); }); break; case "--minify": tasks.push(function () { emitter.setEnableMinifier(true); if (optimizeCommands.length != 0 && optimizeCommands[0] != "strip") optimizeCommands.unshift("strip"); if (optimizeCommands[optimizeCommands.length - 1] != "strip") optimizeCommands.push("strip"); }); break; case "--compilation-server": if ((optarg = getoptarg()) == null) { return 1; } return platform.runCompilationServer(optarg); case "--version": platform.log(Meta.IDENTIFIER); return 0; case "--version-number": platform.log(Meta.VERSION_NUMBER as string); return 0; case "--help": platform.log(JSXCommand.help()); return 0; default: var switchOpt = opt.match(new RegExp("^--(enable|disable)-(.*)$")); if (switchOpt != null) { var mode = switchOpt[1] == "enable"; switch (switchOpt[2]) { case "type-check": tasks.push(function (mode : boolean) : () -> void { return function () { emitter.setEnableRunTimeTypeCheck(mode); optimizer.setEnableRunTimeTypeCheck(mode); }; }(mode)); break NEXTOPT; case "source-map": tasks.push(function (mode : boolean) : () -> void { return function () { emitter.setEnableSourceMap(mode); }; }(mode)); break NEXTOPT; default: break; } } platform.error("unknown option: " + opt); return 1; } } if (argIndex == args.length) { platform.error("no files"); return 1; } var sourceFile = args[argIndex++]; if (inputFilename != null) { platform.setFileContent(inputFilename, platform.load(sourceFile)); sourceFile = inputFilename; } compiler.addSourceFile(null, sourceFile, completionRequest); switch (compiler.getMode()) { case Compiler.MODE_PARSE: if (compiler.compile()) { platform.save(outputFile, JSON.stringify(compiler.getAST())); return 0; } else { return 1; } } if (emitter == null) emitter = new JavaScriptEmitter(platform); setBootstrapMode(sourceFile); compiler.setEmitter(emitter); switch (compiler.getMode()) { case Compiler.MODE_DOC: if (outputFile == null) { platform.error("--output is mandatory for --mode doc"); return 1; } if (compiler.compile()) { new DocumentGenerator(compiler, platform.getRoot() + "/src/doc", outputFile) .setResourceFiles(["style.css"]) .setPathFilter(function (sourcePath) { if (sourcePath.indexOf("system:") == 0) { return false; } if (sourcePath.charAt(0) == "/") { return false; } if (sourcePath.indexOf("../") == 0) { return false; } if (sourcePath.indexOf("/../") != -1) { return false; } return true; }) .buildDoc(); return 0; } else { return 1; } } optimizer = new Optimizer(); tasks.forEach(function(proc) { proc(); }); if (emitter.getEnableMinifier() && emitter.getEnableSourceMap()) { platform.error("--minify and --source-map cannot be specified at the same time"); return 1; } var err = optimizer.setup(optimizeCommands); if (err != null) { platform.error(err); return 1; } emitter.setOutputFile(outputFile); compiler.setOptimizer(optimizer); var result = compiler.compile(); if (completionRequest != null) { platform.save(null, JSON.stringify(completionRequest.getCandidates())); return 0; } if (! result) return 65; // compile error (EX_DATAERR of FreeBSD sysexits(3)) var output = emitter.getOutput(); if (emitter instanceof JavaScriptEmitter) { if (! runImmediately || outputFile != null) { // compile and save platform.save(outputFile, output); if (outputFile != null) { var map = emitter.getSourceMappingFiles(); for (var filename in map) { platform.save(filename, map[filename]); } if (executable != null) { platform.makeFileExecutable(outputFile, executable); } } } else { // compile and run immediately platform.execute(sourceFile, output, args.slice(argIndex)); } } else { throw new Error("FIXME: C++ emitter"); } return 0; } } // vim: set noexpandtab: