cleaned up some mess and started the actual compressor
This commit is contained in:
33
lib/ast.js
33
lib/ast.js
@@ -35,6 +35,9 @@ var AST_Token = DEFNODE("Token", "type value line col pos endpos nlb comments_be
|
|||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
var AST_Node = DEFNODE("Node", "start end", {
|
var AST_Node = DEFNODE("Node", "start end", {
|
||||||
|
clone: function() {
|
||||||
|
return new this.CTOR(this);
|
||||||
|
},
|
||||||
$documentation: "Base class of all AST nodes",
|
$documentation: "Base class of all AST nodes",
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this);
|
return visitor._visit(this);
|
||||||
@@ -44,8 +47,9 @@ var AST_Node = DEFNODE("Node", "start end", {
|
|||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
AST_Node.warn_function = noop;
|
AST_Node.warn_function = null;
|
||||||
AST_Node.warn = function(txt, props) {
|
AST_Node.warn = function(txt, props) {
|
||||||
|
if (AST_Node.warn_function)
|
||||||
AST_Node.warn_function(string_template(txt, props));
|
AST_Node.warn_function(string_template(txt, props));
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -86,10 +90,9 @@ var AST_BlockStatement = DEFNODE("BlockStatement", null, {
|
|||||||
$documentation: "A block statement.",
|
$documentation: "A block statement.",
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
var a = this.body, i = 0, n = a.length;
|
this.body.forEach(function(stat){
|
||||||
while (i < n) {
|
stat._walk(visitor);
|
||||||
a[i++]._walk(visitor);
|
});
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, AST_Statement);
|
}, AST_Statement);
|
||||||
@@ -135,9 +138,8 @@ var AST_ForIn = DEFNODE("ForIn", "init name object", {
|
|||||||
$documentation: "A `for ... in` statement",
|
$documentation: "A `for ... in` statement",
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
if (this.init) this.init._walk(visitor);
|
this.init._walk(visitor);
|
||||||
else if (this.name) this.name._walk(visitor);
|
this.object._walk(visitor);
|
||||||
if (this.object) this.object._walk(visitor);
|
|
||||||
this.body._walk(visitor);
|
this.body._walk(visitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -295,7 +297,7 @@ var AST_Try = DEFNODE("Try", "btry bcatch bfinally", {
|
|||||||
// IE which simply introduces the name in the surrounding scope. If
|
// IE which simply introduces the name in the surrounding scope. If
|
||||||
// we ever want to fix this then AST_Catch should inherit from
|
// we ever want to fix this then AST_Catch should inherit from
|
||||||
// AST_Scope.
|
// AST_Scope.
|
||||||
var AST_Catch = DEFNODE("Catch", "argname", {
|
var AST_Catch = DEFNODE("Catch", "argname body", {
|
||||||
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
$documentation: "A `catch` node; only makes sense as part of a `try` statement",
|
||||||
_walk: function(visitor) {
|
_walk: function(visitor) {
|
||||||
return visitor._visit(this, function(){
|
return visitor._visit(this, function(){
|
||||||
@@ -303,11 +305,16 @@ var AST_Catch = DEFNODE("Catch", "argname", {
|
|||||||
this.body._walk(visitor);
|
this.body._walk(visitor);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}, AST_BlockStatement);
|
});
|
||||||
|
|
||||||
var AST_Finally = DEFNODE("Finally", null, {
|
var AST_Finally = DEFNODE("Finally", "body", {
|
||||||
$documentation: "A `finally` node; only makes sense as part of a `try` statement"
|
$documentation: "A `finally` node; only makes sense as part of a `try` statement",
|
||||||
}, AST_BlockStatement);
|
_walk: function(visitor) {
|
||||||
|
return visitor._visit(this, function(){
|
||||||
|
this.body._walk(visitor);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/* -----[ VAR/CONST ]----- */
|
/* -----[ VAR/CONST ]----- */
|
||||||
|
|
||||||
|
|||||||
249
lib/compress.js
Normal file
249
lib/compress.js
Normal file
@@ -0,0 +1,249 @@
|
|||||||
|
// The layout of the compressor follows the code generator (see
|
||||||
|
// output.js). Basically each node will have a "squeeze" method
|
||||||
|
// that will apply all known compression rules for that node, and
|
||||||
|
// return a new node (or the original node if there was no
|
||||||
|
// compression). We can't quite use the TreeWalker for this
|
||||||
|
// because it's too simplistic.
|
||||||
|
|
||||||
|
// The Compressor object is for storing the options and for
|
||||||
|
// maintaining various internal state that might be useful for
|
||||||
|
// squeezing nodes.
|
||||||
|
|
||||||
|
function Compressor(options) {
|
||||||
|
options = defaults(options, {
|
||||||
|
sequences : true,
|
||||||
|
dead_code : true,
|
||||||
|
keep_comps : true,
|
||||||
|
drop_debugger : true,
|
||||||
|
unsafe : true
|
||||||
|
});
|
||||||
|
var stack = [];
|
||||||
|
return {
|
||||||
|
option : function(key) { return options[key] },
|
||||||
|
push_node : function(node) { stack.push(node) },
|
||||||
|
pop_node : function() { return stack.pop() },
|
||||||
|
stack : function() { return stack },
|
||||||
|
parent : function(n) {
|
||||||
|
return stack[stack.length - 2 - (n || 0)];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
AST_Node.DEFMETHOD("squeeze", function(){
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
|
||||||
|
AST_Token.DEFMETHOD("squeeze", function(){
|
||||||
|
return this;
|
||||||
|
});
|
||||||
|
|
||||||
|
function SQUEEZE(nodetype, squeeze) {
|
||||||
|
nodetype.DEFMETHOD("squeeze", function(compressor){
|
||||||
|
compressor.push_node(this);
|
||||||
|
var new_node = squeeze(this, compressor);
|
||||||
|
compressor.pop_node();
|
||||||
|
return new_node || this;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
function do_list(array, compressor) {
|
||||||
|
return MAP(array, function(node){
|
||||||
|
if (node instanceof Array) {
|
||||||
|
sys.debug(node.map(function(node){
|
||||||
|
return node.TYPE;
|
||||||
|
}).join("\n"));
|
||||||
|
}
|
||||||
|
return node.squeeze(compressor);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SQUEEZE(AST_Debugger, function(self, compressor){
|
||||||
|
if (compressor.option("drop_debugger"))
|
||||||
|
return new AST_EmptyStatement(self);
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_LabeledStatement, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.statement = self.statement.squeeze(compressor);
|
||||||
|
return self.label.references.length == 0 ? self.statement : self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Statement, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.body = do_list(self.body, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_EmptyStatement, function(self, compressor){
|
||||||
|
if (compressor.parent() instanceof AST_BlockStatement)
|
||||||
|
return MAP.skip;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_DWLoop, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.condition = self.condition.squeeze(compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_For, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
if (self.init) self.init = self.init.squeeze(compressor);
|
||||||
|
if (self.condition) self.condition = self.condition.squeeze(compressor);
|
||||||
|
if (self.step) self.step = self.step.squeeze(compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_ForIn, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.init = self.init.squeeze(compressor);
|
||||||
|
self.object = self.object.squeeze(compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_With, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Exit, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
if (self.value) self.value = self.value.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_LoopControl, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
if (self.label) self.label = self.label.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_If, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.condition = self.condition.squeeze(compressor);
|
||||||
|
self.consequent = self.consequent.squeeze(compressor);
|
||||||
|
if (self.alternative)
|
||||||
|
self.alternative = self.alternative.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Switch, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Case, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
self.body = do_list(self.body, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Try, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.btry = self.btry.squeeze(compressor);
|
||||||
|
if (self.bcatch) self.bcatch = self.bcatch.squeeze(compressor);
|
||||||
|
if (self.bfinally) self.bfinally = self.bfinally.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Definitions, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.definitions = do_list(self.definitions, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_VarDef, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
if (self.value) self.value = self.value.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Lambda, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
if (self.name) self.name = self.name.squeeze(compressor);
|
||||||
|
self.argnames = do_list(self.argnames, compressor);
|
||||||
|
self.body = self.body.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Call, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
self.args = do_list(self.args, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Seq, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.first = self.first.squeeze(compressor);
|
||||||
|
self.second = self.second.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Dot, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Sub, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
self.property = self.property.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Unary, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.expression = self.expression.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Binary, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.left = self.left.squeeze(compressor);
|
||||||
|
self.right = self.right.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Conditional, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.condition = self.condition.squeeze(compressor);
|
||||||
|
self.consequent = self.consequent.squeeze(compressor);
|
||||||
|
self.alternative = self.alternative.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Array, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.elements = do_list(self.elements, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_Object, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.properties = do_list(self.properties, compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
SQUEEZE(AST_ObjectProperty, function(self, compressor){
|
||||||
|
self = self.clone();
|
||||||
|
self.value = self.value.squeeze(compressor);
|
||||||
|
return self;
|
||||||
|
});
|
||||||
|
|
||||||
|
})();
|
||||||
@@ -444,11 +444,7 @@ function OutputStream(options) {
|
|||||||
output.print("for");
|
output.print("for");
|
||||||
output.space();
|
output.space();
|
||||||
output.with_parens(function(){
|
output.with_parens(function(){
|
||||||
if (self.init) {
|
|
||||||
self.init.print(output);
|
self.init.print(output);
|
||||||
} else {
|
|
||||||
self.name.print(output);
|
|
||||||
}
|
|
||||||
output.space();
|
output.space();
|
||||||
output.print("in");
|
output.print("in");
|
||||||
output.space();
|
output.space();
|
||||||
|
|||||||
35
lib/parse.js
35
lib/parse.js
@@ -746,7 +746,7 @@ function parse($TEXT, exigent_mode) {
|
|||||||
case "punc":
|
case "punc":
|
||||||
switch (S.token.value) {
|
switch (S.token.value) {
|
||||||
case "{":
|
case "{":
|
||||||
return new AST_BlockStatement({ body: block_() });
|
return block_();
|
||||||
case "[":
|
case "[":
|
||||||
case "(":
|
case "(":
|
||||||
return simple_statement();
|
return simple_statement();
|
||||||
@@ -942,7 +942,7 @@ function parse($TEXT, exigent_mode) {
|
|||||||
--S.in_function;
|
--S.in_function;
|
||||||
S.in_loop = loop;
|
S.in_loop = loop;
|
||||||
S.labels = labels;
|
S.labels = labels;
|
||||||
return new AST_BlockStatement({ body: a });
|
return a;
|
||||||
})()
|
})()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -961,19 +961,25 @@ function parse($TEXT, exigent_mode) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function block_() {
|
function block_() {
|
||||||
|
var start = S.token;
|
||||||
expect("{");
|
expect("{");
|
||||||
var a = [];
|
var a = [];
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) unexpected();
|
if (is("eof")) unexpected();
|
||||||
a.push(statement());
|
a.push(statement());
|
||||||
}
|
}
|
||||||
|
var end = S.token;
|
||||||
next();
|
next();
|
||||||
return a;
|
return new AST_BlockStatement({
|
||||||
|
start : start,
|
||||||
|
body : a,
|
||||||
|
end : end
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
var switch_block_ = embed_tokens(curry(in_loop, function(){
|
var switch_block_ = embed_tokens(curry(in_loop, function(){
|
||||||
expect("{");
|
expect("{");
|
||||||
var a = [], cur = null, branch = null;
|
var a = [], cur = null, branch = null, start = S.token;
|
||||||
while (!is("punc", "}")) {
|
while (!is("punc", "}")) {
|
||||||
if (is("eof")) unexpected();
|
if (is("eof")) unexpected();
|
||||||
if (is("keyword", "case")) {
|
if (is("keyword", "case")) {
|
||||||
@@ -1002,16 +1008,17 @@ function parse($TEXT, exigent_mode) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (branch) branch.end = prev();
|
if (branch) branch.end = prev();
|
||||||
|
var end = S.token;
|
||||||
next();
|
next();
|
||||||
return new AST_SwitchBlock({ body: a });
|
return new AST_SwitchBlock({
|
||||||
|
start : start,
|
||||||
|
body : a,
|
||||||
|
end : end
|
||||||
|
});
|
||||||
}));
|
}));
|
||||||
|
|
||||||
function try_() {
|
function try_() {
|
||||||
var body = new AST_BlockStatement({
|
var body = block_(), bcatch = null, bfinally = null;
|
||||||
start : S.token,
|
|
||||||
body : block_(),
|
|
||||||
end : prev()
|
|
||||||
}), bcatch = null, bfinally = null;
|
|
||||||
if (is("keyword", "catch")) {
|
if (is("keyword", "catch")) {
|
||||||
var start = S.token;
|
var start = S.token;
|
||||||
next();
|
next();
|
||||||
@@ -1021,12 +1028,8 @@ function parse($TEXT, exigent_mode) {
|
|||||||
bcatch = new AST_Catch({
|
bcatch = new AST_Catch({
|
||||||
start : start,
|
start : start,
|
||||||
argname : name,
|
argname : name,
|
||||||
body : new AST_BlockStatement({
|
|
||||||
start : S.token,
|
|
||||||
body : block_(),
|
body : block_(),
|
||||||
end : prev()
|
end : prev()
|
||||||
}),
|
|
||||||
end : prev()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (is("keyword", "finally")) {
|
if (is("keyword", "finally")) {
|
||||||
@@ -1034,12 +1037,8 @@ function parse($TEXT, exigent_mode) {
|
|||||||
next();
|
next();
|
||||||
bfinally = new AST_Finally({
|
bfinally = new AST_Finally({
|
||||||
start : start,
|
start : start,
|
||||||
body : new AST_BlockStatement({
|
|
||||||
start : S.token,
|
|
||||||
body : block_(),
|
body : block_(),
|
||||||
end : prev()
|
end : prev()
|
||||||
}),
|
|
||||||
end : prev()
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (!bcatch && !bfinally)
|
if (!bcatch && !bfinally)
|
||||||
|
|||||||
25
lib/scope.js
25
lib/scope.js
@@ -138,20 +138,25 @@ AST_Toplevel.DEFMETHOD("scope_warnings", function(options){
|
|||||||
col: node.start.col
|
col: node.start.col
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (options.assign_to_global
|
if (options.assign_to_global)
|
||||||
&& node instanceof AST_Assign
|
|
||||||
&& node.left instanceof AST_SymbolRef
|
|
||||||
&& (node.left.undeclared
|
|
||||||
|| (node.left.symbol.global
|
|
||||||
&& node.left.scope !== node.left.symbol.scope)))
|
|
||||||
{
|
{
|
||||||
|
var sym = null;
|
||||||
|
if (node instanceof AST_Assign && node.left instanceof AST_SymbolRef)
|
||||||
|
sym = node.left;
|
||||||
|
else if (node instanceof AST_ForIn && node.init instanceof AST_SymbolRef)
|
||||||
|
sym = node.init;
|
||||||
|
if (sym
|
||||||
|
&& (sym.undeclared
|
||||||
|
|| (sym.symbol.global
|
||||||
|
&& sym.scope !== sym.symbol.scope))) {
|
||||||
AST_Node.warn("{msg}: {name} [{line},{col}]", {
|
AST_Node.warn("{msg}: {name} [{line},{col}]", {
|
||||||
msg: node.left.undeclared ? "Accidental global?" : "Assignment to global",
|
msg: sym.undeclared ? "Accidental global?" : "Assignment to global",
|
||||||
name: node.left.name,
|
name: sym.name,
|
||||||
line: node.start.line,
|
line: sym.start.line,
|
||||||
col: node.start.col
|
col: sym.start.col
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (options.eval
|
if (options.eval
|
||||||
&& node instanceof AST_SymbolRef
|
&& node instanceof AST_SymbolRef
|
||||||
&& node.undeclared
|
&& node.undeclared
|
||||||
|
|||||||
@@ -18,6 +18,11 @@ time_it("scope", function(){
|
|||||||
time_it("mangle", function(){
|
time_it("mangle", function(){
|
||||||
ast.mangle_names();
|
ast.mangle_names();
|
||||||
});
|
});
|
||||||
|
time_it("compress", function(){
|
||||||
|
var compressor = new UglifyJS.Compressor({
|
||||||
|
});
|
||||||
|
ast = ast.squeeze(compressor);
|
||||||
|
});
|
||||||
time_it("generate", function(){
|
time_it("generate", function(){
|
||||||
ast.print(stream);
|
ast.print(stream);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ var vm = require("vm");
|
|||||||
var sys = require("util");
|
var sys = require("util");
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
var UglifyJS = vm.createContext({});
|
var UglifyJS = vm.createContext({
|
||||||
|
sys: sys
|
||||||
|
});
|
||||||
|
|
||||||
function load_global(file) {
|
function load_global(file) {
|
||||||
file = path.resolve(path.dirname(module.filename), file);
|
file = path.resolve(path.dirname(module.filename), file);
|
||||||
|
|||||||
Reference in New Issue
Block a user