Skip to content

Commit

Permalink
Async error messages
Browse files Browse the repository at this point in the history
  • Loading branch information
jazz-soft committed Sep 12, 2019
1 parent 9ffb355 commit fead25a
Show file tree
Hide file tree
Showing 3 changed files with 177 additions and 75 deletions.
84 changes: 45 additions & 39 deletions javascript/JZZ.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,36 +29,23 @@
this._orig = this;
this._ready = false;
this._queue = [];
this._err = [];
this._log = [];
}
_R.prototype._exec = function() {
while (this._ready && this._queue.length) {
var x = this._queue.shift();
if (this._orig._bad) {
if (this._orig._hope && x[0] == _or) {
this._orig._hope = false;
x[0].apply(this, x[1]);
}
else if (this._orig._hope && x[0] == _then) {
x[0].apply(this, x[1]);
}
else {
this._orig._hope = false;
}
}
else if (x[0] != _or) {
x[0].apply(this, x[1]);
}
x[0].apply(this, x[1]);
}
};
_R.prototype._push = function(func, arg) { this._queue.push([func, arg]); _R.prototype._exec.apply(this); };
_R.prototype._slip = function(func, arg) { this._queue.unshift([func, arg]); };
_R.prototype._pause = function() { this._ready = false; };
_R.prototype._resume = function() { this._ready = true; _R.prototype._exec.apply(this); };
_R.prototype._break = function(err) { this._orig._bad = true; this._orig._hope = true; if (err) this._orig._err.push(err); };
_R.prototype._break = function(err) { this._orig._bad = true; this._orig._log.push(err || 'Unknown JZZ error'); };
_R.prototype._repair = function() { this._orig._bad = false; };
_R.prototype._crash = function(err) { this._break(err); this._resume(); };
_R.prototype.err = function() { return _clone(this._err); };
_R.prototype._err = function() { return this._log[this._log.length - 1]; };
_R.prototype.log = function() { return _clone(this._log); };
_R.prototype._image = function() {
var F = function() {}; F.prototype = this._orig;
var ret = new F();
Expand All @@ -75,13 +62,16 @@
};
function _then(good, bad) {
if (this._bad) {
if (bad instanceof Function) bad.apply(this, [new Error(this._err.length ? this._err[this._err.length - 1] : 'JZZ error')]);
if (bad instanceof Function) bad.apply(this, [new Error(this._err())]);
}
else {
if (good instanceof Function) good.apply(this, [this]);
}
}
function _wait(obj, delay) { setTimeout(function() { obj._resume(); }, delay); }
function _wait(obj, delay) {
if (this._bad) obj._crash(this._err());
else setTimeout(function() { obj._resume(); }, delay);
}
_R.prototype.wait = function(delay) {
if (!delay) return this;
var ret = this._image();
Expand All @@ -97,9 +87,17 @@
return ret[name].apply(ret, arg);
};
}
function _and(q) { if (q instanceof Function) q.apply(this); else console.log(q); }
function _and(q) {
if (!this._bad) {
if (q instanceof Function) q.apply(this); else console.log(q);
}
}
_R.prototype.and = function(func) { this._push(_and, [func]); return this._thenable(); };
function _or(q) { if (q instanceof Function) q.apply(this); else console.log(q); }
function _or(q) {
if (this._bad) {
if (q instanceof Function) q.apply(this); else console.log(q);
}
}
_R.prototype.or = function(func) { this._push(_or, [func]); return this._thenable(); };

_R.prototype._info = {};
Expand Down Expand Up @@ -254,7 +252,7 @@
_outsW = _jzz._info.outputs;
}
function _refresh() {
_engine._refresh(this);
if (!this._bad) _engine._refresh(this);
}
_J.prototype.refresh = function() {
this._push(_refresh, []);
Expand Down Expand Up @@ -296,14 +294,16 @@
else msg = 'Port "' + q + '" not found';
port._crash(msg);
}

