From 2b03047cb088b96e5c054055780b54e4f48ae486 Mon Sep 17 00:00:00 2001 From: OJ Kwon <1210596+kwonoj@users.noreply.github.com> Date: Wed, 25 May 2022 11:08:49 -0700 Subject: [PATCH] fix(es/modules): Fix local scoped amd require (#4800) --- crates/swc_ecma_transforms_module/src/amd.rs | 32 +++------ .../swc_ecma_transforms_module/tests/amd.rs | 69 ++++++++++++++++--- 2 files changed, 69 insertions(+), 32 deletions(-) diff --git a/crates/swc_ecma_transforms_module/src/amd.rs b/crates/swc_ecma_transforms_module/src/amd.rs index 6041573e893..d853af86376 100644 --- a/crates/swc_ecma_transforms_module/src/amd.rs +++ b/crates/swc_ecma_transforms_module/src/amd.rs @@ -63,28 +63,10 @@ impl LocalScopedRequireVisitor { } impl Visit for LocalScopedRequireVisitor { - fn visit_call_expr(&mut self, call_expr: &CallExpr) { - let callee = &call_expr.callee; - if let Callee::Expr(expr) = callee { - match &**expr { - Expr::Ident(ident) => { - if self.require_ident.is_none() && &*ident.sym == "require" { - self.require_ident = Some(ident.clone()); - } - } - Expr::Member(MemberExpr { obj, .. }) => { - let expr = &**obj; - if let Expr::Ident(ident) = expr { - if self.require_ident.is_none() && &*ident.sym == "require" { - self.require_ident = Some(ident.clone()); - } - } - } - _ => {} - } + fn visit_ident(&mut self, ident: &Ident) { + if self.require_ident.is_none() && &*ident.sym == "require" { + self.require_ident = Some(ident.clone()); } - - call_expr.visit_children_with(self); } } @@ -532,13 +514,19 @@ impl Fold for Amd { let mut scope_ref_mut = self.scope.borrow_mut(); let scope = &mut *scope_ref_mut; let mut factory_params = Vec::with_capacity(scope.imports.len() + 1); - if has_export { + + // inject local scoped `require` regardless of having exports or not, as long as + // it can be considered as module (either having import or export) + if !scope.imports.is_empty() || has_export { define_deps_arg.elems.push(Some("require".as_arg())); factory_params.push(Param { span: DUMMY_SP, decorators: Default::default(), pat: scoped_local_require_ident.into(), }); + } + + if has_export { define_deps_arg.elems.push(Some("exports".as_arg())); factory_params.push(Param { span: DUMMY_SP, diff --git a/crates/swc_ecma_transforms_module/tests/amd.rs b/crates/swc_ecma_transforms_module/tests/amd.rs index 292a1620206..be52180a1cc 100644 --- a/crates/swc_ecma_transforms_module/tests/amd.rs +++ b/crates/swc_ecma_transforms_module/tests/amd.rs @@ -33,7 +33,7 @@ test!( "import bar from 'bar'; obj[bar('bas')] = '123'", - "define([\"bar\"], function(_bar) { + "define([\"require\", \"bar\"], function(require, _bar) { \"use strict\"; _bar = _interopRequireDefault(_bar); obj[(0, _bar).default('bas')] = '123'; @@ -105,6 +105,55 @@ define(["require", "exports"], function(require, _exports) { "# ); +test!( + syntax(), + |_| tr(Config { + config: util::Config { + strict: true, + ..Default::default() + }, + ..Default::default() + }), + inner_scoped_local_require_member_expr, + r#"export const DefaultIconPath = FileAccess.asBrowserUri('./media/defaultIcon.png', require).toString(true);"#, + r#" +define([ + "require", + "exports", +], function(require, _exports) { + "use strict"; + _exports.DefaultIconPath = void 0; + const DefaultIconPath = FileAccess.asBrowserUri('./media/defaultIcon.png', require).toString(true); + _exports.DefaultIconPath = DefaultIconPath; +}); +"# +); + +test!( + syntax(), + |_| tr(Config { + config: util::Config { + strict: true, + ..Default::default() + }, + ..Default::default() + }), + inner_scoped_local_require_non_export_module, + r#" + import { getPathFromAmdModule } from 'vs/base/test/node/testUtils'; + const fixturesFolder = getPathFromAmdModule(require, './fixtures'); + "#, + r#" + define([ + "require", + "vs/base/test/node/testUtils" +], function(require, _testUtils) { + "use strict"; + const fixturesFolder = (0, _testUtils).getPathFromAmdModule(require, './fixtures'); +}); +"# +); + test!( syntax(), |_| tr(Config { @@ -140,7 +189,7 @@ test!( r#"import * as foo from 'foo'; import bar from 'bar';"#, r#" -define(["foo", "bar"], function(foo, _bar) { +define(["require", "foo", "bar"], function(require, foo, _bar) { "use strict"; }); "# @@ -157,7 +206,7 @@ import React from 'react' window.React = React; "#, r#" -define(["react"], function(_react) { +define(["require", "react"], function(require, _react) { "use strict"; _react = _interopRequireDefault(_react); window.React = _react.default; @@ -282,7 +331,7 @@ foo2; "#, r#" -define(["foo"], function (_foo) { +define(["require", "foo"], function (require, _foo) { "use strict"; _foo = _interopRequireDefault(_foo); @@ -306,7 +355,7 @@ xyz; "#, r#" -define(["foo"], function (_foo) { +define(["require", "foo"], function (require, _foo) { "use strict"; _foo = _interopRequireWildcard(_foo); @@ -540,7 +589,7 @@ foo; "#, r#" -define(["foo"], function (foo) { +define(["require", "foo"], function (require, foo) { "use strict"; foo = _interopRequireWildcard(foo); @@ -628,7 +677,7 @@ import "./directory/foo-bar"; "#, r#" -define(["foo", "foo-bar", "./directory/foo-bar"], function (_foo, _fooBar, _fooBar1) { +define(["require", "foo", "foo-bar", "./directory/foo-bar"], function (require, _foo, _fooBar, _fooBar1) { "use strict"; }); @@ -964,7 +1013,7 @@ import { qux } from './qux'; "#, r#" -define(["./foo", "./bar", "./derp", "./qux"], function (_foo, _bar, _derp, _qux) { +define(["require", "./foo", "./bar", "./derp", "./qux"], function (require, _foo, _bar, _derp, _qux) { "use strict"; _bar = _interopRequireDefault(_bar); @@ -1073,7 +1122,7 @@ xyz; "#, r#" -define(["foo"], function (_foo) { +define(["require", "foo"], function (require, _foo) { "use strict"; _foo.bar; @@ -1239,7 +1288,7 @@ console.log(elm); "#, r#" -define(["foo"], function (_foo) { +define(["require", "foo"], function (require, _foo) { "use strict"; for(let _i = 0; _i < _foo.array.length; _i++){