Releasing Arbiter, v1
EDIT — updated this blog post with a new version of Arbiter, called “Arbiter-frame”, that uses Mithril and communication with an iframe. Logging and error output is still possible, however, now Arbiter can be used to prototype code that interacts with the DOM.
It’s also faster… both to load and when running.
setInterval(log.bind(null, 1), 0)
The above code makes Chrome use %110 CPU in Arbiter, while Arbiter-frame hovers around %70. :-)


So I have been trying to build a dynamic code analysis tool (as demonstrated by Bret Victor’s “inventing on principle” talk) that lets me “spy” on variable values and denote them in the interface.
This is HIGHLY valuable in educational environments, or for just throwing around ideas. Either way, I knew I really wanted something like this.
My pursuit has unequivocally led me down a rabbit hole these past few days, including but — not limited to —
- tweaking Web Workers and message passing (edit: tweaking iframes and message passing between parent/child frames)
- creating functions with…
new Function("...")…which feels awfully weird.
- using ES6 generators to implement data channels
- using ES7 decorators to augment React Components
- using React to drive the interface
- using functional methods, data pipelining, and transducers to process AST (Abstract Syntax Tree) nodes
- creating my own collection of functional methods
const clone = (data) => typeof data === ‘undefined’ ? data : JSON.parse(JSON.stringify(data))
const concat = (arr, x) => arr.concat([x])
const compose = (f, g) => (x) => f(g(x))
const each = (c, cb) => c.forEach(cb)
const c = compose
const map = (c, transform) => c.map(transform)
const reduce = (c, reducer, initial) => c.reduce(reducer, initial)
const filter = (c, pred) => c.filter(pred)
const ident = (x) => x
const until = (c, pred, hasBeenReached = false) =>
c.reduce((a, v) => {
!hasBeenReached && !(hasBeenReached = pred(v)) && a.push(v)
return a
}, [])
const last = (c) => c[c.length > 1 ? c.length-1 : 0]
const head = (c) => c[0]
const rest = (c) => c.slice(1)
const find = (c, pred) => {
for(var i = 0, len = c.length; i < len; i++) {
let r = c[i]
if(pred(r)) return r
}
return null
}
const concatAll = (cc) => [].concat(…cc)
const ignores = (c, ignore) => filter(c, (x) => ignore.indexOf(x) === -1)
- using babel-core — loaded via Browserify into the browser using stage 1 mode (meaning the Babel runtime, and most ES6 methods, ES7 decorators and async functions are available) — to transpile code on the fly to ES5
While my search continues to enable live “spying” on variable values over time and space, atleast I can release this tool for y’all (hey, I’m from Texas ^_^).
I’ve even added the ability for Arbiter to show the contents of and stack trace of Errors (be it syntax or runtime errors).
















On top of that, pressing CMD+S (Windows users should hit the WIN+S) will give you a Google URL Shortener linking to your code, so you can share code examples quickly and easily.


Link to Arbiter: http://matthiasak.github.io/arbiter-frame/dist/
Features:
- pretty-printed and formatted code using the CodeMirror editor
- focus on simplicity and instantaneous feedback as you type
- errors and the feedback loop to the developer is near-instantaneous
- all JS is compiled by Babel-core in the browser, including the regenerator runtime, so that you can use async functions, generators, and all the latest magic
- code is run in a web-worker, so while coding you can quickly see the result of what you are typing
- share code examples with students or colleagues immediately with CMD+S (WIN+S)
Enjoy, and let me know what you think.