Skip to content

Instantly share code, notes, and snippets.

@ixti
Created April 30, 2011 23:51
Show Gist options
  • Save ixti/950107 to your computer and use it in GitHub Desktop.
Save ixti/950107 to your computer and use it in GitHub Desktop.
Node.JS vm's global sandbox bug (although they call it feature)...
// Let's extend prototype of Object with something like delete in ruby, but
// we'll call it grab (just to avoid keyword name collision)
Object.prototype.grab = function grab(key) {
var val = this[key];
delete(this[key]);
return val;
};
test.js, Object.prototype.grab: function
test.js, {}.grab: function
test.js, outter.grab: function
---
script-1.js, Object.prototype.grab: undefined
script-1.js, {}.grab: undefined
script-1.js, outter.grab: function
script-2.js, Object.prototype.grab: undefined
script-2.js, {}.grab: undefined
script-2.js, outter.grab: function
---
script-1.js, Object.prototype.grab: function
script-1.js, {}.grab: undefined
script-1.js, outter.grab: function
script-2.js, Object.prototype.grab: function
script-2.js, {}.grab: undefined
script-2.js, outter.grab: function
---
script-1.js, Object.prototype.grab: function
script-1.js, {}.grab: undefined
script-1.js, outter.grab: function
script-2.js, Object.prototype.grab: function
script-2.js, {}.grab: undefined
script-2.js, outter.grab: function
console.log('script-1.js, Object.prototype.grab: ' + typeof Object.prototype.grab);
console.log('script-1.js, {}.grab: ' + typeof {}.grab);
console.log('script-1.js, outter.grab: ' + typeof outter.grab);
// this is predictably works exatly as script-1, just because require is in the
// different fork (i guess), so calling require here calls it in fact in scope
// of main script, but not here.
require('./extension.js');
console.log('script-2.js, Object.prototype.grab: ' + typeof Object.prototype.grab);
console.log('script-2.js, {}.grab: ' + typeof {}.grab);
console.log('script-2.js, outter.grab: ' + typeof outter.grab);
var fs = require('fs'),
vm = require('vm');
// require our extensions
require('./extension.js');
// our humble Object instance
var outter = {};
// sandbox for the runner
var sandbox = {require: require, console: console, outter: outter};
function RunForestRun(filename) {
var content = fs.readFileSync(filename, 'utf8');
vm.runInNewContext(content, sandbox);
}
function RunLolaRun(filename) {
var content = fs.readFileSync(filename, 'utf8');
vm.runInNewContext(content, sandbox);
}
// check what we have here to be sure our object was extended
console.log('test.js, Object.prototype.grab: ' + typeof Object.prototype.grab);
console.log('test.js, {}.grab: ' + typeof {}.grab);
console.log('test.js, outter.grab: ' + typeof outter.grab);
// ready, steady, go, i feel dumb
console.log('---');
RunForestRun('./script-1.js');
RunForestRun('./script-2.js');
// and now, the most interesting thing: we can expose our extended object,
// so it will have correct prototype inside script files, BUT, instances will
// not be created with that prototype
sandbox.Object = Object;
console.log('---');
RunForestRun('./script-1.js');
RunForestRun('./script-2.js');
console.log('---');
RunLolaRun('./script-1.js');
RunLolaRun('./script-2.js');
////////////////////////////////////////////////////////////////////////////////
// vim:ts=2:sw=2
////////////////////////////////////////////////////////////////////////////////
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment