wrote more of the compressor and added some tests
This commit is contained in:
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 + ")")();
|
||||
}
|
||||
Reference in New Issue
Block a user