Last active
January 9, 2021 16:09
-
-
Save jlongster/6374643 to your computer and use it in GitHub Desktop.
very basic CSP in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var fs = require('fs'); | |
// machine | |
function go_(machine, step) { | |
while(!step.done) { | |
var arr = step.value(); | |
var state = arr[0]; | |
var value = arr[1]; | |
switch (state) { | |
case "park": | |
setImmediate(function() { go_(machine, step); }); | |
return; | |
case "continue": | |
if(value instanceof Error) { | |
step = machine.throw(value); | |
} | |
else { | |
step = machine.next(value); | |
} | |
break; | |
} | |
} | |
} | |
var id = 0; | |
function go(machine) { | |
var gen = machine(); | |
gen.id = 'machine' + id++; | |
go_(gen, gen.next()); | |
} | |
function put(chan, val) { | |
return function() { | |
if(chan.length == 0) { | |
chan.unshift(val); | |
return ["continue", null]; | |
} else { | |
return ["park", null]; | |
} | |
}; | |
} | |
function take(chan) { | |
return function() { | |
if(chan.length == 0) { | |
return ["park", null]; | |
} else { | |
var val = chan.pop(); | |
return ["continue", val]; | |
} | |
}; | |
} | |
function chan() { | |
return []; | |
} | |
// signal an error on a channel. This probably needs to look more like | |
// `put`, instead of eagerly putting it on. | |
function error(chan, err) { | |
if(!(err instanceof Error)) { | |
err = new Error(err); | |
} | |
chan.push(err); | |
} | |
function timeout(ms) { | |
var c = chan(); | |
setTimeout(function() { | |
go(function*() { | |
yield put(c, true); | |
}); | |
}, ms); | |
return c; | |
} | |
// forward all values from one channel to another, also does error | |
// propagation | |
function forward(chan1, chan2) { | |
go(function*() { | |
try { | |
while(1) { | |
yield put(chan2, yield take(chan1)); | |
} | |
} | |
catch(e) { | |
error(chan2, e); | |
} | |
}); | |
} | |
// native wrappers | |
function readFile(path, enc, errorHandler) { | |
var c = chan(); | |
fs.readFile(path, enc, function(err, res) { | |
go(function*() { | |
if(err) { return error(c, err); } | |
yield put(c, res); | |
}); | |
}); | |
return c; | |
}; | |
// testing code | |
function foo(path) { | |
var c = chan(); | |
go(function*() { | |
yield take(timeout(1000)); | |
forward(readFile(path, 'utf-8'), c); | |
}); | |
return c; | |
} | |
go(function*() { | |
try { | |
var str = yield take(foo('./main.js')); | |
console.log(str.slice(0, 20)); | |
} | |
catch(e) { | |
// errors are propagated here, even if it occurs in `readFile` | |
// within `foo` | |
} | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
ported to SpiderMonkey: https://gist.github.com/fitzgen/6393792