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

View File

@@ -7,7 +7,7 @@ jobs:
test: test:
strategy: strategy:
matrix: 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 ] os: [ ubuntu-latest, windows-latest ]
script: [ compress, mocha, release/benchmark, release/jetstream ] script: [ compress, mocha, release/benchmark, release/jetstream ]
name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }} name: ${{ matrix.node }} ${{ matrix.os }} ${{ matrix.script }}
@@ -17,8 +17,8 @@ jobs:
TYPE: ${{ matrix.script }} TYPE: ${{ matrix.script }}
UGLIFY_GITHUB_LAG: 10000 UGLIFY_GITHUB_LAG: 10000
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- uses: actions/cache@v3 - uses: actions/cache@v4
with: with:
path: tmp path: tmp
key: tmp ${{ matrix.script }} 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: env:
NODE: ${{ matrix.node }} NODE: ${{ matrix.node }}
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v4
- name: Perform fuzzing - name: Perform fuzzing
shell: bash shell: bash
run: | run: |

View File

@@ -1,6 +1,6 @@
UglifyJS is released under the BSD license: 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 Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions 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 --keep-fnames Do not mangle/drop function names. Useful for
code relying on Function.prototype.name. code relying on Function.prototype.name.
--module Process input as ES module (implies --toplevel) --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. --name-cache <file> File to hold mangled name mappings.
--self Build UglifyJS as a library (implies --wrap UglifyJS) --self Build UglifyJS as a library (implies --wrap UglifyJS)
--source-map [options] Enable source map/specify source map options: --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. - `mangle.properties` (default: `false`) — a subcategory of the mangle option.
Pass an object to specify custom [mangle property options](#mangle-properties-options). 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 - `module` (default: `true`) — process input as ES module, i.e. implicit
ES module, i.e. implicit `"use strict";` and support for top-level `await`, `"use strict";` and support for top-level `await`. When explicitly specified,
alongside with `toplevel` enabled. also enables `toplevel`.
- `nameCache` (default: `null`) — pass an empty object `{}` or a previously - `nameCache` (default: `null`) — pass an empty object `{}` or a previously
used `nameCache` object if you wish to cache mangled variable and 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. - `merge_vars` (default: `true`) — combine and reuse variables.
- `module` (default: `false`) — set to `true` if you wish to process input as - `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" - `negate_iife` (default: `true`) — negate "Immediately-Called Function Expressions"
where the return value is discarded, to avoid the parentheses that the 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` overhead (compression will be slower). Make sure symbols under `pure_funcs`
are also under `mangle.reserved` to avoid mangling. are also under `mangle.reserved` to avoid mangling.
- `pure_getters` (default: `"strict"`) — If you pass `true` for - `pure_getters` (default: `"strict"`) — Pass `true` for UglifyJS to assume that
this, UglifyJS will assume that object property access object property access (e.g. `foo.bar` or `a[42]`) does not throw exception or
(e.g. `foo.bar` or `foo["bar"]`) doesn't have any side effects. alter program states via getter function. Pass `"strict"` to allow dropping or
Specify `"strict"` to treat `foo.bar` as side-effect-free only when reordering `foo.bar` only if `foo` is not `null` or `undefined` and is safe to
`foo` is certain to not throw, i.e. not `null` or `undefined`. access as a variable. Pass `false` to retain all property accesses.
- `reduce_funcs` (default: `true`) — Allows single-use functions to be - `reduce_funcs` (default: `true`) — Allows single-use functions to be
inlined as function expressions when permissible allowing further 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) regexps (affects directives with non-ascii characters becoming invalid)
- `beautify` (default: `true`) — whether to actually beautify the output. - `beautify` (default: `true`) — whether to actually beautify the output.
Passing `-b` will set this to true, but you might need to pass `-b` even Passing `-b` will set this to true. Use `-O` if you want to generate minified
when you want to generate minified code, in order to specify additional code and specify additional arguments.
arguments, so you can use `-b beautify=false` to override it.
- `braces` (default: `false`) — always insert braces in `if`, `for`, - `braces` (default: `false`) — always insert braces in `if`, `for`,
`do`, `while` or `with` statements, even if their body is a single `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.", " --ie Support non-standard Internet Explorer.",
" --keep-fargs Do not mangle/drop function arguments.", " --keep-fargs Do not mangle/drop function arguments.",
" --keep-fnames Do not mangle/drop function names. Useful for code relying on Function.prototype.name.", " --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.", " --name-cache <file> File to hold mangled name mappings.",
" --rename Force symbol expansion.", " --rename Force symbol expansion.",
" --no-rename Disable symbol expansion.", " --no-rename Disable symbol expansion.",
@@ -155,7 +156,6 @@ function process_option(name, no_value) {
case "expression": case "expression":
case "ie": case "ie":
case "ie8": case "ie8":
case "module":
case "timings": case "timings":
case "toplevel": case "toplevel":
case "v8": case "v8":
@@ -201,6 +201,12 @@ function process_option(name, no_value) {
if (typeof options.mangle != "object") options.mangle = {}; if (typeof options.mangle != "object") options.mangle = {};
options.mangle.properties = parse_js(read_value(), options.mangle.properties); options.mangle.properties = parse_js(read_value(), options.mangle.properties);
break; break;
case "module":
options.module = true;
break;
case "no-module":
options.module = false;
break;
case "name-cache": case "name-cache":
nameCache = read_value(true); nameCache = read_value(true);
options.nameCache = JSON.parse(read_file(nameCache, "{}")); options.nameCache = JSON.parse(read_file(nameCache, "{}"));
@@ -295,9 +301,19 @@ if (specified["in-situ"]) {
process.stdin.setEncoding("utf8"); process.stdin.setEncoding("utf8");
process.stdin.once("data", function() { process.stdin.once("data", function() {
clearTimeout(timerId); 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); chunks.push(chunk);
}).on("end", function() { }
} : function(chunk) {
chunks.push(chunk);
}).once("end", function() {
files = { STDIN: chunks.join("") }; files = { STDIN: chunks.join("") };
run(); run();
}); });

View File

@@ -169,8 +169,6 @@ DEF_BITPROPS(AST_Node, [
"private", "private",
// AST_Call // AST_Call
"pure", "pure",
// AST_Assign
"redundant",
// AST_Node // AST_Node
"single_use", "single_use",
// AST_ClassProperty // 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_fargs: false,
keep_fnames: false, keep_fnames: false,
mangle: {}, mangle: {},
module: false, module: undefined,
nameCache: null, nameCache: null,
output: {}, output: {},
parse: {}, parse: {},
rename: undefined, rename: undefined,
sourceMap: false, sourceMap: false,
timings: false, timings: false,
toplevel: !!(options && options["module"]), toplevel: options && !options["expression"] && options["module"] ? true : undefined,
v8: false, v8: false,
validate: false, validate: false,
warnings: false, warnings: false,
@@ -104,8 +104,9 @@ function minify(files, options) {
if (options.ie) set_shorthand("ie", options, [ "compress", "mangle", "output", "rename" ]); 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_fargs) set_shorthand("keep_fargs", options, [ "compress", "mangle", "rename" ]);
if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]); if (options.keep_fnames) set_shorthand("keep_fnames", options, [ "compress", "mangle", "rename" ]);
if (options.module === undefined && !options.ie) options.module = true;
if (options.module) set_shorthand("module", options, [ "compress", "parse" ]); if (options.module) set_shorthand("module", options, [ "compress", "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.v8) set_shorthand("v8", options, [ "mangle", "output", "rename" ]);
if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]); if (options.webkit) set_shorthand("webkit", options, [ "compress", "mangle", "output", "rename" ]);
var quoted_props; var quoted_props;

View File

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

View File

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

View File

@@ -207,11 +207,14 @@ function JS_Parse_Error(message, filename, line, col, pos) {
this.line = line; this.line = line;
this.col = col; this.col = col;
this.pos = pos; 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.constructor = JS_Parse_Error;
JS_Parse_Error.prototype.name = "SyntaxError";
configure_error_stack(JS_Parse_Error);
function js_error(message, filename, line, col, pos) { function js_error(message, filename, line, col, pos) {
throw new JS_Parse_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); var valid = parse_js_number(num);
if (isNaN(valid)) parse_error("Invalid syntax: " + num); if (isNaN(valid)) parse_error("Invalid syntax: " + num);
if (has_dot || has_e || peek() != "n") return token("num", valid); 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) { function read_escaped_char(in_string) {

View File

@@ -68,9 +68,7 @@ SymbolDef.prototype = {
var cache = this.global && options.cache && options.cache.props; var cache = this.global && options.cache && options.cache.props;
if (cache && cache.has(this.name)) { if (cache && cache.has(this.name)) {
this.mangled_name = cache.get(this.name); this.mangled_name = cache.get(this.name);
} else if (this.unmangleable(options)) { } else if (!this.unmangleable(options)) {
names_in_use(this.scope, options).set(this.name, true);
} else {
var def = this.redefined(); var def = this.redefined();
if (def) { if (def) {
this.mangled_name = def.mangled_name || def.name; this.mangled_name = def.mangled_name || def.name;
@@ -180,6 +178,13 @@ AST_Toplevel.DEFMETHOD("figure_out_scope", function(options) {
}); });
return true; 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) { if (node instanceof AST_SwitchBranch) {
node.init_vars(scope); node.init_vars(scope);
descend(); descend();
@@ -439,35 +444,43 @@ AST_Toplevel.DEFMETHOD("def_global", function(node) {
} }
}); });
function init_block_vars(scope, parent) { function init_block_vars(scope, parent, orig) {
scope.enclosed = []; // variables from this or outer scope(s) that are referenced from this or inner scopes // 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.enclosed = orig ? orig.enclosed.slice() : [];
scope.functions = new Dictionary(); // map name to AST_SymbolDefun (functions defined in this scope) // 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) scope.functions = orig ? orig.functions.clone() : new Dictionary();
if (parent) scope.make_def = parent.make_def; // top-level tracking of SymbolDef instances // 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) { function init_scope_vars(scope, parent, orig) {
init_block_vars(scope, parent); init_block_vars(scope, parent, orig);
scope.uses_eval = false; // will be set to true if this or nested scope uses the global `eval` // 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 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) { AST_BlockScope.DEFMETHOD("init_vars", function(parent, orig) {
init_block_vars(this, parent_scope); init_block_vars(this, parent, orig);
}); });
AST_Scope.DEFMETHOD("init_vars", function(parent_scope) { AST_Scope.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
}); });
AST_Arrow.DEFMETHOD("init_vars", function(parent_scope) { AST_Arrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
return this; return this;
}); });
AST_AsyncArrow.DEFMETHOD("init_vars", function(parent_scope) { AST_AsyncArrow.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
}); });
AST_Lambda.DEFMETHOD("init_vars", function(parent_scope) { AST_Lambda.DEFMETHOD("init_vars", function(parent, orig) {
init_scope_vars(this, parent_scope); init_scope_vars(this, parent, orig);
this.uses_arguments = false; this.uses_arguments = false;
this.def_variable(new AST_SymbolFunarg({ this.def_variable(new AST_SymbolFunarg({
name: "arguments", name: "arguments",
@@ -643,8 +656,12 @@ AST_Toplevel.DEFMETHOD("mangle_names", function(options) {
}, true); }, true);
} }
var to_mangle = node.to_mangle = []; var to_mangle = node.to_mangle = [];
node.variables.each(function(def) { node.variables.each(function(def, name) {
if (!defer_redef(def)) to_mangle.push(def); if (def.unmangleable(options)) {
names_in_use(node, options).set(name, true);
} else if (!defer_redef(def)) {
to_mangle.push(def);
}
}); });
descend(); descend();
if (options.cache && node instanceof AST_Toplevel) { 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]; for (var i = array.length; --i >= 0;) if (func(array[i])) return array[i];
} }
function configure_error_stack(fn) { function configure_error_stack(ex, cause) {
Object.defineProperty(fn.prototype, "stack", { var stack = ex.name + ": " + ex.message;
Object.defineProperty(ex, "stack", {
get: function() { get: function() {
var err = new Error(this.message); if (cause) {
err.name = this.name; cause.name = "" + ex.name;
try { stack = "" + cause.stack;
throw err; var msg = "" + cause.message;
} catch (e) { cause = null;
return e.stack; 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) { function DefaultsError(msg, defs) {
this.message = msg; this.message = msg;
this.defs = defs; this.defs = defs;
try {
throw new Error(msg);
} catch (cause) {
configure_error_stack(this, cause);
}
} }
DefaultsError.prototype = Object.create(Error.prototype); DefaultsError.prototype = Object.create(Error.prototype);
DefaultsError.prototype.constructor = DefaultsError; DefaultsError.prototype.constructor = DefaultsError;
DefaultsError.prototype.name = "DefaultsError"; DefaultsError.prototype.name = "DefaultsError";
configure_error_stack(DefaultsError);
function defaults(args, defs, croak) { function defaults(args, defs, croak) {
if (croak) for (var i in args) { if (croak) for (var i in args) {

View File

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

View File

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

View File

@@ -690,6 +690,65 @@ inline_iife_within_arrow: {
node_version: ">=4" 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: { issue_4388: {
options = { options = {
inline: true, inline: true,
@@ -1253,7 +1312,7 @@ issue_5653: {
} }
expect: { expect: {
console.log((a => { console.log((a => {
return console, +{}; return +{};
})()); })());
} }
expect_stdout: "NaN" expect_stdout: "NaN"

View File

@@ -1348,7 +1348,7 @@ functions_inner_var: {
node_version: ">=8" node_version: ">=8"
} }
instanceof_lambda: { instanceof_lambda_1: {
options = { options = {
evaluate: true, evaluate: true,
side_effects: true, side_effects: true,
@@ -1363,6 +1363,50 @@ instanceof_lambda: {
node_version: ">=8" 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: { issue_4335_1: {
options = { options = {
inline: true, inline: true,
@@ -3598,3 +3642,66 @@ issue_5692_2: {
] ]
node_version: ">=8" 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" expect_stdout: "PASS"
node_version: ">=10.4.0" 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(); } 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"; "use strict";
var a = "FAIL"; var a = "FAIL";
class A { class A {
static p = a = "PASS"; static p = "PASS";
} }
console.log(a); console.log(a = "PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=12" node_version: ">=12"
@@ -3901,3 +3901,132 @@ issue_5682_class_key_computed: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=4" 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 = { options = {
collapse_vars: true, collapse_vars: true,
pure_getters: "strict", pure_getters: "strict",
@@ -5020,6 +5020,46 @@ unsafe_builtin: {
expect_stdout: "1 4" 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: { return_1: {
options = { options = {
collapse_vars: true, collapse_vars: true,
@@ -7350,30 +7390,39 @@ substitution_assign: {
b = 1 + (b = a); b = 1 + (b = a);
console.log(a, b); console.log(a, b);
} }
function f4(a, b) {
b = 1 + (a = b);
console.log(a, b);
}
f1(42, "foo"); f1(42, "foo");
f2(42, "foo"); f2(42, "foo");
f3(42, "foo"); f3(42, "foo");
f4("bar", 41);
} }
expect: { expect: {
function f1(a, b) { function f1(a, b) {
console.log(f1 = a, a); console.log(f1 = a, a);
} }
function f2(a, b) { function f2(a, b) {
a = 1 + (b = a); console.log(a = 1 + (b = a), b);
console.log(a, b);
} }
function f3(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); console.log(a, b);
} }
f1(42, "foo"); f1(42, "foo");
f2(42, "foo"); f2(42, "foo");
f3(42, "foo"); f3(42, "foo");
f4("bar", 41);
} }
expect_stdout: [ expect_stdout: [
"42 42", "42 42",
"43 42", "43 42",
"42 43", "42 43",
"41 42",
] ]
} }
@@ -9864,7 +9913,8 @@ issue_5276: {
} }
expect: { expect: {
var a = A = "PASS"; var a = A = "PASS";
a.p = a.p + null - 42; a.p += null;
a.p -= 42;
console.log(a); console.log(a);
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -10121,3 +10171,189 @@ issue_5643: {
} }
expect_stdout: "42" 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" 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 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: { expect: {
var a; var a;
(function() {})(a = true["p"]); (function() {})(a = true.p);
console.log(a); console.log(a);
} }
expect_stdout: "undefined" expect_stdout: "undefined"
@@ -3069,3 +3069,69 @@ issue_5651: {
expect_stdout: true expect_stdout: true
node_version: ">=6" 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: { expect: {
A = "FAIL"; A = "FAIL";
var [ , b ] = [ A ]; var b = [ A ][1];
console.log(b || "PASS"); console.log(b || "PASS");
} }
expect_stdout: "PASS" expect_stdout: "PASS"
@@ -1382,7 +1382,7 @@ side_effects_object: {
} }
} }
expect: { expect: {
var a = null, c = (console, 42["c"]); var a = null, c = (console, 42..c);
try { try {
c[a = "PASS"]; c[a = "PASS"];
} catch (e) { } catch (e) {
@@ -1684,7 +1684,7 @@ singleton_1: {
expect: { expect: {
var b, a = "P"[0], o = {}; var b, a = "P"[0], o = {};
o.p = [ "FAIL"["1"] ][0]; o.p = [ "FAIL"["1"] ][0];
o.q = { foo: "S"[0] }["foo"]; o.q = { foo: "S"[0] }.foo;
[ b = "S" ] = []; [ b = "S" ] = [];
console.log(a + o.p + o.q + b); console.log(a + o.p + o.q + b);
} }
@@ -3886,3 +3886,358 @@ issue_5651: {
expect_stdout: true expect_stdout: true
node_version: ">=6" 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: { expect: {
let e, a = 42["foo"]; let e, a = 42..foo;
function f(t, { [e]: o }) { function f(t, { [e]: o }) {
t(o, f); t(o, f);
} }

View File

@@ -8663,6 +8663,7 @@ module_inline: {
inline: true, inline: true,
module: true, module: true,
reduce_vars: true, reduce_vars: true,
toplevel: true,
} }
input: { input: {
var a = f; var a = f;
@@ -8740,3 +8741,233 @@ issue_5692: {
} }
expect_stdout: "PASS" 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, evaluate: true,
hoist_vars: true, hoist_vars: true,
reduce_vars: true, reduce_vars: true,
sequences: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -363,6 +364,7 @@ issue_4893_1: {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
reduce_vars: true, reduce_vars: true,
side_effects: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -383,9 +385,8 @@ issue_4893_1: {
} }
expect: { expect: {
try{ try{
(function f() { (function() {
null.p += 42; null.p += 42;
f;
})(); })();
} catch (e) { } catch (e) {
console.log("PASS"); console.log("PASS");
@@ -422,9 +423,7 @@ issue_4893_2: {
expect: { expect: {
try{ try{
(function() { (function() {
var a; null.p += 42;
a = null;
a.p += 42;
})(); })();
} catch (e) { } catch (e) {
console.log("PASS"); console.log("PASS");
@@ -610,6 +609,7 @@ issue_5411_2: {
evaluate: true, evaluate: true,
hoist_vars: true, hoist_vars: true,
reduce_vars: true, reduce_vars: true,
sequences: true,
toplevel: true, toplevel: true,
unused: true, unused: true,
} }
@@ -622,9 +622,9 @@ issue_5411_2: {
} }
expect: { expect: {
var b, c; var b, c;
b++; b++,
b = "PASS", b = "PASS",
c; c,
console.log(b); console.log(b);
} }
expect_stdout: "PASS" 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: { keep_ref: {
options = { options = {
reduce_vars: true, reduce_vars: true,

View File

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

View File

@@ -16,6 +16,105 @@ join_vars_assign: {
expect_stdout: "PASS" 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: { join_object_assignments_1: {
options = { options = {
evaluate: true, evaluate: true,
@@ -1394,3 +1493,37 @@ issue_5175: {
} }
expect_stdout: "PASS PASS" 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" 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: { issue_4191: {
options = { options = {
functions: true, functions: true,
@@ -2170,3 +2294,275 @@ issue_5591: {
] ]
node_version: ">=4" 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", "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" 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" 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"; "bar" >= "bar";
} }
expect: { expect: {
0 instanceof bar(); [] instanceof bar();
bar(); bar();
bar(), bar(); bar(), bar();
bar(); bar();

View File

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

View File

@@ -724,3 +724,246 @@ retain_instanceof: {
} }
expect_stdout: "PASS" 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" 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" 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: { forin_let_1: {
options = { options = {
join_vars: true, join_vars: true,

View File

@@ -896,7 +896,7 @@ dont_inline_nested: {
node_version: ">=4" node_version: ">=4"
} }
drop_body: { drop_body_1: {
options = { options = {
side_effects: true, side_effects: true,
yields: true, yields: true,
@@ -906,6 +906,27 @@ drop_body: {
console.log("bar"); console.log("bar");
})([ console.log("baz") ]); })([ 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: { expect: {
[ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ]; [ [ , [][0] = console.log("foo") ] ] = [ [ console.log("baz") ] ];
} }
@@ -1365,7 +1386,7 @@ issue_5076_1: {
expect: { expect: {
var a; var a;
console.log("PASS"), console.log("PASS"),
a = 42["a"]; a = 42..a;
} }
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=6" node_version: ">=6"
@@ -2019,7 +2040,7 @@ issue_5684: {
node_version: ">=10" node_version: ">=10"
} }
issue_5707: { issue_5707_1: {
options = { options = {
hoist_props: true, hoist_props: true,
reduce_vars: true, reduce_vars: true,
@@ -2033,6 +2054,28 @@ issue_5707: {
function* f(c = (b = 42, console.log("PASS"))) {} function* f(c = (b = 42, console.log("PASS"))) {}
b = f(); 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: { expect: {
console.log("PASS"); console.log("PASS");
} }
@@ -2076,3 +2119,131 @@ issue_5710: {
expect_stdout: "PASS" expect_stdout: "PASS"
node_version: ">=10" 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) // (beautified)
var b = 0;
var expr2 = (0 - 1 - .1 - .1).toString(); var expr2 = (0 - 1 - .1 - .1).toString();
for (var key2 in expr2) { console.log(expr2);
--b; // output: -1.2000000000000002
}
console.log(b);
// output: -19
// //
// minify: -4 // minify: -1.2
// //
// options: { // options: {
// "compress": { // "compress": {

View File

@@ -14,7 +14,7 @@ if (typeof phantom == "undefined") {
args.splice(debug, 1); args.splice(debug, 1);
debug = true; debug = true;
} }
if (!args.length) args.push("-mcb", "beautify=false,webkit"); if (!args.length) args.push("-mcO", "webkit");
args.unshift("bin/uglifyjs"); args.unshift("bin/uglifyjs");
args.push("--validate", "--timings"); args.push("--validate", "--timings");
var child_process = require("child_process"); var child_process = require("child_process");
@@ -63,7 +63,10 @@ if (typeof phantom == "undefined") {
function npm(args, done) { function npm(args, done) {
args.push("--loglevel=error"); 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() { (function install() {

View File

@@ -206,7 +206,13 @@ describe("bin/uglifyjs", function() {
}, 1000); }, 1000);
}); });
it("Should work with --keep-fargs (mangle only)", function(done) { 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) { exec(command, function(err, stdout) {
if (err) throw err; 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"); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; 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"); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; 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"); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; 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"); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; 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"); 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) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -571,7 +605,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (function g(arguments))", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -585,7 +623,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (function eval())", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -599,7 +641,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (iife arguments())", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -613,7 +659,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (catch (eval))", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -627,7 +677,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (var eval)", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -641,7 +695,11 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should throw syntax error (var { eval })", function(done) { 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) { exec(command, function(err, stdout, stderr) {
assert.ok(err); assert.ok(err);
assert.strictEqual(stdout, ""); assert.strictEqual(stdout, "");
@@ -807,7 +865,8 @@ describe("bin/uglifyjs", function() {
var command = [ var command = [
uglifyjscmd, uglifyjscmd,
"test/input/issue-2310/input.js", "test/input/issue-2310/input.js",
"-c", "--compress",
"--no-module",
"--source-map", "url=inline", "--source-map", "url=inline",
].join(" "); ].join(" ");
exec(command, function(err, stdout, stderr) { exec(command, function(err, stdout, stderr) {
@@ -840,7 +899,12 @@ describe("bin/uglifyjs", function() {
}); });
}); });
it("Should work with --mangle reserved=[]", function(done) { 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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(callback){"aaaaaaaaaaaaaaaa";callback(err,data);callback(err,data)}\n'); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function test(a){"aaaaaaaaaaaaaaaa";a(err,data);a(err,data)}\n'); 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) { 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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function f(){"aaaaaaaaaa";var a={prop:1,t:2};return a.prop+a.t}\n'); 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) { 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) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(a){return b(a);function b(c){return c+c}}\n"); 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) { 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) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return function(n){return n+n}(n)}\n"); 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) { 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) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(n){return n+n}\n"); 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) { 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) { exec(command, function(err, stdout, stderr) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n"); assert.strictEqual(stdout, "function f(x){return function(x){return x+x}(x)}\n");
@@ -971,12 +1068,7 @@ describe("bin/uglifyjs", function() {
]).join("\n"); ]).join("\n");
exec(uglifyjscmd + " -mc", function(err, stdout) { exec(uglifyjscmd + " -mc", function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, [ assert.strictEqual(stdout, "console.log(function(){var p={p:25},n={p:121},o={p:1024};return p.p+n.p+o.p}());\n");
"console.log(function(){",
"var p={p:25},n={p:121},o={p:1024};",
"return p.p+n.p+o.p",
"}());\n",
].join(""));
assert.strictEqual(run_code(stdout), run_code(code)); assert.strictEqual(run_code(stdout), run_code(code));
done(); done();
}).stdin.end(code); }).stdin.end(code);

View File

@@ -476,7 +476,9 @@ describe("comments", function() {
for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n"; for (var i = 1; i <= 5000; ++i) js += "// " + i + "\n";
for (; i <= 10000; ++i) js += "/* " + i + " */ /**/"; for (; i <= 10000; ++i) js += "/* " + i + " */ /**/";
js += "x; }"; 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}"); assert.strictEqual(result.code, "function lots_of_comments(x){return 7-x}");
}); });
}); });

View File

@@ -373,7 +373,9 @@ describe("Directives", function() {
'function f(){}' 'function f(){}'
], ],
].forEach(function(test) { ].forEach(function(test) {
var result = UglifyJS.minify(test[0]); var result = UglifyJS.minify(test[0], {
module: false,
});
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, test[1], test[0]); 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() { describe("bin/uglifyjs with input file globs", function() {
var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs'; var uglifyjscmd = '"' + process.argv[0] + '" bin/uglifyjs';
it("bin/uglifyjs with one input file extension glob.", function(done) { 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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n'); assert.strictEqual(stdout, 'var print=console.log.bind(console);function foo(o){print("Foo:",2*o)}\n');
done(); done();
}); });
}); });
it("bin/uglifyjs with one input file name glob.", function(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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n'); assert.strictEqual(stdout, 'function bar(n){return 3*n}function baz(n){return n/2}\n');
done(); done();
}); });
}); });
it("bin/uglifyjs with multiple input file globs.", function(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) { exec(command, function(err, stdout) {
if (err) throw err; if (err) throw err;
assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n'); assert.strictEqual(stdout, 'var print=console.log.bind(console);print("qux",9,6),print("Foo:",22);\n');
done(); done();
}); });

View File

@@ -6,8 +6,10 @@ describe("Input file as map", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/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); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sources, ['/scripts/foo.js']); 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 foo = {"x": 1, y: 2, \'z\': 3};',
'var bar = 15;' '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); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3},bar=15;');
assert.deepEqual(map.sources, ['0', '1']); assert.deepEqual(map.sources, ['0', '1']);
@@ -37,8 +41,12 @@ describe("Input file as map", function() {
var jsMap = { var jsMap = {
'/scripts/foo.js': 'var foo = {"x": 1, y: 2, \'z\': 3};' '/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); var map = JSON.parse(result.map);
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
assert.deepEqual(map.sourcesContent, ['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, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
cache: cache, cache: cache,
toplevel: true toplevel: true,
} },
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
original += code; original += code;
@@ -79,9 +79,9 @@ describe("minify", function() {
var code = read("test/input/issue-1242/" + file); var code = read("test/input/issue-1242/" + file);
var result = UglifyJS.minify(code, { var result = UglifyJS.minify(code, {
mangle: { mangle: {
toplevel: true toplevel: true,
}, },
nameCache: cache nameCache: cache,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
original += code; original += code;
@@ -162,8 +162,9 @@ describe("minify", function() {
var js = 'var foo = {"x": 1, y: 2, \'z\': 3};'; var js = 'var foo = {"x": 1, y: 2, \'z\': 3};';
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true keep_quoted_props: true,
}}); },
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,"z":3};');
}); });
it("Should preserve quote styles when quote_style is 3", function() { it("Should preserve quote styles when quote_style is 3", function() {
@@ -171,8 +172,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: true, keep_quoted_props: true,
quote_style: 3 quote_style: 3,
}}); },
});
assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};'); assert.strictEqual(result.code, 'var foo={"x":1,y:2,\'z\':3};');
}); });
it("Should not preserve quotes in object literals when disabled", function() { it("Should not preserve quotes in object literals when disabled", function() {
@@ -180,8 +182,9 @@ describe("minify", function() {
var result = UglifyJS.minify(js, { var result = UglifyJS.minify(js, {
output: { output: {
keep_quoted_props: false, keep_quoted_props: false,
quote_style: 3 quote_style: 3,
}}); },
});
assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};'); assert.strictEqual(result.code, 'var foo={x:1,y:2,z:3};');
}); });
}); });
@@ -223,7 +226,7 @@ describe("minify", function() {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
} },
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "// comment1 comment2\nbar();"); assert.strictEqual(code, "// comment1 comment2\nbar();");
@@ -233,7 +236,7 @@ describe("minify", function() {
output: { output: {
comments: "all", comments: "all",
beautify: false, beautify: false,
} },
}); });
var code = result.code; var code = result.code;
assert.strictEqual(code, "var a=function(){foo()}();"); assert.strictEqual(code, "var a=function(){foo()}();");
@@ -301,7 +304,7 @@ describe("minify", function() {
compress: false, compress: false,
mangle: false, mangle: false,
output: { output: {
ast: true ast: true,
}, },
}).ast; }).ast;
assert.strictEqual(ast.TYPE, "Toplevel"); assert.strictEqual(ast.TYPE, "Toplevel");
@@ -312,9 +315,9 @@ describe("minify", function() {
var stat = ast.body[0].body[0]; var stat = ast.body[0].body[0];
UglifyJS.minify(ast, { UglifyJS.minify(ast, {
compress: { compress: {
sequences: false sequences: false,
}, },
mangle: false mangle: false,
}); });
assert.ok(stat.body); assert.ok(stat.body);
assert.strictEqual(stat.print_to_string(), "a=x()"); 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() { it("Should report trailing whitespace difference in stringified format", function() {
var code = [ var code = [
"for (var a in (1 - .8).toString()) {", "[].forEach.call((1 - .8).toString(), function() {",
" console.log();", " console.log();",
"}", "});",
].join("\n"); ].join("\n");
var result = reduce_test(code, { var result = reduce_test(code, {
compress: { compress: {
@@ -333,6 +333,7 @@ describe("test/reduce.js", function() {
unsafe_math: true, unsafe_math: true,
}, },
mangle: false, mangle: false,
module: false,
}); });
if (result.error) throw result.error; if (result.error) throw result.error;
assert.strictEqual(result.code, [ assert.strictEqual(result.code, [
@@ -346,7 +347,8 @@ describe("test/reduce.js", function() {
'// "compress": {', '// "compress": {',
'// "unsafe_math": true', '// "unsafe_math": true',
'// },', '// },',
'// "mangle": false', '// "mangle": false,',
'// "module": false',
"// }", "// }",
].join("\n")); ].join("\n"));
}); });

View File

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

View File

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

View File

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

View File

@@ -41,6 +41,11 @@ rm -rf tmp/buble \
@@ -309 +309 @@ export default class BlockStatement extends Node { @@ -309 +309 @@ export default class BlockStatement extends Node {
- let cont = false; // TODO implement proper continue... - let cont = false; // TODO implement proper continue...
+ let cont = !declarations; // 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 EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
minify_in_situ "src" \ minify_in_situ "src" \

View File

@@ -50,7 +50,8 @@ node --version
npm config set audit false npm config set audit false
npm config set fund false npm config set fund false
npm config set loglevel error 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 save false
npm config set strict-ssl false npm config set strict-ssl false
npm config set update-notifier false npm config set update-notifier false

View File

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

View File

@@ -35,18 +35,27 @@ npm_install() {
done 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 \ rm -rf tmp/sucrase \
&& git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \ && git clone https://github.com/alangpierce/sucrase.git tmp/sucrase \
&& cd tmp/sucrase \ && cd tmp/sucrase \
&& rm -rf .git/hooks \ && rm -rf .git/hooks \
&& git checkout 38b66f3009feb76750a799deea211adcc83574f1 \ && git checkout 7284b3733aa114b3f4f5371e36ff5a4704ec860e \
&& patch -l -p1 <<EOF && patch -l -p1 <<EOF
--- a/package.json --- a/package.json
+++ b/package.json +++ b/package.json
@@ -25 +24,0 @@ @@ -25 +24,0 @@
- "prepublishOnly": "yarn clean && yarn build", - "prepublishOnly": "yarn clean && yarn build",
@@ -65 +63,0 @@ @@ -69 +67,0 @@
- "test262-harness": "^6.5.0", - "test262-harness": "^10.0.0",
--- a/script/build.ts --- a/script/build.ts
+++ b/script/build.ts +++ b/script/build.ts
@@ -16 +15,0 @@ async function main(): Promise<void> { @@ -16 +15,0 @@ async function main(): Promise<void> {
@@ -57,11 +66,11 @@ rm -rf tmp/sucrase \
- () => buildIntegration("./integrations/webpack-loader"), - () => buildIntegration("./integrations/webpack-loader"),
- () => buildIntegration("./integrations/webpack-object-rest-spread-plugin"), - () => buildIntegration("./integrations/webpack-object-rest-spread-plugin"),
- () => buildWebsite(), - () => 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. - // Also add in .d.ts files from tsc, which only need to be compiled once.
- await run(\`\${TSC} --project ./src --outDir ./dist-types\`); - await run(\`\${TSC} --project ./src --outDir ./dist-types\`);
- await mergeDirectoryContents("./dist-types/src", "./dist"); - await mergeDirectoryContents("./dist-types/src", "./dist/types");
@@ -70 +61 @@ async function buildSucrase(): Promise<void> { @@ -66 +57 @@ async function buildSucrase(): Promise<void> {
- await run("yarn link"); - await run("yarn link");
+ await run("npm link"); + await run("npm link");
--- a/src/identifyShadowedGlobals.ts --- a/src/identifyShadowedGlobals.ts
@@ -70,28 +79,38 @@ rm -rf tmp/sucrase \
+export { identifyShadowedGlobals as HACK }; +export { identifyShadowedGlobals as HACK };
--- a/src/parser/tokenizer/state.ts --- a/src/parser/tokenizer/state.ts
+++ b/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 }; +export { State as HACK };
--- a/src/transformers/JSXTransformer.ts --- a/src/transformers/JSXTransformer.ts
+++ b/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 }; +export { JSXTransformer as HACK };
--- a/src/util/getClassInfo.ts --- a/src/util/getClassInfo.ts
+++ b/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 }; +export { getClassInfo as HACK };
--- a/src/util/getDeclarationInfo.ts --- a/src/util/getDeclarationInfo.ts
+++ b/src/util/getDeclarationInfo.ts +++ b/src/util/getDeclarationInfo.ts
@@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI @@ -40,0 +41 @@ export default function getDeclarationInfo(tokens: TokenProcessor): DeclarationI
+export { getDeclarationInfo as HACK }; +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 --- a/src/util/getJSXPragmaInfo.ts
+++ b/src/util/getJSXPragmaInfo.ts +++ b/src/util/getJSXPragmaInfo.ts
@@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo { @@ -14,0 +15 @@ export default function getJSXPragmaInfo(options: Options): JSXPragmaInfo {
+export { getJSXPragmaInfo as HACK }; +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 EOF
ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi ERR=$?; if [ "$ERR" != "0" ]; then echo "Error: $ERR"; exit $ERR; fi
npm_install esbuild-wasm@0.8.56 \ npm_install esbuild-wasm@0.8.56 \
&& minify_in_situ "src" \ && minify_in_situ "src" \
&& workaround src/parser/plugins/typescript.ts\
&& workaround src/transformers/CJSImportTransformer.ts\
&& rm -rf node_modules \ && rm -rf node_modules \
&& npm_install \ && npm_install \
&& npm run clean \ && npm run clean \

View File

@@ -34,7 +34,8 @@ exports.run_code = semver.satisfies(process.version, "0.8") ? function(code, top
].some(function(pattern) { ].some(function(pattern) {
return pattern.test(code); return pattern.test(code);
}) ? run_code_exec : run_code_vm)(code, toplevel, timeout); }) ? 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) { exports.same_stdout = semver.satisfies(process.version, "0.12") ? function(expected, actual) {
if (typeof expected != typeof actual) return false; 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) { } : function(expected, actual) {
return typeof expected == typeof actual && strip_func_ids(expected) == strip_func_ids(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 = ""; var count = 0, has_default = "", imports = [], strict_mode = "";
code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) { code = code.replace(/^\s*("|')use strict\1\s*;?/, function(match) {
strict_mode = match; strict_mode = match;

View File

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

View File

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

View File

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

View File

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

View File

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