swc/crates/swc_ecma_minifier/tests/exec.rs

9956 lines
195 KiB
Rust

#![deny(warnings)]
extern crate swc_node_base;
use ansi_term::Color;
use anyhow::Error;
use serde::Deserialize;
use swc_common::{
comments::SingleThreadedComments, errors::Handler, sync::Lrc, FileName, Mark, SourceMap,
};
use swc_ecma_ast::Module;
use swc_ecma_codegen::{
text_writer::{omit_trailing_semi, JsWriter, WriteJs},
Emitter,
};
use swc_ecma_minifier::{
optimize,
option::{
terser::TerserCompressorOptions, CompressOptions, ExtraOptions, MangleOptions,
MinifyOptions,
},
};
use swc_ecma_parser::{parse_file_as_module, EsConfig, Syntax};
use swc_ecma_testing::{exec_node_js, JsExecOptions};
use swc_ecma_transforms_base::{fixer::fixer, hygiene::hygiene, resolver};
use swc_ecma_visit::{FoldWith, VisitMutWith};
use testing::DebugUsingDisplay;
use tracing::{info, span, Level};
#[derive(Debug, Clone, Deserialize)]
struct TestOptions {
#[serde(default)]
defaults: bool,
}
fn parse_compressor_config(cm: Lrc<SourceMap>, s: &str) -> (bool, CompressOptions) {
let opts: TestOptions =
serde_json::from_str(s).expect("failed to deserialize value into a compressor config");
let mut c: TerserCompressorOptions =
serde_json::from_str(s).expect("failed to deserialize value into a compressor config");
c.defaults = opts.defaults;
(c.module, c.into_config(cm))
}
fn stdout_of(code: &str) -> Result<String, Error> {
let stdout = exec_node_js(
code,
JsExecOptions {
cache: true,
module: false,
},
)?;
info!("Stdout: {}", stdout);
Ok(stdout)
}
fn print<N: swc_ecma_codegen::Node>(
cm: Lrc<SourceMap>,
nodes: &[N],
minify: bool,
skip_semi: bool,
) -> String {
let mut buf = vec![];
{
let mut wr: Box<dyn WriteJs> = Box::new(JsWriter::new(cm.clone(), "\n", &mut buf, None));
if minify || skip_semi {
wr = Box::new(omit_trailing_semi(wr));
}
let mut emitter = Emitter {
cfg: swc_ecma_codegen::Config {
minify,
..Default::default()
},
cm,
comments: None,
wr,
};
for n in nodes {
n.emit_with(&mut emitter).unwrap();
}
}
String::from_utf8(buf).unwrap()
}
fn run(
cm: Lrc<SourceMap>,
handler: &Handler,
input: &str,
config: Option<&str>,
mangle: Option<MangleOptions>,
) -> Option<Module> {
let _ = rayon::ThreadPoolBuilder::new()
.thread_name(|i| format!("rayon-{}", i + 1))
.build_global();
let compress_config = config.map(|config| parse_compressor_config(cm.clone(), config).1);
let fm = cm.new_source_file(FileName::Anon, input.into());
let comments = SingleThreadedComments::default();
eprintln!("---- {} -----\n{}", Color::Green.paint("Input"), fm.src);
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
let program = parse_file_as_module(
&fm,
Syntax::Es(EsConfig {
jsx: true,
..Default::default()
}),
Default::default(),
Some(&comments),
&mut vec![],
)
.map_err(|err| {
err.into_diagnostic(handler).emit();
})
.map(|module| module.fold_with(&mut resolver(unresolved_mark, top_level_mark, false)));
// Ignore parser errors.
//
// This is typically related to strict mode caused by module context.
let program = match program {
Ok(v) => v,
_ => return None,
};
let run_hygiene = mangle.is_none();
let mut output = optimize(
program,
cm,
Some(&comments),
None,
&MinifyOptions {
compress: compress_config,
mangle,
..Default::default()
},
&ExtraOptions {
unresolved_mark,
top_level_mark,
},
);
if run_hygiene {
output.visit_mut_with(&mut hygiene());
}
let output = output.fold_with(&mut fixer(None));
Some(output)
}
fn run_exec_test(input_src: &str, config: &str, skip_mangle: bool) {
eprintln!("---- {} -----\n{}", Color::Green.paint("Config"), config);
let expected_output = stdout_of(input_src).unwrap();
eprintln!(
"---- {} -----\n{}",
Color::Green.paint("Expected"),
expected_output
);
testing::run_test2(false, |cm, handler| {
let _tracing = span!(Level::ERROR, "compress-only").entered();
let output = run(cm.clone(), &handler, input_src, Some(config), None);
let output = output.expect("Parsing in base test should not fail");
let output = print(cm, &[output], false, false);
eprintln!(
"---- {} -----\n{}",
Color::Green.paint("Optimized code"),
output
);
let actual_output = stdout_of(&output).expect("failed to execute the optimized code");
assert_ne!(actual_output, "");
assert_eq!(
DebugUsingDisplay(&actual_output),
DebugUsingDisplay(&*expected_output)
);
Ok(())
})
.unwrap();
if !skip_mangle {
testing::run_test2(false, |cm, handler| {
let _tracing = span!(Level::ERROR, "with-mangle").entered();
let output = run(
cm.clone(),
&handler,
input_src,
None,
Some(MangleOptions {
keep_fn_names: true,
top_level: true,
..Default::default()
}),
);
let output = output.expect("Parsing in base test should not fail");
let output = print(cm, &[&output], true, false);
eprintln!(
"---- {} -----\n{}",
Color::Green.paint("Optimized code"),
output
);
let actual_output = stdout_of(&output).expect("failed to execute the optimized code");
assert_ne!(actual_output, "");
assert_eq!(
DebugUsingDisplay(&actual_output),
DebugUsingDisplay(&*expected_output)
);
Ok(())
})
.unwrap();
}
}
fn run_default_exec_test(input_src: &str) {
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(input_src, config, false);
}
#[test]
fn next_feedback_1_capture_1() {
let src = r###"
const arr = [];
const fns = [];
var _loop = function (i) {
fns.push(() => {
arr.push(i);
})
}
for (var i = 0; i < 10; i++) _loop(i);
fns.forEach(fn => fn());
console.log(arr);"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_6() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log((y() || false) && x());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_1() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log(x() && true && y());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_4() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log(y() || false || x());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_3() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log(x() || false || y());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_2() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log(y() && true && x());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn conditionals_reduce_5() {
let src = r###"function x() {
}
function y() {
return "foo";
}
console.log((x() || false) && y());"###;
let config = r###"{
"booleans": true,
"conditionals": true,
"evaluate": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn vercel_001() {
let src = r###"function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
function ItemsList() {
var _ref;
var _temp, _this, _ret;
_classCallCheck(this, ItemsList);
for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ItemsList.__proto__ || Object.getPrototypeOf(ItemsList)).call.apply(_ref, [this].concat(args))), _this), _this.storeHighlightedItemReference = function (highlightedItem) {
_this.props.onHighlightedItemChange(highlightedItem === null ? null : highlightedItem.item);
}, _temp), _possibleConstructorReturn(_this, _ret);
}
new ItemsList();
console.log('PASS')"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn vercel_002() {
let src = r###"function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _possibleConstructorReturn(self, call) {
if (!self) {
throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
}
return call && ("object" == typeof call || "function" == typeof call) ? call : self;
}
function _inherits(subClass, superClass) {
if ("function" != typeof superClass && null !== superClass) {
throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
}
subClass.prototype = Object.create(superClass && superClass.prototype, {
constructor: {
value: subClass,
enumerable: false,
writable: true,
configurable: true
}
});
if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
}
function ItemsList() {
_classCallCheck(this, ItemsList);
for (var _ref, _temp, _this, _ret, _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
args[_key] = arguments[_key];
}
return _ret = (_temp = (_this = _possibleConstructorReturn(this, (_ref = ItemsList.__proto__ || Object.getPrototypeOf(ItemsList)).call.apply(_ref, [
this
].concat(args))), _this), _this.storeHighlightedItemReference = function (highlightedItem) {
_this.props.onHighlightedItemChange(null === highlightedItem ? null : highlightedItem.item);
}, _temp), _possibleConstructorReturn(_this, _ret);
}
new ItemsList();
console.log("PASS");"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn regexp_1() {
let src = r###"
function compile(attributePattern, flags) {
return new RegExp(`(?:^|;)\\s*${attributePattern}\\s*=\\s*` + `(` + `[^";\\s][^;\\s]*` + `|` + `"(?:[^"\\\\]|\\\\"?)+"?` + `)`, flags);
}
console.log(compile("foo", "g"));
console.log(compile("bar", "g"));
console.log(compile("baz", "g"));"###;
let config = r###"{
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn update_object_1() {
let src = r###"console.log(function () {
console.log({
q: {
p: 8
}
}.q.p++);
return 8;
}());"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn update_object_3() {
let src = r###"console.log(function () {
var o = {
p: 7
};
console.log([
o
][0].p++);
return o.p;
}());"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn update_object_2() {
let src = r###"function inc() {
this.p++;
}
console.log(function () {
inc.call({
p: 6
});
console.log(6);
return 6;
}());"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn iife_reassign_1() {
let src = r###"console.log(function c() {
c = 6;
return c;
}())"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn emotion_react_1() {
let src = r###"
/* harmony default export */
var emotion_memoize_browser_esm = (memoize);
var hyphenateRegex = /[A-Z]|^ms/g;
var animationRegex = /_EMO_([^_]+?)_([^]*?)_EMO_/g;
var unitlessKeys = {
animationIterationCount: 1,
borderImageOutset: 1,
borderImageSlice: 1,
borderImageWidth: 1,
boxFlex: 1,
boxFlexGroup: 1,
boxOrdinalGroup: 1,
columnCount: 1,
columns: 1,
flex: 1,
flexGrow: 1,
flexPositive: 1,
flexShrink: 1,
flexNegative: 1,
flexOrder: 1,
gridRow: 1,
gridRowEnd: 1,
gridRowSpan: 1,
gridRowStart: 1,
gridColumn: 1,
gridColumnEnd: 1,
gridColumnSpan: 1,
gridColumnStart: 1,
msGridRow: 1,
msGridRowSpan: 1,
msGridColumn: 1,
msGridColumnSpan: 1,
fontWeight: 1,
lineHeight: 1,
opacity: 1,
order: 1,
orphans: 1,
tabSize: 1,
widows: 1,
zIndex: 1,
zoom: 1,
WebkitLineClamp: 1,
// SVG-related properties
fillOpacity: 1,
floodOpacity: 1,
stopOpacity: 1,
strokeDasharray: 1,
strokeDashoffset: 1,
strokeMiterlimit: 1,
strokeOpacity: 1,
strokeWidth: 1
};
var unitless_browser_esm = (unitlessKeys);
var isCustomProperty = function isCustomProperty(property) {
return property.charCodeAt(1) === 45;
};
var labelPattern = /label:\s*([^\s;\n{]+)\s*(;|$)/g;
var cursor;
var hash_browser_esm = (murmur2);
function handleInterpolation(mergedProps, registered, interpolation) {
if (interpolation == null) {
return '';
}
if (interpolation.__emotion_styles !== undefined) {
if (false) { }
return interpolation;
}
switch (typeof interpolation) {
case 'boolean': {
return '';
}
case 'object': {
if (interpolation.anim === 1) {
cursor = {
name: interpolation.name,
styles: interpolation.styles,
next: cursor
};
return interpolation.name;
}
if (interpolation.styles !== undefined) {
var next = interpolation.next;
if (next !== undefined) {
// not the most efficient thing ever but this is a pretty rare case
// and there will be very few iterations of this generally
while (next !== undefined) {
cursor = {
name: next.name,
styles: next.styles,
next: cursor
};
next = next.next;
}
}
var styles = interpolation.styles + ";";
if (false) { }
return styles;
}
return createStringFromObject(mergedProps, registered, interpolation);
}
case 'function': {
if (mergedProps !== undefined) {
var previousCursor = cursor;
var result = interpolation(mergedProps);
cursor = previousCursor;
return handleInterpolation(mergedProps, registered, result);
} else if (false) { }
break;
}
case 'string':
if (false) {
var replaced, matched;
}
break;
} // finalize string values (regular strings and functions interpolated into css calls)
if (registered == null) {
return interpolation;
}
var cached = registered[interpolation];
return cached !== undefined ? cached : interpolation;
}
function serializeStyles(args, registered, mergedProps) {
if (args.length === 1 && typeof args[0] === 'object' && args[0] !== null && args[0].styles !== undefined) {
return args[0];
}
var stringMode = true;
var styles = '';
cursor = undefined;
var strings = args[0];
if (strings == null || strings.raw === undefined) {
stringMode = false;
console.log('stringMode = false')
styles += handleInterpolation(mergedProps, registered, strings);
} else {
if (false) { }
styles += strings[0];
} // we start at 1 since we've already handled the first arg
console.log(`Styles: ${styles}`)
for (var i = 1; i < args.length; i++) {
styles += handleInterpolation(mergedProps, registered, args[i]);
if (stringMode) {
if (false) { }
styles += strings[i];
}
}
console.log(`Styles: ${styles}`)
var sourceMap;
if (false) { } // using a global regex with .exec is stateful so lastIndex has to be reset each time
labelPattern.lastIndex = 0;
var identifierName = '';
var match; // https://esbench.com/bench/5b809c2cf2949800a0f61fb5
while ((match = labelPattern.exec(styles)) !== null) {
identifierName += '-' + // $FlowFixMe we know it's not null
match[1];
}
console.log(`styles = ${styles}`)
console.log(`identifierName = ${identifierName}`)
var name = hash_browser_esm(styles) + identifierName;
if (false) { }
return {
name: name,
styles: styles,
next: cursor
};
}
function createStringFromObject(mergedProps, registered, obj) {
var string = '';
if (Array.isArray(obj)) {
for (var i = 0; i < obj.length; i++) {
string += handleInterpolation(mergedProps, registered, obj[i]) + ";";
}
} else {
for (var _key in obj) {
var value = obj[_key];
if (typeof value !== 'object') {
if (registered != null && registered[value] !== undefined) {
string += _key + "{" + registered[value] + "}";
} else if (isProcessableValue(value)) {
string += processStyleName(_key) + ":" + processStyleValue(_key, value) + ";";
}
} else {
if (_key === 'NO_COMPONENT_SELECTOR' && "production" !== 'production') { }
if (Array.isArray(value) && typeof value[0] === 'string' && (registered == null || registered[value[0]] === undefined)) {
for (var _i = 0; _i < value.length; _i++) {
if (isProcessableValue(value[_i])) {
string += processStyleName(_key) + ":" + processStyleValue(_key, value[_i]) + ";";
}
}
} else {
var interpolated = handleInterpolation(mergedProps, registered, value);
switch (_key) {
case 'animation':
case 'animationName': {
string += processStyleName(_key) + ":" + interpolated + ";";
break;
}
default: {
if (false) { }
string += _key + "{" + interpolated + "}";
}
}
}
}
}
}
return string;
}
function murmur2(str) {
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
// const m = 0x5bd1e995;
// const r = 24;
// Initialize the hash
var h = 0; // Mix 4 bytes at a time into the hash
var k,
i = 0,
len = str.length;
for (; len >= 4; ++i, len -= 4) {
k = str.charCodeAt(i) & 0xff | (str.charCodeAt(++i) & 0xff) << 8 | (str.charCodeAt(++i) & 0xff) << 16 | (str.charCodeAt(++i) & 0xff) << 24;
console.log(`K1: ${k}`);
k =
/* Math.imul(k, m): */
(k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16);
console.log(`K2: ${k}`);
k ^=
/* k >>> r: */
k >>> 24;
console.log(`K3: ${k}`);
h =
/* Math.imul(k, m): */
(k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16) ^
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
console.log(`H: ${h}`);
} // Handle the last few bytes of the input array
switch (len) {
case 3:
h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
case 2:
h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
case 1:
h ^= str.charCodeAt(i) & 0xff;
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
} // Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >>> 13;
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
return ((h ^ h >>> 15) >>> 0).toString(36);
}
function isProcessableValue(value) {
return value != null && typeof value !== 'boolean';
}
var processStyleName = /* #__PURE__ */ emotion_memoize_browser_esm(function (styleName) {
return isCustomProperty(styleName) ? styleName : styleName.replace(hyphenateRegex, '-$&').toLowerCase();
});
var processStyleValue = function processStyleValue(key, value) {
switch (key) {
case 'animation':
case 'animationName': {
if (typeof value === 'string') {
return value.replace(animationRegex, function (match, p1, p2) {
cursor = {
name: p1,
styles: p2,
next: cursor
};
return p1;
});
}
}
}
if (unitless_browser_esm[key] !== 1 && !isCustomProperty(key) && typeof value === 'number' && value !== 0) {
return value + 'px';
}
return value;
};
function memoize(fn) {
var cache = Object.create(null);
return function (arg) {
if (cache[arg] === undefined) cache[arg] = fn(arg);
return cache[arg];
};
}
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));
console.log(serializeStyles(`:root {
--background-color: rebeccapurple;
}`));"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn simple_1() {
let src = r###"console.log('PASS')"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1588_unsafe_undefined() {
let src = r###"var a, c;
console.log(
(function (undefined) {
return function () {
if (a) return b;
if (c) return d;
};
})()()
);"###;
let config = r###"{
"conditionals": true,
"if_return": true,
"unsafe_undefined": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1588_safe_undefined() {
let src = r###"var a, c;
console.log(
(function (undefined) {
return function () {
if (a) return b;
if (c) return d;
};
})(1)()
);"###;
let config = r###"{
"conditionals": true,
"if_return": true,
"unsafe": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_retain() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"top_retain": "f,a,o",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_t161_top_retain_15() {
let src = r###"class Alpha {
num() {
return x;
}
}
class Beta {
num() {
return y;
}
}
class Carrot {
num() {
return z;
}
}
function f() {
return x;
}
const g = () => y;
const h = () => z;
let x = 2,
y = 3,
z = 4;
console.log(
x,
y,
z,
x * y,
x * z,
y * z,
f(),
g(),
h(),
new Alpha().num(),
new Beta().num(),
new Carrot().num()
);"###;
let config = r###"{
"defaults": true,
"inline": 3,
"passes": 2,
"top_retain": "Alpha,z"
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_t161_top_retain_4() {
let src = r###"function f() {
return 2;
}
function g() {
return 3;
}
console.log(f(), f(), g(), g());"###;
let config = r###"{
"defaults": true,
"inline": 3,
"passes": 3,
"top_retain": "f"
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_t161_top_retain_3() {
let src = r###"function f() {
return 2;
}
function g() {
return 3;
}
console.log(f(), g());"###;
let config = r###"{
"defaults": true,
"inline": 3,
"passes": 3,
"top_retain": "f"
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_double_assign_1() {
let src = r###"function f1() {
var a = {};
var a = [];
return a;
}
function f2() {
var a = {};
a = [];
return a;
}
function f3() {
a = {};
var a = [];
return a;
}
function f4(a) {
a = {};
a = [];
return a;
}
function f5(a) {
var a = {};
a = [];
return a;
}
function f6(a) {
a = {};
var a = [];
return a;
}
console.log(f1(), f2(), f3(), f4(), f5(), f6());"###;
let config = r###"{
"passes": 2,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2846() {
let src = r###"function f(a, b) {
var a = 0;
b && b(a);
return a++;
}
var c = f();
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2660_2() {
let src = r###"var a = 1;
function f(b) {
b && f();
--a, a.toString();
}
f();
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_retain_array() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"top_retain": ["f", "a", "o"],
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_chained_3() {
let src = r###"console.log(
(function (a, b) {
var c = a,
c = b;
b++;
return c;
})(1, 2)
);"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2665() {
let src = r###"var a = 1;
function g() {
a-- && g();
}
typeof h == "function" && h();
function h() {
typeof g == "function" && g();
}
console.log(a);"###;
let config = r###"{
"evaluate": true,
"inline": true,
"keep_fargs": false,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"typeofs": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2516_2() {
let src = r###"function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);"###;
let config = r###"{
"collapse_vars": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_funcs_retain() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"top_retain": "f,a,o",
"toplevel": "funcs",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_1709() {
let src = r###"console.log(
(function x() {
var x = 1;
return x;
})(),
(function y() {
const y = 2;
return y;
})(),
(function z() {
function z() {}
return z;
})()
);"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_var() {
let src = r###"var a;
console.log(a, b);
var a = 1,
b = 2;
console.log(a, b);
var a = 3;
console.log(a, b);"###;
let config = r###"{
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_funcs() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"toplevel": "funcs",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_delete_assign_1() {
let src = r###"var a;
console.log(delete (a = undefined));
console.log(delete (a = void 0));
console.log(delete (a = Infinity));
console.log(delete (a = 1 / 0));
console.log(delete (a = NaN));
console.log(delete (a = 0 / 0));"###;
let config = r###"{
"booleans": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2226_3() {
let src = r###"console.log(
(function (a, b) {
a += b;
return a;
})(1, 2)
);"###;
let config = r###"{
"collapse_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_drop_unused_issue_3146_3() {
let src = r###"var g = "PASS";
(function (f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function (a) {
eval(a);
});"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_drop_unused_issue_3146_4() {
let src = r###"var g = "PASS";
(function (f) {
var g = "FAIL";
f("console.log(g)", g[g]);
})(function (a) {
eval(a);
});"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_vars_retain() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"top_retain": "f,a,o",
"toplevel": "vars",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2226_2() {
let src = r###"console.log(
(function (a, b) {
a += b;
return a;
})(1, 2)
);"###;
let config = r###"{
"collapse_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_fargs() {
let src = r###"function f(a) {
var b = a;
}
console.log(f())"###;
let config = r###"{
"keep_fargs": false,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2136_3() {
let src = r###"function f(x) {
console.log(x);
}
!(function (a, ...b) {
f(b[0]);
})(1, 2, 3);"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2660_1() {
let src = r###"var a = 2;
function f(b) {
return (b && f()) || a--;
}
f(1);
console.log(a);"###;
let config = r###"{
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_double_assign_2() {
let src = r###"for (var i = 0; i < 2; i++) (a = void 0), (a = {}), console.log(a);
var a;"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2136_2() {
let src = r###"function f(x) {
console.log(x);
}
!(function (a, ...b) {
f(b[0]);
})(1, 2, 3);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_t183() {
let src = r###"function foo(val) {
function bar(x) {
if (x) return x;
bar(x - 1);
}
return bar(val);
}
console.log(foo("PASS"));"###;
let config = r###"{
"defaults": true,
"top_retain": []
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_vars() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"toplevel": "vars",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_2516_1() {
let src = r###"function foo() {
function qux(x) {
bar.call(null, x);
}
function bar(x) {
var FOUR = 4;
var trouble = x || never_called();
var value = (FOUR - 1) * trouble;
console.log(value == 6 ? "PASS" : value);
}
Baz = qux;
}
var Baz;
foo();
Baz(2);"###;
let config = r###"{
"collapse_vars": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_defun_lambda_same_name() {
let src = r###"function f(n) {
return n ? n * f(n - 1) : 1;
}
console.log(
(function f(n) {
return n ? n * f(n - 1) : 1;
})(5)
);"###;
let config = r###"{
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_vars_fargs() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"keep_fargs": false,
"toplevel": "vars",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_1968() {
let src = r###"function f(c) {
var a;
if (c) {
let b;
return (a = 2) + (b = 3);
}
}
console.log(f(1));"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_1715_4() {
let src = r###"var a = 1;
!(function a() {
a++;
try {
x();
} catch (a) {
var a;
}
})();
console.log(a);"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_assign() {
let src = r###"function f1() {
var a;
a = 1;
}
function f2() {
var a = 1;
a = 2;
}
function f3(a) {
a = 1;
}
function f4() {
var a;
return (a = 1);
}
function f5() {
var a;
return function () {
a = 1;
};
}
console.log(f1())
console.log(f2())
console.log(f3())
console.log(f4())
console.log(f5())"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_issue_3146_1() {
let src = r###"(function (f) {
f("g()");
})(function (a) {
eval(a);
function g(b) {
if (!b) b = "PASS";
console.log(b);
}
});"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_delete_assign_2() {
let src = r###"var a;
console.log(delete (a = undefined));
console.log(delete (a = void 0));
console.log(delete (a = Infinity));
console.log(delete (a = 1 / 0));
console.log(delete (a = NaN));
console.log(delete (a = 0 / 0));"###;
let config = r###"{
"booleans": true,
"keep_infinity": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_drop_unused_drop_toplevel_all_retain() {
let src = r###"var a,
b = 1,
c = g;
function f(d) {
return function () {
c = 2;
};
}
a = 2;
function g() {}
function h() {}
console.log((b = 3));"###;
let config = r###"{
"top_retain": "f,a,o",
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_comparing_issue_2857_6() {
let src = r###"function f(a) {
if ({}.b === undefined || {}.b === null)
return a.b !== undefined && a.b !== null;
}
console.log(
f({
a: [null],
get b() {
return this.a.shift();
},
})
);"###;
let config = r###"{
"comparisons": true,
"pure_getters": "strict",
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_impure_getter_2() {
let src = r###"({
get a() {
console.log(1);
},
b: 1,
}.a);
({
get a() {
console.log(1);
},
b: 1,
}.b);"###;
let config = r###"{
"pure_getters": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_issue_2838() {
let src = r###"function f(a, b) {
(a || b).c = "PASS";
(function () {
return f(a, b);
}.prototype.foo = "bar");
}
var o = {};
f(null, o);
console.log(o.c);"###;
let config = r###"{
"pure_getters": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_issue_2938_4() {
let src = r###"var Parser = function Parser() {};
var p = Parser.prototype;
var unused = p.x;
p.initialContext = function initialContext() {
p.y;
console.log("PASS");
};
p.braceIsBlock = function () {};
new Parser().initialContext();"###;
let config = r###"{
"pure_getters": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_set_mutable_1() {
let src = r###"!(function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
})();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_issue_2938_3() {
let src = r###"function f(a) {
var unused = a.a;
a.b = "PASS";
a.c;
}
var o = {};
o.d;
f(o);
console.log(o.b);"###;
let config = r###"{
"pure_getters": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_set_immutable_6() {
let src = r###"var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");"###;
let config = r###"{
"collapse_vars": true,
"conditionals": true,
"evaluate": true,
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_set_immutable_1() {
let src = r###"var a = 1;
a.foo += "";
if (a.foo) console.log("FAIL");
else console.log("PASS");"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_pure_getters_set_mutable_2() {
let src = r###"!(function a() {
a.foo += "";
if (a.foo) console.log("PASS");
else console.log("FAIL");
})();"###;
let config = r###"{
"collapse_vars": true,
"conditionals": true,
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_dead_code_issue_2860_1() {
let src = r###"console.log(
(function (a) {
return (a ^= 1);
})()
);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_dead_code_global_fns() {
let src = r###"Boolean(1, 2);
decodeURI(1, 2);
decodeURIComponent(1, 2);
Date(1, 2);
encodeURI(1, 2);
encodeURIComponent(1, 2);
Error(1, 2);
escape(1, 2);
EvalError(1, 2);
isFinite(1, 2);
isNaN(1, 2);
Number(1, 2);
Object(1, 2);
parseFloat(1, 2);
parseInt(1, 2);
RangeError(1, 2);
ReferenceError(1, 2);
String(1, 2);
SyntaxError(1, 2);
TypeError(1, 2);
unescape(1, 2);
URIError(1, 2);
try {
Function(1, 2);
} catch (e) {
console.log(e.name);
}
try {
RegExp(1, 2);
} catch (e) {
console.log(e.name);
}
try {
Array(NaN);
} catch (e) {
console.log(e.name);
}"###;
let config = r###"{
"side_effects": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_block_scope_issue_334() {
let src = r###"(function (A) {
(function () {
doPrint();
})();
function doPrint() {
print(A);
}
})("Hello World!");
function print(A) {
if (!A.x) {
console.log(A);
}
}"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_3021() {
let src = r###"var a = 1,
b = 2;
(function () {
b = a;
if (a++ + b--) return 1;
return;
var b = {};
})();
console.log(a, b);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_contains_this_2() {
let src = r###"var o = {
u: function () {
return this === this;
},
p: 1,
};
console.log(o.p, o.p, o.u);"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_hoist_props_issue_851_hoist_to_conflicting_name() {
let src = r###"const BBB = { CCC: "PASS" };
if (id(true)) {
const BBB_CCC = BBB.CCC;
console.log(BBB_CCC);
}"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_name_collision_1() {
let src = r###"var obj_foo = 1;
var obj_bar = 2;
function f() {
var obj = { foo: 3, bar: 4, "b-r": 5, "b+r": 6, "b!r": 7 };
console.log(obj_foo, obj.foo, obj.bar, obj["b-r"], obj["b+r"], obj["b!r"]);
}
f();"###;
let config = r###"{
"hoist_props": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_new_this() {
let src = r###"var o = {
a: 1,
b: 2,
f: function (a) {
this.b = a;
},
};
console.log(new o.f(o.a).b, o.b);"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_toplevel_let() {
let src = r###"let a = { b: 1, c: 2 };
console.log(a.b + a.c);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"toplevel": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_undefined_key() {
let src = r###"var a,
o = {};
o[a] = 1;
o.b = 2;
console.log(o[a] + o.b);"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"join_vars": true,
"passes": 4,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_direct_access_1() {
let src = r###"var a = 0;
var obj = { a: 1, b: 2 };
for (var k in obj) a++;
console.log(a, obj.a);"###;
let config = r###"{
"hoist_props": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2473_3() {
let src = r###"var o = { a: 1, b: 2 };
console.log(o.a, o.b);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"top_retain": "o",
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2473_4() {
let src = r###"(function () {
var o = { a: 1, b: 2 };
console.log(o.a, o.b);
})();"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"top_retain": "o",
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_toplevel_const() {
let src = r###"const a = { b: 1, c: 2 };
console.log(a.b + a.c);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"toplevel": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2377_3() {
let src = r###"var obj = {
foo: 1,
bar: 2,
square: function (x) {
return x * x;
},
cube: function (x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"inline": true,
"passes": 4,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2508_2() {
let src = r###"var o = {
a: { b: 2 },
f: function (x) {
console.log(x);
},
};
o.f(o.a);"###;
let config = r###"{
"collapse_vars": true,
"hoist_props": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2508_5() {
let src = r###"var o = {
f: function (x) {
console.log(x);
},
};
o.f(o.f);"###;
let config = r###"{
"collapse_vars": true,
"hoist_props": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2377_2() {
let src = r###"var obj = {
foo: 1,
bar: 2,
square: function (x) {
return x * x;
},
cube: function (x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_toplevel_var() {
let src = r###"var a = { b: 1, c: 2 };
console.log(a.b + a.c);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true,
"toplevel": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_3046() {
let src = r###"console.log(
(function (a) {
do {
var b = { c: a++ };
} while (b.c && a);
return a;
})(0)
);"###;
let config = r###"{
"hoist_props": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_name_collision_3() {
let src = r###"var o = {
p: 1,
"+": function (x) {
return x;
},
"-": function (x) {
return x + 1;
},
},
o__$0 = 2,
o__$1 = 3;
console.log(o.p === o.p, o["+"](4), o["-"](5));"###;
let config = r###"{
"hoist_props": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_hoist_class_with_new() {
let src = r###"var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, new o.p(o.x).value, new o.p(o.y).value);"###;
let config = r###"{
"comparisons": true,
"evaluate": true,
"hoist_props": true,
"inline": true,
"keep_classnames": true,
"keep_fnames": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, true);
}
#[test]
fn terser_hoist_props_hoist_function_with_call() {
let src = r###"var o = {
p: function Foo(value) {
return 10 * value;
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, o.p(o.x), o.p(o.y));"###;
let config = r###"{
"comparisons": true,
"evaluate": true,
"hoist_props": true,
"inline": true,
"keep_fnames": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_name_collision_2() {
let src = r###"var o = {
p: 1,
"+": function (x) {
return x;
},
"-": function (x) {
return x + 1;
},
},
o__$0 = 2,
o__$1 = 3;
console.log(o.p === o.p, o["+"](4), o["-"](5), o__$0, o__$1);"###;
let config = r###"{
"hoist_props": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_direct_access_2() {
let src = r###"var o = { a: 1 };
var f = function (k) {
if (o[k]) return "PASS";
};
console.log(f("a"));"###;
let config = r###"{
"hoist_props": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_hoist_class() {
let src = r###"function run(c, v) {
return new c(v).value;
}
var o = {
p: class Foo {
constructor(value) {
this.value = value * 10;
}
},
x: 1,
y: 2,
};
console.log(o.p.name, o.p === o.p, run(o.p, o.x), run(o.p, o.y));"###;
let config = r###"{
"comparisons": true,
"evaluate": true,
"hoist_props": true,
"inline": true,
"keep_classnames": true,
"keep_fnames": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, true);
}
#[test]
fn terser_hoist_props_issue_2519() {
let src = r###"function testFunc() {
var dimensions = { minX: 5, maxX: 6 };
var scale = 1;
var d = { x: (dimensions.maxX + dimensions.minX) / 2 };
return d.x * scale;
}
console.log(testFunc());"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"hoist_props": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2377_1() {
let src = r###"var obj = {
foo: 1,
bar: 2,
square: function (x) {
return x * x;
},
cube: function (x) {
return x * x * x;
},
};
console.log(obj.foo, obj.cube(3));"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2508_6() {
let src = r###"var o = {
f: (x) => {
console.log(x);
},
};
o.f(o.f);"###;
let config = r###"{
"collapse_vars": true,
"hoist_props": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_hoist_props_issue_2508_1() {
let src = r###"var o = {
a: [1],
f: function (x) {
console.log(x);
},
};
o.f(o.a);"###;
let config = r###"{
"collapse_vars": true,
"hoist_props": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_identity_inline_identity_extra_params() {
let src = r###"const id = (x) => x;
console.log(id(1, console.log(2)), id(3, 4));"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_identity_inline_identity_function() {
let src = r###"function id(x) {
return x;
}
console.log(id(1), id(2));"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_identity_inline_identity_duplicate_arg_var() {
let src = r###"const id = (x) => {
return x;
var x;
};
console.log(id(1), id(2));"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_template_string_regex_2() {
let src = r###"console.log(`${/a/} ${6 / 2} ${/b/.test("b")} ${1 ? /c/ : /d/}`);"###;
let config = r###"{
"evaluate": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_template_string_evaluate_nested_templates() {
let src = r###"/*#__NOINLINE__*/ const any = 'any string, but should not be inlined';
var foo = `${`${`${`foo`}`}`}`;
var bar = `before ${`innerBefore ${any} innerAfter`} after`;
var baz = `1 ${2 + `3 ${any} 4` + 5} 6`;
console.log(foo);
console.log(bar);
console.log(baz);"###;
let config = r###"{
"evaluate": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_destructuring_assign_of_computed_key() {
let src = r###"let x;
let four = 4;
({ [5 + 2 - four]: x } = { [1 + 2]: 42 });
console.log(x);"###;
let config = r###"{
"evaluate": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_unused_destructuring_getter_side_effect_2() {
let src = r###"function extract(obj) {
const { a: a, b: b } = obj;
console.log(b);
}
extract({ a: 1, b: 2 });
extract({
get a() {
var s = "side effect";
console.log(s);
return s;
},
b: 4,
});"###;
let config = r###"{
"pure_getters": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_mangle_destructuring_decl_array() {
let src = r###"var [, t, e, n, s, o = 2, r = [1 + 2]] = [9, 8, 7, 6];
console.log(t, e, n, s, o, r);"###;
let config = r###"{
"evaluate": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_issue_3205_4() {
let src = r###"(function () {
function f(o) {
var { a: x } = o;
console.log(x);
}
f({ a: "PASS" });
})();"###;
let config = r###"{
"inline": 3,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_issue_3205_3() {
let src = r###"(function () {
function f(o, { a: x } = o) {
console.log(x);
}
f({ a: "PASS" });
})();"###;
let config = r###"{
"inline": 3,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_unused_destructuring_multipass() {
let src = r###"let { w: w, x: y, z: z } = { x: 1, y: 2, z: 3 };
console.log(y);
if (0) {
console.log(z);
}"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"toplevel": true,
"passes": 2,
"pure_getters": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_arrow_func_with_destructuring_args() {
let src = r###"(({ foo: foo = 1 + 0, bar: bar = 2 }, [car = 3, far = 4]) => {
console.log(foo, bar, car, far);
})({ bar: 5 - 0 }, [, 6]);"###;
let config = r###"{
"evaluate": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_issue_3205_2() {
let src = r###"(function () {
function f() {
var o = { a: "PASS" },
{ a: x } = o;
console.log(x);
}
f();
})();"###;
let config = r###"{
"inline": 3,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_empty_object_destructuring_3() {
let src = r###"var {} = Object;
let { L: L } = Object,
L2 = "foo";
const bar = "bar",
{ prop: C1, C2: C2 = console.log("side effect"), C3: C3 } = Object;"###;
let config = r###"{
"pure_getters": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_empty_object_destructuring_4() {
let src = r###"var {} = Object;
let { L: L } = Object,
L2 = "foo";
const bar = "bar",
{ prop: C1, C2: C2 = console.log("side effect"), C3: C3 } = Object;"###;
let config = r###"{
"pure_getters": true,
"toplevel": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_issue_3205_5() {
let src = r###"(function () {
function f(g) {
var o = g,
{ a: x } = o;
console.log(x);
}
f({ a: "PASS" });
})();"###;
let config = r###"{
"inline": 3,
"passes": 4,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_unused_destructuring_decl_1() {
let src = r###"let { x: L, y: y } = { x: 2 };
var { U: u, V: V } = { V: 3 };
const { C: C, D: D } = { C: 1, D: 4 };
console.log(L, V);"###;
let config = r###"{
"pure_getters": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_mangle_destructuring_decl() {
let src = r###"function test(opts) {
let a = opts.a || { e: 7, n: 8 };
let { t: t, e: e, n: n, s: s = 5 + 4, o: o, r: r } = a;
console.log(t, e, n, s, o, r);
}
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});"###;
let config = r###"{
"evaluate": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_unused_destructuring_arrow_param() {
let src = r###"let bar = ({ w: w = console.log("side effect"), x: x, y: z }) => {
console.log(x);
};
bar({ x: 4, y: 5, z: 6 });"###;
let config = r###"{
"pure_getters": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_anon_func_with_destructuring_args() {
let src = r###"(function ({ foo: foo = 1 + 0, bar: bar = 2 }, [car = 3, far = 4]) {
console.log(foo, bar, car, far);
})({ bar: 5 - 0 }, [, 6]);"###;
let config = r###"{
"evaluate": true,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_mangle_destructuring_assign_toplevel_true() {
let src = r###"function test(opts) {
let s, o, r;
let a = opts.a || { e: 7, n: 8 };
({ t, e, n, s = 5 + 4, o, r } = a);
console.log(t, e, n, s, o, r);
}
let t, e, n;
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});"###;
let config = r###"{
"toplevel": true,
"evaluate": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_mangle_destructuring_decl_collapse_vars() {
let src = r###"function test(opts) {
let a = opts.a || { e: 7, n: 8 };
let { t: t, e: e, n: n, s: s = 5 + 4, o: o, r: r } = a;
console.log(t, e, n, s, o, r);
}
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_unused_destructuring_decl_5() {
let src = r###"const { a: a, b: c, d: d = new Object(1) } = { b: 7 };
let { e: e, f: g, h: h = new Object(2) } = { e: 8 };
var { w: w, x: y, z: z = new Object(3) } = { w: 4, x: 5, y: 6 };
console.log(c, e, z + 0);"###;
let config = r###"{
"pure_getters": true,
"toplevel": true,
"top_retain": ["a", "e", "w"],
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_destructuring_mangle_destructuring_assign_toplevel_false() {
let src = r###"function test(opts) {
let s, o, r;
let a = opts.a || { e: 7, n: 8 };
({ t, e, n, s = 9, o, r } = a);
console.log(t, e, n, s, o, r);
}
let t, e, n;
test({ a: { t: 1, e: 2, n: 3, s: 4, o: 5, r: 6 } });
test({});"###;
let config = r###"{
"toplevel": false,
"evaluate": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arrow_issue_2105_2() {
let src = r###"((factory) => {
factory();
})(() =>
((fn) => {
fn()().prop();
})(() => {
let bar = () => {
var quux = () => {
console.log("PASS");
},
foo = () => {
console.log;
quux();
};
return { prop: foo };
};
return bar;
})
);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arrow_issue_2105_1() {
let src = r###"!(function (factory) {
factory();
})(function () {
return (function (fn) {
fn()().prop();
})(function () {
function bar() {
var quux = function () {
console.log("PASS");
},
foo = function () {
console.log;
quux();
};
return { prop: foo };
}
return bar;
});
});"###;
let config = r###"{
"unsafe_arrows": true,
"collapse_vars": true,
"ecma": 2015,
"inline": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"unsafe_methods": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arrow_issue_2084() {
let src = r###"var c = 0;
!(function () {
!(function (c) {
c = 1 + c;
var c = 0;
function f14(a_1) {
if (((c = 1 + c), 0 !== (23).toString()))
(c = 1 + c), a_1 && (a_1[0] = 0);
}
f14();
})(-1);
})();
console.log(c);"###;
let config = r###"{
"unsafe_arrows": true,
"collapse_vars": true,
"conditionals": true,
"ecma": 2015,
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_t120_issue_t120_4() {
let src = r###"for (
var x = 1,
t = (o) => {
var i = +o;
return console.log(i + i) && 0;
};
x--;
t(2)
);"###;
let config = r###"{
"defaults": true,
"inline": 3,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_t120_issue_t120_5() {
let src = r###"for (
var x = 1,
t = (o) => {
var i = +o;
return console.log(i + i) && 0;
};
x--;
)
t(3);"###;
let config = r###"{
"defaults": true,
"inline": 3,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_class_properties_mangle_keep_quoted() {
let src = r###"class Foo {
bar = "bar";
static zzz = "zzz";
toString() {
return this.bar + Foo.zzz;
}
}
console.log(new Foo().toString())"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_class_properties_static_means_execution() {
let src = r###"let x = 0;
class NoProps {}
class WithProps {
prop = (x = x === 1 ? "PASS" : "FAIL");
}
class WithStaticProps {
static prop = (x = x === 0 ? 1 : "FAIL");
}
new NoProps();
new WithProps();
new WithStaticProps();
console.log(x);"###;
let config = r###"{
"toplevel": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1447_conditional_false_stray_else_in_loop() {
let src = r###"for (var i = 1; i <= 4; ++i) {
if (i <= 2) continue;
console.log(i);
}"###;
let config = r###"{
"booleans": true,
"comparisons": true,
"conditionals": false,
"dead_code": true,
"evaluate": true,
"hoist_vars": true,
"if_return": true,
"join_vars": true,
"loops": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_object_spread_unsafe() {
let src = r###"var o1 = { x: 1, y: 2 };
var o2 = { x: 3, z: 4 };
var cloned = { ...o1 };
var merged = { ...o1, ...o2 };
console.log(cloned, merged);"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"join_vars": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2794_4() {
let src = r###"for (var x of ([1, 2], [3, 4])) {
console.log(x);
}"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2794_3() {
let src = r###"function foo() {
for (const a of func(value)) {
console.log(a);
}
function func(va) {
return doSomething(va);
}
}
function doSomething(x) {
return [x, 2 * x, 3 * x];
}
const value = 10;
foo();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": 3,
"passes": 3,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_array_spread_of_sequence() {
let src = r###"var a = [1];
console.log([...(a, a)]);
console.log([...a, a]);
console.log([...(a || a)]);
console.log([...(a || a)]);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2794_2() {
let src = r###"function foo() {
for (const a of func(value)) {
console.log(a);
}
function func(va) {
return doSomething(va);
}
}
function doSomething(x) {
return [x, 2 * x, 3 * x];
}
const value = 10;
foo();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"passes": 1,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": false,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2874_1() {
let src = r###"(function () {
function foo() {
let letters = ["A", "B", "C"];
let result = [2, 1, 0].map((key) => bar(letters[key] + key));
return result;
}
function bar(value) {
return () => console.log(value);
}
foo().map((fn) => fn());
})();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": 3,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2762() {
let src = r###"var bar = 1,
T = true;
(function () {
if (T) {
const a = function () {
var foo = bar;
console.log(foo, a.prop, b.prop);
};
a.prop = 2;
const b = { prop: 3 };
a();
}
})();"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_1898() {
let src = r###"class Foo {
bar() {
for (const x of [6, 5]) {
for (let y of [4, 3]) {
for (var z of [2, 1]) {
console.log(x, y, z);
}
}
}
}
}
new Foo().bar();"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2794_6() {
let src = r###"for (let e of ([1, 2], [3, 4, 5])) {
console.log(e);
}"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2794_1() {
let src = r###"function foo() {
for (const a of func(value)) {
console.log(a);
}
function func(va) {
return doSomething(va);
}
}
function doSomething(x) {
return [x, 2 * x, 3 * x];
}
const value = 10;
foo();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"passes": 1,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": false,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2874_2() {
let src = r###"(function () {
let keys = [];
function foo() {
var result = [2, 1, 0].map((value) => {
keys.push(value);
return bar();
});
return result;
}
function bar() {
var letters = ["A", "B", "C"],
key = keys.shift();
return () => console.log(letters[key] + key);
}
foo().map((fn) => fn());
})();"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": 3,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_t80() {
let src = r###"function foo(data = []) {
var u,
v = "unused";
if (arguments.length == 1) {
data = [data];
}
return data;
}
console.log(JSON.stringify([foo(), foo(null), foo(5, 6)]));"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2349() {
let src = r###"function foo(boo, key) {
const value = boo.get();
return value.map(({ [key]: bar }) => bar);
}
console.log(foo({ get: () => [{ blah: 42 }] }, "blah"));"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2874_3() {
let src = r###"function f() {
return x + y;
}
let x, y;
let a = (z) => {
x = "A";
y = z;
console.log(f());
};
a(1);
a(2);"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": 3,
"reduce_funcs": false,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_harmony_issue_2349b() {
let src = r###"function foo(boo, key) {
const value = boo.get();
return value.map(function ({ [key]: bar }) {
return bar;
});
}
console.log(
foo(
{
get: function () {
return [{ blah: 42 }];
},
},
"blah"
)
);"###;
let config = r###"{
"arrows": true,
"collapse_vars": true,
"ecma": 2015,
"evaluate": true,
"inline": true,
"passes": 3,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"side_effects": true,
"unsafe_arrows": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1275_string_plus_optimization() {
let src = r###"function foo(anything) {
function throwing_function() {
throw "nope";
}
try {
console.log("0" + throwing_function() ? "yes" : "no");
} catch (ex) {
console.log(ex);
}
console.log("0" + anything ? "yes" : "no");
console.log(anything + "0" ? "Yes" : "No");
console.log("" + anything);
console.log(anything + "");
}
foo();"###;
let config = r###"{
"booleans": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_async_async_inline() {
let src = r###"(async function () {
return await 3;
})();
(async function (x) {
await console.log(x);
})(4);
function invoke(x, y) {
return x(y);
}
invoke(async function () {
return await 1;
});
invoke(async function (x) {
await console.log(x);
}, 2);
function top() {
console.log("top");
}
top();
async function async_top() {
console.log("async_top");
}
async_top();"###;
let config = r###"{
"collapse_vars": true,
"conditionals": true,
"evaluate": true,
"inline": true,
"negate_iife": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_logical_assignments_assign_in_conditional_part() {
let src = r###"var status = "PASS";
var nil = null;
var nil_prop = { prop: null };
nil &&= console.log((status = "FAIL"));
nil_prop.prop &&= console.log((status = "FAIL"));
console.log(status);"###;
let config = r###"{
"toplevel": true,
"evaluate": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_logical_assignments_assignment_in_left_part() {
let src = r###"var status = "FAIL";
var x = {};
x[(status = "PASS")] ||= 1;
console.log(status);"###;
let config = r###"{
"toplevel": true,
"evaluate": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_labels_labels_4() {
let src = r###"out: for (var i = 0; i < 5; ++i) {
if (i < 3) continue out;
console.log(i);
}"###;
let config = r###"{
"conditionals": true,
"dead_code": true,
"if_return": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_labels_labels_3() {
let src = r###"for (var i = 0; i < 5; ++i) {
if (i < 3) continue;
console.log(i);
}"###;
let config = r###"{
"conditionals": true,
"dead_code": true,
"if_return": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_labels_labels_6() {
let src = r###"out: break out;
console.log('PASS')"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_t292_no_flatten_with_var_colliding_with_arg_value_inner_scope() {
let src = r###"var g = ["a"];
function problem(arg) {
return g.indexOf(arg);
}
function unused(arg) {
return problem(arg);
}
function a(arg) {
return problem(arg);
}
function b(test) {
var problem = test * 2;
console.log(problem);
return g[problem];
}
function c(arg) {
return b(a(arg));
}
console.log(c("a"));"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_t292_no_flatten_with_arg_colliding_with_arg_value_inner_scope() {
let src = r###"var g = ["a"];
function problem(arg) {
return g.indexOf(arg);
}
function unused(arg) {
return problem(arg);
}
function a(arg) {
return problem(arg);
}
function b(problem) {
return g[problem];
}
function c(arg) {
return b(a(arg));
}
console.log(c("a"));"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1770_numeric_literal() {
let src = r###"var obj = {
0: 0,
"-0": 1,
42: 2,
42: 3,
37: 4,
o: 5,
1e42: 6,
j: 7,
1e42: 8,
};
console.log(obj[-0], obj[-""], obj["-0"]);
console.log(obj[42], obj["42"]);
console.log(obj[37], obj["o"], obj[37], obj["37"]);
console.log(obj[1e42], obj["j"], obj["1e+42"]);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1770_mangle_props() {
let src = r###"var obj = { undefined: 1, NaN: 2, Infinity: 3, "-Infinity": 4, null: 5 };
console.log(
obj[void 0],
obj[undefined],
obj["undefined"],
obj[0 / 0],
obj[NaN],
obj["NaN"],
obj[1 / 0],
obj[Infinity],
obj["Infinity"],
obj[-1 / 0],
obj[-Infinity],
obj["-Infinity"],
obj[null],
obj["null"]
);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1105_infinity_not_in_with_scope() {
let src = r###"var o = { Infinity: "oInfinity" };
var vInfinity = "Infinity";
vInfinity = Infinity;
console.log(o)
console.log(vInfinity)"###;
let config = r###"{
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_3113_1() {
let src = r###"var c = 0;
(function () {
function f() {
while (g());
}
var a = f();
function g() {
a && a[c++];
}
g((a = 1));
})();
console.log(c);"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2799_2() {
let src = r###"(function () {
function foo() {
Function.prototype.call.apply(console.log, [null, "PASS"]);
}
foo();
})();"###;
let config = r###"{
"reduce_vars": true,
"unsafe_proto": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_recursive_inlining_1() {
let src = r###"!(function () {
function foo() {
bar();
}
function bar() {
foo();
}
console.log("PASS");
})();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_var_assign_2() {
let src = r###"!(function () {
var a;
if ((a = 2)) console.log(a);
})();"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2757_1() {
let src = r###"let u;
(function () {
let v;
console.log(u, v);
})();"###;
let config = r###"{
"evaluate": true,
"inline": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_inverted_var() {
let src = r###"console.log(
(function () {
var a = 1;
return a;
})(),
(function () {
var b;
b = 2;
return b;
})(),
(function () {
c = 3;
return c;
var c;
})(),
(function (c) {
c = 4;
return c;
})(),
(function (c) {
c = 5;
return c;
var c;
})(),
(function c() {
c = 6;
return typeof c;
})(),
(function c() {
c = 7;
return c;
var c;
})(),
(function () {
c = 8;
return c;
var c = "foo";
})()
);"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_pure_getters_3() {
let src = r###"var a;
var a = a && a.b;
console.log(a && a.b)"###;
let config = r###"{
"pure_getters": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_side_effect_free_1() {
let src = r###"console.log(
(function () {
var o = { p: 1 };
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 2 };
console.log(o.p);
return o;
})()
);
console.log(
(function () {
var o = { p: 3 };
console.log([o][0].p);
return o.p;
})()
);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2420_2() {
let src = r###"function f() {
var that = this;
if (that.bar) that.foo();
else
!(function (that, self) {
console.log(this === that, self === this, that === self);
})(that, this);
}
f.call({
bar: 1,
foo: function () {
console.log("foo", this.bar);
},
});
f.call({});"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_escape_expansion() {
let src = r###"function main() {
var thing = baz();
if (thing !== (thing = baz())) console.log("FAIL");
else console.log("PASS");
}
function foo() {}
function bar(...x) {
return x[0];
}
function baz() {
return bar(...[foo]);
}
main();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_obj_arg_1() {
let src = r###"var C = 1;
function f(obj) {
return obj.bar();
}
console.log(
f({
bar: function () {
return C + C;
},
})
);"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2420_3() {
let src = r###"function f() {
var that = this;
if (that.bar) that.foo();
else
((that, self) => {
console.log(this === that, self === this, that === self);
})(that, this);
}
f.call({
bar: 1,
foo: function () {
console.log("foo", this.bar);
},
});
f.call({});"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_reduce_vars_iife_eval_2() {
let src = r###"(function () {
var x = function f() {
return f;
};
console.log(x() === eval("x"));
})();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_pure_getters_2() {
let src = r###"var a;
var a = a && a.b;
console.log(a && a.b)"###;
let config = r###"{
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_func_modified() {
let src = r###"function f(a) {
function a() {
return 1;
}
function b() {
return 2;
}
function c() {
return 3;
}
b.inject = [];
c = function () {
return 4;
};
return a() + b() + c();
}
console.log(f(1423796))"###;
let config = r###"{
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2860_1() {
let src = r###"console.log(
(function (a) {
return (a ^= 1);
a ^= 2;
})()
);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2836() {
let src = r###"function f() {
return "FAIL";
}
console.log(f());
function f() {
return "PASS";
}"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_chained_assignments() {
let src = r###"function f() {
var a = [94, 173, 190, 239];
var b = 0;
b |= a[0];
b <<= 8;
b |= a[1];
b <<= 8;
b |= a[2];
b <<= 8;
b |= a[3];
return b;
}
console.log(f().toString(16));"###;
let config = r###"{
"evaluate": true,
"inline": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_obj_for_1() {
let src = r###"var o = { a: 1 };
for (var i = o.a--; i; i--) console.log(i);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_iife() {
let src = r###"!(function (a, b, c) {
b++;
console.log(a - 1, b * 1, c + 2);
})(1, 2, 3);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_inner_var_label() {
let src = r###"function f(a) {
l: {
if (a) break l;
var t = 1;
}
console.log(t);
}
f(123123)
f(0)"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_side_effects_assign() {
let src = r###"var a = typeof void (a && a.in == 1, 0);
console.log(a);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_catch_6() {
let src = r###"try {
throw 42;
} catch (a) {
console.log(a);
}
function a() {}"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_passes() {
let src = r###"function f() {
var a = 1,
b = 2,
c = 3;
if (a) {
b = c;
} else {
c = b;
}
console.log(a + b);
console.log(b + c);
console.log(a + c);
console.log(a + b + c);
}
f()"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_catch_1() {
let src = r###"function a() {}
try {
throw 42;
} catch (a) {
console.log(a);
}"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_array_2() {
let src = r###"var arr = [
1,
2,
function (x) {
return x * x;
},
function (x) {
return x * x * x;
},
];
console.log(arr[0], arr[1], arr[2](2), arr[3]);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_6() {
let src = r###"(function (a) {
switch (1) {
case (a = 1):
console.log(a);
break;
default:
console.log(2);
break;
}
})(1);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"keep_fargs": false,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_redefine_farg_1() {
let src = r###"function f(a) {
var a;
return typeof a;
}
function g(a) {
var a = 42;
return typeof a;
}
function h(a, b) {
var a = b;
return typeof a;
}
console.log(f([]), g([]), h([]));"###;
let config = r###"{
"evaluate": true,
"keep_fargs": false,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_1() {
let src = r###"(function f() {
switch (1) {
case 0:
var a = true;
break;
default:
if (typeof a === "undefined") console.log("PASS");
else console.log("FAIL");
}
})();"###;
let config = r###"{
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"typeofs": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_perf_3() {
let src = r###"var foo = function (x, y, z) {
return x < y ? x * y + z : x * z - y;
};
var indirect_foo = function (x, y, z) {
return foo(x, y, z);
};
var sum = 0;
for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i);
console.log(sum);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_var_3() {
let src = r###"function a() {}
function b() {}
console.log(typeof a, typeof b);
var a = 42,
b;"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true,
"toplevel": true,
"typeofs": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_accessor_2() {
let src = r###"var A = 1;
var B = {
get c() {
console.log(A);
},
};
B.c;"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unused_modified() {
let src = r###"console.log(
(function () {
var b = 1,
c = "FAIL";
if (0 || b--) c = "PASS";
b = 1;
return c;
})()
);"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_object_1() {
let src = r###"function f0() {
var a = 1;
var b = {};
b[a] = 2;
console.log(a + 3);
}
function f1() {
var a = { b: 1 };
a.b = 2;
console.log(a.b + 3);
}
f0()
f1()"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_duplicate_lambda_defun_name_1() {
let src = r###"console.log(
(function f(a) {
function f() {}
return f.length;
})()
);"###;
let config = r###"{
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2423_5() {
let src = r###"function x() {
y();
}
function y() {
console.log(1);
}
function z() {
function y() {
console.log(2);
}
x();
}
z();
z();"###;
let config = r###"{
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_array_4() {
let src = r###"var arr = [
1,
2,
function () {
return ++this[0];
},
];
console.log(arr[0], arr[1], arr[2], arr[0]);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2774() {
let src = r###"console.log(
{
get a() {
var b;
(b = true) && b.c;
b = void 0;
},
}.a
);"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_lvalues_def_2() {
let src = r###"var b = 1;
var a = (b += 1),
b = NaN;
console.log(a, b);"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_func_arg_2() {
let src = r###"var a = 42;
!(function (a) {
console.log(a());
})(function (a) {
return a;
});"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate() {
let src = r###"function f0() {
var a = { b: 1 };
console.log(a.b + 3);
}
function f1() {
var a = { b: { c: 1 }, d: 2 };
console.log(a.b + 3, a.d + 4, a.b.c + 5, a.d.c + 6);
}
console.log(f0())
console.log(f1())"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2423_3() {
let src = r###"function c() {
return 1;
}
function p() {
console.log(c());
}
p();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_inline_3() {
let src = r###"function f() {
return g(2);
function g(b) {
return b;
}
}
console.log(f())"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_3113_2() {
let src = r###"var c = 0;
(function () {
function f() {
while (g());
}
var a = f();
function g() {
a && a[c++];
}
a = 1;
g();
})();
console.log(c);"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2799_1() {
let src = r###"console.log(
(function () {
return f;
function f(n) {
function g(i) {
return i && i + g(i - 1);
}
function h(j) {
return g(j);
}
return h(n);
}
})()(5)
);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_iife_new() {
let src = r###"var A = new (function (a, b, c) {
b++;
console.log(a - 1, b * 1, c + 2);
})(1, 2, 3);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_recursive_inlining_3() {
let src = r###"!(function () {
function foo(x) {
console.log("foo", x);
if (x) bar(x - 1);
}
function bar(x) {
console.log("bar", x);
if (x) qux(x - 1);
}
function qux(x) {
console.log("qux", x);
if (x) foo(x - 1);
}
qux(4);
})();"###;
let config = r###"{
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_recursive_inlining_4() {
let src = r###"!(function () {
function foo(x) {
console.log("foo", x);
if (x) bar(x - 1);
}
function bar(x) {
console.log("bar", x);
if (x) qux(x - 1);
}
function qux(x) {
console.log("qux", x);
if (x) foo(x - 1);
}
qux(4);
bar(5);
})();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2757_2() {
let src = r###"(function () {
let bar;
const unused = function () {
bar = true;
};
if (!bar) {
console.log(1);
}
console.log(2);
})();"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_recursive_inlining_2() {
let src = r###"!(function () {
function foo() {
qux();
}
function bar() {
foo();
}
function qux() {
bar();
}
console.log("PASS");
})();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_var_assign_1() {
let src = r###"!(function () {
var a;
a = 2;
console.log(a);
})();"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1865() {
let src = r###"function f(some) {
some.thing = false;
}
console.log(
(function () {
var some = { thing: true };
f(some);
return some.thing;
})()
);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2449() {
let src = r###"var a = "PASS";
function f() {
return a;
}
function g() {
return f();
}
(function () {
var a = "FAIL";
if (a == a) console.log(g());
})();"###;
let config = r###"{
"passes": 10,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2420_1() {
let src = r###"function run() {
var self = this;
if (self.count++) self.foo();
else self.bar();
}
var o = {
count: 0,
foo: function () {
console.log("foo");
},
bar: function () {
console.log("bar");
},
};
run.call(o);
run.call(o);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2485() {
let src = r###"var foo = function (bar) {
var n = function (a, b) {
return a + b;
};
var sumAll = function (arg) {
return arg.reduce(n, 0);
};
var runSumAll = function (arg) {
return sumAll(arg);
};
bar.baz = function (arg) {
var n = runSumAll(arg);
return (n.get = 1), n;
};
return bar;
};
var bar = foo({});
console.log(bar.baz([1, 2, 3]));"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_inner_var_for_2() {
let src = r###"!(function () {
var a = 1;
for (var b = 1; --b; ) var a = 2;
console.log(a);
})();"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_obj_arg_2() {
let src = r###"var C = 1;
function f(obj) {
return obj.bar();
}
console.log(
f({
bar: function () {
return C + C;
},
})
);"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"passes": 3,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_reduce_vars_reduce_vars() {
let src = r###"var A = 1;
(function f0() {
var a = 2;
console.log(a - 5);
console.log(A - 5);
})();
(function f1() {
var a = 2;
console.log(a - 5);
eval("console.log(a);");
})();
(function f2(eval) {
var a = 2;
console.log(a - 5);
eval("console.log(a);");
})(eval);
(function f3() {
var b = typeof C !== "undefined";
var c = 4;
if (b) {
return "yes";
} else {
return "no";
}
})();
console.log(A + 1);"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"global_defs": {
"C": 0
},
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_modified() {
let src = r###"function f0() {
var a = 1,
b = 2;
b++;
console.log(a + 1);
console.log(b + 1);
}
function f1() {
var a = 1,
b = 2;
--b;
console.log(a + 1);
console.log(b + 1);
}
function f2() {
var a = 1,
b = 2,
c = 3;
b = c;
console.log(a + b);
console.log(b + c);
console.log(a + c);
console.log(a + b + c);
}
function f3() {
var a = 1,
b = 2,
c = 3;
b *= c;
console.log(a + b);
console.log(b + c);
console.log(a + c);
console.log(a + b + c);
}
function f4() {
var a = 1,
b = 2,
c = 3;
if (a) {
b = c;
} else {
c = b;
}
console.log(a + b);
console.log(b + c);
console.log(a + c);
console.log(a + b + c);
}
function f5(a) {
B = a;
console.log(typeof A ? "yes" : "no");
console.log(typeof B ? "yes" : "no");
}
f0(), f1(), f2(), f3(), f4(), f5();"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_escaped() {
let src = r###"console.log(
(function () {
var o = { p: 1 };
console.log(o, o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 2 };
console.log(o.p, o);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 3 },
a = [o];
console.log(a[0].p++);
return o.p;
})()
);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2669() {
let src = r###"let foo;
console.log(([foo] = ["PASS"]) && foo);"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_catch_3() {
let src = r###"try {
throw 42;
function a() {}
} catch (a) {
console.log(a);
}"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2860_2() {
let src = r###"console.log(
(function (a) {
return (a ^= 1);
a ^= 2;
})()
);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_delay_def() {
let src = r###"function f() {
return a;
var a;
}
function g() {
return a;
var a = 1;
}
console.log(f(), g());"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2496() {
let src = r###"function execute(callback) {
callback();
}
class Foo {
constructor(message) {
this.message = message;
}
go() {
this.message = "PASS";
console.log(this.message);
}
run() {
execute(() => {
this.go();
});
}
}
new Foo("FAIL").run();"###;
let config = r###"{
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_catch_2() {
let src = r###"try {
function a() {}
throw 42;
} catch (a) {
console.log(a);
}"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2450_5() {
let src = r###"var a;
function f(b) {
console.log(a === b);
a = b;
}
function g() {}
[1, 2, 3].forEach(function () {
f(g);
});"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1850_2() {
let src = r###"function f() {
console.log(a, a, a);
}
var a = 1;
f();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": "funcs",
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_3110_3() {
let src = r###"(function () {
function foo() {
return isDev ? "foo" : "bar";
}
console.log(foo());
var isDev = true;
var obj = { foo: foo };
console.log(obj.foo());
})();"###;
let config = r###"{
"conditionals": true,
"evaluate": true,
"inline": true,
"properties": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_redefine() {
let src = r###"function f() {
function g() {
return 1;
}
function h() {
return 2;
}
g = function () {
return 3;
};
return g() + h();
}
console.log(f())"###;
let config = r###"{
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2423_6() {
let src = r###"function x() {
y();
}
function y() {
console.log(1);
}
function z() {
function y() {
console.log(2);
}
x();
y();
}
z();
z();"###;
let config = r###"{
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_object_2() {
let src = r###"var obj = {
foo: 1,
bar: 2,
square: function (x) {
return x * x;
},
cube: function (x) {
return x * x * x;
},
};
console.log(obj.foo, obj.bar, obj.square(2), obj.cube);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_2423_1() {
let src = r###"function c() {
return 1;
}
function p() {
console.log(c());
}
p();
p();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_redefine_farg_2() {
let src = r###"function f(a) {
var a;
return typeof a;
}
function g(a) {
var a = 42;
return typeof a;
}
function h(a, b) {
var a = b;
return typeof a;
}
console.log(f([]), g([]), h([]));"###;
let config = r###"{
"evaluate": true,
"inline": true,
"keep_fargs": false,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_2() {
let src = r###"(function f() {
switch (1) {
case 0:
var a = true;
break;
default:
if (typeof a === "undefined") console.log("PASS");
else console.log("FAIL");
}
})();"###;
let config = r###"{
"conditionals": true,
"dead_code": true,
"evaluate": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_unsafe_evaluate_array_1() {
let src = r###"function f0() {
var a = 1;
var b = [];
b[a] = 2;
console.log(a + 3);
}
function f1() {
var a = [1];
a[2] = 3;
console.log(a.length);
}
function f2() {
var a = [1];
a.push(2);
console.log(a.length);
}
console.log(f0())
console.log(f1())
console.log(f2())"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_perf_7() {
let src = r###"var indirect_foo = function (x, y, z) {
var foo = function (x, y, z) {
return x < y ? x * y + z : x * z - y;
};
return foo(x, y, z);
};
var sum = 0;
for (var i = 0; i < 100; ++i) sum += indirect_foo(i, i + 1, 3 * i);
console.log(sum);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_5() {
let src = r###"(function (a) {
switch (1) {
case a:
console.log(a);
break;
default:
console.log(2);
break;
}
})(1);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"keep_fargs": false,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_escaped_prop_3() {
let src = r###"var a;
function f(b) {
if (a) console.log(a === b.c);
a = b.c;
}
function g() {}
function h() {
f({ c: g });
}
h();
h();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_call() {
let src = r###"function f() {
return g() + h(1) - h(g(), 2, 3);
function g() {
return 4;
}
function h(a) {
return a;
}
}
console.log(f())"###;
let config = r###"{
"evaluate": true,
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_defun_label() {
let src = r###"!(function () {
function f(a) {
L: {
if (a) break L;
return 1;
}
}
console.log(f(2));
})();"###;
let config = r###"{
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_reduce_vars_unsafe_evaluate_modified() {
let src = r###"console.log(
(function () {
var o = { p: 1 };
o.p++;
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 2 };
--o.p;
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 3 };
o.p += "";
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 4 };
o = {};
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 5 };
o.p = -9;
console.log(o.p);
return o.p;
})()
);
function inc() {
this.p++;
}
console.log(
(function () {
var o = { p: 6 };
inc.call(o);
console.log(o.p);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 7 };
console.log([o][0].p++);
return o.p;
})()
);
console.log(
(function () {
var o = { p: 8 };
console.log({ q: o }.q.p++);
return o.p;
})()
);"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_lvalues_def_1() {
let src = r###"var b = 1;
var a = b++,
b = NaN;
console.log(a, b);"###;
let config = r###"{
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_func_arg_1() {
let src = r###"var a = 42;
!(function (a) {
console.log(a());
})(function () {
return a;
});"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_escape_local_sequence() {
let src = r###"function main() {
var thing = baz();
if (thing !== (thing = baz())) console.log("PASS");
else console.log("FAIL");
}
function baz() {
function foo() {}
function bar() {}
return foo, bar;
}
main();"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_regex_loop() {
let src = r###"function f(x) {
for (var r, s = "acdabcdeabbb"; (r = x().exec(s)); ) console.log(r[0]);
}
var a = /ab*/g;
f(function () {
return a;
});"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_3140_4() {
let src = r###"(function () {
var a;
function f() {}
f.g = function g() {
var o = { p: this };
function h() {
console.log(a ? "PASS" : "FAIL");
}
a = true;
o.p();
a = false;
h.g = g;
return h;
};
return f;
})()
.g()
.g();"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_4() {
let src = r###"(function f() {
switch (1) {
case 0:
var a = true;
break;
case 1:
if (typeof a === "undefined") console.log("PASS");
else console.log("FAIL");
}
})();"###;
let config = r###"{
"conditionals": true,
"dead_code": true,
"evaluate": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_redefine_farg_3() {
let src = r###"function f(a) {
var a;
return typeof a;
}
function g(a) {
var a = 42;
return typeof a;
}
function h(a, b) {
var a = b;
return typeof a;
}
console.log(f([]), g([]), h([]));"###;
let config = r###"{
"collapse_vars": true,
"evaluate": true,
"inline": true,
"keep_fargs": false,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_3140_3() {
let src = r###"(function () {
var a;
function f() {}
f.g = function g() {
var self = this;
function h() {
console.log(a ? "PASS" : "FAIL");
}
a = true;
(function () {
return self;
})()();
a = false;
h.g = g;
return h;
};
return f;
})()
.g()
.g();"###;
let config = r###"{
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_issue_1670_3() {
let src = r###"(function f() {
switch (1) {
case 0:
var a = true;
break;
case 1:
if (typeof a === "undefined") console.log("PASS");
else console.log("FAIL");
}
})();"###;
let config = r###"{
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"switches": true,
"typeofs": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_reduce_vars_perf_1() {
let src = r###"function foo(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
function indirect_foo(x, y, z) {
return foo(x, y, z);
}
var sum = 0;
for (var i = 0; i < 100; ++i) {
sum += indirect_foo(i, i + 1, 3 * i);
}
console.log(sum);"###;
let config = r###"{
"reduce_funcs": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2187_2() {
let src = r###"var b = 1;
console.log(
(function (a) {
return a && ++b;
})(b--)
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2436_14() {
let src = r###"var a = "PASS";
var b = {};
(function () {
var c = a;
c &&
(function (c, d) {
console.log(c, d);
})(b, c);
})();"###;
let config = r###"{
"collapse_vars": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2506() {
let src = r###"var c = 0;
function f0(bar) {
function f1(Infinity_2) {
function f13(NaN) {
if ((false <= NaN) & (this >> 1 >= 0)) {
c++;
}
}
var b_2 = f13(NaN, c++);
}
var bar = f1(-3, -1);
}
f0(false);
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"passes": 2,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2436_13() {
let src = r###"var a = "PASS";
(function () {
function f(b) {
(function g(b) {
var b = b && (b.null = "FAIL");
})(a);
}
f();
})();
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"passes": 2,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2187_3() {
let src = r###"var b = 1;
console.log(
(function (a) {
return a && ++b;
})(b--)
);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2203_1() {
let src = r###"a = "FAIL";
console.log(
{
a: "PASS",
b: function () {
return (function (c) {
return c.a;
})((String, Object, this));
},
}.b()
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2914_2() {
let src = r###"function read(input) {
var i = 0;
var e = 0;
var t = 0;
while (e < 32) {
var n = input[i++];
t = (127 & n) << e;
if (0 === (128 & n)) return t;
e += 7;
}
}
console.log(read([129]));"###;
let config = r###"{
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2319_1() {
let src = r###"console.log(
(function (a) {
return a;
})(
!(function () {
return this;
})()
)
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_cascade_forin() {
let src = r###"var a;
function f(b) {
return [b, b, b];
}
for (var c in ((a = console), f(a))) console.log(c);"###;
let config = r###"{
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_inner_lvalues() {
let src = r###"var a,
b = 10;
var a = (--b || a || 3).toString(),
c = --b + -a;
console.log(null, a, b);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2298() {
let src = r###"!(function () {
function f() {
var a = undefined;
var undefined = a++;
try {
!(function g(b) {
b[1] = "foo";
})();
console.log("FAIL");
} catch (e) {
console.log("PASS");
}
}
f();
})();"###;
let config = r###"{
"collapse_vars": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_chained_3() {
let src = r###"console.log(
(function (a, b) {
var c = a,
c = b;
b++;
return c;
})(1, 2)
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_collapse_vars_self_reference() {
let src = r###"function f1() {
var self = {
inner: function () {
return self;
},
};
console.log(self)
}
function f2() {
var self = { inner: self };
console.log(self)
}
f1()
f2()"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"loops": true,
"properties": true,
"sequences": true,
"side_effects": true,
"unused": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_chained_2() {
let src = r###"var a;
var a = 2;
a = 3 / a;
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_cond_branch_1() {
let src = r###"function f1(b, c) {
var log = console.log;
var a = ++c;
if (b) b++;
log(a, b);
}
function f2(b, c) {
var log = console.log;
var a = ++c;
b && b++;
log(a, b);
}
function f3(b, c) {
var log = console.log;
var a = ++c;
b ? b++ : b--;
log(a, b);
}
f1(1, 2);
f2(3, 4);
f3(5, 6);"###;
let config = r###"{
"collapse_vars": true,
"sequences": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_var_side_effects_2() {
let src = r###"var print = console.log.bind(console);
function foo(x) {
var twice = x.y * 2;
print("Foo:", twice);
}
foo({ y: 10 });"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_3032() {
let src = r###"console.log(
{
f: function () {
this.a = 42;
return [this.a, !1];
},
}.f()[0]
);"###;
let config = r###"{
"collapse_vars": true,
"pure_getters": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_var_side_effects_3() {
let src = r###"var print = console.log.bind(console);
function foo(x) {
var twice = x.y * 2;
print("Foo:", twice);
}
foo({ y: 10 });"###;
let config = r###"{
"collapse_vars": true,
"pure_getters": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_collapse_vars_throw() {
let src = r###"var f1 = function (x, y) {
var a,
b,
r = x + y,
q = r * r,
z = q - r;
(a = z), (b = 7);
throw a + b;
};
try {
f1(1, 2);
} catch (e) {
console.log(e);
}"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"loops": true,
"properties": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2203_4() {
let src = r###"a = "FAIL";
console.log(
{
a: "PASS",
b: function () {
return ((c) => c.a)((String, Object, (() => this)()));
},
}.b()
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2203_3() {
let src = r###"a = "FAIL";
console.log(
{
a: "PASS",
b: function () {
return (function (c) {
return c.a;
})((String, Object, (() => this)()));
},
}.b()
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2187_1() {
let src = r###"var a = 1;
!(function (foo) {
foo();
var a = 2;
console.log(a);
})(function () {
console.log(a);
});"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_var_defs() {
let src = r###"var f1 = function (x, y) {
var a,
b,
r = x + y,
q = r * r,
z = q - r,
a = z,
b = 7;
console.log(a + b);
};
f1("1", 0);"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"loops": true,
"properties": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2203_2() {
let src = r###"a = "PASS";
console.log(
{
a: "FAIL",
b: function () {
return (function (c) {
return c.a;
})(
(String,
Object,
(function () {
return this;
})())
);
},
}.b()
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_collapse_vars_seq() {
let src = r###"var f1 = function (x, y) {
var a,
b,
r = x + y,
q = r * r,
z = q - r;
(a = z), (b = 7);
return a + b;
};
console.log(f1(1, 2));"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"loops": true,
"properties": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2319_3() {
let src = r###""use strict";
console.log(
(function (a) {
return a;
})(
!(function () {
return this;
})()
)
);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_may_throw_2() {
let src = r###"function f(b) {
try {
var a = x();
++b;
return b(a);
} catch (e) {}
console.log(b);
}
f(0);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_issue_2453() {
let src = r###"function log(n) {
console.log(n);
}
const a = 42;
log(a);"###;
let config = r###"{
"collapse_vars": true,
"conditionals": true,
"inline": true,
"join_vars": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_cond_branch_2() {
let src = r###"function f1(b, c) {
var log = console.log;
var a = ++c;
if (b) b += a;
log(a, b);
}
function f2(b, c) {
var log = console.log;
var a = ++c;
b && (b += a);
log(a, b);
}
function f3(b, c) {
var log = console.log;
var a = ++c;
b ? (b += a) : b--;
log(a, b);
}
f1(1, 2);
f2(3, 4);
f3(5, 6);"###;
let config = r###"{
"collapse_vars": true,
"sequences": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_chained_1() {
let src = r###"var a = 2;
var a = 3 / a;
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_collapse_vars_reduce_vars_assign() {
let src = r###"!(function () {
var a = 1;
(a = [].length), console.log(a);
})();"###;
let config = r###"{
"collapse_vars": true,
"reduce_funcs": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_inline_inline_within_extends_2() {
let src = r###"class Baz extends foo(bar(Array)) {
constructor() {
super(...arguments);
}
}
function foo(foo_base) {
return class extends foo_base {
constructor() {
super(...arguments);
}
second() {
return this[1];
}
};
}
function bar(bar_base) {
return class extends bar_base {
constructor(...args) {
super(...args);
}
};
}
console.log(new Baz(1, "PASS", 3).second());"###;
let config = r###"{
"defaults": true,
"evaluate": true,
"inline": 3,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"collapse_vars": false,
"unused": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_evaluate_unsafe_float_key() {
let src = r###"console.log(
{ 2.72: 1 } + 1,
{ 2.72: 1 }[2.72] + 1,
{ 2.72: 1 }["2.72"] + 1,
{ 2.72: 1 }[3.14] + 1,
{ 2.72: 1 }[2.72][3.14] + 1,
{ 2.72: 1 }[2.72]["3.14"] + 1
);"###;
let config = r###"{
"evaluate": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_evaluate_unsafe_float_key_complex() {
let src = r###"console.log(
{ 2.72: { 3.14: 1 }, 3.14: 1 } + 1,
{ 2.72: { 3.14: 1 }, 3.14: 1 }[2.72] + 1,
{ 2.72: { 3.14: 1 }, 3.14: 1 }["2.72"] + 1,
{ 2.72: { 3.14: 1 }, 3.14: 1 }[3.14] + 1,
{ 2.72: { 3.14: 1 }, 3.14: 1 }[2.72][3.14] + 1,
{ 2.72: { 3.14: 1 }, 3.14: 1 }[2.72]["3.14"] + 1
);"###;
let config = r###"{
"evaluate": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_892_dont_mangle_arguments() {
let src = r###"(function () {
var arguments = arguments,
not_arguments = 9;
console.log(not_arguments, arguments);
})(5, 6, 7);"###;
let config = r###"{
"booleans": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"drop_debugger": true,
"evaluate": true,
"hoist_funs": true,
"hoist_vars": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"keep_fnames": false,
"loops": true,
"negate_iife": false,
"properties": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_t64() {
let src = r###"var obj = {};
obj.Base = class {
constructor() {
this.id = "PASS";
}
};
obj.Derived = class extends obj.Base {
constructor() {
super();
console.log(this.id);
}
};
new obj.Derived();"###;
let config = r###"{
"collapse_vars": true,
"join_vars": true,
"properties": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_computed_property() {
let src = r###"console.log({ a: "bar", [console.log("foo")]: 42 }.a);"###;
let config = r###"{
"properties": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_sub_properties() {
let src = r###"const a = {};
a[0] = 0;
a["0"] = 1;
a[3.14] = 2;
a["3" + ".14"] = 3;
a["i" + "f"] = 4;
a["foo" + " bar"] = 5;
a[0 / 0] = 6;
a[null] = 7;
a[undefined] = 8;
console.log(a)"###;
let config = r###"{
"evaluate": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_dont_mangle_computed_property_2() {
let src = r###"const prop = Symbol("foo");
const obj = {
[prop]: "bar",
baz: 1,
qux: 2,
[3 + 4]: "seven",
0: "zero",
1: "one",
null: "Null",
undefined: "Undefined",
Infinity: "infinity",
NaN: "nan",
void: "Void",
};
console.log(
obj[prop],
obj["baz"],
obj.qux,
obj[7],
obj[0],
obj[1 + 0],
obj[null],
obj[undefined],
obj[1 / 0],
obj[NaN],
obj.void
);
console.log(obj.null, obj.undefined, obj.Infinity, obj.NaN);"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_prop_side_effects_2() {
let src = r###"var C = 1;
console.log(C);
var obj = {
"": function () {
return C + C;
},
};
console.log(obj[""]());"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 2,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_negative() {
let src = r###"var o = {};
o[0] = 0;
o[-0] = 1;
o[-1] = 2;
console.log(o[0], o[-0], o[-1]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2208_4() {
let src = r###"function foo() {}
console.log(
{
a: foo(),
p: function () {
return 42;
},
}.p()
);"###;
let config = r###"{
"inline": true,
"properties": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_869_1() {
let src = r###"var o = { p: "FAIL" };
Object.defineProperty(o, "p", {
get: function () {
return "PASS";
},
});
console.log(o.p);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_undefined_2() {
let src = r###"var o = {};
o[undefined] = 1;
console.log(o[undefined]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2208_5() {
let src = r###"console.log(
{
p: "FAIL",
p: function () {
return 42;
},
}.p()
);"###;
let config = r###"{
"inline": true,
"properties": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2513() {
let src = r###"!(function (Infinity, NaN, undefined) {
console.log("a"[1 / 0], "b"["Infinity"]);
console.log("c"[0 / 0], "d"["NaN"]);
console.log("e"[void 0], "f"["undefined"]);
})(0, 0, 0);"###;
let config = r###"{
"evaluate": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_return_1() {
let src = r###"console.log(
(function () {
var o = { p: 3 };
return (o.q = "foo");
})()
);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2816_ecma6() {
let src = r###""use strict";
var o = { a: 1 };
o.b = 2;
o.a = 3;
o.c = 4;
console.log(o.a, o.b, o.c);"###;
let config = r###"{
"ecma": "6",
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_1() {
let src = r###"console.log(
(function () {
var x = { a: 1, c: (console.log("c"), "C") };
x.b = 2;
(x[3] = function () {
console.log(x);
}),
(x["a"] = /foo/),
(x.bar = x);
return x;
})()
);"###;
let config = r###"{
"evaluate": true,
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_dont_mangle_computed_property_1() {
let src = r###""AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC";
const prop = Symbol("foo");
const obj = {
[prop]: "bar",
baz: 1,
qux: 2,
[3 + 4]: "seven",
0: "zero",
1: "one",
null: "Null",
undefined: "Undefined",
Infinity: "infinity",
NaN: "nan",
void: "Void",
};
console.log(
obj[prop],
obj["baz"],
obj.qux,
obj[7],
obj[0],
obj[1 + 0],
obj[null],
obj[undefined],
obj[1 / 0],
obj[NaN],
obj.void
);
console.log(obj.null, obj.undefined, obj.Infinity, obj.NaN);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_if() {
let src = r###"console.log(
(function () {
var o = {};
if ((o.a = "PASS")) return o.a;
})()
);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_nan_2() {
let src = r###"var o = {};
o[NaN] = 1;
o[0 / 0] = 2;
console.log(o[NaN], o[NaN]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_prop_side_effects_1() {
let src = r###"var C = 1;
console.log(C);
var obj = {
bar: function () {
return C + C;
},
};
console.log(obj.bar());"###;
let config = r###"{
"evaluate": true,
"inline": true,
"properties": true,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_null_1() {
let src = r###"var o = {};
o[null] = 1;
console.log(o[null]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2208_7() {
let src = r###"console.log(
{
p() {
return 42;
},
}.p()
);"###;
let config = r###"{
"ecma": 2015,
"inline": true,
"properties": true,
"side_effects": true,
"unsafe_arrows": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_869_2() {
let src = r###"var o = { p: "FAIL" };
Object.defineProperties(o, {
p: {
get: function () {
return "PASS";
},
},
});
console.log(o.p);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_issue_2208_9() {
let src = r###"a = 42;
console.log(
{
p: () =>
(function () {
return this.a;
})(),
}.p()
);"###;
let config = r###"{
"inline": true,
"properties": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_undefined_1() {
let src = r###"var o = {};
o[undefined] = 1;
console.log(o[undefined]);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_forin() {
let src = r###"console.log(
(function () {
var o = {};
for (var a in ((o.a = "PASS"), o)) return o[a];
})()
);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_void_0() {
let src = r###"var o = {};
o[void 0] = 1;
console.log(o[void 0]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_return_2() {
let src = r###"console.log(
(function () {
var o = { p: 3 };
return (o.q = /foo/), (o.r = "bar");
})()
);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_regex() {
let src = r###"var o = {};
o[/rx/] = 1;
console.log(o[/rx/]);"###;
let config = r###"{
"evaluate": true,
"join_vars": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_2() {
let src = r###"var o = { foo: 1 };
o.bar = 2;
o.baz = 3;
console.log(o.foo, o.bar + o.bar, o.foo * o.bar * o.baz);"###;
let config = r###"{
"evaluate": true,
"hoist_props": true,
"join_vars": true,
"passes": 3,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_properties_join_object_assignments_return_3() {
let src = r###"console.log(
(function () {
var o = { p: 3 };
return (o.q = "foo"), (o.p += ""), console.log(o.q), o.p;
})()
);"###;
let config = r###"{
"join_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1321_issue_1321_no_debug() {
let src = r###"var x = {};
x.foo = 1;
x["a"] = 2 * x.foo;
console.log(x.foo, x["a"]);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1321_issue_1321_with_quoted() {
let src = r###"var x = {};
x.foo = 1;
x["a"] = 2 * x.foo;
console.log(x.foo, x["a"]);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1321_issue_1321_debug() {
let src = r###"var x = {};
x.foo = 1;
x["_$foo$_"] = 2 * x.foo;
console.log(x.foo, x["_$foo$_"]);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_976_eval_collapse_vars() {
let src = r###"function f1() {
var e = 7;
var s = "abcdef";
var i = 2;
var eval = console.log.bind(console);
var x = s.charAt(i++);
var y = s.charAt(i++);
var z = s.charAt(i++);
eval(x, y, z, e);
}
function p1() {
var a = foo(),
b = bar(),
eval = baz();
return a + b + eval;
}
function p2() {
var a = foo(),
b = bar(),
eval = baz;
return a + b + eval();
}
(function f2(eval) {
var a = 2;
console.log(a - 5);
eval("console.log(a);");
})(eval);"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"comparisons": true,
"conditionals": true,
"dead_code": true,
"evaluate": true,
"hoist_funs": true,
"if_return": true,
"join_vars": true,
"keep_fargs": true,
"loops": true,
"properties": true,
"sequences": false,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_array_constructor_unsafe() {
let src = r###"const foo = 'string'
console.log(new Array());
console.log(new Array(0));
console.log(new Array(1));
console.log(new Array(11));
console.log(Array(11));
console.log(new Array(12));
console.log(Array(12));
console.log(new Array(foo));
console.log(Array(foo));
console.log(new Array("foo"));
console.log(Array("foo"));"###;
let config = r###"{
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_sequences_forin() {
let src = r###"var o = [];
o.push("PASS");
for (var a in o) console.log(o[a]);"###;
let config = r###"{
"sequences": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_sequences_for_init_var() {
let src = r###"var a = "PASS";
(function () {
var b = 42;
for (var c = 5; c > 0; ) c--;
a = "FAIL";
var a;
})();
console.log(a);"###;
let config = r###"{
"join_vars": true,
"unused": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_sequences_func_def_1() {
let src = r###"function f() {
return (f = 0), !!f;
}
console.log(f());"###;
let config = r###"{
"collapse_vars": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1639_issue_1639_1() {
let src = r###"var a = 100,
b = 10;
var L1 = 5;
while (--L1 > 0) {
if ((--b, false)) {
if (b) {
var ignore = 0;
}
}
}
console.log(a, b);"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"conditionals": true,
"evaluate": true,
"join_vars": true,
"loops": true,
"sequences": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1639_issue_1639_2() {
let src = r###"var a = 100,
b = 10;
function f19() {
if ((++a, false)) if (a) if (++a);
}
f19();
console.log(a, b);"###;
let config = r###"{
"booleans": true,
"collapse_vars": true,
"conditionals": true,
"evaluate": true,
"join_vars": true,
"sequences": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arrays_for_loop() {
let src = r###"function f0() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0; i < a.length; i++) b += a[i];
return b;
}
function f1() {
var a = [1, 2, 3];
var b = 0;
for (var i = 0, len = a.length; i < len; i++) b += a[i];
return b;
}
function f2() {
var a = [1, 2, 3];
for (var i = 0; i < a.length; i++) a[i]++;
return a[2];
}
console.log(f0(), f1(), f2());"###;
let config = r###"{
"evaluate": true,
"reduce_funcs": true,
"reduce_vars": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_keep_quoted_strict_keep_quoted_strict() {
let src = r###"var propa = 1;
var a = {
propa,
get propb() {
return 2;
},
propc: 3,
get propd() {
return 4;
},
};
var b = {
propa: 5,
get propb() {
return 6;
},
propc: 7,
get propd() {
return 8;
},
};
var c = {};
Object.defineProperty(c, "propa", { value: 9 });
Object.defineProperty(c, "propc", { value: 10 });
console.log(a.propa, a.propb, a.propc, a["propc"], a.propd, a["propd"]);
console.log(b["propa"], b["propb"], b.propc, b["propc"], b.propd, b["propd"]);
console.log(c.propa, c["propc"]);"###;
let config = r###"{
"evaluate": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_switch_issue_1663() {
let src = r###"var a = 100,
b = 10;
function f() {
switch (1) {
case 1:
b = a++;
return ++b;
default:
var b;
}
}
f();
console.log(a, b);"###;
let config = r###"{
"dead_code": true,
"evaluate": true,
"side_effects": true,
"switches": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2107() {
let src = r###"var c = 0;
!(function () {
c++;
})(
c++ +
new (function () {
this.a = 0;
var a = (c = c + 1) + (c = 1 + c);
return c++ + a;
})()
);
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"passes": 3,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2630_5() {
let src = r###"var c = 1;
!(function () {
do {
c *= 10;
} while (f());
function f() {
return (function () {
return (c = 2 + c) < 100;
})((c = c + 3));
}
})();
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2630_2() {
let src = r###"var c = 0;
!(function () {
while (f()) {}
function f() {
var not_used = (function () {
c = 1 + c;
})((c = c + 1));
}
})();
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"passes": 2,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2101() {
let src = r###"a = {};
console.log(
(function () {
return (function () {
return this.a;
})();
})() ===
(function () {
return a;
})()
);"###;
let config = r###"{
"inline": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2630_3() {
let src = r###"var x = 2,
a = 1;
(function () {
function f1(a) {
f2();
--x >= 0 && f1({});
}
f1(a++);
function f2() {
a++;
}
})();
console.log(a);"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2630_4() {
let src = r###"var x = 3,
a = 1,
b = 2;
(function () {
(function f1() {
while (--x >= 0 && f2());
})();
function f2() {
a++ + (b += a);
}
})();
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_1841_2() {
let src = r###"var b = 10;
!(function (arg) {
for (var key in "hi") var n = arg.baz, n = [(b = 42)];
})(--b);
console.log(b);"###;
let config = r###"{
"keep_fargs": false,
"pure_getters": false,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_t131a() {
let src = r###"(function () {
function thing() {
return { a: 1 };
}
function one() {
return thing();
}
function two() {
var x = thing();
x.a = 2;
x.b = 3;
return x;
}
console.log(JSON.stringify(one()), JSON.stringify(two()));
})();"###;
let config = r###"{
"inline": 1,
"join_vars": true,
"reduce_vars": true,
"side_effects": true,
"passes": 2,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_apply_1() {
let src = r###"(function (a, b) {
console.log(a, b);
}.apply("foo", ["bar"]));
(function (a, b) {
console.log(this, a, b);
}.apply("foo", ["bar"]));
(function (a, b) {
console.log(a, b);
}.apply("foo", ["bar"], "baz"));"###;
let config = r###"{
"inline": true,
"passes": 2,
"reduce_vars": true,
"side_effects": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2898() {
let src = r###"var c = 0;
(function () {
while (f());
function f() {
var b = ((c = 1 + c), void (c = 1 + c));
b && b[0];
}
})();
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"reduce_vars": true,
"sequences": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_inline_1() {
let src = r###"(function () {
console.log(1);
})();
(function (a) {
console.log(a);
})(2);
(function (b) {
var c = b;
console.log(c);
})(3);"###;
let config = r###"{
"inline": 1,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_3125() {
let src = r###"console.log(
function () {
return "PASS";
}.call()
);"###;
let config = r###"{
"inline": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_3016_2() {
let src = r###"var b = 1;
do {
(function (a) {
return a[b];
try {
a = 2;
} catch (a) {
var a;
}
})(3);
} while (0);
console.log(b);"###;
let config = r###"{
"dead_code": true,
"inline": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2531_1() {
let src = r###"function outer() {
function inner(value) {
function closure() {
return value;
}
return function () {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());"###;
let config = r###"{
"evaluate": true,
"inline": true,
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_use_before_init_in_loop() {
let src = r###"var a = "PASS";
for (var b = 2; --b >= 0; )
(function () {
var c = (function () {
return 1;
})(c && (a = "FAIL"));
})();
console.log(a);"###;
let config = r###"{
"inline": true,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_apply_expansion_2() {
let src = r###"var values = [2, 3];
console.log.apply(console, [1, ...values, 4]);"###;
let config = r###"{
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2663_2() {
let src = r###"(function () {
var i;
function fn(j) {
return (function () {
console.log(j);
})();
}
for (i in { a: 1, b: 2, c: 3 }) fn(i);
})();"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_call_3() {
let src = r###"console.log(
function () {
return arguments[0] + eval("arguments")[1];
}.call(0, 1, 2)
);"###;
let config = r###"{
"side_effects": true,
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_call_expansion_1() {
let src = r###"(function (...a) {
console.log(...a);
}.call(console, 1, ...[2, 3], 4));"###;
let config = r###"{
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2630_1() {
let src = r###"var c = 0;
(function () {
while (f());
function f() {
var a = (function () {
var b = c++,
d = (c = 1 + c);
})();
}
})();
console.log(c);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"sequences": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_203() {
let src = r###"var m = {};
var fn = Function("require", "module", "exports", "module.exports = 42;");
fn(null, m, m.exports);
console.log(m.exports);"###;
let config = r###"{
"keep_fargs": false,
"side_effects": true,
"unsafe_Function": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2842() {
let src = r###"(function () {
function inlinedFunction(data) {
return data[data[0]];
}
function testMinify() {
if (true) {
const data = inlinedFunction([1, 2, 3]);
console.log(data);
}
}
return testMinify();
})();"###;
let config = r###"{
"side_effects": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_1841_1() {
let src = r###"var b = 10;
!(function (arg) {
for (var key in "hi") var n = arg.baz, n = [(b = 42)];
})(--b);
console.log(b);"###;
let config = r###"{
"keep_fargs": false,
"pure_getters": "strict",
"reduce_funcs": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2476() {
let src = r###"function foo(x, y, z) {
return x < y ? x * y + z : x * z - y;
}
for (var sum = 0, i = 0; i < 10; i++) sum += foo(i, i + 1, 3 * i);
console.log(sum);"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_t131b() {
let src = r###"(function () {
function thing() {
return { a: 1 };
}
function one() {
return thing();
}
function two() {
var x = thing();
x.a = 2;
x.b = 3;
return x;
}
console.log(JSON.stringify(one()), JSON.stringify(two()));
})();"###;
let config = r###"{
"defaults": true,
"passes": 2
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_inline_2() {
let src = r###"(function () {
console.log(1);
})();
(function (a) {
console.log(a);
})(2);
(function (b) {
var c = b;
console.log(c);
})(3);"###;
let config = r###"{
"inline": 2,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2531_3() {
let src = r###"function outer() {
function inner(value) {
function closure() {
return value;
}
return function () {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_inline_3() {
let src = r###"(function () {
console.log(1);
})();
(function (a) {
console.log(a);
})(2);
(function (b) {
var c = b;
console.log(c);
})(3);"###;
let config = r###"{
"inline": 3,
"side_effects": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2657() {
let src = r###""use strict";
console.log(
(function f() {
return h;
function g(b) {
return b || b();
}
function h(a) {
g(a);
return a;
}
})()(42)
);"###;
let config = r###"{
"inline": true,
"reduce_vars": true,
"sequences": true,
"passes": 2,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_apply_expansion_1() {
let src = r###"console.log.apply(console, [1, ...[2, 3], 4]);"###;
let config = r###"{
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_3016_1() {
let src = r###"var b = 1;
do {
(function (a) {
return a[b];
var a;
})(3);
} while (0);
console.log(b);"###;
let config = r###"{
"inline": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2531_2() {
let src = r###"function outer() {
function inner(value) {
function closure() {
return value;
}
return function () {
return closure();
};
}
return inner("Hello");
}
console.log("Greeting:", outer()());"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 3,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_call_expansion_2() {
let src = r###"var values = [2, 3];
(function (...a) {
console.log(...a);
}.call(console, 1, ...values, 4));"###;
let config = r###"{
"unsafe": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_issue_2783() {
let src = r###"(function () {
return g;
function f(a) {
var b = a.b;
if (b) return b;
return a;
}
function g(o, i) {
while (i--) {
console.log(f(o));
}
}
})()({ b: "PASS" }, 1);"###;
let config = r###"{
"collapse_vars": true,
"conditionals": true,
"if_return": true,
"inline": true,
"reduce_vars": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_functions_unsafe_call_1() {
let src = r###"(function (a, b) {
console.log(a, b);
}.call("foo", "bar"));
(function (a, b) {
console.log(this, a, b);
}.call("foo", "bar"));"###;
let config = r###"{
"inline": true,
"passes": 2,
"reduce_vars": true,
"side_effects": true,
"unsafe": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_different_variable_in_multiple_for_of() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp of test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let t of dd) {
console.log(t);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": true,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_of() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp of test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let tmp of dd) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": true,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_of_sequences_let() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp of test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let tmp of dd) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": true,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"sequences": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_in_sequences_const() {
let src = r###"var test = ["a", "b", "c"];
for (const tmp in test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (const tmp in test) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": false,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"sequences": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_more_variable_in_multiple_for() {
let src = r###"for (let a = 9, i = 0; i < 20; i += a) {
let b = a++ + i;
console.log(a, b, i);
for (let k = b, m = b * b, i = 0; i < 10; i++) {
console.log(a, b, m, k, i);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": false,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_different_variable_in_multiple_for_in() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp in test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let t in test) {
console.log(t);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": false,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_in() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp in test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let tmp in test) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": false,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_in_sequences_let() {
let src = r###"var test = ["a", "b", "c"];
for (let tmp in test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (let tmp in test) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": false,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"sequences": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_1466_same_variable_in_multiple_for_of_sequences_const() {
let src = r###"var test = ["a", "b", "c"];
for (const tmp of test) {
console.log(tmp);
let dd;
dd = ["e", "f", "g"];
for (const tmp of dd) {
console.log(tmp);
}
}"###;
let config = r###"{
"hoist_funs": true,
"dead_code": true,
"conditionals": true,
"comparisons": true,
"evaluate": true,
"booleans": true,
"loops": true,
"unused": true,
"keep_fargs": true,
"if_return": true,
"join_vars": true,
"sequences": true,
"side_effects": true,
"collapse_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_747_dont_reuse_prop() {
let src = r###""aaaaaaaaaabbbbb";
var obj = {};
obj.a = 123;
obj.asd = 256;
console.log(obj.a);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_747_unmangleable_props_should_always_be_reserved() {
let src = r###""aaaaaaaaaabbbbb";
var obj = {};
obj.asd = 256;
obj.a = 123;
console.log(obj.a);"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_7() {
let src = r###"let a = 9,
b = 0;
for (const a = 1; a < 3; ++b) break;
console.log(a, b);"###;
let config = r###"{
"dead_code": true,
"loops": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_8() {
let src = r###"var a = 9,
b = 0;
for (const a = 1; a < 3; ++b) break;
console.log(a, b);"###;
let config = r###"{
"dead_code": true,
"loops": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_6() {
let src = r###"const a = 9,
b = 0;
for (const a = 1; a < 3; ++b) break;
console.log(a, b);"###;
let config = r###"{
"dead_code": true,
"loops": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_3() {
let src = r###"L1: for (var x = 0; x < 3; x++) {
L2: for (var y = 0; y < 2; y++) {
break L1;
}
}
console.log(x, y);"###;
let config = r###"{
"dead_code": true,
"loops": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_4() {
let src = r###"L1: for (var x = 0; x < 3; x++) {
L2: for (var y = 0; y < 2; y++) {
break L2;
}
}
console.log(x, y);"###;
let config = r###"{
"dead_code": true,
"loops": true,
"passes": 2
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_loops_issue_2740_5() {
let src = r###"L1: for (var x = 0; x < 3; x++) {
break L1;
L2: for (var y = 0; y < 2; y++) {
break L2;
}
}
console.log(x, y);"###;
let config = r###"{
"dead_code": true,
"loops": true,
"passes": 2
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_rename_function_iife_catch() {
let src = r###"function f(n) {
!(function () {
try {
throw 0;
} catch (n) {
var a = 1;
console.log(n, a);
}
})();
}
f();"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_rename_mangle_catch_var() {
let src = r###"var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);"###;
let config = r###"{
"ie8": false,
"toplevel": false
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_negate_iife_issue_1254_negate_iife_true() {
let src = r###"(function () {
return function () {
console.log("test");
};
})()();"###;
let config = r###"{
"negate_iife": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_try_catch_catch_destructuring_with_sequence() {
let src = r###"try {
throw {};
} catch ({ xCover = (0, function () { }) }) {
console.log(typeof xCover)
}"###;
let config = r###"{}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_281_pure_annotation_1() {
let src = r###"(function () {
console.log("hello");
})();"###;
let config = r###"{
"inline": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_281_keep_fargs() {
let src = r###"var a = 1;
!(function (a_1) {
a++;
})(a++ + (a && a.var));
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"keep_fargs": true,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_281_drop_fargs() {
let src = r###"var a = 1;
!(function (a_1) {
a++;
})(a++ + (a && a.var));
console.log(a);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"keep_fargs": false,
"side_effects": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_issue_281_pure_annotation_2() {
let src = r###"(function (n) {
console.log("hello", n);
})(42);"###;
let config = r###"{
"collapse_vars": true,
"inline": true,
"side_effects": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_duplicate_parameter_with_arguments() {
let src = r###"(function (a, a) {
console.log((a = "foo"), arguments[0]);
})("baz", "Bar");"###;
let config = r###"{
"arguments": true,
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_destructuring_1() {
let src = r###"(function (a, { d: d }) {
console.log((a = "foo"), arguments[0]);
})("baz", { d: "Bar" });"###;
let config = r###"{
"arguments": true,
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_destructuring_2() {
let src = r###"(function ({ d: d }, a) {
console.log((a = "foo"), arguments[0].d);
})({ d: "Bar" }, "baz");"###;
let config = r###"{
"arguments": true,
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_modified_strict() {
let src = r###""use strict";
(function (a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);"###;
let config = r###"{
"arguments": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_replace_index() {
let src = r###"var arguments = [];
console.log(arguments[0]);
(function () {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function (a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function (arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function () {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);"###;
let config = r###"{
"arguments": true,
"evaluate": true,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_modified() {
let src = r###"(function (a, b) {
var c = arguments[0];
var d = arguments[1];
var a = "foo";
b++;
arguments[0] = "moo";
arguments[1] *= 2;
console.log(a, b, c, d, arguments[0], arguments[1]);
})("bar", 42);"###;
let config = r###"{
"arguments": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_replace_index_strict() {
let src = r###""use strict";
(function () {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function (a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);"###;
let config = r###"{
"arguments": true,
"evaluate": true,
"properties": true,
"reduce_vars": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_issue_687() {
let src = r###"function shouldBePure() {
return arguments.length;
}
console.log(shouldBePure())"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_arguments_replace_index_keep_fargs() {
let src = r###"var arguments = [];
console.log(arguments[0]);
(function () {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function (a, b) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function (arguments) {
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);
(function () {
var arguments;
console.log(arguments[1], arguments["1"], arguments["foo"]);
})("bar", 42);"###;
let config = r###"{
"arguments": true,
"evaluate": true,
"keep_fargs": false,
"properties": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_typeof_issue_2728_3() {
let src = r###"(function () {
function arguments() {}
console.log(typeof arguments);
})();"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true,
"typeofs": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_typeof_issue_2728_4() {
let src = r###"function arguments() {}
console.log(typeof arguments);"###;
let config = r###"{
"evaluate": true,
"reduce_vars": true,
"toplevel": true,
"typeofs": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_typeof_typeof_defun_1() {
let src = r###"function f() {
console.log("YES");
}
function g() {
h = 42;
console.log("NOPE");
}
function h() {
console.log("YUP");
}
g = 42;
"function" == typeof f && f();
"function" == typeof g && g();
"function" == typeof h && h();"###;
let config = r###"{
"evaluate": true,
"inline": true,
"passes": 2,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"typeofs": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_pure_funcs_issue_3065_4() {
let src = r###"var debug = function (msg) {
console.log(msg);
};
debug(
(function () {
console.log("PASS");
return "FAIL";
})()
);"###;
let config = r###"{
"pure_funcs": ["debug"],
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
#[ignore]
fn terser_pure_funcs_issue_3065_3() {
let src = r###"function debug(msg) {
console.log(msg);
}
debug(
(function () {
console.log("PASS");
return "FAIL";
})()
);"###;
let config = r###"{
"pure_funcs": ["debug"],
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn issues_vercel_ms_1() {
let src = r###"const s = 1000;
const m = s * 60;
const h = m * 60;
const d = h * 24;
const w = d * 7;
const y = d * 365.25;
function ms(value, options) {
try {
if (typeof value === "string" && value.length > 0) {
return parse(value);
} else if (typeof value === "number" && isFinite(value)) {
return options?.long ? fmtLong(value) : fmtShort(value);
}
throw new Error("Value is not a string or number.");
} catch (error) {
const message = isError(error) ? `${error.message}. value=${JSON.stringify(value)}` : "An unknown error has occured.";
throw new Error(message);
}
}
function parse(str) {
str = String(str);
if (str.length > 100) {
throw new Error("Value exceeds the maximum length of 100 characters.");
}
const match = /^(-?(?:\d+)?\.?\d+) *(milliseconds?|msecs?|ms|seconds?|secs?|s|minutes?|mins?|m|hours?|hrs?|h|days?|d|weeks?|w|years?|yrs?|y)?$/i.exec(str);
if (!match) {
return NaN;
}
const n = parseFloat(match[1]);
const type = (match[2] || "ms").toLowerCase();
switch (type) {
case "years":
case "year":
case "yrs":
case "yr":
case "y":
return n * y;
case "weeks":
case "week":
case "w":
return n * w;
case "days":
case "day":
case "d":
return n * d;
case "hours":
case "hour":
case "hrs":
case "hr":
case "h":
return n * h;
case "minutes":
case "minute":
case "mins":
case "min":
case "m":
return n * m;
case "seconds":
case "second":
case "secs":
case "sec":
case "s":
return n * s;
case "milliseconds":
case "millisecond":
case "msecs":
case "msec":
case "ms":
return n;
default:
throw new Error(`The unit ${type} was matched, but no matching case exists.`);
}
}
function fmtShort(ms) {
const msAbs = Math.abs(ms);
if (msAbs >= d) {
return `${Math.round(ms / d)}d`;
}
if (msAbs >= h) {
return `${Math.round(ms / h)}h`;
}
if (msAbs >= m) {
return `${Math.round(ms / m)}m`;
}
if (msAbs >= s) {
return `${Math.round(ms / s)}s`;
}
return `${ms}ms`;
}
function fmtLong(ms) {
const msAbs = Math.abs(ms);
if (msAbs >= d) {
return plural(ms, msAbs, d, "day");
}
if (msAbs >= h) {
return plural(ms, msAbs, h, "hour");
}
if (msAbs >= m) {
return plural(ms, msAbs, m, "minute");
}
if (msAbs >= s) {
return plural(ms, msAbs, s, "second");
}
return `${ms} ms`;
}
function plural(ms, msAbs, n, name) {
const isPlural = msAbs >= n * 1.5;
return `${Math.round(ms / n)} ${name}${isPlural ? "s" : ""}`;
}
function isError(error) {
return typeof error === "object" && error !== null && "message" in error;
}
console.log(ms(123))
console.log(ms('123day'))
console.log(ms(12321341234217))
console.log(ms(12321341234217))
console.log(ms(12321341234217))
console.log(ms(12321341234217))
console.log(ms(12321341234217))
console.log(ms(12321341234217))
console.log(ms(12321341234217))"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn issues_2011_1() {
let src = r###"class ClassA {
constructor() {
console.log('Class A');
}
}
const cls = class ClassB {
static MyA = ClassA;
constructor() {
console.log('Claas B');
}
it() {
console.log('method it - start');
this.bb = new ClassB.MyA();
console.log('method it - end');
}
}
new cls().it();"###;
let config = r###"{
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn issues_2011_2() {
let src = r###"function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
return Constructor;
}
function _defineProperty(obj, key, value) {
if (key in obj) {
Object.defineProperty(obj, key, {
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var ClassA = function ClassA() {
"use strict";
_classCallCheck(this, ClassA);
console.log('Class A');
};
var cls = function () {
var ClassB = /*#__PURE__*/ function () {
"use strict";
function ClassB() {
_classCallCheck(this, ClassB);
console.log('Claas B');
}
_createClass(ClassB, [
{
key: "it",
value: function it() {
console.log('method it - start');
this.bb = new ClassB.MyA();
console.log('method it - end');
}
}
]);
return ClassB;
}();
_defineProperty(ClassB, "MyA", ClassA);
return ClassB;
}();
new cls().it();"###;
let config = r###"{
"defaults": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn murmur2_1() {
let src = r###"function murmur2(str) {
// 'm' and 'r' are mixing constants generated offline.
// They're not really 'magic', they just happen to work well.
// const m = 0x5bd1e995;
// const r = 24;
// Initialize the hash
var h = 0; // Mix 4 bytes at a time into the hash
var k,
i = 0,
len = str.length;
for (; len >= 4; ++i, len -= 4) {
k = str.charCodeAt(i) & 0xff | (str.charCodeAt(++i) & 0xff) << 8 | (str.charCodeAt(++i) & 0xff) << 16 | (str.charCodeAt(++i) & 0xff) << 24;
k =
/* Math.imul(k, m): */
(k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16);
k ^=
/* k >>> r: */
k >>> 24;
h =
/* Math.imul(k, m): */
(k & 0xffff) * 0x5bd1e995 + ((k >>> 16) * 0xe995 << 16) ^
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
} // Handle the last few bytes of the input array
switch (len) {
case 3:
h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
case 2:
h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
case 1:
h ^= str.charCodeAt(i) & 0xff;
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
} // Do a few final mixes of the hash to ensure the last few
// bytes are well-incorporated.
h ^= h >>> 13;
h =
/* Math.imul(h, m): */
(h & 0xffff) * 0x5bd1e995 + ((h >>> 16) * 0xe995 << 16);
return ((h ^ h >>> 15) >>> 0).toString(36);
}
console.log(murmur2("123421334"))
console.log(murmur2("123asd ;nv"))
console.log(murmur2("1va1ns`klj"))"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn murmur2_reduced() {
let src = r###"function murmur2(str) {
var h = 0;
var k, i = 0, len = str.length;
for (; len >= 4; ++i, len -= 4) {
k = 255 & str.charCodeAt(i) | (255 & str.charCodeAt(++i)) << 8 | (255 & str.charCodeAt(++i)) << 16 | (255 & str.charCodeAt(++i)) << 24;
k = (65535 & k) * 1540483477 + ((k >>> 16) * 59797 << 16);
k ^= k >>> 24;
h = (65535 & k) * 1540483477 + ((k >>> 16) * 59797 << 16) ^ (65535 & h) * 1540483477 + ((h >>> 16) * 59797 << 16);
}
switch (len) {
case 3:
h ^= (255 & str.charCodeAt(i + 2)) << 16;
case 2:
h ^= (255 & str.charCodeAt(i + 1)) << 8;
case 1:
h ^= 255 & str.charCodeAt(i);
h = (65535 & h) * 1540483477 + ((h >>> 16) * 59797 << 16);
}
h ^= h >>> 13;
h = (65535 & h) * 1540483477 + ((h >>> 16) * 59797 << 16);
return ((h ^ h >>> 15) >>> 0).toString(36);
}
console.log(murmur2("123421334"));
console.log(murmur2("123asd ;nv"));
console.log(murmur2("1va1ns`klj"));"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn plotly_1() {
let src = r###"
function log2(v) {
var r, shift;
r = (v > 0xFFFF) << 4; v >>>= r;
shift = (v > 0xFF ) << 3; v >>>= shift; r |= shift;
shift = (v > 0xF ) << 2; v >>>= shift; r |= shift;
shift = (v > 0x3 ) << 1; v >>>= shift; r |= shift;
return r | (v >> 1);
}
console.log(log2(65536))
console.log(log2(2))
console.log(log2(4))
console.log(log2(8))
"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn internal_1() {
let src = r###"
function H (x) {
return function (y, z) {
return x._ + y + z
}
}
function P () {
var a = 0
a = {
_: 1
}
a.calc = H(a)
return a
}
console.log(P().calc(1, 1))
"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn direct_eval_1() {
let src = r###"
const obj = {
1: function () {
const foo = 1;
return {
test: function (s) {
return eval(s)
}
}
},
2: function foo(mod1) {
console.log(mod1.test('foo'))
}
};
obj[2](obj[1]());
"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn indirect_eval_1() {
let src = r###"
const obj = {
1: function () {
const foo = 1;
return {
test: function (s) {
const e = eval;
return e(s)
}
}
},
2: function foo(mod1) {
let success = false;
try {
mod1.test('foo')
} catch (e) {
success = true;
console.log('PASS');
}
if (!success) {
throw new Error('indirect eval should not be direct eval');
}
}
};
obj[2](obj[1]());
"###;
let config = r###"{
"defaults": true,
"toplevel": true
}"###;
run_exec_test(src, config, false);
}
#[test]
fn try_catch_1() {
let src = r###"
var a = "FAIL";
try {
throw 1;
} catch (args) {
a = "PASS";
}
console.log(a);
"###;
run_default_exec_test(src);
}
#[test]
fn try_catch_2() {
let src = r###"
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
"###;
run_default_exec_test(src);
}
#[test]
fn try_catch_3() {
let src = r###"
var a = "FAIL";
try {
throw 1;
} catch (args) {
var a = "PASS";
}
console.log(a);
"###;
run_default_exec_test(src);
}
#[test]
fn try_catch_4() {
let src = r###"
"aaaaaaaa";
var a = 1,
b = "FAIL";
try {
throw 1;
} catch (c) {
try {
throw 0;
} catch (a) {
if (c) b = "PASS";
}
}
console.log(b);
"###;
run_default_exec_test(src);
}
#[test]
fn try_catch_5() {
let src = r###"
var a = "PASS";
try {
throw "FAIL1";
} catch (a) {
var a = "FAIL2";
}
console.log(a);
"###;
run_default_exec_test(src);
}
#[test]
fn issue_4444_1() {
let src = r###"
const test = () => {
let a = 0;
let b = 0;
let c = [1, 2, 3, 4, 5].map((i) => {
a += i;
b += i;
return i;
});
return [a, b, c];
};
const [a, b, c] = test();
console.log("test", a, b, c);
"###;
let config = r###"
{
"arguments": false,
"arrows": false,
"booleans": true,
"booleans_as_integers": false,
"collapse_vars": true,
"comparisons": true,
"computed_props": false,
"conditionals": false,
"dead_code": false,
"directives": false,
"drop_console": false,
"drop_debugger": true,
"evaluate": false,
"expression": false,
"hoist_funs": false,
"hoist_props": false,
"hoist_vars": false,
"if_return": true,
"join_vars": false,
"keep_classnames": false,
"keep_fargs": true,
"keep_fnames": false,
"keep_infinity": false,
"loops": true,
"negate_iife": false,
"properties": true,
"reduce_funcs": false,
"reduce_vars": false,
"side_effects": true,
"switches": false,
"typeofs": false,
"unsafe": false,
"unsafe_arrows": false,
"unsafe_comps": false,
"unsafe_Function": false,
"unsafe_math": false,
"unsafe_symbols": false,
"unsafe_methods": false,
"unsafe_proto": false,
"unsafe_regexp": false,
"unsafe_undefined": false,
"unused": true
}
"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_insane_1() {
let src = r###"
function f() {
a--;
try {
a++;
x();
} catch (a) {
if (a) var a;
var a = 10;
}
console.log(a)
}
f();
"###;
let config = r###"
{
"conditionals": true,
"negate_iife": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}
"###;
run_exec_test(src, config, false);
}
#[test]
fn terser_insane_2() {
let src = r###"
function f() {
console.log(a)
a--;
console.log(a)
try {
console.log(a)
a++;
console.log(a)
x();
} catch (a) {
if (a) var a;
var a = 10;
}
console.log(a)
}
f();
"###;
let config = r###"
{
"conditionals": true,
"negate_iife": true,
"passes": 2,
"reduce_funcs": true,
"reduce_vars": true,
"side_effects": true,
"toplevel": true,
"unused": true
}
"###;
run_exec_test(src, config, false);
}
#[test]
fn issue_4788_1() {
let src = r###"
let id = 0;
const obj = {
get foo() {
console.log("foo", id++);
},
};
obj.foo;
const obj2 = {
...obj,
};
obj2.foo;
const obj3 = {
...obj,
foo: 1,
};
obj3.foo;
"###;
run_default_exec_test(src);
}