function _openMidiOut(port, arg) {
var arr = _filterList(arg, _outs);
if (!arr.length) { _notFound(port, arg); return; }
var pack = function(x) { return function() { x.engine._openOut(this, x.name); }; };
for (var i = 0; i < arr.length; i++) arr[i] = pack(arr[i]);
port._slip(_tryAny, [arr]);
port._resume();
if (this._bad) port._crash(this._err());
else {
var arr = _filterList(arg, _outs);
if (!arr.length) { _notFound(port, arg); return; }
var pack = function(x) { return function() { x.engine._openOut(this, x.name); }; };
for (var i = 0; i < arr.length; i++) arr[i] = pack(arr[i]);
port._slip(_tryAny, [arr]);
port._resume();
}
}
_J.prototype.openMidiOut = function(arg) {
var port = new _M();
Expand All @@ -318,12 +318,15 @@
};

function _openMidiIn(port, arg) {
var arr = _filterList(arg, _ins);
if (!arr.length) { _notFound(port, arg); return; }
var pack = function(x) { return function() { x.engine._openIn(this, x.name); }; };
for (var i = 0; i < arr.length; i++) arr[i] = pack(arr[i]);
port._slip(_tryAny, [arr]);
port._resume();
if (this._bad) port._crash(this._err());
else {
var arr = _filterList(arg, _ins);
if (!arr.length) { _notFound(port, arg); return; }
var pack = function(x) { return function() { x.engine._openIn(this, x.name); }; };
for (var i = 0; i < arr.length; i++) arr[i] = pack(arr[i]);
port._slip(_tryAny, [arr]);
port._resume();
}
}
_J.prototype.openMidiIn = function(arg) {
var port = new _M();
Expand All @@ -338,8 +341,11 @@
};

