diff --git a/lib/index.js b/lib/index.js index 91048ef..62f11b9 100644 --- a/lib/index.js +++ b/lib/index.js @@ -117,6 +117,7 @@ function run() { } await Promise.all([runChild && runChild.kill(), aliasReplace()]); + debug('Fork new child process'); runChild && runChild.forkChild(); }, 1000); diff --git a/lib/process.js b/lib/process.js index ea5edb2..d4a8007 100644 --- a/lib/process.js +++ b/lib/process.js @@ -117,6 +117,10 @@ const forkRun = (runCmdPath, runArgs = [], options = {}) => { const killRunningChild = async signal => { if (isWin) { await new Promise(resolve => { + if (!runChild || runChild.exitCode !== null) { + // has exited + resolve(); + } runChild.once('exit', (code, signal) => { resolve(); }); diff --git a/test/fixtures/base/run.js b/test/fixtures/base/run.js index b23610a..c504c9e 100644 --- a/test/fixtures/base/run.js +++ b/test/fixtures/base/run.js @@ -1 +1 @@ -process.send({ type: 'ready' }); \ No newline at end of file +process.send({ type: 'ready' }); diff --git a/test/fixtures/unreject_error/run.js b/test/fixtures/unreject_error/run.js new file mode 100644 index 0000000..522ca1e --- /dev/null +++ b/test/fixtures/unreject_error/run.js @@ -0,0 +1,2 @@ +require('./dist/a.js') +process.send({ type: 'ready' }); diff --git a/test/fixtures/unreject_error/tsconfig.json b/test/fixtures/unreject_error/tsconfig.json new file mode 100644 index 0000000..b3be0de --- /dev/null +++ b/test/fixtures/unreject_error/tsconfig.json @@ -0,0 +1,21 @@ +{ + "compilerOptions": { + "target": "es2018", // target es2018 + "module": "commonjs", + "moduleResolution": "node", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "inlineSourceMap":true, + "noImplicitThis": true, + "noUnusedLocals": true, + "stripInternal": true, + "skipLibCheck": true, + "pretty": true, + "outDir": "dist" + }, + "exclude": [ + "dist", + "node_modules", + "test" + ] +} diff --git a/test/index.test.js b/test/index.test.js index cdc44a4..1ce828b 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -197,4 +197,48 @@ describe('/test/index.js', () => { }); }); }); + + it('should restart when running failed with error and file changed soon', async () => { + // prepare + const runPath = join(__dirname, 'fixtures/unreject_error'); + const file = join(runPath, 'a.ts'); + await removeFile([ + file, + join(runPath, 'dist/a.js'), + ]); + + const tpl = ` +(async () => { + throw new Error('error') +})(); +`; + + // write to a.ts + writeFileSync(file, tpl); + + const cp = await execa('node', [mtscPath, '--watch', '--run', './run.js'], { + cwd: runPath, + }); + + await sleep(1000); + + // change file + writeFileSync(file, 'console.log("b")'); + + await new Promise((resolve, reject) => { + cp.on('exit', code => { + try { + expect(existsSync(join(runPath, 'dist/a.js'))).toBeTruthy(); + expect(readFileSync(join(runPath, 'dist/a.js'), 'utf-8')).toMatch(/"b"/); + resolve(); + } catch (err) { + reject(err); + } + }); + + setTimeout(() => { + cp.kill(); + }, 3000); + }); + }); });