swc/crates/swc_ecma_transforms_compat/tests/es2015_spread.rs

995 lines
15 KiB
Rust

use swc_common::{chain, Mark};
use swc_ecma_transforms_base::resolver;
use swc_ecma_transforms_compat::es2015::{block_scoping, parameters, spread};
use swc_ecma_transforms_testing::{test, test_exec};
use swc_ecma_visit::Fold;
fn syntax() -> ::swc_ecma_parser::Syntax {
Default::default()
}
fn tr() -> impl Fold {
let unresolved_mark = Mark::new();
let top_level_mark = Mark::new();
chain!(
resolver(unresolved_mark, top_level_mark, false),
parameters(Default::default(), unresolved_mark),
spread(Default::default())
)
}
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
issue_270,
"instance[name](...args);",
"var _instance;
(_instance = instance)[name].apply(_instance, _toConsumableArray(args));"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_call,
"ca(a, b, c, ...d, e)",
"ca.apply(void 0, [a, b, c].concat(_toConsumableArray(d), [e]));"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_call_multi_spread,
"ca(a, b, ...d, e, f, ...h)",
"ca.apply(void 0, [a, b].concat(_toConsumableArray(d), [e, f], _toConsumableArray(h)));"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_call_noop,
"ca(a, b, c, d, e)",
"ca(a, b, c, d, e);"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_array,
"[a, b, c, ...d, e]",
"[a, b, c].concat(_toConsumableArray(d), [e])"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_array_empty,
"[a,, b, c, ...d,,, e]",
"[a,, b, c].concat(_toConsumableArray(d), [,, e])"
);
test!(
::swc_ecma_parser::Syntax::default(),
|_| tr(),
custom_new_noop,
"new C(a, b, c, c, d, e)",
"new C(a, b, c, c, d, e);"
);
// this_context
test!(
syntax(),
|_| tr(),
this_context,
r#"
var obj = {
foo: function foo() {
this.bar(...arguments)
this.blah(...arguments)
}
}
"#,
r#"
var obj = {
foo: function foo() {
this.bar.apply(this, arguments);
this.blah.apply(this, arguments);
}
};
"#
);
// arguments_array
test!(
syntax(),
|_| tr(),
arguments_array,
r#"
function foo() {
return bar([...arguments]);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#,
r#"
function foo() {
return bar(Array.prototype.slice.call(arguments));
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#
);
// single_exec
test_exec!(
syntax(),
|_| tr(),
single_exec,
r#"
// test that toConsumableArray clones the array.
const arr = [];
const foo = () => arr;
const x = [...foo()];
expect(x).not.toBe(arr);
"#
);
// arguments_concat
test!(
syntax(),
|_| tr(),
arguments_concat,
r#"
function foo() {
return bar("test", ...arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#,
r#"
function foo() {
return bar.apply(void 0, ["test"].concat(Array.prototype.slice.call(arguments)));
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#
);
// contexted_method_call_super_multiple_args
test!(
syntax(),
|_| tr(),
contexted_method_call_super_multiple_args,
r#"
class Foo {
bar() {
super.bar(arg1, arg2, ...args);
}
}
"#,
r#"
class Foo {
bar() {
super.bar.apply(this, [arg1, arg2].concat(_toConsumableArray(args)));
}
}
"#
);
// array_literal_first
test!(
syntax(),
|_| tr(),
array_literal_first,
r#"
var lyrics = [...parts, "head", "and", "toes"];
"#,
r#"
var lyrics = _toConsumableArray(parts).concat(["head", "and", "toes"]);
"#
);
// regression_t6761
test!(
syntax(),
|_| tr(),
regression_t6761,
r#"
function fn(){}
var args = [1, 2, 3];
var obj = {obj: {fn}};
switch (true){
case true:
obj.obj.fn(...args);
break;
}
"#,
r#"
function fn() {}
var args = [1, 2, 3];
var obj = {
obj: {
fn
}
};
switch (true) {
case true:
var _obj;
(_obj = obj.obj).fn.apply(_obj, _toConsumableArray(args));
break;
}
"#
);
// method_call_middle
test!(
syntax(),
|_| tr(),
method_call_middle,
r#"
add(foo, ...numbers, bar);
"#,
r#"
add.apply(void 0, [foo].concat(_toConsumableArray(numbers), [bar]));
"#
);
// contexted_method_call_multiple_args
test!(
syntax(),
|_| tr(),
contexted_method_call_multiple_args,
r#"
foob.add(foo, bar, ...numbers);
foob.test.add(foo, bar, ...numbers);
"#,
r#"
var _foob, _test;
(_foob = foob).add.apply(_foob, [foo, bar].concat(_toConsumableArray(numbers)));
(_test = foob.test).add.apply(_test, [foo, bar].concat(_toConsumableArray(numbers)));
"#
);
// contexted_computed_method_call_multiple_args
test!(
syntax(),
|_| tr(),
contexted_computed_method_call_multiple_args,
r#"
obj[method](foo, bar, ...args);
"#,
r#"
var _obj;
(_obj = obj)[method].apply(_obj, [foo, bar].concat(_toConsumableArray(args)));
"#
);
// regression_6647
// method_call_multiple_args
test!(
syntax(),
|_| tr(),
method_call_multiple_args,
r#"
add(foo, bar, ...numbers);
"#,
r#"
add.apply(void 0, [foo, bar].concat(_toConsumableArray(numbers)));
"#
);
// array_literal_middle
test!(
syntax(),
|_| tr(),
array_literal_middle,
r#"
var a = [b, ...c, d];
"#,
r#"
var a = [b].concat(_toConsumableArray(c), [d]);
"#
);
// array_literal_with_hole
test!(
syntax(),
|_| tr(),
array_literal_with_hole,
r#"
var arr = [ 'a',, 'b', ...c ];
"#,
r#"
var arr = ['a',, 'b'].concat(_toConsumableArray(c));
"#
);
// regression_issue_8907
test!(
syntax(),
|_| tr(),
regression_issue_8907_modified,
r#"
const arr = [];
arr.concat = () => {
throw new Error('Should not be called');
};
const x = [...arr];
"#,
r#"
const arr = [];
arr.concat = () => {
throw new Error('Should not be called');
};
const x = _toConsumableArray(arr);
"#
);
// regression_issue_8907
test!(
// Cost is too high
ignore,
syntax(),
|_| tr(),
regression_issue_8907,
r#"
const arr = [];
arr.concat = () => {
throw new Error('Should not be called');
};
const x = [...arr];
"#,
r#"
const arr = [];
arr.concat = () => {
throw new Error('Should not be called');
};
const x = [].concat(arr);
"#
);
// method_call_multiple
test!(
syntax(),
|_| tr(),
method_call_multiple,
r#"
add(foo, ...numbers, bar, what, ...test);
"#,
r#"
add.apply(void 0, [foo].concat(_toConsumableArray(numbers), [bar, what], _toConsumableArray(test)));
"#
);
// arguments
test!(
syntax(),
|_| tr(),
arguments,
r#"
function foo() {
return bar(...arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#,
r#"
function foo() {
return bar.apply(void 0, arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#
);
// regression_issue_8907_exec
test_exec!(
syntax(),
|_| tr(),
regression_issue_8907_exec,
r#"
const arr = [];
arr.concat = () => {
throw new Error('Should not be called');
};
let x;
expect(() => {
x = [...arr];
}).not.toThrow();
expect(x).not.toBe(arr);
"#
);
// array_literal_multiple
test!(
syntax(),
|_| tr(),
array_literal_multiple,
r#"
var a = [b, ...c, d, e, ...f];
"#,
r#"
var a = [b].concat(_toConsumableArray(c), [d, e], _toConsumableArray(f));
"#
);
// arguments_array_exec
test_exec!(
syntax(),
|_| tr(),
arguments_array_exec,
r#"
// test that toConsumableArray clones the array.
function foo() {
const x = [...arguments];
expect(x).not.toBe(arguments);
}
foo(1,2);
"#
);
// array_literals
test!(
syntax(),
|_| tr(),
array_literals,
r#"
var lyrics = ["head", "and", "toes", ...parts];
"#,
r#"
var lyrics = ["head", "and", "toes"].concat(_toConsumableArray(parts));
"#
);
// regression
// spread_new_expression
test!(
syntax(),
|_| tr(),
spread_new_expression,
r#"
new Numbers(...nums);
new Numbers(1, ...nums);
"#,
r#"
_construct(Numbers, _toConsumableArray(nums));
_construct(Numbers, [1].concat(_toConsumableArray(nums)));
"#
);
// spread_array_literal_with_hole
test!(
syntax(),
|_| tr(),
spread_array_literal_with_hole,
r#"
var arr = [ 'a',, 'b', ...c ];
"#,
r#"
var arr = ['a',, 'b'].concat(_toConsumableArray(c));
"#
);
// spread_single
test_exec!(
syntax(),
|_| tr(),
spread_single_exec,
r#"
// test that toConsumableArray clones the array.
const arr = [];
const foo = () => arr;
const x = [...foo()];
expect(x).not.toBe(arr);
"#
);
// spread_contexted_method_call_multiple_args
test!(
syntax(),
|_| tr(),
spread_contexted_method_call_multiple_args,
r#"
foob.add(foo, bar, ...numbers);
foob.test.add(foo, bar, ...numbers);
"#,
r#"
var _foob, _test;
(_foob = foob).add.apply(_foob, [foo, bar].concat(_toConsumableArray(numbers)));
(_test = foob.test).add.apply(_test, [foo, bar].concat(_toConsumableArray(numbers)))
"#
);
// spread_method_call_array_literal
test!(
syntax(),
|_| tr(),
spread_method_call_array_literal,
r#"
f(...[1, 2, 3]);
"#,
r#"
f.apply(void 0, [1, 2, 3]);
"#
);
// spread_method_call_single_arg
test!(
syntax(),
|_| tr(),
spread_method_call_single_arg,
r#"
add(...numbers);
"#,
r#"
add.apply(void 0, _toConsumableArray(numbers));
"#
);
// spread_known_rest
test!(
// Cost is too high.
ignore,
syntax(),
|_| chain!(tr(), block_scoping()),
spread_known_rest,
r#"
function foo(...bar) {
return [...bar];
}
"#,
r#"
function foo() {
for (var _len = arguments.length, bar = new Array(_len), _key = 0; _key < _len; _key++) {
bar[_key] = arguments[_key];
}
return [].concat(bar);
}
"#
);
// spread_method_call_middle
test!(
syntax(),
|_| tr(),
spread_method_call_middle,
r#"
add(foo, ...numbers, bar);
"#,
r#"
add.apply(void 0, [foo].concat(_toConsumableArray(numbers), [bar]));
"#
);
// spread_method_call_first
test!(
syntax(),
|_| tr(),
spread_method_call_first,
r#"
add(...numbers, foo, bar);
"#,
r#"
add.apply(void 0, _toConsumableArray(numbers).concat([foo, bar]));
"#
);
// spread_contexted_method_call_super_single_arg
test!(
syntax(),
|_| tr(),
spread_contexted_method_call_super_single_arg,
r#"
class Foo {
bar() {
super.bar(...args);
}
}
"#,
r#"
class Foo {
bar() {
super.bar.apply(this, _toConsumableArray(args));
}
}
"#
);
// spread_contexted_method_call_single_arg
test!(
syntax(),
|_| tr(),
spread_contexted_method_call_single_arg,
r#"
foob.add(...numbers);
foob.test.add(...numbers);
"#,
r#"
var _foob, _test;
(_foob = foob).add.apply(_foob, _toConsumableArray(numbers));
(_test = foob.test).add.apply(_test, _toConsumableArray(numbers));
"#
);
// spread_array_literal_middle
test!(
syntax(),
|_| tr(),
spread_array_literal_middle,
r#"
var a = [b, ...c, d];
"#,
r#"
var a = [b].concat(_toConsumableArray(c), [d]);
"#
);
// spread_array_literals
test!(
syntax(),
|_| tr(),
spread_array_literals,
r#"
var lyrics = ["head", "and", "toes", ...parts];
"#,
r#"
var lyrics = ["head", "and", "toes"].concat(_toConsumableArray(parts));
"#
);
// regression_10416
test!(
syntax(),
|_| tr(),
regression_10416,
r#"
const E_ARR = [];
export default function () {
const someVar = E_ARR;
return [...someVar];
}
"#,
r#"
const E_ARR = [];
export default function () {
const someVar = E_ARR;
return _toConsumableArray(someVar);
}
"#
);
// spread_method_call_multiple
test!(
syntax(),
|_| tr(),
spread_method_call_multiple,
r#"
add(foo, ...numbers, bar, what, ...test);
"#,
r#"
add.apply(void 0, [foo].concat(_toConsumableArray(numbers), [bar, what], _toConsumableArray(test)));
"#
);
// spread_arguments
test!(
syntax(),
|_| tr(),
spread_arguments,
r#"
function foo() {
return bar(...arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#,
r#"
function foo() {
return bar.apply(void 0, arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#
);
// spread_contexted_method_call_super_multiple_args
test!(
syntax(),
|_| tr(),
spread_contexted_method_call_super_multiple_args,
r#"
class Foo {
bar() {
super.bar(arg1, arg2, ...args);
}
}
"#,
r#"
class Foo {
bar() {
super.bar.apply(this, [arg1, arg2].concat(_toConsumableArray(args)));
}
}
"#
);
// spread_contexted_computed_method_call_single_arg
test!(
syntax(),
|_| tr(),
spread_contexted_computed_method_call_single_arg,
r#"
obj[method](...args);
"#,
r#"
var _obj;
(_obj = obj)[method].apply(_obj, _toConsumableArray(args));
"#
);
// spread_arguments_concat
test!(
syntax(),
|_| tr(),
spread_arguments_concat,
r#"
function foo() {
return bar("test", ...arguments);
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#,
r#"
function foo() {
return bar.apply(void 0, ["test"].concat(Array.prototype.slice.call(arguments)));
}
function bar(one, two, three) {
return [one, two, three];
}
foo("foo", "bar");
"#
);
test!(
syntax(),
|_| tr(),
spread_string_literial,
"
String.raw({ raw: 'abcd' }, ...'___');
",
r#"
var _String;
(_String = String).raw.apply(_String, [
{
raw: 'abcd'
}
].concat(Array.from('___')));
"#
);
test!(
syntax(),
|_| tr(),
spread_string_literial_2,
"
f({ x: 0 }, ...[1, 2], [3], ...'456');
",
r#"
f.apply(void 0, [
{
x: 0
}
].concat(_toConsumableArray([
1,
2
]), [
[
3
]
], Array.from('456')));
"#
);
test!(
syntax(),
|_| tr(),
spread_literial,
r#"
f(1, ...[2, 3], ...[...[4, 5]], ...[6, ...[7]]);
f(1, ..."123", ...[..."456", ..."789"]);
"#,
r#"
f.apply(void 0, [
1
].concat(_toConsumableArray([
2,
3
]), _toConsumableArray(_toConsumableArray([
4,
5
])), _toConsumableArray([
6
].concat(_toConsumableArray([
7
])))));
f.apply(void 0, [
1
].concat(Array.from("123"), _toConsumableArray(Array.from("456").concat(Array.from("789")))));
"#
);
test!(
syntax(),
|_| tr(),
spread_literial_init_hole,
r#"
f(1, ...[2, , 3], ...[...[4, ,]]);
f(...[2, , 3], ...[...[4, ,]]);
"#,
"
f.apply(void 0, [
1
].concat(_toConsumableArray([
2,
,
3
]), _toConsumableArray(_toConsumableArray([
4,
,
]))));
f.apply(void 0, _toConsumableArray([
2,
,
3
]).concat(_toConsumableArray(_toConsumableArray([
4,
,
]))));
"
);