diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 98dfaa2fb47dab..7d0a95888483da 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -809,6 +809,7 @@ pub struct Flags { pub eszip: bool, pub node_conditions: Vec, pub preload: Vec, + pub require: Vec, pub tunnel: bool, } @@ -4193,6 +4194,7 @@ fn compile_args_without_check_args(app: Command) -> Command { .arg(ca_file_arg()) .arg(unsafely_ignore_certificate_errors_arg()) .arg(preload_arg()) + .arg(require_arg()) .arg(min_dep_age_arg()) } @@ -4782,6 +4784,17 @@ fn preload_arg() -> Arg { .value_hint(ValueHint::FilePath) } +fn require_arg() -> Arg { + Arg::new("require") + .long("require") + .value_name("FILE") + .action(ArgAction::Append) + .help( + "A list of CommonJS modules that will be executed before the main module", + ) + .value_hint(ValueHint::FilePath) +} + fn min_dep_age_arg() -> Arg { Arg::new("minimum-dependency-age") .long("minimum-dependency-age") @@ -6632,6 +6645,7 @@ fn compile_args_without_check_parse( ca_file_arg_parse(flags, matches); unsafely_ignore_certificate_errors_parse(flags, matches); preload_arg_parse(flags, matches); + require_arg_parse(flags, matches); min_dep_age_arg_parse(flags, matches); Ok(()) } @@ -6915,6 +6929,12 @@ fn preload_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { } } +fn require_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { + if let Some(require) = matches.remove_many::("require") { + flags.require = require.collect(); + } +} + fn min_dep_age_arg_parse(flags: &mut Flags, matches: &mut ArgMatches) { flags.minimum_dependency_age = matches.remove_one("minimum-dependency-age"); } @@ -13635,6 +13655,53 @@ Usage: deno repl [OPTIONS] [-- [ARGS]...]\n" ); } + #[test] + fn require_flag_test() { + let flags = flags_from_vec(svec![ + "deno", + "run", + "--require", + "require.js", + "main.ts" + ]) + .unwrap(); + assert_eq!( + flags, + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "main.ts".into(), + ..Default::default() + }), + require: svec!["require.js"], + code_cache_enabled: true, + ..Default::default() + } + ); + + let flags = flags_from_vec(svec![ + "deno", + "run", + "--require", + "r1.js", + "--require", + "./r2.js", + "main.ts" + ]) + .unwrap(); + assert_eq!( + flags, + Flags { + subcommand: DenoSubcommand::Run(RunFlags { + script: "main.ts".into(), + ..Default::default() + }), + require: svec!["r1.js", "./r2.js"], + code_cache_enabled: true, + ..Default::default() + } + ); + } + #[test] fn check_with_v8_flags() { let flags = diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 3ca9442644aff7..97f5dde788889c 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -642,12 +642,25 @@ impl CliOptions { return Ok(vec![]); } - let mut preload = Vec::with_capacity(self.flags.preload.len()); + let mut modules = Vec::with_capacity(self.flags.preload.len()); for preload_specifier in self.flags.preload.iter() { - preload.push(resolve_url_or_path(preload_specifier, self.initial_cwd())?); + modules.push(resolve_url_or_path(preload_specifier, self.initial_cwd())?); } - Ok(preload) + Ok(modules) + } + + pub fn require_modules(&self) -> Result, AnyError> { + if self.flags.require.is_empty() { + return Ok(vec![]); + } + + let mut require = Vec::with_capacity(self.flags.require.len()); + for require_specifier in self.flags.require.iter() { + require.push(resolve_url_or_path(require_specifier, self.initial_cwd())?); + } + + Ok(require) } fn resolve_main_module_with_resolver_if_bare( diff --git a/cli/factory.rs b/cli/factory.rs index 37468f956ff812..4ba24f795aebf1 100644 --- a/cli/factory.rs +++ b/cli/factory.rs @@ -1271,6 +1271,7 @@ impl CliFactory { } else { deno_resolver::loader::AllowJsonImports::WithAttribute }, + require_modules: options.require_modules()?, }, ))) }) diff --git a/cli/lib/standalone/binary.rs b/cli/lib/standalone/binary.rs index 81bfed31099f32..1c9294594eec75 100644 --- a/cli/lib/standalone/binary.rs +++ b/cli/lib/standalone/binary.rs @@ -87,6 +87,7 @@ pub struct Metadata { pub workspace_resolver: SerializedWorkspaceResolver, pub entrypoint_key: String, pub preload_modules: Vec, + pub require_modules: Vec, pub node_modules: Option, pub unstable_config: UnstableConfig, pub otel_config: OtelConfig, diff --git a/cli/lib/worker.rs b/cli/lib/worker.rs index f2c2d2ba677080..e1421b47607c6f 100644 --- a/cli/lib/worker.rs +++ b/cli/lib/worker.rs @@ -584,11 +584,13 @@ impl LibMainWorkerFactory { permissions: PermissionsContainer, main_module: Url, preload_modules: Vec, + require_modules: Vec, ) -> Result { self.create_custom_worker( mode, main_module, preload_modules, + require_modules, permissions, vec![], Default::default(), @@ -603,6 +605,7 @@ impl LibMainWorkerFactory { mode: WorkerExecutionMode, main_module: Url, preload_modules: Vec, + require_modules: Vec, permissions: PermissionsContainer, custom_extensions: Vec, stdio: deno_runtime::deno_io::Stdio, @@ -725,6 +728,7 @@ impl LibMainWorkerFactory { Ok(LibMainWorker { main_module, preload_modules, + require_modules, worker, }) } @@ -812,6 +816,7 @@ impl LibMainWorkerFactory { pub struct LibMainWorker { main_module: Url, preload_modules: Vec, + require_modules: Vec, worker: MainWorker, } @@ -879,6 +884,13 @@ impl LibMainWorker { self.worker.evaluate_module(id).await?; self.worker.run_event_loop(false).await?; } + // Even though we load as ESM here, these files will be forced to be loaded as CJS + // because of checks in get_known_mode_with_is_script + for require_module_url in self.require_modules.iter() { + let id = self.worker.preload_side_module(require_module_url).await?; + self.worker.evaluate_module(id).await?; + self.worker.run_event_loop(false).await?; + } Ok(()) } diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs index e832938a0fca02..a4c708d7e1f724 100644 --- a/cli/lsp/config.rs +++ b/cli/lsp/config.rs @@ -1469,6 +1469,7 @@ impl ConfigData { specified_import_map: None, types_node_version_req: Some(crate::npm::get_types_node_version_req()), unstable_sloppy_imports: false, + require_modules: vec![], }, ); let pb = ProgressBar::new(ProgressBarStyle::TextOnly); diff --git a/cli/lsp/testing/execution.rs b/cli/lsp/testing/execution.rs index 189dac9cce9063..c147301a3c0ab6 100644 --- a/cli/lsp/testing/execution.rs +++ b/cli/lsp/testing/execution.rs @@ -323,6 +323,8 @@ impl TestRun { specifier, // Executing tests in the LSP currently doesn't support preload option vec![], + // Executing tests in the LSP currently doesn't support require option + vec![], worker_sender, fail_fast_tracker, test::TestSpecifierOptions { diff --git a/cli/rt/run.rs b/cli/rt/run.rs index ec5997bb9e184e..6a4b547ac4bf2b 100644 --- a/cli/rt/run.rs +++ b/cli/rt/run.rs @@ -849,6 +849,11 @@ pub async fn run( node_resolution_sys, node_resolver::NodeResolverOptions::default(), )); + let require_modules = metadata + .require_modules + .iter() + .map(|key| root_dir_url.join(key).unwrap()) + .collect::>(); let cjs_tracker = Arc::new(CjsTracker::new( in_npm_pkg_checker.clone(), pkg_json_resolver.clone(), @@ -859,6 +864,7 @@ pub async fn run( } else { IsCjsResolutionMode::ExplicitTypeCommonJs }, + require_modules.clone(), )); let npm_req_resolver = Arc::new(NpmReqResolver::new(NpmReqResolverOptions { sys: sys.clone(), @@ -1088,6 +1094,7 @@ pub async fn run( permissions, main_module, preload_modules, + require_modules, )?; let exit_code = worker.run().await?; diff --git a/cli/standalone/binary.rs b/cli/standalone/binary.rs index 842ba89c75a11b..c3b463a9bb80bc 100644 --- a/cli/standalone/binary.rs +++ b/cli/standalone/binary.rs @@ -723,6 +723,13 @@ impl<'a> DenoCompileBinaryWriter<'a> { .map(|s| root_dir_url.specifier_key(&s).into_owned()) .collect::>(); + let require_modules = self + .cli_options + .require_modules()? + .into_iter() + .map(|s| root_dir_url.specifier_key(&s).into_owned()) + .collect::>(); + let metadata = Metadata { argv: compile_flags.args.clone(), seed: self.cli_options.seed(), @@ -744,6 +751,7 @@ impl<'a> DenoCompileBinaryWriter<'a> { env_vars_from_env_file, entrypoint_key: root_dir_url.specifier_key(entrypoint).into_owned(), preload_modules, + require_modules, workspace_resolver: SerializedWorkspaceResolver { import_map: self.workspace_resolver.maybe_import_map().map(|i| { SerializedWorkspaceResolverImportMap { diff --git a/cli/tools/bench/mod.rs b/cli/tools/bench/mod.rs index 3ef4c0a3b24926..bf578679339242 100644 --- a/cli/tools/bench/mod.rs +++ b/cli/tools/bench/mod.rs @@ -157,6 +157,7 @@ async fn bench_specifier( permissions_container: PermissionsContainer, specifier: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, sender: UnboundedSender, filter: TestFilter, ) -> Result<(), AnyError> { @@ -165,6 +166,7 @@ async fn bench_specifier( permissions_container, specifier.clone(), preload_modules, + require_modules, &sender, filter, ) @@ -188,6 +190,7 @@ async fn bench_specifier_inner( permissions_container: PermissionsContainer, specifier: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, sender: &UnboundedSender, filter: TestFilter, ) -> Result<(), CreateCustomWorkerError> { @@ -196,6 +199,7 @@ async fn bench_specifier_inner( WorkerExecutionMode::Bench, specifier.clone(), preload_modules, + require_modules, permissions_container, vec![ops::bench::deno_bench::init(sender.clone())], Default::default(), @@ -301,6 +305,7 @@ async fn bench_specifiers( permission_desc_parser: &Arc>, specifiers: Vec, preload_modules: Vec, + require_modules: Vec, options: BenchSpecifierOptions, ) -> Result<(), AnyError> { let (sender, mut receiver) = unbounded_channel::(); @@ -313,6 +318,7 @@ async fn bench_specifiers( let sender = sender.clone(); let options = option_for_handles.clone(); let preload_modules = preload_modules.clone(); + let require_modules = require_modules.clone(); let cli_options = cli_options.clone(); let permission_desc_parser = permission_desc_parser.clone(); spawn_blocking(move || { @@ -333,6 +339,7 @@ async fn bench_specifiers( permissions_container, specifier, preload_modules, + require_modules, sender, options.filter, ); @@ -499,6 +506,7 @@ pub async fn run_benchmarks( } let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; let log_level = cli_options.log_level(); let worker_factory = Arc::new(factory.create_cli_main_worker_factory().await?); @@ -508,6 +516,7 @@ pub async fn run_benchmarks( factory.permission_desc_parser()?, specifiers, preload_modules, + require_modules, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), json: workspace_bench_options.json, @@ -637,12 +646,14 @@ pub async fn run_benchmarks_with_watch( let log_level = cli_options.log_level(); let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; bench_specifiers( worker_factory, cli_options, factory.permission_desc_parser()?, specifiers, preload_modules, + require_modules, BenchSpecifierOptions { filter: TestFilter::from_flag(&workspace_bench_options.filter), json: workspace_bench_options.json, diff --git a/cli/tools/compile.rs b/cli/tools/compile.rs index 79ae3a003fbc74..a4be6c8efe179e 100644 --- a/cli/tools/compile.rs +++ b/cli/tools/compile.rs @@ -440,6 +440,10 @@ fn get_module_roots_and_include_paths( module_roots.push(preload_module); } + for require_module in cli_options.require_modules()? { + module_roots.push(require_module); + } + Ok((module_roots, include_paths)) } diff --git a/cli/tools/deploy.rs b/cli/tools/deploy.rs index c04dae26a64349..0eb29c74187f26 100644 --- a/cli/tools/deploy.rs +++ b/cli/tools/deploy.rs @@ -61,6 +61,7 @@ pub async fn deploy(mut flags: Flags) -> Result { WorkerExecutionMode::Deploy, specifier, vec![], + vec![], PermissionsContainer::allow_all( factory.permission_desc_parser()?.clone(), ), diff --git a/cli/tools/jupyter/mod.rs b/cli/tools/jupyter/mod.rs index 576130745de92f..845485ebf278da 100644 --- a/cli/tools/jupyter/mod.rs +++ b/cli/tools/jupyter/mod.rs @@ -102,6 +102,8 @@ pub async fn kernel( main_module.clone(), // `deno jupyter` doesn't support preloading modules vec![], + // `deno jupyter` doesn't support require modules + vec![], permissions, vec![ ops::jupyter::deno_jupyter::init(stdio_tx.clone()), diff --git a/cli/tools/lint/plugins.rs b/cli/tools/lint/plugins.rs index bf809e0c39bcbd..e46c17a40f4af3 100644 --- a/cli/tools/lint/plugins.rs +++ b/cli/tools/lint/plugins.rs @@ -160,6 +160,8 @@ async fn create_plugin_runner_inner( main_module.clone(), // `deno lint` doesn't support preloading modules vec![], + // `deno lint` doesn't support require modules + vec![], permissions, vec![crate::ops::lint::deno_lint_ext::init(logger.clone())], Default::default(), diff --git a/cli/tools/repl/mod.rs b/cli/tools/repl/mod.rs index c4fad51802bf27..6cfeb8d7842d5a 100644 --- a/cli/tools/repl/mod.rs +++ b/cli/tools/repl/mod.rs @@ -186,6 +186,8 @@ pub async fn run( main_module.clone(), // `deno repl` doesn't support preloading modules vec![], + // `deno repl` doesn't support require modules + vec![], permissions.clone(), vec![crate::ops::testing::deno_test::init(test_event_sender)], Default::default(), diff --git a/cli/tools/run/mod.rs b/cli/tools/run/mod.rs index b2ccf3859a8c1f..3d3b0753aa244e 100644 --- a/cli/tools/run/mod.rs +++ b/cli/tools/run/mod.rs @@ -91,6 +91,7 @@ pub async fn run_script( ), ))?; let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; if main_module.scheme() == "npm" { set_npm_user_agent(); @@ -106,6 +107,7 @@ pub async fn run_script( mode, main_module.clone(), preload_modules, + require_modules, unconfigured_runtime, ) .await @@ -127,6 +129,7 @@ pub async fn run_from_stdin( let cli_options = factory.cli_options()?; let main_module = cli_options.resolve_main_module()?; let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; maybe_npm_install(&factory).await?; @@ -151,6 +154,7 @@ pub async fn run_from_stdin( WorkerExecutionMode::Run, main_module.clone(), preload_modules, + require_modules, unconfigured_runtime, ) .await?; @@ -191,6 +195,7 @@ async fn run_with_watch( let cli_options = factory.cli_options()?; let main_module = cli_options.resolve_main_module()?; let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; if main_module.scheme() == "npm" { set_npm_user_agent(); @@ -203,7 +208,12 @@ async fn run_with_watch( let mut worker = factory .create_cli_main_worker_factory() .await? - .create_main_worker(mode, main_module.clone(), preload_modules) + .create_main_worker( + mode, + main_module.clone(), + preload_modules, + require_modules, + ) .await?; if watch_flags.hmr { @@ -231,6 +241,7 @@ pub async fn eval_command( let file_fetcher = factory.file_fetcher()?; let main_module = cli_options.resolve_main_module()?; let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; maybe_npm_install(&factory).await?; @@ -257,6 +268,7 @@ pub async fn eval_command( WorkerExecutionMode::Eval, main_module.clone(), preload_modules, + require_modules, ) .await?; let exit_code = worker.run().await?; @@ -308,6 +320,7 @@ pub async fn run_eszip( let mode = WorkerExecutionMode::Run; let main_module = resolve_url_or_path(entrypoint, cli_options.initial_cwd())?; let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; let worker_factory = factory .create_cli_main_worker_factory_with_roots(roots) @@ -317,6 +330,7 @@ pub async fn run_eszip( mode, main_module.clone(), preload_modules, + require_modules, unconfigured_runtime, ) .await?; diff --git a/cli/tools/serve.rs b/cli/tools/serve.rs index 5d92deafb34e20..b9baa906778b98 100644 --- a/cli/tools/serve.rs +++ b/cli/tools/serve.rs @@ -100,6 +100,7 @@ async fn do_serve( main_module.clone(), // TODO(bartlomieju): vec![], + vec![], unconfigured_runtime, ) .await?; @@ -155,6 +156,7 @@ async fn run_worker( main_module, // TODO(bartlomieju): vec![], + vec![], ) .await?; if hmr { diff --git a/cli/tools/test/mod.rs b/cli/tools/test/mod.rs index 242d0a50ee4004..0b5bb6342c7d44 100644 --- a/cli/tools/test/mod.rs +++ b/cli/tools/test/mod.rs @@ -648,10 +648,12 @@ fn get_test_reporter(options: &TestSpecifiersOptions) -> Box { reporter } +#[allow(clippy::too_many_arguments)] async fn configure_main_worker( worker_factory: Arc, specifier: &Url, preload_modules: Vec, + require_modules: Vec, permissions_container: PermissionsContainer, worker_sender: TestEventWorkerSender, options: &TestSpecifierOptions, @@ -662,6 +664,7 @@ async fn configure_main_worker( WorkerExecutionMode::Test, specifier.clone(), preload_modules, + require_modules, permissions_container, vec![ ops::testing::deno_test::init(worker_sender.sender), @@ -707,11 +710,13 @@ async fn configure_main_worker( /// Test a single specifier as documentation containing test programs, an executable test module or /// both. +#[allow(clippy::too_many_arguments)] pub async fn test_specifier( worker_factory: Arc, permissions_container: PermissionsContainer, specifier: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, worker_sender: TestEventWorkerSender, fail_fast_tracker: FailFastTracker, options: TestSpecifierOptions, @@ -724,6 +729,7 @@ pub async fn test_specifier( worker_factory, &specifier, preload_modules, + require_modules, permissions_container, worker_sender, &options, @@ -1169,6 +1175,7 @@ async fn test_specifiers( permission_desc_parser: &Arc>, specifiers: Vec, preload_modules: Vec, + require_modules: Vec, options: TestSpecifiersOptions, ) -> Result<(), AnyError> { let specifiers = if let Some(seed) = options.specifier.shuffle { @@ -1197,6 +1204,7 @@ async fn test_specifiers( let worker_factory = worker_factory.clone(); let specifier_dir = cli_options.workspace().resolve_member_dir(&specifier); let preload_modules = preload_modules.clone(); + let require_modules = require_modules.clone(); let worker_sender = test_event_sender_factory.worker(); let fail_fast_tracker = fail_fast_tracker.clone(); let specifier_options = options.specifier.clone(); @@ -1220,6 +1228,7 @@ async fn test_specifiers( permissions_container, specifier, preload_modules, + require_modules, worker_sender, fail_fast_tracker, specifier_options, @@ -1582,6 +1591,7 @@ pub async fn run_tests( let worker_factory = Arc::new(factory.create_cli_main_worker_factory().await?); let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; // Run tests test_specifiers( @@ -1590,6 +1600,7 @@ pub async fn run_tests( factory.permission_desc_parser()?, specifiers_for_typecheck_and_test, preload_modules, + require_modules, TestSpecifiersOptions { cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err( |_| { @@ -1794,6 +1805,7 @@ pub async fn run_tests_with_watch( let worker_factory = Arc::new(factory.create_cli_main_worker_factory().await?); let preload_modules = cli_options.preload_modules()?; + let require_modules = cli_options.require_modules()?; test_specifiers( worker_factory, @@ -1801,6 +1813,7 @@ pub async fn run_tests_with_watch( factory.permission_desc_parser()?, specifiers_for_typecheck_and_test, preload_modules, + require_modules, TestSpecifiersOptions { cwd: Url::from_directory_path(cli_options.initial_cwd()).map_err( |_| { diff --git a/cli/worker.rs b/cli/worker.rs index 24ad323722ba6f..d0a7651c479849 100644 --- a/cli/worker.rs +++ b/cli/worker.rs @@ -328,12 +328,14 @@ impl CliMainWorkerFactory { mode: WorkerExecutionMode, main_module: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, ) -> Result { self .create_custom_worker( mode, main_module, preload_modules, + require_modules, self.root_permissions.clone(), vec![], Default::default(), @@ -347,6 +349,7 @@ impl CliMainWorkerFactory { mode: WorkerExecutionMode, main_module: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, unconfigured_runtime: Option, ) -> Result { self @@ -354,6 +357,7 @@ impl CliMainWorkerFactory { mode, main_module, preload_modules, + require_modules, self.root_permissions.clone(), vec![], Default::default(), @@ -368,6 +372,7 @@ impl CliMainWorkerFactory { mode: WorkerExecutionMode, main_module: ModuleSpecifier, preload_modules: Vec, + require_modules: Vec, permissions: PermissionsContainer, custom_extensions: Vec, stdio: deno_runtime::deno_io::Stdio, @@ -427,6 +432,7 @@ impl CliMainWorkerFactory { mode, main_module, preload_modules, + require_modules, permissions, custom_extensions, stdio, diff --git a/libs/resolver/cjs/mod.rs b/libs/resolver/cjs/mod.rs index aa6198957a3c5f..b1894e6df005d3 100644 --- a/libs/resolver/cjs/mod.rs +++ b/libs/resolver/cjs/mod.rs @@ -28,6 +28,7 @@ pub struct CjsTracker< > { is_cjs_resolver: IsCjsResolver, known: MaybeDashMap, + require_modules: Vec, } impl @@ -37,6 +38,7 @@ impl in_npm_pkg_checker: TInNpmPackageChecker, pkg_json_resolver: PackageJsonResolverRc, mode: IsCjsResolutionMode, + require_modules: Vec, ) -> Self { Self { is_cjs_resolver: IsCjsResolver::new( @@ -45,6 +47,7 @@ impl mode, ), known: Default::default(), + require_modules, } } @@ -135,10 +138,12 @@ impl media_type: MediaType, is_script: Option, ) -> Option { + let is_from_require = self.require_modules.contains(specifier); self.is_cjs_resolver.get_known_mode_with_is_script( specifier, media_type, is_script, + is_from_require, &self.known, ) } @@ -223,6 +228,7 @@ impl specifier: &Url, media_type: MediaType, is_script: Option, + is_from_require: bool, known_cache: &MaybeDashMap, ) -> Option { if specifier.scheme() != "file" { @@ -257,6 +263,10 @@ impl | MediaType::SourceMap | MediaType::Sql | MediaType::Unknown => { + if is_from_require { + return Some(ResolutionMode::Require); + } + if let Some(value) = known_cache.get(specifier).map(|v| *v) { if value == ResolutionMode::Require && is_script == Some(false) { // we now know this is actually esm diff --git a/libs/resolver/factory.rs b/libs/resolver/factory.rs index a839bf03e63a0c..c6254823a912c9 100644 --- a/libs/resolver/factory.rs +++ b/libs/resolver/factory.rs @@ -682,6 +682,8 @@ pub struct ResolverFactoryOptions { /// Known good version requirement to use for the `@types/node` package /// when the version is unspecified or "latest". pub types_node_version_req: Option, + /// Modules loaded via --require flag that should always be treated as CommonJS + pub require_modules: Vec, } pub struct ResolverFactory { @@ -848,6 +850,7 @@ impl ResolverFactory { self.in_npm_package_checker()?.clone(), self.pkg_json_resolver().clone(), self.options.is_cjs_resolution_mode, + self.options.require_modules.clone(), ))) }) } diff --git a/tests/specs/run/require_modules_multiple/__test__.jsonc b/tests/specs/run/require_modules_multiple/__test__.jsonc new file mode 100644 index 00000000000000..602d6773c6a9b6 --- /dev/null +++ b/tests/specs/run/require_modules_multiple/__test__.jsonc @@ -0,0 +1,5 @@ +{ + "args": "run --require require_first.js --require require_second.js main_multiple.ts", + "exitCode": 0, + "output": "multiple.out" +} diff --git a/tests/specs/run/require_modules_multiple/main_multiple.ts b/tests/specs/run/require_modules_multiple/main_multiple.ts new file mode 100644 index 00000000000000..61bee4a6690495 --- /dev/null +++ b/tests/specs/run/require_modules_multiple/main_multiple.ts @@ -0,0 +1,10 @@ +console.log("main_multiple.ts starts"); + +console.log(`First: ${globalThis.__first__}`); +console.log(`Second: ${globalThis.__second__}`); +console.log(`First filename: ${globalThis.__first_filename__}`); +console.log(`Second filename: ${globalThis.__second_filename__}`); +console.log(`First dirname: ${globalThis.__first_dirname__}`); +console.log(`Second dirname: ${globalThis.__second_dirname__}`); + +console.log("main_multiple.ts finished"); diff --git a/tests/specs/run/require_modules_multiple/multiple.out b/tests/specs/run/require_modules_multiple/multiple.out new file mode 100644 index 00000000000000..c7d178e300c1ea --- /dev/null +++ b/tests/specs/run/require_modules_multiple/multiple.out @@ -0,0 +1,12 @@ +require_first.js loading +require_first.js platform: [WILDCARD] +require_second.js loading +require_second.js path separator: [WILDCARD] +main_multiple.ts starts +First: first +Second: second +First filename: [WILDCARD]require_first.js +Second filename: [WILDCARD]require_second.js +First dirname: [WILDCARD]require_modules_multiple +Second dirname: [WILDCARD]require_modules_multiple +main_multiple.ts finished diff --git a/tests/specs/run/require_modules_multiple/require_first.js b/tests/specs/run/require_modules_multiple/require_first.js new file mode 100644 index 00000000000000..2ca5dbb839dab3 --- /dev/null +++ b/tests/specs/run/require_modules_multiple/require_first.js @@ -0,0 +1,9 @@ +console.log("require_first.js loading"); + +const os = require("node:os"); + +console.log(`require_first.js platform: ${os.platform()}`); + +globalThis.__first__ = "first"; +globalThis.__first_filename__ = __filename; +globalThis.__first_dirname__ = __dirname; diff --git a/tests/specs/run/require_modules_multiple/require_second.js b/tests/specs/run/require_modules_multiple/require_second.js new file mode 100644 index 00000000000000..c64baa7bac7d46 --- /dev/null +++ b/tests/specs/run/require_modules_multiple/require_second.js @@ -0,0 +1,9 @@ +console.log("require_second.js loading"); + +const path = require("node:path"); + +console.log(`require_second.js path separator: ${path.sep}`); + +globalThis.__second__ = "second"; +globalThis.__second_filename__ = __filename; +globalThis.__second_dirname__ = __dirname;