diff --git a/lib/minify.js b/lib/minify.js index 1771338c1f..66d0bd324a 100644 --- a/lib/minify.js +++ b/lib/minify.js @@ -49,8 +49,9 @@ function parse_source_map(content) { function set_shorthand(name, options, keys) { keys.forEach(function(key) { if (options[key]) { - if (typeof options[key] != "object") options[key] = {}; - if (!(name in options[key])) options[key][name] = options[name]; + var defs = {}; + defs[name] = options[name]; + options[key] = defaults(options[key], defs); } }); } @@ -105,7 +106,7 @@ function minify(files, options) { if (options.keep_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]); if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]); if (options.module === undefined && !options.ie) options.module = true; - if (options.module) set_shorthand("module", options, [ "compress", "parse" ]); + if (options.module) set_shorthand("module", options, [ "compress", "output", "parse" ]); if (options.toplevel !== undefined) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]); if (options.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]); if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]); diff --git a/lib/output.js b/lib/output.js index 2982cc3f60..ac275445eb 100644 --- a/lib/output.js +++ b/lib/output.js @@ -63,6 +63,7 @@ function OutputStream(options) { inline_script : true, keep_quoted_props: false, max_line_len : false, + module : false, preamble : null, preserve_line : false, quote_keys : false, @@ -140,12 +141,22 @@ function OutputStream(options) { reset(); var to_utf8 = options.ascii_only ? function(str, identifier) { - if (identifier) str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) { + if (identifier || options.module) str = str.replace(/[\ud800-\udbff][\udc00-\udfff]/g, function(ch) { return "\\u{" + (ch.charCodeAt(0) - 0xd7c0 << 10 | ch.charCodeAt(1) - 0xdc00).toString(16) + "}"; }); - return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(ch) { - var code = ch.charCodeAt(0).toString(16); + return str.replace(/[\u0000-\u001f\u007f-\uffff]/g, function(s, i) { + var code = s.charCodeAt(0).toString(16); if (code.length <= 2 && !identifier) { + switch (s) { + case "\n": return "\\n"; + case "\r": return "\\r"; + case "\t": return "\\t"; + case "\b": return "\\b"; + case "\f": return "\\f"; + case "\x0B": return options.ie ? "\\x0B" : "\\v"; + case "\0": + return /[0-9]/.test(str.charAt(i+1)) ? "\\x00" : "\\0"; + } while (code.length < 2) code = "0" + code; return "\\x" + code; } else { diff --git a/test/compress/templates.js b/test/compress/templates.js index 604f9dedf5..a03f7658c2 100644 --- a/test/compress/templates.js +++ b/test/compress/templates.js @@ -432,6 +432,7 @@ pure_funcs: { ascii_only: { beautify = { ascii_only: true, + module: false, } options = { templates: false, @@ -445,9 +446,27 @@ ascii_only: { node_version: ">=6" } +ascii_only_ecma: { + beautify = { + ascii_only: true, + module: true, + } + options = { + templates: false, + } + input: { + console.log(`\ud801\udc37\ud801𐐷${42}\u{10437}`); + } + expect_exact: "console.log(`\\ud801\\udc37\\ud801\\u{10437}${42}\\u{10437}`);" + expect_stdout: "𐐷\ud801𐐷42𐐷" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} + ascii_only_templates: { beautify = { ascii_only: true, + module: false, } options = { templates: true, @@ -461,9 +480,44 @@ ascii_only_templates: { node_version: ">=6" } +ascii_only_templates_ecma: { + beautify = { + ascii_only: true, + module: true, + } + options = { + templates: true, + } + input: { + console.log(`\ud801\udc37\ud801𐐷${42}\u{10437}`); + } + expect_exact: "console.log(`\\u{10437}\\ud801\\u{10437}${42}\\u{10437}`);" + expect_stdout: "𐐷\ud801𐐷42𐐷" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} + unicode: { beautify = { ascii_only: false, + module: false, + } + options = { + templates: false, + } + input: { + console.log(`\ud801\udc37\ud801𐐷${42}\u{10437}`); + } + expect_exact: "console.log(`\\ud801\\udc37\\ud801𐐷${42}\\u{10437}`);" + expect_stdout: "𐐷\ud801𐐷42𐐷" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} + +unicode_ecma: { + beautify = { + ascii_only: false, + module: true, } options = { templates: false, @@ -480,6 +534,24 @@ unicode: { unicode_templates: { beautify = { ascii_only: false, + module: false, + } + options = { + templates: true, + } + input: { + console.log(`\ud801\udc37\ud801𐐷${42}\u{10437}`); + } + expect_exact: "console.log(`𐐷\\ud801𐐷${42}𐐷`);" + expect_stdout: "𐐷\ud801𐐷42𐐷" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} + +unicode_templates_ecma: { + beautify = { + ascii_only: false, + module: true, } options = { templates: true, diff --git a/test/compress/unicode.js b/test/compress/unicode.js index abbd417df5..aa9da7be69 100644 --- a/test/compress/unicode.js +++ b/test/compress/unicode.js @@ -191,6 +191,24 @@ issue_2569: { surrogate_pair: { beautify = { ascii_only: false, + module: false, + } + input: { + var \u{2f800} = { + \u{2f801}: "\u{100000}", + }; + \u{2f800}.\u{2f802} = "\u{100001}"; + console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]); + } + expect_exact: 'var \ud87e\udc00={"\ud87e\udc01":"\udbc0\udc00"};\ud87e\udc00.\ud87e\udc02="\udbc0\udc01";console.log(typeof \ud87e\udc00,\ud87e\udc00.\ud87e\udc01,\ud87e\udc00["\ud87e\udc02"]);' + expect_stdout: "object \udbc0\udc00 \udbc0\udc01" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} +surrogate_pair_ecma: { + beautify = { + ascii_only: false, + module: true, } input: { var \u{2f800} = { @@ -208,6 +226,7 @@ surrogate_pair: { surrogate_pair_ascii: { beautify = { ascii_only: true, + module: false, } input: { var \u{2f800} = { @@ -221,3 +240,21 @@ surrogate_pair_ascii: { // non-BMP support is platform-dependent on Node.js v4 node_version: ">=6" } + +surrogate_pair_ascii_ecma: { + beautify = { + ascii_only: true, + module: true, + } + input: { + var \u{2f800} = { + \u{2f801}: "\u{100000}", + }; + \u{2f800}.\u{2f802} = "\u{100001}"; + console.log(typeof \u{2f800}, \u{2f800}.\u{2f801}, \u{2f800}["\u{2f802}"]); + } + expect_exact: 'var \\u{2f800}={"\\u{2f801}":"\\u{100000}"};\\u{2f800}.\\u{2f802}="\\u{100001}";console.log(typeof \\u{2f800},\\u{2f800}.\\u{2f801},\\u{2f800}["\\u{2f802}"]);' + expect_stdout: "object \udbc0\udc00 \udbc0\udc01" + // non-BMP support is platform-dependent on Node.js v4 + node_version: ">=6" +} diff --git a/test/mocha/minify.js b/test/mocha/minify.js index a9ef993980..0b3bb87493 100644 --- a/test/mocha/minify.js +++ b/test/mocha/minify.js @@ -19,7 +19,10 @@ describe("minify", function() { var options = { compress: true, mangle: false, - output: {}, + output: { + v8: false, + }, + webkit: true, }; var value = JSON.stringify(options); var result = UglifyJS.minify("print(6 * 7);", options);