swc/ecmascript/transforms/compat/tests/es2015_template_literals.rs

1001 lines
17 KiB
Rust
Raw Normal View History

2019-12-09 15:02:51 +03:00
use swc_ecma_parser::Syntax;
use swc_ecma_transforms_compat::es2015::template_literal;
use swc_ecma_transforms_testing::test;
use swc_ecma_transforms_testing::test_exec;
2020-07-23 20:18:22 +03:00
use swc_ecma_visit::Fold;
2019-12-09 15:02:51 +03:00
fn syntax() -> Syntax {
Default::default()
}
2020-07-23 20:18:22 +03:00
fn tr(_: ()) -> impl Fold {
template_literal()
2019-12-09 15:02:51 +03:00
}
2019-02-18 16:31:50 +03:00
test_exec!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
2019-02-18 16:31:50 +03:00
issue_231,
"const truthy = 'a=b';
const foo = `http://example.com/foo/bar${truthy && '?'}${truthy}`;
expect(foo).toBe('http://example.com/foo/bar?a=b');\
"
2019-02-18 16:31:50 +03:00
);
test_exec!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
issue_388,
"
'use strict';
const write = (text) => {
console.log(text)
}
write(1)
write('2')
write`3`"
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
escape_quotes,
r#"var t = `'${foo}' "${bar}"`;"#,
2019-12-09 15:02:51 +03:00
r#"var t = "'".concat(foo, '\' "').concat(bar, '"');"#,
ok_if_code_eq
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
multiple,
r#"var foo = `test ${foo} ${bar}`;"#,
2019-12-09 15:02:51 +03:00
r#"var foo = 'test '.concat(foo, ' ').concat(bar);"#
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
none,
r#"var foo = `test`;"#,
r#"var foo = "test";"#
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
only,
r#"var foo = `${test}`;"#,
r#"var foo = ''.concat(test);"#
);
test_exec!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
order,
r#"
const calls = [];
`
${
(calls.push(1), {
[Symbol.toPrimitive](){
calls.push(2);
return 'foo';
}
})
}
${
(calls.push(3), {
[Symbol.toPrimitive](){
calls.push(4);
return 'bar';
}
})
}
`;
expect(calls).toEqual([1, 2, 3, 4]);"#
);
test_exec!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
order2,
r#"const calls = [];
`
${{
[Symbol.toPrimitive]() {
calls.push(1);
return "foo";
}
}}
${1 +
{
valueOf() {
calls.push(2);
return 2;
}
}}
`;
expect(calls).toEqual([1, 2]);"#
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
single,
r#"var foo = `test ${foo}`;"#,
r#"var foo = 'test '.concat(foo);"#
);
test!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
statement,
r#"var foo = `test ${foo + bar}`;"#,
r#"var foo = 'test '.concat(foo + bar);"#,
ok_if_code_eq
);
test_exec!(
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
symbol,
r#"const fn = () => `${Symbol()}`;
expect(fn).toThrow(TypeError);"#
);
test!(
2019-12-09 15:02:51 +03:00
// TODO: Fix parser
ignore,
syntax(),
|_| tr(Default::default()),
template_revision,
r#"tag`\unicode and \u{55}`;
tag`\01`;
tag`\xg${0}right`;
tag`left${0}\xg`;
tag`left${0}\xg${1}right`;
tag`left${0}\u000g${1}right`;
tag`left${0}\u{-0}${1}right`;
function a() {
var undefined = 4;
tag`\01`;
}"#,
r#"
2019-12-09 15:02:51 +03:00
function _templateObject8() {
const data = _taggedTemplateLiteral([void 0], ["\\01"]);
_templateObject8 = function () {
return data;
2019-12-09 15:02:51 +03:00
};
return data;
}
2019-12-09 15:02:51 +03:00
function _templateObject7() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\u{-0}", "right"]);
_templateObject7 = function () {
return data;
2019-12-09 15:02:51 +03:00
};
return data;
}
2019-12-09 15:02:51 +03:00
function _templateObject6() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\u000g", "right"]);
_templateObject6 = function () {
return data;
};
return data;
}
function _templateObject5() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\xg", "right"]);
_templateObject5 = function () {
return data;
};
return data;
}
function _templateObject4() {
const data = _taggedTemplateLiteral(["left", void 0], ["left", "\\xg"]);
_templateObject4 = function () {
return data;
};
return data;
}
function _templateObject3() {
const data = _taggedTemplateLiteral([void 0, "right"], ["\\xg", "right"]);
_templateObject3 = function () {
return data;
};
return data;
}
function _templateObject2() {
2019-12-09 15:02:51 +03:00
const data = _taggedTemplateLiteral([void 0], ["\\01"]);
_templateObject2 = function () {
return data;
2019-12-09 15:02:51 +03:00
};
return data;
}
2019-12-09 15:02:51 +03:00
function _templateObject() {
const data = _taggedTemplateLiteral([void 0], ["\\unicode and \\u{55}"]);
_templateObject = function () {
return data;
};
return data;
}
tag(_templateObject());
tag(_templateObject2());
tag(_templateObject3(), 0);
tag(_templateObject4(), 0);
tag(_templateObject5(), 0, 1);
tag(_templateObject6(), 0, 1);
tag(_templateObject7(), 0, 1);
function a() {
var undefined = 4;
tag(_templateObject8());
}"#
);
// default_order_exec
test_exec!(
syntax(),
|_| tr(Default::default()),
default_order_exec,
r#"
const calls = [];
`
${
(calls.push(1), {
[Symbol.toPrimitive](){
calls.push(2);
return 'foo';
}
})
}
${
(calls.push(3), {
[Symbol.toPrimitive](){
calls.push(4);
return 'bar';
}
})
}
`;
expect(calls).toEqual([1, 2, 3, 4]);
"#
);
// default_only
test!(
syntax(),
|_| tr(Default::default()),
default_only,
r#"
var foo = `${test}`;
"#,
r#"
var foo = "".concat(test);
"#
);
// default_single
test!(
syntax(),
|_| tr(Default::default()),
default_single,
r#"
var foo = `test ${foo}`;
"#,
r#"
var foo = "test ".concat(foo);
"#
);
// default_statement
test!(
syntax(),
|_| tr(Default::default()),
default_statement,
r#"
var foo = `test ${foo + bar}`;
"#,
r#"
var foo = "test ".concat(foo + bar);
"#
);
// default_expression_first
test!(
syntax(),
|_| tr(Default::default()),
default_expression_first,
r#"
var foo = 5;
var bar = 10;
var baz = 15;
var example = `${"a"}`;
var example2 = `${1}`;
var example3 = 1 + `${foo}${bar}${baz}`;
var example4 = 1 + `${foo}bar${baz}`;
var example5 = `${""}`;
"#,
r#"
var foo = 5;
var bar = 10;
var baz = 15;
var example = "a";
var example2 = "".concat(1);
var example3 = 1 + "".concat(foo).concat(bar).concat(baz);
var example4 = 1 + "".concat(foo, "bar").concat(baz);
var example5 = "";
"#
);
// default_literals
test!(
syntax(),
|_| tr(Default::default()),
default_literals,
r#"
var foo = `${1}${f}oo${true}${b}ar${0}${baz}`;
"#,
r#"
var foo = ''.concat(1).concat(f, 'oo', true).concat(b, 'ar', 0).concat(baz);
"#
);
// default_multiline
test!(
syntax(),
|_| tr(Default::default()),
default_multiline,
r#"
var o = `wow
this is
actually multiline!`;
"#,
r#"
var o = "wow\nthis is\nactually multiline!";
"#,
ok_if_code_eq
);
2019-12-09 15:02:51 +03:00
// default_template_revision
test!(
2019-12-09 15:02:51 +03:00
// TODO: Improve parser
ignore,
2019-12-09 15:02:51 +03:00
syntax(),
|_| tr(Default::default()),
default_template_revision,
r#"
tag`\unicode and \u{55}`;
tag`\01`;
tag`\xg${0}right`;
tag`left${0}\xg`;
tag`left${0}\xg${1}right`;
tag`left${0}\u000g${1}right`;
tag`left${0}\u{-0}${1}right`;
2019-12-09 15:02:51 +03:00
function a() {
var undefined = 4;
tag`\01`;
2019-12-09 15:02:51 +03:00
}
"#,
r#"
function _templateObject8() {
const data = _taggedTemplateLiteral([void 0], ["\\01"]);
_templateObject8 = function () {
return data;
};
return data;
}
function _templateObject7() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\u{-0}", "right"]);
_templateObject7 = function () {
return data;
};
return data;
}
function _templateObject6() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\u000g", "right"]);
_templateObject6 = function () {
return data;
};
return data;
}
function _templateObject5() {
const data = _taggedTemplateLiteral(["left", void 0, "right"], ["left", "\\xg", "right"]);
_templateObject5 = function () {
return data;
};
return data;
}
function _templateObject4() {
const data = _taggedTemplateLiteral(["left", void 0], ["left", "\\xg"]);
_templateObject4 = function () {
return data;
};
return data;
}
function _templateObject3() {
const data = _taggedTemplateLiteral([void 0, "right"], ["\\xg", "right"]);
_templateObject3 = function () {
return data;
};
return data;
}
function _templateObject2() {
const data = _taggedTemplateLiteral([void 0], ["\\01"]);
_templateObject2 = function () {
return data;
};
return data;
}
function _templateObject() {
const data = _taggedTemplateLiteral([void 0], ["\\unicode and \\u{55}"]);
_templateObject = function () {
return data;
};
return data;
}
2019-12-09 15:02:51 +03:00
function _taggedTemplateLiteral(strings, raw) { if (!raw) { raw = strings.slice(0); } return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } })); }
tag(_templateObject());
tag(_templateObject2());
tag(_templateObject3(), 0);
tag(_templateObject4(), 0);
tag(_templateObject5(), 0, 1);
tag(_templateObject6(), 0, 1);
tag(_templateObject7(), 0, 1);
function a() {
var undefined = 4;
tag(_templateObject8());
2019-12-09 15:02:51 +03:00
}
"#
);
// default_order2_exec
test_exec!(
syntax(),
|_| tr(Default::default()),
default_order2_exec,
r#"
const calls = [];
`
${{
[Symbol.toPrimitive]() {
calls.push(1);
return "foo";
}
}}
${1 +
{
valueOf() {
calls.push(2);
return 2;
}
}}
`;
expect(calls).toEqual([1, 2]);
"#
);
// default_cache_revision_exec
test_exec!(
syntax(),
|_| tr(Default::default()),
default_cache_revision_exec,
r#"
var tag = v => v;
function foo() {
return tag`some template`;
}
function bar() {
return tag`some template`;
}
expect(foo()).toBe(foo());
expect(foo()).toEqual(["some template"]);
expect(bar()).toBe(bar());
expect(bar()).toEqual(["some template"]);
expect(bar()).not.toBe(foo());
"#
);
// default_functions
test!(
syntax(),
|_| tr(Default::default()),
default_functions,
r#"
var foo = `test ${_.test(foo)} ${bar}`;
"#,
r#"
var foo = "test ".concat(_.test(foo), " ").concat(bar);
"#
);
// default_none
test!(
syntax(),
|_| tr(Default::default()),
default_none,
r#"
var foo = `test`;
"#,
r#"
var foo = "test";
"#
);
// default_symbol_exec
test_exec!(
syntax(),
|_| tr(Default::default()),
default_symbol_exec,
r#"
const fn = () => `${Symbol()}`;
expect(fn).toThrow(TypeError);
"#
);
// default_cache_revision
test!(
syntax(),
|_| tr(Default::default()),
default_cache_revision,
r#"
var tag = v => v;
function foo() {
return tag`some template`;
}
function bar() {
return tag`some template`;
}
expect(foo()).toBe(foo());
expect(foo()).toEqual(["some template"]);
expect(bar()).toBe(bar());
expect(bar()).toEqual(["some template"]);
expect(bar()).not.toBe(foo());
"#,
r#"
function _templateObject() {
const data = _taggedTemplateLiteral(["some template"]);
_templateObject = function () {
return data;
};
return data;
}
function _templateObject1() {
const data = _taggedTemplateLiteral(["some template"]);
_templateObject1 = function () {
return data;
};
return data;
}
var tag = v => v;
function foo() {
return tag(_templateObject());
}
function bar() {
return tag(_templateObject1());
}
expect(foo()).toBe(foo());
expect(foo()).toEqual(["some template"]);
expect(bar()).toBe(bar());
expect(bar()).toEqual(["some template"]);
expect(bar()).not.toBe(foo());
"#
);
// default_tag
test!(
syntax(),
|_| tr(Default::default()),
default_tag,
r#"
var foo = bar`wow\na${ 42 }b ${_.foobar()}`;
var bar = bar`wow\nab${ 42 } ${_.foobar()}`;
var bar = bar`wow\naB${ 42 } ${_.baz()}`;
"#,
r#"
function _templateObject() {
const data = _taggedTemplateLiteral(["wow\na", "b ", ""], ["wow\\na", "b ", ""]);
_templateObject = function () {
return data;
};
return data;
}
function _templateObject1() {
const data = _taggedTemplateLiteral(["wow\nab", " ", ""], ["wow\\nab", " ", ""]);
_templateObject1 = function () {
return data;
};
return data;
}
function _templateObject2() {
const data = _taggedTemplateLiteral(["wow\naB", " ", ""], ["wow\\naB", " ", ""]);
_templateObject2 = function () {
return data;
};
return data;
}
var foo = bar(_templateObject(), 42, _.foobar());
var bar = bar(_templateObject1(), 42, _.foobar());
var bar = bar(_templateObject2(), 42, _.baz());
"#
);
// default_simple_tag
test!(
syntax(),
|_| tr(Default::default()),
default_simple_tag,
r#"
var foo = tag`wow`;
var bar = tag`first${1}second`;
"#,
r#"
function _templateObject() {
const data = _taggedTemplateLiteral(["wow"]);
_templateObject = function () {
return data;
};
return data;
}
function _templateObject1() {
const data = _taggedTemplateLiteral(["first", "second"]);
_templateObject1 = function () {
return data;
};
return data;
}
var foo = tag(_templateObject());
var bar = tag(_templateObject1(), 1);
"#
);
test!(
syntax(),
|_| tr(Default::default()),
issue_598_1,
"
export function foo() {
console.log(i18n`Hello World`);
console.log(i18n`Nobody will ever see this.`);
}
",
"function _templateObject() {
const data = _taggedTemplateLiteral([
\"Hello World\"
]);
_templateObject = function() {
return data;
};
return data;
}
function _templateObject1() {
const data = _taggedTemplateLiteral([
\"Nobody will ever see this.\"
]);
_templateObject1 = function() {
return data;
};
return data;
}
export function foo() {
console.log(i18n(_templateObject()));
console.log(i18n(_templateObject1()));
}
"
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_01,
"`\"`",
r#""\"""#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_02,
"`\"\"`",
r#"
"\"\""
"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_03,
"`\"${foo}`",
r#"
"\"".concat(foo);
"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_04,
"`\"${foo}\"`",
r#"
"\"".concat(foo, "\"");
"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_05,
"`\"\"${foo}\"\"`",
r#"
"\"\"".concat(foo, "\"\"");
"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_06,
"\"``\"",
"\"``\"",
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_07,
r#"`The ${argumentName} has unexpected type of "`"#,
r#""The ".concat(argumentName, " has unexpected type of \"");"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_08,
r#"`". Expected argument to be an object with the following `"#,
r#""\". Expected argument to be an object with the following ";"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_09,
r#"`keys: "${reducerKeys.join('", "')}"`"#,
r#""keys: \"".concat(reducerKeys.join('\", \"'), "\"");"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
codegen_10,
r#"`The ${argumentName} has unexpected type of "` +
matchType +
`". Expected argument to be an object with the following ` +
`keys: "${reducerKeys.join('", "')}"`"#,
r#""The ".concat(argumentName, " has unexpected type of \"") + matchType + "\". Expected argument to be an object with the following " + "keys: \"".concat(reducerKeys.join('", "'), "\"")"#,
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
issue_1280,
"
const myVar = T`'Hello'`;
",
"
function _templateObject() {
const data = _taggedTemplateLiteral([
\"'Hello'\"
]);
_templateObject = function() {
return data;
};
return data;
}
const myVar = T(_templateObject());
",
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
issue_1488_1,
"
`\\``
",
"
'`'
"
);
test!(
syntax(),
|_| tr(Default::default()),
issue_1549_1,
"const a = `\r\n`;",
"const a = \"\\n\";",
ok_if_code_eq
);
test!(
syntax(),
|_| tr(Default::default()),
issue_1549_2,
"const a = \"\\r\\n\";",
"const a = \"\\r\\n\";"
);
test!(
syntax(),
|_| tr(Default::default()),
issue_1742_1,
"
function foo() {
return this;
}
foo`template`
",
"
function _templateObject() {
const data = _taggedTemplateLiteral([
'template'
]);
_templateObject = function() {
return data;
};
return data;
}
function foo() {
return this;
}
foo(_templateObject());
"
);
test_exec!(
syntax(),
|_| tr(Default::default()),
issue_1742_2,
"
const obj = {
foo() {
return this;
}
}
expect(typeof obj.foo`template`).toEqual('object')
"
);