fix(es/transforms/typescript): Fix strip (#2496)

swc_ecma_transforms_typescript:
 - Visit the RHS of import equals declaration properly.
This commit is contained in:
Nayeem Rahman 2021-10-21 07:12:51 +01:00 committed by GitHub
parent 7af0f8c81b
commit c29a6e11c9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 98 additions and 76 deletions

2
Cargo.lock generated
View File

@ -2981,7 +2981,7 @@ dependencies = [
[[package]] [[package]]
name = "swc_ecma_transforms_typescript" name = "swc_ecma_transforms_typescript"
version = "0.54.0" version = "0.54.1"
dependencies = [ dependencies = [
"serde", "serde",
"swc_atoms 0.2.9", "swc_atoms 0.2.9",

View File

@ -6,7 +6,7 @@ edition = "2018"
license = "Apache-2.0/MIT" license = "Apache-2.0/MIT"
name = "swc_ecma_transforms_typescript" name = "swc_ecma_transforms_typescript"
repository = "https://github.com/swc-project/swc.git" repository = "https://github.com/swc-project/swc.git"
version = "0.54.0" version = "0.54.1"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]

View File

@ -280,6 +280,10 @@ struct DeclInfo {
has_type: bool, has_type: bool,
/// Var, Fn, Class /// Var, Fn, Class
has_concrete: bool, has_concrete: bool,
/// In `import foo = bar.baz`, `foo`'s dependency is `bar`. This means that
/// when setting `has_concrete` for `foo`, it must also be set for
/// `bar`.
maybe_dependency: Option<Ident>,
} }
impl<C> Strip<C> impl<C> Strip<C>
@ -1370,10 +1374,22 @@ where
} }
fn visit_ident(&mut self, n: &Ident, _: &dyn Node) { fn visit_ident(&mut self, n: &Ident, _: &dyn Node) {
let is_type_only_export = self.is_type_only_export;
let entry = self.scope.referenced_idents.entry(n.to_id()).or_default(); let entry = self.scope.referenced_idents.entry(n.to_id()).or_default();
entry.has_concrete |= !is_type_only_export; if self.is_type_only_export {
entry.has_type = true;
} else {
entry.has_concrete = true;
}
if let Some(i) = &entry.maybe_dependency {
let id = i.to_id();
if let Some(entry) = self.scope.referenced_idents.get_mut(&id) {
if self.is_type_only_export {
entry.has_type = true;
} else {
entry.has_concrete = true;
}
}
}
n.visit_children_with(self); n.visit_children_with(self);
} }
@ -1439,14 +1455,41 @@ where
fn visit_ts_entity_name(&mut self, name: &TsEntityName, _: &dyn Node) { fn visit_ts_entity_name(&mut self, name: &TsEntityName, _: &dyn Node) {
match *name { match *name {
TsEntityName::Ident(ref i) => { TsEntityName::Ident(ref i) => {
let entry = self.scope.referenced_idents.entry(i.to_id()).or_default();
entry.has_type = true;
if let Some(i) = &entry.maybe_dependency {
let id = i.to_id();
if let Some(entry) = self.scope.referenced_idents.get_mut(&id) {
entry.has_type = true;
}
}
}
TsEntityName::TsQualifiedName(ref q) => q.left.visit_with(&*q, self),
}
}
fn visit_ts_import_equals_decl(&mut self, n: &TsImportEqualsDecl, _: &dyn Node) {
match &n.module_ref {
TsModuleRef::TsEntityName(name) => {
let entry = self let entry = self
.scope .scope
.referenced_idents .referenced_idents
.entry((i.sym.clone(), i.span.ctxt())) .entry(n.id.to_id())
.or_default(); .or_default();
entry.has_type = true; let mut name = name;
loop {
match name {
TsEntityName::Ident(ref i) => {
entry.maybe_dependency = Some(i.clone());
break;
}
TsEntityName::TsQualifiedName(ref q) => name = &q.left,
}
}
}
_ => {
n.visit_children_with(self);
} }
TsEntityName::TsQualifiedName(ref q) => q.left.visit_with(&*q, self),
} }
} }
} }
@ -2080,7 +2123,16 @@ where
} }
ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => { ModuleItem::ModuleDecl(ModuleDecl::TsImportEquals(import)) => {
if !import.is_type_only { let maybe_entry = self.scope.referenced_idents.get(&import.id.to_id());
let has_concrete = if let Some(entry) = maybe_entry {
entry.has_concrete
} else {
true
};
// TODO(nayeemrmn): For some reason TSC preserves `import foo = bar.baz`
// when `bar.baz` is not defined, even if `foo` goes unused. We can't currently
// identify that case so we strip it anyway.
if !import.is_type_only && (has_concrete || import.is_export) {
let var = Decl::Var(VarDecl { let var = Decl::Var(VarDecl {
span: DUMMY_SP, span: DUMMY_SP,
kind: VarDeclKind::Var, kind: VarDeclKind::Var,

View File

@ -462,8 +462,6 @@ to!(module_01, "module 'foo'{ }", "");
to!(declare_01, "declare var env: FOO", ""); to!(declare_01, "declare var env: FOO", "");
to!(import_equals, "import A = B.C", "var A = B.C;");
to!( to!(
issue_757, issue_757,
"// test.ts "// test.ts
@ -4076,7 +4074,7 @@ to!(
export { TestInfo } export { TestInfo }
", ",
" "
" "
); );
@ -4116,6 +4114,32 @@ Foo.identifier = 5;
" "
); );
to!(
deno_12395_import_equals_1,
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
import MongoClient = mongo.MongoClient;
const mongoClient = new MongoClient();
",
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
var MongoClient = mongo.MongoClient;
const mongoClient = new MongoClient();
"
);
to!(
deno_12395_import_equals_2,
"
import * as mongo from 'https://deno.land/x/mongo@v0.27.0/mod.ts';
import MongoClient = mongo.MongoClient;
const mongoClient: MongoClient = {};
",
"
const mongoClient = {};
"
);
#[testing::fixture("tests/fixture/**/input.ts")] #[testing::fixture("tests/fixture/**/input.ts")]
#[testing::fixture("tests/fixture/**/input.tsx")] #[testing::fixture("tests/fixture/**/input.tsx")]
fn exec(input: PathBuf) { fn exec(input: PathBuf) {

View File

@ -16,7 +16,6 @@ export { E11 as E1 };
})); }));
// @Filename: foo_1.ts // @Filename: foo_1.ts
const foo = require("./foo_0"); const foo = require("./foo_0");
var f = foo.M1;
var i; var i;
var x = { var x = {
}; };

View File

@ -5,6 +5,4 @@ export class C1 {
} }
} }
C1.s1 = !0, (E1 = E11 || (E11 = { C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C"; }))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");
const foo = require("./foo_0");
foo.M1;

View File

@ -21,7 +21,6 @@ export { E11 as E1 };
})); }));
// @Filename: foo_1.ts // @Filename: foo_1.ts
var foo = require("./foo_0"); var foo = require("./foo_0");
var f = foo.M1;
var i; var i;
var x = { var x = {
}; };

