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
							 |