From d51c508ba5a268bd65561076ade9da4ad16b122f Mon Sep 17 00:00:00 2001 From: Pooya Parsa Date: Sat, 10 Nov 2018 01:23:13 +0330 Subject: [PATCH] feat(log-update): support concurrent writes to stdout/stderr on render --- src/reporters/fancy.js | 17 +---------- src/utils/log-update.js | 67 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 21 deletions(-) diff --git a/src/reporters/fancy.js b/src/reporters/fancy.js index 7866060..e4317df 100644 --- a/src/reporters/fancy.js +++ b/src/reporters/fancy.js @@ -1,6 +1,5 @@ /* eslint-disable no-console */ import chalk from 'chalk'; -import consola from 'consola'; import { renderBar, colorize, ellipsisLeft } from '../utils/cli'; import { formatRequest } from '../utils/webpack'; @@ -12,29 +11,15 @@ const logUpdate = new LogUpdate(); let lastRender = Date.now(); export default class FancyReporter { - start() { - // TODO: remove in next major release. - // Some projects still depend on legacy versions of consola - if (typeof consola.pause === 'function') { - consola.pause(); - } - } - allDone() { logUpdate.done(); - - if (typeof consola.resume === 'function') { - consola.resume(); - } } done(context) { this._renderStates(context.statesArray); if (context.hasErrors) { - if (typeof consola.resume === 'function') { - consola.resume(); - } + logUpdate.done(); } } diff --git a/src/utils/log-update.js b/src/utils/log-update.js index 151f9fc..e65940c 100644 --- a/src/utils/log-update.js +++ b/src/utils/log-update.js @@ -6,20 +6,30 @@ import wrapAnsi from 'wrap-ansi'; export default class LogUpdate { constructor() { this.prevLineCount = 0; + this.listening = false; + this.extraLines = ''; + this._onData = this._onData.bind(this); + this._streams = [process.stdout, process.stderr]; } render(lines) { + this.listen(); + const wrappedLines = wrapAnsi(lines, this.columns, { trim: false, hard: true, wordWrap: false, }); - const earaseChars = ansiEscapes.eraseLines(this.prevLineCount); + const data = + ansiEscapes.eraseLines(this.prevLineCount) + + wrappedLines + + '\n' + + this.extraLines; - this.write(earaseChars + wrappedLines + '\n'); + this.write(data); - this.prevLineCount = wrappedLines.split('\n').length + 1; + this.prevLineCount = data.split('\n').length; } get columns() { @@ -27,15 +37,62 @@ export default class LogUpdate { } write(data) { - process.stderr.write(data, 'utf-8'); + if (process.stderr.__write) { + process.stderr.__write(data, 'utf-8'); + } else { + process.stderr.write(data, 'utf-8'); + } } clear() { + this.done(); this.write(ansiEscapes.eraseLines(this.prevLineCount)); - this.prevLineCount = 0; } done() { + this.stopListen(); + this.prevLineCount = 0; + this.extraLines = ''; + } + + _onData(data) { + const str = String(data); + const lines = str.split('\n').length - 1; + if (lines > 0) { + this.prevLineCount += lines; + this.extraLines += data; + } + } + + listen() { + if (this.listening) { + return; + } + + const t = this; + + for (const stream of this._streams) { + if (!stream.__write) { + stream.__write = stream.write; + stream.write = function write(data, ...args) { + t._onData(data); + this.__write(data, ...args); + }; + } + } + + this.listening = true; + } + + stopListen() { + for (const stream of this._streams) { + if (stream.__write) { + stream.write = stream.__write; + delete stream.__write; + } + } + + this.listening = false; } }