Compare commits
9 Commits
harmony-v3
...
harmony-v3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
68645b28d3 | ||
|
|
aaa8212837 | ||
|
|
bd84007cf4 | ||
|
|
55387e8fd0 | ||
|
|
1241600013 | ||
|
|
7e3e9da860 | ||
|
|
a784717fe2 | ||
|
|
00f509405b | ||
|
|
e8235657e4 |
@@ -631,6 +631,13 @@ If you're using the `X-SourceMap` header instead, you can just omit `sourceMap.u
|
||||
- `unsafe_math` (default: false) -- optimize numerical expressions like
|
||||
`2 * x * 3` into `6 * x`, which may give imprecise floating point results.
|
||||
|
||||
- `unsafe_methods` (default: false) -- Converts `{ m: function(){} }` to
|
||||
`{ m(){} }`. `ecma` must be set to `6` or greater to enable this transform.
|
||||
If `unsafe_methods` is a RegExp then key/value pairs with keys matching the
|
||||
RegExp will be converted to concise methods.
|
||||
Note: if enabled there is a risk of getting a "`<method name>` is not a
|
||||
constructor" TypeError should any code try to `new` the former function.
|
||||
|
||||
- `unsafe_proto` (default: false) -- optimize expressions like
|
||||
`Array.prototype.slice.call(a)` into `[].slice.call(a)`
|
||||
|
||||
|
||||
@@ -134,11 +134,10 @@ var AST_Debugger = DEFNODE("Debugger", null, {
|
||||
$documentation: "Represents a debugger statement",
|
||||
}, AST_Statement);
|
||||
|
||||
var AST_Directive = DEFNODE("Directive", "value scope quote", {
|
||||
var AST_Directive = DEFNODE("Directive", "value quote", {
|
||||
$documentation: "Represents a directive, like \"use strict\";",
|
||||
$propdoc: {
|
||||
value: "[string] The value of this directive as a plain string (it's not an AST_String!)",
|
||||
scope: "[AST_Scope/S] The scope that this directive affects",
|
||||
quote: "[string] the original quote character"
|
||||
},
|
||||
}, AST_Statement);
|
||||
@@ -303,10 +302,9 @@ var AST_With = DEFNODE("With", "expression", {
|
||||
|
||||
/* -----[ scope and functions ]----- */
|
||||
|
||||
var AST_Scope = DEFNODE("Scope", "directives variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
var AST_Scope = DEFNODE("Scope", "variables functions uses_with uses_eval parent_scope enclosed cname", {
|
||||
$documentation: "Base class for all statements introducing a lexical scope",
|
||||
$propdoc: {
|
||||
directives: "[string*/S] an array of directives declared in this scope",
|
||||
variables: "[Object/S] a map of name -> SymbolDef for all variables/functions defined in this scope",
|
||||
functions: "[Object/S] like `variables`, but only lists function declarations",
|
||||
uses_with: "[boolean/S] tells whether this scope uses the `with` statement",
|
||||
|
||||
@@ -88,6 +88,7 @@ function Compressor(options, false_by_default) {
|
||||
unsafe_comps : false,
|
||||
unsafe_Func : false,
|
||||
unsafe_math : false,
|
||||
unsafe_methods: false,
|
||||
unsafe_proto : false,
|
||||
unsafe_regexp : false,
|
||||
unused : !false_by_default,
|
||||
@@ -874,7 +875,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
}
|
||||
|
||||
function has_overlapping_symbol(fn, arg) {
|
||||
function has_overlapping_symbol(fn, arg, fn_strict) {
|
||||
var found = false, scan_this = !(fn instanceof AST_Arrow);
|
||||
arg.walk(new TreeWalker(function(node, descend) {
|
||||
if (found) return true;
|
||||
@@ -885,7 +886,7 @@ merge(Compressor.prototype, {
|
||||
}
|
||||
return found = true;
|
||||
}
|
||||
if (scan_this && node instanceof AST_This) {
|
||||
if ((fn_strict || scan_this) && node instanceof AST_This) {
|
||||
return found = true;
|
||||
}
|
||||
if (node instanceof AST_Scope && !(node instanceof AST_Arrow)) {
|
||||
@@ -910,6 +911,8 @@ merge(Compressor.prototype, {
|
||||
&& all(iife.args, function(arg) {
|
||||
return !(arg instanceof AST_Expansion);
|
||||
})) {
|
||||
var fn_strict = compressor.has_directive("use strict");
|
||||
if (fn_strict && fn.body.indexOf(fn_strict) < 0) fn_strict = false;
|
||||
var names = Object.create(null);
|
||||
for (var i = fn.argnames.length; --i >= 0;) {
|
||||
var sym = fn.argnames[i];
|
||||
@@ -918,7 +921,7 @@ merge(Compressor.prototype, {
|
||||
if (sym instanceof AST_Expansion) {
|
||||
var elements = iife.args.slice(i);
|
||||
if (all(elements, function(arg) {
|
||||
return !has_overlapping_symbol(fn, arg);
|
||||
return !has_overlapping_symbol(fn, arg, fn_strict);
|
||||
})) {
|
||||
candidates.unshift(make_node(AST_VarDef, sym, {
|
||||
name: sym.expression,
|
||||
@@ -930,7 +933,7 @@ merge(Compressor.prototype, {
|
||||
} else {
|
||||
var arg = iife.args[i];
|
||||
if (!arg) arg = make_node(AST_Undefined, sym).transform(compressor);
|
||||
else if (has_overlapping_symbol(fn, arg)) arg = null;
|
||||
else if (has_overlapping_symbol(fn, arg, fn_strict)) arg = null;
|
||||
if (arg) candidates.unshift(make_node(AST_VarDef, sym, {
|
||||
name: sym,
|
||||
value: arg
|
||||
@@ -4866,7 +4869,10 @@ merge(Compressor.prototype, {
|
||||
// p:async function(){} ---> async p(){}
|
||||
// p:()=>{} ---> p(){}
|
||||
// p:async()=>{} ---> async p(){}
|
||||
if (compressor.option("ecma") >= 6) {
|
||||
var unsafe_methods = compressor.option("unsafe_methods");
|
||||
if (unsafe_methods
|
||||
&& compressor.option("ecma") >= 6
|
||||
&& (!(unsafe_methods instanceof RegExp) || unsafe_methods.test(self.key + ""))) {
|
||||
var key = self.key;
|
||||
var value = self.value;
|
||||
var is_arrow_with_block = value instanceof AST_Arrow
|
||||
|
||||
@@ -506,13 +506,17 @@ function OutputStream(options) {
|
||||
nodetype.DEFMETHOD("_codegen", generator);
|
||||
};
|
||||
|
||||
var use_asm = false;
|
||||
var in_directive = false;
|
||||
var active_scope = null;
|
||||
var use_asm = null;
|
||||
|
||||
AST_Node.DEFMETHOD("print", function(stream, force_parens){
|
||||
var self = this, generator = self._codegen, prev_use_asm = use_asm;
|
||||
if (self instanceof AST_Directive && self.value == "use asm" && stream.parent() instanceof AST_Scope) {
|
||||
use_asm = true;
|
||||
var self = this, generator = self._codegen;
|
||||
if (self instanceof AST_Scope) {
|
||||
active_scope = self;
|
||||
}
|
||||
else if (!use_asm && self instanceof AST_Directive && self.value == "use asm") {
|
||||
use_asm = active_scope;
|
||||
}
|
||||
function doit() {
|
||||
self.add_comments(stream);
|
||||
@@ -526,8 +530,8 @@ function OutputStream(options) {
|
||||
doit();
|
||||
}
|
||||
stream.pop_node();
|
||||
if (self instanceof AST_Scope) {
|
||||
use_asm = prev_use_asm;
|
||||
if (self === use_asm) {
|
||||
use_asm = null;
|
||||
}
|
||||
});
|
||||
AST_Node.DEFMETHOD("_print", AST_Node.prototype.print);
|
||||
|
||||
@@ -546,7 +546,7 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options){
|
||||
var mangle_with_block_scope =
|
||||
(!options.ie8 && node instanceof AST_SymbolCatch) ||
|
||||
node instanceof AST_SymbolBlockDeclaration;
|
||||
if (mangle_with_block_scope) {
|
||||
if (mangle_with_block_scope && options.reserved.indexOf(node.name) < 0) {
|
||||
to_mangle.push(node.definition());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"homepage": "https://github.com/mishoo/UglifyJS2/tree/harmony",
|
||||
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
|
||||
"license": "BSD-2-Clause",
|
||||
"version": "3.1.1",
|
||||
"version": "3.1.2",
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
|
||||
@@ -290,6 +290,7 @@ issue_2105_1: {
|
||||
passes: 3,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
|
||||
@@ -104,3 +104,65 @@ asm_mixed: {
|
||||
}
|
||||
}
|
||||
|
||||
asm_toplevel: {
|
||||
options = {}
|
||||
input: {
|
||||
"use asm";
|
||||
0.0;
|
||||
function f() {
|
||||
0.0;
|
||||
(function(){
|
||||
0.0;
|
||||
});
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '"use asm";0.0;function f(){0.0;(function(){0.0})}0.0;'
|
||||
}
|
||||
|
||||
asm_function_expression: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
var a = function() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
function f() {
|
||||
0.0;
|
||||
return function(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;var a=function(){"use asm";0.0};function f(){0;return function(){"use asm";0.0};0}0;'
|
||||
}
|
||||
|
||||
asm_nested_functions: {
|
||||
options = {}
|
||||
input: {
|
||||
0.0;
|
||||
function a() {
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function b() {
|
||||
0.0;
|
||||
function c(){
|
||||
"use asm";
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
function d(){
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
0.0;
|
||||
}
|
||||
expect_exact: '0;function a(){"use asm";0.0}0;function b(){0;function c(){"use asm";0.0}0;function d(){0}0}0;'
|
||||
}
|
||||
|
||||
@@ -2725,3 +2725,73 @@ issue_2313_2: {
|
||||
}
|
||||
expect_stdout: "0"
|
||||
}
|
||||
|
||||
issue_2319_1: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
return !function() {
|
||||
return this;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_2319_2: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
console.log(function(a) {
|
||||
"use strict";
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
console.log(function(a) {
|
||||
"use strict";
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect_stdout: "false"
|
||||
}
|
||||
|
||||
issue_2319_3: {
|
||||
options = {
|
||||
collapse_vars: true,
|
||||
unused: true,
|
||||
}
|
||||
input: {
|
||||
"use strict";
|
||||
console.log(function(a) {
|
||||
return a;
|
||||
}(!function() {
|
||||
return this;
|
||||
}()));
|
||||
}
|
||||
expect: {
|
||||
"use strict";
|
||||
console.log(function(a) {
|
||||
return !function() {
|
||||
return this;
|
||||
}();
|
||||
}());
|
||||
}
|
||||
expect_stdout: "true"
|
||||
}
|
||||
|
||||
@@ -804,3 +804,38 @@ object_spread_of_sequence: {
|
||||
console.log({ ...o || o });
|
||||
}
|
||||
}
|
||||
|
||||
// issue 2316
|
||||
class_name_can_be_preserved_with_reserved: {
|
||||
mangle = {
|
||||
reserved: [ "Foo" ],
|
||||
}
|
||||
input: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class Bar {}
|
||||
Bar.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var Bar = class Bar {};
|
||||
Bar.bar;
|
||||
}
|
||||
}
|
||||
expect: {
|
||||
function x() {
|
||||
class Foo {}
|
||||
Foo.bar;
|
||||
class a {}
|
||||
a.foo;
|
||||
}
|
||||
function y() {
|
||||
var Foo = class Foo {};
|
||||
Foo.bar;
|
||||
var a = class a {};
|
||||
a.bar;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -516,6 +516,7 @@ variable_as_computed_property: {
|
||||
prop_func_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -544,6 +545,7 @@ prop_func_to_concise_method: {
|
||||
prop_arrow_to_concise_method: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -592,6 +594,7 @@ concise_method_to_prop_arrow: {
|
||||
prop_func_to_async_concise_method: {
|
||||
options = {
|
||||
ecma: 8,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -614,6 +617,7 @@ prop_func_to_async_concise_method: {
|
||||
prop_func_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -646,6 +650,7 @@ prop_func_to_concise_method_various: {
|
||||
prop_arrows_to_concise_method_various: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
({
|
||||
@@ -674,6 +679,7 @@ prop_arrows_to_concise_method_various: {
|
||||
prop_arrow_with_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
@@ -711,6 +717,7 @@ prop_arrow_with_this: {
|
||||
prop_arrow_with_nested_this: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
input: {
|
||||
function run(arg) {
|
||||
|
||||
@@ -887,6 +887,7 @@ methods_keep_quoted_true: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -906,6 +907,7 @@ methods_keep_quoted_false: {
|
||||
options = {
|
||||
arrows: true,
|
||||
ecma: 6,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -931,6 +933,7 @@ methods_keep_quoted_from_dead_code: {
|
||||
evaluate: true,
|
||||
reduce_vars: true,
|
||||
side_effects: true,
|
||||
unsafe_methods: true,
|
||||
}
|
||||
mangle = {
|
||||
properties: {
|
||||
@@ -964,3 +967,88 @@ issue_2256: {
|
||||
g.keep = g.g;
|
||||
}
|
||||
}
|
||||
|
||||
issue_2321: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: false,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") }
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
foo: function() {
|
||||
console.log("foo");
|
||||
},
|
||||
bar() {
|
||||
console.log("bar");
|
||||
}
|
||||
};
|
||||
var foo = new f.foo();
|
||||
var bar = f.bar();
|
||||
}
|
||||
expect_stdout: [
|
||||
"foo",
|
||||
"bar",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
unsafe_methods_regex: {
|
||||
options = {
|
||||
ecma: 6,
|
||||
unsafe_methods: /^[A-Z1]/,
|
||||
}
|
||||
input: {
|
||||
var f = {
|
||||
123: function(){ console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar") },
|
||||
Baz: function(){ console.log("baz") },
|
||||
BOO: function(){ console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect: {
|
||||
var f = {
|
||||
123() { console.log("123") },
|
||||
foo: function(){ console.log("foo") },
|
||||
bar() { console.log("bar"); },
|
||||
Baz() { console.log("baz") },
|
||||
BOO() { console.log("boo") },
|
||||
null: function(){ console.log("null") },
|
||||
undefined: function(){ console.log("undefined") },
|
||||
};
|
||||
f[123]();
|
||||
new f.foo();
|
||||
f.bar();
|
||||
f.Baz();
|
||||
f.BOO();
|
||||
new f.null();
|
||||
new f.undefined();
|
||||
}
|
||||
expect_stdout: [
|
||||
"123",
|
||||
"foo",
|
||||
"bar",
|
||||
"baz",
|
||||
"boo",
|
||||
"null",
|
||||
"undefined",
|
||||
]
|
||||
node_version: ">=6"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user