Compare commits

...

59 Commits

Author SHA1 Message Date
Alex Lam S.L
787dfbed64 enhance inline (#5871) 2024-06-30 14:00:05 +03:00
Alex Lam S.L
6b23899ef3 fix corner case in collapse_vars (#5870)
fixes #5869
2024-06-28 21:19:58 +03:00
Alex Lam S.L
8c5a899986 enhance collapse_vars, unsafe & unused (#5868) 2024-06-26 22:38:27 +03:00
Alex Lam S.L
ed36c1ec5c fix corner case in unused (#5867)
fixes #5866
2024-06-26 16:13:29 +03:00
Alex Lam S.L
ce8ef52e2b enhance hoist_vars (#5865) 2024-06-25 23:56:39 +03:00
Alex Lam S.L
6669ea19ef fix corner case in hoist_vars (#5864)
fixes #5863
2024-06-25 19:19:47 +03:00
Alex Lam S.L
205a1d1f19 fix corner case in reduce_vars (#5862)
fixes #5860
fixes #5861
2024-06-21 01:29:11 +03:00
Alex Lam S.L
95d3ede664 fix corner cases in pure_getters & reduce_vars (#5859)
fixes #5856
fixes #5857
fixes #5858
2024-06-20 17:43:55 +03:00
Alex Lam S.L
8195a664fd fix corner case in collapse_vars (#5855)
fixes #5854
2024-06-19 05:15:03 +03:00
Alex Lam S.L
9c80456634 enhance dead_code & side_effects (#5840)
closes #5794
2024-06-19 01:36:04 +03:00
Alex Lam S.L
dc7aa32172 fix corner case in inline (#5853)
fixes #5851
2024-06-17 10:37:18 +03:00
Alex Lam S.L
23d74bedeb fix corner cases in join_vars (#5852)
fixes #5849
fixes #5850
2024-06-17 09:11:11 +03:00
Alex Lam S.L
f31311e439 fix corner case in inline (#5848)
fixes #5844
2024-06-17 06:38:16 +03:00
Alex Lam S.L
87c9edbbc7 fix corner case in unused (#5847)
fixes #5843
2024-06-17 04:36:02 +03:00
Alex Lam S.L
8dc99fa25f fix corner case in inline (#5846)
fixes #5842
2024-06-17 02:09:06 +03:00
Alex Lam S.L
dc51a23d31 fix corner case in inline (#5845)
fixes #5841
2024-06-17 02:08:53 +03:00
alexlamsl
0934c0e431 v3.18.0 2024-06-10 03:01:35 +03:00
Alex Lam S.L
ca4185a0fd improve ESTree compatibility (#5836)
closes #5834
closes #5835
2024-06-10 01:37:24 +03:00
Alex Lam S.L
e7b9b4aafb workaround function declaration quirks in ES6+ (#5833)
fixes #1666
2024-06-09 00:57:15 +03:00
Alex Lam S.L
3dfb379486 fix corner case in join_vars (#5832)
fixes #5831
2024-06-08 20:15:50 +03:00
Alex Lam S.L
2cb6454b1f fix corner case in merge_vars (#5830)
fixes #5829
2024-06-08 20:15:37 +03:00
Alex Lam S.L
09910771a1 fix corner case in awaits (#5828)
fixes #5791
2024-06-06 04:51:02 +03:00
Alex Lam S.L
c21a8eee7b include Node.js v20 in CI tests (#5827) 2024-06-05 23:49:20 +03:00
Alex Lam S.L
34b6143306 fix scope assignment to switch expressions (#5826)
fixes #5787
fixes #5792
2024-06-05 22:05:16 +03:00
Alex Lam S.L
ffe0fe7762 enhance join_vars (#5824)
closes #5790
2024-06-05 13:46:11 +03:00
forgotPassword
aa7c3389e6 domprops: enableHighAccuracy, maximumAge (#5822) 2024-06-05 04:17:30 +03:00
Alex Lam S.L
30fd331bf1 workaround node & npm issues (#5825)
- upgrade GitHub Actions dependencies
- workaround `sucrase` issues
2024-06-05 03:55:16 +03:00
Alex Lam S.L
f0ca9cfbe6 fix corner case in collapse_vars (#5780)
fixes #5779
2023-01-16 21:30:59 +08:00
Alex Lam S.L
a437a61518 fix corner case in reduce_vars (#5778)
fixes #5777
2023-01-16 21:30:45 +08:00
Alex Lam S.L
57dd3f6a2c fix corner case in evaluate (#5775)
fixes #5774
2023-01-07 20:38:04 +08:00
Alex Lam S.L
f07dc5cfba fix corner case in merge_vars (#5773)
fixes #5772
2023-01-07 18:27:18 +08:00
Alex Lam S.L
358faaacaa fix corner case in merge_vars (#5771)
fixes #5770
2023-01-04 13:17:04 +08:00
Alex Lam S.L
c9117041fa fix corner case in functions & inline (#5767)
fixes #5766
2022-12-27 08:59:16 +08:00
Alex Lam S.L
f2b6f1def0 improve --reduce-test (#5763) 2022-12-13 10:07:15 +08:00
Alex Lam S.L
797184f587 improve CLI interoperability (#5762) 2022-12-11 13:25:06 +08:00
Alex Lam S.L
78242ff21d minor lints (#5761) 2022-12-09 05:55:57 +08:00
Alex Lam S.L
dd88f3866b fix corner case in inline (#5760)
fixes #5759
2022-12-07 11:40:12 +08:00
Alex Lam S.L
17c3ae6cba improve usability (#5758) 2022-12-04 09:10:32 +08:00
Alex Lam S.L
0cbd5ea64a fix corner case in join_vars & loops (#5757)
fixes #5756
2022-12-03 11:44:37 +08:00
Alex Lam S.L
404794f5db fix corner case in if_return (#5755)
fixes #5754
2022-12-02 11:05:36 +08:00
Alex Lam S.L
650e63c8aa improve usability (#5753) 2022-12-02 10:14:07 +08:00
Alex Lam S.L
59e385591c improve interoperability of custom Errors (#5752)
closes #5751
2022-12-02 03:54:00 +08:00
Alex Lam S.L
574ca47666 fix corner case in yields (#5750)
fixes #5749
2022-12-01 05:18:04 +08:00
Alex Lam S.L
548f0938e8 fix corner case in collapse_vars (#5748)
fixes #5747
2022-12-01 03:59:22 +08:00
Alex Lam S.L
2352909c3d fix corner case in join_vars (#5746)
fixes #5745
2022-11-23 21:49:30 +08:00
Alex Lam S.L
4e7744af2d minor lints (#5744) 2022-11-23 07:26:35 +08:00
Alex Lam S.L
aef7065262 fix corner case in inline (#5742)
fixes #5741
2022-11-23 07:26:08 +08:00
Alex Lam S.L
24c3db11e6 minor lints (#5740) 2022-11-23 05:08:42 +08:00
Alex Lam S.L
e5cbd3e0f3 enhance join_vars (#5739) 2022-11-23 01:57:16 +08:00
Alex Lam S.L
68d62a8a31 enable --module by default (#5738)
- fix corner case in `mangle`
2022-11-22 02:25:34 +08:00
Alex Lam S.L
21aff996a5 enhance varify (#5737) 2022-11-21 11:30:02 +08:00
Alex Lam S.L
1d400f1a25 fix corner case in inline (#5736)
fixes #5735
2022-11-14 10:35:26 +08:00
Alex Lam S.L
7f424a55c5 suppress false positives in ufuzz (#5734) 2022-11-14 10:34:43 +08:00
Alex Lam S.L
e37a1489d4 fix corner case in reduce_vars (#5731)
fixes #5730
2022-11-03 13:05:07 +08:00
Alex Lam S.L
2b1c321ac8 fix corner case in evaluate (#5729)
fixes #5728
2022-11-03 12:25:48 +08:00
Alex Lam S.L
8d28052182 fix corner cases in evaluate & side_effects (#5726) 2022-11-01 09:38:33 +08:00
Alex Lam S.L
f40dbd6e33 fix corner case in inline & unused (#5725)
fixes #5724
2022-10-29 10:53:30 +08:00
Alex Lam S.L
7270671687 fix corner case in conditionals (#5723)
fixes #5722
2022-10-29 00:17:59 +08:00
Alex Lam S.L
30bf068768 fix corner case in collapse_vars (#5720)
fixes #5719
2022-10-24 22:16:06 +08:00
68 changed files with 3863 additions and 416 deletions

View File

@@ -9,11 +9,11 @@ jobs:
fail-fast: false
matrix:
options:
- '-mb braces'
- '--ie -c'
- '-mc'
- '-p acorn --toplevel -mco spidermonkey'
- '--toplevel -mc passes=3,pure_getters,unsafe'
- '-mb braces'
- '--toplevel -mc'
- '-p acorn -mco spidermonkey'
- '-mc passes=3,pure_getters,unsafe'
script:
- acorn.sh
- bootstrap.sh
@@ -50,7 +50,7 @@ jobs:
OPTIONS: ${{ matrix.options }}
SCRIPT: ${{ matrix.script }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Perform uglify, build & test
shell: bash
run: |

View File

@@ -7,7 +7,7 @@ jobs:
test:
strategy:
matrix:
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', latest ]
node: [ '0.10', '0.12', '4', '6', '8', '10', '12', '14', '16', '18', '20' ]
os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ]
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
@@ -17,8 +17,8 @@ jobs:
TYPE: ${{ matrix.script }}
UGLIFY_GITHUB_LAG: 10000
steps:
- uses: actions/checkout@v3
- uses: actions/cache@v3
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: tmp
key: tmp ${{ matrix.script }}

18
.github/workflows/moz.yml vendored Normal file
View File

@@ -0,0 +1,18 @@
name: ESTree
on:
pull_request:
push:
branches: [ master ]
jobs:
test:
name: fuzzing
runs-on: ubuntu-latest
env:
NODE: latest
steps:
- uses: actions/checkout@v4
- name: Perform tests
shell: bash
run: |
. ./test/release/install.sh
node test/mozilla-ast.js 5000

View File

@@ -32,7 +32,7 @@ jobs:
env:
NODE: ${{ matrix.node }}
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Perform fuzzing
shell: bash
run: |

View File

@@ -1,6 +1,6 @@
UglifyJS is released under the BSD license:
Copyright 2012-2019 (c) Mihai Bazon <mihai.bazon@gmail.com>
Copyright 2012-2024 (c) Mihai Bazon <mihai.bazon@gmail.com>
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions

View File

@@ -119,6 +119,8 @@ a double dash to prevent input files being used as option arguments:
--keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name.
--module Process input as ES module (implies --toplevel)
--no-module Avoid optimizations which may alter runtime behavior
under prior versions of JavaScript.
--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:
@@ -530,9 +532,9 @@ if (result.error) throw result.error;
- `mangle.properties` (default: `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options).
- `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` and support for top-level `await`,
alongside with `toplevel` enabled.
- `module` (default: `true`) — process input as ES module, i.e. implicit
`"use strict";` and support for top-level `await`. When explicitly specified,
also enables `toplevel`.
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously
used `nameCache` object if you wish to cache mangled variable and
@@ -750,7 +752,7 @@ to be `false` and all symbol names will be omitted.
- `merge_vars` (default: `true`) — combine and reuse variables.
- `module` (default: `false`) — set to `true` if you wish to process input as
ES module, i.e. implicit `"use strict";` alongside with `toplevel` enabled.
ES module, i.e. implicit `"use strict";`.
- `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parentheses that the
@@ -777,11 +779,11 @@ to be `false` and all symbol names will be omitted.
overhead (compression will be slower). Make sure symbols under `pure_funcs`
are also under `mangle.reserved` to avoid mangling.
- `pure_getters` (default: `"strict"`) — If you pass `true` for
this, UglifyJS will assume that object property access
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects.
Specify `"strict"` to treat `foo.bar` as side-effect-free only when
`foo` is certain to not throw, i.e. not `null` or `undefined`.
- `pure_getters` (default: `"strict"`) — Pass `true` for UglifyJS to assume that
object property access (e.g. `foo.bar` or `a[42]`) does not throw exception or
alter program states via getter function. Pass `"strict"` to allow dropping or
reordering `foo.bar` only if `foo` is not `null` or `undefined` and is safe to
access as a variable. Pass `false` to retain all property accesses.
- `reduce_funcs` (default: `true`) — Allows single-use functions to be
inlined as function expressions when permissible allowing further
@@ -925,9 +927,8 @@ can pass additional arguments that control the code output:
regexps (affects directives with non-ascii characters becoming invalid)
- `beautify` (default: `true`) — whether to actually beautify the 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.
Passing `-b` will set this to true. Use `-O` if you want to generate minified
code and specify additional arguments.
- `braces` (default: `false`) — always insert braces in `if`, `for`,
`do`, `while` or `with` statements, even if their body is a single

View File

@@ -108,7 +108,8 @@ function process_option(name, no_value) {
" --ie Support non-standard Internet Explorer.",
" --keep-fargs Do not mangle/drop function arguments.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.",
" --module Process input as ES module (implies --toplevel)",
" --module Process input as ES module (implies --toplevel).",
" --no-module Process input with improved JavaScript compatibility.",
" --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.",
" --no-rename Disable symbol expansion.",
@@ -155,7 +156,6 @@ function process_option(name, no_value) {
case "expression":
case "ie":
case "ie8":
case "module":
case "timings":
case "toplevel":
case "v8":
@@ -201,6 +201,12 @@ function process_option(name, no_value) {
if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = parse_js(read_value(), options.mangle.properties);
break;
case "module":
options.module = true;
break;
case "no-module":
options.module = false;
break;
case "name-cache":
nameCache = read_value(true);
options.nameCache = JSON.parse(read_file(nameCache, "{}"));
@@ -295,9 +301,19 @@ if (specified["in-situ"]) {
process.stdin.setEncoding("utf8");
process.stdin.once("data", function() {
clearTimeout(timerId);
}).on("data", function(chunk) {
}).on("data", process.stdin.isTTY ? function(chunk) {
// emulate console input termination via Ctrl+D / Ctrl+Z
var match = /[\x04\x1a]\r?\n?$/.exec(chunk);
if (match) {
chunks.push(chunk.slice(0, -match[0].length));
process.stdin.pause();
process.stdin.emit("end");
} else {
chunks.push(chunk);
}
} : function(chunk) {
chunks.push(chunk);
}).on("end", function() {
}).once("end", function() {
files = { STDIN: chunks.join("") };
run();
});

View File

@@ -169,8 +169,6 @@ DEF_BITPROPS(AST_Node, [
"private",
// AST_Call
"pure",
// AST_Assign
"redundant",
// AST_Node
"single_use",
// AST_ClassProperty

File diff suppressed because it is too large Load Diff

View File

@@ -82,14 +82,14 @@ function minify(files, options) {
keep_fargs: false,
keep_fnames: false,
mangle: {},
module: false,
module: undefined,
nameCache: null,
output: {},
parse: {},
rename: undefined,
sourceMap: false,
timings: false,
toplevel: !!(options && options["module"]),
toplevel: options && !options["expression"] && options["module"] ? true : undefined,
v8: false,
validate: false,
warnings: false,
@@ -104,8 +104,9 @@ function minify(files, options) {
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]);
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.toplevel) set_shorthand("toplevel", options, [ "compress", "mangle", "rename" ]);
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" ]);
var quoted_props;

View File

@@ -125,6 +125,16 @@
body: normalize_directives(from_moz(M.body).body),
});
},
CallExpression: function(M) {
return new AST_Call({
start: my_start_token(M),
end: my_end_token(M),
expression: from_moz(M.callee),
args: M.arguments.map(from_moz),
optional: M.optional,
pure: M.pure,
});
},
ClassDeclaration: function(M) {
return new AST_DefClass({
start: my_start_token(M),
@@ -458,7 +468,7 @@
end: my_end_token(M),
};
if (M.bigint) {
args.value = M.bigint.toLowerCase() + "n";
args.value = M.bigint.toLowerCase();
return new AST_BigInt(args);
}
var val = M.value;
@@ -631,7 +641,6 @@
map("AssignmentPattern", AST_DefaultValue, "left>name, right>value");
map("ConditionalExpression", AST_Conditional, "test>condition, consequent>consequent, alternate>alternative");
map("NewExpression", AST_New, "callee>expression, arguments@args, pure=pure");
map("CallExpression", AST_Call, "callee>expression, arguments@args, optional=optional, pure=pure");
map("SequenceExpression", AST_Sequence, "expressions@expressions");
map("SpreadElement", AST_Spread, "argument>expression");
map("ObjectExpression", AST_Object, "properties@properties");
@@ -668,6 +677,7 @@
type: "ArrowFunctionExpression",
async: is_async(M),
params: params,
expression: !!M.value,
body: M.value ? to_moz(M.value) : to_moz_scope("BlockStatement", M),
};
return {
@@ -680,6 +690,21 @@
};
});
def_to_moz(AST_Call, function To_Moz_CallExpression(M) {
var expr = M.expression;
if (M.args.length == 1 && expr instanceof AST_SymbolRef && expr.name == "import") return {
type: "ImportExpression",
source: to_moz(M.args[0]),
};
return {
type: "CallExpression",
callee: to_moz(expr),
arguments: M.args.map(to_moz),
optional: M.optional,
pure: M.pure,
};
});
def_to_moz(AST_DefClass, function To_Moz_ClassDeclaration(M) {
return {
type: "ClassDeclaration",
@@ -767,6 +792,7 @@
def_to_moz(AST_Directive, function To_Moz_Directive(M) {
return {
type: "ExpressionStatement",
directive: M.value,
expression: set_moz_loc(M, {
type: "Literal",
value: M.value,
@@ -787,7 +813,6 @@
type: "TryStatement",
block: to_moz_block(M),
handler: to_moz(M.bcatch),
guardedHandlers: [],
finalizer: to_moz(M.bfinally),
};
});
@@ -796,7 +821,6 @@
return {
type: "CatchClause",
param: to_moz(M.argname),
guard: null,
body: to_moz_block(M),
};
});
@@ -805,6 +829,7 @@
return {
type: "ExportNamedDeclaration",
declaration: to_moz(M.body),
specifiers: [],
};
});
@@ -954,6 +979,8 @@
type: "Property",
kind: "init",
computed: computed,
method: false,
shorthand: false,
key: key,
value: to_moz(M.value),
};
@@ -990,6 +1017,7 @@
kind: kind,
computed: computed,
method: M instanceof AST_ObjectMethod,
shorthand: false,
key: key,
value: to_moz(M.value),
};
@@ -1043,8 +1071,8 @@
var value = M.value;
return {
type: "Literal",
bigint: value.slice(0, -1),
raw: value,
bigint: value,
raw: value + "n",
};
});

View File

@@ -1783,6 +1783,9 @@ function OutputStream(options) {
output.print(self.strings[i]);
output.print("`");
});
DEFPRINT(AST_BigInt, function(output) {
output.print(this.value + "n");
});
DEFPRINT(AST_Constant, function(output) {
output.print("" + this.value);
});

View File

@@ -207,11 +207,14 @@ function JS_Parse_Error(message, filename, line, col, pos) {
this.line = line;
this.col = col;
this.pos = pos;
try {
throw new SyntaxError(message, filename, line, col);
} catch (cause) {
configure_error_stack(this, cause);
}
}
JS_Parse_Error.prototype = Object.create(Error.prototype);
JS_Parse_Error.prototype = Object.create(SyntaxError.prototype);
JS_Parse_Error.prototype.constructor = JS_Parse_Error;
JS_Parse_Error.prototype.name = "SyntaxError";
configure_error_stack(JS_Parse_Error);
function js_error(message, filename, line, col, pos) {
throw new JS_Parse_Error(message, filename, line, col, pos);
@@ -391,7 +394,8 @@ function tokenizer($TEXT, filename, html5_comments, shebang) {
var valid = parse_js_number(num);
if (isNaN(valid)) parse_error("Invalid syntax: " + num);
if (has_dot || has_e || peek() != "n") return token("num", valid);
return token("bigint", num.toLowerCase() + next());
next();
return token("bigint", num.toLowerCase());
}
function read_escaped_char(in_string) {

View File

@@ -68,9 +68,7 @@ SymbolDef.prototype = {
var cache = this.global && options.cache && options.cache.props;
if (cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name);
} else if (this.unmangleable(options)) {
names_in_use(this.scope, options).set(this.name, true);
} else {
} else if (!this.unmangleable(options)) {
var def = this.redefined();
if (def) {
this.mangled_name = def.mangled_name || def.name;
@@ -180,6 +178,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
});
return true;
}
if (node instanceof AST_Switch) {
node.expression.walk(tw);
walk_scope(function() {
walk_body(node, tw);
});
return true;
}
if (node instanceof AST_SwitchBranch) {
node.init_vars(scope);
descend();
@@ -439,35 +444,43 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
}
});
function init_block_vars(scope, parent) {
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes
scope.parent_scope = parent; // the parent scope (null if this is the top level)
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope)
scope.variables = new Dictionary(); // map name to AST_SymbolVar (variables defined in this scope; includes functions)
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances
function init_block_vars(scope, parent, orig) {
// variables from this or outer scope(s) that are referenced from this or inner scopes
scope.enclosed = orig ? orig.enclosed.slice() : [];
// map name to AST_SymbolDefun (functions defined in this scope)
scope.functions = orig ? orig.functions.clone() : new Dictionary();
// map name to AST_SymbolVar (variables defined in this scope; includes functions)
scope.variables = orig ? orig.variables.clone() : new Dictionary();
if (!parent) return;
// top-level tracking of SymbolDef instances
scope.make_def = parent.make_def;
// the parent scope (null if this is the top level)
scope.parent_scope = parent;
}
function init_scope_vars(scope, parent) {
init_block_vars(scope, parent);
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval`
scope.uses_with = false; // will be set to true if this or some nested scope uses the `with` statement
function init_scope_vars(scope, parent, orig) {
init_block_vars(scope, parent, orig);
// will be set to true if this or nested scope uses the global `eval`
scope.uses_eval = false;
// will be set to true if this or some nested scope uses the `with` statement
scope.uses_with = false;
}
AST_BlockScope.DEFMETHOD("init_vars", function(parent_scope) {
init_block_vars(this, parent_scope);
AST_BlockScope.DEFMETHOD("init_vars", function(parent, orig) {
init_block_vars(this, parent, orig);
});
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
AST_Scope.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent, orig);
});
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
AST_Arrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent, orig);
return this;
});
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent, orig);
});
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) {
init_scope_vars(this, parent_scope);
AST_Lambda.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent, orig);
this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({
name: "arguments",
@@ -643,8 +656,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
}, true);
}
var to_mangle = node.to_mangle = [];
node.variables.each(function(def) {
if (!defer_redef(def)) to_mangle.push(def);
node.variables.each(function(def, name) {
if (def.unmangleable(options)) {
names_in_use(node, options).set(name, true);
} else if (!defer_redef(def)) {
to_mangle.push(def);
}
});
descend();
if (options.cache && node instanceof AST_Toplevel) {

View File

@@ -55,28 +55,41 @@ function find_if(func, array) {
for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
}
function configure_error_stack(fn) {
Object.defineProperty(fn.prototype, "stack", {
function configure_error_stack(ex, cause) {
var stack = ex.name + ": " + ex.message;
Object.defineProperty(ex, "stack", {
get: function() {
var err = new Error(this.message);
err.name = this.name;
try {
throw err;
} catch (e) {
return e.stack;
if (cause) {
cause.name = "" + ex.name;
stack = "" + cause.stack;
var msg = "" + cause.message;
cause = null;
var index = stack.indexOf(msg);
if (index < 0) {
index = 0;
} else {
index += msg.length;
index = stack.indexOf("\n", index) + 1;
}
stack = stack.slice(0, index) + stack.slice(stack.indexOf("\n", index) + 1);
}
}
return stack;
},
});
}
function DefaultsError(msg, defs) {
this.message = msg;
this.defs = defs;
try {
throw new Error(msg);
} catch (cause) {
configure_error_stack(this, cause);
}
}
DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
function defaults(args, defs, croak) {
if (croak) for (var i in args) {

View File

@@ -3,7 +3,7 @@
"description": "JavaScript parser, mangler/compressor and beautifier toolkit",
"author": "Mihai Bazon <mihai.bazon@gmail.com> (http://lisperator.net/)",
"license": "BSD-2-Clause",
"version": "3.17.4",
"version": "3.18.0",
"engines": {
"node": ">=0.8.0"
},

View File

@@ -3,6 +3,7 @@
"use strict";
require("../tools/tty");
var createHash = require("crypto").createHash;
var fetch = require("./fetch");
var spawn = require("child_process").spawn;

View File

@@ -690,6 +690,65 @@ inline_iife_within_arrow: {
node_version: ">=4"
}
instanceof_lambda_1: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log(42 instanceof (() => {}));
}
expect: {
console.log(false);
}
expect_stdout: "false"
node_version: ">=4"
}
instanceof_lambda_2: {
options = {
evaluate: true,
side_effects: false,
}
input: {
console.log(null instanceof (() => {}));
}
expect: {
console.log((null, () => {}, false));
}
expect_stdout: "false"
node_version: ">=4"
}
instanceof_lambda_3: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log({} instanceof (() => {}));
}
expect: {
console.log({} instanceof (() => {}));
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=4"
}
instanceof_lambda_4: {
options = {
side_effects: true,
}
input: {
({ p: "foo" }) instanceof (() => {});
}
expect: {
[] instanceof (() => {});
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=4"
}
issue_4388: {
options = {
inline: true,
@@ -1253,7 +1312,7 @@ issue_5653: {
}
expect: {
console.log((a => {
return console, +{};
return +{};
})());
}
expect_stdout: "NaN"

View File

@@ -1348,7 +1348,7 @@ functions_inner_var: {
node_version: ">=8"
}
instanceof_lambda: {
instanceof_lambda_1: {
options = {
evaluate: true,
side_effects: true,
@@ -1363,6 +1363,50 @@ instanceof_lambda: {
node_version: ">=8"
}
instanceof_lambda_2: {
options = {
evaluate: true,
side_effects: false,
}
input: {
console.log(null instanceof async function() {});
}
expect: {
console.log((null, async function() {}, false));
}
expect_stdout: "false"
node_version: ">=8"
}
instanceof_lambda_3: {
options = {
evaluate: true,
side_effects: true,
}
input: {
console.log({} instanceof async function() {});
}
expect: {
console.log({} instanceof async function() {});
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=8"
}
instanceof_lambda_4: {
options = {
side_effects: true,
}
input: {
({ p: "foo" }) instanceof async function() {};
}
expect: {
[] instanceof async function() {};
}
expect_stdout: TypeError("Function has non-object prototype 'undefined' in instanceof check")
node_version: ">=8"
}
issue_4335_1: {
options = {
inline: true,
@@ -3598,3 +3642,66 @@ issue_5692_2: {
]
node_version: ">=8"
}
issue_5791: {
options = {
awaits: true,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
(async function() {
async function f() {
try {
await {
then(resolve) {
setImmediate(() => {
console.log("foo");
resolve();
});
},
};
} catch (e) {
console.log("FAIL", e);
}
}
async function g() {
try {
await f();
} catch (e) {}
}
await g();
console.log("bar");
})();
}
expect: {
(async function() {
await async function() {
try {
await async function() {
try {
await {
then(resolve) {
setImmediate(() => {
console.log("foo");
resolve();
});
},
};
} catch (e) {
console.log("FAIL", e);
}
}();
} catch (e) {}
}();
console.log("bar");
})();
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=8"
}

View File

@@ -90,3 +90,17 @@ issue_4801: {
expect_stdout: "PASS"
node_version: ">=10.4.0"
}
issue_5728: {
options = {
evaluate: true,
}
input: {
console.log("" + 4n + 2);
}
expect: {
console.log("42");
}
expect_stdout: "42"
node_version: ">=10.4.0"
}

View File

@@ -47,3 +47,45 @@ keep_some_blocks: {
} else stuff();
}
}
issue_1666: {
input: {
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect: {
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect_stdout: true
}
issue_1666_strict: {
input: {
"use strict";
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect: {
"use strict";
var a = 42;
{
function a() {}
a();
}
console.log("PASS");
}
expect_stdout: true
}

View File

@@ -1165,9 +1165,9 @@ collapse_rhs_static: {
"use strict";
var a = "FAIL";
class A {
static p = a = "PASS";
static p = "PASS";
}
console.log(a);
console.log(a = "PASS");
}
expect_stdout: "PASS"
node_version: ">=12"
@@ -3901,3 +3901,132 @@ issue_5682_class_key_computed: {
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5724: {
options = {
arrows: true,
inline: true,
keep_fargs: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
class A {
static P = function(a) {
console.log(a, a);
}(a);
}
}
expect: {
"use strict";
(function(a) {
console.log(a, a);
})(a);
}
expect_stdout: ReferenceError("a is not defined")
node_version: ">=12"
}
issue_5735_1: {
options = {
inline: true,
}
input: {
console.log(typeof function(a) {
return class {
static P = { ...a };
};
}([ 42..p ] = []));
}
expect: {
console.log(typeof function(a) {
return class {
static P = { ...a };
};
}([ 42..p ] = []));
}
expect_stdout: "function"
node_version: ">=12"
}
issue_5735_2: {
options = {
inline: true,
}
input: {
console.log(typeof function(a) {
return class {
p = a;
};
}(console.log("PASS")));
}
expect: {
console.log(typeof function(a) {
return class {
p = a;
};
}(console.log("PASS")));
}
expect_stdout: [
"PASS",
"function",
]
node_version: ">=12"
}
issue_5747_1: {
options = {
collapse_vars: true,
}
input: {
"use strict";
(async function() {
var a = await 42;
class A {
static P = a && console.log(typeof this);
}
})();
}
expect: {
"use strict";
(async function() {
var a = await 42;
class A {
static P = a && console.log(typeof this);
}
})();
}
expect_stdout: "function"
node_version: ">=12"
}
issue_5747_2: {
options = {
collapse_vars: true,
}
input: {
"use strict";
(async function() {
var a = await 42;
class A {
static {
a && console.log(typeof this);
}
}
})();
}
expect: {
"use strict";
(async function() {
var a = await 42;
class A {
static {
a && console.log(typeof this);
}
}
})();
}
expect_stdout: "function"
node_version: ">=16"
}

View File

@@ -4996,7 +4996,7 @@ cascade_forin: {
]
}
unsafe_builtin: {
unsafe_builtin_1: {
options = {
collapse_vars: true,
pure_getters: "strict",
@@ -5020,6 +5020,46 @@ unsafe_builtin: {
expect_stdout: "1 4"
}
unsafe_builtin_2: {
options = {
collapse_vars: true,
toplevel: true,
unsafe: true,
unused: true,
}
input: {
A = "PASS";
var a = A;
console.log(a);
}
expect: {
console.log(A = "PASS");
}
expect_stdout: "PASS"
}
unsafe_builtin_3: {
options = {
collapse_vars: true,
unsafe: true,
unused: true,
}
input: {
A = "PASS";
(function() {
var a = A;
console.log(a);
})();
}
expect: {
A = "PASS";
(function() {
console.log(A);
})();
}
expect_stdout: "PASS"
}
return_1: {
options = {
collapse_vars: true,
@@ -7350,30 +7390,39 @@ substitution_assign: {
b = 1 + (b = a);
console.log(a, b);
}
function f4(a, b) {
b = 1 + (a = b);
console.log(a, b);
}
f1(42, "foo");
f2(42, "foo");
f3(42, "foo");
f4("bar", 41);
}
expect: {
function f1(a, b) {
console.log(f1 = a, a);
}
function f2(a, b) {
a = 1 + (b = a);
console.log(a, b);
console.log(a = 1 + (b = a), b);
}
function f3(a, b) {
b = 1 + (b = a);
console.log(a, b = 1 + (b = a));
}
function f4(a, b) {
b = 1 + (a = b);
console.log(a, b);
}
f1(42, "foo");
f2(42, "foo");
f3(42, "foo");
f4("bar", 41);
}
expect_stdout: [
"42 42",
"43 42",
"42 43",
"41 42",
]
}
@@ -9864,7 +9913,8 @@ issue_5276: {
}
expect: {
var a = A = "PASS";
a.p = a.p + null - 42;
a.p += null;
a.p -= 42;
console.log(a);
}
expect_stdout: "PASS"
@@ -10121,3 +10171,189 @@ issue_5643: {
}
expect_stdout: "42"
}
issue_5719: {
options = {
collapse_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = 42, b;
switch (b = a) {
case a:
case b:
case a++:
}
console.log(a === b++ ? "PASS" : "FAIL");
}
expect: {
var a = 42, b;
switch (b = a) {
case a:
case b:
case a++:
}
console.log(a === b++ ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
}
issue_5779: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
}
input: {
var a = A = "foo";
a.p = 42;
if (a && !a.p)
console.log("PASS");
}
expect: {
var a = A = "foo";
a.p = 42;
if (a, !a.p)
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_1666: {
options = {
collapse_vars: true,
}
input: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_strict: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_undefined: {
options = {
collapse_vars: true,
}
input: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}
issue_1666_undefined_strict: {
options = {
collapse_vars: true,
}
input: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}
issue_5869: {
options = {
collapse_vars: true,
evaluate: true,
pure_getters: "strict",
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a, b, log = console.log;
log();
a.p = 0;
b = a;
log(b);
}
expect: {
var a, log = console.log;
log();
log(void (a.p = 0));
}
expect_stdout: TypeError("Cannot set properties of undefined")
}

View File

@@ -3068,3 +3068,23 @@ issue_5712: {
}
expect_stdout: "PASS"
}
issue_5722: {
options = {
conditionals: true,
evaluate: true,
keep_fnames: true,
side_effects: true,
}
input: {
var a = true;
a && function f() {
return 42;
}(a++) ? null + (console.log("PASS") && a++) : "";
}
expect: {
var a = true;
a && (void a++, console.log("PASS")) && a++;
}
expect_stdout: "PASS"
}

View File

@@ -2204,3 +2204,30 @@ issue_5660: {
}
expect_stdout: true
}
issue_5787: {
options = {
unused: true,
}
input: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect_stdout: true
}

View File

@@ -2293,7 +2293,7 @@ issue_5340_3: {
}
expect: {
var a;
(function() {})(a = true["p"]);
(function() {})(a = true.p);
console.log(a);
}
expect_stdout: "undefined"
@@ -3069,3 +3069,69 @@ issue_5651: {
expect_stdout: true
node_version: ">=6"
}
issue_5774: {
options = {
collapse_vars: true,
conditionals: true,
evaluate: true,
join_vars: true,
reduce_vars: true,
sequences: true,
unsafe: true,
}
input: {
(function() {
while (console.log("PASS")) {
if (console) {
a = void 0;
var b = void 0;
var c = void 0;
([ a = 0 ] = [ b, b ]);
var a;
}
}
})();
}
expect: {
(function() {
while (console.log("PASS")) {
var a, b, c, a;
console && (
c = b = a = void 0,
[ a = 0 ] = [ a, a ]
);
}
})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5863: {
options = {
collapse_vars: true,
hoist_vars: true,
}
input: {
console.log(typeof function f(a = function() {
f = 42;
return f;
}()) {
var f;
var f;
return a;
}());
}
expect: {
console.log(typeof function f(a = function() {
f = 42;
return f;
}()) {
var f;
return a;
}());
}
expect_stdout: "function"
node_version: ">=6"
}

View File

@@ -1339,7 +1339,7 @@ maintain_position_var: {
}
expect: {
A = "FAIL";
var [ , b ] = [ A ];
var b = [ A ][1];
console.log(b || "PASS");
}
expect_stdout: "PASS"
@@ -1382,7 +1382,7 @@ side_effects_object: {
}
}
expect: {
var a = null, c = (console, 42["c"]);
var a = null, c = (console, 42..c);
try {
c[a = "PASS"];
} catch (e) {
@@ -1684,7 +1684,7 @@ singleton_1: {
expect: {
var b, a = "P"[0], o = {};
o.p = [ "FAIL"["1"] ][0];
o.q = { foo: "S"[0] }["foo"];
o.q = { foo: "S"[0] }.foo;
[ b = "S" ] = [];
console.log(a + o.p + o.q + b);
}
@@ -3886,3 +3886,358 @@ issue_5651: {
expect_stdout: true
node_version: ">=6"
}
issue_5843_1: {
options = {
unused: true,
}
input: {
var { p: a } = {
__proto__: {
p: "PASS",
},
};
console.log(a);
}
expect: {
var a = {
__proto__: {
p: "PASS",
},
}.p;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5843_2: {
options = {
side_effects: true,
unused: true,
}
input: {
var a;
({ p: a } = {
__proto__: {
p: "PASS",
},
});
console.log(a);
}
expect: {
var a;
a = {
__proto__: {
p: "PASS",
},
}.p;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5844: {
options = {
inline: true,
}
input: {
try {
(function(a) {
[ a.p ] = 42;
})(console.log("PASS"));
} catch (e) {}
}
expect: {
try {
(function(a) {
[ a.p ] = 42;
})(console.log("PASS"));
} catch (e) {}
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5854_1: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a) {
var b = a;
a++;
[ b[0] ] = [ "foo" ];
return a;
}([]) ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
var b = a;
a++;
[ b[0] ] = [ "foo" ];
return a;
}([]) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5854_2: {
options = {
collapse_vars: true,
}
input: {
console.log(function(a) {
var b = a;
a++;
({ p: b[0] } = { p: "foo" });
return a;
}([]) ? "PASS" : "FAIL");
}
expect: {
console.log(function(a) {
var b = a;
a++;
({ p: b[0] } = { p: "foo" });
return a;
}([]) ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_1: {
options = {
unused: true,
}
input: {
var a = {};
var { p: { q: b } } = {
p: a,
r: a.q = "PASS",
};
console.log(b);
}
expect: {
var a = {};
var { q: b } = {
p: a,
r: a.q = "PASS",
}.p;
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_2: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = {}, b;
({ p: { q: b } } = {
p: a,
r: a.q = "PASS",
});
console.log(b);
}
expect: {
var b, a = {};
({ q: b } = {
p: a,
r: a.q = "PASS",
}.p);
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_3: {
options = {
unused: true,
}
input: {
var a = {};
var [ { p: b } ] = [ a, a.p = "PASS" ];
console.log(b);
}
expect: {
var a = {};
var { p: b } = [ a, a.p = "PASS" ][0];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_4: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = {}, b;
[ { p: b } ] = [ a, a.p = "PASS" ];
console.log(b);
}
expect: {
var b, a = {};
({ p: b } = [ a, a.p = "PASS" ][0]);
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_5: {
options = {
unused: true,
}
input: {
var a = [];
var [ [ b ] ] = [ a, a[0] = "PASS" ];
console.log(b);
}
expect: {
var a = [];
var [ b ] = [ a, a[0] = "PASS" ][0];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_6: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = [], b;
[ [ b ] ] = [ a, a[0] = "PASS" ];
console.log(b);
}
expect: {
var b, a = [];
[ b ] = [ a, a[0] = "PASS" ][0];
console.log(b);
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_7: {
options = {
unused: true,
}
input: {
var a = {};
var [ { p: b }, c ] = [ a, a.p = {} ];
console.log(b === c ? "PASS" : "FAIL");
}
expect: {
var a = {};
var [ { p: b }, c ] = [ a, a.p = {} ];
console.log(b === c ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_8: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = {}, b, c;
[ { p: b }, c ] = [ a, a.p = {} ];
console.log(b === c ? "PASS" : "FAIL");
}
expect: {
var b, c, a = {};
[ { p: b }, c ] = [ a, a.p = {} ];
console.log(b === c ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_9: {
options = {
unused: true,
}
input: {
var a = {};
var [ b, { p: c } ] = [ a.p = {}, a ];
console.log(b === c ? "PASS" : "FAIL");
}
expect: {
var a = {};
var [ b, c ] = [ a.p = {}, a.p ];
console.log(b === c ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_10: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = {}, b, c;
[ b, { p: c } ] = [ a.p = {}, a ];
console.log(b === c ? "PASS" : "FAIL");
}
expect: {
var b, c, a = {};
[ b, c ] = [ a.p = {}, a.p ];
console.log(b === c ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_11: {
options = {
unused: true,
}
input: {
var a = {};
var { p: { q: b } } = { p: a = { q: {} } };
console.log(a.q === b ? "PASS" : "FAIL");
}
expect: {
var a = {};
var b = { p: (a = { q: {} }).q }.p;
console.log(a.q === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5866_12: {
options = {
side_effects: true,
unused: true,
}
input: {
var a = {}, b;
({ p: { q: b } } = { p: a = { q: {} } });
console.log(a.q === b ? "PASS" : "FAIL");
}
expect: {
var b, a = {};
b = { p: (a = { q: {} }).q }.p;
console.log(a.q === b ? "PASS" : "FAIL");
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -260,7 +260,7 @@ hoist_exports_2: {
}
}
expect: {
let e, a = 42["foo"];
let e, a = 42..foo;
function f(t, { [e]: o }) {
t(o, f);
}

View File

@@ -8663,6 +8663,7 @@ module_inline: {
inline: true,
module: true,
reduce_vars: true,
toplevel: true,
}
input: {
var a = f;
@@ -8740,3 +8741,233 @@ issue_5692: {
}
expect_stdout: "PASS"
}
issue_5766_1: {
options = {
booleans: true,
evaluate: true,
functions: true,
inline: true,
passes: 2,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
log = function(a) {
console.log(typeof a);
};
do {
(function() {
try {
var f = function() {};
log(f && f);
} catch (e) {}
})();
} while (0);
}
expect: {
log = function(a) {
console.log(typeof a);
};
do {
try {
function f() {}
log(f);
} catch (e) {}
} while (0);
}
expect_stdout: "function"
}
issue_5766_2: {
options = {
evaluate: true,
functions: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
log = function(a) {
console.log(typeof a);
};
do {
(function() {
try {
var f = function() {};
log(f && f);
} catch (e) {}
})();
} while (0);
}
expect: {
log = function(a) {
console.log(typeof a);
};
do {
try {
function f() {}
log(f);
} catch (e) {}
} while (0);
}
expect_stdout: "function"
}
issue_5841_1: {
options = {
conditionals: true,
evaluate: true,
inline: true,
join_vars: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a = 42;
(function() {
f();
var b = f();
function f() {
if (console && a)
g && g();
}
function g() {
var c;
for (;console.log("foo"););
(function h(d) {
d && d.p;
})();
}
})();
}
expect: {
var a = 42;
(function() {
f();
f();
function f() {
{
if (console && a) {
for (;console.log("foo"););
return;
}
return;
}
}
})();
}
expect_stdout: [
"foo",
"foo",
]
}
issue_5841_2: {
options = {
conditionals: true,
evaluate: true,
if_return: true,
inline: true,
join_vars: true,
passes: 2,
reduce_funcs: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a = 42;
(function() {
f();
var b = f();
function f() {
if (console && a)
g && g();
}
function g() {
var c;
for (;console.log("foo"););
(function h(d) {
d && d.p;
})();
}
})();
}
expect: {
var a = 42;
(function() {
f();
f();
function f() {
if (console && a)
for (;console.log("foo"););
}
})();
}
expect_stdout: [
"foo",
"foo",
]
}
issue_5851_1: {
options = {
inline: true,
reduce_vars: true,
toplevel: true,
}
input: {
console.log("PASS") && f();
function f() {
return f();
}
f;
}
expect: {
console.log("PASS") && f();
function f() {
return f();
}
f;
}
expect_stdout: "PASS"
}
issue_5851_2: {
options = {
conditionals: true,
inline: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
input: {
var a = f();
f();
function f() {
if (console.log("foo"))
console && f();
}
}
expect: {
f();
f();
function f() {
console.log("foo") && console && f();
}
}
expect_stdout: [
"foo",
"foo",
]
}

View File

@@ -228,6 +228,7 @@ issue_4489: {
evaluate: true,
hoist_vars: true,
reduce_vars: true,
sequences: true,
toplevel: true,
unused: true,
}
@@ -363,6 +364,7 @@ issue_4893_1: {
evaluate: true,
hoist_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
}
@@ -383,9 +385,8 @@ issue_4893_1: {
}
expect: {
try{
(function f() {
(function() {
null.p += 42;
f;
})();
} catch (e) {
console.log("PASS");
@@ -422,9 +423,7 @@ issue_4893_2: {
expect: {
try{
(function() {
var a;
a = null;
a.p += 42;
null.p += 42;
})();
} catch (e) {
console.log("PASS");
@@ -610,6 +609,7 @@ issue_5411_2: {
evaluate: true,
hoist_vars: true,
reduce_vars: true,
sequences: true,
toplevel: true,
unused: true,
}
@@ -622,9 +622,9 @@ issue_5411_2: {
}
expect: {
var b, c;
b++;
b++,
b = "PASS",
c;
c,
console.log(b);
}
expect_stdout: "PASS"

View File

@@ -167,6 +167,34 @@ rename_mangle: {
}
}
mangle_export_import: {
mangle = {
toplevel: true,
}
input: {
export let o = A;
import { p as A } from "foo";
}
expect: {
export let o = p;
import { p } from "foo";
}
}
mangle_import_export: {
mangle = {
toplevel: true,
}
input: {
import { p as A } from "foo";
export let o = A;
}
expect: {
import { p } from "foo";
export let o = p;
}
}
keep_ref: {
options = {
reduce_vars: true,

View File

@@ -26,7 +26,7 @@ record_update: {
currying: {
options = {
inline: true,
passes: 2,
passes: 3,
pure_getters: "strict",
reduce_funcs: true,
reduce_vars: true,

View File

@@ -16,6 +16,105 @@ join_vars_assign: {
expect_stdout: "PASS"
}
join_array_assignments_1: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = [ "foo", , "bar" ];
a[1] = "baz";
a[7] = "moo";
a[0] = "moz";
return a;
}().join());
}
expect: {
console.log(function () {
var a = [ "moz", "baz", "bar", , , , , "moo" ];
return a;
}().join());
}
expect_stdout: "moz,baz,bar,,,,,moo"
}
join_array_assignments_2: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = [ "foo" ];
a[1] = "bar";
a[7] = "baz";
a[2] = "moo";
return a;
}().join());
}
expect: {
console.log(function () {
var a = [ "foo", "bar" ];
a[7] = "baz";
a[2] = "moo";
return a;
}().join());
}
expect_stdout: "foo,bar,moo,,,,,baz"
}
join_array_assignments_3: {
options = {
evaluate: true,
join_vars: true,
}
input: {
console.log(function () {
var a = [ "foo" ];
a[1] = "bar";
a.b = "baz";
a[2] = "moo";
return a;
}().join());
}
expect: {
console.log(function () {
var a = [ "foo", "bar" ];
a.b = "baz";
a[2] = "moo";
return a;
}().join());
}
expect_stdout: true
}
join_array_assignments_4: {
options = {
evaluate: true,
join_vars: true,
side_effects: true,
}
input: {
console.log(function () {
var a = [ "foo" ];
a[0] = "bar";
a[1] = a;
a[2] = "baz";
return a;
}().join());
}
expect: {
console.log(function () {
var a = [ "bar" ];
a[1] = a;
a[2] = "baz";
return a;
}().join());
}
expect_stdout: true
}
join_object_assignments_1: {
options = {
evaluate: true,
@@ -1394,3 +1493,37 @@ issue_5175: {
}
expect_stdout: "PASS PASS"
}
issue_5831: {
options = {
evaluate: true,
join_vars: true,
}
input: {
var a = [ console.log("PASS") ];
a[0] = 42;
}
expect: {
var a = [ (console.log("PASS"), 42) ];
}
expect_stdout: "PASS"
}
issue_5849: {
options = {
evaluate: true,
join_vars: true,
side_effects: true,
}
input: {
var a;
a = [ 42 ];
a[0] = "PASS";
console.log(a.join(""));
}
expect: {
var a, a = [ "PASS" ];
console.log(a.join(""));
}
expect_stdout: "PASS"
}

View File

@@ -1130,6 +1130,130 @@ default_init: {
node_version: ">=4"
}
join_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (var c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
join_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect: {
"use strict";
let a = "foo", b = "bar";
for (let c of [ a, b ])
console.log(c);
}
expect_stdout: [
"foo",
"bar",
]
node_version: ">=4"
}
keep_let_var_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
var a = "foo";
let b = "bar";
for (var c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect: {
"use strict";
var a = "foo", c;
let b = "bar";
for (c of [ a, b ])
console.log(c);
function f() {
return a;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"foo",
]
node_version: ">=4"
}
keep_let_var_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect: {
"use strict";
let a = "foo";
var b = "bar";
for (let c of [ a, b ])
console.log(c);
function f() {
return b;
}
console.log(f(f));
}
expect_stdout: [
"foo",
"bar",
"bar",
]
node_version: ">=4"
}
issue_4191: {
options = {
functions: true,
@@ -2170,3 +2294,275 @@ issue_5591: {
]
node_version: ">=4"
}
issue_5741: {
options = {
inline: true,
join_vars: true,
reduce_vars: true,
}
input: {
"use strict";
(function(a) {
let b = function() {
var c = a;
console.log(c);
}();
function g() {
a++;
b;
}
})("PASS");
}
expect: {
"use strict";
(function(a) {
let b = (c = a, void console.log(c));
var c;
function g() {
a++;
b;
}
})("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5745_1: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
}
a;
console.log(a);
}
expect: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
}
a;
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5745_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
{
let f = function() {
return f && "PASS";
};
var a = f();
a;
console.log(a);
}
}
expect: {
"use strict";
{
let f = function() {
return f && "PASS";
}, a = f();
a;
console.log(a);
}
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_1: {
options = {
join_vars: true,
loops: true,
reduce_vars: true,
toplevel: true,
}
input: {
"use strict";
do {
function f() {
return b;
}
var a = "PASS".toString();
let b;
console.log(a);
} while (!console);
}
expect: {
"use strict";
do {
function f() {
return b;
}
let a = "PASS".toString(), b;
console.log(a);
} while (!console);
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_2: {
options = {
join_vars: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
function f() {
let a = console.log("PASS");
{
var b;
for (var c in b) {
b;
var c = function() {
a;
};
}
}
}
f();
}
expect: {
"use strict";
(function() {
let a = console.log("PASS"), b;
for (c in b) {
b;
var c = function() {
a;
};
}
})();
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5756_3: {
options = {
module: true,
reduce_vars: true,
toplevel: true,
unused: true,
varify: true,
}
input: {
"use strict";
console.log(f()());
function f() {
const a = "PASS";
return function() {
return a;
};
}
}
expect: {
"use strict";
console.log(function() {
let a = "PASS";
return function() {
return a;
};
}()());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5759: {
options = {
collapse_vars: true,
inline: true,
join_vars: true,
reduce_vars: true,
unused: true,
}
input: {
"use strict";
function f() {
for (var a in [ true ]) {
let b;
(function() {
var c = void 0;
b;
console.log(c);
var d = null;
console.log(c);
})();
}
}
f();
}
expect: {
"use strict";
function f() {
for (var a in [ true ]) {
let b;
var c = c = void 0;
b;
console.log(c);
console.log(c);
}
}
f();
}
expect_stdout: [
"undefined",
"undefined",
]
node_version: ">=4"
}
issue_5787: {
options = {
unused: true,
}
input: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
// Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared
let a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
let a = "PASS";
return a;
}
}());
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -3889,3 +3889,114 @@ issue_5714: {
"42",
]
}
issue_5770_1: {
options = {
dead_code: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: do {
if (console)
for (var a = "FAIL 1"; a; a--)
continue L;
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect: {
L: do {
if (console) {
var a = "FAIL 1";
if (a)
continue L;
}
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect_stdout: "PASS"
}
issue_5770_2: {
options = {
conditionals: true,
dead_code: true,
if_return: true,
loops: true,
merge_vars: true,
toplevel: true,
}
input: {
L: do {
for (var a = "FAIL 1"; a; a--)
continue L;
var b = "FAIL 2";
} while (console.log(b || "PASS"));
}
expect: {
L: do {
var a = "FAIL 1";
var b;
} while (a || (b = "FAIL 2"), console.log(b || "PASS"));
}
expect_stdout: "PASS"
}
issue_5772_1: {
options = {
dead_code: true,
merge_vars: true,
loops: true,
}
input: {
(function(a) {
while (--a)
return;
var b = console.log("foo") && (c = 42) ? 0 : console.log(c);
var c = b;
})();
}
expect: {
(function(a) {
if (--a)
return;
var a = console.log("foo") && (c = 42) ? 0 : console.log(c);
var c = a;
})();
}
expect_stdout: [
"foo",
"undefined",
]
}
issue_5772_2: {
options = {
dead_code: true,
merge_vars: true,
loops: true,
}
input: {
(function(a) {
while (--a)
return;
var b;
var c = console.log("foo") && (b = 1) ? 2 : 3;
console.log(b, c);
})();
}
expect: {
(function(a) {
if (--a)
return;
var b;
var a = console.log("foo") && (b = 1) ? 2 : 3;
console.log(b, a);
})();
}
expect_stdout: [
"foo",
"undefined 3",
]
}

View File

@@ -344,3 +344,43 @@ issue_5266: {
]
node_version: ">=14"
}
issue_5829_1: {
options = {
merge_vars: true,
}
input: {
(function f(a) {
var b;
(!a ?? (b = 0)) || console.log(b || "PASS");
})("FAIL");
}
expect: {
(function f(a) {
var b;
(!a ?? (b = 0)) || console.log(b || "PASS");
})("FAIL");
}
expect_stdout: "PASS"
node_version: ">=14"
}
issue_5829_2: {
options = {
merge_vars: true,
}
input: {
(function f(a) {
var b;
(a ?? (b = 0)) && console.log(b || "PASS");
})("FAIL");
}
expect: {
(function f(a) {
var b;
(a ?? (b = 0)) && console.log(b || "PASS");
})("FAIL");
}
expect_stdout: "PASS"
node_version: ">=14"
}

View File

@@ -617,3 +617,33 @@ issue_5292_sub_pure_getters_strict: {
]
node_version: ">=14"
}
issue_5856: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
try {
var a;
a?.p;
a.q;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
try {
var a;
a?.p;
a.q;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
node_version: ">=14"
}

View File

@@ -147,7 +147,7 @@ relational: {
"bar" >= "bar";
}
expect: {
0 instanceof bar();
[] instanceof bar();
bar();
bar(), bar();
bar();

View File

@@ -1687,3 +1687,31 @@ issue_4939: {
}
expect_stdout: "PASS"
}
issue_5856: {
options = {
pure_getters: true,
reduce_vars: true,
side_effects: true,
unused: true,
}
input: {
var a = [ "FAIL", "PASS" ];
(function(b) {
var c = b[0];
b[0] = b[1];
b[1] = c;
})(a);
console.log(a[0]);
}
expect: {
var a = [ "FAIL", "PASS" ];
(function(b) {
var c = b[0];
b[0] = b[1];
b[1] = c;
})(a);
console.log(a[0]);
}
expect_stdout: "PASS"
}

View File

@@ -8062,3 +8062,287 @@ issue_5716_5: {
}
expect_stdout: "42"
}
issue_5730_1: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
L: {
var f = function() {
console.log(a);
};
}
f();
a++;
}
expect: {
var a = "PASS";
var f = function() {
console.log(a);
};
f();
a++;
}
expect_stdout: "PASS"
}
issue_5730_2: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var a = "PASS";
try {
var f = function() {
console.log(a);
};
} finally {}
f();
a++;
}
expect: {
var a = "PASS";
try {
var f = function() {
console.log(a);
};
} finally {}
f();
a++;
}
expect_stdout: "PASS"
}
issue_5730_3: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var f, a = "PASS";
L: {
f = function() {
console.log(a);
};
}
f();
a++;
}
expect: {
var f, a = "PASS";
f = function() {
console.log(a);
};
f();
a++;
}
expect_stdout: "PASS"
}
issue_5777_1: {
options = {
reduce_vars: true,
unused: true,
}
input: {
function f() {
(function(a) {
function g() {
h();
}
g();
a = function() {};
function h() {
console.log(a);
}
})("PASS");
}
f();
}
expect: {
function f() {
(function(a) {
(function() {
h();
})();
a = function() {};
function h() {
console.log(a);
}
})("PASS");
}
f();
}
expect_stdout: "PASS"
}
issue_5777_2: {
options = {
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
function f(a) {
(function() {
function g() {
h();
}
g();
a = function() {};
function h() {
console.log(a);
}
})();
}
f("PASS");
}
expect: {
(function(a) {
(function() {
(function() {
h();
})();
a = function() {};
function h() {
console.log(a);
}
})();
})("PASS");
}
expect_stdout: "PASS"
}
issue_1666: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_strict: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect: {
"use strict";
var x = 42;
{
x();
function x() {
console.log("foo");
}
}
console.log(typeof x);
}
expect_stdout: true
}
issue_1666_undefined: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}
issue_1666_undefined_strict: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
}
input: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect: {
"use strict";
var undefined = 42;
{
undefined();
function undefined() {
console.log("foo");
}
}
console.log(typeof undefined);
}
expect_stdout: true
}

View File

@@ -739,3 +739,55 @@ issue_3480_ie8_toplevel: {
}
expect_stdout: "PASS"
}
issue_5787_1: {
rename = true
input: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
const a = 42;
switch (a) {
case 42:
const a = "PASS";
return a;
}
}());
}
expect_stdout: true
}
issue_5787_2: {
rename = true
input: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
// Node.js v4 (vm): SyntaxError: Identifier 'a' has already been declared
let a = "PASS";
return a;
}
}());
}
expect: {
console.log(function() {
let a = 42;
switch (a) {
case 42:
let b = "PASS";
return b;
}
}());
}
expect_stdout: "PASS"
node_version: ">=6"
}

View File

@@ -125,6 +125,7 @@ log_nested: {
timers: {
options = {
evaluate: true,
reduce_vars: true,
toplevel: true,
unused: true,
@@ -132,26 +133,22 @@ timers: {
input: {
var count = 0, interval = 1000, duration = 3210;
var timer = setInterval(function() {
console.log(++count);
if (!count++) setTimeout(function() {
clearInterval(timer);
console.log(count <= 4 ? "PASS" : "FAIL");
}, duration);
}, interval);
setTimeout(function() {
clearInterval(timer);
}, duration);
}
expect: {
var count = 0;
var timer = setInterval(function() {
console.log(++count);
if (!count++) setTimeout(function() {
clearInterval(timer);
console.log(count <= 4 ? "PASS" : "FAIL");
}, 3210);
}, 1000);
setTimeout(function() {
clearInterval(timer);
}, 3210);
}
expect_stdout: [
"1",
"2",
"3",
]
expect_stdout: "PASS"
node_version: ">=0.12"
}

View File

@@ -724,3 +724,246 @@ retain_instanceof: {
}
expect_stdout: "PASS"
}
drop_access: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var o = {};
o.p;
try {
(function() {
o.q;
})();
console.log("PASS");
} catch (e) {
console.log("FAIL");
}
}
expect: {
var o = {};
o.p;
try {
console.log("PASS");
} catch (e) {
console.log("FAIL");
}
}
expect_stdout: "PASS"
}
keep_access: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var o = {};
o.p;
o = null;
try {
(function() {
o.q;
})();
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
var o = {};
o.p;
o = null;
try {
(function() {
o.q;
})();
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
keep_access_after_call: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var o = {};
o.p;
o.q;
f();
try {
o.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
function f() {
o = null;
}
}
expect: {
var o = {};
o.p;
f();
try {
o.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
function f() {
o = null;
}
}
expect_stdout: "PASS"
}
issue_5860_drop_1: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = {};
a.p;
var a;
a.q;
console.log("PASS");
}
expect: {
var a = {};
a.p;
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_5860_drop_2: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
a = {};
a.p;
var a;
a.q;
console.log("PASS");
}
expect: {
a = {};
a.p;
var a;
console.log("PASS");
}
expect_stdout: "PASS"
}
issue_5860_keep_1: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = {};
a.p;
a.q;
var a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
var a = {};
a.p;
var a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_5860_keep_2: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
a = {};
a.p;
a.q;
var a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
a = {};
a.p;
var a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}
issue_5860_keep_3: {
options = {
pure_getters: "strict",
reduce_vars: true,
side_effects: true,
}
input: {
var a = {};
a.p;
a.q;
a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect: {
var a = {};
a.p;
a = null;
try {
a.r;
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
expect_stdout: "PASS"
}

View File

@@ -1253,3 +1253,24 @@ issue_5602: {
]
node_version: ">=6"
}
issue_5850: {
options = {
evaluate: true,
join_vars: true,
unused: true,
}
input: {
var a = [ ..."FAIL" ];
a[0] = "P";
a[2] = a[3] = "S";
console.log(a.join(""));
}
expect: {
var a = [ ..."FAIL" ];
a[0] = "P";
a[2] = a[3] = "S";
console.log(a.join(""));
}
node_version: ">=6"
}

View File

@@ -329,6 +329,42 @@ forin_const_2: {
node_version: ">=6"
}
forin_const_3: {
options = {
module: true,
reduce_vars: true,
toplevel: true,
varify: true,
}
input: {
"use strict";
const o = {
p: 42,
q: "PASS",
};
for (const k in o)
(function f() {
console.log(k, o[k]);
})();
}
expect: {
"use strict";
let o = {
p: 42,
q: "PASS",
};
for (let k in o)
(function f() {
console.log(k, o[k]);
})();
}
expect_stdout: [
"p 42",
"q PASS",
]
node_version: ">=4"
}
forin_let_1: {
options = {
join_vars: true,

View File

@@ -896,7 +896,7 @@ dont_inline_nested: {
node_version: ">=4"
}
drop_body: {
drop_body_1: {
options = {
side_effects: true,
yields: true,
@@ -906,6 +906,27 @@ drop_body: {
console.log("bar");
})([ console.log("baz") ]);
}
expect: {
void ([ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ]);
}
expect_stdout: [
"baz",
"foo",
]
node_version: ">=6"
}
drop_body_2: {
options = {
passes: 2,
side_effects: true,
yields: true,
}
input: {
(function*([ , a = console.log("foo") ]) {
console.log("bar");
})([ console.log("baz") ]);
}
expect: {
[ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ];
}
@@ -1365,7 +1386,7 @@ issue_5076_1: {
expect: {
var a;
console.log("PASS"),
a = 42["a"];
a = 42..a;
}
expect_stdout: "PASS"
node_version: ">=6"
@@ -2019,7 +2040,7 @@ issue_5684: {
node_version: ">=10"
}
issue_5707: {
issue_5707_1: {
options = {
hoist_props: true,
reduce_vars: true,
@@ -2033,6 +2054,28 @@ issue_5707: {
function* f(c = (b = 42, console.log("PASS"))) {}
b = f();
}
expect: {
(function(c = console.log("PASS")) {})();
}
expect_stdout: "PASS"
node_version: ">=6"
}
issue_5707_2: {
options = {
hoist_props: true,
passes: 2,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a, b;
function* f(c = (b = 42, console.log("PASS"))) {}
b = f();
}
expect: {
console.log("PASS");
}
@@ -2076,3 +2119,131 @@ issue_5710: {
expect_stdout: "PASS"
node_version: ">=10"
}
issue_5749_1: {
options = {
collapse_vars: true,
reduce_vars: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
function* f() {}
a = f(new function() {
var b = a |= 0, c = a += console.log("PASS");
}());
}
expect: {
(function() {})(function() {
console.log("PASS");
}());
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5749_2: {
options = {
collapse_vars: true,
inline: true,
reduce_vars: true,
sequences: true,
side_effects: true,
toplevel: true,
unused: true,
yields: true,
}
input: {
var a;
function* f() {}
a = f(new function() {
var b = a |= 0, c = a += console.log("PASS");
}());
}
expect: {
console.log("PASS");
}
expect_stdout: "PASS"
node_version: ">=4"
}
issue_5754: {
options = {
if_return: true,
}
input: {
async function* f(a, b) {
try {
if (a)
return void 0;
} finally {
console.log(b);
}
}
f(42, "foo").next();
f(null, "bar").next();
console.log("baz");
}
expect: {
async function* f(a, b) {
try {
if (a)
return void 0;
} finally {
console.log(b);
}
}
f(42, "foo").next();
f(null, "bar").next();
console.log("baz");
}
expect_stdout: [
"bar",
"baz",
"foo",
]
node_version: ">=10"
}
issue_5842: {
options = {
inline: true,
}
input: {
var a = "FAIL";
(async function*() {
(function() {
try {
try {
return console;
} finally {
a = "PASS";
}
} catch (e) {}
FAIL;
})();
})().next();
console.log(a);
}
expect: {
var a = "FAIL";
(async function*() {
(function() {
try {
try {
return console;
} finally {
a = "PASS";
}
} catch (e) {}
FAIL;
})();
})().next();
console.log(a);
}
expect_stdout: "PASS"
node_version: ">=10"
}

View File

@@ -1,16 +1,10 @@
// (beautified)
var b = 0;
var expr2 = (0 - 1 - .1 - .1).toString();
for (var key2 in expr2) {
--b;
}
console.log(b);
// output: -19
console.log(expr2);
// output: -1.2000000000000002
//
// minify: -4
// minify: -1.2
//
// options: {
// "compress": {

View File

@@ -14,7 +14,7 @@ if (typeof phantom == "undefined") {
args.splice(debug, 1);
debug = true;
}
if (!args.length) args.push("-mcb", "beautify=false,webkit");
if (!args.length) args.push("-mcO", "webkit");
args.unshift("bin/uglifyjs");
args.push("--validate", "--timings");
var child_process = require("child_process");
@@ -63,7 +63,10 @@ if (typeof phantom == "undefined") {
function npm(args, done) {
args.push("--loglevel=error");
child_process.spawn(cmd, args, { stdio: [ "ignore", 1, 2 ] }).on("exit", done);
child_process.spawn(cmd, args, {
shell: true,
stdio: [ "ignore", 1, 2 ],
}).on("exit", done);
}
(function install() {

View File

@@ -206,7 +206,13 @@ describe("bin/uglifyjs", function() {
}, 1000);
});
it("Should work with --keep-fargs (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m';
var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fargs",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
@@ -214,7 +220,14 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --keep-fargs (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fargs -m -c';
var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fargs",
"--mangle",
"--no-module",
"--compress",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){return x(function(a){return a*a})}}function g(op){return op(1)+op(2)}console.log(5==f(g)());\n");
@@ -222,7 +235,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with keep_fargs under mangler options", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js -m keep_fargs=true';
var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--mangle", "keep_fargs=true",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(){function n(a){return a*a}return x(n)}}function g(op){return op(1)+op(2)}console.log(f(g)()==5);\n");
@@ -230,7 +248,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --keep-fnames (mangle only)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m';
var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fnames",
"--mangle",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(r){return function(){function n(n){return n*n}return r(n)}}function g(n){return n(1)+n(2)}console.log(f(g)()==5);\n");
@@ -238,7 +261,14 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --keep-fnames (mangle & compress)", function(done) {
var command = uglifyjscmd + ' test/input/issue-1431/sample.js --keep-fnames -m -c';
var command = [
uglifyjscmd,
"test/input/issue-1431/sample.js",
"--keep-fnames",
"--mangle",
"--no-module",
"--compress",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(){return n(function n(r){return r*r})}}function g(n){return n(1)+n(2)}console.log(5==f(g)());\n");
@@ -557,7 +587,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (delete x)", function(done) {
var command = uglifyjscmd + " test/input/invalid/delete.js";
var command = [
uglifyjscmd,
"test/input/invalid/delete.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -571,7 +605,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (function g(arguments))", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_1.js";
var command = [
uglifyjscmd,
"test/input/invalid/function_1.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -585,7 +623,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (function eval())", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_2.js";
var command = [
uglifyjscmd,
"test/input/invalid/function_2.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -599,7 +641,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (iife arguments())", function(done) {
var command = uglifyjscmd + " test/input/invalid/function_3.js";
var command = [
uglifyjscmd,
"test/input/invalid/function_3.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -613,7 +659,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (catch (eval))", function(done) {
var command = uglifyjscmd + " test/input/invalid/try.js";
var command = [
uglifyjscmd,
"test/input/invalid/try.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -627,7 +677,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (var eval)", function(done) {
var command = uglifyjscmd + " test/input/invalid/var.js";
var command = [
uglifyjscmd,
"test/input/invalid/var.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -641,7 +695,11 @@ describe("bin/uglifyjs", function() {
});
});
it("Should throw syntax error (var { eval })", function(done) {
var command = uglifyjscmd + " test/input/invalid/destructured_var.js";
var command = [
uglifyjscmd,
"test/input/invalid/destructured_var.js",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
assert.ok(err);
assert.strictEqual(stdout, "");
@@ -807,7 +865,8 @@ describe("bin/uglifyjs", function() {
var command = [
uglifyjscmd,
"test/input/issue-2310/input.js",
"-c",
"--compress",
"--no-module",
"--source-map", "url=inline",
].join(" ");
exec(command, function(err, stdout, stderr) {
@@ -840,7 +899,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --mangle reserved=[]", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=[callback]";
var command = [
uglifyjscmd,
"test/input/issue-505/input.js",
"--mangle", "reserved=[callback]",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n');
@@ -848,7 +912,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with --mangle reserved=false", function(done) {
var command = uglifyjscmd + " test/input/issue-505/input.js -m reserved=false";
var command = [
uglifyjscmd,
"test/input/issue-505/input.js",
"--mangle", "reserved=false",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n');
@@ -865,7 +934,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with mangle.properties.regex from --config-file", function(done) {
var command = uglifyjscmd + " test/input/issue-3315/input.js --config-file test/input/issue-3315/config.json";
var command = [
uglifyjscmd,
"test/input/issue-3315/input.js",
"--config-file", "test/input/issue-3315/config.json",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n');
@@ -882,7 +956,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with explicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js --rename";
var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--no-module",
"--rename",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n");
@@ -890,7 +969,14 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with explicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2 --no-rename";
var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--mangle",
"--no-module",
"--no-rename",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n");
@@ -898,7 +984,13 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with implicit --rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -mc passes=2";
var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n+n}\n");
@@ -906,7 +998,12 @@ describe("bin/uglifyjs", function() {
});
});
it("Should work with implicit --no-rename", function(done) {
var command = uglifyjscmd + " test/input/rename/input.js -c passes=2";
var command = [
uglifyjscmd,
"test/input/rename/input.js",
"--compress", "passes=2",
"--no-module",
].join(" ");
exec(command, function(err, stdout, stderr) {
if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
@@ -971,12 +1068,7 @@ describe("bin/uglifyjs", function() {
]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, [
"console.log(function(){",
"var p={p:25},n={p:121},o={p:1024};",
"return p.p+n.p+o.p",
"}());\n",
].join(""));
assert.strictEqual(stdout, "console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\n");
assert.strictEqual(run_code(stdout), run_code(code));
done();
}).stdin.end(code);

View File

@@ -476,7 +476,9 @@ describe("comments", function() {
for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n";
for (; i <= 10000; ++i) js += "/* " + i + " */ /**/";
js += "x; }";
var result = UglifyJS.minify(js, { mangle: false });
var result = UglifyJS.minify(js, {
mangle: false,
});
assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
});
});

View File

@@ -373,7 +373,9 @@ describe("Directives", function() {
'function f(){}'
],
].forEach(function(test) {
var result = UglifyJS.minify(test[0]);
var result = UglifyJS.minify(test[0], {
module: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, test[1], test[0]);
});

View File

@@ -5,31 +5,44 @@ var path = require("path");
describe("bin/uglifyjs with input file globs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("bin/uglifyjs with one input file extension glob.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/foo.*" -cm';
var command = [
uglifyjscmd,
'"test/input/issue-1242/foo.*"',
"--compress",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n');
done();
});
});
it("bin/uglifyjs with one input file name glob.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/b*.es5" -cm';
var command = [
uglifyjscmd,
'"test/input/issue-1242/b*.es5"',
"--compress",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n');
done();
});
});
it("bin/uglifyjs with multiple input file globs.", function(done) {
var command = uglifyjscmd + ' "test/input/issue-1242/???.es5" "test/input/issue-1242/*.js" -mc toplevel,passes=3';
var command = [
uglifyjscmd,
'"test/input/issue-1242/???.es5"',
'"test/input/issue-1242/*.js"',
"--compress", "toplevel,passes=3",
"--mangle",
"--no-module",
].join(" ");
exec(command, function(err, stdout) {
if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
done();
});

View File

@@ -6,8 +6,10 @@ describe("Input file as map", function() {
var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
};
var result = UglifyJS.minify(jsMap, {sourceMap: true});
var result = UglifyJS.minify(jsMap, {
sourceMap: true,
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sources, ['/scripts/foo.js']);
@@ -26,8 +28,10 @@ describe("Input file as map", function() {
'var foo = {"x": 1, y: 2, \'z\': 3};',
'var bar = 15;'
];
var result = UglifyJS.minify(jsSeq, {sourceMap: true});
var result = UglifyJS.minify(jsSeq, {
sourceMap: true,
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
assert.deepEqual(map.sources, ['0', '1']);
@@ -37,8 +41,12 @@ describe("Input file as map", function() {
var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};'
};
var result = UglifyJS.minify(jsMap, {sourceMap: {includeSources: true}});
var result = UglifyJS.minify(jsMap, {
sourceMap: {
includeSources: true,
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sourcesContent, ['var foo = {"x": 1, y: 2, \'z\': 3};']);

View File

@@ -48,8 +48,8 @@ describe("minify", function() {
var result = UglifyJS.minify(code, {
mangle: {
cache: cache,
toplevel: true
}
toplevel: true,
},
});
if (result.error) throw result.error;
original += code;
@@ -79,9 +79,9 @@ describe("minify", function() {
var code = read("test/input/issue-1242/" + file);
var result = UglifyJS.minify(code, {
mangle: {
toplevel: true
toplevel: true,
},
nameCache: cache
nameCache: cache,
});
if (result.error) throw result.error;
original += code;
@@ -162,8 +162,9 @@ describe("minify", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = UglifyJS.minify(js, {
output: {
keep_quoted_props: true
}});
keep_quoted_props: true,
},
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
});
it("Should preserve quote styles when quote_style is 3", function() {
@@ -171,8 +172,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, {
output: {
keep_quoted_props: true,
quote_style: 3
}});
quote_style: 3,
},
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
});
it("Should not preserve quotes in object literals when disabled", function() {
@@ -180,8 +182,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, {
output: {
keep_quoted_props: false,
quote_style: 3
}});
quote_style: 3,
},
});
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
});
});
@@ -223,7 +226,7 @@ describe("minify", function() {
output: {
comments: "all",
beautify: false,
}
},
});
var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();");
@@ -233,7 +236,7 @@ describe("minify", function() {
output: {
comments: "all",
beautify: false,
}
},
});
var code = result.code;
assert.strictEqual(code, "var a=function(){foo()}();");
@@ -301,7 +304,7 @@ describe("minify", function() {
compress: false,
mangle: false,
output: {
ast: true
ast: true,
},
}).ast;
assert.strictEqual(ast.TYPE, "Toplevel");
@@ -312,9 +315,9 @@ describe("minify", function() {
var stat = ast.body[0].body[0];
UglifyJS.minify(ast, {
compress: {
sequences: false
sequences: false,
},
mangle: false
mangle: false,
});
assert.ok(stat.body);
assert.strictEqual(stat.print_to_string(), "a=x()");

View File

@@ -236,9 +236,9 @@ describe("test/reduce.js", function() {
});
it("Should report trailing whitespace difference in stringified format", function() {
var code = [
"for (var a in (1 - .8).toString()) {",
"[].forEach.call((1 - .8).toString(), function() {",
" console.log();",
"}",
"});",
].join("\n");
var result = reduce_test(code, {
compress: {
@@ -333,6 +333,7 @@ describe("test/reduce.js", function() {
unsafe_math: true,
},
mangle: false,
module: false,
});
if (result.error) throw result.error;
assert.strictEqual(result.code, [
@@ -346,7 +347,8 @@ describe("test/reduce.js", function() {
'// "compress": {',
'// "unsafe_math": true',
'// },',
'// "mangle": false',
'// "mangle": false,',
'// "module": false',
"// }",
].join("\n"));
});

View File

@@ -296,8 +296,8 @@ describe("sourcemaps", function() {
it("Should append source map to output js when sourceMapInline is enabled", function() {
var result = UglifyJS.minify('var a = function(foo) { return foo; };', {
sourceMap: {
url: "inline"
}
url: "inline",
},
});
if (result.error) throw result.error;
var code = result.code;
@@ -305,7 +305,7 @@ describe("sourcemaps", function() {
"//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIjAiXSwibmFtZXMiOlsiYSIsImZvbyJdLCJtYXBwaW5ncyI6IkFBQUEsSUFBSUEsRUFBSSxTQUFTQyxHQUFPLE9BQU9BLENBQUsifQ==");
});
it("Should not append source map to output js when sourceMapInline is not enabled", function() {
var result = UglifyJS.minify('var a = function(foo) { return foo; };');
var result = UglifyJS.minify("var a = function(foo) { return foo; };");
if (result.error) throw result.error;
var code = result.code;
assert.strictEqual(code, "var a=function(n){return n};");
@@ -316,11 +316,11 @@ describe("sourcemaps", function() {
directives: false,
},
output: {
max_line_len: 20
max_line_len: 20,
},
sourceMap: {
url: "inline"
}
url: "inline",
},
});
if (result.error) throw result.error;
assert.strictEqual(result.code, read("test/input/issue-505/output.js"));
@@ -334,7 +334,7 @@ describe("sourcemaps", function() {
sourceMap: {
includeSources: true,
url: "inline",
}
},
});
if (result.error) throw result.error;
var map = JSON.parse(result.map);
@@ -348,7 +348,7 @@ describe("sourcemaps", function() {
sourceMap: {
content: "inline",
includeSources: true,
}
},
});
if (result.error) throw result.error;
map = JSON.parse(result.map);

View File

@@ -20,6 +20,9 @@ Error.stackTraceLimit = Infinity;
module.exports = function reduce_test(testcase, minify_options, reduce_options) {
minify_options = minify_options || {};
reduce_options = reduce_options || {};
var parse_options = {
module: minify_options.module || minify_options.module === undefined,
}
var print_options = {};
[
"ie",
@@ -190,7 +193,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
else if (node instanceof U.AST_BlockStatement) {
if (in_list && node.body.filter(function(node) {
return node instanceof U.AST_Const;
return node instanceof U.AST_Const || node instanceof U.AST_Let;
}).length == 0) {
node.start._permute++;
CHANGED = true;
@@ -332,19 +335,21 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
}
else if (node instanceof U.AST_ForEnumeration) {
var expr;
switch ((node.start._permute * steps | 0) % 3) {
switch ((node.start._permute * steps | 0) % 4) {
case 0:
if (node.init instanceof U.AST_Definitions) {
if (node.init instanceof U.AST_Const) break;
if (node.init.definitions[0].name instanceof U.AST_Destructured) break;
}
expr = node.init;
break;
case 1:
expr = node.object;
break;
case 1:
expr = wrap_with_console_log(node.object);
break;
case 2:
if (!has_loopcontrol(node.body, node, parent)) expr = node.body;
if (has_loopcontrol(node.body, node, parent)) break;
expr = node.body;
break;
case 3:
if (!(node.init instanceof U.AST_Var)) break;
if (node.init.definitions[0].name instanceof U.AST_Destructured) break;
expr = node.init;
break;
}
node.start._permute += step;
@@ -358,9 +363,17 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
node.condition,
node.body,
node.alternative,
][ (node.start._permute * steps | 0) % 3 ];
node,
][ (node.start._permute * steps | 0) % 4 ];
node.start._permute += step;
if (expr) {
if (expr === node) {
if (node.alternative) {
expr = node.clone();
expr.alternative = null;
CHANGED = true;
return expr;
}
} else if (expr) {
// replace if statement with its condition, then block or else block
CHANGED = true;
return to_statement(expr);
@@ -539,7 +552,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var before_iterations, diff_error_message, passes = 3, testcase_ast;
for (var pass = 1; pass <= passes; pass++) {
if (before_iterations !== testcase) {
testcase_ast = U.parse(testcase);
testcase_ast = U.parse(testcase, parse_options);
if (diff_error_message === testcase) {
// only difference detected is in error message, so expose that and try again
testcase_ast.transform(new U.TreeTransformer(function(node, descend) {
@@ -561,7 +574,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
testcase = code;
differs = diff;
} else {
testcase_ast = U.parse(testcase);
testcase_ast = U.parse(testcase, parse_options);
}
}
diff_error_message = null;
@@ -621,6 +634,7 @@ module.exports = function reduce_test(testcase, minify_options, reduce_options)
var beautified = U.minify(testcase, {
compress: false,
mangle: false,
module: minify_options.module,
output: function() {
var options = JSON.parse(JSON.stringify(print_options));
options.beautify = true;
@@ -773,7 +787,7 @@ function run_code(code, toplevel, result_cache, timeout) {
if (!value) {
var start = Date.now();
result_cache[key] = value = {
result: sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout),
result: sandbox.run_code(code, toplevel, timeout),
elapsed: Date.now() - start,
};
}
@@ -801,13 +815,7 @@ function compare_run_code(code, minify_options, result_cache, max_timeout) {
};
function run(code, timeout) {
if (minify_options.module) code = [
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return run_code(code, toplevel, result_cache, timeout);
return run_code(sandbox.patch_module_statements(code, minify_options.module), toplevel, result_cache, timeout);
}
}

View File

@@ -1,11 +1,8 @@
require("./run")([
"-b",
"-b braces",
"-m",
"-mc passes=3",
"-mc passes=3,toplevel",
"-mb braces",
"--toplevel -c",
"--no-module -mc",
"-mc passes=3,unsafe",
"-mc keep_fargs=false,passes=3",
"-mc keep_fargs=false,passes=3,pure_getters,unsafe,unsafe_comps,unsafe_math,unsafe_proto",
].map(function(options) {
var args = options.split(/ /);

View File

@@ -41,6 +41,11 @@ rm -rf tmp/buble \
@@ -309 +309 @@ export default class BlockStatement extends Node {
- let cont = false; // TODO implement proper continue...
+ let cont = !declarations; // TODO implement proper continue...
--- a/src/program/types/VariableDeclaration.js
+++ b/src/program/types/VariableDeclaration.js
@@ -38 +38 @@ export default class VariableDeclaration extends Node {
- code.remove(c, declarator.id.start);
+ code.remove(c, declarator.id.start, lastDeclaratorIsPattern);
EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
minify_in_situ "src" \

View File

@@ -50,7 +50,8 @@ node --version
npm config set audit false
npm config set fund false
npm config set loglevel error
npm config set optional false
npm config set omit optional || true
npm config set optional false || true
npm config set save false
npm config set strict-ssl false
npm config set update-notifier false

View File

@@ -4,6 +4,7 @@ require("./run")([
].map(function(options) {
var args = options.split(/ /);
args.unshift("test/jetstream.js");
args.push("-b", "beautify=false,webkit");
args.push("-O", "webkit");
args.push("--no-module");
return args;
}));

View File

@@ -35,18 +35,27 @@ npm_install() {
done
}
workaround() {
FILE="$1"
echo 'Monkey patching' $FILE
CODE=`cat $FILE`
sed -E 's/for ?\((var [^;{]+;)/\1for\(;/g' > $FILE <<EOF
$CODE
EOF
}
rm -rf tmp/sucrase \
&& git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \
&& cd tmp/sucrase \
&& rm -rf .git/hooks \
&& git checkout 38b66f3009feb76750a799deea211adcc83574f1 \
&& git checkout 7284b3733aa114b3f4f5371e36ff5a4704ec860e \
&& patch -l -p1 <<EOF
--- a/package.json
+++ b/package.json
@@ -25 +24,0 @@
- "prepublishOnly": "yarn clean && yarn build",
@@ -65 +63,0 @@
- "test262-harness": "^6.5.0",
@@ -69 +67,0 @@
- "test262-harness": "^10.0.0",
--- a/script/build.ts
+++ b/script/build.ts
@@ -16 +15,0 @@ async function main(): Promise<void> {
@@ -57,11 +66,11 @@ rm -rf tmp/sucrase \
- () => buildIntegration("./integrations/webpack-loader"),
- () => buildIntegration("./integrations/webpack-object-rest-spread-plugin"),
- () => buildWebsite(),
@@ -66,3 +59,0 @@ async function buildSucrase(): Promise<void> {
@@ -62,3 +55,0 @@ async function buildSucrase(): Promise<void> {
- // Also add in .d.ts files from tsc, which only need to be compiled once.
- await run(\`\${TSC} --project ./src --outDir ./dist-types\`);
- await mergeDirectoryContents("./dist-types/src", "./dist");
@@ -70 +61 @@ async function buildSucrase(): Promise<void> {
- await mergeDirectoryContents("./dist-types/src", "./dist/types");
@@ -66 +57 @@ async function buildSucrase(): Promise<void> {
- await run("yarn link");
+ await run("npm link");
--- a/src/identifyShadowedGlobals.ts
@@ -70,28 +79,38 @@ rm -rf tmp/sucrase \
+export { identifyShadowedGlobals as HACK };
--- a/src/parser/tokenizer/state.ts
+++ b/src/parser/tokenizer/state.ts
@@ -100,0 +101 @@ export default class State {
@@ -106,0 +107 @@ export default class State {
+export { State as HACK };
--- a/src/transformers/JSXTransformer.ts
+++ b/src/transformers/JSXTransformer.ts
@@ -253,0 +254 @@ export default class JSXTransformer extends Transformer {
@@ -560,0 +561 @@ export default class JSXTransformer extends Transformer {
+export { JSXTransformer as HACK };
--- a/src/util/getClassInfo.ts
+++ b/src/util/getClassInfo.ts
@@ -164,0 +165 @@ export default function getClassInfo(
@@ -195,0 +196 @@ export default function getClassInfo(
+export { getClassInfo as HACK };
--- a/src/util/getDeclarationInfo.ts
+++ b/src/util/getDeclarationInfo.ts
@@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI
+export { getDeclarationInfo as HACK };
--- a/src/util/getImportExportSpecifierInfo.ts
+++ b/src/util/getImportExportSpecifierInfo.ts
@@ -87,0 +88 @@ export default function getImportExportSpecifierInfo(
+export { getImportExportSpecifierInfo as HACK };
--- a/src/util/getJSXPragmaInfo.ts
+++ b/src/util/getJSXPragmaInfo.ts
@@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo {
+export { getJSXPragmaInfo as HACK };
--- a/test/source-maps-test.ts
+++ b/test/source-maps-test.ts
@@ -26,0 +27 @@ var _a = require('./a'); var _a2 = _interopRequireDefault(_a);
+delete result.sourceMap.ignoreList;
EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
npm_install esbuild-wasm@0.8.56 \
&& minify_in_situ "src" \
&& workaround src/parser/plugins/typescript.ts\
&& workaround src/transformers/CJSImportTransformer.ts\
&& rm -rf node_modules \
&& npm_install \
&& npm run clean \

View File

@@ -34,7 +34,8 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
].some(function(pattern) {
return pattern.test(code);
}) ? run_code_exec : run_code_vm)(code, toplevel, timeout);
return stdout.length > 1000 ? stdout.slice(0, 1000) + "…《" + stdout.length + "》" : stdout;
var len = typeof stdout == "string" && stdout.length;
return len > 1000 ? stdout.slice(0, 1000) + "…《" + len + "》" : stdout;
};
exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
if (typeof expected != typeof actual) return false;
@@ -48,7 +49,16 @@ exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expec
} : function(expected, actual) {
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(actual);
};
exports.patch_module_statements = function(code) {
exports.patch_module_statements = function(code, module) {
if (module || module === undefined && /\bawait\b/.test(code)) {
code = [
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
];
if (module) code.unshift('"use strict";');
code = code.join("\n");
}
var count = 0, has_default = "", imports = [], strict_mode = "";
code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) {
strict_mode = match;

View File

@@ -2113,13 +2113,7 @@ if (require.main !== module) {
}
function run_code(code, toplevel, timeout) {
if (async && has_await) code = [
'"use strict";',
"(async()=>{",
code,
'})().catch(e=>process.on("exit",()=>{throw e}));',
].join("\n");
return sandbox.run_code(sandbox.patch_module_statements(code), toplevel, timeout);
return sandbox.run_code(sandbox.patch_module_statements(code, async && has_await), toplevel, timeout);
}
function writeln(stream, msg) {
@@ -2139,7 +2133,7 @@ function errorln(msg) {
function try_beautify(code, toplevel, result, printfn, options) {
var o = JSON.parse(beautify_options);
if (async && has_await) o.module = true;
o.module = !!(async && has_await);
var beautified = UglifyJS.minify(code, o);
if (beautified.error) {
printfn("// !!! beautify failed !!!");
@@ -2268,6 +2262,7 @@ function log(options) {
var reduce_options = JSON.parse(options);
reduce_options.validate = true;
var reduced = reduce_test(original_code, reduce_options, {
max_timeout: max_timeout,
verbose: false,
}).code;
if (reduced) {
@@ -2529,6 +2524,7 @@ beautify_options = JSON.stringify(beautify_options);
minify_options = minify_options.map(JSON.stringify);
var original_code, original_result, original_erred;
var uglify_code, uglify_result, ok;
var max_timeout = 10000;
for (var round = 1; round <= num_iterations; round++) {
process.stdout.write(round + " of " + num_iterations + "\r");
@@ -2546,13 +2542,19 @@ for (var round = 1; round <= num_iterations; round++) {
println("original result:");
println(result);
println();
// ignore v8 parser bug
return bug_async_arrow_rest(result)
// ignore Node.js `__proto__` quirks
|| bug_proto_stream(result)
// ignore runtime platform bugs
|| result.message == "Script execution aborted.";
})) continue;
if (is_error_timeout(result)) orig_result[toplevel] = result = run_code(original_code, toplevel, max_timeout);
// skip over test cases which take too long to run
if (is_error_timeout(result)) return true;
// ignore v8 parser bug
if (bug_async_arrow_rest(result)) return true;
// ignore Node.js `__proto__` quirks
if (bug_proto_stream(result)) return true;
// ignore runtime platform bugs
if (result.message == "Script execution aborted.") return true;
})) {
num_iterations++;
continue;
}
minify_options.forEach(function(options) {
var o = JSON.parse(options);
if (async && has_await) {
@@ -2575,22 +2577,10 @@ for (var round = 1; round <= num_iterations; round++) {
if (!ok && uglify_erred && bug_proto_stream(uglify_result)) ok = true;
// ignore runtime platform bugs
if (!ok && uglify_erred && uglify_result.message == "Script execution aborted.") ok = true;
// handle difference caused by time-outs
if (!ok) {
if (original_erred && is_error_timeout(original_result)) {
if (uglify_erred && is_error_timeout(uglify_result)) {
// ignore difference in error message
ok = true;
} else {
// ignore spurious time-outs
if (!orig_result[toplevel ? 3 : 2]) orig_result[toplevel ? 3 : 2] = run_code(original_code, toplevel, 10000);
ok = sandbox.same_stdout(orig_result[toplevel ? 3 : 2], uglify_result);
}
} else if (uglify_erred && is_error_timeout(uglify_result)) {
// ignore spurious time-outs
var waited_result = run_code(uglify_code, toplevel, 10000);
ok = sandbox.same_stdout(original_result, waited_result);
}
// ignore spurious time-outs
if (!ok && uglify_erred && is_error_timeout(uglify_result)) {
var waited_result = run_code(uglify_code, toplevel, max_timeout);
ok = sandbox.same_stdout(original_result, waited_result);
}
// ignore declaration order of global variables
if (!ok && !toplevel) {

View File

@@ -2,6 +2,7 @@
{
"compress": false,
"mangle": false,
"module": false,
"output": {
"beautify": true,
"braces": true
@@ -9,14 +10,19 @@
"rename": true
},
{
"compress": false
"compress": false,
"module": false
},
{
"mangle": false
"mangle": false,
"module": false
},
{
"module": false
},
{},
{
"ie": true,
"module": false,
"toplevel": true
},
{
@@ -28,6 +34,7 @@
},
"keep_fargs": true,
"keep_fnames": true,
"module": false,
"toplevel": true
},
{
@@ -39,6 +46,7 @@
"unsafe_math": true,
"unsafe_proto": true,
"unsafe_regexp": true
}
},
"module": false
}
]

View File

@@ -4323,6 +4323,7 @@
"enable",
"enableBackground",
"enableDelegations",
"enableHighAccuracy",
"enableStyleSheetsForSet",
"enableVertexAttribArray",
"enabled",
@@ -5553,6 +5554,7 @@
"maxWidth",
"maxZoom",
"maximize",
"maximumAge",
"maximumFractionDigits",
"measure",
"measureText",

View File

@@ -100,7 +100,7 @@ function infer_options(options) {
exports.default_options = function() {
var defs = infer_options({ 0: 0 });
Object.keys(defs).forEach(function(component) {
var options = {};
var options = { module: false };
options[component] = { 0: 0 };
if (options = infer_options(options)) {
defs[component] = options;

View File

@@ -6,7 +6,7 @@ try {
} catch (e) {
// ensure output buffers are flushed before process termination
var exit = process.exit;
process.exit = function() {
if ("bufferSize" in process.stdout) process.exit = function() {
var args = [].slice.call(arguments);
process.once("uncaughtException", function() {
(function callback() {