function _onChange(watcher, arg) {
watcher._slip(_connectW, [arg]);
watcher._resume();
if (this._bad) watcher._crash();
else {
watcher._slip(_connectW, [arg]);
watcher._resume();
}
}
_J.prototype.onChange = function(arg) {
if (!this._orig._watcher) this._orig._watcher = new _W();
Expand Down Expand Up @@ -378,7 +384,7 @@
return msg;
};
_M.prototype._receive = function(msg) { this._emit(this._filter(msg)); };
function _receive(msg) { this._receive(msg); }
function _receive(msg) { if (!this._bad) this._receive(msg); }
_M.prototype.send = function() {
this._push(_receive, [MIDI.apply(null, arguments)]);
return this._thenable();
Expand Down
152 changes: 124 additions & 28 deletions test/async.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,22 @@ describe('async calls', function() {
var broke = 'We broke it!';
var notexisting = 'Not existing port';
var notfound = 'Port "Not existing port" not found';
var midi_in_name = 'Widget MIDI-In';
var midi_in_impl = {
_info: function(name) { return { name: name }; },
_openIn: function(port, name) {
port._info = this._info(name);
port._resume();
}
};
var midi_out_name = 'Widget MIDI-Out';
var midi_out_impl = {
_info: function(name) { return { name: name }; },
_openOut: function(port, name) {
port._info = this._info(name);
port._resume();
}
};

it('await JZZ()', async function() {
await JZZ();
Expand All @@ -13,7 +29,23 @@ describe('async calls', function() {
it('await JZZ() / throw', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); });
await JZZ().and(function() { this._break(); });
}
catch (err) {
msg = err.message;
JZZ()._repair();
}
assert.equal(msg, 'Unknown JZZ error');
});

it('await JZZ().or()', async function() {
await JZZ().or(function() { assert.equal(true, false); });
});

it('await JZZ().or() / throw', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).or(function() {});
}
catch (err) {
msg = err.message;
Expand All @@ -22,12 +54,28 @@ describe('async calls', function() {
assert.equal(msg, broke);
});

it('await JZZ().then(...)', async function() {
it('await JZZ().and()', async function() {
await JZZ().and(function() {});
});

it('await JZZ().and() / throw', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).and(function() {});
}
catch (err) {
msg = err.message;
JZZ()._repair();
}
assert.equal(msg, broke);
});

it('await JZZ().then()', async function() {
await JZZ().then(function() {});
await JZZ().then(undefined, function() {});
});

it('await JZZ().then(...) / throw', async function() {
it('await JZZ().then() / throw', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).then(function() {});
Expand All @@ -47,24 +95,28 @@ describe('async calls', function() {
JZZ()._repair();
});

it('await JZZ().wait(...)', async function() {
it('await JZZ().wait()', async function() {
await JZZ().wait(1);
});

it('await JZZ().openMidiIn(...)', async function() {
var name = 'Widget MIDI-In';
var widget = {
_info: function(name) { return { name: name }; },
_openIn: function(port, name) {
port._info = this._info(name);
port._resume();
}
};
JZZ.lib.registerMidiIn(name, widget);
await JZZ().openMidiIn(name);
it('await JZZ().wait() / throw', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).wait(1);
}
catch (err) {
msg = err.message;
}
assert.equal(msg, broke);
JZZ()._repair();
});

it('await JZZ().openMidiIn()', async function() {
JZZ.lib.registerMidiIn(midi_in_name, midi_in_impl);
await JZZ().openMidiIn(midi_in_name);
});

it('await JZZ().openMidiIn(...) / throw', async function() {
it('await JZZ().openMidiIn() / throw 1', async function() {
var msg;
try {
var jzz = await JZZ();
Expand All @@ -76,20 +128,24 @@ describe('async calls', function() {
assert.equal(msg, notfound);
});

it('await JZZ().openMidiOut(...)', async function() {
var name = 'Widget MIDI-Out';
var widget = {
_info: function(name) { return { name: name }; },
_openOut: function(port, name) {
port._info = this._info(name);
port._resume();
}
};
JZZ.lib.registerMidiOut(name, widget);
await JZZ().openMidiOut(name);
it('await JZZ().openMidiIn() / throw 2', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).wait(1).openMidiIn(notexisting);
}
catch (err) {
msg = err.message;
}
assert.equal(msg, broke);
JZZ()._repair();
});

it('await JZZ().openMidiOut()', async function() {
JZZ.lib.registerMidiOut(midi_out_name, midi_out_impl);
await JZZ().openMidiOut(midi_out_name);
});

it('await JZZ().openMidiOut(...) / throw', async function() {
it('await JZZ().openMidiOut() / throw 1', async function() {
var msg;
try {
var jzz = await JZZ();
Expand All @@ -101,4 +157,44 @@ describe('async calls', function() {
assert.equal(msg, notfound);
});

it('await JZZ().openMidiOut() / throw 2', async function() {
var msg;
try {
await JZZ().and(function() { this._break(broke); }).wait(1).openMidiOut(notexisting);
}
catch (err) {
msg = err.message;
}
assert.equal(msg, broke);
JZZ()._repair();
});

it('await JZZ().openMidiOut().noteOn()', async function() {
JZZ.lib.registerMidiOut(midi_out_name, midi_out_impl);
await JZZ().openMidiOut(midi_out_name).wait(1).noteOn(0, 0x40, 0x7f);
});

it('await JZZ().openMidiOut().noteOn() / throw 1', async function() {
JZZ.lib.registerMidiOut(midi_out_name, midi_out_impl);
var msg;
try {
await JZZ().openMidiOut(midi_out_name).wait(1).noteOn(0, 0xff, 0xff);
}
catch (err) {
msg = err.message;
}
assert.equal(msg, 'Bad MIDI value: 255');
});

it('await JZZ().openMidiOut().noteOn() / throw 2', async function() {
var msg;
try {
await JZZ().openMidiOut(notexisting).wait(1).noteOn(0, 0x40, 0x7f);
}
catch (err) {
msg = err.message;
}
assert.equal(msg, notfound);
});

});
Loading

0 comments on commit fead25a

Please sign in to comment.