Fun class declarations
======================
Here's an interesting idea for class declarations (using a JS-like language)
class Cartesian(x, y) exports getX, getY, toPolar {
var r = Math.sqrt(x * x + y * y);
var a = Math.atan(x / y);
var cachedPolar = new Polar(r, a);
function getX() {
return x;
}
function getY() {
return y;
}
function toPolar() {
return cachedPolar;
}
}
class Polar(r, a) exports getR, getA, toCartesian {
var x = r * Math.cos(a);
var y = r * Math.sin(a);
var cachedCartesian = new Cartesian(x, y);
function getR() {
return r;
}
function getA() {
return a;
}
function toCartesian() {
return cachedCartesian;
}
}
You can write any arbitrary code in the class, and then the exports get exposed from your scope to the outside. You can use it as normal: `new Polar(5, 90).toCartesian()` gives
`new Cartesian(0, 5)` as expected.
Command-line calculator
=======================
## Using a REPL
Sometimes, you just want to do some arithmetic. You could just do
node
22 / 7 // 3.142857142857143
^C
^C
to get an approximation of Pi (and it has the advantage of having constants like Math.PI), but node takes a while to start up and you have to double ^C to exit.
Not perfect. You could use Python:
python
22.0 / 7.0 # 3.142857142857143
exit()
But then, you need to say 22.0 instead of 22, and exit() instead of ^C twice. (You could also use lua, groovysh, etc). Another problem is that you can't pipe into it.
What I really want is something like:
calc "22/7" # 3.1428571428571428
echo "22/7" | calc # 3.1428571428571428
## Using a browser
Previously, I'd just been asking DuckDuckGo;
it can do some fairly complex arithmetic evaluations, as well as providing some other useful functions: [22/7](http://ddg.gg/?q=22/7),
[(1 + 1/100000)^100000](https://duckduckgo.com/?q=%281%20%2B%201%2F100000%29^100000), and things like that. Still, that's a bit clunky. I can do better.
## GNU bc
The next obvious answer is GNU bc. Example:
bc -q
2 + 2 # 4
quit
However, that still has the problem of being interactive, as well as not being able to ^C out. However, I can pipe into bc, something I couldn't do with the others.
### GNU bc + shell script
Here's a shell script that I wrote with a lot of searching the Internet (I'm not good at bash). It allows you to pipe in inputs, or give them as command line arguments.
#!/bin/bash
stdin="$(ls -l /proc/self/fd/0)"
stdin="${stdin/*-> /}"
if [[ "$stdin" =~ ^/dev/pts/[0-9] ]]; then
{ echo "scale=16"; echo $1; echo "quit"; } | bc -q
else
{ echo "scale=16"; cat /dev/stdin; echo "quit"; } | bc -q
fi
Now, the following actually works:
calc "22/7" # 3.1428571428571428
echo "22/7" | calc # 3.1428571428571428
### Using external libraries
We now have what we set out for. But, how can we find, for example, the cube root of 16?
calc "64^(1/3)" # 1, incorrect
calc "e(l(64)/3)" # 3.99999..., close enough
Although bc can calculate cube roots (as is provably possible, since it's turing complete), it's very cryptic and needs a lot of typing. How about:
calc "cbrt(64)" # 4
calc "root(64, 3)" # 4
The way one would do this is by including funcs.bc, an external library. Here's the modified script to include funcs.bc, if it is available in /home/ethan/bc/funcs.bc:
#!/bin/bash
stdin="$(ls -l /proc/self/fd/0)"
stdin="${stdin/*-> /}"
bcpath="/home/ethan/bc/funcs.bc"
if [[ "$stdin" =~ ^/dev/pts/[0-9] ]]; then
{ cat $bcpath; echo $1; echo "quit"; } | bc -q -l
else
{ cat $bcpath; cat /dev/stdin; echo "quit"; } | bc -q -l
fi
Now, the above commands (for cube roots) work.
### We can go further
What if I want to chain them? With the existing setup, the logical thing to try would be:
{ calc "root(2^32, 4)"; echo " * "; calc "2^2"; } | calc
But, this gives the following error message:
(standard_in) 721: syntax error
Let's look at it a bit more in-depth.
{ calc "root(2^32, 4)"; echo " * "; calc "2^2"; } | cat
yields
256.00000000000000000000000000000000000000000000000000
* 4
And there lies our problem: the trailing newline from calc. (Note that there's also a newline after the 4). Since newlines are often useful, I decided to add an extra
parameter to calc that goes after all of the others, which removes the trailing newline. Code:
#!/bin/bash
stdin="$(ls -l /proc/self/fd/0)"
stdin="${stdin/*-> /}"
bcpath="/home/ethan/bc/funcs.bc"
if [[ "$stdin" =~ ^/dev/pts/[0-9] ]]; then
if [[ $2 == "d" ]]; then
{ cat $bcpath; echo $1; echo ""; echo "quit"; } | bc -q -l | gawk 'BEGIN{RS="\n+";ORS=""}x{print x}x=RT'
else
{ cat $bcpath; echo $1; echo ""; echo "quit"; } | bc -q -l
fi
else
if [[ $1 == "d" ]]; then
{ cat $bcpath; cat /dev/stdin; echo ""; echo "quit"; } | bc -q -l | gawk 'BEGIN{RS="\n+";ORS=""}x{print x}x=RT'
else
{ cat $bcpath; cat /dev/stdin; echo ""; echo "quit"; } | bc -q -l
fi
fi
Now, adding a "d" after the command (i.e. calc "6 + 4" d) removes the trailing newline. Modifying our previous command with the trailing d, we now get:
{ calc "root(2^32, 4)" d; printf " * "; calc "2^2" d; } | calc
which yields
1024.00000000000000000000000000000000000000000000000000
which is what we wanted.
## Node + math.js
It might be worth investigating making a calculator with node and math.js; there's support for things like complex numbers, something bc doesn't have, and it's
more customizable (I'm using a library and my own node script, instead of passing things into the stdin of bc).
JS Sandboxes
============
What if you have untrusted JS code that you want to run on your website, without compromising its security or trust with its users (for example, can the untrusted
code make hundreds of gigabytes worth of AJAX requests?), and without, for example, writing a JS interpreter in JS itself, because that would be slow?
## WebWorkers to the rescue
I immediately thought: WebWorkers! They can't see the DOM, or really anything important, without postMessage, which I would easily be able to chech for validity
(I'd be the one implementing the postMessage handlers), and an infinite loop won't freeze the page. After some further testing, things like resource starving don't
seem to work very well (even on a single-core Virtualbox VM with 2GB of RAM).
## Disabling access to builtins
The next thing is disallowing AJAX. (I would allow it through postMessage, or possibly just my own wrapper over it, but I would limit the bandwidth, etc). I quickly
realized that disabling individual objects worked perfectly -- I could, for example, disallow access to postMessage by simply assigning it to null. But, how would I
disallow access to all objects (with a whitelist)? I could have a file that I import which would assign all of the known objects to null. But, what if a new one
appeared, say in a new browser version, that is fine on its own, but in these circumstances, undermines the security?
The obvious solution is to iterate over the self object (the WebWorker equivalent of window), and assign each to null. But, that presents its own disadvantages;
for example, you'd need to use eval, and eval is slow and bad practice.
### Arbitrary JS with loadScripts()
Instead of doing something that's bad practice, do something that's almost exactly equivalent but will cause less people to yell at you! What I ended up doing
is looping over the self object, and appending to a string. If prop is the name of the property of self, "var prop = null;" will be appended to the string. Then,
I convert the string to a data URL, and then pass that into loadScripts(). Then, the script to be sandboxed can be loaded. (Note that, for this, you have to allow
the script to run loadScripts(), which may be problematic). Alternatively, you can grab the script that you're about to load via AJAX, and then append it to the
data URL that you're loading; this is better under certain circumstances.