Skip to content

Instantly share code, notes, and snippets.

@gimenete
Created March 5, 2014 22:26
Show Gist options
  • Save gimenete/9377962 to your computer and use it in GitHub Desktop.
Save gimenete/9377962 to your computer and use it in GitHub Desktop.
Run less.js in a sandbox
var fs = require('fs')
var path = require('path')
var vm = require('vm')
var util = require('util')
String.prototype.endsWith = function(suffix) {
return this.indexOf(suffix, this.length - suffix.length) !== -1;
}
var basedir = path.join(__dirname, 'less_files')+path.sep
console.log('basedir', basedir)
function proxy(module) {
var obj = {}
for (var key in module) {
if (module.hasOwnProperty(key)) {
var value = module[key]
if (value instanceof Function) {
function proxyFunction(key, func) {
return function() {
var args = Array.prototype.slice.call(arguments)
console.log(key, 'called with arguments', args)
return module[key].apply(module, args)
}
}
obj[key] = proxyFunction(key, value)
}
}
}
return obj
}
var _fs = {} // proxy(fs) // proxy just while developing more proxied functions
_fs.stat = function(filename) {
if (filename.indexOf(basedir) !== 0) {
return arguments[arguments.length-1](new Error('Forbidden'))
}
return fs.stat.apply(fs, arguments)
}
_fs.readFile = function(filename) {
if (filename.indexOf(basedir) !== 0) {
return arguments[arguments.length-1](new Error('Forbidden'))
}
return fs.readFile.apply(fs, arguments)
}
var _console = {
log: function() {
console.log(util.format.apply(null, Array.prototype.slice.call(arguments)))
}
}
var modules = {}
modules['path'] = { exports: require('path') }
modules['url'] = { exports: require('url') }
modules['fs'] = { exports: _fs }
function createSandbox(dir) {
var sandbox = {}
sandbox.require = function(module) {
if (modules[module]) {
return modules[module].exports
}
var fullpath = null
if (module.indexOf('./') !== 0 && module.indexOf('../') !== 0) {
var json = JSON.parse(fs.readFileSync(path.join(dir, 'node_modules', module, 'package.json'), 'utf8'))
var main = json.main
var fullpath = path.join(dir, 'node_modules', module, main)
} else {
fullpath = path.join(dir, module)
}
if (!fullpath.endsWith('.js')) {
fullpath += '.js'
}
if (modules[fullpath]) {
return modules[fullpath].exports
}
var code = fs.readFileSync(fullpath, 'utf8')
var _sandbox = createSandbox(path.dirname(fullpath))
modules[fullpath] = _sandbox.module
vm.runInNewContext(code, _sandbox, fullpath)
return _sandbox.module.exports
}
sandbox.module = { exports: {} }
sandbox.exports = sandbox.module.exports
sandbox.console = _console
return sandbox
}
var filename = 'bootstrap.less'
var lesscode = fs.readFileSync(path.join(basedir, filename), 'utf8')
var code = "var less = require('less'); var parser = new(less.Parser)(lessoptions).parse(lesscode, completion)"
var lessoptions = {
paths: [basedir],
filename: filename
}
var completion = function(err, tree) {
if (err) {
return console.log('err', err)
}
// console.log('output', tree.toCSS({ compress: true }))
}
var sandbox = createSandbox(__dirname)
sandbox.basedir = basedir
sandbox.lesscode = lesscode
sandbox.lessoptions = lessoptions
sandbox.completion = completion
for (var i = 0; i < 100; i++) {
// sandboxed
// vm.runInNewContext(code, sandbox, 'file.js')
// native
var less = require('less'); var parser = new(less.Parser)(lessoptions).parse(lesscode, completion)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment