From 2cf0b2e2dec5b05d7538677f5a86bfb49ef8d834 Mon Sep 17 00:00:00 2001 From: magic-akari Date: Thu, 7 Sep 2023 23:05:05 +0800 Subject: [PATCH] chore: add docs --- .../src/strip_import_export.rs | 5 ++ .../src/transform.rs | 52 ++++++++++++++----- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs index 1c684217d6e3f..293c9a5fcc649 100644 --- a/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs +++ b/crates/swc_ecma_transforms_typescript/src/strip_import_export.rs @@ -226,6 +226,11 @@ impl DeclareCollect { /// These steps match tsc behavior: /// 1. Remove all import bindings that are not used. /// 2. Remove all export bindings that are defined as types. +/// 3. If a local value declaration shares a name with an imported binding, +/// treat the imported binding as a type import. +/// 4. If a local type declaration shares a name with an imported binding and +/// it's used in a value position, treat the imported binding as a value +/// import. #[derive(Default)] pub(crate) struct StripImportExport { pub id_usage: AHashSet, diff --git a/crates/swc_ecma_transforms_typescript/src/transform.rs b/crates/swc_ecma_transforms_typescript/src/transform.rs index 9e89e44736ac6..1f9fb1e783711 100644 --- a/crates/swc_ecma_transforms_typescript/src/transform.rs +++ b/crates/swc_ecma_transforms_typescript/src/transform.rs @@ -500,6 +500,7 @@ impl Transform { member_name: name.clone(), }; + // Never store TsEnumRecordValue::Opaque value in the record. let value = if value.is_const() { value.clone() } else { @@ -579,6 +580,40 @@ impl Transform { } } + /// Note: + /// Const exported declarations are transformed into immutable bindings. + /// `export` from `export let` / ` export var` will be stripped, + /// and a mutable binding will be created by `Object.defineProperty`. + /// + /// Exported function and class will be treat as const exported which is in + /// line with how the TypeScript compiler handles exports. + /// + /// Inline exported syntax should not be used with function which will lead + /// to issues with function hoisting. + /// + /// Input: + /// ```TypeScript + /// export const foo = init, { bar: baz } = init; + /// + /// export function a() {} + /// + /// export let b = init; + /// ``` + /// + /// Output: + /// ```TypeScript + /// const foo = NS.foo = init, { bar: baz } = { bar: NS.baz } = init; + /// + /// function a() {} + /// NS.a = a; + /// + /// let b = init; + /// Object.defineProperty(NS, "b", { + /// enumerable: true, + /// get () { return b; }, + /// set (v) { b = v; } + /// }); + /// ``` fn transform_export_var_decl_in_ts_module_block( mut var_decl: VarDecl, id: &Id, @@ -586,16 +621,6 @@ impl Transform { debug_assert!(!var_decl.declare); if var_decl.kind == VarDeclKind::Const { - // Input: - // ```TypeScript - // export const foo = init; - // export const { foo: bar } = init; - // ``` - // Output: - // ```TypeScript - // const foo = Foo.foo = init; - // const { foo: bar } = { foo: Foo.bar } = init; - // ``` var_decl.decls.iter_mut().for_each(|var_declarator| { Self::export_const_var_with_init(var_declarator, id); }); @@ -863,8 +888,9 @@ impl Transform { let mut should_inject = false; let create_require = private_ident!("_createRequire"); let require = private_ident!("__require"); - let cjs_require = quote_ident!(DUMMY_SP.apply_mark(self.unresolved_mark), "require"); - let cjs_exports = quote_ident!(DUMMY_SP.apply_mark(self.unresolved_mark), "exports"); + let global_span = DUMMY_SP.apply_mark(self.unresolved_mark); + let cjs_require = quote_ident!(global_span, "require"); + let cjs_exports = quote_ident!(global_span, "exports"); let mut cjs_export_assign = None; @@ -982,7 +1008,7 @@ impl Transform { } if should_inject { - n.inject_after_directive(vec![ + n.inject_after_directive([ // import { createRequire } from "module"; ModuleDecl::Import(ImportDecl { span: DUMMY_SP,