wrote more of the compressor and added some tests
This commit is contained in:
@@ -2,6 +2,7 @@ function DEFNODE(type, props, methods, base) {
|
|||||||
if (arguments.length < 4) base = AST_Node;
|
if (arguments.length < 4) base = AST_Node;
|
||||||
if (!props) props = [];
|
if (!props) props = [];
|
||||||
else props = props.split(/\s+/);
|
else props = props.split(/\s+/);
|
||||||
|
var self_props = props;
|
||||||
if (base && base.PROPS)
|
if (base && base.PROPS)
|
||||||
props = props.concat(base.PROPS);
|
props = props.concat(base.PROPS);
|
||||||
var code = "return function AST_" + type + "(props){ if (props) { ";
|
var code = "return function AST_" + type + "(props){ if (props) { ";
|
||||||
@@ -19,6 +20,7 @@ function DEFNODE(type, props, methods, base) {
|
|||||||
}
|
}
|
||||||
ctor.prototype.CTOR = ctor;
|
ctor.prototype.CTOR = ctor;
|
||||||
ctor.PROPS = props || null;
|
ctor.PROPS = props || null;
|
||||||
|
ctor.SELF_PROPS = self_props;
|
||||||
if (type) {
|
if (type) {
|
||||||
ctor.prototype.TYPE = ctor.TYPE = type;
|
ctor.prototype.TYPE = ctor.TYPE = type;
|
||||||
}
|
}
|
||||||
@@ -563,7 +565,10 @@ TreeWalker.prototype = {
|
|||||||
if (!ret && descend) {
|
if (!ret && descend) {
|
||||||
descend.call(node);
|
descend.call(node);
|
||||||
}
|
}
|
||||||
this.stack.pop(node);
|
this.stack.pop();
|
||||||
return ret;
|
return ret;
|
||||||
|
},
|
||||||
|
parent: function(n) {
|
||||||
|
return this.stack[this.stack.length - 2 - (n || 0)];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
149
lib/compress.js
149
lib/compress.js
@@ -9,13 +9,16 @@
|
|||||||
// maintaining various internal state that might be useful for
|
// maintaining various internal state that might be useful for
|
||||||
// squeezing nodes.
|
// squeezing nodes.
|
||||||
|
|
||||||
function Compressor(options) {
|
function Compressor(options, false_by_default) {
|
||||||
options = defaults(options, {
|
options = defaults(options, {
|
||||||
sequences : true,
|
sequences : !false_by_default,
|
||||||
dead_code : true,
|
properties : !false_by_default,
|
||||||
keep_comps : true,
|
dead_code : !false_by_default,
|
||||||
drop_debugger : true,
|
keep_comps : !false_by_default,
|
||||||
unsafe : true
|
drop_debugger : !false_by_default,
|
||||||
|
unsafe : !false_by_default,
|
||||||
|
|
||||||
|
warnings : true
|
||||||
});
|
});
|
||||||
var stack = [];
|
var stack = [];
|
||||||
return {
|
return {
|
||||||
@@ -25,6 +28,10 @@ function Compressor(options) {
|
|||||||
stack : function() { return stack },
|
stack : function() { return stack },
|
||||||
parent : function(n) {
|
parent : function(n) {
|
||||||
return stack[stack.length - 2 - (n || 0)];
|
return stack[stack.length - 2 - (n || 0)];
|
||||||
|
},
|
||||||
|
warn : function() {
|
||||||
|
if (options.warnings)
|
||||||
|
AST_Node.warn.apply(AST_Node, arguments);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -35,6 +42,12 @@ function Compressor(options) {
|
|||||||
return this;
|
return this;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function make_node(ctor, orig, props) {
|
||||||
|
if (!props.start) props.start = orig.start;
|
||||||
|
if (!props.end) props.end = orig.end;
|
||||||
|
return new ctor(props);
|
||||||
|
};
|
||||||
|
|
||||||
function SQUEEZE(nodetype, squeeze) {
|
function SQUEEZE(nodetype, squeeze) {
|
||||||
nodetype.DEFMETHOD("squeeze", function(compressor){
|
nodetype.DEFMETHOD("squeeze", function(compressor){
|
||||||
compressor.push_node(this);
|
compressor.push_node(this);
|
||||||
@@ -46,11 +59,6 @@ function Compressor(options) {
|
|||||||
|
|
||||||
function do_list(array, compressor) {
|
function do_list(array, compressor) {
|
||||||
return MAP(array, function(node){
|
return MAP(array, function(node){
|
||||||
if (node instanceof Array) {
|
|
||||||
sys.debug(node.map(function(node){
|
|
||||||
return node.TYPE;
|
|
||||||
}).join("\n"));
|
|
||||||
}
|
|
||||||
return node.squeeze(compressor);
|
return node.squeeze(compressor);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -72,15 +80,109 @@ function Compressor(options) {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function tighten_body(statements, compressor) {
|
||||||
|
statements = do_list(statements, compressor);
|
||||||
|
statements = eliminate_spurious_blocks(statements);
|
||||||
|
if (compressor.option("dead_code")) {
|
||||||
|
statements = eliminate_dead_code(statements, compressor);
|
||||||
|
}
|
||||||
|
if (compressor.option("sequences")) {
|
||||||
|
statements = sequencesize(statements);
|
||||||
|
}
|
||||||
|
return statements;
|
||||||
|
};
|
||||||
|
|
||||||
|
function eliminate_spurious_blocks(statements) {
|
||||||
|
return statements.reduce(function(a, stat){
|
||||||
|
if (stat.TYPE == "BlockStatement") {
|
||||||
|
// XXX: no instanceof here because we would catch
|
||||||
|
// AST_Lambda-s and other blocks too. perhaps we
|
||||||
|
// should refine the hierarchy.
|
||||||
|
a.push.apply(a, stat.body);
|
||||||
|
} else {
|
||||||
|
a.push(stat);
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function eliminate_dead_code(statements, compressor) {
|
||||||
|
var has_quit = false;
|
||||||
|
return statements.reduce(function(a, stat){
|
||||||
|
if (has_quit) {
|
||||||
|
if (stat instanceof AST_Defun) {
|
||||||
|
a.push(stat);
|
||||||
|
}
|
||||||
|
else if (compressor.option("warnings")) {
|
||||||
|
stat.walk(new TreeWalker(function(node){
|
||||||
|
if (node instanceof AST_Definitions
|
||||||
|
|| node instanceof AST_Defun) {
|
||||||
|
compressor.warn("Declarations in unreachable code! [{line},{col}]", node.start);
|
||||||
|
if (node instanceof AST_Definitions) {
|
||||||
|
node = node.clone();
|
||||||
|
node.remove_initializers();
|
||||||
|
a.push(node);
|
||||||
|
}
|
||||||
|
else if (node instanceof AST_Defun) {
|
||||||
|
a.push(node);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof AST_Scope)
|
||||||
|
return true;
|
||||||
|
}))
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
a.push(stat);
|
||||||
|
if (stat instanceof AST_Jump) {
|
||||||
|
has_quit = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, []);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sequencesize(statements) {
|
||||||
|
var prev = null, last = statements.length - 1;
|
||||||
|
if (last) statements = statements.reduce(function(a, cur, i){
|
||||||
|
if (prev instanceof AST_SimpleStatement
|
||||||
|
&& cur instanceof AST_SimpleStatement) {
|
||||||
|
var seq = make_node(AST_Seq, prev, {
|
||||||
|
first: prev.body,
|
||||||
|
second: cur.body
|
||||||
|
});
|
||||||
|
prev.body = seq;
|
||||||
|
}
|
||||||
|
else if (i == last && cur instanceof AST_Exit
|
||||||
|
&& cur.value && a.length == 1) {
|
||||||
|
// it only makes sense to do this transformation
|
||||||
|
// if the AST gets to a single statement.
|
||||||
|
var seq = make_node(AST_Seq, prev, {
|
||||||
|
first: prev.body,
|
||||||
|
second: cur.value
|
||||||
|
});
|
||||||
|
cur.value = seq;
|
||||||
|
return [ cur ];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
a.push(cur);
|
||||||
|
prev = cur;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}, []);
|
||||||
|
return statements;
|
||||||
|
}
|
||||||
|
|
||||||
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
SQUEEZE(AST_BlockStatement, function(self, compressor){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.body = do_list(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
|
if (self.body.length == 1 && !self.required)
|
||||||
|
return self.body[0];
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
SQUEEZE(AST_EmptyStatement, function(self, compressor){
|
SQUEEZE(AST_EmptyStatement, function(self, compressor){
|
||||||
if (compressor.parent() instanceof AST_BlockStatement)
|
return self;
|
||||||
return MAP.skip;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
SQUEEZE(AST_DWLoop, function(self, compressor){
|
SQUEEZE(AST_DWLoop, function(self, compressor){
|
||||||
@@ -144,7 +246,7 @@ function Compressor(options) {
|
|||||||
SQUEEZE(AST_Case, function(self, compressor){
|
SQUEEZE(AST_Case, function(self, compressor){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.expression = self.expression.squeeze(compressor);
|
self.expression = self.expression.squeeze(compressor);
|
||||||
self.body = do_list(self.body, compressor);
|
self.body = tighten_body(self.body, compressor);
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -156,6 +258,14 @@ function Compressor(options) {
|
|||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
AST_Definitions.DEFMETHOD("remove_initializers", function(){
|
||||||
|
this.definitions = this.definitions.map(function(def){
|
||||||
|
var def = def.clone();
|
||||||
|
def.value = null;
|
||||||
|
return def;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
SQUEEZE(AST_Definitions, function(self, compressor){
|
SQUEEZE(AST_Definitions, function(self, compressor){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.definitions = do_list(self.definitions, compressor);
|
self.definitions = do_list(self.definitions, compressor);
|
||||||
@@ -199,7 +309,14 @@ function Compressor(options) {
|
|||||||
SQUEEZE(AST_Sub, function(self, compressor){
|
SQUEEZE(AST_Sub, function(self, compressor){
|
||||||
self = self.clone();
|
self = self.clone();
|
||||||
self.expression = self.expression.squeeze(compressor);
|
self.expression = self.expression.squeeze(compressor);
|
||||||
self.property = self.property.squeeze(compressor);
|
var prop = self.property = self.property.squeeze(compressor);
|
||||||
|
if (prop instanceof AST_String && compressor.option("properties")) {
|
||||||
|
prop = prop.getValue();
|
||||||
|
if (is_identifier(prop)) {
|
||||||
|
self = new AST_Dot(self);
|
||||||
|
self.property = prop;
|
||||||
|
}
|
||||||
|
}
|
||||||
return self;
|
return self;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
49
test/compress/blocks.js
Normal file
49
test/compress/blocks.js
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
remove_blocks: {
|
||||||
|
input: {
|
||||||
|
{;}
|
||||||
|
foo();
|
||||||
|
{};
|
||||||
|
{
|
||||||
|
{};
|
||||||
|
};
|
||||||
|
bar();
|
||||||
|
{}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keep_some_blocks: {
|
||||||
|
input: {
|
||||||
|
// 1.
|
||||||
|
if (foo) {
|
||||||
|
{{{}}}
|
||||||
|
if (bar) baz();
|
||||||
|
{{}}
|
||||||
|
} else {
|
||||||
|
stuff();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2.
|
||||||
|
if (foo) {
|
||||||
|
for (var i = 0; i < 5; ++i)
|
||||||
|
if (bar) baz();
|
||||||
|
} else {
|
||||||
|
stuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
// 1.
|
||||||
|
if (foo) {
|
||||||
|
if (bar) baz();
|
||||||
|
} else stuff();
|
||||||
|
|
||||||
|
// 2.
|
||||||
|
if (foo) {
|
||||||
|
for (var i = 0; i < 5; ++i)
|
||||||
|
if (bar) baz();
|
||||||
|
} else stuff();
|
||||||
|
}
|
||||||
|
}
|
||||||
53
test/compress/dead-code.js
Normal file
53
test/compress/dead-code.js
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
dead_code_1: {
|
||||||
|
options = {
|
||||||
|
dead_code: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
a();
|
||||||
|
b();
|
||||||
|
x = 10;
|
||||||
|
return;
|
||||||
|
if (x) {
|
||||||
|
y();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
a();
|
||||||
|
b();
|
||||||
|
x = 10;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dead_code_2_should_warn: {
|
||||||
|
options = {
|
||||||
|
dead_code: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
g();
|
||||||
|
x = 10;
|
||||||
|
throw "foo";
|
||||||
|
// completely discarding the `if` would introduce some
|
||||||
|
// bugs. UglifyJS v1 doesn't deal with this issue.
|
||||||
|
if (x) {
|
||||||
|
y();
|
||||||
|
var x;
|
||||||
|
function g(){};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
g();
|
||||||
|
x = 10;
|
||||||
|
throw "foo";
|
||||||
|
var x;
|
||||||
|
function g(){};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
test/compress/debugger.js
Normal file
24
test/compress/debugger.js
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
keep_debugger: {
|
||||||
|
options = {
|
||||||
|
drop_debugger: false
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
debugger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drop_debugger: {
|
||||||
|
options = {
|
||||||
|
drop_debugger: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
debugger;
|
||||||
|
if (foo) debugger;
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (foo);
|
||||||
|
}
|
||||||
|
}
|
||||||
25
test/compress/properties.js
Normal file
25
test/compress/properties.js
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
keep_properties: {
|
||||||
|
options = {
|
||||||
|
properties: false
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a["foo"] = "bar";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a["foo"] = "bar";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dot_properties: {
|
||||||
|
options = {
|
||||||
|
properties: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
a["foo"] = "bar";
|
||||||
|
a["if"] = "if";
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
a.foo = "bar";
|
||||||
|
a["if"] = "if";
|
||||||
|
}
|
||||||
|
}
|
||||||
60
test/compress/sequences.js
Normal file
60
test/compress/sequences.js
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
make_sequences_1: {
|
||||||
|
options = {
|
||||||
|
sequences: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
baz();
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
foo(),bar(),baz();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_sequences_2: {
|
||||||
|
options = {
|
||||||
|
sequences: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
if (boo) {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
baz();
|
||||||
|
} else {
|
||||||
|
x();
|
||||||
|
y();
|
||||||
|
z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
if (boo) foo(),bar(),baz();
|
||||||
|
else x(),y(),z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
make_sequences_3: {
|
||||||
|
options = {
|
||||||
|
sequences: true
|
||||||
|
};
|
||||||
|
input: {
|
||||||
|
function f() {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
return baz();
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
foo();
|
||||||
|
bar();
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expect: {
|
||||||
|
function f() {
|
||||||
|
return foo(), bar(), baz();
|
||||||
|
}
|
||||||
|
function g() {
|
||||||
|
throw foo(), bar(), new Error();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
144
test/run-tests.js
Executable file
144
test/run-tests.js
Executable file
@@ -0,0 +1,144 @@
|
|||||||
|
#! /usr/bin/env node
|
||||||
|
|
||||||
|
var U = require("../tools/node");
|
||||||
|
var path = require("path");
|
||||||
|
var fs = require("fs");
|
||||||
|
var assert = require("assert");
|
||||||
|
var sys = require("util");
|
||||||
|
|
||||||
|
var tests_dir = path.dirname(module.filename);
|
||||||
|
|
||||||
|
run_compress_tests();
|
||||||
|
|
||||||
|
/* -----[ utils ]----- */
|
||||||
|
|
||||||
|
function tmpl() {
|
||||||
|
return U.string_template.apply(this, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log() {
|
||||||
|
var txt = tmpl.apply(this, arguments);
|
||||||
|
sys.puts(txt);
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_directory(dir) {
|
||||||
|
log("--- Entering [{dir}]", { dir: dir });
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_start_file(file) {
|
||||||
|
log("*** {file}", { file: file });
|
||||||
|
}
|
||||||
|
|
||||||
|
function log_test(name) {
|
||||||
|
log(" Running test [{name}]", { name: name });
|
||||||
|
}
|
||||||
|
|
||||||
|
function find_test_files(dir) {
|
||||||
|
var files = fs.readdirSync(dir).filter(function(name){
|
||||||
|
return /\.js$/i.test(name);
|
||||||
|
});
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
function test_directory(dir) {
|
||||||
|
return path.resolve(tests_dir, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
function run_compress_tests() {
|
||||||
|
var dir = test_directory("compress");
|
||||||
|
log_directory("compress");
|
||||||
|
var files = find_test_files(dir);
|
||||||
|
function test_file(file) {
|
||||||
|
log_start_file(file);
|
||||||
|
function test_case(test) {
|
||||||
|
log_test(test.name);
|
||||||
|
var cmp = new U.Compressor(test.options || {}, true);
|
||||||
|
var expect = make_code(test.expect, false);
|
||||||
|
var output = make_code(test.input.squeeze(cmp), false);
|
||||||
|
if (expect != output) {
|
||||||
|
log("!!! failed\n---INPUT---\n{input}\n---OUTPUT---\n{output}\n---EXPECTED---\n{expected}\n\n", {
|
||||||
|
input: make_code(test.input),
|
||||||
|
output: output,
|
||||||
|
expected: expect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var tests = parse_test(path.resolve(dir, file));
|
||||||
|
for (var i in tests) if (tests.hasOwnProperty(i)) {
|
||||||
|
test_case(tests[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
files.forEach(function(file){
|
||||||
|
test_file(file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function parse_test(file) {
|
||||||
|
var script = fs.readFileSync(file, "utf8");
|
||||||
|
var ast = U.parse(script);
|
||||||
|
var tests = {};
|
||||||
|
var tw = new U.TreeWalker(function(node, descend){
|
||||||
|
if (node instanceof U.AST_LabeledStatement
|
||||||
|
&& tw.parent() instanceof U.AST_Toplevel) {
|
||||||
|
var name = node.label.name;
|
||||||
|
tests[name] = get_one_test(name, node.statement);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (!(node instanceof U.AST_Toplevel)) croak(node);
|
||||||
|
});
|
||||||
|
ast.walk(tw);
|
||||||
|
return tests;
|
||||||
|
|
||||||
|
function croak(node) {
|
||||||
|
throw new Error(tmpl("Can't understand test file {file} [{line},{col}]\n{code}", {
|
||||||
|
file: file,
|
||||||
|
line: node.start.line,
|
||||||
|
col: node.start.col,
|
||||||
|
code: make_code(node, false)
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_one_test(name, block) {
|
||||||
|
var test = { name: name, options: {} };
|
||||||
|
var tw = new U.TreeWalker(function(node, descend){
|
||||||
|
if (node instanceof U.AST_Assign) {
|
||||||
|
if (!(node.left instanceof U.AST_SymbolRef)) {
|
||||||
|
croak(node);
|
||||||
|
}
|
||||||
|
var name = node.left.name;
|
||||||
|
test[name] = evaluate(node.right);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (node instanceof U.AST_LabeledStatement) {
|
||||||
|
assert.ok(
|
||||||
|
node.label.name == "input" || node.label.name == "expect",
|
||||||
|
tmpl("Unsupported label {name} [{line},{col}]", {
|
||||||
|
name: node.label.name,
|
||||||
|
line: node.label.start.line,
|
||||||
|
col: node.label.start.col
|
||||||
|
})
|
||||||
|
);
|
||||||
|
var stat = node.statement;
|
||||||
|
if (stat instanceof U.AST_BlockStatement)
|
||||||
|
stat.required = 1;
|
||||||
|
test[node.label.name] = stat;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
block.walk(tw);
|
||||||
|
return test;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function make_code(ast, beautify) {
|
||||||
|
if (arguments.length == 1) beautify = true;
|
||||||
|
var stream = U.OutputStream({ beautify: beautify });
|
||||||
|
ast.print(stream);
|
||||||
|
return stream.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
function evaluate(code) {
|
||||||
|
if (code instanceof U.AST_Node)
|
||||||
|
code = make_code(code);
|
||||||
|
return new Function("return(" + code + ")")();
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
var sys = require("util");
|
var sys = require("util");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
|
|
||||||
var UglifyJS = require("../tools/node.js");
|
var UglifyJS = require("../tools/node");
|
||||||
|
|
||||||
var filename = process.argv[2];
|
var filename = process.argv[2];
|
||||||
var code = fs.readFileSync(filename, "utf8");
|
var code = fs.readFileSync(filename, "utf8");
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ var sys = require("util");
|
|||||||
var path = require("path");
|
var path = require("path");
|
||||||
|
|
||||||
var UglifyJS = vm.createContext({
|
var UglifyJS = vm.createContext({
|
||||||
sys: sys
|
sys : sys,
|
||||||
|
console : console
|
||||||
});
|
});
|
||||||
|
|
||||||
function load_global(file) {
|
function load_global(file) {
|
||||||
|
|||||||
Reference in New Issue
Block a user