1 | /*jshint node:true */ |
---|
2 | define([ |
---|
3 | "../../buildControl", |
---|
4 | "../../fileUtils", |
---|
5 | "dojo/has" |
---|
6 | ], function(bc, fileUtils, has){ |
---|
7 | // start up a few processes to compensate for the miserably slow closure compiler |
---|
8 | |
---|
9 | var processes = [], |
---|
10 | killAllRunners = function(){ |
---|
11 | processes.forEach(function(proc){ |
---|
12 | try{ |
---|
13 | proc.runner && proc.runner.kill(); |
---|
14 | proc.runner = 0; |
---|
15 | }catch(e){ |
---|
16 | //squelch |
---|
17 | } |
---|
18 | }); |
---|
19 | }; |
---|
20 | |
---|
21 | // don't leave orphan child procs |
---|
22 | global.process.on("exit", killAllRunners); |
---|
23 | global.process.on("uncaughtException", function(err){ |
---|
24 | killAllRunners(); |
---|
25 | // TODO: log these via bc.log |
---|
26 | console.log(err); |
---|
27 | console.log(err.stack); |
---|
28 | global.process.exit(-1); |
---|
29 | }); |
---|
30 | |
---|
31 | var |
---|
32 | processesStarted = 0, |
---|
33 | totalOptimizerOutput = "", |
---|
34 | nextProcId = 0, |
---|
35 | i, //used in for loop |
---|
36 | sendJob = function(src, dest, optimizeSwitch, copyright){ |
---|
37 | processes[nextProcId++].write(src, dest, optimizeSwitch, copyright); |
---|
38 | nextProcId= nextProcId % bc.maxOptimizationProcesses; |
---|
39 | }, |
---|
40 | doneRe = new RegExp("^Done\\s\\(compile\\stime.+$", "m"), |
---|
41 | optimizerRunner = require.toUrl("build/optimizeRunner.js"), |
---|
42 | buildRoot = optimizerRunner.match(/(.+)\/build\/optimizeRunner\.js$/)[1], |
---|
43 | runJava, //function, defined later |
---|
44 | oldSendJob = sendJob, //preserves reference if sendJob is replaced |
---|
45 | child_process = require.nodeRequire("child_process"), |
---|
46 | isCygwin = global.process.platform === 'cygwin', |
---|
47 | separator = has("is-windows") ? ";" : ":", |
---|
48 | javaClasses = fileUtils.catPath(buildRoot, "closureCompiler/compiler.jar") + separator + fileUtils.catPath(buildRoot, "shrinksafe/js.jar") + separator + fileUtils.catPath(buildRoot, "shrinksafe/shrinksafe.jar"); |
---|
49 | if(isCygwin){ |
---|
50 | //assume we're working with Windows Java, and need to translate paths |
---|
51 | runJava = function(cb){ |
---|
52 | child_process.exec("cygpath -wp '" + javaClasses + "'", function(err, stdout){ |
---|
53 | javaClasses = stdout.trim(); |
---|
54 | child_process.exec("cygpath -w '" + optimizerRunner + "'", function(err, stdout){ |
---|
55 | optimizerRunner = stdout.trim(); |
---|
56 | cb(); |
---|
57 | }); |
---|
58 | }); |
---|
59 | }; |
---|
60 | //wrap sendJob calls to convert to windows paths first |
---|
61 | sendJob = function(src, dest, optimizeSwitch, copyright){ |
---|
62 | child_process.exec("cygpath -wp '" + src + "'", function(err, srcstdout){ |
---|
63 | child_process.exec("cygpath -wp '" + dest + "'", function(err, deststdout){ |
---|
64 | oldSendJob(srcstdout.trim(), deststdout.trim(), |
---|
65 | optimizeSwitch, copyright); |
---|
66 | }); |
---|
67 | }); |
---|
68 | }; |
---|
69 | }else if(has("is-windows")){ |
---|
70 | runJava = function(cb){ |
---|
71 | javaClasses = fileUtils.normalize(javaClasses); |
---|
72 | optimizerRunner = fileUtils.normalize(optimizerRunner); |
---|
73 | cb(); |
---|
74 | }; |
---|
75 | sendJob = function(src, dest, optimizeSwitch, copyright){ |
---|
76 | var wsrc = fileUtils.normalize(src); |
---|
77 | var wdest = fileUtils.normalize(dest); |
---|
78 | oldSendJob(wsrc, wdest, optimizeSwitch, copyright); |
---|
79 | }; |
---|
80 | }else{ |
---|
81 | //no waiting necessary, pass through |
---|
82 | runJava = function(cb) { cb(); }; |
---|
83 | } |
---|
84 | runJava(function() { |
---|
85 | for(i = 0; i < bc.maxOptimizationProcesses; i++) {(function(){ |
---|
86 | var |
---|
87 | runner = child_process.spawn("java", ["-cp", javaClasses, "org.mozilla.javascript.tools.shell.Main", optimizerRunner]), |
---|
88 | proc = { |
---|
89 | runner:runner, |
---|
90 | results:"", |
---|
91 | tempResults:"", |
---|
92 | sent:[], |
---|
93 | write:function(src, dest, optimizeSwitch, copyright){ |
---|
94 | proc.sent.push(dest); |
---|
95 | runner.stdin.write(src + "\n" + dest + "\n" + optimizeSwitch + "\n" + JSON.stringify({ copyright: copyright, options: bc.optimizeOptions, useSourceMaps: bc.useSourceMaps }) + "\n"); |
---|
96 | }, |
---|
97 | sink:function(output){ |
---|
98 | proc.tempResults += output; |
---|
99 | var match, message, chunkLength; |
---|
100 | while((match = proc.tempResults.match(doneRe))){ |
---|
101 | message = match[0]; |
---|
102 | if(/OPTIMIZER\sFAILED/.test(message)){ |
---|
103 | bc.log("optimizeFailed", ["module identifier", proc.sent.shift(), "exception", message.substring(5)]); |
---|
104 | }else{ |
---|
105 | bc.log("optimizeDone", [proc.sent.shift() + " " + message.substring(5)]); |
---|
106 | } |
---|
107 | chunkLength = match.index + message.length; |
---|
108 | proc.results += proc.tempResults.substring(0, chunkLength); |
---|
109 | proc.tempResults = proc.tempResults.substring(chunkLength); |
---|
110 | } |
---|
111 | } |
---|
112 | }; |
---|
113 | processesStarted++; // matches *3* |
---|
114 | runner.stdout.on("data", function(data){ |
---|
115 | // the +"" converts to Javascript string |
---|
116 | proc.sink(data + ""); |
---|
117 | }), |
---|
118 | runner.stderr.on("data", function(data){ |
---|
119 | // the +"" converts to Javascript string |
---|
120 | proc.sink(data + ""); |
---|
121 | }), |
---|
122 | runner.on("exit", function(){ |
---|
123 | proc.results += proc.tempResults; |
---|
124 | totalOptimizerOutput += proc.results; |
---|
125 | bc.logOptimizerOutput(totalOptimizerOutput); |
---|
126 | processesStarted--; // matches *3* |
---|
127 | if(!processesStarted){ |
---|
128 | // all the processes have completed and shut down at this point |
---|
129 | if(bc.showOptimizerOutput){ |
---|
130 | bc.log("optimizeMessages", [totalOptimizerOutput]); |
---|
131 | } |
---|
132 | bc.passGate(); // matched with *1* |
---|
133 | } |
---|
134 | }); |
---|
135 | processes.push(proc); |
---|
136 | })();} |
---|
137 | }); //end runJava(function...) |
---|
138 | |
---|
139 | bc.gateListeners.push(function(gate){ |
---|
140 | if(gate==="cleanup"){ |
---|
141 | // going through the cleanup gate signals that all optimizations have been started; |
---|
142 | // we now signal the runner there are no more files and wait for the runner to stop |
---|
143 | bc.log("pacify", "waiting for the optimizer runner to finish..."); |
---|
144 | bc.waiting++; // matched with *1* |
---|
145 | processes.forEach(function(proc){ |
---|
146 | proc.write(".\n"); |
---|
147 | }); |
---|
148 | processes = []; |
---|
149 | } |
---|
150 | }); |
---|
151 | |
---|
152 | return sendJob; |
---|
153 | }); |
---|