View File

@ -1,4 +1,4 @@
var E1, foo, E11, i, z, C1 = function() { var E1, E11, i, z, C1 = function() {
"use strict"; "use strict";
!function(instance, Constructor) { !function(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
@ -6,4 +6,4 @@ var E1, foo, E11, i, z, C1 = function() {
}; };
export { E11 as E1 }; export { E11 as E1 };
C1.s1 = !0, (E1 = E11 || (E11 = { C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0").M1; }))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -16,7 +16,6 @@ export { E11 as E1 };
})); }));
// @Filename: foo_1.ts // @Filename: foo_1.ts
const foo = require("./foo_0"); const foo = require("./foo_0");
var f = foo.M1;
var i; var i;
var x = { var x = {
}; };

View File

@ -5,6 +5,4 @@ export class C1 {
} }
} }
C1.s1 = !0, (E1 = E11 || (E11 = { C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C"; }))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");
const foo = require("./foo_0");
foo.M1;

View File

@ -21,7 +21,6 @@ export { E11 as E1 };
})); }));
// @Filename: foo_1.ts // @Filename: foo_1.ts
var foo = require("./foo_0"); var foo = require("./foo_0");
var f = foo.M1;
var i; var i;
var x = { var x = {
}; };

View File

@ -1,4 +1,4 @@
var E1, foo, E11, i, z, C1 = function() { var E1, E11, i, z, C1 = function() {
"use strict"; "use strict";
!function(instance, Constructor) { !function(instance, Constructor) {
if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function"); if (!(instance instanceof Constructor)) throw new TypeError("Cannot call a class as a function");
@ -6,4 +6,4 @@ var E1, foo, E11, i, z, C1 = function() {
}; };
export { E11 as E1 }; export { E11 as E1 };
C1.s1 = !0, (E1 = E11 || (E11 = { C1.s1 = !0, (E1 = E11 || (E11 = {
}))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0").M1; }))[E1.A = 0] = "A", E1[E1.B = 1] = "B", E1[E1.C = 2] = "C", require("./foo_0");

View File

@ -1,14 +1,6 @@
// no code gen expected // no code gen expected
var B;
(function(B) {
var a = A;
})(B || (B = {
}));
// no code gen expected
var C; var C;
(function(C) { (function(C) {
var a = A;
var b = a.inA;
var m; var m;
var p; var p;
var p = { var p = {
@ -21,14 +13,12 @@ var C;
// no code gen expected // no code gen expected
var D; var D;
(function(D) { (function(D) {
var a = A;
var p; var p;
})(D || (D = { })(D || (D = {
})); }));
// no code gen expected // no code gen expected
var E1; var E1;
(function(E) { (function(E) {
var a = A.inA;
function xDist(x) { function xDist(x) {
return 0 - x.x; return 0 - x.x;
} }

View File

@ -1,14 +1,6 @@
// no code gen expected // no code gen expected
var B;
(function(B) {
var a = A;
})(B || (B = {
}));
// no code gen expected
var C; var C;
(function(C) { (function(C) {
var a = A;
var b = a.inA;
var m; var m;
var p; var p;
var p = { var p = {
@ -21,7 +13,6 @@ var C;
// no code gen expected // no code gen expected
var D; var D;
(function(D) { (function(D) {
var a = A;
var p; var p;
})(D || (D = { })(D || (D = {
})); }));
@ -31,7 +22,6 @@ var E1;
var xDist = function xDist(x) { var xDist = function xDist(x) {
return 0 - x.x; return 0 - x.x;
}; };
var a = A.inA;
E.xDist = xDist; E.xDist = xDist;
})(E1 || (E1 = { })(E1 || (E1 = {
})); }));

View File

@ -9,7 +9,6 @@ var moduleA1;
moduleA.Point = Point; moduleA.Point = Point;
})(moduleA1 || (moduleA1 = { })(moduleA1 || (moduleA1 = {
})); }));
var alias = moduleA1;
var p; var p;
var p; var p;
var p; var p;
@ -22,7 +21,6 @@ class clodule {
}; };
})(clodule || (clodule = { })(clodule || (clodule = {
})); }));
var clolias = clodule;
var p; var p;
var p; var p;
var p; var p;
@ -39,7 +37,6 @@ function fundule() {
}; };
})(fundule || (fundule = { })(fundule || (fundule = {
})); }));
var funlias = fundule;
var p; var p;
var p; var p;
var p; var p;

View File

@ -14,7 +14,6 @@ var moduleA1;
moduleA.Point = Point; moduleA.Point = Point;
})(moduleA1 || (moduleA1 = { })(moduleA1 || (moduleA1 = {
})); }));
var alias = moduleA1;
var p; var p;
var p; var p;
var p; var p;
@ -29,7 +28,6 @@ var clodule = function clodule() {
}; };
})(clodule || (clodule = { })(clodule || (clodule = {
})); }));
var clolias = clodule;
var p; var p;
var p; var p;
var p; var p;
@ -46,7 +44,6 @@ function fundule() {
}; };
})(fundule || (fundule = { })(fundule || (fundule = {
})); }));
var funlias = fundule;
var p; var p;
var p; var p;
var p; var p;

