test(minifier): port the rest of tests (#6420)

This commit is contained in:
7086cmd 2024-10-10 12:28:00 +00:00
parent e59da61755
commit c5deb3235e
2 changed files with 438 additions and 2 deletions

View file

@ -28,7 +28,7 @@ impl PeepholeReplaceKnownMethods {
}
}
/// <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeReplaceKnownMethodsTest.java>
/// Port from: <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeReplaceKnownMethodsTest.java>
#[cfg(test)]
mod test {
use oxc_allocator::Allocator;
@ -745,4 +745,165 @@ mod test {
fold("x = parseInt('021', 8)", "x = 17");
fold("x = parseInt('-021', 8)", "x = -17");
}
#[test]
#[ignore]
fn test_replace_with_char_at() {
// enableTypeCheck();
// replaceTypesWithColors();
// disableCompareJsDoc();
fold_string_typed("a.substring(0, 1)", "a.charAt(0)");
fold_same_string_typed("a.substring(-4, -3)");
fold_same_string_typed("a.substring(i, j + 1)");
fold_same_string_typed("a.substring(i, i + 1)");
fold_same_string_typed("a.substring(1, 2, 3)");
fold_same_string_typed("a.substring()");
fold_same_string_typed("a.substring(1)");
fold_same_string_typed("a.substring(1, 3, 4)");
fold_same_string_typed("a.substring(-1, 3)");
fold_same_string_typed("a.substring(2, 1)");
fold_same_string_typed("a.substring(3, 1)");
fold_string_typed("a.slice(4, 5)", "a.charAt(4)");
fold_same_string_typed("a.slice(-2, -1)");
fold_string_typed("var /** number */ i; a.slice(0, 1)", "var /** number */ i; a.charAt(0)");
fold_same_string_typed("a.slice(i, j + 1)");
fold_same_string_typed("a.slice(i, i + 1)");
fold_same_string_typed("a.slice(1, 2, 3)");
fold_same_string_typed("a.slice()");
fold_same_string_typed("a.slice(1)");
fold_same_string_typed("a.slice(1, 3, 4)");
fold_same_string_typed("a.slice(-1, 3)");
fold_same_string_typed("a.slice(2, 1)");
fold_same_string_typed("a.slice(3, 1)");
fold_string_typed("a.substr(0, 1)", "a.charAt(0)");
fold_string_typed("a.substr(2, 1)", "a.charAt(2)");
fold_same_string_typed("a.substr(-2, 1)");
fold_same_string_typed("a.substr(bar(), 1)");
fold_same_string_typed("''.substr(bar(), 1)");
fold_same_string_typed("a.substr(2, 1, 3)");
fold_same_string_typed("a.substr(1, 2, 3)");
fold_same_string_typed("a.substr()");
fold_same_string_typed("a.substr(1)");
fold_same_string_typed("a.substr(1, 2)");
fold_same_string_typed("a.substr(1, 2, 3)");
// enableTypeCheck();
fold_same("function f(/** ? */ a) { a.substring(0, 1); }");
fold_same("function f(/** ? */ a) { a.substr(0, 1); }");
// fold_same(lines(
// "/** @constructor */ function A() {};",
// "A.prototype.substring = function(begin, end) {};",
// "function f(/** !A */ a) { a.substring(0, 1); }",
// ));
// fold_same(lines(
// "/** @constructor */ function A() {};",
// "A.prototype.slice = function(begin, end) {};",
// "function f(/** !A */ a) { a.slice(0, 1); }",
// ));
// useTypes = false;
fold_same_string_typed("a.substring(0, 1)");
fold_same_string_typed("a.substr(0, 1)");
fold_same_string_typed("''.substring(i, i + 1)");
}
#[test]
#[ignore]
fn test_fold_concat_chaining() {
// enableTypeCheck();
fold("[1,2].concat(1).concat(2,['abc']).concat('abc')", "[1,2].concat(1,2,['abc'],'abc')");
fold("[].concat(['abc']).concat(1).concat([2,3])", "['abc'].concat(1,[2,3])");
// cannot fold concat based on type information
fold_same("returnArrayType().concat(returnArrayType()).concat(1).concat(2)");
fold_same("returnArrayType().concat(returnUnionType()).concat(1).concat(2)");
fold(
"[1,2,1].concat(1).concat(returnArrayType()).concat(2)",
"[1,2,1].concat(1).concat(returnArrayType(),2)",
);
fold(
"[1].concat(1).concat(2).concat(returnArrayType())",
"[1].concat(1,2).concat(returnArrayType())",
);
fold_same("[].concat(1).concat(returnArrayType())");
fold_same("obj.concat([1,2]).concat(1)");
}
#[test]
#[ignore]
fn test_remove_array_literal_from_front_of_concat() {
// enableTypeCheck();
fold("[].concat([1,2,3],1)", "[1,2,3].concat(1)");
fold_same("[1,2,3].concat(returnArrayType())");
// Call method with the same name as Array.prototype.concat
fold_same("obj.concat([1,2,3])");
fold_same("[].concat(1,[1,2,3])");
fold_same("[].concat(1)");
fold("[].concat([1])", "[1].concat()");
// Chained folding of empty array lit
fold("[].concat([], [1,2,3], [4])", "[1,2,3].concat([4])");
fold("[].concat([]).concat([1]).concat([2,3])", "[1].concat([2,3])");
// Cannot fold based on type information
fold_same("[].concat(returnArrayType(),1)");
fold_same("[].concat(returnArrayType())");
fold_same("[].concat(returnUnionType())");
}
#[test]
#[ignore]
fn test_array_of_spread() {
fold("x = Array.of(...['a', 'b', 'c'])", "x = [...['a', 'b', 'c']]");
fold("x = Array.of(...['a', 'b', 'c',])", "x = [...['a', 'b', 'c']]");
fold("x = Array.of(...['a'], ...['b', 'c'])", "x = [...['a'], ...['b', 'c']]");
fold("x = Array.of('a', ...['b', 'c'])", "x = ['a', ...['b', 'c']]");
fold("x = Array.of('a', ...['b', 'c'])", "x = ['a', ...['b', 'c']]");
}
#[test]
#[ignore]
fn test_array_of_no_spread() {
fold("x = Array.of('a', 'b', 'c')", "x = ['a', 'b', 'c']");
fold("x = Array.of('a', ['b', 'c'])", "x = ['a', ['b', 'c']]");
fold("x = Array.of('a', ['b', 'c'],)", "x = ['a', ['b', 'c']]");
}
#[test]
#[ignore]
fn test_array_of_no_args() {
fold("x = Array.of()", "x = []");
}
#[test]
#[ignore]
fn test_array_of_no_change() {
fold_same("x = Array.of.apply(window, ['a', 'b', 'c'])");
fold_same("x = ['a', 'b', 'c']");
fold_same("x = [Array.of, 'a', 'b', 'c']");
}
#[test]
#[ignore]
fn test_fold_array_bug() {
fold_same("Array[123]()");
}
fn fold_same_string_typed(js: &str) {
fold_string_typed(js, js);
}
fn fold_string_typed(js: &str, expected: &str) {
let left = "function f(/** string */ a) {".to_string() + js + "}";
let right = "function f(/** string */ a) {".to_string() + expected + "}";
test(left.as_str(), right.as_str());
}
}

