diff --git a/crates/swc_ecma_transforms_module/src/amd.rs b/crates/swc_ecma_transforms_module/src/amd.rs index fba2c3d07af..4fab881eb58 100644 --- a/crates/swc_ecma_transforms_module/src/amd.rs +++ b/crates/swc_ecma_transforms_module/src/amd.rs @@ -163,6 +163,7 @@ impl VisitMut for Amd { stmts.visit_mut_children_with(&mut ModuleRefRewriter { import_map, lazy_record: Default::default(), + allow_top_level_this: self.config.allow_top_level_this, is_global_this: true, }); diff --git a/crates/swc_ecma_transforms_module/src/common_js.rs b/crates/swc_ecma_transforms_module/src/common_js.rs index 836020e48fb..bf3c7a04085 100644 --- a/crates/swc_ecma_transforms_module/src/common_js.rs +++ b/crates/swc_ecma_transforms_module/src/common_js.rs @@ -139,6 +139,7 @@ impl VisitMut for Cjs { stmts.visit_mut_children_with(&mut ModuleRefRewriter { import_map, lazy_record, + allow_top_level_this: self.config.allow_top_level_this, is_global_this: true, }); diff --git a/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs b/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs index 8f3d4853ccf..593de8c7f9b 100644 --- a/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs +++ b/crates/swc_ecma_transforms_module/src/module_ref_rewriter.rs @@ -35,6 +35,8 @@ pub(crate) struct ModuleRefRewriter { pub lazy_record: AHashSet, + pub allow_top_level_this: bool, + pub is_global_this: bool, } @@ -67,7 +69,7 @@ impl VisitMut for ModuleRefRewriter { } Expr::This(ThisExpr { span }) => { - if self.is_global_this { + if !self.allow_top_level_this && self.is_global_this { *n = *undefined(*span); } } diff --git a/crates/swc_ecma_transforms_module/src/umd.rs b/crates/swc_ecma_transforms_module/src/umd.rs index 2fee6ff2aae..b217fd8e245 100644 --- a/crates/swc_ecma_transforms_module/src/umd.rs +++ b/crates/swc_ecma_transforms_module/src/umd.rs @@ -143,6 +143,7 @@ impl VisitMut for Umd { stmts.visit_mut_children_with(&mut ModuleRefRewriter { import_map, lazy_record: Default::default(), + allow_top_level_this: self.config.config.allow_top_level_this, is_global_this: true, }); diff --git a/crates/swc_ecma_transforms_module/src/util.rs b/crates/swc_ecma_transforms_module/src/util.rs index 7e67ac8602c..5f46f53c20c 100644 --- a/crates/swc_ecma_transforms_module/src/util.rs +++ b/crates/swc_ecma_transforms_module/src/util.rs @@ -14,6 +14,8 @@ use swc_ecma_utils::{ #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct Config { + #[serde(default)] + pub allow_top_level_this: bool, #[serde(default)] pub strict: bool, #[serde(default = "default_strict_mode")] @@ -34,6 +36,7 @@ pub struct Config { impl Default for Config { fn default() -> Self { Config { + allow_top_level_this: false, strict: false, strict_mode: default_strict_mode(), lazy: Lazy::default(), diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/input.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/input.js new file mode 100644 index 00000000000..91f17159012 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/input.js @@ -0,0 +1 @@ +export var v = this; diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/module.json b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/module.json new file mode 100644 index 00000000000..ef6da865a13 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/module.json @@ -0,0 +1,3 @@ +{ + "allowTopLevelThis": false +} \ No newline at end of file diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.amd.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.amd.js new file mode 100644 index 00000000000..09e8ea8a257 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.amd.js @@ -0,0 +1,14 @@ +define([ + "require", + "exports" +], function(require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v + }); + var v = void 0; +}); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.cjs b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.cjs new file mode 100644 index 00000000000..e0e1c9bf9e6 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.cjs @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v +}); +var v = void 0; diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.umd.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.umd.js new file mode 100644 index 00000000000..51054ce6224 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/false/output.umd.js @@ -0,0 +1,17 @@ +(function(global, factory) { + if (typeof module === "object" && typeof module.exports === "object") factory(exports); + else if (typeof define === "function" && define.amd) define([ + "exports" + ], factory); + else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {}); +})(this, function(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v + }); + var v = void 0; +}); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/input.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/input.js new file mode 100644 index 00000000000..91f17159012 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/input.js @@ -0,0 +1 @@ +export var v = this; diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/module.json b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/module.json new file mode 100644 index 00000000000..229b19a0a3f --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/module.json @@ -0,0 +1,3 @@ +{ + "allowTopLevelThis": true +} \ No newline at end of file diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.amd.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.amd.js new file mode 100644 index 00000000000..6916ceb1d5b --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.amd.js @@ -0,0 +1,14 @@ +define([ + "require", + "exports" +], function(require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v + }); + var v = this; +}); diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.cjs b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.cjs new file mode 100644 index 00000000000..aabbfb4c652 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.cjs @@ -0,0 +1,9 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { + value: true +}); +Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v +}); +var v = this; diff --git a/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.umd.js b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.umd.js new file mode 100644 index 00000000000..96512217a38 --- /dev/null +++ b/crates/swc_ecma_transforms_module/tests/fixture/common/allow-top-level-this/true/output.umd.js @@ -0,0 +1,17 @@ +(function(global, factory) { + if (typeof module === "object" && typeof module.exports === "object") factory(exports); + else if (typeof define === "function" && define.amd) define([ + "exports" + ], factory); + else if (global = typeof globalThis !== "undefined" ? globalThis : global || self) factory(global.input = {}); +})(this, function(exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { + value: true + }); + Object.defineProperty(exports, "v", { + enumerable: true, + get: ()=>v + }); + var v = this; +});