2020-02-13 05:45:14 +03:00
//! Copied from https://github.com/google/closure-compiler/blob/6ca3b62990064488074a1a8931b9e8dc39b148b3/test/com/google/javascript/jscomp/InlineVariablesTest.java
2021-12-04 05:35:16 +03:00
use swc_common ::{ chain , Mark } ;
2020-10-11 18:36:44 +03:00
use swc_ecma_parser ::{ Syntax , TsConfig } ;
2022-04-26 10:38:50 +03:00
use swc_ecma_transforms_base ::resolver ;
2022-03-05 09:46:09 +03:00
use swc_ecma_transforms_compat ::es2022 ::class_properties ;
2021-01-05 08:29:52 +03:00
use swc_ecma_transforms_optimization ::simplify ::inlining ::inlining ;
use swc_ecma_transforms_testing ::test ;
use swc_ecma_transforms_typescript ::strip ;
2021-05-15 10:07:24 +03:00
use swc_ecma_visit ::Fold ;
2022-04-26 10:38:50 +03:00
fn simple_strip ( top_level_mark : Mark ) -> impl Fold {
2021-12-04 05:35:16 +03:00
strip ::strip_with_config (
strip ::Config {
no_empty_export : true ,
.. Default ::default ( )
} ,
2022-04-26 10:38:50 +03:00
top_level_mark ,
2021-12-04 05:35:16 +03:00
)
2021-05-15 10:07:24 +03:00
}
2020-02-13 05:45:14 +03:00
macro_rules ! to {
( $name :ident , $src :expr , $expected :expr ) = > {
test! (
Default ::default ( ) ,
2022-04-26 10:38:50 +03:00
| _ | chain! (
resolver ( Mark ::new ( ) , Mark ::new ( ) , false ) ,
inlining ( Default ::default ( ) )
) ,
2020-02-13 05:45:14 +03:00
$name ,
$src ,
$expected
) ;
} ;
( ignore , $name :ident , $src :expr , $expected :expr ) = > {
test! (
ignore ,
Default ::default ( ) ,
2022-04-26 10:38:50 +03:00
| _ | chain! (
resolver ( Mark ::new ( ) , Mark ::new ( ) , false ) ,
inlining ( Default ::default ( ) )
) ,
2020-02-13 05:45:14 +03:00
$name ,
$src ,
$expected
) ;
} ;
}
macro_rules ! identical {
( $name :ident , $src :expr ) = > {
to! ( $name , $src , $src ) ;
} ;
}
2021-09-01 16:11:55 +03:00
#[ track_caller ]
2020-02-13 05:45:14 +03:00
fn test ( src : & str , expected : & str ) {
2021-01-05 08:29:52 +03:00
swc_ecma_transforms_testing ::test_transform (
2020-02-13 05:45:14 +03:00
::swc_ecma_parser ::Syntax ::default ( ) ,
2022-04-26 10:38:50 +03:00
| _ | {
let unresolved_mark = Mark ::new ( ) ;
let top_level_mark = Mark ::new ( ) ;
chain! (
resolver ( unresolved_mark , top_level_mark , false ) ,
inlining ( Default ::default ( ) )
)
} ,
2020-02-13 05:45:14 +03:00
src ,
expected ,
2021-01-05 08:29:52 +03:00
true ,
2020-02-13 05:45:14 +03:00
)
}
/// Should not modify expression.
fn test_same ( s : & str ) {
test ( s , s )
}
to! (
top_level_simple_var ,
" var a = 1; var b = a; " ,
" var a; var b; "
) ;
to! (
function_scope_simple_var ,
" var a = 1;
var b = a ;
use ( b ) ; " ,
" var a;
var b ;
use ( 1 ) ; "
) ;
identical! ( top_level_increment , " var x = 1; x++; " ) ;
identical! ( top_level_decrement , " var x = 1; x--; " ) ;
identical! ( top_level_assign_op , " var x = 1; x += 3; " ) ;
to! (
simple_inline_in_fn ,
" var x = 1; var z = x; use(z) " ,
" var x; var z; use(1) "
) ;
to! (
ignore ,
unresolved_inline_in_fn ,
" var a = new obj();
result = a ; " ,
" result = new obj() "
) ;
// GitHub issue #1234: https://github.com/google/closure-compiler/issues/1234
identical! (
closure_compiler_1234 ,
" var x;
switch ( 'a' ) {
case 'a' :
break ;
2021-11-07 14:46:12 +03:00
default :
2020-02-13 05:45:14 +03:00
x = 1 ;
break ;
}
use ( x ) ; "
) ;
to! (
let_1 ,
" function f(x) {
if ( true ) {
let y = x ;
y ;
y ;
}
} " ,
" function f(x) {
if ( true ) {
let y ;
x ;
x ;
}
} "
) ;
to! (
const_1 ,
" function f(x) {
if ( true ) {
const y = x ;
y ;
y ;
}
} " ,
" function f(x) {
if ( true ) {
const y = x ;
x ;
x ;
}
} "
) ;
to! (
let_2 ,
" let y;
{
let y = x ;
y ;
}
y ;
" ,
" let y;
{
2021-11-07 14:46:12 +03:00
let y ;
2020-02-13 05:45:14 +03:00
x ;
}
y ; "
) ;
to! (
let_const_1 ,
"
const g = 3 ;
let y = g ;
y ;
" ,
" const g = 3;
let y ;
3 ;
"
) ;
to! (
let_const_2 ,
" let y = x;
y ;
const g = 2 ;
{
const g = 3 ;
let y = g ;
y ;
}
y ;
g ;
" ,
" let y;
x ;
const g = 2 ;
{
2021-09-01 16:11:55 +03:00
const g = 3 ;
let y ;
2020-02-13 05:45:14 +03:00
3 ;
}
x ;
2 ;
"
) ;
to! (
regex ,
" var b;b=/ab/;(b)?x=1:x=2; " ,
" var b;b=/ab/;/ab/?x=1:x=2; "
) ;
to! (
generator_let_yield ,
" function* f() { let x = 1; yield x; } " ,
" function* f() { let x; yield 1; } "
) ;
// TODO: Inline single use
identical! (
generator_let_increment ,
" function* f(x) { let y = x++; yield y; } "
) ;
identical! ( for_of_1 , " var i = 0; for(i of n) {} " ) ;
identical! ( for_of_2 , " for( var i of n) { var x = i; } " ) ;
to! (
tpl_lit_1 ,
" var name = 'Foo'; `Hello ${name}` " ,
" var name; `Hello ${'Foo'}` "
) ;
to! (
tpl_lit_2 ,
" var name = 'Foo'; var foo = name; `Hello ${foo}` " ,
" var name; var foo; `Hello ${'Foo'}` "
) ;
to! (
tpl_lit_3 ,
" var age = 3; `Age: ${age}` " ,
" var age; `Age: ${3}` "
) ;
to! (
ignore ,
tagged_tpl_lit_1 ,
concat! (
" var name = 'Foo'; " ,
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${name} ${3}`; " ,
) ,
concat! (
" var output = function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" }`My name is ${'Foo'} ${3}`; " ,
)
) ;
to! (
tagged_tpl_lit_2 ,
concat! (
" var name = 'Foo'; " ,
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${name} ${3}`; " ,
" output = myTag`My name is ${name} ${2}`; " ,
) ,
concat! (
" var name; " ,
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${'Foo'} ${3}`; " ,
" output = myTag`My name is ${'Foo'} ${2}`; " ,
)
) ;
identical! (
function_scope_var_1 ,
" var x = 1;
function foo ( ) {
x = 2 ;
}
use ( x ) ;
"
) ;
identical! (
function_scope_var_2 ,
" (function(){
var x = 1 ;
function foo ( ) {
x = 2 ;
}
use ( x ) ;
} ) ( ) ; "
) ;
identical! (
top_level_does_not_inline_fn_decl ,
" function foo(){}
use ( foo ) ; "
) ;
to! (
custom_loop_1 ,
"
let b = 2 ;
let a = 1 ;
if ( b ) {
a = 2 ;
}
let c ;
if ( a ) {
c = 3 ;
}
" ,
" let b;
let a = 1 ;
if ( 2 ) {
a = 2 ;
}
let c ;
if ( a ) {
c = 3 ;
} "
) ;
to! (
custom_loop_2 ,
" let b = 2;
let a = 1 ;
a = 2 ;
let c ;
if ( a ) c = 3 " ,
" let b;
let a ;
a = 2 ;
let c ;
if ( 2 ) c = 3 "
) ;
to! (
custom_loop_3 ,
" let c;
c = 3 ;
console . log ( c ) ; " ,
" let c;
c = 3 ;
console . log ( 3 ) ; "
) ;
#[ test ]
fn test_pass_doesnt_produce_invalid_code1 ( ) {
test_same ( concat! (
" function f(x = void 0) { " ,
" var z; " ,
" { " ,
" const y = {}; " ,
" x && (y['x'] = x); " ,
" z = y; " ,
" } " ,
" return z; " ,
" } " ,
) ) ;
}
#[ test ]
fn test_pass_doesnt_produce_invalid_code2 ( ) {
test_same ( concat! (
" function f(x = void 0) { " ,
" { " ,
" var z; " ,
" const y = {}; " ,
" x && (y['x'] = x); " ,
" z = y; " ,
" } " ,
" return z; " ,
" } " ,
) ) ;
}
#[ test ]
fn test_pass_doesnt_produce_invalid_code3 ( ) {
test (
concat! (
" function f(x = void 0) { " ,
" var z; " ,
" const y = {}; " ,
" x && (y['x'] = x); " ,
" z = y; " ,
" { " ,
" return z; " ,
" } " ,
" } " ,
) ,
concat! (
" function f(x = void 0) { " ,
" var z; " ,
" const y = {}; " ,
" x && (y['x'] = x); " ,
" z = y; " ,
" { " ,
" return y; " ,
" } " ,
" } " ,
) ,
) ;
}
// Test respect for scopes and blocks
#[ test ]
fn test_inline_global ( ) {
test ( " var x = 1; var z = x; " , " var x; var z; " ) ;
}
#[ test ]
fn test_do_not_inline_increment ( ) {
test_same ( " var x = 1; x++; " ) ;
}
#[ test ]
fn test_do_not_inline_decrement ( ) {
test_same ( " var x = 1; x--; " ) ;
}
#[ test ]
fn test_do_not_inline_into_lhs_of_assign ( ) {
test_same ( " var x = 1; x += 3; " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inline_into_rhs_of_assign ( ) {
test ( " var x = foo(); var y = x; " , " var x; var y = foo(); " ) ;
}
#[ test ]
fn test_inline_into_rhs_of_assign ( ) {
test ( " var x = foo(); var y = x; " , " var x = foo(); var y = x; " ) ;
}
#[ test ]
fn test_inline_in_function1 ( ) {
test (
" function baz() { var x = 1; var z = x; } " ,
" function baz() { var x; var z; } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_in_function2 ( ) {
test (
" function baz() { var a = new obj(); result = a; } " ,
" function baz() { result = new obj() } " ,
) ;
}
#[ test ]
fn test_inline_in_function3 ( ) {
test_same ( " function baz() { var a = new obj(); (function(){a;})(); result = a; } " ) ;
}
#[ test ]
fn test_inline_in_function4 ( ) {
test_same ( " function baz() { var a = new obj(); foo.result = a; } " ) ;
}
#[ test ]
fn test_inline_in_function5 ( ) {
test (
" function baz() { var a = (foo = new obj()); foo.x(); result = a; } " ,
" function baz() { var a = foo = new obj(); foo.x(); result = a; } " ,
) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inline_in_function6 ( ) {
test (
" function baz() { { var x = foo(); var z = x; } } " ,
" function baz() { { var x; var z = foo(); } } " ,
) ;
}
#[ test ]
fn test_inline_in_function6 ( ) {
test (
" function baz() { { var x = foo(); var z = x; } } " ,
" function baz() { { var x = foo(); var z = x; } } " ,
) ;
}
#[ test ]
fn test_inline_in_function7 ( ) {
test (
" function baz() { var x = 1; { var z = x; } } " ,
" function baz() { var x; { var z; } } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_arrow_function1 ( ) {
test ( " var x = 0; var f = () => x + 1; " , " var f = () => 0 + 1; " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_arrow_function2 ( ) {
test (
" var x = 0; var f = () => { return x + 1; } " ,
" var f = () => { return 0 + 1; } " ,
) ;
}
#[ test ]
fn test_do_not_exit_conditional1 ( ) {
test_same ( " if (true) { var x = 1; } var z = x; " ) ;
}
#[ test ]
fn test_do_not_exit_conditional2 ( ) {
test_same ( " if (true) var x = 1; var z = x; " ) ;
}
#[ test ]
fn test_do_not_exit_conditional3 ( ) {
test_same ( " var x; if (true) x=1; var z = x; " ) ;
}
#[ test ]
fn test_do_not_exit_loop ( ) {
test_same ( " while (z) { var x = 3; } var y = x; " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_do_not_exit_for_loop ( ) {
test (
" for (var i = 1; false; false) var z = i; " ,
" for (;false;false) var z = 1; " ,
) ;
test_same ( " for (; false; false) var i = 1; var z = i; " ) ;
test_same ( " for (var i in {}); var z = i; " ) ;
}
#[ test ]
fn test_do_not_exit_for_loop ( ) {
test (
" for (var i = 1; false; false) var z = i; " ,
" for (var i = 1;false;false) var z = i; " ,
) ;
test_same ( " for (; false; false) var i = 1; var z = i; " ) ;
test_same ( " for (var i in {}); var z = i; " ) ;
}
#[ test ]
fn test_do_not_enter_subscope ( ) {
test_same ( concat! (
" var x = function() { " ,
" var self = this; " ,
" return function() { var y = self; }; " ,
" } "
) ) ;
test_same ( " var x = function() { var y = [1]; return function() { var z = y; }; } " ) ;
}
#[ test ]
fn test_do_not_exit_try ( ) {
test (
" try { var x = y; } catch (e) {} var z = y; " ,
" try { var x = y; } catch (e) {} var z = y; " ,
) ;
2021-09-01 16:11:55 +03:00
test_same ( " try { throw e; var x = 1; } catch (e1) {} var z = x; " ) ;
2020-02-13 05:45:14 +03:00
}
#[ test ]
fn test_do_not_enter_catch ( ) {
test_same ( " try { } catch (e) { var z = e; } " ) ;
}
#[ test ]
fn test_do_not_enter_finally ( ) {
2021-09-01 16:11:55 +03:00
test_same ( " try { throw e; var x = 1; } catch (e1) {} finally { var z = x; } " ) ;
2020-02-13 05:45:14 +03:00
}
#[ test ]
#[ ignore ]
fn orig_test_inside_if_conditional ( ) {
test (
" var a = foo(); if (a) { alert(3); } " ,
" var a; if (foo()) { alert(3); } " ,
) ;
test (
" var a; a = foo(); if (a) { alert(3); } " ,
" var a; if (foo()) { alert(3); } " ,
) ;
}
#[ test ]
fn test_inside_if_conditional ( ) {
test (
" var a = foo(); if (a) { alert(3); } " ,
" var a = foo(); if (a) { alert(3); } " ,
) ;
test (
" var a; a = foo(); if (a) { alert(3); } " ,
" var a; a = foo(); if (a) { alert(3); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_only_read_at_initialization ( ) {
test ( " var a; a = foo(); " , " foo(); " ) ;
test (
" var a; if (a = foo()) { alert(3); } " ,
" if (foo()) { alert(3); } " ,
) ;
test ( " var a; switch (a = foo()) {} " , " switch(foo()) {} " ) ;
test (
" var a; function f(){ return a = foo(); } " ,
" function f(){ return foo(); } " ,
) ;
test (
" function f(){ var a; return a = foo(); } " ,
" function f(){ return foo(); } " ,
) ;
test (
" var a; with (a = foo()) { alert(3); } " ,
" with (foo()) { alert(3); } " ,
) ;
test ( " var a; b = (a = foo()); " , " b = foo(); " ) ;
test (
" var a; while(a = foo()) { alert(3); } " ,
" while(foo()) { alert(3); } " ,
) ;
test (
" var a; for(;a = foo();) { alert(3); } " ,
" for(;foo();) { alert(3); } " ,
) ;
test (
" var a; do {} while(a = foo()) { alert(3); } " ,
" do {} while(foo()) { alert(3); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_immutable_with_single_reference_after_initialzation ( ) {
test ( " var a; a = 1; " , " var a; a = 1; " ) ;
test ( " var a; if (a = 1) { alert(3); } " , " if (1) { alert(3); } " ) ;
test ( " var a; switch (a = 1) {} " , " switch(1) {} " ) ;
test (
" var a; function f(){ return a = 1; } " ,
" function f(){ return 1; } " ,
) ;
test (
" function f(){ var a; return a = 1; } " ,
" function f(){ return 1; } " ,
) ;
test (
" var a; with (a = 1) { alert(3); } " ,
" with (1) { alert(3); } " ,
) ;
test ( " var a; b = (a = 1); " , " b = 1; " ) ;
test (
" var a; while(a = 1) { alert(3); } " ,
" while(1) { alert(3); } " ,
) ;
test (
" var a; for(;a = 1;) { alert(3); } " ,
" for(;1;) { alert(3); } " ,
) ;
test (
" var a; do {} while(a = 1) { alert(3); } " ,
" do {} while(1) { alert(3); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_single_reference_after_initialzation ( ) {
test ( " var a; a = foo();a; " , " foo(); " ) ;
test_same ( " var a; if (a = foo()) { alert(3); } a; " ) ;
test_same ( " var a; switch (a = foo()) {} a; " ) ;
test_same ( " var a; function f(){ return a = foo(); } a; " ) ;
test_same ( " function f(){ var a; return a = foo(); a;} " ) ;
test_same ( " var a; with (a = foo()) { alert(3); } a; " ) ;
test_same ( " var a; b = (a = foo()); a; " ) ;
test_same ( " var a; while(a = foo()) { alert(3); } a; " ) ;
test_same ( " var a; for(;a = foo();) { alert(3); } a; " ) ;
test_same ( " var a; do {} while(a = foo()) { alert(3); } a; " ) ;
}
#[ test ]
fn test_inside_if_branch ( ) {
test_same ( " var a = foo(); if (1) { alert(a); } " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inside_and_conditional ( ) {
test ( " var a = foo(); a && alert(3); " , " foo() && alert(3); " ) ;
}
#[ test ]
fn test_inside_and_conditional ( ) {
test (
" var a = foo(); a && alert(3); " ,
" var a = foo(); a && alert(3); " ,
) ;
}
#[ test ]
fn test_inside_and_branch ( ) {
test_same ( " var a = foo(); 1 && alert(a); " ) ;
}
#[ test ]
fn test_inside_or_branch ( ) {
test_same ( " var a = foo(); 1 || alert(a); " ) ;
}
#[ test ]
fn test_inside_hook_branch ( ) {
test_same ( " var a = foo(); 1 ? alert(a) : alert(3) " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inside_hook_conditional ( ) {
test (
" var a = foo(); a ? alert(1) : alert(3) " ,
" foo() ? alert(1) : alert(3) " ,
) ;
}
#[ test ]
fn test_inside_hook_conditional ( ) {
test (
" var a = foo(); a ? alert(1) : alert(3) " ,
" var a = foo(); a ? alert(1) : alert(3) " ,
) ;
}
#[ test ]
fn test_inside_or_branch_inside_if_conditional ( ) {
test_same ( " var a = foo(); if (x || a) {} " ) ;
}
#[ test ]
fn test_inside_or_branch_inside_if_conditional_with_constant ( ) {
// We don't inline non-immutable constants into branches.
test_same ( " var a = [false]; if (x || a) {} " ) ;
}
// Test movement of constant values
#[ test ]
#[ ignore ]
fn test_do_cross_function ( ) {
// We know foo() does not affect x because we require that x is only
// referenced twice.
test ( " var x = 1; foo(); var z = x; " , " foo(); var z = 1; " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_do_not_cross_referencing_function ( ) {
test_same ( " var f = function() { var z = x; }; var x = 1; f(); var z = x; f(); " ) ;
}
#[ test ]
fn test_do_not_cross_referencing_function ( ) {
test (
" var f = function() { var z = foo(); }; var x = 1; f(); var z = x; f(); " ,
" var f = function() { var z = foo(); }; var x = 1; f(); var z = x; f(); " ,
) ;
}
// Test tricky declarations and references
#[ test ]
fn test_chained_assignment ( ) {
test ( " var a = 2, b = 2; var c = b; " , " var a, b; var c; " ) ;
test ( " var a = 2, b = 2; var c = a; " , " var a, b; var c; " ) ;
test (
" var a = b = 2; var f = 3; var c = a; " ,
" var a; var f; var c = b = 2; " ,
) ;
test_same ( " var a = b = 2; var c; " ) ;
}
#[ test ]
fn test_for_in ( ) {
test (
" for (var i in j) { var c = i; } " ,
" for (var i in j) { var c = i; } " ,
) ;
test_same ( " var i = 0; for (i in j) ; " ) ;
test_same ( " var i = 0; for (i in j) { var c = i; } " ) ;
test_same ( " i = 0; for (var i in j) { var c = i; } " ) ;
test_same ( " var j = {'key':'value'}; for (var i in j) {print(i)}; " ) ;
}
// Test movement of values that have (may) side effects
#[ test ]
#[ ignore ]
fn test_do_cross_new_variables ( ) {
test ( " var x = foo(); var z = x; " , " var z = foo(); " ) ;
}
#[ test ]
fn test_do_not_cross_function_calls ( ) {
test_same ( " var x = foo(); bar(); var z = x; " ) ;
}
// Test movement of values that are complex but lack side effects
#[ test ]
fn test_do_not_cross_assignment ( ) {
test_same ( " var x = {}; var y = x.a; x.a = 1; var z = y; " ) ;
test_same ( " var a = this.id; foo(this.id = 3, a); " ) ;
}
#[ test ]
fn test_do_not_cross_delete ( ) {
test_same ( " var x = {}; var y = x.a; delete x.a; var z = y; " ) ;
}
#[ test ]
fn test_do_not_cross_assignment_plus ( ) {
test_same ( " var a = b; b += 2; var c = a; " ) ;
}
#[ test ]
fn test_do_not_cross_increment ( ) {
test_same ( " var a = b.c; b.c++; var d = a; " ) ;
}
#[ test ]
fn test_do_not_cross_constructor ( ) {
test_same ( " var a = b; new Foo(); var c = a; " ) ;
}
#[ test ]
#[ ignore ]
fn test_do_cross_var ( ) {
// Assumes we do not rely on undefined variables (not technically correct!)
test ( " var a = b; var b = 3; alert(a) " , " alert(3); " ) ;
}
#[ test ]
#[ ignore ]
fn test_overlapping_in_lines ( ) {
test (
concat! (
" a = function(el, x, opt_y) { " ,
" var cur = bar(el); " ,
" opt_y = x.y; " ,
" x = x.x; " ,
" var dx = x - cur.x; " ,
" var dy = opt_y - cur.y; " ,
" foo(el, el.offsetLeft + dx, el.offsetTop + dy); " ,
" }; "
) ,
concat! (
" a = function(el, x, opt_y) { " ,
" var cur = bar(el); " ,
" opt_y = x.y; " ,
" x = x.x; " ,
" foo(el, el.offsetLeft + (x - cur.x), " ,
" el.offsetTop + (opt_y - cur.y)); " ,
" }; "
) ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_loops ( ) {
test (
" var x = true; while (true) alert(x); " ,
" var x; while (true) alert(true); " ,
) ;
test (
" var x = true; while (true) for (var i in {}) alert(x); " ,
" var x; while (true) for (var i in {}) alert(true); " ,
) ;
test_same ( " var x = [true]; while (true) alert(x); " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_function ( ) {
test (
" var x = false; var f = function() { alert(x); }; " ,
" var f = function() { alert(false); }; " ,
) ;
test_same ( " var x = [false]; var f = function() { alert(x); }; " ) ;
}
#[ test ]
fn test_no_inline_into_named_function ( ) {
test_same ( " f(); var x = false; function f() { alert(x); }; " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_nested_non_hoisted_named_functions ( ) {
test (
" f(); var x = false; if (false) function f() { alert(x); }; " ,
" f(); if (false) function f() { alert(false); }; " ,
) ;
}
#[ test ]
fn test_no_inline_into_nested_named_functions ( ) {
test_same ( " f(); var x = false; function f() { if (false) { alert(x); } }; " ) ;
}
#[ test ]
fn test_no_inline_mutated_variable ( ) {
test_same ( " var x = false; if (true) { var y = x; x = true; } " ) ;
}
#[ test ]
fn test_inline_immutable_multiple_times ( ) {
test ( " var x = null; var y = x, z = x; " , " var x; var y, z; " ) ;
test ( " var x = 3; var y = x, z = x; " , " var x; var y, z; " ) ;
}
#[ test ]
fn test_inline_string_multiple_times_when_aliasing_all_strings ( ) {
test (
" var x = 'abcdefghijklmnopqrstuvwxyz'; var y = x, z = x; " ,
" var x; var y, z; " ,
) ;
}
#[ test ]
fn test_no_inline_backwards ( ) {
test_same ( " var y = x; var x = foo(); " ) ;
}
#[ test ]
fn test_no_inline_out_of_branch ( ) {
test_same ( " if (true) var x = foo(); var y = x; " ) ;
}
#[ test ]
#[ ignore ]
fn orig_test_interfering_in_lines ( ) {
test (
" var a = 3; var f = function() { var x = a; alert(x); }; " ,
" var a; var f = function() { var x; alert(3); }; " ,
) ;
}
#[ test ]
fn test_interfering_in_lines ( ) {
test (
" var a = 3; var f = function() { var x = a; alert(x); }; " ,
" var a = 3; var f = function() { var x = a; alert(x); }; " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_into_try_catch ( ) {
test (
concat! (
" var a = true; " ,
" try { var b = a; } " ,
" catch (e) { var c = a + b; var d = true; } " ,
" finally { var f = a + b + c + d; } "
) ,
concat! (
" try { var b = true; } " ,
" catch (e) { var c = true + b; var d = true; } " ,
" finally { var f = true + b + c + d; } "
) ,
) ;
}
// Make sure that we still inline constants that are not provably
// written before they're read.
#[ test ]
fn test_inline_constants ( ) {
test (
" function foo() { return XXX; } var XXX = true; " ,
" function foo() { return XXX; } var XXX = true; " ,
) ;
}
#[ test ]
fn test_inline_string_when_worthwhile ( ) {
test ( " var x = 'a'; foo(x, x, x); " , " var x; foo('a', 'a', 'a'); " ) ;
}
#[ test ]
fn test_inline_constant_alias ( ) {
test (
" var XXX = new Foo(); q(XXX); var YYY = XXX; bar(YYY) " ,
" var XXX = new Foo(); q(XXX); var YYY = XXX; bar(YYY) " ,
) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inline_constant_alias_with_non_constant ( ) {
test (
" var XXX = new Foo(); q(XXX); var y = XXX; bar(y); baz(y) " ,
" var XXX = new Foo(); q(XXX); var y; bar(XXX); baz(XXX) " ,
) ;
}
#[ test ]
fn test_inline_constant_alias_with_non_constant ( ) {
test (
" var XXX = new Foo(); q(XXX); var y = XXX; bar(y); baz(y) " ,
" var XXX = new Foo(); q(XXX); var y = XXX; bar(y); baz(y) " ,
) ;
}
#[ test ]
#[ ignore ]
fn orig_test_cascading_in_lines ( ) {
test (
" var XXX = 4; function f() { var YYY = XXX; bar(YYY); baz(YYY); } " ,
" var XXX; function f() { var YYY; bar(4); baz(4); } " ,
) ;
}
#[ test ]
fn test_cascading_in_lines ( ) {
test (
" var XXX = 4; function f() { var YYY = XXX; bar(YYY); baz(YYY); } " ,
" var XXX = 4; function f() { var YYY = XXX; bar(YYY); baz(YYY); } " ,
) ;
}
#[ test ]
fn test_no_inline_getprop_into_call_1 ( ) {
test ( " var a = b; a(); " , " var a; b(); " ) ;
}
#[ test ]
fn test_no_inline_getprop_into_call_2 ( ) {
test ( " var a = b.c; f(a); " , " var a; f(b.c); " ) ;
}
#[ test ]
fn test_no_inline_getprop_into_call_3 ( ) {
test_same ( " var a = b.c; a(); " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_function_declaration ( ) {
test (
" var f = function () {}; var a = f; " ,
" var f; var a = function () {}; " ,
) ;
test (
" var f = function () {}; foo(); var a = f; " ,
" foo(); var a = function () {}; " ,
) ;
test ( " var f = function () {}; foo(f); " , " foo(function () {}); " ) ;
test_same ( " var f = function () {}; function g() {var a = f;} " ) ;
test_same ( " var f = function () {}; function g() {h(f);} " ) ;
}
#[ test ]
fn test_recursive_function1 ( ) {
2021-04-06 07:31:11 +03:00
test (
" var x = 0; (function x() { return x ? x() : 3; })(); " ,
2021-12-03 19:55:27 +03:00
" var x; (function x1() { return x1 ? x1() : 3; })(); " ,
2021-04-06 07:31:11 +03:00
) ;
2020-02-13 05:45:14 +03:00
}
#[ test ]
fn test_recursive_function2 ( ) {
test_same ( " function y() { return y(); } " ) ;
}
#[ test ]
fn test_unreferenced_bleeding_function ( ) {
test_same ( " var x = function y() {} " ) ;
}
#[ test ]
fn test_referenced_bleeding_function ( ) {
test_same ( " var x = function y() { return y(); } " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases1 ( ) {
test (
" var x = this.foo(); this.bar(); var y = x; this.baz(y); " ,
" var x = this.foo(); this.bar(); var y; this.baz(x); " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases1b ( ) {
test (
" var x = this.foo(); this.bar(); var y; y = x; this.baz(y); " ,
" var x = this.foo(); this.bar(); var y; x; this.baz(x); " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases1c ( ) {
test (
" var x; x = this.foo(); this.bar(); var y = x; this.baz(y); " ,
" var x; x = this.foo(); this.bar(); var y; this.baz(x); " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases1d ( ) {
test (
" var x; x = this.foo(); this.bar(); var y; y = x; this.baz(y); " ,
" var x; x = this.foo(); this.bar(); var y; x; this.baz(x); " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases2 ( ) {
test (
" var x = this.foo(); this.bar(); function f() { var y = x; this.baz(y); } " ,
" var x = this.foo(); this.bar(); function f() { var y; this.baz(x); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases2b ( ) {
test (
" var x = this.foo(); this.bar(); function f() { var y; y = x; this.baz(y); } " ,
" var x = this.foo(); this.bar(); function f() { var y; x; this.baz(x); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases2c ( ) {
test (
" var x; x = this.foo(); this.bar(); function f() { var y = x; this.baz(y); } " ,
" var x; x = this.foo(); this.bar(); function f() { var y = x; this.baz(x); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases2d ( ) {
test (
" var x; x = this.foo(); this.bar(); function f() { var y; y = x; this.baz(y); } " ,
" var x; x = this.foo(); this.bar(); function f() { this.baz(x); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_aliases_in_loop ( ) {
test (
concat! (
" function f() { " ,
" var x = extern(); " ,
" for (var i = 0; i < 5; i++) { " ,
" (function() { " ,
" var y = x; window.setTimeout(function() { extern(y); }, 0); " ,
" })(); " ,
" } " ,
" } "
) ,
concat! (
" function f() { " ,
" var x = extern(); " ,
" for (var i = 0; i < 5; i++) { " ,
" (function() { " ,
" window.setTimeout(function() { extern(x); }, 0); " ,
" })(); " ,
" } " ,
" } "
) ,
) ;
}
#[ test ]
fn test_no_inline_aliases_in_loop ( ) {
test_same ( concat! (
" function f() { " ,
" for (var i = 0; i < 5; i++) { " ,
" var x = extern(); " ,
" (function() { " ,
" var y = x; window.setTimeout(function() { extern(y); }, 0); " ,
" })(); " ,
" } " ,
" } "
) ) ;
}
#[ test ]
fn modifier_test_no_inline_aliases1 ( ) {
test (
" var x = this.foo(); this.bar(); var y = x; x = 3; this.baz(y); " ,
" var x = this.foo(); this.bar(); var y = x; x = 3; this.baz(y); " ,
) ;
}
#[ test ]
fn test_no_inline_aliases1b ( ) {
test_same ( " var x = this.foo(); this.bar(); var y; y = x; x = 3; this.baz(y); " ) ;
}
#[ test ]
fn test_no_inline_aliases2 ( ) {
test_same ( " var x = this.foo(); this.bar(); var y = x; y = 3; this.baz(y); " ) ;
}
#[ test ]
fn test_no_inline_aliases2b ( ) {
test_same ( " var x = this.foo(); this.bar(); var y; y = x; y = 3; this.baz(y); " ) ;
}
#[ test ]
fn test_no_inline_aliases3 ( ) {
test_same ( concat! (
" var x = this.foo(); this.bar(); " ,
" function f() { var y = x; g(); this.baz(y); } " ,
" function g() { x = 3; } "
) ) ;
}
#[ test ]
fn test_no_inline_aliases3b ( ) {
test_same ( concat! (
" var x = this.foo(); this.bar(); " ,
" function f() { var y; y = x; g(); this.baz(y); } " ,
" function g() { x = 3; } "
) ) ;
}
#[ test ]
fn test_no_inline_aliases4 ( ) {
test_same ( " var x = this.foo(); this.bar(); function f() { var y = x; y = 3; this.baz(y); } " ) ;
}
#[ test ]
fn test_no_inline_aliases4b ( ) {
test_same (
" var x = this.foo(); this.bar(); function f() { var y; y = x; y = 3; this.baz(y); } " ,
) ;
}
#[ test ]
fn test_no_inline_aliases5 ( ) {
test_same ( " var x = this.foo(); this.bar(); var y = x; this.bing(); this.baz(y); x = 3; " ) ;
}
#[ test ]
fn test_no_inline_aliases5b ( ) {
test_same ( " var x = this.foo(); this.bar(); var y; y = x; this.bing(); this.baz(y); x = 3; " ) ;
}
#[ test ]
fn test_no_inline_aliases6 ( ) {
test_same ( " var x = this.foo(); this.bar(); var y = x; this.bing(); this.baz(y); y = 3; " ) ;
}
#[ test ]
fn test_no_inline_aliases6b ( ) {
test_same ( " var x = this.foo(); this.bar(); var y; y = x; this.bing(); this.baz(y); y = 3; " ) ;
}
#[ test ]
fn test_no_inline_aliases7 ( ) {
test_same ( concat! (
" var x = this.foo(); this.bar(); " ,
" function f() { var y = x; this.bing(); this.baz(y); x = 3; } "
) ) ;
}
#[ test ]
fn test_no_inline_aliases7b ( ) {
test_same ( concat! (
" var x = this.foo(); this.bar(); " ,
" function f() { var y; y = x; this.bing(); this.baz(y); x = 3; } "
) ) ;
}
#[ test ]
fn test_no_inline_aliases8 ( ) {
test_same ( " var x = this.foo(); this.bar(); function f() { var y = x; this.baz(y); y = 3; } " ) ;
}
#[ test ]
fn test_no_inline_aliases8b ( ) {
test_same (
" var x = this.foo(); this.bar(); function f() { var y; y = x; this.baz(y); y = 3; } " ,
) ;
}
#[ test ]
fn test_inline_parameter_alias1 ( ) {
test (
" function f(x) { var y = x; g(); y;y; } " ,
" function f(x) { var y; g(); x;x; } " ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_parameter_alias2 ( ) {
test (
" function f(x) { var y; y = x; g(); y;y; } " ,
" function f(x) { x; g(); x;x; } " ,
) ;
}
#[ test ]
#[ ignore ]
fn orig_test_inline_function_alias1a ( ) {
test (
" function f(x) {} var y = f; g(); y();y(); " ,
" var y = function f(x) {}; g(); y();y(); " ,
) ;
}
#[ test ]
fn test_inline_function_alias1a ( ) {
test (
" function f(x) {} var y = f; g(); y();y(); " ,
" function f(x) {} var y; g(); f();f(); " ,
) ;
}
#[ test ]
fn test_inline_function_alias1b ( ) {
test (
" function f(x) {}; f;var y = f; g(); y();y(); " ,
" function f(x) {}; f; var y; g(); f();f(); " ,
) ;
}
#[ test ]
fn test_inline_function_alias2a ( ) {
test (
" function f(x) {} var y; y = f; g(); y();y(); " ,
" function f(x) {} var y; y = f; g(); f();f(); " ,
) ;
}
#[ test ]
fn test_inline_function_alias2b ( ) {
test (
" function f(x) {}; f; var y; y = f; g(); y();y(); " ,
" function f(x) {}; f; var y; y = f; g(); f();f(); " ,
) ;
}
#[ test ]
fn test_inline_switch_var ( ) {
test ( " var x = y; switch (x) {} " , " var x; switch (y) {} " ) ;
}
#[ test ]
fn test_inline_switch_let ( ) {
test ( " let x = y; switch (x) {} " , " let x; switch (y) {} " ) ;
}
// Successfully inlines 'values' and 'e'
#[ test ]
#[ ignore ]
fn test_inline_into_for_loop1 ( ) {
test (
concat! (
" function calculate_hashCode() { " ,
" var values = [1, 2, 3, 4, 5]; " ,
" var hashCode = 1; " ,
" for (var $array = values, i = 0; i < $array.length; i++) { " ,
" var e = $array[i]; " ,
" hashCode = 31 * hashCode + calculate_hashCode(e); " ,
" } " ,
" return hashCode; " ,
" } " ,
) ,
concat! (
" function calculate_hashCode() { " ,
" var hashCode = 1; " ,
" var $array = [1, 2, 3, 4, 5]; " ,
" var i = 0; " ,
" for (; i < $array.length; i++) { " ,
" hashCode = 31 * hashCode + calculate_hashCode($array[i]); " ,
" } " ,
" return hashCode; " ,
" } " ,
) ,
) ;
}
// Inlines 'e' but fails to inline 'values'
// TODO(tbreisacher): Investigate and see if we can improve this.
#[ test ]
fn test_inline_into_for_loop2 ( ) {
test (
concat! (
" function calculate_hashCode() { " ,
" let values = [1, 2, 3, 4, 5]; " ,
" let hashCode = 1; " ,
" for (let $array = values, i = 0; i < $array.length; i++) { " ,
" let e = $array[i]; " ,
" hashCode = 31 * hashCode + calculate_hashCode(e); " ,
" } " ,
" return hashCode; " ,
" } " ,
) ,
concat! (
" function calculate_hashCode() { " ,
" let values = [1, 2, 3, 4, 5]; " ,
" let hashCode = 1; " ,
" for (let $array = values, i = 0; i < $array.length; i++) { " ,
" let e = $array[i]; " ,
" hashCode = 31 * hashCode + calculate_hashCode(e); " ,
" } " ,
" return hashCode; " ,
" } " ,
) ,
) ;
}
// This used to be inlined, but regressed when we switched to the ES6 scope
// creator.
#[ test ]
fn test_no_inline_catch_alias_var1 ( ) {
test_same ( concat! (
" try { " ,
" } catch (e) { " ,
" var y = e; " ,
" g(); " ,
" y;y; " ,
" } " ,
) ) ;
}
// This used to be inlined, but regressed when we switched to the ES6 scope
// creator.
#[ test ]
fn test_no_inline_catch_alias_var2 ( ) {
test_same ( concat! (
" try { " ,
" } catch (e) { " ,
" var y; y = e; " ,
" g(); " ,
" y;y; " ,
" } " ,
) ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_catch_alias_let1 ( ) {
test (
concat! (
" try { " ,
" } catch (e) { " ,
" let y = e; " ,
" g(); " ,
" y;y; " ,
" } " ,
) ,
concat! ( " try { " , " } catch (e) { " , " g(); " , " e;e; " , " } " ) ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_catch_alias_let2 ( ) {
test (
concat! (
" try { " ,
" } catch (e) { " ,
" let y; y = e; " ,
" g(); " ,
" y;y; " ,
" } " ,
) ,
concat! ( " try { " , " } catch (e) { " , " e; " , " g(); " , " e;e; " , " } " ) ,
) ;
}
#[ test ]
#[ ignore ]
fn test_inline_this ( ) {
test (
concat! (
" /** @constructor */ " ,
" function C() {} " ,
" " ,
" C.prototype.m = function() { " ,
" var self = this; " ,
" if (true) { " ,
" alert(self); " ,
" } " ,
" }; " ,
) ,
concat! (
" (/** @constructor */ " ,
" function C() {}).prototype.m = function() { " ,
" if (true) { " ,
" alert(this); " ,
" } " ,
" }; " ,
) ,
) ;
}
#[ test ]
fn test_var_in_block1 ( ) {
test (
" function f(x) { if (true) {var y = x; y; y;} } " ,
" function f(x) { if (true) {var y; x; x;} } " ,
) ;
}
#[ test ]
fn test_var_in_block2 ( ) {
test (
" function f(x) { switch (0) { case 0: { var y = x; y; y; } } } " ,
" function f(x) { switch (0) { case 0: { var y; x; x; } } } " ,
) ;
}
#[ test ]
fn test_inline_undefined1 ( ) {
test ( " var x; x; " , " var x; void 0; " ) ;
}
#[ test ]
fn test_inline_undefined2 ( ) {
test_same ( " var x; x++; " ) ;
}
#[ test ]
fn test_inline_undefined3 ( ) {
test_same ( " var x; var x; " ) ;
}
#[ test ]
fn test_inline_undefined4 ( ) {
test ( " var x; x; x; " , " var x; void 0; void 0; " ) ;
}
#[ test ]
fn test_inline_undefined5 ( ) {
test_same ( " var x; for(x in a) {} " ) ;
}
#[ test ]
fn test_issue90 ( ) {
test ( " var x; x && alert(1) " , " var x; (void 0) && alert(1) " ) ;
}
#[ test ]
#[ ignore ]
fn test_this_alias ( ) {
test (
" function f() { var a = this; a.y(); a.z(); } " ,
" function f() { this.y(); this.z(); } " ,
) ;
}
#[ test ]
fn test_this_escaped_alias ( ) {
test_same ( " function f() { var a = this; var g = function() { a.y(); }; a.z(); } " ) ;
}
#[ test ]
#[ ignore ]
fn test_inline_named_function ( ) {
test ( " function f() {} f(); " , " (function f(){})() " ) ;
}
#[ test ]
fn test_issue378_modified_arguments1 ( ) {
test_same ( concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" arguments[0] = this; \n " ,
" f.apply(this, arguments); \n " ,
" } "
) ) ;
}
#[ test ]
fn test_issue378_modified_arguments2 ( ) {
test_same ( concat! (
" function g(callback) { \n " ,
" /** @const */ \n " ,
" var f = callback; \n " ,
" arguments[0] = this; \n " ,
" f.apply(this, arguments); \n " ,
" } "
) ) ;
}
#[ test ]
fn test_issue378_escaped_arguments1 ( ) {
test_same ( concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" h(arguments,this); \n " ,
" f.apply(this, arguments); \n " ,
" } \n " ,
" function h(a,b) { \n " ,
" a[0] = b; " ,
" } "
) ) ;
}
#[ test ]
fn test_issue378_escaped_arguments2 ( ) {
test_same ( concat! (
" function g(callback) { \n " ,
" /** @const */ \n " ,
" var f = callback; \n " ,
" h(arguments,this); \n " ,
" f.apply(this); \n " ,
" } \n " ,
" function h(a,b) { \n " ,
" a[0] = b; " ,
" } "
) ) ;
}
#[ test ]
#[ ignore ] // We just give up optimization when arguments is used
fn test_issue378_escaped_arguments3 ( ) {
test (
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" f.apply(this, arguments); \n " ,
" } \n "
) ,
" function g(callback) { \n callback.apply(this, arguments); \n } \n " ,
) ;
}
#[ test ]
fn test_issue378_escaped_arguments4 ( ) {
test_same ( concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" h(arguments[0],this); \n " ,
" f.apply(this, arguments); \n " ,
" } \n " ,
" function h(a,b) { \n " ,
" a[0] = b; " ,
" } "
) ) ;
}
#[ test ]
#[ ignore ] // We just give up optimization when arguments is used
fn test_issue378_arguments_read1 ( ) {
test (
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" var g = arguments[0]; \n " ,
" f.apply(this, arguments); \n " ,
" } "
) ,
concat! (
" function g(callback) { \n " ,
" var g = arguments[0]; \n " ,
" callback.apply(this, arguments); \n " ,
" } "
) ,
) ;
}
#[ test ]
#[ ignore ] // We just give up optimization when arguments is used
fn test_issue378_arguments_read2 ( ) {
test (
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" h(arguments[0],this); \n " ,
" f.apply(this, arguments[0]); \n " ,
" } \n " ,
" function h(a,b) { \n " ,
" a[0] = b; " ,
" } "
) ,
concat! (
" function g(callback) { \n " ,
" h(arguments[0],this); \n " ,
" callback.apply(this, arguments[0]); \n " ,
" } \n " ,
" function h(a,b) { \n " ,
" a[0] = b; " ,
" } "
) ,
) ;
}
#[ test ]
#[ ignore ] // We just give up optimization when arguments is used
fn test_arguments_modified_in_outer_function ( ) {
test (
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" arguments[0] = this; \n " ,
" f.apply(this, arguments); \n " ,
" function inner(callback) { " ,
" var x = callback; \n " ,
" x.apply(this); \n " ,
" } " ,
" } "
) ,
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" arguments[0] = this; \n " ,
" f.apply(this, arguments); \n " ,
" function inner(callback) { " ,
" callback.apply(this); \n " ,
" } " ,
" } "
) ,
) ;
}
#[ test ]
#[ ignore ] // We just give up optimization when arguments is used
fn test_arguments_modified_in_inner_function ( ) {
test (
concat! (
" function g(callback) { \n " ,
" var f = callback; \n " ,
" f.apply(this, arguments); \n " ,
" function inner(callback) { " ,
" var x = callback; \n " ,
" arguments[0] = this; \n " ,
" x.apply(this); \n " ,
" } " ,
" } "
) ,
concat! (
" function g(callback) { \n " ,
" callback.apply(this, arguments); \n " ,
" function inner(callback1) { " ,
" var x = callback1; \n " ,
" arguments[0] = this; \n " ,
" x.apply(this); \n " ,
" } " ,
" } "
) ,
) ;
}
#[ test ]
fn test_bug6598844 ( ) {
test_same ( concat! (
" function F() { this.a = 0; } " ,
" F.prototype.inc = function() { this.a++; return 10; }; " ,
" F.prototype.bar = function() { var x = this.inc(); this.a += x; }; "
) ) ;
}
#[ test ]
fn test_external_issue1053 ( ) {
test_same ( " var u; function f() { u = Random(); var x = u; f(); alert(x===u)} " ) ;
}
#[ test ]
#[ ignore ]
fn test_hoisted_function1 ( ) {
test (
" var x = 1; function f() { return x; } " ,
" var x; function f() { return 1; } " ,
) ;
}
#[ test ]
fn test_hoisted_function2 ( ) {
test_same ( concat! (
" var impl_0; " ,
" b(a()); " ,
" function a() { impl_0 = {}; } " ,
" function b() { window['f'] = impl_0; } "
) ) ;
}
#[ test ]
fn test_hoisted_function3 ( ) {
test_same ( " var impl_0; b(); impl_0 = 1; function b() { window['f'] = impl_0; } " ) ;
}
#[ test ]
#[ ignore ]
fn test_hoisted_function4 ( ) {
test (
" var impl_0; impl_0 = 1; b(); function b() { window['f'] = impl_0; } " ,
" var impl_0; 1; b(); function b() { window['f'] = 1; } " ,
) ;
}
#[ test ]
fn test_hoisted_function5 ( ) {
test_same ( " a(); var debug = 1; function b() { return debug; } function a() { return b(); } " ) ;
}
#[ test ]
#[ ignore ]
fn test_hoisted_function6 ( ) {
test (
concat! (
" var debug = 1; " ,
" a(); " ,
" function b() { return debug; } " ,
" function a() { return b(); } "
) ,
" var debug; a(); function b() { return 1; } function a() { return b(); } " ,
) ;
}
#[ test ]
#[ ignore ]
fn orig_test_issue354 ( ) {
test (
concat! (
" var enabled = true; " ,
" function Widget() {} " ,
" Widget.prototype = { " ,
" frob: function() { " ,
" search(); " ,
" } " ,
" }; " ,
" function search() { " ,
" if (enabled) " ,
" alert(1); " ,
" else " ,
" alert(2); " ,
" } " ,
" window.foo = new Widget(); " ,
" window.bar = search; "
) ,
concat! (
" var enabled; " ,
" function Widget() {} " ,
" Widget.prototype = { " ,
" frob: function() { " ,
" search(); " ,
" } " ,
" }; " ,
" function search() { " ,
" if (true) " ,
" alert(1); " ,
" else " ,
" alert(2); " ,
" } " ,
" window.foo = new Widget(); " ,
" window.bar = search; "
) ,
) ;
}
#[ test ]
fn test_issue354 ( ) {
test (
concat! (
" var enabled = true; " ,
" function Widget() {} " ,
" Widget.prototype = { " ,
" frob: function() { " ,
" search(); " ,
" } " ,
" }; " ,
" function search() { " ,
" if (enabled) " ,
" alert(1); " ,
" else " ,
" alert(2); " ,
" } " ,
" window.foo = new Widget(); " ,
" window.bar = search; "
) ,
concat! (
" var enabled = true; " ,
" function Widget() {} " ,
" Widget.prototype = { " ,
" frob: function() { " ,
" search(); " ,
" } " ,
" }; " ,
" function search() { " ,
" if (enabled) " ,
" alert(1); " ,
" else " ,
" alert(2); " ,
" } " ,
" window.foo = new Widget(); " ,
" window.bar = search; "
) ,
) ;
}
// Test respect for scopes and blocks
#[ test ]
#[ ignore ]
fn orig_test_issue1177 ( ) {
test_same ( " function x_64(){var x_7;for(;;);var x_68=x_7=x_7;} " ) ;
test_same ( " function x_64(){var x_7;for(;;);var x_68=x_7=x_7++;} " ) ;
test_same ( " function x_64(){var x_7;for(;;);var x_68=x_7=x_7*2;} " ) ;
}
// GitHub issue #1234: https://github.com/google/closure-compiler/issues/1234
#[ test ]
fn test_switch_github_issue1234 ( ) {
test_same ( concat! (
" var x; " ,
" switch ('a') { " ,
" case 'a': " ,
" break; " ,
" default: " ,
" x = 1; " ,
" break; " ,
" } " ,
" use(x); " ,
) ) ;
}
#[ test ]
fn test_let_const ( ) {
test (
concat! (
" function f(x) { " ,
" if (true) { " ,
" let y = x; y; y; " ,
" } " ,
" } " ,
) ,
concat! (
" function f(x) { " ,
" if (true) { " ,
" let y; " ,
" x; x; " ,
" } " ,
" } "
) ,
) ;
test (
concat! (
" function f(x) { " ,
" if (true) { " ,
" const y = x; y; y; " ,
" } " ,
" } " ,
) ,
concat! (
" function f(x) { " ,
" if (true) { " ,
" const y = x; " ,
" x; x; " ,
" } " ,
" } "
) ,
) ;
test (
concat! (
" function f(x) { " ,
" let y; " ,
" { " ,
" let y = x; y; " ,
" } " ,
" } " ,
) ,
concat! (
" function f(x) { " ,
" let y; " ,
2021-09-01 16:11:55 +03:00
" { let y; " ,
2020-02-13 05:45:14 +03:00
" x; " ,
" } " ,
" } "
) ,
) ;
test (
concat! (
" function f(x) { " ,
" let y = x; y; const g = 2; " ,
" { " ,
" const g = 3; let y = g; y; " ,
" } " ,
" } " ,
) ,
concat! (
" function f(x) { " ,
" let y; " ,
" x; const g = 2; " ,
2021-09-01 16:11:55 +03:00
" { const g = 3; let y; 3;} " ,
2020-02-13 05:45:14 +03:00
" } "
) ,
) ;
}
#[ test ]
#[ ignore ]
fn test_generators ( ) {
test (
concat! ( " function* f() { " , " let x = 1; " , " yield x; " , " } " ) ,
concat! ( " function* f() { " , " let x; " , " yield 1; " , " } " ) ,
) ;
test (
concat! ( " function* f(x) { " , " let y = x++ " , " yield y; " , " } " ) ,
concat! ( " function* f(x) { " , " yield x++; " , " } " ) ,
) ;
}
#[ test ]
fn test_template_strings ( ) {
test (
" var name = 'Foo'; `Hello ${name}` " ,
" var name;`Hello ${'Foo'}` " ,
) ;
test (
" var name = 'Foo'; var foo = name; `Hello ${foo}` " ,
" var name;
var foo ; ` Hello $ { ' Foo ' } ` " ,
) ;
test ( " var age = 3; `Age: ${age}` " , " var age; `Age: ${3}` " ) ;
}
#[ test ]
#[ ignore ]
fn test_tagged_template_literals ( ) {
test (
concat! (
" var name = 'Foo'; " ,
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${name} ${3}`; " ,
) ,
concat! (
" var output = function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" }`My name is ${'Foo'} ${3}`; " ,
) ,
) ;
test (
concat! (
" var name = 'Foo'; " ,
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${name} ${3}`; " ,
" output = myTag`My name is ${name} ${2}`; " ,
) ,
concat! (
" function myTag(strings, nameExp, numExp) { " ,
" var modStr; " ,
" if (numExp > 2) { " ,
" modStr = nameExp + 'Bar' " ,
" } else { " ,
" modStr = nameExp + 'BarBar' " ,
" } " ,
" } " ,
" var output = myTag`My name is ${'Foo'} ${3}`; " ,
" output = myTag`My name is ${'Foo'} ${2}`; " ,
) ,
) ;
}
2020-10-11 18:36:44 +03:00
test! (
Syntax ::Typescript ( TsConfig {
decorators : true ,
.. Default ::default ( )
} ) ,
2022-03-10 10:13:58 +03:00
| t | {
2022-04-26 10:38:50 +03:00
let unresolved_mark = Mark ::new ( ) ;
let top_level_mark = Mark ::fresh ( Mark ::root ( ) ) ;
2021-12-04 05:35:16 +03:00
chain! (
2022-04-26 10:38:50 +03:00
resolver ( unresolved_mark , top_level_mark , false ) ,
simple_strip ( top_level_mark ) ,
2022-03-10 10:13:58 +03:00
class_properties (
Some ( t . comments . clone ( ) ) ,
class_properties ::Config {
set_public_fields : true ,
.. Default ::default ( )
}
) ,
2021-12-04 05:35:16 +03:00
inlining ( Default ::default ( ) )
)
} ,
2020-10-11 18:36:44 +03:00
issue_1156_1 ,
"
export interface D {
resolve : any ;
reject : any ;
}
2021-11-07 14:46:12 +03:00
2020-10-11 18:36:44 +03:00
export function d ( ) : D {
let methods ;
const promise = new Promise ( ( resolve , reject ) = > {
methods = { resolve , reject } ;
} ) ;
return Object . assign ( promise , methods ) ;
}
" ,
"
export function d ( ) {
let methods ;
const promise = new Promise ( ( resolve , reject ) = > {
methods = {
resolve ,
reject
} ;
} ) ;
return Object . assign ( promise , methods ) ;
}
"
) ;
test! (
Syntax ::Typescript ( TsConfig {
decorators : true ,
.. Default ::default ( )
} ) ,
2022-03-10 10:13:58 +03:00
| t | {
2022-04-26 10:38:50 +03:00
let unresolved_mark = Mark ::new ( ) ;
let top_level_mark = Mark ::new ( ) ;
2021-12-04 05:35:16 +03:00
chain! (
2022-04-26 10:38:50 +03:00
resolver ( unresolved_mark , top_level_mark , false ) ,
simple_strip ( top_level_mark ) ,
2022-03-10 10:13:58 +03:00
class_properties (
Some ( t . comments . clone ( ) ) ,
class_properties ::Config {
set_public_fields : true ,
.. Default ::default ( )
}
) ,
2021-12-04 05:35:16 +03:00
inlining ( Default ::default ( ) )
)
} ,
2020-10-11 18:36:44 +03:00
issue_1156_2 ,
"
interface D {
resolve : any ;
reject : any ;
}
2021-11-07 14:46:12 +03:00
2020-10-11 18:36:44 +03:00
function d ( ) : D {
let methods ;
const promise = new Promise ( ( resolve , reject ) = > {
methods = { resolve , reject } ;
} ) ;
return Object . assign ( promise , methods ) ;
}
class A {
private s : D = d ( ) ;
2021-11-07 14:46:12 +03:00
2020-10-11 18:36:44 +03:00
a ( ) {
this . s . resolve ( ) ;
}
2021-11-07 14:46:12 +03:00
2020-10-11 18:36:44 +03:00
b ( ) {
this . s = d ( ) ;
}
}
2021-11-07 14:46:12 +03:00
2020-10-11 18:36:44 +03:00
new A ( ) ;
" ,
"
function d ( ) {
let methods ;
const promise = new Promise ( ( resolve , reject ) = > {
methods = {
resolve ,
reject
} ;
} ) ;
return Object . assign ( promise , methods ) ;
}
class A {
a ( ) {
this . s . resolve ( ) ;
}
b ( ) {
this . s = d ( ) ;
}
2021-03-21 16:31:35 +03:00
constructor ( ) {
this . s = d ( ) ;
}
2020-10-11 18:36:44 +03:00
}
new A ( ) ;
"
) ;
2020-10-30 08:49:02 +03:00
test! (
Syntax ::Typescript ( TsConfig {
decorators : true ,
.. Default ::default ( )
} ) ,
2021-12-04 05:35:16 +03:00
| _ | {
2022-04-26 10:38:50 +03:00
let unresolved_mark = Mark ::new ( ) ;
let top_level_mark = Mark ::new ( ) ;
2021-12-04 05:35:16 +03:00
chain! (
2022-04-26 10:38:50 +03:00
resolver ( unresolved_mark , top_level_mark , false ) ,
simple_strip ( top_level_mark ) ,
2021-12-04 05:35:16 +03:00
inlining ( Default ::default ( ) )
)
} ,
2020-10-30 08:49:02 +03:00
deno_8180_1 ,
r #"
var Status ;
( function ( Status ) {
Status [ Status [ " Continue " ] = 100 ] = " Continue " ;
Status [ Status [ " SwitchingProtocols " ] = 101 ] = " SwitchingProtocols " ;
} ) ( Status | | ( Status = { } ) ) ;
const STATUS_TEXT = new Map ( [
[
Status . Continue ,
" Continue "
] ,
[
Status . SwitchingProtocols ,
" Switching Protocols "
2021-11-07 14:46:12 +03:00
]
2020-10-30 08:49:02 +03:00
] ) ;
" #,
r #"
2021-12-03 19:55:27 +03:00
var Status ;
( function ( Status1 ) {
Status1 [ Status1 [ " Continue " ] = 100 ] = " Continue " ;
Status1 [ Status1 [ " SwitchingProtocols " ] = 101 ] = " SwitchingProtocols " ;
} ) ( Status | | ( Status = {
2020-10-30 08:49:02 +03:00
} ) ) ;
const STATUS_TEXT = new Map ( [
[
2021-12-03 19:55:27 +03:00
Status . Continue ,
2020-10-30 08:49:02 +03:00
" Continue "
] ,
[
2021-12-03 19:55:27 +03:00
Status . SwitchingProtocols ,
2020-10-30 08:49:02 +03:00
" Switching Protocols "
]
2021-11-07 14:46:12 +03:00
] ) ;
2020-10-30 08:49:02 +03:00
" #
) ;
test! (
Syntax ::Typescript ( TsConfig {
decorators : true ,
.. Default ::default ( )
} ) ,
2021-12-04 05:35:16 +03:00
| _ | {
2022-04-26 10:38:50 +03:00
let unresolved_mark = Mark ::new ( ) ;
let top_level_mark = Mark ::new ( ) ;
2021-12-04 05:35:16 +03:00
chain! (
2022-04-26 10:38:50 +03:00
resolver ( unresolved_mark , top_level_mark , false ) ,
simple_strip ( top_level_mark ) ,
2021-12-04 05:35:16 +03:00
inlining ( Default ::default ( ) )
)
} ,
2020-10-30 08:49:02 +03:00
deno_8189_1 ,
"
let A , I = null ;
function g ( ) {
return null ! = = I & & I . buffer = = = A . memory . buffer | | ( I = new \
Uint8Array ( A . memory . buffer ) ) , I
}
" ,
"
let A , I = null ;
function g ( ) {
return null ! = = I & & I . buffer = = = A . memory . buffer | | ( I = new \
Uint8Array ( A . memory . buffer ) ) , I ;
}
"
) ;