[Pkg-javascript-commits] [uglifyjs] 168/491: improve usability of name cache under `minify()` (#2176)
Jonas Smedegaard
dr at jones.dk
Wed Feb 14 19:51:32 UTC 2018
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag debian/3.3.10-1
in repository uglifyjs.
commit bdeadffbf582b393dbc14a45b3e69ddf16f47690
Author: Alex Lam S.L <alexlamsl at gmail.com>
Date: Thu Jun 29 12:48:34 2017 +0800
improve usability of name cache under `minify()` (#2176)
fixes #2174
---
README.md | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--
bin/uglifyjs | 27 ++------------------------
lib/minify.js | 36 ++++++++++++++++++++++++++++++++++-
test/mocha/minify.js | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 140 insertions(+), 28 deletions(-)
diff --git a/README.md b/README.md
index de2c2c9..c277f65 100644
--- a/README.md
+++ b/README.md
@@ -111,7 +111,7 @@ a double dash to prevent input files being used as option arguments:
By default UglifyJS will not try to be IE-proof.
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
- --name-cache File to hold mangled name mappings.
+ --name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options:
`base` Path to compute relative paths from input files.
@@ -383,7 +383,47 @@ var code = {
var options = { toplevel: true };
var result = UglifyJS.minify(code, options);
console.log(result.code);
-// console.log(function(n,o){return n+o}(3,7));
+// console.log(3+7);
+```
+
+The `nameCache` option:
+```javascript
+var options = {
+ mangle: {
+ toplevel: true,
+ },
+ nameCache: {}
+};
+var result1 = UglifyJS.minify({
+ "file1.js": "function add(first, second) { return first + second; }"
+}, options);
+var result2 = UglifyJS.minify({
+ "file2.js": "console.log(add(1 + 2, 3 + 4));"
+}, options);
+console.log(result1.code);
+// function n(n,r){return n+r}
+console.log(result2.code);
+// console.log(n(3,7));
+```
+
+You may persist the name cache to the file system in the following way:
+```javascript
+var cacheFileName = "/tmp/cache.json";
+var options = {
+ mangle: {
+ properties: true,
+ },
+ nameCache: JSON.parse(fs.readFileSync(cacheFileName, "utf8"))
+};
+fs.writeFileSync("part1.js", UglifyJS.minify({
+ "file1.js": fs.readFileSync("file1.js", "utf8"),
+ "file2.js": fs.readFileSync("file2.js", "utf8")
+}, options).code, "utf8");
+fs.writeFileSync("part2.js", UglifyJS.minify({
+ "file3.js": fs.readFileSync("file3.js", "utf8"),
+ "file4.js": fs.readFileSync("file4.js", "utf8")
+}, options).code, "utf8");
+fs.writeFileSync(cacheFileName, JSON.stringify(options.nameCache), "utf8");
```
An example of a combination of `minify()` options:
@@ -461,6 +501,13 @@ if (result.error) throw result.error;
- `toplevel` (default `false`) - set to `true` if you wish to enable top level
variable and function name mangling and to drop unused variables and functions.
+- `nameCache` (default `null`) - pass an empty object `{}` or a previously
+ used `nameCache` object if you wish to cache mangled variable and
+ property names across multiple invocations of `minify()`. Note: this is
+ a read/write property. `minify()` will read the name cache state of this
+ object and update it during minification so that it may be
+ reused or externally persisted by the user.
+
- `ie8` (default `false`) - set to `true` to support IE8.
## Minify options structure
@@ -487,6 +534,7 @@ if (result.error) throw result.error;
sourceMap: {
// source map options
},
+ nameCache: null, // or specify a name cache object
toplevel: false,
ie8: false,
}
diff --git a/bin/uglifyjs b/bin/uglifyjs
index f4feb39..68d67c2 100755
--- a/bin/uglifyjs
+++ b/bin/uglifyjs
@@ -106,17 +106,8 @@ if (program.mangleProps) {
if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = program.mangleProps;
}
-var cache;
if (program.nameCache) {
- cache = JSON.parse(read_file(program.nameCache, "{}"));
- if (options.mangle) {
- if (typeof options.mangle != "object") options.mangle = {};
- options.mangle.cache = to_cache("vars");
- if (options.mangle.properties) {
- if (typeof options.mangle.properties != "object") options.mangle.properties = {};
- options.mangle.properties.cache = to_cache("props");
- }
- }
+ options.nameCache = JSON.parse(read_file(program.nameCache, "{}"));
}
if (program.output == "ast") {
options.output = {
@@ -266,9 +257,7 @@ function run() {
print(result.code);
}
if (program.nameCache) {
- fs.writeFileSync(program.nameCache, JSON.stringify(cache, function(key, value) {
- return value instanceof UglifyJS.Dictionary ? value.toObject() : value;
- }));
+ fs.writeFileSync(program.nameCache, JSON.stringify(options.nameCache));
}
if (result.timings) for (var phase in result.timings) {
print_error("- " + phase + ": " + result.timings[phase].toFixed(3) + "s");
@@ -381,18 +370,6 @@ function parse_source_map() {
}
}
-function to_cache(key) {
- if (cache[key]) {
- cache[key].props = UglifyJS.Dictionary.fromObject(cache[key].props);
- } else {
- cache[key] = {
- cname: -1,
- props: new UglifyJS.Dictionary()
- };
- }
- return cache[key];
-}
-
function skip_key(key) {
return skip_keys.indexOf(key) >= 0;
}
diff --git a/lib/minify.js b/lib/minify.js
index cc638be..b4bfe45 100644
--- a/lib/minify.js
+++ b/lib/minify.js
@@ -27,6 +27,23 @@ function set_shorthand(name, options, keys) {
}
}
+function init_cache(cache) {
+ if (!cache) return;
+ if (!("cname" in cache)) cache.cname = -1;
+ if (!("props" in cache)) {
+ cache.props = new Dictionary();
+ } else if (!(cache.props instanceof Dictionary)) {
+ cache.props = Dictionary.fromObject(cache.props);
+ }
+}
+
+function to_json(cache) {
+ return {
+ cname: cache.cname,
+ props: cache.props.toObject()
+ };
+}
+
function minify(files, options) {
var warn_function = AST_Node.warn_function;
try {
@@ -35,6 +52,7 @@ function minify(files, options) {
ie8: false,
keep_fnames: false,
mangle: {},
+ nameCache: null,
output: {},
parse: {},
sourceMap: false,
@@ -52,7 +70,7 @@ function minify(files, options) {
set_shorthand("warnings", options, [ "compress" ]);
if (options.mangle) {
options.mangle = defaults(options.mangle, {
- cache: null,
+ cache: options.nameCache && (options.nameCache.vars || {}),
eval: false,
ie8: false,
keep_fnames: false,
@@ -60,6 +78,16 @@ function minify(files, options) {
reserved: [],
toplevel: false,
}, true);
+ if (options.nameCache && options.mangle.properties) {
+ if (typeof options.mangle.properties != "object") {
+ options.mangle.properties = {};
+ }
+ if (!("cache" in options.mangle.properties)) {
+ options.mangle.properties.cache = options.nameCache.props || {};
+ }
+ }
+ init_cache(options.mangle.cache);
+ init_cache(options.mangle.properties.cache);
}
if (options.sourceMap) {
options.sourceMap = defaults(options.sourceMap, {
@@ -153,6 +181,12 @@ function minify(files, options) {
}
}
}
+ if (options.nameCache && options.mangle) {
+ if (options.mangle.cache) options.nameCache.vars = to_json(options.mangle.cache);
+ if (options.mangle.properties && options.mangle.properties.cache) {
+ options.nameCache.props = to_json(options.mangle.properties.cache);
+ }
+ }
if (timings) {
timings.end = Date.now();
result.timings = {
diff --git a/test/mocha/minify.js b/test/mocha/minify.js
index b4722ce..88e9c4e 100644
--- a/test/mocha/minify.js
+++ b/test/mocha/minify.js
@@ -1,6 +1,7 @@
var Uglify = require('../../');
var assert = require("assert");
var readFileSync = require("fs").readFileSync;
+var run_code = require("../sandbox").run_code;
function read(path) {
return readFileSync(path, "utf8");
@@ -20,6 +21,58 @@ describe("minify", function() {
assert.strictEqual(result.code, "alert(2);");
});
+ it("Should work with mangle.cache", function() {
+ var cache = {};
+ var original = "";
+ var compressed = "";
+ [
+ "bar.es5",
+ "baz.es5",
+ "foo.es5",
+ "qux.js",
+ ].forEach(function(file) {
+ var code = read("test/input/issue-1242/" + file);
+ var result = Uglify.minify(code, {
+ mangle: {
+ cache: cache,
+ toplevel: true
+ }
+ });
+ if (result.error) throw result.error;
+ original += code;
+ compressed += result.code;
+ });
+ assert.strictEqual(JSON.stringify(cache).slice(0, 20), '{"cname":5,"props":{');
+ assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
+ assert.strictEqual(run_code(compressed), run_code(original));
+ });
+
+ it("Should work with nameCache", function() {
+ var cache = {};
+ var original = "";
+ var compressed = "";
+ [
+ "bar.es5",
+ "baz.es5",
+ "foo.es5",
+ "qux.js",
+ ].forEach(function(file) {
+ var code = read("test/input/issue-1242/" + file);
+ var result = Uglify.minify(code, {
+ mangle: {
+ toplevel: true
+ },
+ nameCache: cache
+ });
+ if (result.error) throw result.error;
+ original += code;
+ compressed += result.code;
+ });
+ assert.strictEqual(JSON.stringify(cache).slice(0, 28), '{"vars":{"cname":5,"props":{');
+ assert.strictEqual(compressed, 'function n(n){return 3*n}function r(n){return n/2}function c(o){l("Foo:",2*o)}var l=console.log.bind(console);var f=n(3),i=r(12);l("qux",f,i),c(11);');
+ assert.strictEqual(run_code(compressed), run_code(original));
+ });
+
describe("keep_quoted_props", function() {
it("Should preserve quotes in object literals", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/uglifyjs.git
More information about the Pkg-javascript-commits
mailing list