From 6f6c6b7714cde21c4b342dcb2abfd92f2df4b020 Mon Sep 17 00:00:00 2001 From: Kyrylo Gliebov Date: Fri, 7 Dec 2018 20:18:33 +0100 Subject: [PATCH] Add error service --- src/player.jsx | 132 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 86 insertions(+), 46 deletions(-) diff --git a/src/player.jsx b/src/player.jsx index e0e2fe4..6e5444d 100644 --- a/src/player.jsx +++ b/src/player.jsx @@ -26,21 +26,6 @@ let $ = require("jquery"); require("console.css"); require("bootstrap-slider"); -/* - * Get an object field, verifying its presence and type. - */ -let getValidField = function (object, field, type) { - let value; - if (!(field in object)) { - throw Error("\"" + field + "\" field is missing"); - } - value = object[field]; - if (typeof (value) != typeof (type)) { - throw Error("invalid \"" + field + "\" field type: " + typeof (value)); - } - return value; -}; - let scrollToBottom = function(id) { const el = document.getElementById(id); if (el) { @@ -48,6 +33,54 @@ let scrollToBottom = function(id) { } }; +function ErrorList(props) { + let list = []; + + if (props.list) { + list = props.list.map((message, key) => { return }); + } + + return ( + + {list} + + ); +} + +function ErrorItem(props) { + return ( +
+ + + {props.message} +
+ ); +} + +let ErrorService = class { + constructor() { + this.addMessage = this.addMessage.bind(this); + this.errors = []; + } + + addMessage(message) { + if (typeof message === "object" && message !== null) { + if ("toString" in message) { + message = message.toString(); + } else { + message = _("unknown error"); + } + } + if (typeof message === "string" || message instanceof String) { + if (this.errors.indexOf(message) === -1) { + this.errors.push(message); + } + } + } +}; + /* * An auto-loading buffer of recording's packets. */ @@ -55,10 +88,11 @@ let PacketBuffer = class { /* * Initialize a buffer. */ - constructor(matchList) { + constructor(matchList, reportError) { this.handleError = this.handleError.bind(this); this.handleStream = this.handleStream.bind(this); this.handleDone = this.handleDone.bind(this); + this.getValidField = this.getValidField.bind(this); /* RegExp used to parse message's timing field */ this.timingRE = new RegExp( /* Delay (1) */ @@ -81,6 +115,7 @@ let PacketBuffer = class { ); /* List of matches to apply when loading the buffer from Journal */ this.matchList = matchList; + this.reportError = reportError; /* * An array of two-element arrays (tuples) each containing a * packet index and a deferred object. The list is kept sorted to @@ -119,6 +154,21 @@ let PacketBuffer = class { this.done = false; } + /* + * Get an object field, verifying its presence and type. + */ + getValidField(object, field, type) { + let value; + if (!(field in object)) { + this.reportError("\"" + field + "\" field is missing"); + } + value = object[field]; + if (typeof (value) != typeof (type)) { + this.reportError("invalid \"" + field + "\" field type: " + typeof (value)); + } + return value; + } + /* * Return a promise which is resolved when a packet at a particular * index is received by the buffer. The promise is rejected with a @@ -235,6 +285,7 @@ let PacketBuffer = class { this.idxDfdList[i][1].reject(error); } this.idxDfdList = []; + this.reportError(error); } /* @@ -257,7 +308,7 @@ let PacketBuffer = class { /* Match next timing entry */ matches = this.timingRE.exec(timing); if (matches === null) { - throw Error("invalid timing string"); + this.reportError(_("invalid timing string")); } else if (matches[0] == "") { break; } @@ -297,7 +348,7 @@ let PacketBuffer = class { /* Add (replacement) input characters */ s = in_txt.slice(in_txt_pos, in_txt_pos += x); if (s.length != x) { - throw Error("timing entry out of input bounds"); + this.reportError(_("timing entry out of input bounds")); } io.push(s); break; @@ -319,7 +370,7 @@ let PacketBuffer = class { /* Add (replacement) output characters */ s = out_txt.slice(out_txt_pos, out_txt_pos += x); if (s.length != x) { - throw Error("timing entry out of output bounds"); + this.reportError(_("timing entry out of output bounds")); } io.push(s); break; @@ -348,10 +399,10 @@ let PacketBuffer = class { } if (in_txt_pos < in_txt.length) { - throw Error("extra input present"); + this.reportError(_("extra input present")); } if (out_txt_pos < out_txt.length) { - throw Error("extra output present"); + this.reportError(_("extra output present")); } if (io.length > 0) { @@ -375,24 +426,24 @@ let PacketBuffer = class { const string = String(); /* Check version */ - ver = getValidField(message, "ver", string); + ver = this.getValidField(message, "ver", string); matches = ver.match("^(\\d+)\\.(\\d+)$"); if (matches === null || matches[1] > 2) { - throw Error("\"ver\" field has invalid value: " + ver); + this.reportError("\"ver\" field has invalid value: " + ver); } /* TODO Perhaps check host, rec, user, term, and session fields */ /* Extract message ID */ - id = getValidField(message, "id", number); + id = this.getValidField(message, "id", number); if (id <= this.id) { - throw Error("out of order \"id\" field value: " + id); + this.reportError("out of order \"id\" field value: " + id); } /* Extract message time position */ - pos = getValidField(message, "pos", number); + pos = this.getValidField(message, "pos", number); if (pos < this.message_pos) { - throw Error("out of order \"pos\" field value: " + pos); + this.reportError("out of order \"pos\" field value: " + pos); } /* Update last received message ID and time position */ @@ -401,9 +452,9 @@ let PacketBuffer = class { /* Parse message data */ this.parseMessageData( - getValidField(message, "timing", string), - getValidField(message, "in_txt", string), - getValidField(message, "out_txt", string)); + this.getValidField(message, "timing", string), + this.getValidField(message, "in_txt", string), + this.getValidField(message, "out_txt", string)); } /* @@ -573,7 +624,6 @@ export class Player extends React.Component { containerWidth: 630, currentTsPost: 0, scale: 1, - error: null, input: "", mark: 0, }; @@ -581,7 +631,9 @@ export class Player extends React.Component { this.containerHeight = 290; /* Auto-loading buffer of recording's packets */ - this.buf = new PacketBuffer(this.props.matchList); + this.error_service = new ErrorService(); + this.reportError = this.error_service.addMessage; + this.buf = new PacketBuffer(this.props.matchList, this.reportError); /* Current recording time, ms */ this.recTS = 0; @@ -655,7 +707,7 @@ export class Player extends React.Component { /* Handle packet retrieval error */ handleError(error) { if (error !== null) { - this.setState({error: error}); + this.reportError(error); console.warn(error); } } @@ -1046,18 +1098,6 @@ export class Player extends React.Component { "float": "right", }; - let error = ""; - if (this.state.error) { - error = ( -
- - - {this.state.error}. -
); - } - // ensure react never reuses this div by keying it with the terminal widget return (
@@ -1124,8 +1164,8 @@ export class Player extends React.Component {
+
- {error}