View File

@ -1,15 +1,11 @@
// none of these should work, since non are actually modules // none of these should work, since non are actually modules
var V = 12; var V = 12;
var v = V;
class C { class C {
} }
var c = C;
var E1; var E1;
(function(E) { (function(E) {
E[E["Red"] = 0] = "Red"; E[E["Red"] = 0] = "Red";
E[E["Blue"] = 1] = "Blue"; E[E["Blue"] = 1] = "Blue";
})(E1 || (E1 = { })(E1 || (E1 = {
})); }));
var e = E1;
var i = I;
export { }; export { };

View File

@ -5,18 +5,14 @@ function _classCallCheck(instance, Constructor) {
} }
// none of these should work, since non are actually modules // none of these should work, since non are actually modules
var V = 12; var V = 12;
var v = V;
var C = function C() { var C = function C() {
"use strict"; "use strict";
_classCallCheck(this, C); _classCallCheck(this, C);
}; };
var c = C;
var E1; var E1;
(function(E) { (function(E) {
E[E["Red"] = 0] = "Red"; E[E["Red"] = 0] = "Red";
E[E["Blue"] = 1] = "Blue"; E[E["Blue"] = 1] = "Blue";
})(E1 || (E1 = { })(E1 || (E1 = {
})); }));
var e = E1;
var i = I;
export { }; export { };

