229 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
		
		
			
		
	
	
			229 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
|  | "use strict"; | ||
|  | Object.defineProperty(exports, "__esModule", { value: true }); | ||
|  | exports.HaxeCompiler = void 0; | ||
|  | const ProjectFile_1 = require("./ProjectFile"); | ||
|  | const child_process = require("child_process"); | ||
|  | const fs = require("fs"); | ||
|  | const path = require("path"); | ||
|  | const chokidar = require("chokidar"); | ||
|  | const log = require("./log"); | ||
|  | const exec_1 = require("./exec"); | ||
|  | const ws_1 = require("ws"); | ||
|  | class HaxeCompiler { | ||
|  |     constructor(from, temp, to, resourceDir, haxeDirectory, hxml, sourceDirectories, sysdir, port, isLiveReload, httpPort) { | ||
|  |         this.ready = true; | ||
|  |         this.todo = false; | ||
|  |         this.port = '7000'; | ||
|  |         this.isLiveReload = false; | ||
|  |         this.wsClients = []; | ||
|  |         this.from = from; | ||
|  |         this.temp = temp; | ||
|  |         this.to = to; | ||
|  |         this.resourceDir = resourceDir; | ||
|  |         this.haxeDirectory = haxeDirectory; | ||
|  |         this.hxml = hxml; | ||
|  |         this.sysdir = sysdir; | ||
|  |         this.port = port; | ||
|  |         this.isLiveReload = isLiveReload; | ||
|  |         this.sourceMatchers = []; | ||
|  |         for (let dir of sourceDirectories) { | ||
|  |             this.sourceMatchers.push(path.join(dir, '**').replace(/\\/g, '/')); | ||
|  |         } | ||
|  |         if (isLiveReload) { | ||
|  |             this.wss = new ws_1.WebSocketServer({ | ||
|  |                 port: parseInt(httpPort) + 1 | ||
|  |             }); | ||
|  |             this.wss.on('connection', (client) => { | ||
|  |                 if (this.wsClients.includes(client)) | ||
|  |                     return; | ||
|  |                 this.wsClients.push(client); | ||
|  |             }); | ||
|  |         } | ||
|  |     } | ||
|  |     close() { | ||
|  |         if (this.watcher) | ||
|  |             this.watcher.close(); | ||
|  |         if (this.compilationServer) | ||
|  |             this.compilationServer.kill(); | ||
|  |         if (this.isLiveReload) | ||
|  |             this.wss.close(); | ||
|  |     } | ||
|  |     async run(watch) { | ||
|  |         if (watch) { | ||
|  |             this.watcher = chokidar.watch(this.sourceMatchers, { ignored: /[\/\\]\.(git|DS_Store)/, persistent: true, ignoreInitial: true }); | ||
|  |             this.watcher.on('add', (file) => { | ||
|  |                 this.scheduleCompile(); | ||
|  |             }); | ||
|  |             this.watcher.on('change', (file) => { | ||
|  |                 this.scheduleCompile(); | ||
|  |             }); | ||
|  |             this.watcher.on('unlink', (file) => { | ||
|  |                 this.scheduleCompile(); | ||
|  |             }); | ||
|  |             this.startCompilationServer(); | ||
|  |             this.triggerCompilationServer(); | ||
|  |         } | ||
|  |         else { | ||
|  |             try { | ||
|  |                 await this.compile(); | ||
|  |             } | ||
|  |             catch (error) { | ||
|  |                 return Promise.reject(error); | ||
|  |             } | ||
|  |         } | ||
|  |         return Promise.resolve(); | ||
|  |     } | ||
|  |     scheduleCompile() { | ||
|  |         if (this.ready) { | ||
|  |             this.triggerCompilationServer(); | ||
|  |         } | ||
|  |         else { | ||
|  |             this.todo = true; | ||
|  |         } | ||
|  |     } | ||
|  |     runHaxeAgain(parameters, onClose) { | ||
|  |         let exe = 'haxe'; | ||
|  |         let env = process.env; | ||
|  |         if (fs.existsSync(this.haxeDirectory) && fs.statSync(this.haxeDirectory).isDirectory()) { | ||
|  |             let localexe = path.resolve(this.haxeDirectory, 'haxe' + (0, exec_1.sys)()); | ||
|  |             if (!fs.existsSync(localexe)) | ||
|  |                 localexe = path.resolve(this.haxeDirectory, 'haxe'); | ||
|  |             if (fs.existsSync(localexe)) | ||
|  |                 exe = localexe; | ||
|  |             const stddir = path.resolve(this.haxeDirectory, 'std'); | ||
|  |             if (fs.existsSync(stddir) && fs.statSync(stddir).isDirectory()) { | ||
|  |                 env.HAXE_STD_PATH = stddir; | ||
|  |             } | ||
|  |         } | ||
|  |         let haxe = child_process.spawn(exe, parameters, { env: env, cwd: path.normalize(this.from) }); | ||
|  |         haxe.stdout.on('data', (data) => { | ||
|  |             log.info(data.toString()); | ||
|  |         }); | ||
|  |         haxe.stderr.on('data', (data) => { | ||
|  |             log.error(data.toString()); | ||
|  |         }); | ||
|  |         haxe.on('close', onClose); | ||
|  |         return haxe; | ||
|  |     } | ||
|  |     runHaxeAgainAndWait(parameters) { | ||
|  |         return new Promise((resolve, reject) => { | ||
|  |             this.runHaxeAgain(parameters, (code, signal) => { | ||
|  |                 if (code === 0) { | ||
|  |                     resolve(); | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     reject(); | ||
|  |                 } | ||
|  |             }); | ||
|  |         }); | ||
|  |     } | ||
|  |     static cleanHxml(hxml) { | ||
|  |         let params = []; | ||
|  |         let ignoreNext = false; | ||
|  |         let parameters = hxml.split('\n'); | ||
|  |         for (let parameter of parameters) { | ||
|  |             if (!parameter.startsWith('-main') && !parameter.startsWith('-js')) { | ||
|  |                 params.push(parameter); | ||
|  |             } | ||
|  |         } | ||
|  |         return params.join('\n'); | ||
|  |     } | ||
|  |     runHaxe(parameters, onClose) { | ||
|  |         if (fs.existsSync(path.join(this.resourceDir, 'workers.txt'))) { | ||
|  |             fs.unlinkSync(path.join(this.resourceDir, 'workers.txt')); | ||
|  |         } | ||
|  |         let haxe = this.runHaxeAgain(parameters, async (code, signal) => { | ||
|  |             if (fs.existsSync(path.join(this.resourceDir, 'workers.txt'))) { | ||
|  |                 let hxml = fs.readFileSync(path.join(this.from, parameters[0]), { encoding: 'utf8' }); | ||
|  |                 let workers = fs.readFileSync(path.join(this.resourceDir, 'workers.txt'), { encoding: 'utf8' }); | ||
|  |                 let lines = workers.split('\n'); | ||
|  |                 for (let line of lines) { | ||
|  |                     if (line.trim() === '') | ||
|  |                         continue; | ||
|  |                     log.info('Creating ' + line + ' worker.'); | ||
|  |                     let newhxml = HaxeCompiler.cleanHxml(hxml); | ||
|  |                     newhxml += '-main ' + line.trim() + '\n'; | ||
|  |                     newhxml += '-js ' + path.join(this.sysdir, line.trim()) + '.js\n'; | ||
|  |                     newhxml += '-D kha_in_worker\n'; | ||
|  |                     fs.writeFileSync(path.join(this.from, 'temp.hxml'), newhxml, { encoding: 'utf8' }); | ||
|  |                     await this.runHaxeAgainAndWait(['temp.hxml']); | ||
|  |                 } | ||
|  |                 onClose(code, signal); | ||
|  |             } | ||
|  |             else { | ||
|  |                 onClose(code, signal); | ||
|  |             } | ||
|  |         }); | ||
|  |         return haxe; | ||
|  |     } | ||
|  |     startCompilationServer() { | ||
|  |         this.compilationServer = this.runHaxe(['--wait', this.port], (code) => { | ||
|  |             log.info('Haxe compilation server stopped.'); | ||
|  |         }); | ||
|  |     } | ||
|  |     triggerCompilationServer() { | ||
|  |         process.stdout.write('\x1Bc'); | ||
|  |         log.info('Haxe compilation...'); | ||
|  |         this.ready = false; | ||
|  |         this.todo = false; | ||
|  |         return new Promise((resolve, reject) => { | ||
|  |             this.runHaxe(['--connect', this.port, this.hxml], (code) => { | ||
|  |                 if (this.to && fs.existsSync(path.join(this.from, this.temp))) { | ||
|  |                     fs.renameSync(path.join(this.from, this.temp), path.join(this.from, this.to)); | ||
|  |                 } | ||
|  |                 this.ready = true; | ||
|  |                 if (code === 0) { | ||
|  |                     process.stdout.write('\x1Bc'); | ||
|  |                     log.info('Haxe compile end.'); | ||
|  |                     if (this.isLiveReload) { | ||
|  |                         this.wsClients.forEach(client => { | ||
|  |                             client.send(JSON.stringify({})); | ||
|  |                         }); | ||
|  |                     } | ||
|  |                     for (let callback of ProjectFile_1.Callbacks.postHaxeRecompilation) { | ||
|  |                         callback(); | ||
|  |                     } | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     log.info('Haxe compile error.'); | ||
|  |                 } | ||
|  |                 if (code === 0) { | ||
|  |                     resolve(); | ||
|  |                 } | ||
|  |                 // (node:3630) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future,
 | ||
|  |                 // promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
 | ||
|  |                 // else reject('Haxe compiler error.');
 | ||
|  |                 if (this.todo) { | ||
|  |                     this.scheduleCompile(); | ||
|  |                 } | ||
|  |             }); | ||
|  |         }); | ||
|  |     } | ||
|  |     compile() { | ||
|  |         return new Promise((resolve, reject) => { | ||
|  |             this.runHaxe([this.hxml], (code) => { | ||
|  |                 if (code === 0) { | ||
|  |                     if (this.to && fs.existsSync(path.join(this.from, this.temp))) { | ||
|  |                         fs.renameSync(path.join(this.from, this.temp), path.join(this.from, this.to)); | ||
|  |                     } | ||
|  |                     resolve(); | ||
|  |                 } | ||
|  |                 else { | ||
|  |                     process.exitCode = 1; | ||
|  |                     log.error('Haxe compiler error.'); | ||
|  |                     reject(); | ||
|  |                 } | ||
|  |             }); | ||
|  |         }); | ||
|  |     } | ||
|  |     static spinRename(from, to) { | ||
|  |         for (;;) { | ||
|  |             if (fs.existsSync(from)) { | ||
|  |                 fs.renameSync(from, to); | ||
|  |                 return; | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | exports.HaxeCompiler = HaxeCompiler; | ||
|  | //# sourceMappingURL=HaxeCompiler.js.map
 |