Vendor things
This commit is contained in:
parent
5deceec006
commit
977e3c17e5
19434 changed files with 10682014 additions and 0 deletions
104
third-party/vendor/swc_ecma_codegen/src/comments.rs
vendored
Normal file
104
third-party/vendor/swc_ecma_codegen/src/comments.rs
vendored
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
use swc_common::comments::CommentKind;
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! write_comments {
|
||||
($e:expr, $prefix_space:expr, $cmts:expr) => {{
|
||||
let cmts = match $cmts {
|
||||
Some(v) => v,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
for cmt in cmts.iter() {
|
||||
match cmt.kind {
|
||||
CommentKind::Line => {
|
||||
if $prefix_space && !$e.cfg.minify {
|
||||
$e.wr.write_comment(" ")?;
|
||||
}
|
||||
|
||||
srcmap!($e, cmt, true);
|
||||
|
||||
$e.wr.write_comment("//")?;
|
||||
$e.wr.write_comment(&cmt.text)?;
|
||||
|
||||
srcmap!($e, cmt, false);
|
||||
|
||||
$e.wr.write_line()?;
|
||||
}
|
||||
CommentKind::Block => {
|
||||
if $prefix_space && !$e.cfg.minify {
|
||||
$e.wr.write_comment(" ")?;
|
||||
}
|
||||
|
||||
srcmap!($e, cmt, true);
|
||||
|
||||
$e.wr.write_comment("/*")?;
|
||||
$e.wr.write_comment(&cmt.text)?;
|
||||
|
||||
{
|
||||
let hi = cmt.span_hi();
|
||||
if !hi.is_dummy() && hi.0 > 2 {
|
||||
$e.wr.add_srcmap(hi - swc_common::BytePos(2))?;
|
||||
}
|
||||
}
|
||||
$e.wr.write_comment("*/")?;
|
||||
|
||||
if !$e.cfg.minify {
|
||||
$e.wr.write_space()?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(());
|
||||
}};
|
||||
}
|
||||
|
||||
impl<'a, W, S: SourceMapper> Emitter<'a, W, S>
|
||||
where
|
||||
W: WriteJs,
|
||||
S: SourceMapperExt,
|
||||
{
|
||||
pub(super) fn emit_trailing_comments_of_pos(
|
||||
&mut self,
|
||||
pos: BytePos,
|
||||
prefix_space: bool,
|
||||
_is_hi: bool,
|
||||
) -> Result {
|
||||
if pos.is_dummy() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let comments = match self.comments {
|
||||
Some(ref comments) => comments,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
let cmts = comments.take_trailing(pos);
|
||||
|
||||
write_comments!(self, prefix_space, &cmts)
|
||||
}
|
||||
|
||||
pub(super) fn emit_leading_comments(&mut self, mut pos: BytePos, is_hi: bool) -> Result {
|
||||
if pos.is_dummy() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let comments = match self.comments {
|
||||
Some(ref comments) => comments,
|
||||
None => return Ok(()),
|
||||
};
|
||||
|
||||
if is_hi {
|
||||
pos = pos - BytePos(1)
|
||||
}
|
||||
|
||||
write_comments!(self, false, comments.take_leading(pos))
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(super) fn emit_leading_comments_of_span(&mut self, span: Span, is_hi: bool) -> Result {
|
||||
let pos = if is_hi { span.hi } else { span.lo };
|
||||
self.emit_leading_comments(pos, is_hi)
|
||||
}
|
||||
}
|
||||
46
third-party/vendor/swc_ecma_codegen/src/config.rs
vendored
Normal file
46
third-party/vendor/swc_ecma_codegen/src/config.rs
vendored
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
#[cfg(feature = "serde-impl")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use swc_ecma_ast::EsVersion;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[cfg_attr(feature = "serde-impl", derive(Serialize, Deserialize))]
|
||||
#[cfg_attr(feature = "serde-impl", serde(rename_all = "camelCase"))]
|
||||
pub struct Config {
|
||||
/// The target runtime environment.
|
||||
///
|
||||
/// This defaults to [EsVersion::latest] because it preserves input as much
|
||||
/// as possible.
|
||||
///
|
||||
/// Note: This does not verifies if output is valid for the target runtime.
|
||||
/// e.g. `const foo = 1;` with [EsVersion::Es3] will emitted as `const foo =
|
||||
/// 1` without verification.
|
||||
/// This is because it's not a concern of the code generator.
|
||||
#[cfg_attr(feature = "serde-impl", serde(default = "EsVersion::latest"))]
|
||||
pub target: EsVersion,
|
||||
|
||||
/// Forces the code generator to use only ascii characters.
|
||||
///
|
||||
/// This is useful for environments that do not support unicode.
|
||||
#[cfg_attr(feature = "serde-impl", serde(default))]
|
||||
pub ascii_only: bool,
|
||||
|
||||
#[cfg_attr(feature = "serde-impl", serde(default))]
|
||||
pub minify: bool,
|
||||
|
||||
/// If true, the code generator will emit the lastest semicolon.
|
||||
///
|
||||
/// Defaults to `false`.
|
||||
#[cfg_attr(feature = "serde-impl", serde(default))]
|
||||
pub omit_last_semi: bool,
|
||||
}
|
||||
|
||||
impl Default for Config {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
target: EsVersion::latest(),
|
||||
minify: false,
|
||||
ascii_only: false,
|
||||
omit_last_semi: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
211
third-party/vendor/swc_ecma_codegen/src/decl.rs
vendored
Normal file
211
third-party/vendor/swc_ecma_codegen/src/decl.rs
vendored
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
use swc_common::{SourceMapper, Spanned};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen_macros::emitter;
|
||||
|
||||
use super::{Emitter, Result};
|
||||
use crate::text_writer::WriteJs;
|
||||
|
||||
impl<'a, W, S: SourceMapper> Emitter<'a, W, S>
|
||||
where
|
||||
W: WriteJs,
|
||||
S: SourceMapperExt,
|
||||
{
|
||||
#[emitter]
|
||||
fn emit_decl(&mut self, node: &Decl) -> Result {
|
||||
match node {
|
||||
Decl::Class(ref n) => emit!(n),
|
||||
Decl::Fn(ref n) => emit!(n),
|
||||
|
||||
Decl::Var(ref n) => {
|
||||
self.emit_var_decl_inner(n)?;
|
||||
formatting_semi!();
|
||||
srcmap!(n, false);
|
||||
}
|
||||
Decl::Using(n) => emit!(n),
|
||||
Decl::TsEnum(ref n) => emit!(n),
|
||||
Decl::TsInterface(ref n) => emit!(n),
|
||||
Decl::TsModule(ref n) => emit!(n),
|
||||
Decl::TsTypeAlias(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_class_decl(&mut self, node: &ClassDecl) -> Result {
|
||||
self.emit_class_decl_inner(node, false)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_using_decl(&mut self, node: &UsingDecl) -> Result {
|
||||
self.emit_leading_comments_of_span(node.span(), false)?;
|
||||
|
||||
if node.is_await {
|
||||
keyword!("await");
|
||||
space!();
|
||||
}
|
||||
|
||||
keyword!("using");
|
||||
space!();
|
||||
|
||||
self.emit_list(
|
||||
node.span,
|
||||
Some(&node.decls),
|
||||
ListFormat::VariableDeclarationList,
|
||||
)?;
|
||||
}
|
||||
|
||||
pub(super) fn emit_class_decl_inner(
|
||||
&mut self,
|
||||
node: &ClassDecl,
|
||||
skip_decorators: bool,
|
||||
) -> Result {
|
||||
self.emit_leading_comments_of_span(node.span(), false)?;
|
||||
|
||||
srcmap!(self, node, true);
|
||||
|
||||
if node.declare {
|
||||
keyword!(self, "declare");
|
||||
space!(self);
|
||||
}
|
||||
|
||||
if !skip_decorators {
|
||||
for dec in &node.class.decorators {
|
||||
emit!(self, dec);
|
||||
}
|
||||
}
|
||||
|
||||
keyword!(self, "class");
|
||||
space!(self);
|
||||
emit!(self, node.ident);
|
||||
emit!(self, node.class.type_params);
|
||||
|
||||
self.emit_class_trailing(&node.class)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_fn_decl(&mut self, node: &FnDecl) -> Result {
|
||||
self.emit_leading_comments_of_span(node.span(), false)?;
|
||||
|
||||
self.wr.commit_pending_semi()?;
|
||||
|
||||
srcmap!(node, true);
|
||||
|
||||
if node.declare {
|
||||
keyword!("declare");
|
||||
space!();
|
||||
}
|
||||
|
||||
if node.function.is_async {
|
||||
keyword!("async");
|
||||
space!();
|
||||
}
|
||||
|
||||
keyword!("function");
|
||||
if node.function.is_generator {
|
||||
punct!("*");
|
||||
formatting_space!();
|
||||
} else {
|
||||
space!();
|
||||
}
|
||||
|
||||
emit!(node.ident);
|
||||
|
||||
self.emit_fn_trailing(&node.function)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_var_decl(&mut self, node: &VarDecl) -> Result {
|
||||
self.emit_var_decl_inner(node)?;
|
||||
}
|
||||
|
||||
fn emit_var_decl_inner(&mut self, node: &VarDecl) -> Result {
|
||||
self.emit_leading_comments_of_span(node.span, false)?;
|
||||
|
||||
self.wr.commit_pending_semi()?;
|
||||
|
||||
srcmap!(self, node, true);
|
||||
|
||||
if node.declare {
|
||||
keyword!(self, "declare");
|
||||
space!(self);
|
||||
}
|
||||
|
||||
keyword!(self, node.kind.as_str());
|
||||
|
||||
let starts_with_ident = match node.decls.first() {
|
||||
Some(VarDeclarator {
|
||||
name: Pat::Array(..) | Pat::Rest(..) | Pat::Object(..),
|
||||
..
|
||||
}) => false,
|
||||
_ => true,
|
||||
};
|
||||
if starts_with_ident {
|
||||
space!(self);
|
||||
} else {
|
||||
formatting_space!(self);
|
||||
}
|
||||
|
||||
self.emit_list(
|
||||
node.span(),
|
||||
Some(&node.decls),
|
||||
ListFormat::VariableDeclarationList,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_var_declarator(&mut self, node: &VarDeclarator) -> Result {
|
||||
self.emit_leading_comments_of_span(node.span(), false)?;
|
||||
|
||||
srcmap!(node, true);
|
||||
|
||||
emit!(node.name);
|
||||
|
||||
if let Some(ref init) = node.init {
|
||||
formatting_space!();
|
||||
punct!("=");
|
||||
formatting_space!();
|
||||
emit!(init);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::assert_min;
|
||||
|
||||
#[test]
|
||||
fn issue_275() {
|
||||
assert_min(
|
||||
"function* foo(){
|
||||
yield getServiceHosts()
|
||||
}",
|
||||
"function*foo(){yield getServiceHosts()}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1764() {
|
||||
assert_min(
|
||||
"class Hoge {};
|
||||
class HogeFuga extends Hoge {};",
|
||||
"class Hoge{};class HogeFuga extends Hoge{};",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn single_argument_arrow_expression() {
|
||||
assert_min("function* f(){ yield x => x}", "function*f(){yield x=>x}");
|
||||
assert_min(
|
||||
"function* f(){ yield ({x}) => x}",
|
||||
"function*f(){yield({x})=>x}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn class_static_block() {
|
||||
assert_min("class Foo { static { 1 + 1; }}", "class Foo{static{1+1}}");
|
||||
}
|
||||
}
|
||||
205
third-party/vendor/swc_ecma_codegen/src/expr.rs
vendored
Normal file
205
third-party/vendor/swc_ecma_codegen/src/expr.rs
vendored
Normal file
|
|
@ -0,0 +1,205 @@
|
|||
/// Copied from [ratel][]
|
||||
///
|
||||
/// [ratel]:https://github.com/ratel-rust/ratel-core
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::assert_min;
|
||||
|
||||
#[test]
|
||||
fn values() {
|
||||
assert_min("null", "null");
|
||||
assert_min("undefined", "undefined");
|
||||
assert_min("true", "true");
|
||||
assert_min("false", "false");
|
||||
assert_min("42", "42");
|
||||
assert_min("3.14", "3.14");
|
||||
assert_min(r#" 'foobar' "#, r#""foobar""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bin_expr() {
|
||||
assert_min("1+2+3+4+5", "1+2+3+4+5");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn template_expression() {
|
||||
assert_min("``", "``");
|
||||
assert_min("foo``", "foo``");
|
||||
assert_min("`foobar`", "`foobar`");
|
||||
assert_min("foo`bar`", "foo`bar`");
|
||||
assert_min("`foo${ 10 }bar${ 20 }baz`", "`foo${10}bar${20}baz`");
|
||||
assert_min("foo`bar${ 10 }baz`", "foo`bar${10}baz`");
|
||||
assert_min("foo`${ 10 }`", "foo`${10}`");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sequence_expression() {
|
||||
assert_min("foo, bar, baz;", "foo,bar,baz");
|
||||
assert_min("1, 2, 3;", "1,2,3");
|
||||
assert_min("1,2,3+4;", "1,2,3+4");
|
||||
assert_min("1+2,3,4;", "1+2,3,4");
|
||||
assert_min("1+(2,3,4);", "1+(2,3,4)");
|
||||
assert_min("(1,2,3)+4;", "(1,2,3)+4");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_expression() {
|
||||
assert_min("a = 10", "a=10");
|
||||
assert_min("a == 10", "a==10");
|
||||
assert_min("a === 10", "a===10");
|
||||
assert_min("a != 10", "a!=10");
|
||||
assert_min("a !== 10", "a!==10");
|
||||
assert_min("a += 10", "a+=10");
|
||||
assert_min("a -= 10", "a-=10");
|
||||
assert_min("a <<= 10", "a<<=10");
|
||||
assert_min("a >>= 10", "a>>=10");
|
||||
assert_min("a >>>= 10", "a>>>=10");
|
||||
assert_min("2 + 2", "2+2");
|
||||
assert_min("2 - 2", "2-2");
|
||||
assert_min("2 * 2", "2*2");
|
||||
assert_min("2 / 2", "2/2");
|
||||
assert_min("2 % 2", "2%2");
|
||||
assert_min("2 ** 2", "2**2");
|
||||
assert_min("2 << 2", "2<<2");
|
||||
assert_min("2 >> 2", "2>>2");
|
||||
assert_min("2 >>> 2", "2>>>2");
|
||||
assert_min("foo in bar", "foo in bar");
|
||||
assert_min("foo instanceof Foo", "foo instanceof Foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prefix_expression() {
|
||||
assert_min("+foo", "+foo");
|
||||
assert_min("-foo", "-foo");
|
||||
assert_min("!foo", "!foo");
|
||||
assert_min("~foo", "~foo");
|
||||
assert_min("++foo", "++foo");
|
||||
assert_min("--foo", "--foo");
|
||||
assert_min("new foo", "new foo");
|
||||
assert_min("new foo()", "new foo");
|
||||
assert_min("new foo().bar()", "new foo().bar()");
|
||||
assert_min("void foo", "void foo");
|
||||
assert_min("typeof foo", "typeof foo");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn postfix_expression() {
|
||||
assert_min("foo++", "foo++");
|
||||
assert_min("foo--", "foo--");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn conditional_expression() {
|
||||
assert_min("true ? foo : bar", "true?foo:bar")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_expression() {
|
||||
assert_min("(function () {})", "(function(){})");
|
||||
assert_min("(function foo() {})", "(function foo(){})");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore]
|
||||
fn class_expression() {
|
||||
assert_min("(class {})", "(class{})");
|
||||
assert_min("(class Foo {})", "(class Foo{})");
|
||||
assert_min("(class extends Foo {})", "(class extends Foo{})");
|
||||
assert_min("(class Foo extends Bar {})", "(class Foo extends Bar{})");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn call_expression() {
|
||||
assert_min("foobar();", "foobar()");
|
||||
assert_min("foobar(1, 2, 3);", "foobar(1,2,3)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn member_expression() {
|
||||
assert_min("foo.bar", "foo.bar");
|
||||
assert_min("this.bar", "this.bar");
|
||||
assert_min("10..fooz", "10..fooz");
|
||||
assert_min("foo[10]", "foo[10]");
|
||||
assert_min(r#"foo["bar"]"#, r#"foo["bar"]"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_expression() {
|
||||
assert_min("[]", "[]");
|
||||
assert_min("[foo]", "[foo]");
|
||||
assert_min("[foo,bar]", "[foo,bar]");
|
||||
assert_min("[foo,bar,baz,]", "[foo,bar,baz]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn array_spread() {
|
||||
assert_min("[...foo,...bar]", "[...foo,...bar]");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sparse_array_expression() {
|
||||
assert_min("[]", "[]");
|
||||
assert_min("[,]", "[,]");
|
||||
assert_min("[,1]", "[,1]");
|
||||
assert_min("[,,];", "[,,]");
|
||||
assert_min("[1,,];", "[1,,]");
|
||||
assert_min("[,,1];", "[,,1]");
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn sparse_array_expression_pretty() {
|
||||
// assert_pretty("[]", "[];");
|
||||
// assert_pretty("[,]", "[, ];");
|
||||
// assert_pretty("[1,]", "[1, ];");
|
||||
// assert_pretty("[,1]", "[, 1];");
|
||||
// assert_pretty("[,,];", "[, , ];");
|
||||
// assert_pretty("[1,,];", "[1, , ];");
|
||||
// assert_pretty("[,,1];", "[, , 1];");
|
||||
// }
|
||||
|
||||
#[test]
|
||||
fn object_expression() {
|
||||
assert_min("({});", "({})");
|
||||
assert_min("({ foo });", "({foo})");
|
||||
assert_min("({ foo: 10 });", "({foo:10})");
|
||||
assert_min("({ foo, bar });", "({foo,bar})");
|
||||
assert_min("({ foo: 10, bar: 20 });", "({foo:10,bar:20})");
|
||||
assert_min("({ foo: 10, bar() {} });", "({foo:10,bar(){}})");
|
||||
assert_min("({ foo(bar, baz) {} });", "({foo(bar,baz){}})");
|
||||
// let expected = "({\n foo: true,\n bar: false\n});";
|
||||
// assert_pretty("({ foo: true, bar: false })", expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binding_power() {
|
||||
assert_min("1 + 2 * 3;", "1+2*3");
|
||||
assert_min("1 + 2 * 3;", "1+2*3");
|
||||
assert_min("(1 + 2) * 3;", "(1+2)*3");
|
||||
assert_min(
|
||||
"(denominator / divider * 100).toFixed(2);",
|
||||
"(denominator/divider*100).toFixed(2)",
|
||||
);
|
||||
assert_min("(1 + 1)[0];", "(1+1)[0]");
|
||||
assert_min("2 * 2 / 2;", "2*2/2");
|
||||
assert_min("2 * (2 / 2);", "2*(2/2)");
|
||||
assert_min("2 * 2 / 2;", "2*2/2");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn regression_increments() {
|
||||
assert_min("x++ + ++y", "x+++ ++y");
|
||||
assert_min("x++ - ++y", "x++-++y");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bigint_property_key() {
|
||||
assert_min("({ 1n: 2 });", "({1n:2})");
|
||||
assert_min("(class C { 1n = 1 });", "(class C{1n=1})");
|
||||
assert_min("(class C { 1n () { } });", "(class C{1n(){}})");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn html_comment() {
|
||||
assert_min("a < !--b && c-- > d;", "a< !--b&&c-- >d");
|
||||
}
|
||||
}
|
||||
194
third-party/vendor/swc_ecma_codegen/src/jsx.rs
vendored
Normal file
194
third-party/vendor/swc_ecma_codegen/src/jsx.rs
vendored
Normal file
|
|
@ -0,0 +1,194 @@
|
|||
use swc_common::{SourceMapper, Spanned};
|
||||
use swc_ecma_ast::*;
|
||||
use swc_ecma_codegen_macros::emitter;
|
||||
|
||||
use super::{Emitter, Result};
|
||||
use crate::text_writer::WriteJs;
|
||||
|
||||
impl<'a, W, S: SourceMapper> Emitter<'a, W, S>
|
||||
where
|
||||
W: WriteJs,
|
||||
S: SourceMapperExt,
|
||||
{
|
||||
#[emitter]
|
||||
fn emit_jsx_element(&mut self, node: &JSXElement) -> Result {
|
||||
emit!(node.opening);
|
||||
self.emit_list(
|
||||
node.span(),
|
||||
Some(&node.children),
|
||||
ListFormat::JsxElementOrFragmentChildren,
|
||||
)?;
|
||||
if let Some(ref closing) = node.closing {
|
||||
emit!(closing)
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_opening_element(&mut self, node: &JSXOpeningElement) -> Result {
|
||||
punct!("<");
|
||||
emit!(node.name);
|
||||
|
||||
if let Some(type_args) = &node.type_args {
|
||||
emit!(type_args);
|
||||
}
|
||||
|
||||
if !node.attrs.is_empty() {
|
||||
space!();
|
||||
|
||||
self.emit_list(
|
||||
node.span(),
|
||||
Some(&node.attrs),
|
||||
ListFormat::JsxElementAttributes,
|
||||
)?;
|
||||
}
|
||||
|
||||
if node.self_closing {
|
||||
punct!("/");
|
||||
}
|
||||
punct!(">");
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_element_name(&mut self, node: &JSXElementName) -> Result {
|
||||
match *node {
|
||||
JSXElementName::Ident(ref n) => emit!(n),
|
||||
JSXElementName::JSXMemberExpr(ref n) => emit!(n),
|
||||
JSXElementName::JSXNamespacedName(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_attr(&mut self, node: &JSXAttr) -> Result {
|
||||
emit!(node.name);
|
||||
|
||||
if let Some(ref value) = node.value {
|
||||
punct!("=");
|
||||
|
||||
emit!(value);
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_attr_value(&mut self, node: &JSXAttrValue) -> Result {
|
||||
match *node {
|
||||
JSXAttrValue::Lit(ref n) => emit!(n),
|
||||
JSXAttrValue::JSXExprContainer(ref n) => emit!(n),
|
||||
JSXAttrValue::JSXElement(ref n) => emit!(n),
|
||||
JSXAttrValue::JSXFragment(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_attr_name(&mut self, node: &JSXAttrName) -> Result {
|
||||
match *node {
|
||||
JSXAttrName::Ident(ref n) => emit!(n),
|
||||
JSXAttrName::JSXNamespacedName(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_attr_or_spread(&mut self, node: &JSXAttrOrSpread) -> Result {
|
||||
match *node {
|
||||
JSXAttrOrSpread::JSXAttr(ref n) => emit!(n),
|
||||
JSXAttrOrSpread::SpreadElement(ref n) => {
|
||||
punct!("{");
|
||||
emit!(n);
|
||||
punct!("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_element_child(&mut self, node: &JSXElementChild) -> Result {
|
||||
match *node {
|
||||
JSXElementChild::JSXElement(ref n) => emit!(n),
|
||||
JSXElementChild::JSXExprContainer(ref n) => emit!(n),
|
||||
JSXElementChild::JSXFragment(ref n) => emit!(n),
|
||||
JSXElementChild::JSXSpreadChild(ref n) => emit!(n),
|
||||
JSXElementChild::JSXText(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_spread_child(&mut self, node: &JSXSpreadChild) -> Result {
|
||||
punct!("{");
|
||||
punct!("...");
|
||||
emit!(node.expr);
|
||||
punct!("}");
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_expr_container(&mut self, node: &JSXExprContainer) -> Result {
|
||||
punct!("{");
|
||||
emit!(node.expr);
|
||||
punct!("}");
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_expr(&mut self, node: &JSXExpr) -> Result {
|
||||
match *node {
|
||||
JSXExpr::Expr(ref n) => emit!(n),
|
||||
JSXExpr::JSXEmptyExpr(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_closing_element(&mut self, node: &JSXClosingElement) -> Result {
|
||||
punct!("</");
|
||||
emit!(node.name);
|
||||
punct!(">");
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_fragment(&mut self, node: &JSXFragment) -> Result {
|
||||
emit!(node.opening);
|
||||
|
||||
self.emit_list(
|
||||
node.span(),
|
||||
Some(&node.children),
|
||||
ListFormat::JsxElementOrFragmentChildren,
|
||||
)?;
|
||||
|
||||
emit!(node.closing);
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_opening_fragment(&mut self, _: &JSXOpeningFragment) -> Result {
|
||||
punct!("<>")
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_closing_fragment(&mut self, _: &JSXClosingFragment) -> Result {
|
||||
punct!("</>")
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_namespaced_name(&mut self, node: &JSXNamespacedName) -> Result {
|
||||
emit!(node.ns);
|
||||
punct!(":");
|
||||
emit!(node.name);
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_empty_expr(&mut self, _: &JSXEmptyExpr) -> Result {}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_text(&mut self, node: &JSXText) -> Result {
|
||||
self.emit_atom(node.span(), &node.value)?;
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_member_expr(&mut self, node: &JSXMemberExpr) -> Result {
|
||||
emit!(node.obj);
|
||||
punct!(".");
|
||||
emit!(node.prop);
|
||||
}
|
||||
|
||||
#[emitter]
|
||||
fn emit_jsx_object(&mut self, node: &JSXObject) -> Result {
|
||||
match *node {
|
||||
JSXObject::Ident(ref n) => emit!(n),
|
||||
JSXObject::JSXMemberExpr(ref n) => emit!(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
4035
third-party/vendor/swc_ecma_codegen/src/lib.rs
vendored
Normal file
4035
third-party/vendor/swc_ecma_codegen/src/lib.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
148
third-party/vendor/swc_ecma_codegen/src/macros.rs
vendored
Normal file
148
third-party/vendor/swc_ecma_codegen/src/macros.rs
vendored
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
#![allow(unused)]
|
||||
|
||||
macro_rules! opt_leading_space {
|
||||
($emitter:expr, $e:expr) => {
|
||||
if let Some(ref e) = $e {
|
||||
formatting_space!($emitter);
|
||||
emit!($emitter, e);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! opt {
|
||||
($emitter:expr, $e:expr) => {{
|
||||
if let Some(ref expr) = $e {
|
||||
emit!($emitter, expr);
|
||||
}
|
||||
}};
|
||||
($emitter:expr, $e:expr,) => {{
|
||||
opt!($emitter, $e)
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! emit {
|
||||
($emitter:expr, $e:expr) => {{
|
||||
crate::Node::emit_with(&$e, $emitter)?;
|
||||
}};
|
||||
}
|
||||
|
||||
macro_rules! keyword {
|
||||
($emitter:expr, $span:expr, $s:expr) => {
|
||||
$emitter.wr.write_keyword(Some($span), $s)?
|
||||
};
|
||||
($emitter:expr, $s:expr) => {
|
||||
$emitter.wr.write_keyword(None, $s)?
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! punct {
|
||||
($emitter:expr, $sp:expr, ";") => {
|
||||
$emitter.wr.write_semi(Some($sp))?;
|
||||
};
|
||||
($emitter:expr, $sp:expr, $s:expr) => {
|
||||
$emitter.wr.write_punct(Some($sp), $s)?;
|
||||
};
|
||||
|
||||
($emitter:expr, ";") => {
|
||||
$emitter.wr.write_semi(None)?
|
||||
};
|
||||
($emitter:expr, $s:expr) => {
|
||||
$emitter.wr.write_punct(None, $s)?
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! operator {
|
||||
($emitter:expr, $sp:expr, $s:expr) => {
|
||||
$emitter.wr.write_operator(Some($sp), $s)?;
|
||||
};
|
||||
|
||||
($emitter:expr, $s:expr) => {
|
||||
$emitter.wr.write_operator(None, $s)?;
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! space {
|
||||
($emitter:expr) => {
|
||||
$emitter.wr.write_space()?
|
||||
};
|
||||
($emitter:expr,) => {
|
||||
space!($emitter)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! formatting_space {
|
||||
($emitter:expr) => {
|
||||
if !$emitter.cfg.minify {
|
||||
$emitter.wr.write_space()?;
|
||||
}
|
||||
};
|
||||
($emitter:expr,) => {
|
||||
formatting_space!($emitter)
|
||||
};
|
||||
}
|
||||
|
||||
/// This macro *may* emit a semicolon, if it's required in this context.
|
||||
macro_rules! formatting_semi {
|
||||
($emitter:expr) => {
|
||||
punct!($emitter, ";")
|
||||
};
|
||||
($emitter:expr, ) => {
|
||||
punct!($emitter, ";")
|
||||
};
|
||||
}
|
||||
|
||||
/// This macro *always* emits a semicolon, as it's required by the structure we
|
||||
/// emit.
|
||||
macro_rules! semi {
|
||||
($emitter:expr, $sp:expr) => {
|
||||
$emitter.wr.write_semi(Some($sp))?;
|
||||
};
|
||||
($emitter:expr) => {
|
||||
$emitter.wr.write_semi(None)?;
|
||||
};
|
||||
}
|
||||
|
||||
///
|
||||
/// - `srcmap!(true)` for start (span.lo)
|
||||
/// - `srcmap!(false)` for end (span.hi)
|
||||
macro_rules! srcmap {
|
||||
($emitter:expr, $n:expr, true) => {{
|
||||
#[cfg(debug_assertions)]
|
||||
let _span = tracing::span!(
|
||||
tracing::Level::ERROR,
|
||||
"srcmap",
|
||||
file = file!(),
|
||||
line = line!()
|
||||
)
|
||||
.entered();
|
||||
|
||||
let lo = $n.span_lo();
|
||||
if !lo.is_dummy() {
|
||||
$emitter.wr.add_srcmap(lo)?;
|
||||
}
|
||||
}};
|
||||
($emitter:expr, $n:expr, false) => {
|
||||
srcmap!($emitter, $n, false, false)
|
||||
};
|
||||
($emitter:expr, $n:expr, false, $subtract:expr) => {
|
||||
#[cfg(debug_assertions)]
|
||||
let _span = tracing::span!(
|
||||
tracing::Level::ERROR,
|
||||
"srcmap",
|
||||
file = file!(),
|
||||
line = line!()
|
||||
)
|
||||
.entered();
|
||||
|
||||
let hi = $n.span_hi();
|
||||
if !hi.is_dummy() {
|
||||
if $subtract {
|
||||
// hi is exclusive
|
||||
$emitter.wr.add_srcmap(hi - swc_common::BytePos(1))?;
|
||||
} else {
|
||||
// TODO(kdy1): Remove this branch.
|
||||
$emitter.wr.add_srcmap(hi)?;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
154
third-party/vendor/swc_ecma_codegen/src/stmt.rs
vendored
Normal file
154
third-party/vendor/swc_ecma_codegen/src/stmt.rs
vendored
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
/// Copied from [ratel][]
|
||||
///
|
||||
/// [ratel]:https://github.com/ratel-rust/ratel-core
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::tests::{assert_min, assert_pretty};
|
||||
|
||||
#[test]
|
||||
fn block_statement() {
|
||||
assert_min("{}", "{}");
|
||||
assert_min("{foo;}", "{foo}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_block_statement() {
|
||||
assert_pretty("{\n}", "{}");
|
||||
assert_pretty("{\n//todo\n}", "{\n//todo\n}");
|
||||
|
||||
assert_pretty(
|
||||
"try {\n\n} catch {\n // Pass\n}\n",
|
||||
"try {} catch {\n// Pass\n}",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_object_lit() {
|
||||
assert_pretty("Object.assign({\n}, a, b);", "Object.assign({}, a, b);");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn labeled_statement() {
|
||||
assert_min("foo: {}", "foo:{}");
|
||||
assert_min("foo: bar;", "foo:bar");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn function_statement() {
|
||||
assert_min("function foo() {}", "function foo(){}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn declaration_statement() {
|
||||
assert_min("var foo;", "var foo");
|
||||
assert_min("let foo;", "let foo");
|
||||
assert_min("var foo = 10;", "var foo=10");
|
||||
assert_min("let foo = 10;", "let foo=10");
|
||||
assert_min("const foo = 10;", "const foo=10");
|
||||
assert_min("var foo, bar;", "var foo,bar");
|
||||
assert_min("let foo, bar;", "let foo,bar");
|
||||
assert_min("var foo = 10, bar = 20;", "var foo=10,bar=20");
|
||||
assert_min("let foo = 10, bar = 20;", "let foo=10,bar=20");
|
||||
assert_min("const foo = 10, bar = 20;", "const foo=10,bar=20");
|
||||
assert_min("const a = {...foo};", "const a={...foo}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn if_statement() {
|
||||
assert_min("if (true) foo;", "if(true)foo");
|
||||
assert_min("if (true) { foo; }", "if(true){foo}");
|
||||
assert_min("if (true) foo; else bar;", "if(true)foo;else bar");
|
||||
assert_min("if (true) { foo; } else { bar; }", "if(true){foo}else{bar}");
|
||||
assert_min("if (true) foo; else { bar; }", "if(true)foo;else{bar}");
|
||||
assert_min("if (true) { foo; } else bar;", "if(true){foo}else bar");
|
||||
assert_min("if (true) y(); else x++;", "if(true)y();else x++");
|
||||
assert_min("if (true) y(); else x--;", "if(true)y();else x--");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn while_statement() {
|
||||
assert_min("while (true) foo;", "while(true)foo");
|
||||
assert_min("while (true) { foo; }", "while(true){foo}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn do_statement() {
|
||||
assert_min("do { foo; } while (true)", "do{foo}while(true)");
|
||||
assert_min("do foo; while (true)", "do foo;while(true)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_statement() {
|
||||
assert_min("for (var i = 0; i < 10; i++) {}", "for(var i=0;i<10;i++){}");
|
||||
assert_min("for (i = 0; i < 10; i++) {}", "for(i=0;i<10;i++){}");
|
||||
assert_min("for (;;) {}", "for(;;){}");
|
||||
assert_min("for (foo in bar){}", "for(foo in bar){}");
|
||||
assert_min("for (let foo in bar){}", "for(let foo in bar){}");
|
||||
assert_min("for (foo of bar){}", "for(foo of bar){}");
|
||||
assert_min("for (let foo of bar){}", "for(let foo of bar){}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_statement_pretty() {
|
||||
assert_pretty(
|
||||
"for (var i = 0; i < 10; i++) {}",
|
||||
"for(var i = 0; i < 10; i++){}",
|
||||
);
|
||||
assert_pretty("for (i = 0; i < 10; i++) {}", "for(i = 0; i < 10; i++){}");
|
||||
assert_pretty("for (;;) {}", "for(;;){}");
|
||||
assert_pretty("for (foo in bar){}", "for(foo in bar){}");
|
||||
assert_pretty("for (let foo in bar){}", "for(let foo in bar){}");
|
||||
assert_pretty("for (foo of bar){}", "for (foo of bar){}");
|
||||
assert_pretty("for (let foo of bar){}", "for (let foo of bar){}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn import() {
|
||||
assert_min(
|
||||
"import colors, { color } from 'patterns/colors';",
|
||||
"import colors,{color}from\"patterns/colors\"",
|
||||
);
|
||||
assert_pretty(
|
||||
"import colors, { color } from 'patterns/colors';",
|
||||
"import colors, { color } from 'patterns/colors';",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_204_01() {
|
||||
assert_min(r"'\r\n';", r#""\r\n""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_204_02() {
|
||||
assert_min(r"const a = fn() + '\r\n';", r#"const a=fn()+"\r\n""#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_177() {
|
||||
assert_min(
|
||||
"#!/usr/bin/env node
|
||||
let x = 4;",
|
||||
"#!/usr/bin/env node
|
||||
let x=4",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_197() {
|
||||
assert_pretty(
|
||||
"// type Foo = 'Oops';
|
||||
const Link = 'Boo';",
|
||||
"// type Foo = 'Oops';
|
||||
const Link = 'Boo';",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_266() {
|
||||
assert_min(
|
||||
"'Q' + +x1 + ',' + +y1 + ',' + (this._x1 = +x) + ',' + (this._y1 = +y);",
|
||||
"\"Q\"+ +x1+\",\"+ +y1+\",\"+(this._x1=+x)+\",\"+(this._y1=+y)",
|
||||
);
|
||||
}
|
||||
}
|
||||
891
third-party/vendor/swc_ecma_codegen/src/tests.rs
vendored
Normal file
891
third-party/vendor/swc_ecma_codegen/src/tests.rs
vendored
Normal file
|
|
@ -0,0 +1,891 @@
|
|||
use std::{
|
||||
fmt::Debug,
|
||||
io::Write,
|
||||
sync::{Arc, RwLock},
|
||||
};
|
||||
|
||||
use swc_common::{comments::SingleThreadedComments, FileName, SourceMap};
|
||||
use swc_ecma_parser;
|
||||
use testing::DebugUsingDisplay;
|
||||
|
||||
use self::swc_ecma_parser::{EsConfig, Parser, StringInput, Syntax};
|
||||
use super::*;
|
||||
use crate::{config::Config, text_writer::omit_trailing_semi};
|
||||
|
||||
struct Builder {
|
||||
cfg: Config,
|
||||
cm: Lrc<SourceMap>,
|
||||
comments: SingleThreadedComments,
|
||||
}
|
||||
|
||||
impl Builder {
|
||||
pub fn with<'a, F, Ret>(self, _: &str, s: &'a mut Vec<u8>, op: F) -> Ret
|
||||
where
|
||||
F: for<'aa> FnOnce(&mut Emitter<'aa, Box<(dyn WriteJs + 'aa)>, SourceMap>) -> Ret,
|
||||
Ret: 'static,
|
||||
{
|
||||
let writer = text_writer::JsWriter::new(self.cm.clone(), "\n", s, None);
|
||||
let writer: Box<dyn WriteJs> = if self.cfg.minify {
|
||||
Box::new(omit_trailing_semi(writer))
|
||||
} else {
|
||||
Box::new(writer)
|
||||
};
|
||||
|
||||
{
|
||||
let mut e = Emitter {
|
||||
cfg: self.cfg,
|
||||
cm: self.cm.clone(),
|
||||
wr: writer,
|
||||
comments: Some(&self.comments),
|
||||
};
|
||||
|
||||
op(&mut e)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn text<F>(self, src: &str, op: F) -> String
|
||||
where
|
||||
F: for<'aa> FnOnce(&mut Emitter<'aa, Box<(dyn WriteJs + 'aa)>, SourceMap>),
|
||||
{
|
||||
let mut buf = vec![];
|
||||
|
||||
self.with(src, &mut buf, op);
|
||||
|
||||
String::from_utf8(buf).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_then_emit(from: &str, cfg: Config, syntax: Syntax) -> String {
|
||||
::testing::run_test(false, |cm, handler| {
|
||||
let src = cm.new_source_file(FileName::Real("custom.js".into()), from.to_string());
|
||||
println!(
|
||||
"--------------------\nSource: \n{}\nPos: {:?} ~ {:?}\n",
|
||||
from, src.start_pos, src.end_pos
|
||||
);
|
||||
|
||||
let comments = Default::default();
|
||||
let res = {
|
||||
let mut parser = Parser::new(syntax, StringInput::from(&*src), Some(&comments));
|
||||
let res = parser
|
||||
.parse_module()
|
||||
.map_err(|e| e.into_diagnostic(handler).emit());
|
||||
|
||||
for err in parser.take_errors() {
|
||||
err.into_diagnostic(handler).emit()
|
||||
}
|
||||
|
||||
res?
|
||||
};
|
||||
|
||||
let out = Builder { cfg, cm, comments }.text(from, |e| e.emit_module(&res).unwrap());
|
||||
Ok(out)
|
||||
})
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub(crate) fn assert_min(from: &str, to: &str) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
minify: true,
|
||||
target: EsVersion::latest(),
|
||||
omit_last_semi: true,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::Es(Default::default()),
|
||||
);
|
||||
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to),);
|
||||
}
|
||||
|
||||
pub(crate) fn assert_min_target(from: &str, to: &str, target: EsVersion) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
minify: true,
|
||||
omit_last_semi: true,
|
||||
target,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to),);
|
||||
}
|
||||
|
||||
/// Clone of the regular `assert_min` function but with TypeScript syntax.
|
||||
pub(crate) fn assert_min_typescript(from: &str, to: &str) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
minify: true,
|
||||
omit_last_semi: true,
|
||||
target: EsVersion::latest(),
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::Typescript(Default::default()),
|
||||
);
|
||||
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to),);
|
||||
}
|
||||
|
||||
pub(crate) fn assert_pretty(from: &str, to: &str) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
minify: false,
|
||||
target: EsVersion::latest(),
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
println!("Expected: {:?}", to);
|
||||
println!("Actual: {:?}", out);
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to),);
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn test_from_to(from: &str, expected: &str) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
target: EsVersion::latest(),
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
dbg!(&out);
|
||||
dbg!(&expected);
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(out.trim()),
|
||||
DebugUsingDisplay(expected.trim()),
|
||||
);
|
||||
}
|
||||
|
||||
fn test_identical(from: &str) {
|
||||
test_from_to(from, from)
|
||||
}
|
||||
|
||||
fn test_from_to_custom_config(from: &str, to: &str, cfg: Config, syntax: Syntax) {
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
omit_last_semi: true,
|
||||
..cfg
|
||||
},
|
||||
syntax,
|
||||
);
|
||||
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to.trim()),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_stmt() {
|
||||
test_from_to(";", ";");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comment_1() {
|
||||
test_from_to(
|
||||
"// foo
|
||||
a",
|
||||
"// foo
|
||||
a;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comment_2() {
|
||||
test_from_to("a // foo", "a // foo\n;\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comment_3() {
|
||||
test_from_to(
|
||||
"// foo
|
||||
// bar
|
||||
a
|
||||
// foo
|
||||
b // bar",
|
||||
"// foo\n// bar\na;\n// foo\nb // bar\n;\n",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comment_4() {
|
||||
test_from_to("/** foo */ a", "/** foo */ a;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn comment_5() {
|
||||
test_from_to(
|
||||
"// foo
|
||||
// bar
|
||||
a",
|
||||
"// foo
|
||||
// bar
|
||||
a;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_octal_escape() {
|
||||
test_from_to(
|
||||
r"'\x00a';
|
||||
'\x000';
|
||||
'\x001';
|
||||
'\x009'",
|
||||
r"'\x00a';
|
||||
'\x000';
|
||||
'\x001';
|
||||
'\x009';",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_named_export() {
|
||||
test_from_to("export { }", "export { };");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_named_export_min() {
|
||||
test_from_to_custom_config(
|
||||
"export { }",
|
||||
"export{}",
|
||||
Config {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
},
|
||||
Default::default(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_named_export_from() {
|
||||
test_from_to("export { } from 'foo';", "export { } from 'foo';");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_named_export_from_min() {
|
||||
test_from_to_custom_config(
|
||||
"export { } from 'foo';",
|
||||
"export{}from\"foo\"",
|
||||
Config {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
},
|
||||
Default::default(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn named_export_from() {
|
||||
test_from_to("export { bar } from 'foo';", "export { bar } from 'foo';");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn named_export_from_min() {
|
||||
test_from_to_custom_config(
|
||||
"export { bar } from 'foo';",
|
||||
"export{bar}from\"foo\"",
|
||||
Config {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
},
|
||||
Default::default(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn export_namespace_from() {
|
||||
test_from_to_custom_config(
|
||||
"export * as Foo from 'foo';",
|
||||
"export * as Foo from 'foo';",
|
||||
Default::default(),
|
||||
Syntax::Es(EsConfig::default()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn export_namespace_from_min() {
|
||||
test_from_to_custom_config(
|
||||
"export * as Foo from 'foo';",
|
||||
"export*as Foo from\"foo\"",
|
||||
Config {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::Es(EsConfig::default()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn named_and_namespace_export_from() {
|
||||
test_from_to_custom_config(
|
||||
"export * as Foo, { bar } from 'foo';",
|
||||
"export * as Foo, { bar } from 'foo';",
|
||||
Default::default(),
|
||||
Syntax::Es(EsConfig {
|
||||
export_default_from: true,
|
||||
..EsConfig::default()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn named_and_namespace_export_from_min() {
|
||||
test_from_to_custom_config(
|
||||
"export * as Foo, { bar } from 'foo';",
|
||||
"export*as Foo,{bar}from\"foo\"",
|
||||
Config {
|
||||
minify: true,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::Es(EsConfig {
|
||||
export_default_from: true,
|
||||
..EsConfig::default()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_450() {
|
||||
test_from_to(
|
||||
r"console.log(`
|
||||
\`\`\`html
|
||||
<h1>It works!</h1>
|
||||
\`\`\`
|
||||
`);",
|
||||
"console.log(`\n\\`\\`\\`html\n<h1>It works!</h1>\n\\`\\`\\`\n`);",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_546() {
|
||||
test_from_to(
|
||||
"import availabilities, * as availabilityFunctions from 'reducers/availabilities';",
|
||||
"import availabilities, * as availabilityFunctions from 'reducers/availabilities';",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_637() {
|
||||
test_from_to(
|
||||
r"`\
|
||||
`;", r"`\
|
||||
`;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_639() {
|
||||
test_from_to(r"`\x1b[33m Yellow \x1b[0m`;", r"`\x1b[33m Yellow \x1b[0m`;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_910() {
|
||||
test_from_to(
|
||||
"console.log(\"Hello World\");",
|
||||
"console.log(\"Hello World\");",
|
||||
);
|
||||
|
||||
test_from_to("console.log('Hello World');", "console.log('Hello World');");
|
||||
|
||||
test_from_to(
|
||||
"console.log(\"Hello\\\" World\");",
|
||||
"console.log(\"Hello\\\" World\");",
|
||||
);
|
||||
|
||||
test_from_to(
|
||||
"console.log('Hello\\' World');",
|
||||
"console.log('Hello\\' World');",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_1() {
|
||||
test_from_to(
|
||||
"`id '${id}' must be a non-empty string`;",
|
||||
"`id '${id}' must be a non-empty string`;",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_2() {
|
||||
test_from_to(
|
||||
"`${Module.wrapper[0]}${script}${Module.wrapper[1]}`",
|
||||
"`${Module.wrapper[0]}${script}${Module.wrapper[1]}`;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_1() {
|
||||
test_from_to(
|
||||
"`${parent.path}\x00${request}`",
|
||||
"`${parent.path}\x00${request}`;",
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_2() {
|
||||
test_from_to("`${arg}\0`", "`${arg}\0`;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_3() {
|
||||
test_from_to(
|
||||
r"`${resolvedDevice.toLowerCase()}\\`",
|
||||
r"`${resolvedDevice.toLowerCase()}\\`;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_4() {
|
||||
test_from_to(
|
||||
r"`\\\\${firstPart}\\${path.slice(last)}`",
|
||||
r"`\\\\${firstPart}\\${path.slice(last)}`;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_5() {
|
||||
test_from_to(
|
||||
r"const data = text.encode(`${arg}\0`);",
|
||||
r"const data = text.encode(`${arg}\0`);",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tpl_escape_6() {
|
||||
let from = r#"export class MultipartReader {
|
||||
newLine = encoder.encode("\r\n");
|
||||
newLineDashBoundary = encoder.encode(`\r\n--${this.boundary}`);
|
||||
dashBoundaryDash = encoder.encode(`--${this.boundary}--`);
|
||||
}"#;
|
||||
let to = r#"export class MultipartReader {
|
||||
newLine = encoder.encode("\r\n");
|
||||
newLineDashBoundary = encoder.encode(`\r\n--${this.boundary}`);
|
||||
dashBoundaryDash = encoder.encode(`--${this.boundary}--`);
|
||||
}"#;
|
||||
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
target: EsVersion::latest(),
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::Typescript(Default::default()),
|
||||
);
|
||||
assert_eq!(DebugUsingDisplay(out.trim()), DebugUsingDisplay(to.trim()),);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_915_1() {
|
||||
test_identical(r"relResolveCacheIdentifier = `${parent.path}\x00${request}`;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_915_2() {
|
||||
test_identical(r"relResolveCacheIdentifier = `${parent.path}\x00${request}`;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_915_3() {
|
||||
test_identical(r#"encoder.encode("\\r\\n");"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_915_4() {
|
||||
test_identical(r"`\\r\\n--${this.boundary}`;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn jsx_1() {
|
||||
test_from_to_custom_config(
|
||||
"<Foo title=\"name\" desc=\"<empty>\" bool it>foo</Foo>;",
|
||||
"<Foo title=\"name\" desc=\"<empty>\" bool it>foo</Foo>;",
|
||||
Default::default(),
|
||||
Syntax::Es(EsConfig {
|
||||
jsx: true,
|
||||
..Default::default()
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deno_8162() {
|
||||
test_from_to(
|
||||
r#""\x00\r\n\x85\u2028\u2029";"#,
|
||||
r#""\x00\r\n\x85\u2028\u2029";"#,
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integration_01() {
|
||||
test_from_to(
|
||||
r#"
|
||||
`Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` +
|
||||
`"${unexpectedKeys.join('", "')}" found in ${argumentName}. ` +
|
||||
`Expected to find one of the known reducer keys instead: ` +
|
||||
`"${reducerKeys.join('", "')}". Unexpected keys will be ignored.`
|
||||
"#,
|
||||
"
|
||||
`Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` + `\"${unexpectedKeys.join('\", \
|
||||
\"')}\" found in ${argumentName}. ` + `Expected to find one of the known reducer keys \
|
||||
instead: ` + `\"${reducerKeys.join('\", \"')}\". Unexpected keys will be ignored.`;
|
||||
",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn integration_01_reduced_01() {
|
||||
test_from_to(
|
||||
r#"
|
||||
`Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` +
|
||||
`"${unexpectedKeys.join('", "')}" found in ${argumentName}. `
|
||||
"#,
|
||||
"
|
||||
`Unexpected ${unexpectedKeys.length > 1 ? 'keys' : 'key'} ` + `\"${unexpectedKeys.join('\", \
|
||||
\"')}\" found in ${argumentName}. `;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deno_8541_1() {
|
||||
test_from_to(
|
||||
"React.createElement('span', null, '\\u{b7}');",
|
||||
"React.createElement('span', null, '\\u{b7}');",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deno_8925() {
|
||||
assert_pretty("const 𝒫 = 2;", "const 𝒫 = 2;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Tested by a bundler test"]
|
||||
fn deno_9620() {
|
||||
assert_pretty(
|
||||
"const content = `--------------------------366796e1c748a2fb\r
|
||||
Content-Disposition: form-data; name=\"payload\"\r
|
||||
Content-Type: text/plain\r
|
||||
\r
|
||||
CONTENT\r
|
||||
--------------------------366796e1c748a2fb--`",
|
||||
"`const content = `--------------------------366796e1c748a2fb\\r\\nContent-Disposition: \
|
||||
form-data; name=\"payload\"\\r\\nContent-Type: \
|
||||
text/plain\\r\\n\\r\\nCONTENT\\r\\n--------------------------366796e1c748a2fb--`;",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_quoted_utf16() {
|
||||
#[track_caller]
|
||||
fn es2020(src: &str, expected: &str) {
|
||||
assert_eq!(
|
||||
super::get_quoted_utf16(src, true, EsVersion::Es2020),
|
||||
expected
|
||||
)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn es2020_nonascii(src: &str, expected: &str) {
|
||||
assert_eq!(
|
||||
super::get_quoted_utf16(src, true, EsVersion::Es2020),
|
||||
expected
|
||||
)
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn es5(src: &str, expected: &str) {
|
||||
assert_eq!(super::get_quoted_utf16(src, true, EsVersion::Es5), expected)
|
||||
}
|
||||
|
||||
es2020("abcde", "\"abcde\"");
|
||||
es2020(
|
||||
"\x00\r\n\u{85}\u{2028}\u{2029};",
|
||||
"\"\\x00\\r\\n\\x85\\u2028\\u2029;\"",
|
||||
);
|
||||
|
||||
es2020("\n", "\"\\n\"");
|
||||
es2020("\t", "\"\t\"");
|
||||
|
||||
es2020("'string'", "\"'string'\"");
|
||||
|
||||
es2020("\u{0}", "\"\\x00\"");
|
||||
es2020("\u{1}", "\"\\x01\"");
|
||||
|
||||
es2020("\u{1000}", "\"\\u1000\"");
|
||||
es2020("\u{ff}", "\"\\xff\"");
|
||||
es2020("\u{10ffff}", "\"\\u{10FFFF}\"");
|
||||
es2020("😀", "\"\\u{1F600}\"");
|
||||
es2020("ퟻ", "\"\\uD7FB\"");
|
||||
|
||||
es2020_nonascii("\u{FEFF}abc", "\"\\uFEFFabc\"");
|
||||
es2020_nonascii("\u{10ffff}", "\"\\u{10FFFF}\"");
|
||||
|
||||
es5("\u{FEFF}abc", "\"\\uFEFFabc\"");
|
||||
es5("\u{10ffff}", "\"\\uDBFF\\uDFFF\"");
|
||||
es5("\u{FFFF}", "\"\\uFFFF\"");
|
||||
es5("😀", "\"\\uD83D\\uDE00\"");
|
||||
es5("ퟻ", "\"\\uD7FB\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn deno_8541_2() {
|
||||
test_from_to(
|
||||
"React.createElement('span', null, '\\u00b7');",
|
||||
"React.createElement('span', null, '\\u00b7');",
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1452_1() {
|
||||
assert_min("async foo => 0", "async foo=>0");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1619_1() {
|
||||
assert_min_target(
|
||||
"\"\\x00\" + \"\\x31\"",
|
||||
"\"\\x00\"+\"1\"",
|
||||
EsVersion::latest(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1619_2() {
|
||||
assert_min_target(
|
||||
"\"\\x00\" + \"\\x31\"",
|
||||
"\"\\x00\"+\"1\"",
|
||||
EsVersion::latest(),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_1619_3() {
|
||||
assert_eq!(
|
||||
get_quoted_utf16("\x00\x31", true, EsVersion::Es3),
|
||||
"\"\\x001\""
|
||||
);
|
||||
}
|
||||
|
||||
fn check_latest(src: &str, expected: &str) {
|
||||
let actual = parse_then_emit(
|
||||
src,
|
||||
Config {
|
||||
minify: false,
|
||||
target: EsVersion::latest(),
|
||||
..Default::default()
|
||||
},
|
||||
Default::default(),
|
||||
);
|
||||
assert_eq!(expected, actual.trim());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_unicode_in_ident() {
|
||||
check_latest("\\ud83d;", "\\ud83d;");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_escape_with_source_str() {
|
||||
check_latest("'\\ud83d'", "'\\ud83d';");
|
||||
check_latest(
|
||||
"'\\ud83d\\ud83d\\ud83d\\ud83d\\ud83d'",
|
||||
"'\\ud83d\\ud83d\\ud83d\\ud83d\\ud83d';",
|
||||
);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Buf(Arc<RwLock<Vec<u8>>>);
|
||||
impl Write for Buf {
|
||||
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
|
||||
self.0.write().unwrap().write(data)
|
||||
}
|
||||
|
||||
fn flush(&mut self) -> io::Result<()> {
|
||||
self.0.write().unwrap().flush()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_2213() {
|
||||
assert_min("a - -b * c", "a- -b*c")
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_3617() {
|
||||
// Convert characters to es5 compatibility code
|
||||
let from = r"// a string of all valid unicode whitespaces
|
||||
module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
|
||||
'\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF' + '\u{a0}';";
|
||||
let expected = r#"// a string of all valid unicode whitespaces
|
||||
module.exports = " \n\v\f\r \xa0\u1680\u2000\u2001\u2002" + "\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF" + "\xa0";"#;
|
||||
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
ascii_only: true,
|
||||
target: EsVersion::Es5,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
dbg!(&out);
|
||||
dbg!(&expected);
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(out.trim()),
|
||||
DebugUsingDisplay(expected.trim()),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn issue_3617_1() {
|
||||
// Print characters as is for ECMA target > 5
|
||||
let from = r"// a string of all valid unicode whitespaces
|
||||
module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' +
|
||||
'\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF' + '\u{a0}';";
|
||||
let expected = r"// a string of all valid unicode whitespaces
|
||||
module.exports = '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u2000\u2001\u2002' + '\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028\u2029\uFEFF' + '\u{a0}';";
|
||||
|
||||
let out = parse_then_emit(
|
||||
from,
|
||||
Config {
|
||||
target: EsVersion::Es2022,
|
||||
..Default::default()
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
dbg!(&out);
|
||||
dbg!(&expected);
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(out.trim()),
|
||||
DebugUsingDisplay(expected.trim()),
|
||||
);
|
||||
}
|
||||
|
||||
fn test_all(src: &str, expected: &str, expected_minified: &str, config: Config) {
|
||||
{
|
||||
let out = parse_then_emit(
|
||||
src,
|
||||
Config {
|
||||
minify: false,
|
||||
omit_last_semi: true,
|
||||
..config
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
dbg!(out.trim());
|
||||
dbg!(expected.trim());
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(out.trim()),
|
||||
DebugUsingDisplay(expected.trim()),
|
||||
);
|
||||
}
|
||||
{
|
||||
eprintln!("> minified");
|
||||
let out = parse_then_emit(
|
||||
src,
|
||||
Config {
|
||||
minify: true,
|
||||
omit_last_semi: true,
|
||||
..config
|
||||
},
|
||||
Syntax::default(),
|
||||
);
|
||||
|
||||
dbg!(out.trim());
|
||||
dbg!(expected_minified.trim());
|
||||
|
||||
assert_eq!(
|
||||
DebugUsingDisplay(out.trim()),
|
||||
DebugUsingDisplay(expected_minified.trim()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii_only_str_1() {
|
||||
test_all(
|
||||
"'😊❤️'",
|
||||
"'😊❤️';\n",
|
||||
r#""😊❤️""#,
|
||||
Config {
|
||||
ascii_only: false,
|
||||
target: EsVersion::Es2015,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii_only_str_2() {
|
||||
test_all(
|
||||
"'😊❤️'",
|
||||
r#""\u{1F60A}\u2764\uFE0F";"#,
|
||||
r#""\u{1F60A}\u2764\uFE0F""#,
|
||||
Config {
|
||||
ascii_only: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii_only_str_3() {
|
||||
test_all(
|
||||
"'\\u{1F60A}'",
|
||||
"'\\u{1F60A}';\n",
|
||||
"\"\\u{1F60A}\"",
|
||||
Config {
|
||||
ascii_only: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii_only_tpl_lit() {
|
||||
test_all(
|
||||
"`😊❤️`",
|
||||
r"`\u{1F60A}\u{2764}\u{FE0F}`;",
|
||||
r"`\u{1F60A}\u{2764}\u{FE0F}`",
|
||||
Config {
|
||||
ascii_only: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ascii_only_issue_7240() {
|
||||
test_all(
|
||||
r#"
|
||||
export default {
|
||||
"\u3131": '\u11B0',
|
||||
}
|
||||
"#,
|
||||
r#"
|
||||
export default {
|
||||
"\u3131": '\u11B0'
|
||||
};
|
||||
"#,
|
||||
r#"export default{"\u3131":"\u11B0"}"#,
|
||||
Config {
|
||||
ascii_only: true,
|
||||
..Default::default()
|
||||
},
|
||||
);
|
||||
}
|
||||
233
third-party/vendor/swc_ecma_codegen/src/text_writer.rs
vendored
Normal file
233
third-party/vendor/swc_ecma_codegen/src/text_writer.rs
vendored
Normal file
|
|
@ -0,0 +1,233 @@
|
|||
use swc_common::Span;
|
||||
|
||||
pub use self::{basic_impl::JsWriter, semicolon::omit_trailing_semi};
|
||||
use super::*;
|
||||
|
||||
mod basic_impl;
|
||||
mod semicolon;
|
||||
|
||||
/// TODO
|
||||
pub type Symbol = Str;
|
||||
|
||||
/// Ecmascript writer.
|
||||
///
|
||||
/// Ported from `EmitWriteJs`.
|
||||
pub trait WriteJs {
|
||||
fn increase_indent(&mut self) -> Result;
|
||||
fn decrease_indent(&mut self) -> Result;
|
||||
|
||||
/// This *may* write semicolon.
|
||||
fn write_semi(&mut self, span: Option<Span>) -> Result;
|
||||
|
||||
fn write_space(&mut self) -> Result;
|
||||
fn write_keyword(&mut self, span: Option<Span>, s: &'static str) -> Result;
|
||||
fn write_operator(&mut self, span: Option<Span>, s: &str) -> Result;
|
||||
fn write_param(&mut self, s: &str) -> Result;
|
||||
fn write_property(&mut self, s: &str) -> Result;
|
||||
|
||||
fn write_line(&mut self) -> Result;
|
||||
|
||||
fn write_lit(&mut self, span: Span, s: &str) -> Result;
|
||||
fn write_comment(&mut self, s: &str) -> Result;
|
||||
|
||||
fn write_str_lit(&mut self, span: Span, s: &str) -> Result;
|
||||
fn write_str(&mut self, s: &str) -> Result;
|
||||
|
||||
fn write_symbol(&mut self, span: Span, s: &str) -> Result;
|
||||
|
||||
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result;
|
||||
|
||||
fn care_about_srcmap(&self) -> bool;
|
||||
|
||||
fn add_srcmap(&mut self, pos: BytePos) -> Result;
|
||||
|
||||
fn commit_pending_semi(&mut self) -> Result;
|
||||
}
|
||||
|
||||
impl<W> WriteJs for Box<W>
|
||||
where
|
||||
W: ?Sized + WriteJs,
|
||||
{
|
||||
#[inline]
|
||||
fn increase_indent(&mut self) -> Result {
|
||||
(**self).increase_indent()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decrease_indent(&mut self) -> Result {
|
||||
(**self).decrease_indent()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_semi(&mut self, span: Option<Span>) -> Result {
|
||||
(**self).write_semi(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_space(&mut self) -> Result {
|
||||
(**self).write_space()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_keyword(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
(**self).write_keyword(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_operator(&mut self, span: Option<Span>, s: &str) -> Result {
|
||||
(**self).write_operator(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_param(&mut self, s: &str) -> Result {
|
||||
(**self).write_param(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_property(&mut self, s: &str) -> Result {
|
||||
(**self).write_property(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_line(&mut self) -> Result {
|
||||
(**self).write_line()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_lit(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_comment(&mut self, s: &str) -> Result {
|
||||
(**self).write_comment(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_str_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_str_lit(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
(**self).write_str(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_symbol(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_symbol(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
(**self).write_punct(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn care_about_srcmap(&self) -> bool {
|
||||
(**self).care_about_srcmap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_srcmap(&mut self, pos: BytePos) -> Result {
|
||||
(**self).add_srcmap(pos)
|
||||
}
|
||||
|
||||
fn commit_pending_semi(&mut self) -> Result {
|
||||
(**self).commit_pending_semi()
|
||||
}
|
||||
}
|
||||
|
||||
impl<W> WriteJs for &'_ mut W
|
||||
where
|
||||
W: ?Sized + WriteJs,
|
||||
{
|
||||
#[inline]
|
||||
fn increase_indent(&mut self) -> Result {
|
||||
(**self).increase_indent()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decrease_indent(&mut self) -> Result {
|
||||
(**self).decrease_indent()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_semi(&mut self, span: Option<Span>) -> Result {
|
||||
(**self).write_semi(span)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_space(&mut self) -> Result {
|
||||
(**self).write_space()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_keyword(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
(**self).write_keyword(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_operator(&mut self, span: Option<Span>, s: &str) -> Result {
|
||||
(**self).write_operator(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_param(&mut self, s: &str) -> Result {
|
||||
(**self).write_param(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_property(&mut self, s: &str) -> Result {
|
||||
(**self).write_property(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_line(&mut self) -> Result {
|
||||
(**self).write_line()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_lit(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_comment(&mut self, s: &str) -> Result {
|
||||
(**self).write_comment(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_str_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_str_lit(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
(**self).write_str(s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_symbol(&mut self, span: Span, s: &str) -> Result {
|
||||
(**self).write_symbol(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
(**self).write_punct(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn care_about_srcmap(&self) -> bool {
|
||||
(**self).care_about_srcmap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_srcmap(&mut self, pos: BytePos) -> Result {
|
||||
(**self).add_srcmap(pos)
|
||||
}
|
||||
|
||||
fn commit_pending_semi(&mut self) -> Result {
|
||||
(**self).commit_pending_semi()
|
||||
}
|
||||
}
|
||||
361
third-party/vendor/swc_ecma_codegen/src/text_writer/basic_impl.rs
vendored
Normal file
361
third-party/vendor/swc_ecma_codegen/src/text_writer/basic_impl.rs
vendored
Normal file
|
|
@ -0,0 +1,361 @@
|
|||
use std::io::Write;
|
||||
|
||||
use rustc_hash::FxHashSet;
|
||||
use swc_common::{sync::Lrc, BytePos, LineCol, SourceMap, Span};
|
||||
|
||||
use super::{Result, WriteJs};
|
||||
|
||||
///
|
||||
/// -----
|
||||
///
|
||||
/// Ported from `createTextWriter` of the typescript compiler.
|
||||
///
|
||||
/// https://github.com/Microsoft/TypeScript/blob/45eaf42006/src/compiler/utilities.ts#L2548
|
||||
pub struct JsWriter<'a, W: Write> {
|
||||
indent: usize,
|
||||
indent_str: &'static str,
|
||||
line_start: bool,
|
||||
line_count: usize,
|
||||
line_pos: usize,
|
||||
new_line: &'a str,
|
||||
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
|
||||
srcmap_done: FxHashSet<(BytePos, u32, u32)>,
|
||||
/// Used to avoid including whitespaces created by indention.
|
||||
pending_srcmap: Option<BytePos>,
|
||||
wr: W,
|
||||
}
|
||||
|
||||
impl<'a, W: Write> JsWriter<'a, W> {
|
||||
pub fn new(
|
||||
_: Lrc<SourceMap>,
|
||||
new_line: &'a str,
|
||||
wr: W,
|
||||
srcmap: Option<&'a mut Vec<(BytePos, LineCol)>>,
|
||||
) -> Self {
|
||||
JsWriter {
|
||||
indent: Default::default(),
|
||||
indent_str: " ",
|
||||
line_start: true,
|
||||
line_count: 0,
|
||||
line_pos: Default::default(),
|
||||
new_line,
|
||||
srcmap,
|
||||
wr,
|
||||
pending_srcmap: Default::default(),
|
||||
srcmap_done: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn preamble(&mut self, s: &str) -> Result {
|
||||
self.raw_write(s)?;
|
||||
self.update_pos(s);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the indentation string. Defaults to four spaces.
|
||||
pub fn set_indent_str(&mut self, indent_str: &'static str) {
|
||||
self.indent_str = indent_str;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_indent_string(&mut self) -> Result {
|
||||
for _ in 0..self.indent {
|
||||
self.raw_write(self.indent_str)?;
|
||||
}
|
||||
if self.srcmap.is_some() {
|
||||
self.line_pos += self.indent_str.len() * self.indent;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn raw_write(&mut self, data: &str) -> Result {
|
||||
// #[cfg(debug_assertions)]
|
||||
// tracing::trace!("Write: `{}`", data);
|
||||
self.wr.write_all(data.as_bytes())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write(&mut self, span: Option<Span>, data: &str) -> Result {
|
||||
if !data.is_empty() {
|
||||
if self.line_start {
|
||||
self.write_indent_string()?;
|
||||
self.line_start = false;
|
||||
|
||||
if let Some(pending) = self.pending_srcmap.take() {
|
||||
self.srcmap(pending);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(span) = span {
|
||||
self.srcmap(span.lo());
|
||||
}
|
||||
|
||||
self.raw_write(data)?;
|
||||
self.update_pos(data);
|
||||
|
||||
if let Some(span) = span {
|
||||
self.srcmap(span.hi());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn update_pos(&mut self, s: &str) {
|
||||
if self.srcmap.is_some() {
|
||||
let line_start_of_s = compute_line_starts(s);
|
||||
self.line_count += line_start_of_s.line_count;
|
||||
|
||||
let chars = s[line_start_of_s.byte_pos..].encode_utf16().count();
|
||||
if line_start_of_s.line_count > 0 {
|
||||
self.line_pos = chars;
|
||||
} else {
|
||||
self.line_pos += chars;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn srcmap(&mut self, byte_pos: BytePos) {
|
||||
if byte_pos.is_dummy() && byte_pos != BytePos(u32::MAX) {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(ref mut srcmap) = self.srcmap {
|
||||
if self
|
||||
.srcmap_done
|
||||
.insert((byte_pos, self.line_count as _, self.line_pos as _))
|
||||
{
|
||||
let loc = LineCol {
|
||||
line: self.line_count as _,
|
||||
col: self.line_pos as _,
|
||||
};
|
||||
|
||||
// #[cfg(debug_assertions)]
|
||||
// tracing::trace!("SourceMap: {:?} => {:?}", byte_pos, loc);
|
||||
|
||||
srcmap.push((byte_pos, loc));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, W: Write> WriteJs for JsWriter<'a, W> {
|
||||
#[inline]
|
||||
fn increase_indent(&mut self) -> Result {
|
||||
self.indent += 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn decrease_indent(&mut self) -> Result {
|
||||
self.indent -= 1;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn write_semi(&mut self, span: Option<Span>) -> Result {
|
||||
self.write(span, ";")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_space(&mut self) -> Result {
|
||||
self.write(None, " ")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_keyword(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
self.write(span, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_operator(&mut self, span: Option<Span>, s: &str) -> Result {
|
||||
self.write(span, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_param(&mut self, s: &str) -> Result {
|
||||
self.write(None, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_property(&mut self, s: &str) -> Result {
|
||||
self.write(None, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_line(&mut self) -> Result {
|
||||
let pending = self.pending_srcmap.take();
|
||||
if !self.line_start {
|
||||
self.raw_write(self.new_line)?;
|
||||
if self.srcmap.is_some() {
|
||||
self.line_count += 1;
|
||||
self.line_pos = 0;
|
||||
}
|
||||
self.line_start = true;
|
||||
|
||||
if let Some(pending) = pending {
|
||||
self.srcmap(pending)
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
if !s.is_empty() {
|
||||
self.srcmap(span.lo());
|
||||
self.write(None, s)?;
|
||||
self.srcmap(span.hi());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_comment(&mut self, s: &str) -> Result {
|
||||
self.write(None, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_str_lit(&mut self, span: Span, s: &str) -> Result {
|
||||
if !s.is_empty() {
|
||||
self.srcmap(span.lo());
|
||||
self.write(None, s)?;
|
||||
self.srcmap(span.hi());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_str(&mut self, s: &str) -> Result {
|
||||
self.write(None, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_symbol(&mut self, span: Span, s: &str) -> Result {
|
||||
self.write(Some(span), s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
self.write(span, s)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn care_about_srcmap(&self) -> bool {
|
||||
self.srcmap.is_some()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn add_srcmap(&mut self, pos: BytePos) -> Result {
|
||||
if self.srcmap.is_some() {
|
||||
if self.line_start {
|
||||
self.pending_srcmap = Some(pos);
|
||||
} else {
|
||||
self.srcmap(pos);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn commit_pending_semi(&mut self) -> Result {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LineStart {
|
||||
line_count: usize,
|
||||
byte_pos: usize,
|
||||
}
|
||||
fn compute_line_starts(s: &str) -> LineStart {
|
||||
let mut count = 0;
|
||||
let mut line_start = 0;
|
||||
|
||||
let mut chars = s.as_bytes().iter().enumerate().peekable();
|
||||
|
||||
while let Some((pos, c)) = chars.next() {
|
||||
match c {
|
||||
b'\r' => {
|
||||
count += 1;
|
||||
if let Some(&(_, b'\n')) = chars.peek() {
|
||||
let _ = chars.next();
|
||||
line_start = pos + 2
|
||||
} else {
|
||||
line_start = pos + 1
|
||||
}
|
||||
}
|
||||
|
||||
b'\n' => {
|
||||
count += 1;
|
||||
line_start = pos + 1;
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
LineStart {
|
||||
line_count: count,
|
||||
byte_pos: line_start,
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::sync::Arc;
|
||||
|
||||
use swc_common::SourceMap;
|
||||
|
||||
use super::JsWriter;
|
||||
use crate::text_writer::WriteJs;
|
||||
|
||||
#[test]
|
||||
fn changes_indent_str() {
|
||||
let source_map = Arc::new(SourceMap::default());
|
||||
let mut output = Vec::new();
|
||||
let mut writer = JsWriter::new(source_map, "\n", &mut output, None);
|
||||
writer.set_indent_str("\t");
|
||||
writer.increase_indent().unwrap();
|
||||
writer.write_indent_string().unwrap();
|
||||
writer.increase_indent().unwrap();
|
||||
writer.write_indent_string().unwrap();
|
||||
assert_eq!(output, "\t\t\t".as_bytes());
|
||||
}
|
||||
}
|
||||
100
third-party/vendor/swc_ecma_codegen/src/text_writer/semicolon.rs
vendored
Normal file
100
third-party/vendor/swc_ecma_codegen/src/text_writer/semicolon.rs
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
use swc_common::{BytePos, Span, DUMMY_SP};
|
||||
|
||||
use super::{Result, WriteJs};
|
||||
|
||||
pub fn omit_trailing_semi<W: WriteJs>(w: W) -> impl WriteJs {
|
||||
OmitTrailingSemi {
|
||||
inner: w,
|
||||
pending_semi: None,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct OmitTrailingSemi<W: WriteJs> {
|
||||
inner: W,
|
||||
pending_semi: Option<Span>,
|
||||
}
|
||||
|
||||
macro_rules! with_semi {
|
||||
(
|
||||
$fn_name:ident
|
||||
(
|
||||
$(
|
||||
$arg_name:ident
|
||||
:
|
||||
$arg_ty:ty
|
||||
),*
|
||||
)
|
||||
) => {
|
||||
fn $fn_name(&mut self, $($arg_name: $arg_ty),* ) -> Result {
|
||||
self.commit_pending_semi()?;
|
||||
|
||||
self.inner.$fn_name( $($arg_name),* )
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl<W: WriteJs> WriteJs for OmitTrailingSemi<W> {
|
||||
with_semi!(increase_indent());
|
||||
|
||||
with_semi!(decrease_indent());
|
||||
|
||||
with_semi!(write_space());
|
||||
|
||||
with_semi!(write_comment(s: &str));
|
||||
|
||||
with_semi!(write_keyword(span: Option<Span>, s: &'static str));
|
||||
|
||||
with_semi!(write_operator(span: Option<Span>, s: &str));
|
||||
|
||||
with_semi!(write_param(s: &str));
|
||||
|
||||
with_semi!(write_property(s: &str));
|
||||
|
||||
with_semi!(write_line());
|
||||
|
||||
with_semi!(write_lit(span: Span, s: &str));
|
||||
|
||||
with_semi!(write_str_lit(span: Span, s: &str));
|
||||
|
||||
with_semi!(write_str(s: &str));
|
||||
|
||||
with_semi!(write_symbol(span: Span, s: &str));
|
||||
|
||||
fn write_semi(&mut self, span: Option<Span>) -> Result {
|
||||
self.pending_semi = Some(span.unwrap_or(DUMMY_SP));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn write_punct(&mut self, span: Option<Span>, s: &'static str) -> Result {
|
||||
match s {
|
||||
"\"" | "'" | "[" | "!" | "/" | "{" | "(" | "~" | "-" | "+" | "#" | "`" | "*" => {
|
||||
self.commit_pending_semi()?;
|
||||
}
|
||||
|
||||
_ => {
|
||||
self.pending_semi = None;
|
||||
}
|
||||
}
|
||||
|
||||
self.inner.write_punct(span, s)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn care_about_srcmap(&self) -> bool {
|
||||
self.inner.care_about_srcmap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn add_srcmap(&mut self, pos: BytePos) -> Result {
|
||||
self.inner.add_srcmap(pos)
|
||||
}
|
||||
|
||||
fn commit_pending_semi(&mut self) -> Result {
|
||||
if let Some(span) = self.pending_semi {
|
||||
self.inner.write_semi(Some(span))?;
|
||||
self.pending_semi = None;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
1135
third-party/vendor/swc_ecma_codegen/src/typescript.rs
vendored
Normal file
1135
third-party/vendor/swc_ecma_codegen/src/typescript.rs
vendored
Normal file
File diff suppressed because it is too large
Load diff
250
third-party/vendor/swc_ecma_codegen/src/util.rs
vendored
Normal file
250
third-party/vendor/swc_ecma_codegen/src/util.rs
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
use swc_ecma_ast::*;
|
||||
|
||||
pub trait EndsWithAlphaNum {
|
||||
fn ends_with_alpha_num(&self) -> bool;
|
||||
}
|
||||
|
||||
impl EndsWithAlphaNum for ForHead {
|
||||
fn ends_with_alpha_num(&self) -> bool {
|
||||
match self {
|
||||
ForHead::VarDecl(n) => n.ends_with_alpha_num(),
|
||||
ForHead::Pat(n) => n.ends_with_alpha_num(),
|
||||
ForHead::UsingDecl(n) => n.ends_with_alpha_num(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EndsWithAlphaNum for Pat {
|
||||
fn ends_with_alpha_num(&self) -> bool {
|
||||
match self {
|
||||
Pat::Object(_) | Pat::Array(_) => false,
|
||||
Pat::Rest(p) => p.arg.ends_with_alpha_num(),
|
||||
Pat::Assign(p) => p.right.ends_with_alpha_num(),
|
||||
Pat::Expr(p) => p.ends_with_alpha_num(),
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EndsWithAlphaNum for VarDecl {
|
||||
fn ends_with_alpha_num(&self) -> bool {
|
||||
match self.decls.last() {
|
||||
None => true,
|
||||
Some(d) => match d.init.as_deref() {
|
||||
Some(e) => e.ends_with_alpha_num(),
|
||||
None => d.name.ends_with_alpha_num(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EndsWithAlphaNum for UsingDecl {
|
||||
fn ends_with_alpha_num(&self) -> bool {
|
||||
match self.decls.last() {
|
||||
None => true,
|
||||
Some(d) => match d.init.as_deref() {
|
||||
Some(e) => e.ends_with_alpha_num(),
|
||||
None => d.name.ends_with_alpha_num(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl EndsWithAlphaNum for Expr {
|
||||
fn ends_with_alpha_num(&self) -> bool {
|
||||
!matches!(
|
||||
self,
|
||||
Expr::Array(..)
|
||||
| Expr::Object(..)
|
||||
| Expr::Lit(Lit::Str(..))
|
||||
| Expr::Paren(..)
|
||||
| Expr::Member(MemberExpr {
|
||||
prop: MemberProp::Computed(..),
|
||||
..
|
||||
})
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Leftmost recursion
|
||||
pub trait StartsWithAlphaNum {
|
||||
fn starts_with_alpha_num(&self) -> bool;
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for PropName {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match self {
|
||||
PropName::Str(_) | PropName::Computed(_) => false,
|
||||
PropName::Ident(_) | PropName::Num(_) | PropName::BigInt(_) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for Expr {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match self {
|
||||
Expr::Ident(_)
|
||||
| Expr::Lit(Lit::Bool(_))
|
||||
| Expr::Lit(Lit::Num(_))
|
||||
| Expr::Lit(Lit::Null(_))
|
||||
| Expr::Lit(Lit::BigInt(_))
|
||||
| Expr::Await(_)
|
||||
| Expr::Fn(_)
|
||||
| Expr::Class(_)
|
||||
| Expr::This(_)
|
||||
| Expr::Yield(_)
|
||||
| Expr::New(_)
|
||||
| Expr::MetaProp(_)
|
||||
| Expr::SuperProp(_) => true,
|
||||
|
||||
Expr::PrivateName(_) => false,
|
||||
|
||||
// Handle other literals.
|
||||
Expr::Lit(_) => false,
|
||||
|
||||
Expr::Seq(SeqExpr { ref exprs, .. }) => exprs
|
||||
.first()
|
||||
.map(|e| e.starts_with_alpha_num())
|
||||
.unwrap_or(false),
|
||||
|
||||
//
|
||||
Expr::Assign(AssignExpr { ref left, .. }) => left.starts_with_alpha_num(),
|
||||
|
||||
Expr::Bin(BinExpr { ref left, .. }) | Expr::Cond(CondExpr { test: ref left, .. }) => {
|
||||
left.starts_with_alpha_num()
|
||||
}
|
||||
Expr::Call(CallExpr { callee: left, .. }) => left.starts_with_alpha_num(),
|
||||
Expr::Member(MemberExpr { obj: ref left, .. }) => left.starts_with_alpha_num(),
|
||||
|
||||
Expr::Unary(UnaryExpr { op, .. }) => {
|
||||
matches!(op, op!("void") | op!("delete") | op!("typeof"))
|
||||
}
|
||||
|
||||
Expr::Arrow(ref expr) => {
|
||||
if expr.is_async {
|
||||
true
|
||||
} else {
|
||||
match expr.params.as_slice() {
|
||||
[p] => p.starts_with_alpha_num(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Update(ref expr) => {
|
||||
if expr.prefix {
|
||||
false
|
||||
} else {
|
||||
expr.arg.starts_with_alpha_num()
|
||||
}
|
||||
}
|
||||
|
||||
Expr::Tpl(_) | Expr::Array(_) | Expr::Object(_) | Expr::Paren(_) => false,
|
||||
|
||||
Expr::TaggedTpl(TaggedTpl { ref tag, .. }) => tag.starts_with_alpha_num(),
|
||||
|
||||
// it's empty
|
||||
Expr::JSXEmpty(..) => false,
|
||||
// start with `<`
|
||||
Expr::JSXFragment(..) | Expr::JSXElement(..) => false,
|
||||
Expr::JSXNamespacedName(..) => true,
|
||||
Expr::JSXMember(..) => true,
|
||||
|
||||
Expr::TsTypeAssertion(..) => false,
|
||||
Expr::TsNonNull(TsNonNullExpr { ref expr, .. })
|
||||
| Expr::TsAs(TsAsExpr { ref expr, .. })
|
||||
| Expr::TsConstAssertion(TsConstAssertion { ref expr, .. })
|
||||
| Expr::TsInstantiation(TsInstantiation { ref expr, .. })
|
||||
| Expr::TsSatisfies(TsSatisfiesExpr { ref expr, .. }) => expr.starts_with_alpha_num(),
|
||||
|
||||
Expr::OptChain(OptChainExpr { base, .. }) => match &**base {
|
||||
OptChainBase::Member(base) => base.obj.starts_with_alpha_num(),
|
||||
OptChainBase::Call(base) => base.callee.starts_with_alpha_num(),
|
||||
},
|
||||
|
||||
Expr::Invalid(..) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for Pat {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
Pat::Ident(..) => true,
|
||||
Pat::Assign(AssignPat { ref left, .. }) => left.starts_with_alpha_num(),
|
||||
Pat::Object(..) | Pat::Array(..) | Pat::Rest(..) => false,
|
||||
Pat::Expr(ref expr) => expr.starts_with_alpha_num(),
|
||||
Pat::Invalid(..) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for PatOrExpr {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
PatOrExpr::Pat(ref p) => p.starts_with_alpha_num(),
|
||||
PatOrExpr::Expr(ref e) => e.starts_with_alpha_num(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for ExprOrSpread {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
ExprOrSpread {
|
||||
spread: Some(_), ..
|
||||
} => false,
|
||||
ExprOrSpread {
|
||||
spread: None,
|
||||
ref expr,
|
||||
} => expr.starts_with_alpha_num(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl StartsWithAlphaNum for Callee {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
Callee::Super(_) | Callee::Import(_) => true,
|
||||
Callee::Expr(ref e) => e.starts_with_alpha_num(),
|
||||
}
|
||||
}
|
||||
}
|
||||
impl StartsWithAlphaNum for Stmt {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
Stmt::Expr(ref expr) => expr.expr.starts_with_alpha_num(),
|
||||
Stmt::Decl(ref decl) => decl.starts_with_alpha_num(),
|
||||
Stmt::Debugger(..)
|
||||
| Stmt::With(..)
|
||||
| Stmt::While(..)
|
||||
| Stmt::DoWhile(..)
|
||||
| Stmt::Return(..)
|
||||
| Stmt::Labeled(..)
|
||||
| Stmt::Break(..)
|
||||
| Stmt::Continue(..)
|
||||
| Stmt::Switch(..)
|
||||
| Stmt::Throw(..)
|
||||
| Stmt::Try(..)
|
||||
| Stmt::For(..)
|
||||
| Stmt::ForIn(..)
|
||||
| Stmt::ForOf(..)
|
||||
| Stmt::If(..) => true,
|
||||
Stmt::Block(..) | Stmt::Empty(..) => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl StartsWithAlphaNum for Decl {
|
||||
fn starts_with_alpha_num(&self) -> bool {
|
||||
match *self {
|
||||
Decl::Class(..)
|
||||
| Decl::Fn(..)
|
||||
| Decl::Var(..)
|
||||
| Decl::TsEnum(..)
|
||||
| Decl::TsInterface(..)
|
||||
| Decl::TsModule(..)
|
||||
| Decl::TsTypeAlias(..)
|
||||
| Decl::Using(..) => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue