554 lines
18 KiB
JavaScript
554 lines
18 KiB
JavaScript
var Contextify = require('../lib/contextify.js');
|
|
|
|
exports['basic tests'] = {
|
|
// Creating a context shouldn't fail.
|
|
'blank context' : function (test) {
|
|
var ctx = Contextify({});
|
|
test.notEqual(ctx, null);
|
|
test.notEqual(ctx, undefined);
|
|
test.done();
|
|
},
|
|
|
|
// Creating a context with sandbox shouldn't change existing sandbox
|
|
// properties.
|
|
'basic context' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
test.equal(sandbox.prop1, 'prop1');
|
|
test.equal(sandbox.prop2, 'prop2');
|
|
test.done();
|
|
},
|
|
|
|
'basic createContext' : function (test) {
|
|
var sandbox = {
|
|
prop1: 'prop1',
|
|
prop2: 'prop2'
|
|
};
|
|
var context = Contextify.createContext(sandbox);
|
|
test.equal(sandbox.prop1, 'prop1');
|
|
test.equal(sandbox.prop2, 'prop2');
|
|
test.done();
|
|
},
|
|
|
|
// Ensure that the correct properties exist on a wrapped sandbox.
|
|
'test contextified object extra properties' : function (test) {
|
|
var sandbox = Contextify({});
|
|
test.notEqual(sandbox.run, undefined);
|
|
test.notEqual(sandbox.getGlobal, undefined);
|
|
test.notEqual(sandbox.dispose, undefined);
|
|
test.done();
|
|
},
|
|
|
|
'createContext should not modify the sandbox' : function (test) {
|
|
var sandbox = {};
|
|
Contextify.createContext(sandbox);
|
|
test.equal(sandbox.run, undefined);
|
|
test.equal(sandbox.getGlobal, undefined);
|
|
test.equal(sandbox.dispose, undefined);
|
|
test.done();
|
|
},
|
|
|
|
// Passing undefined should create an empty context.
|
|
'test undefined sandbox' : function (test) {
|
|
// Should return an empty object.
|
|
test.notEqual(Contextify(undefined, undefined), undefined);
|
|
test.notEqual(Contextify(), undefined);
|
|
test.done();
|
|
},
|
|
|
|
'sandbox prototype properties should be searched' : function (test) {
|
|
var sandbox = {};
|
|
sandbox.__proto__ = {
|
|
prop1 : 'test'
|
|
};
|
|
Contextify(sandbox);
|
|
test.equal(sandbox.getGlobal().prop1, 'test');
|
|
test.done();
|
|
},
|
|
|
|
// Make sure properties that aren't there...aren't there.
|
|
'test for nonexistent properties' : function (test) {
|
|
var global = Contextify({}).getGlobal();
|
|
test.equal(global.test1, undefined);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure properties with value "undefined" are there.
|
|
'test for "undefined" properties' : function (test) {
|
|
var sandbox = { x: undefined };
|
|
Contextify(sandbox);
|
|
sandbox.run("_x = x");
|
|
test.equal(sandbox._x, undefined);
|
|
test.done();
|
|
},
|
|
|
|
'test for "undefined" properties with createContext' : function (test) {
|
|
var sandbox = { x: undefined };
|
|
var context = Contextify.createContext(sandbox);
|
|
context.run("_x = x");
|
|
test.equal(sandbox._x, undefined);
|
|
test.done();
|
|
},
|
|
|
|
'test for "undefined" variables' : function (test) {
|
|
var sandbox = { };
|
|
Contextify(sandbox);
|
|
// In JavaScript a declared variable is set to 'undefined'.
|
|
sandbox.run("var y; (function() { var _y ; y = _y })()");
|
|
test.equal(sandbox._y, undefined);
|
|
// This should apply to top-level variables (global properties).
|
|
sandbox.run("var z; _z = z");
|
|
test.equal(sandbox._z, undefined);
|
|
// Make sure nothing wacky happens when accessing global declared but
|
|
// undefined variables.
|
|
test.equal(sandbox.getGlobal().z, undefined);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure run can be called with a filename parameter.
|
|
'test run with filename' : function (test) {
|
|
var sandbox = Contextify();
|
|
sandbox.run('var x = 3', "test.js");
|
|
test.equal(sandbox.x, 3);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure run can be called on a context
|
|
'test run with createContext' : function (test) {
|
|
var sandbox = {};
|
|
var context = Contextify.createContext(sandbox);
|
|
context.run('var x = 3', "test.js");
|
|
test.equal(sandbox.x, 3);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure getters/setters on the sandbox object are used.
|
|
'test accessors on sandbox' : function (test) {
|
|
var sandbox = {};
|
|
sandbox.__defineGetter__('test', function () { return 3;});
|
|
sandbox.__defineSetter__('test2', function (val) { this.x = val;});
|
|
Contextify(sandbox);
|
|
var global = sandbox.getGlobal();
|
|
test.equal(global.test, 3);
|
|
sandbox.test2 = 5;
|
|
test.equal(sandbox.x, 5);
|
|
global.test2 = 7;
|
|
test.equal(global.x, 7);
|
|
test.equal(sandbox.x, 7);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure dispose cleans up the sandbox.
|
|
'test dispose' : function (test) {
|
|
var sandbox = Contextify();
|
|
test.notEqual(sandbox.run, undefined);
|
|
test.notEqual(sandbox.getGlobal, undefined);
|
|
test.notEqual(sandbox.dispose, undefined);
|
|
sandbox.dispose();
|
|
test.throws(function () {
|
|
sandbox.run();
|
|
}, Error);
|
|
test.throws(function () {
|
|
sandbox.getGlobal();
|
|
}, Error);
|
|
test.throws(function () {
|
|
sandbox.dispose();
|
|
}, Error);
|
|
test.done();
|
|
}
|
|
};
|
|
|
|
exports['synchronous script tests'] = {
|
|
// Synchronous context script execution:
|
|
// Ensure that global variables are put on the sandbox object.
|
|
'global variables in scripts should go on sandbox' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
sandbox.run('x = 3');
|
|
test.equal(sandbox.x, 3);
|
|
test.done();
|
|
},
|
|
|
|
// Synchronous context script execution:
|
|
// Ensure that sandbox properties can be accessed as global variables.
|
|
'sandbox properties should be globals' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
sandbox.run("test1 = (prop1 == 'prop1');" +
|
|
"test2 = (prop2 == 'prop2');");
|
|
test.ok(sandbox.test1);
|
|
test.ok(sandbox.test2);
|
|
test.done();
|
|
}
|
|
};
|
|
|
|
exports['asynchronous script tests'] = {
|
|
// Asynchronous context script execution:
|
|
// Ensure that global variables are put on the sandbox object.
|
|
'global variables in scripts should go on sandbox' : function (test) {
|
|
var sandbox = {
|
|
setTimeout : setTimeout,
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
sandbox.run('setTimeout(function () {x = 3}, 0);');
|
|
test.equal(sandbox.x, undefined);
|
|
setTimeout(function () {
|
|
test.equal(sandbox.x, 3);
|
|
test.done();
|
|
}, 0);
|
|
},
|
|
|
|
// Asynchronous context script execution:
|
|
// Ensure that sandbox properties can be accessed as global variables.
|
|
'sandbox properties should be globals' : function (test) {
|
|
var sandbox = {
|
|
setTimeout : setTimeout,
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
sandbox.run("setTimeout(function () {" +
|
|
"test1 = (prop1 == 'prop1');" +
|
|
"test2 = (prop2 == 'prop2');" +
|
|
"}, 0)");
|
|
test.equal(sandbox.test1, undefined);
|
|
test.equal(sandbox.test2, undefined);
|
|
setTimeout(function () {
|
|
test.ok(sandbox.test1);
|
|
test.ok(sandbox.test2);
|
|
test.done();
|
|
}, 0);
|
|
},
|
|
|
|
// Asynchronous context script execution:
|
|
// Ensure that sandbox properties can be accessed as global variables.
|
|
'createContext: sandbox properties should be globals' : function (test) {
|
|
var sandbox = {
|
|
setTimeout : setTimeout,
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
var context = Contextify.createContext(sandbox);
|
|
context.run("setTimeout(function () {" +
|
|
"test1 = (prop1 == 'prop1');" +
|
|
"test2 = (prop2 == 'prop2');" +
|
|
"}, 0)");
|
|
test.equal(sandbox.test1, undefined);
|
|
test.equal(sandbox.test2, undefined);
|
|
setTimeout(function () {
|
|
test.ok(sandbox.test1);
|
|
test.ok(sandbox.test2);
|
|
test.done();
|
|
}, 0);
|
|
}
|
|
};
|
|
|
|
exports['test global'] = {
|
|
// Make sure getGlobal() works.
|
|
'basic test' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
Contextify(sandbox);
|
|
var global = sandbox.getGlobal();
|
|
test.notDeepEqual(global, null);
|
|
test.notDeepEqual(global, undefined);
|
|
// Make sure global is forwarding properly.
|
|
test.equal(global.prop1, 'prop1');
|
|
test.equal(global.prop2, 'prop2');
|
|
global.prop3 = 'prop3';
|
|
test.equal(sandbox.prop3, 'prop3');
|
|
test.done();
|
|
},
|
|
|
|
// Make sure that references to the global are correct.
|
|
'self references to the global object' : function (test) {
|
|
var sandbox = Contextify({});
|
|
var global = sandbox.getGlobal();
|
|
sandbox.ref1 = global;
|
|
sandbox.ref2 = {
|
|
ref2 : global
|
|
};
|
|
sandbox.run("test1 = (this == ref1);" +
|
|
"test2 = (this == ref2.ref2);");
|
|
test.ok(sandbox.test1);
|
|
test.ok(sandbox.test2);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure the enumerator is enumerating correctly.
|
|
'test enumerator' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
var global = Contextify(sandbox).getGlobal();
|
|
var globalProps = Object.keys(global);
|
|
test.equal(globalProps.length, 5);
|
|
test.ok(globalProps.indexOf('prop1') != -1);
|
|
test.ok(globalProps.indexOf('prop2') != -1);
|
|
test.ok(globalProps.indexOf('run') != -1);
|
|
test.ok(globalProps.indexOf('getGlobal') != -1);
|
|
test.ok(globalProps.indexOf('dispose') != -1);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure deleter is working.
|
|
'test deleter' : function (test) {
|
|
var sandbox = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
var global = Contextify(sandbox).getGlobal();
|
|
test.equal(Object.keys(global).length, 5);
|
|
test.equal(Object.keys(sandbox).length, 5);
|
|
delete global.prop1;
|
|
test.equal(Object.keys(global).length, 4);
|
|
test.equal(Object.keys(sandbox).length, 4);
|
|
delete global.prop2;
|
|
test.equal(Object.keys(global).length, 3);
|
|
test.equal(Object.keys(sandbox).length, 3);
|
|
delete global.run;
|
|
test.equal(Object.keys(global).length, 2);
|
|
test.equal(Object.keys(sandbox).length, 2);
|
|
delete global.getGlobal;
|
|
test.equal(Object.keys(global).length, 1);
|
|
test.equal(Object.keys(sandbox).length, 1);
|
|
delete global.dispose;
|
|
test.equal(Object.keys(global).length, 0);
|
|
test.equal(Object.keys(sandbox).length, 0);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure the global's class name is the same as the sandbox.
|
|
'test global class name' : function (test) {
|
|
function DOMWindow () {};
|
|
var sandbox = Contextify(new DOMWindow());
|
|
var global = sandbox.getGlobal();
|
|
test.equal(sandbox.constructor.name, 'DOMWindow');
|
|
test.equal(sandbox.constructor.name, global.constructor.name);
|
|
sandbox.run('thisName = this.constructor.name');
|
|
test.equal(sandbox.thisName, sandbox.constructor.name);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure functions in global scope are accessible through global.
|
|
'test global functions' : function (test) {
|
|
var sandbox = Contextify();
|
|
var global = sandbox.getGlobal();
|
|
sandbox.run("function testing () {}");
|
|
test.notEqual(global.testing, undefined);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure global can be a receiver for run().
|
|
'test global.run()' : function (test) {
|
|
var global = Contextify().getGlobal();
|
|
global.run("x = 5");
|
|
test.equal(global.x, 5);
|
|
test.done();
|
|
},
|
|
|
|
// Make sure global can be a receiver for getGlobal().
|
|
'test global.getGlobal()' : function (test) {
|
|
var global = Contextify().getGlobal();
|
|
test.deepEqual(global, global.getGlobal());
|
|
test.done();
|
|
},
|
|
|
|
//Make sure global can be a receiver for dispose().
|
|
'test global.dispose()' : function (test) {
|
|
var sandbox = Contextify();
|
|
var global = sandbox.getGlobal();
|
|
test.notEqual(global.run, undefined);
|
|
test.notEqual(global.getGlobal, undefined);
|
|
test.notEqual(global.dispose, undefined);
|
|
global.dispose();
|
|
// It's not safe to use the global after disposing.
|
|
test.throws(function () {
|
|
sandbox.run();
|
|
}, Error);
|
|
test.throws(function () {
|
|
sandbox.getGlobal();
|
|
}, Error);
|
|
test.throws(function () {
|
|
sandbox.dispose();
|
|
}, Error);
|
|
test.done();
|
|
}
|
|
};
|
|
|
|
|
|
// Test that multiple contexts don't interfere with each other.
|
|
exports['test multiple contexts'] = function (test) {
|
|
var sandbox1 = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
var sandbox2 = {
|
|
prop1 : 'prop1',
|
|
prop2 : 'prop2'
|
|
};
|
|
var global1 = Contextify(sandbox1).getGlobal();
|
|
var global2 = Contextify(sandbox2).getGlobal();
|
|
test.equal(global1.prop1, 'prop1');
|
|
test.equal(global2.prop1, 'prop1');
|
|
sandbox1.run('test = 3');
|
|
sandbox2.run('test = 4');
|
|
test.equal(sandbox1.test, 3);
|
|
test.equal(global1.test, 3);
|
|
test.equal(sandbox2.test, 4);
|
|
test.equal(global2.test, 4);
|
|
test.done();
|
|
};
|
|
|
|
// Test console - segfaults in REPL.
|
|
exports['test console'] = function (test) {
|
|
var sandbox = {
|
|
console : console,
|
|
prop1 : 'prop1'
|
|
};
|
|
Contextify(sandbox);
|
|
test.doesNotThrow(function () {
|
|
sandbox.run('console.log(prop1);');
|
|
});
|
|
test.done();
|
|
};
|
|
|
|
|
|
// Test eval scope.
|
|
exports['test eval'] = {
|
|
'basic test' : function (test) {
|
|
var sandbox = Contextify();
|
|
sandbox.run('eval("test1 = 1")');
|
|
test.equal(sandbox.test1, 1);
|
|
sandbox.run('(function() { eval("test2 = 2") })()');
|
|
test.equal(sandbox.test2, 2);
|
|
test.done();
|
|
},
|
|
|
|
'this test' : function (test) {
|
|
var sandbox = Contextify();
|
|
sandbox.run('e = eval ; e("test1 = 1")');
|
|
test.equal(sandbox.test1, 1);
|
|
sandbox.run('var t = 1 ; (function() { var t = 2; test2 = eval("t") })()');
|
|
test.equal(sandbox.test2, 2);
|
|
sandbox.run('t = 1 ; (function() { var t = 2; e = eval; test3 = e("t") })()');
|
|
test.equal(sandbox.test3, 1);
|
|
sandbox.run('var t = 1 ; global = this; (function() { var t = 2; e = eval; test4 = global.eval.call(global, "t") })()');
|
|
test.equal(sandbox.test4, 1);
|
|
test.done();
|
|
}
|
|
};
|
|
|
|
|
|
// Make sure exceptions get thrown for invalid scripts.
|
|
exports['test exceptions'] = {
|
|
'basic test' : function (test) {
|
|
var sandbox = Contextify();
|
|
// Exceptions thrown from "run" will be from the Contextified context.
|
|
var ReferenceError = sandbox.run('ReferenceError');
|
|
var SyntaxError = sandbox.run('SyntaxError');
|
|
test.throws(function () {
|
|
sandbox.run('doh');
|
|
}, ReferenceError);
|
|
test.throws(function () {
|
|
sandbox.run('x = y');
|
|
}, ReferenceError);
|
|
test.throws(function () {
|
|
sandbox.run('function ( { (( }{);');
|
|
}, SyntaxError);
|
|
test.done();
|
|
},
|
|
|
|
'test double dispose() - sandbox' : function (test) {
|
|
var sandbox = Contextify();
|
|
test.doesNotThrow(function () {
|
|
sandbox.dispose();
|
|
});
|
|
test.throws(function () {
|
|
sandbox.dispose();
|
|
}, 'Called dispose() twice.');
|
|
test.done();
|
|
},
|
|
|
|
'test double dispose - global' : function (test) {
|
|
var sandbox = Contextify();
|
|
var global = sandbox.getGlobal();
|
|
test.doesNotThrow(function () {
|
|
global.dispose();
|
|
});
|
|
test.throws(function () {
|
|
global.dispose();
|
|
}, 'Called dispose() twice.');
|
|
test.done();
|
|
},
|
|
|
|
'test run() after dispose()' : function (test) {
|
|
var sandbox = Contextify();
|
|
test.doesNotThrow(function () {
|
|
sandbox.dispose();
|
|
});
|
|
test.throws(function () {
|
|
sandbox.run('var x = 3');
|
|
}, 'Called run() after dispose().');
|
|
test.done();
|
|
},
|
|
|
|
'test getGlobal() after dispose()' : function (test) {
|
|
var sandbox = Contextify();
|
|
test.doesNotThrow(function () {
|
|
sandbox.dispose();
|
|
});
|
|
test.throws(function () {
|
|
var g = sandbox.getGlobal();
|
|
}, 'Called getGlobal() after dispose().');
|
|
test.done();
|
|
}
|
|
};
|
|
|
|
exports['test scripts'] = {
|
|
'test createScript()' : function (test) {
|
|
var script = Contextify.createScript('var x = 3', 'test.js');
|
|
test.equal(typeof script.runInContext, 'function');
|
|
test.done();
|
|
},
|
|
|
|
'test createScript() without code' : function (test) {
|
|
test.throws(function () {
|
|
Contextify.createScript();
|
|
});
|
|
test.throws(function () {
|
|
Contextify.createScript(true);
|
|
});
|
|
test.throws(function () {
|
|
Contextify.createScript(null);
|
|
});
|
|
test.throws(function () {
|
|
Contextify.createScript(1);
|
|
});
|
|
test.done();
|
|
},
|
|
|
|
'test runInContext' : function (test) {
|
|
var sandbox = {};
|
|
var script = Contextify.createScript('var x = 3', 'test.js');
|
|
var context = Contextify.createContext(sandbox);
|
|
script.runInContext(context);
|
|
test.equal(sandbox.x, 3);
|
|
test.done();
|
|
}
|
|
};
|