Sorry, but you're going to fail at this unless you build the full AST, do source-to-source translation, and insert runtime checks in a slew of places.
({}).valueOf.call(null).alert('lose');
[].sort.call(null).alert('lose')
({}.constructor.prototype.toString=function(){return "f".constructor.fromCharCode(95,95,112,97,114,101,110,116,95,95);}, y={},y[{}].alert('lose'))
I'm too lazy to come up with anything else at the moment, but this is doomed to failure the current way you're doing it. See also the stuff I wrote up and posted at [
stuff.mit.edu] regarding hacking Facebook's sandboxing mechanism for more of this kind of stuff against a far more principled (but not quite at the level of Caja) approach.