Compare commits

...

17 Commits

Author SHA1 Message Date
Alex Lam S.L
1e9ef17e32 Merge pull request #1892 from alexlamsl/harmony-v3.0.2
Merging from master for 3.0.2
2017-05-10 03:14:45 +08:00
alexlamsl
222100ea4c Merge branch 'master' into harmony-v3.0.2 2017-05-10 01:57:32 +08:00
Alex Lam S.L
5fd8244a2e v3.0.2 2017-05-10 01:52:00 +08:00
Alex Lam S.L
93db48a317 rename package 2017-05-10 01:46:55 +08:00
Alex Lam S.L
2944e3df7d fix collapse_vars on destructuring declarations (#1889)
fixes #1886
2017-05-09 17:44:28 +08:00
Alex Lam S.L
c14e280585 print error stack in CLI (#1890) 2017-05-09 16:36:44 +08:00
Alex Lam S.L
bc3fa78e8c mention minify().error 2017-05-09 16:09:48 +08:00
Alex Lam S.L
8c7c107765 update minify() usage in test/ufuzz.js (#1888)
fixes #1887
2017-05-09 15:58:46 +08:00
Alex Lam S.L
e0ae8da089 Merge pull request #1885 from alexlamsl/harmony-v3.0.1
Merging from master for 3.0.1
2017-05-09 02:49:28 +08:00
alexlamsl
81f1311b24 Merge branch 'master' into harmony-v3.0.1 2017-05-09 02:10:06 +08:00
Alex Lam S.L
2433bb4e52 fix Unicode handling in parser (#1884)
There was an implicit assumption that first character within surrogate header range implies the next character must form a surrogate pair, which is not necessarily true.
2017-05-09 01:58:31 +08:00
kzc
3dd328dce3 [3.x] fix documentation for beautify options (#1882)
- use underscores rather than dashes.
2017-05-08 23:06:56 +08:00
Alex Lam S.L
014f428153 v3.0.1 2017-05-08 07:05:57 +08:00
Alex Lam S.L
a3b2eb75bd return Error from minify() (#1880)
Have `minify()` return `Error` in `result.error` rather than throwing it.
2017-05-08 07:05:19 +08:00
Alex Lam S.L
da295de82b support dumping AST (#1879)
Re-order `AST_Binary` properties to make dump more readable.

closes #769
2017-05-08 06:23:01 +08:00
Alex Lam S.L
4f8ca4626e deprecate low level API (#1877)
fixes #1872
2017-05-08 03:24:42 +08:00
Alex Lam S.L
e54748365c support minify() output as AST (#1878)
- `options.output.ast` (default `false`)
- `options.output.code` (default `true`)
2017-05-08 02:11:45 +08:00
45 changed files with 266 additions and 192 deletions

View File

@@ -95,8 +95,9 @@ The available options are:
`wrap_iife` Wrap IIFEs in parenthesis. Note: you may
want to disable `negate_iife` under
compressor options.
-o, --output <file> Output file (default STDOUT). Specify "spidermonkey"
to dump SpiderMonkey AST format (as JSON) to STDOUT.
-o, --output <file> Output file path (default STDOUT). Specify `ast` or
`spidermonkey` to write UglifyJS or SpiderMonkey AST
as JSON to STDOUT respectively.
--comments [filter] Preserve copyright comments in the output. By
default this works like Google Closure, keeping
JSDoc-style comments that contain "@license" or
@@ -489,21 +490,21 @@ can pass additional arguments that control the code output:
Passing `-b` will set this to true, but you might need to pass `-b` even
when you want to generate minified code, in order to specify additional
arguments, so you can use `-b beautify=false` to override it.
- `indent-level` (default 4)
- `indent-start` (default 0) -- prefix all lines by that many spaces
- `quote-keys` (default `false`) -- pass `true` to quote all keys in literal
- `indent_level` (default 4)
- `indent_start` (default 0) -- prefix all lines by that many spaces
- `quote_keys` (default `false`) -- pass `true` to quote all keys in literal
objects
- `space-colon` (default `true`) -- insert a space after the colon signs
- `ascii-only` (default `false`) -- escape Unicode characters in strings and
- `space_colon` (default `true`) -- insert a space after the colon signs
- `ascii_only` (default `false`) -- escape Unicode characters in strings and
regexps (affects directives with non-ascii characters becoming invalid)
- `inline-script` (default `false`) -- escape the slash in occurrences of
- `inline_script` (default `false`) -- escape the slash in occurrences of
`</script` in strings
- `width` (default 80) -- only takes effect when beautification is on, this
specifies an (orientative) line width that the beautifier will try to
obey. It refers to the width of the line text (excluding indentation).
It doesn't work very well currently, but it does make the code generated
by UglifyJS more readable.
- `max-line-len` (default 32000) -- maximum line length (for uglified code)
- `max_line_len` (default 32000) -- maximum line length (for uglified code)
- `bracketize` (default `false`) -- always insert brackets in `if`, `for`,
`do`, `while` or `with` statements, even if their body is a single
statement.
@@ -598,7 +599,8 @@ performs all the steps in a configurable manner.
Example:
```javascript
var result = UglifyJS.minify("var b = function() {};");
console.log(result.code); // minified output
console.log(result.code); // minified output
console.log(result.error); // runtime error
```
You can also compress multiple files:

View File

@@ -15,6 +15,7 @@ var path = require("path");
var program = require("commander");
var UglifyJS = require("../tools/node");
var skip_keys = [ "cname", "enclosed", "parent_scope", "scope", "thedef", "uses_eval", "uses_with" ];
var files = {};
var options = {
compress: false,
@@ -89,7 +90,7 @@ if (program.mangleProps) {
if (typeof program.mangleProps != "object") program.mangleProps = {};
if (!Array.isArray(program.mangleProps.reserved)) program.mangleProps.reserved = [];
require("../tools/domprops").forEach(function(name) {
UglifyJS.push_uniq(program.mangleProps.reserved, name);
UglifyJS._push_uniq(program.mangleProps.reserved, name);
});
}
if (typeof options.mangle != "object") options.mangle = {};
@@ -107,6 +108,12 @@ if (program.nameCache) {
}
}
}
if (program.output == "ast") {
options.output = {
ast: true,
code: false
};
}
if (program.parse) {
if (program.parse.acorn || program.parse.spidermonkey) {
if (program.sourceMap) fatal("ERROR: inline source map only works with built-in parser");
@@ -165,7 +172,7 @@ function run() {
UglifyJS.AST_Node.warn_function = function(msg) {
console.error("WARN:", msg);
};
if (program.stats) program.stats = Date.now();
if (program.stats) program.stats = Date.now();
try {
if (program.parse) {
if (program.parse.acorn) {
@@ -185,9 +192,13 @@ function run() {
});
}
}
var result = UglifyJS.minify(files, options);
} catch (ex) {
if (ex instanceof UglifyJS.JS_Parse_Error) {
fatal(ex.stack);
}
var result = UglifyJS.minify(files, options);
if (result.error) {
var ex = result.error;
if (ex.name == "SyntaxError") {
console.error("Parse error at " + ex.filename + ":" + ex.line + "," + ex.col);
var col = ex.col;
var lines = files[ex.filename].split(/\r?\n/);
@@ -209,10 +220,32 @@ function run() {
console.error("Supported options:");
console.error(ex.defs);
}
fatal("ERROR: " + ex.message);
}
if (program.output == "spidermonkey") {
console.log(JSON.stringify(UglifyJS.parse(new Buffer(result.code).toString()).to_mozilla_ast(), null, 2));
fatal(ex.stack);
} else if (program.output == "ast") {
console.log(JSON.stringify(result.ast, function(key, value) {
if (skip_key(key)) return;
if (value instanceof UglifyJS.AST_Token) return;
if (value instanceof UglifyJS.Dictionary) return;
if (value instanceof UglifyJS.AST_Node) {
var result = {
_class: "AST_" + value.TYPE
};
value.CTOR.PROPS.forEach(function(prop) {
result[prop] = value[prop];
});
return result;
}
return value;
}, 2));
} else if (program.output == "spidermonkey") {
console.log(JSON.stringify(UglifyJS.minify(result.code, {
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
}).ast.to_mozilla_ast(), null, 2));
} else if (program.output) {
fs.writeFileSync(program.output, result.code);
if (result.map) {
@@ -230,8 +263,8 @@ function run() {
}
function fatal(message) {
console.error(message);
process.exit(1);
console.error(message.replace(/^\S*?Error:/, "ERROR:"));
process.exit(1);
}
// A file glob function that only supports "*" and "?" wildcards in the basename.
@@ -270,7 +303,7 @@ function read_file(path, default_value) {
return fs.readFileSync(path, "utf8");
} catch (ex) {
if (ex.code == "ENOENT" && default_value != null) return default_value;
fatal("ERROR: " + ex.message);
fatal(ex.stack);
}
}
@@ -278,9 +311,17 @@ function parse_js(flag, constants) {
return function(value, options) {
options = options || {};
try {
UglifyJS.parse(value, {
expression: true
}).walk(new UglifyJS.TreeWalker(function(node) {
UglifyJS.minify(value, {
parse: {
expression: true
},
compress: false,
mangle: false,
output: {
ast: true,
code: false
}
}).ast.walk(new UglifyJS.TreeWalker(function(node) {
if (node instanceof UglifyJS.AST_Assign) {
var name = node.left.print_to_string();
var value = node.right;
@@ -337,3 +378,7 @@ function to_cache(key) {
}
return cache[key];
}
function skip_key(key) {
return skip_keys.indexOf(key) >= 0;
}

View File

@@ -857,7 +857,7 @@ var AST_UnaryPostfix = DEFNODE("UnaryPostfix", null, {
$documentation: "Unary postfix expression, i.e. `i++`"
}, AST_Unary);
var AST_Binary = DEFNODE("Binary", "left operator right", {
var AST_Binary = DEFNODE("Binary", "operator left right", {
$documentation: "Binary expression, i.e. `a + b`",
$propdoc: {
left: "[AST_Node] left-hand side expression",

View File

@@ -799,7 +799,7 @@ merge(Compressor.prototype, {
}
function get_lhs(expr) {
if (expr instanceof AST_VarDef) {
if (expr instanceof AST_VarDef && expr.name instanceof AST_SymbolDeclaration) {
var def = expr.name.definition();
if (def.orig.length > 1
|| def.references.length == 1 && (!def.global || compressor.toplevel(def))) {

View File

@@ -108,38 +108,46 @@ function minify(files, options) {
toplevel = mangle_properties(toplevel, options.mangle.properties);
}
}
if (options.sourceMap) {
if (typeof options.sourceMap.content == "string") {
options.sourceMap.content = JSON.parse(options.sourceMap.content);
}
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
orig: options.sourceMap.content,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) {
for (var name in files) {
options.output.source_map.get().setSourceContent(name, files[name]);
var result = {};
if (options.output.ast) {
result.ast = toplevel;
}
if (!HOP(options.output, "code") || options.output.code) {
if (options.sourceMap) {
if (typeof options.sourceMap.content == "string") {
options.sourceMap.content = JSON.parse(options.sourceMap.content);
}
options.output.source_map = SourceMap({
file: options.sourceMap.filename,
orig: options.sourceMap.content,
root: options.sourceMap.root
});
if (options.sourceMap.includeSources) {
for (var name in files) {
options.output.source_map.get().setSourceContent(name, files[name]);
}
}
}
}
var stream = OutputStream(options.output);
toplevel.print(stream);
var result = {
code: stream.get()
};
if (options.sourceMap) {
result.map = options.output.source_map.toString();
if (options.sourceMap.url == "inline") {
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
} else if (options.sourceMap.url) {
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
delete options.output.ast;
delete options.output.code;
var stream = OutputStream(options.output);
toplevel.print(stream);
result.code = stream.get();
if (options.sourceMap) {
result.map = options.output.source_map.toString();
if (options.sourceMap.url == "inline") {
result.code += "\n//# sourceMappingURL=data:application/json;charset=utf-8;base64," + to_base64(result.map);
} else if (options.sourceMap.url) {
result.code += "\n//# sourceMappingURL=" + options.sourceMap.url;
}
}
}
if (warnings.length) {
result.warnings = warnings;
}
return result;
} catch (ex) {
return { error: ex };
} finally {
AST_Node.warn_function = warn_function;
}

View File

@@ -215,16 +215,6 @@ function OutputStream(options) {
var might_add_newline = 0;
var last = "";
function last_char() {
var char = last.charAt(last.length - 1);
if (is_surrogate_pair_tail(char)) {
return last.charAt(last.length - 2) + char;
}
return char;
};
var ensure_line_len = options.max_line_len ? function() {
if (current_col > options.max_line_len) {
if (might_add_newline) {
@@ -247,7 +237,7 @@ function OutputStream(options) {
function print(str) {
str = String(str);
var ch = get_full_char(str, 0);
var prev = last_char();
var prev = get_full_char(last, last.length - 1);
if (might_need_semicolon) {
might_need_semicolon = false;

View File

@@ -134,8 +134,17 @@ var UNICODE = {
function get_full_char(str, pos) {
var char = str.charAt(pos);
if (char >= "\ud800" && char <= "\udbff") {
return char + str.charAt(pos + 1);
if (is_surrogate_pair_head(char)) {
var next = str.charAt(pos + 1);
if (is_surrogate_pair_tail(next)) {
return char + next;
}
}
if (is_surrogate_pair_tail(char)) {
var prev = str.charAt(pos - 1);
if (is_surrogate_pair_head(prev)) {
return prev + char;
}
}
return char;
}
@@ -152,8 +161,8 @@ function get_full_char_length(str) {
var surrogates = 0;
for (var i = 0; i < str.length; i++) {
if (str.charCodeAt(i) >= 0xd800 && str.charCodeAt(i) <= 0xdbff) {
if (str.charCodeAt(i + 1) >= 0xdc00 && str.charCodeAt(i + 1) <= 0xdfff) {
if (is_surrogate_pair_head(str.charCodeAt(i))) {
if (is_surrogate_pair_tail(str.charCodeAt(i + 1))) {
surrogates++;
i++;
}
@@ -291,7 +300,7 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
ch = "\n";
}
} else {
if (is_surrogate_pair_head(ch)) {
if (ch.length > 1) {
++S.pos;
++S.col;
}

View File

@@ -1,10 +1,10 @@
{
"name": "uglify-js",
"name": "uglify-es",
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"homepage": "http://lisperator.net/uglifyjs",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.0.0",
"version": "3.0.2",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -315,3 +315,18 @@ unused: {
console.log(a);
}
}
issue_1886: {
options = {
collapse_vars: true,
}
input: {
let [a] = [1];
console.log(a);
}
expect: {
let [a] = [1];
console.log(a);
}
expect_exact: "1"
}

13
test/exports.js Normal file
View File

@@ -0,0 +1,13 @@
exports["Compressor"] = Compressor;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["OutputStream"] = OutputStream;
exports["SourceMap"] = SourceMap;
exports["TreeWalker"] = TreeWalker;
exports["base54"] = base54;
exports["defaults"] = defaults;
exports["mangle_properties"] = mangle_properties;
exports["minify"] = minify;
exports["parse"] = parse;
exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier;

View File

@@ -1,4 +1,4 @@
var UglifyJS = require('../../');
var UglifyJS = require("../node");
var assert = require("assert");
describe("Accessor tokens", function() {

View File

@@ -1,4 +1,4 @@
var UglifyJS = require('../../');
var UglifyJS = require("../node");
var assert = require("assert");
describe("arguments", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Arrow functions", function() {
it("Should not accept spread tokens on non-last parameters or without arguments parentheses", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Class", function() {
it("Should not accept spread on non-last parameters in methods", function() {

View File

@@ -19,7 +19,7 @@ describe("bin/uglifyjs", function () {
eval(stdout);
assert.strictEqual(typeof WrappedUglifyJS, 'object');
assert.strictEqual(true, WrappedUglifyJS.parse('foo;') instanceof WrappedUglifyJS.AST_Node);
assert.strictEqual(WrappedUglifyJS.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
done();
});
@@ -185,7 +185,7 @@ describe("bin/uglifyjs", function () {
exec(command, function (err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stderr, "ERROR: inline source map only works with singular input\n");
assert.strictEqual(stderr.split(/\n/)[0], "ERROR: inline source map only works with singular input");
done();
});
});
@@ -509,4 +509,15 @@ describe("bin/uglifyjs", function () {
return JSON.stringify(map).replace(/"/g, '\\"');
}
});
it("Should dump AST as JSON", function(done) {
var command = uglifyjscmd + " test/input/global_defs/simple.js -mco ast";
exec(command, function (err, stdout) {
if (err) throw err;
var ast = JSON.parse(stdout);
assert.strictEqual(ast._class, "AST_Toplevel");
assert.ok(Array.isArray(ast.body));
done();
});
});
});

View File

@@ -1,4 +1,4 @@
var UglifyJS = require('../../');
var UglifyJS = require("../node");
var assert = require("assert");
describe("comment filters", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Comment", function() {
it("Should recognize eol of single line comments", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Destructuring", function() {
it("Should generate similar trees for destructuring in left hand side expressions, definitions, functions and arrow functions", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Directives", function() {
it ("Should allow tokenizer to store directives state", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("EOF", function() {
it("Should test code for at least throwing syntax error when incomplete", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Export", function() {
it ("Should parse export directives", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Expression", function() {
it("Should not allow the first exponentiation operator to be prefixed with an unary operator", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Function", function() {
it ("Should parse binding patterns correctly", function() {

View File

@@ -1,4 +1,4 @@
var UglifyJS = require('../../');
var UglifyJS = require("../node");
var assert = require("assert");
describe("Getters and setters", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Left-hand side expressions", function () {
it("Should parse destructuring with const/let/var correctly", function () {

View File

@@ -1,4 +1,4 @@
var Uglify = require('../../');
var Uglify = require("../node");
var assert = require("assert");
describe("line-endings", function() {

View File

@@ -114,17 +114,18 @@ describe("minify", function() {
}
});
it("Should fail with multiple input and inline source map", function() {
assert.throws(function() {
Uglify.minify([
read("./test/input/issue-520/input.js"),
read("./test/input/issue-520/output.js")
], {
sourceMap: {
content: "inline",
url: "inline"
}
});
var result = Uglify.minify([
read("./test/input/issue-520/input.js"),
read("./test/input/issue-520/output.js")
], {
sourceMap: {
content: "inline",
url: "inline"
}
});
var err = result.error;
assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "Error: inline source map only works with singular input");
});
});
@@ -170,26 +171,14 @@ describe("minify", function() {
});
describe("JS_Parse_Error", function() {
it("should throw syntax error", function() {
assert.throws(function() {
Uglify.minify("function f(a{}");
}, function(err) {
assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
assert.strictEqual(err.filename, "0");
assert.strictEqual(err.line, 1);
assert.strictEqual(err.col, 12);
return true;
});
it("should return syntax error", function() {
var result = Uglify.minify("function f(a{}");
var err = result.error;
assert.ok(err instanceof Error);
assert.strictEqual(err.stack.split(/\n/)[0], "SyntaxError: Unexpected token punc «{», expected punc «,»");
assert.strictEqual(err.filename, "0");
assert.strictEqual(err.line, 1);
assert.strictEqual(err.col, 12);
});
});
describe("Compressor", function() {
it("should be backward compatible with ast.transform(compressor)", function() {
var ast = Uglify.parse("function f(a){for(var i=0;i<a;i++)console.log(i)}");
ast.figure_out_scope();
ast = ast.transform(Uglify.Compressor());
assert.strictEqual(ast.print_to_string(), "function f(a){for(var i=0;i<a;i++)console.log(i)}");
});
})
});

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("New", function() {
it("Should add trailing parentheses for new expressions with zero arguments in beautify mode", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Number literals", function () {
it("Should not allow legacy octal literals in strict mode", function() {

View File

@@ -1,4 +1,4 @@
var Uglify = require("../../");
var Uglify = require("../node");
var assert = require("assert");
describe("Object", function() {

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../../");
var UglifyJS = require("../node");
var assert = require("assert");
describe("operator", function() {

View File

@@ -1,6 +1,6 @@
var assert = require("assert");
var exec = require("child_process").exec;
var uglify = require("../../");
var uglify = require("../node");
describe("spidermonkey export/import sanity test", function() {
it("should produce a functional build when using --self with spidermonkey", function(done) {
@@ -15,18 +15,7 @@ describe("spidermonkey export/import sanity test", function() {
eval(stdout);
assert.strictEqual(typeof SpiderUglify, "object");
var ast = SpiderUglify.parse("foo([true,,2+3]);");
assert.strictEqual(true, ast instanceof SpiderUglify.AST_Node);
ast.figure_out_scope();
ast = SpiderUglify.Compressor({}).compress(ast);
assert.strictEqual(true, ast instanceof SpiderUglify.AST_Node);
var stream = SpiderUglify.OutputStream({});
ast.print(stream);
var code = stream.toString();
assert.strictEqual(code, "foo([!0,,5]);");
assert.strictEqual(SpiderUglify.minify("foo([true,,2+3]);").code, "foo([!0,,5]);");
done();
});

View File

@@ -1,4 +1,4 @@
var UglifyJS = require('../../');
var UglifyJS = require("../node");
var assert = require("assert");
describe("String literals", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Template string", function() {
it("Should not accept invalid sequences", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Try", function() {
it("Should not allow catch with an empty parameter", function() {

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("Unicode", function() {
it("Should not accept invalid code ranges in unicode escape", function() {
@@ -135,4 +135,11 @@ describe("Unicode", function() {
}).code, tests[i][1]);
}
});
it("Should parse raw characters correctly", function() {
var ast = uglify.parse('console.log("\\udbff");');
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
ast = uglify.parse(ast.print_to_string());
assert.strictEqual(ast.print_to_string(), 'console.log("\udbff");');
});
});

View File

@@ -1,5 +1,5 @@
var assert = require("assert");
var uglify = require("../../");
var uglify = require("../node");
describe("With", function() {
it("Should throw syntaxError when using with statement in strict mode", function() {

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("../../");
var UglifyJS = require("../node");
var assert = require("assert");
describe("Yield", function() {

View File

@@ -1,7 +1,7 @@
// Testing UglifyJS <-> SpiderMonkey AST conversion
// through generative testing.
var UglifyJS = require(".."),
var UglifyJS = require("./node"),
escodegen = require("escodegen"),
esfuzz = require("esfuzz"),
estraverse = require("estraverse"),

6
test/node.js Normal file
View File

@@ -0,0 +1,6 @@
var fs = require("fs");
new Function("MOZ_SourceMap", "exports", require("../tools/node").FILES.map(function(file) {
if (/exports\.js$/.test(file)) file = require.resolve("./exports");
return fs.readFileSync(file, "utf8");
}).join("\n\n"))(require("source-map"), exports);

View File

@@ -1,6 +1,6 @@
#! /usr/bin/env node
var U = require("../tools/node");
var U = require("./node");
var path = require("path");
var fs = require("fs");
var assert = require("assert");

View File

@@ -1,4 +1,4 @@
var UglifyJS = require("..");
var UglifyJS = require("./node");
var ok = require("assert");
module.exports = function () {

View File

@@ -12,7 +12,7 @@
stream._handle.setBlocking(true);
});
var UglifyJS = require("..");
var UglifyJS = require("./node");
var randomBytes = require("crypto").randomBytes;
var sandbox = require("./sandbox");
@@ -856,23 +856,21 @@ function createVarName(maybe, dontStore) {
}
function try_beautify(code, result) {
try {
var beautified = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
bracketize: true,
},
}).code;
if (sandbox.same_stdout(sandbox.run_code(beautified), result)) {
console.log("// (beautified)");
console.log(beautified);
return;
}
} catch (e) {
var beautified = UglifyJS.minify(code, {
compress: false,
mangle: false,
output: {
beautify: true,
bracketize: true,
},
});
if (beautified.error) {
console.log("// !!! beautify failed !!!");
console.log(e.stack);
console.log(beautified.error.stack);
} else if (sandbox.same_stdout(sandbox.run_code(beautified.code), result)) {
console.log("// (beautified)");
console.log(beautified.code);
return;
}
console.log("//");
console.log(code);
@@ -908,12 +906,13 @@ function log_suspects(minify_options, component) {
var o = JSON.parse(JSON.stringify(options));
o[name] = false;
m[component] = o;
try {
var r = sandbox.run_code(UglifyJS.minify(original_code, m).code);
return sandbox.same_stdout(original_result, r);
} catch (e) {
var result = UglifyJS.minify(original_code, m);
if (result.error) {
console.log("Error testing options." + component + "." + name);
console.log(e);
console.log(result.error);
} else {
var r = sandbox.run_code(result.code);
return sandbox.same_stdout(original_result, r);
}
}
});
@@ -981,18 +980,16 @@ for (var round = 1; round <= num_iterations; round++) {
original_code = createTopLevelCode();
original_result = sandbox.run_code(original_code);
(typeof original_result != "string" ? fallback_options : minify_options).forEach(function(options) {
try {
uglify_code = UglifyJS.minify(original_code, JSON.parse(options)).code;
} catch (e) {
uglify_code = e;
}
ok = typeof uglify_code == "string";
if (ok) {
uglify_code = UglifyJS.minify(original_code, JSON.parse(options));
if (!uglify_code.error) {
uglify_code = uglify_code.code;
uglify_result = sandbox.run_code(uglify_code);
ok = sandbox.same_stdout(original_result, uglify_result);
} else if (typeof original_result != "string") {
ok = uglify_code.name == original_result.name;
} else {
uglify_code = uglify_code.error;
if (typeof original_result != "string") {
ok = uglify_code.name == original_result.name;
}
}
if (verbose || (verbose_interval && !(round % INTERVAL_COUNT)) || !ok) log(options);
else if (verbose_error && typeof original_result != "string") {

View File

@@ -1,15 +1,4 @@
exports["Compressor"] = Compressor;
exports["Dictionary"] = Dictionary;
exports["JS_Parse_Error"] = JS_Parse_Error;
exports["OutputStream"] = OutputStream;
exports["SourceMap"] = SourceMap;
exports["TreeWalker"] = TreeWalker;
exports["base54"] = base54;
exports["defaults"] = defaults;
exports["mangle_properties"] = mangle_properties;
exports["minify"] = minify;
exports["parse"] = parse;
exports["push_uniq"] = push_uniq;
exports["string_template"] = string_template;
exports["tokenizer"] = tokenizer;
exports["is_identifier"] = is_identifier;
exports["_push_uniq"] = push_uniq;

View File

@@ -18,15 +18,19 @@ var FILES = UglifyJS.FILES = [
return require.resolve(file);
});
new Function("MOZ_SourceMap", "exports", FILES.map(function(file){
return fs.readFileSync(file, "utf8");
}).join("\n\n"))(
new Function("MOZ_SourceMap", "exports", function() {
var code = FILES.map(function(file) {
return fs.readFileSync(file, "utf8");
});
code.push("exports.describe_ast = " + describe_ast.toString());
return code.join("\n\n");
}())(
require("source-map"),
UglifyJS
);
UglifyJS.describe_ast = function() {
var out = UglifyJS.OutputStream({ beautify: true });
function describe_ast() {
var out = OutputStream({ beautify: true });
function doitem(ctor) {
out.print("AST_" + ctor.TYPE);
var props = ctor.SELF_PROPS.filter(function(prop){
@@ -56,6 +60,6 @@ UglifyJS.describe_ast = function() {
});
}
};
doitem(UglifyJS.AST_Node);
doitem(AST_Node);
return out + "";
};
}