View File

@ -13,7 +13,6 @@ var B;
x: 0, x: 0,
y: 0 y: 0
}; };
var Point = A;
})(B || (B = { })(B || (B = {
})); }));
var X1; var X1;
@ -25,7 +24,6 @@ var X1;
})); }));
var Z; var Z;
(function(Z) { (function(Z) {
var Y = X1.Y;
var Y = 12; var Y = 12;
})(Z || (Z = { })(Z || (Z = {
})); }));

View File

@ -1,9 +1,8 @@
var A, X, Z; var A, X;
(A || (A = { (A || (A = {
})).Point = { })).Point = {
x: 0, x: 0,
y: 0 y: 0
}, (X || (X = { }, (X || (X = {
})).Y = class { })).Y = class {
}, Z || (Z = { };
}), X.Y;

View File

@ -18,7 +18,6 @@ var B;
x: 0, x: 0,
y: 0 y: 0
}; };
var Point = A;
})(B || (B = { })(B || (B = {
})); }));
var X1; var X1;
@ -32,7 +31,6 @@ var X1;
})); }));
var Z; var Z;
(function(Z) { (function(Z) {
var Y = X1.Y;
var Y = 12; var Y = 12;
})(Z || (Z = { })(Z || (Z = {
})); }));

View File

@ -1,4 +1,4 @@
var A, X1, Z; var A, X1;
(A || (A = { (A || (A = {
})).Point = { })).Point = {
x: 0, x: 0,
@ -12,5 +12,4 @@ var A, X1, Z;
}; };
X.Y = Y; X.Y = Y;
})(X1 || (X1 = { })(X1 || (X1 = {
})), Z || (Z = { }));
}), X1.Y;

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { }; export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { }; export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { }; export { };

View File

@ -1,2 +1 @@
var TypeScript = TypeScriptServices.TypeScript;
export { }; export { };

View File

@ -25,7 +25,6 @@ var M1;
})); }));
export var r6; export var r6;
export var r7; export var r7;
var Z = M1;
export var r8; export var r8;
export var r9; export var r9;
var E1; var E1;

View File

@ -34,7 +34,6 @@ var M1;
})); }));
export var r6; export var r6;
export var r7; export var r7;
var Z = M1;
export var r8; export var r8;
export var r9; export var r9;
var E1; var E1;