View file

@ -512,7 +512,7 @@ impl<'a> PeepholeSubstituteAlternateSyntax {
}
}
/// <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeSubstituteAlternateSyntaxTest.java>
/// Port from <https://github.com/google/closure-compiler/blob/master/test/com/google/javascript/jscomp/PeepholeSubstituteAlternateSyntaxTest.java>
#[cfg(test)]
mod test {
use oxc_allocator::Allocator;
@ -645,4 +645,279 @@ mod test {
"x = [{}, [\"abc\", {}, [[]]]]",
);
}
#[test]
#[ignore]
fn test_split_comma_expressions() {
// late = false;
// Don't try to split in expressions.
test_same("while (foo(), !0) boo()");
test_same("var a = (foo(), !0);");
test_same("a = (foo(), !0);");
// Don't try to split COMMA under LABELs.
test_same("a:a(),b()");
test("1, 2, 3, 4", "1; 2; 3; 4");
test("x = 1, 2, 3", "x = 1; 2; 3");
test_same("x = (1, 2, 3)");
test("1, (2, 3), 4", "1; 2; 3; 4");
test("(x=2), foo()", "x=2; foo()");
test("foo(), boo();", "foo(); boo()");
test("(a(), b()), (c(), d());", "a(); b(); c(); d()");
test("a(); b(); (c(), d());", "a(); b(); c(); d();");
test("foo(), true", "foo();true");
test_same("foo();true");
test("function x(){foo(), !0}", "function x(){foo(); !0}");
test_same("function x(){foo(); !0}");
}
#[test]
#[ignore]
fn test_comma1() {
// late = false;
test("1, 2", "1; 2");
// late = true;
// test_same("1, 2");
}
#[test]
#[ignore]
fn test_comma2() {
// late = false;
test("1, a()", "1; a()");
test("1, a?.()", "1; a?.()");
// late = true;
// test_same("1, a()");
// test_same("1, a?.()");
}
#[test]
#[ignore]
fn test_comma3() {
// late = false;
test("1, a(), b()", "1; a(); b()");
test("1, a?.(), b?.()", "1; a?.(); b?.()");
// late = true;
// test_same("1, a(), b()");
// test_same("1, a?.(), b?.()");
}
#[test]
#[ignore]
fn test_comma4() {
// late = false;
test("a(), b()", "a();b()");
test("a?.(), b?.()", "a?.();b?.()");
// late = true;
// test_same("a(), b()");
// test_same("a?.(), b?.()");
}
#[test]
#[ignore]
fn test_comma5() {
// late = false;
test("a(), b(), 1", "a(); b(); 1");
test("a?.(), b?.(), 1", "a?.(); b?.(); 1");
// late = true;
// test_same("a(), b(), 1");
// test_same("a?.(), b?.(), 1");
}
#[test]
#[ignore]
fn test_string_array_splitting() {
test_same("var x=['1','2','3','4']");
test_same("var x=['1','2','3','4','5']");
test("var x=['1','2','3','4','5','6']", "var x='123456'.split('')");
test("var x=['1','2','3','4','5','00']", "var x='1 2 3 4 5 00'.split(' ')");
test("var x=['1','2','3','4','5','6','7']", "var x='1234567'.split('')");
test("var x=['1','2','3','4','5','6','00']", "var x='1 2 3 4 5 6 00'.split(' ')");
test("var x=[' ,',',',',',',',',',',']", "var x=' ,;,;,;,;,;,'.split(';')");
test("var x=[',,',' ',',',',',',',',']", "var x=',,; ;,;,;,;,'.split(';')");
test("var x=['a,',' ',',',',',',',',']", "var x='a,; ;,;,;,;,'.split(';')");
// all possible delimiters used, leave it alone
test_same("var x=[',', ' ', ';', '{', '}']");
}
#[test]
#[ignore]
fn test_template_string_to_string() {
test("`abcde`", "'abcde'");
test("`ab cd ef`", "'ab cd ef'");
test_same("`hello ${name}`");
test_same("tag `hello ${name}`");
test_same("tag `hello`");
test("`hello ${'foo'}`", "'hello foo'");
test("`${2} bananas`", "'2 bananas'");
test("`This is ${true}`", "'This is true'");
}
#[test]
#[ignore]
fn test_bind_to_call1() {
test("(goog.bind(f))()", "f()");
test("(goog.bind(f,a))()", "f.call(a)");
test("(goog.bind(f,a,b))()", "f.call(a,b)");
test("(goog.bind(f))(a)", "f(a)");
test("(goog.bind(f,a))(b)", "f.call(a,b)");
test("(goog.bind(f,a,b))(c)", "f.call(a,b,c)");
test("(goog.partial(f))()", "f()");
test("(goog.partial(f,a))()", "f(a)");
test("(goog.partial(f,a,b))()", "f(a,b)");
test("(goog.partial(f))(a)", "f(a)");
test("(goog.partial(f,a))(b)", "f(a,b)");
test("(goog.partial(f,a,b))(c)", "f(a,b,c)");
test("((function(){}).bind())()", "((function(){}))()");
test("((function(){}).bind(a))()", "((function(){})).call(a)");
test("((function(){}).bind(a,b))()", "((function(){})).call(a,b)");
test("((function(){}).bind())(a)", "((function(){}))(a)");
test("((function(){}).bind(a))(b)", "((function(){})).call(a,b)");
test("((function(){}).bind(a,b))(c)", "((function(){})).call(a,b,c)");
// Without using type information we don't know "f" is a function.
test_same("(f.bind())()");
test_same("(f.bind(a))()");
test_same("(f.bind())(a)");
test_same("(f.bind(a))(b)");
// Don't rewrite if the bind isn't the immediate call target
test_same("(goog.bind(f)).call(g)");
}
#[test]
#[ignore]
fn test_bind_to_call2() {
test("(goog$bind(f))()", "f()");
test("(goog$bind(f,a))()", "f.call(a)");
test("(goog$bind(f,a,b))()", "f.call(a,b)");
test("(goog$bind(f))(a)", "f(a)");
test("(goog$bind(f,a))(b)", "f.call(a,b)");
test("(goog$bind(f,a,b))(c)", "f.call(a,b,c)");
test("(goog$partial(f))()", "f()");
test("(goog$partial(f,a))()", "f(a)");
test("(goog$partial(f,a,b))()", "f(a,b)");
test("(goog$partial(f))(a)", "f(a)");
test("(goog$partial(f,a))(b)", "f(a,b)");
test("(goog$partial(f,a,b))(c)", "f(a,b,c)");
// Don't rewrite if the bind isn't the immediate call target
test_same("(goog$bind(f)).call(g)");
}
#[test]
#[ignore]
fn test_bind_to_call3() {
// TODO(johnlenz): The code generator wraps free calls with (0,...) to
// prevent leaking "this", but the parser doesn't unfold it, making a
// AST comparison fail. For now do a string comparison to validate the
// correct code is in fact generated.
// The FREE call wrapping should be moved out of the code generator
// and into a denormalizing pass.
// disableCompareAsTree();
// retraverseOnChange = true;
// late = false;
test("(goog.bind(f.m))()", "(0,f.m)()");
test("(goog.bind(f.m,a))()", "f.m.call(a)");
test("(goog.bind(f.m))(a)", "(0,f.m)(a)");
test("(goog.bind(f.m,a))(b)", "f.m.call(a,b)");
test("(goog.partial(f.m))()", "(0,f.m)()");
test("(goog.partial(f.m,a))()", "(0,f.m)(a)");
test("(goog.partial(f.m))(a)", "(0,f.m)(a)");
test("(goog.partial(f.m,a))(b)", "(0,f.m)(a,b)");
// Without using type information we don't know "f" is a function.
test_same("f.m.bind()()");
test_same("f.m.bind(a)()");
test_same("f.m.bind()(a)");
test_same("f.m.bind(a)(b)");
// Don't rewrite if the bind isn't the immediate call target
test_same("goog.bind(f.m).call(g)");
}
#[test]
#[ignore]
fn test_simple_function_call1() {
test("var a = String(23)", "var a = '' + 23");
// Don't fold the existence check to preserve behavior
test_same("var a = String?.(23)");
test("var a = String('hello')", "var a = '' + 'hello'");
// Don't fold the existence check to preserve behavior
test_same("var a = String?.('hello')");
test_same("var a = String('hello', bar());");
test_same("var a = String({valueOf: function() { return 1; }});");
}
#[test]
#[ignore]
fn test_simple_function_call2() {
test("var a = Boolean(true)", "var a = !0");
// Don't fold the existence check to preserve behavior
test("var a = Boolean?.(true)", "var a = Boolean?.(!0)");
test("var a = Boolean(false)", "var a = !1");
// Don't fold the existence check to preserve behavior
test("var a = Boolean?.(false)", "var a = Boolean?.(!1)");
test("var a = Boolean(1)", "var a = !!1");
// Don't fold the existence check to preserve behavior
test_same("var a = Boolean?.(1)");
test("var a = Boolean(x)", "var a = !!x");
// Don't fold the existence check to preserve behavior
test_same("var a = Boolean?.(x)");
test("var a = Boolean({})", "var a = !!{}");
// Don't fold the existence check to preserve behavior
test_same("var a = Boolean?.({})");
test_same("var a = Boolean()");
test_same("var a = Boolean(!0, !1);");
}
#[test]
#[ignore]
fn test_rotate_associative_operators() {
test("a || (b || c); a * (b * c); a | (b | c)", "(a || b) || c; (a * b) * c; (a | b) | c");
test_same("a % (b % c); a / (b / c); a - (b - c);");
test("a * (b % c);", "b % c * a");
test("a * b * (c / d)", "c / d * b * a");
test("(a + b) * (c % d)", "c % d * (a + b)");
test_same("(a / b) * (c % d)");
test_same("(c = 5) * (c % d)");
test("(a + b) * c * (d % e)", "d % e * c * (a + b)");
test("!a * c * (d % e)", "d % e * c * !a");
}
#[test]
#[ignore]
fn nullish_coalesce() {
test("a ?? (b ?? c);", "(a ?? b) ?? c");
}
#[test]
#[ignore]
fn test_no_rotate_infinite_loop() {
test("1/x * (y/1 * (1/z))", "1/x * (y/1) * (1/z)");
test_same("1/x * (y/1) * (1/z)");
}
}