commando.html5/node_modules/bunker/index.js

117 lines
3.0 KiB
JavaScript

var burrito = require('burrito');
var vm = require('vm');
var EventEmitter = require('events').EventEmitter;
module.exports = function (src) {
var b = new Bunker();
if (src) b.include(src);
return b;
};
function Bunker () {
this.sources = [];
this.nodes = [];
this.names = {
call : burrito.generateName(6),
expr : burrito.generateName(6),
stat : burrito.generateName(6),
return : burrito.generateName(6)
};
}
Bunker.prototype = new EventEmitter;
Bunker.prototype.include = function (src) {
this.sources.push(src);
this.source = null;
return this;
};
Bunker.prototype.compile = function () {
var src = this.sources.join('\n');
var nodes = this.nodes;
var names = this.names;
return burrito(src, function (node) {
var i = nodes.length;
if (node.name === 'call') {
nodes.push(node);
node.wrap(names.call + '(' + i + ')(%s)');
}
else if (node.name === 'stat' || node.name === 'throw'
|| node.name === 'var') {
nodes.push(node);
node.wrap('{' + names.stat + '(' + i + ');%s}');
}
else if (node.name === 'return') {
nodes.push(node);
// We need to wrap the new source in a function definition
// so that UglifyJS will allow the presence of return
var stat = names.stat + '(' + i + ');';
var wrapped = 'function ' + names.return + '() {'
+ stat + node.source()
+'}'
;
var parsed = burrito.parse(wrapped);
// Remove the function definition from the AST
parsed[1] = parsed[1][0][3];
node.state.update(parsed, true);
}
else if (node.name === 'binary') {
nodes.push(node);
node.wrap(names.expr + '(' + i + ')(%s)');
}
else if (node.name === 'unary-postfix' || node.name === 'unary-prefix') {
nodes.push(node);
node.wrap(names.expr + '(' + i + ')(%s)');
}
if (i !== nodes.length) {
node.id = i;
}
});
};
Bunker.prototype.assign = function (context) {
if (!context) context = {};
var self = this;
var stack = [];
context[self.names.call] = function (i) {
var node = self.nodes[i];
stack.unshift(node);
self.emit('node', node, stack);
return function (expr) {
stack.shift();
return expr;
};
};
context[self.names.expr] = function (i) {
var node = self.nodes[i];
self.emit('node', node, stack);
return function (expr) {
return expr;
};
};
context[self.names.stat] = function (i) {
var node = self.nodes[i];
self.emit('node', node, stack);
};
return context;
};
Bunker.prototype.run = function (context) {
var src = this.compile();
vm.runInNewContext(src, this.assign(context));
return this;
};